mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-26 05:27:01 +00:00
Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with multiple contexts. (#5203, #5221, #4141)
# Conflicts: # docs/CHANGELOG.txt
This commit is contained in:
parent
04689979b4
commit
e54db4ee70
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts.
|
||||||
// 2022-01-03: Metal: Ignore ImDrawCmd where ElemCount == 0 (very rare but can technically be manufactured by user code).
|
// 2022-01-03: Metal: Ignore ImDrawCmd where ElemCount == 0 (very rare but can technically be manufactured by user code).
|
||||||
// 2021-12-30: Metal: Added Metal C++ support. Enable with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file.
|
// 2021-12-30: Metal: Added Metal C++ support. Enable with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file.
|
||||||
// 2021-08-24: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted. (#4464)
|
// 2021-08-24: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted. (#4464)
|
||||||
@ -54,6 +55,7 @@
|
|||||||
// renderer backend. Stores the render pipeline state cache and the default
|
// renderer backend. Stores the render pipeline state cache and the default
|
||||||
// font texture, and manages the reusable buffer cache.
|
// font texture, and manages the reusable buffer cache.
|
||||||
@interface MetalContext : NSObject
|
@interface MetalContext : NSObject
|
||||||
|
@property (nonatomic, strong) id<MTLDevice> device;
|
||||||
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
||||||
@property (nonatomic, strong) FramebufferDescriptor *framebufferDescriptor; // framebuffer descriptor for current frame; transient
|
@property (nonatomic, strong) FramebufferDescriptor *framebufferDescriptor; // framebuffer descriptor for current frame; transient
|
||||||
@property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
|
@property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
|
||||||
@ -77,7 +79,16 @@
|
|||||||
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder;
|
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static MetalContext *g_sharedMetalContext = nil;
|
struct ImGui_ImplMetal_Data
|
||||||
|
{
|
||||||
|
MetalContext* SharedMetalContext;
|
||||||
|
|
||||||
|
ImGui_ImplMetal_Data() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static ImGui_ImplMetal_Data* ImGui_ImplMetal_CreateBackendData() { return IM_NEW(ImGui_ImplMetal_Data)(); }
|
||||||
|
static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : NULL; }
|
||||||
|
static void ImGui_ImplMetal_DestroyBackendData() { IM_DELETE(ImGui_ImplMetal_GetBackendData()); }
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_METAL_CPP
|
#ifdef IMGUI_IMPL_METAL_CPP
|
||||||
|
|
||||||
@ -119,16 +130,14 @@ bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device)
|
|||||||
|
|
||||||
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
||||||
{
|
{
|
||||||
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_CreateBackendData();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.BackendRendererUserData = (void*)bd;
|
||||||
io.BackendRendererName = "imgui_impl_metal";
|
io.BackendRendererName = "imgui_impl_metal";
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
|
||||||
static dispatch_once_t onceToken;
|
bd->SharedMetalContext = [[MetalContext alloc] init];
|
||||||
dispatch_once(&onceToken, ^{
|
bd->SharedMetalContext.device = device;
|
||||||
g_sharedMetalContext = [[MetalContext alloc] init];
|
|
||||||
});
|
|
||||||
|
|
||||||
ImGui_ImplMetal_CreateDeviceObjects(device);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -136,42 +145,48 @@ bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
|||||||
void ImGui_ImplMetal_Shutdown()
|
void ImGui_ImplMetal_Shutdown()
|
||||||
{
|
{
|
||||||
ImGui_ImplMetal_DestroyDeviceObjects();
|
ImGui_ImplMetal_DestroyDeviceObjects();
|
||||||
|
ImGui_ImplMetal_DestroyBackendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor)
|
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor)
|
||||||
{
|
{
|
||||||
IM_ASSERT(g_sharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?");
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||||
|
IM_ASSERT(bd->SharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?");
|
||||||
|
bd->SharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
|
||||||
|
|
||||||
g_sharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
|
if (bd->SharedMetalContext.depthStencilState == nil)
|
||||||
|
ImGui_ImplMetal_CreateDeviceObjects(bd->SharedMetalContext.device);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metal Render function.
|
// Metal Render function.
|
||||||
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
|
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
|
||||||
{
|
{
|
||||||
[g_sharedMetalContext renderDrawData:draw_data commandBuffer:commandBuffer commandEncoder:commandEncoder];
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||||
|
[bd->SharedMetalContext renderDrawData:draw_data commandBuffer:commandBuffer commandEncoder:commandEncoder];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplMetal_CreateFontsTexture(id<MTLDevice> device)
|
bool ImGui_ImplMetal_CreateFontsTexture(id<MTLDevice> device)
|
||||||
{
|
{
|
||||||
[g_sharedMetalContext makeFontTextureWithDevice:device];
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.Fonts->SetTexID((__bridge void *)g_sharedMetalContext.fontTexture); // ImTextureID == void*
|
[bd->SharedMetalContext makeFontTextureWithDevice:device];
|
||||||
|
io.Fonts->SetTexID((__bridge void *)bd->SharedMetalContext.fontTexture); // ImTextureID == void*
|
||||||
|
|
||||||
return (g_sharedMetalContext.fontTexture != nil);
|
return (bd->SharedMetalContext.fontTexture != nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplMetal_DestroyFontsTexture()
|
void ImGui_ImplMetal_DestroyFontsTexture()
|
||||||
{
|
{
|
||||||
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
g_sharedMetalContext.fontTexture = nil;
|
bd->SharedMetalContext.fontTexture = nil;
|
||||||
io.Fonts->SetTexID(nullptr);
|
io.Fonts->SetTexID(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
|
bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
|
||||||
{
|
{
|
||||||
[g_sharedMetalContext makeDeviceObjectsWithDevice:device];
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||||
|
[bd->SharedMetalContext makeDeviceObjectsWithDevice:device];
|
||||||
ImGui_ImplMetal_CreateFontsTexture(device);
|
ImGui_ImplMetal_CreateFontsTexture(device);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -179,8 +194,9 @@ bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
|
|||||||
|
|
||||||
void ImGui_ImplMetal_DestroyDeviceObjects()
|
void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||||
{
|
{
|
||||||
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||||
ImGui_ImplMetal_DestroyFontsTexture();
|
ImGui_ImplMetal_DestroyFontsTexture();
|
||||||
[g_sharedMetalContext emptyRenderPipelineStateCache];
|
[bd->SharedMetalContext emptyRenderPipelineStateCache];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - MetalBuffer implementation
|
#pragma mark - MetalBuffer implementation
|
||||||
@ -458,8 +474,9 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
|||||||
vertexBuffer:(MetalBuffer *)vertexBuffer
|
vertexBuffer:(MetalBuffer *)vertexBuffer
|
||||||
vertexBufferOffset:(size_t)vertexBufferOffset
|
vertexBufferOffset:(size_t)vertexBufferOffset
|
||||||
{
|
{
|
||||||
|
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||||
[commandEncoder setCullMode:MTLCullModeNone];
|
[commandEncoder setCullMode:MTLCullModeNone];
|
||||||
[commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState];
|
[commandEncoder setDepthStencilState:bd->SharedMetalContext.depthStencilState];
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
// Setup viewport, orthographic projection matrix
|
||||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts.
|
||||||
// 2022-03-22: Inputs: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key
|
// 2022-03-22: Inputs: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key
|
||||||
// 2022-02-07: Inputs: Forward keyDown/keyUp events to OS when unused by dear imgui.
|
// 2022-02-07: Inputs: Forward keyDown/keyUp events to OS when unused by dear imgui.
|
||||||
// 2022-01-31: Fix building with old Xcode versions that are missing gamepad features.
|
// 2022-01-31: Fix building with old Xcode versions that are missing gamepad features.
|
||||||
@ -57,13 +58,22 @@
|
|||||||
@class KeyEventResponder;
|
@class KeyEventResponder;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
static double g_HostClockPeriod = 0.0;
|
struct ImGui_ImplOSX_Data
|
||||||
static double g_Time = 0.0;
|
{
|
||||||
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
|
double HostClockPeriod;
|
||||||
static bool g_MouseCursorHidden = false;
|
double Time;
|
||||||
static ImFocusObserver* g_FocusObserver = nil;
|
NSCursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||||
static KeyEventResponder* g_KeyEventResponder = nil;
|
bool MouseCursorHidden;
|
||||||
static NSTextInputContext* g_InputContext = nil;
|
ImFocusObserver* FocusObserver;
|
||||||
|
KeyEventResponder* KeyEventResponder;
|
||||||
|
NSTextInputContext* InputContext;
|
||||||
|
|
||||||
|
ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static ImGui_ImplOSX_Data* ImGui_ImplOSX_CreateBackendData() { return IM_NEW(ImGui_ImplOSX_Data)(); }
|
||||||
|
static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; }
|
||||||
|
static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); }
|
||||||
|
|
||||||
// Undocumented methods for creating cursors.
|
// Undocumented methods for creating cursors.
|
||||||
@interface NSCursor()
|
@interface NSCursor()
|
||||||
@ -75,14 +85,16 @@ static NSTextInputContext* g_InputContext = nil;
|
|||||||
|
|
||||||
static void InitHostClockPeriod()
|
static void InitHostClockPeriod()
|
||||||
{
|
{
|
||||||
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||||
struct mach_timebase_info info;
|
struct mach_timebase_info info;
|
||||||
mach_timebase_info(&info);
|
mach_timebase_info(&info);
|
||||||
g_HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Period is the reciprocal of frequency.
|
bd->HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Period is the reciprocal of frequency.
|
||||||
}
|
}
|
||||||
|
|
||||||
static double GetMachAbsoluteTimeInSeconds()
|
static double GetMachAbsoluteTimeInSeconds()
|
||||||
{
|
{
|
||||||
return (double)mach_absolute_time() * g_HostClockPeriod;
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||||
|
return (double)mach_absolute_time() * bd->HostClockPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -363,6 +375,8 @@ static ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code)
|
|||||||
bool ImGui_ImplOSX_Init(NSView* view)
|
bool ImGui_ImplOSX_Init(NSView* view)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_CreateBackendData();
|
||||||
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup backend capabilities flags
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
@ -372,16 +386,16 @@ bool ImGui_ImplOSX_Init(NSView* view)
|
|||||||
io.BackendPlatformName = "imgui_impl_osx";
|
io.BackendPlatformName = "imgui_impl_osx";
|
||||||
|
|
||||||
// Load cursors. Some of them are undocumented.
|
// Load cursors. Some of them are undocumented.
|
||||||
g_MouseCursorHidden = false;
|
bd->MouseCursorHidden = false;
|
||||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor];
|
bd->MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor];
|
bd->MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor];
|
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor];
|
bd->MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor];
|
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor];
|
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor];
|
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor];
|
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor];
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor];
|
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor];
|
||||||
|
|
||||||
// Note that imgui.cpp also include default OSX clipboard handlers which can be enabled
|
// Note that imgui.cpp also include default OSX clipboard handlers which can be enabled
|
||||||
// by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line.
|
// by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line.
|
||||||
@ -412,44 +426,45 @@ bool ImGui_ImplOSX_Init(NSView* view)
|
|||||||
return s_clipboard.Data;
|
return s_clipboard.Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
g_FocusObserver = [[ImFocusObserver alloc] init];
|
bd->FocusObserver = [[ImFocusObserver alloc] init];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
|
[[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver
|
||||||
selector:@selector(onApplicationBecomeActive:)
|
selector:@selector(onApplicationBecomeActive:)
|
||||||
name:NSApplicationDidBecomeActiveNotification
|
name:NSApplicationDidBecomeActiveNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
|
[[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver
|
||||||
selector:@selector(onApplicationBecomeInactive:)
|
selector:@selector(onApplicationBecomeInactive:)
|
||||||
name:NSApplicationDidResignActiveNotification
|
name:NSApplicationDidResignActiveNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
// Add the NSTextInputClient to the view hierarchy,
|
// Add the NSTextInputClient to the view hierarchy,
|
||||||
// to receive keyboard events and translate them to input text.
|
// to receive keyboard events and translate them to input text.
|
||||||
g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
|
bd->KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
|
||||||
g_InputContext = [[NSTextInputContext alloc] initWithClient:g_KeyEventResponder];
|
bd->InputContext = [[NSTextInputContext alloc] initWithClient:bd->KeyEventResponder];
|
||||||
[view addSubview:g_KeyEventResponder];
|
[view addSubview:bd->KeyEventResponder];
|
||||||
|
|
||||||
// Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down).
|
// Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down).
|
||||||
// This monitor taps into global event stream and captures these events.
|
// This monitor taps into global event stream and captures these events.
|
||||||
NSEventMask eventMask = NSEventMaskFromType(NSKeyUp) | NSEventMaskFlagsChanged;
|
NSEventMask eventMask = NSEventMaskFromType(NSKeyUp) | NSEventMaskFlagsChanged;
|
||||||
[NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event)
|
[NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event)
|
||||||
{
|
{
|
||||||
ImGui_ImplOSX_HandleEvent(event, g_KeyEventResponder);
|
ImGui_ImplOSX_HandleEvent(event, bd->KeyEventResponder);
|
||||||
return event;
|
return event;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void
|
io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void
|
||||||
{
|
{
|
||||||
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||||
if (data->WantVisible)
|
if (data->WantVisible)
|
||||||
{
|
{
|
||||||
[g_InputContext activate];
|
[bd->InputContext activate];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[g_InputContext discardMarkedText];
|
[bd->InputContext discardMarkedText];
|
||||||
[g_InputContext invalidateCharacterCoordinates];
|
[bd->InputContext invalidateCharacterCoordinates];
|
||||||
[g_InputContext deactivate];
|
[bd->InputContext deactivate];
|
||||||
}
|
}
|
||||||
[g_KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight];
|
[bd->KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight];
|
||||||
};
|
};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -457,11 +472,14 @@ bool ImGui_ImplOSX_Init(NSView* view)
|
|||||||
|
|
||||||
void ImGui_ImplOSX_Shutdown()
|
void ImGui_ImplOSX_Shutdown()
|
||||||
{
|
{
|
||||||
g_FocusObserver = NULL;
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||||
|
bd->FocusObserver = NULL;
|
||||||
|
ImGui_ImplOSX_DestroyBackendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplOSX_UpdateMouseCursor()
|
static void ImGui_ImplOSX_UpdateMouseCursor()
|
||||||
{
|
{
|
||||||
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||||
return;
|
return;
|
||||||
@ -470,23 +488,23 @@ static void ImGui_ImplOSX_UpdateMouseCursor()
|
|||||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||||
{
|
{
|
||||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||||
if (!g_MouseCursorHidden)
|
if (!bd->MouseCursorHidden)
|
||||||
{
|
{
|
||||||
g_MouseCursorHidden = true;
|
bd->MouseCursorHidden = true;
|
||||||
[NSCursor hide];
|
[NSCursor hide];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSCursor* desired = g_MouseCursors[imgui_cursor] ?: g_MouseCursors[ImGuiMouseCursor_Arrow];
|
NSCursor* desired = bd->MouseCursors[imgui_cursor] ?: bd->MouseCursors[ImGuiMouseCursor_Arrow];
|
||||||
// -[NSCursor set] generates measureable overhead if called unconditionally.
|
// -[NSCursor set] generates measureable overhead if called unconditionally.
|
||||||
if (desired != NSCursor.currentCursor)
|
if (desired != NSCursor.currentCursor)
|
||||||
{
|
{
|
||||||
[desired set];
|
[desired set];
|
||||||
}
|
}
|
||||||
if (g_MouseCursorHidden)
|
if (bd->MouseCursorHidden)
|
||||||
{
|
{
|
||||||
g_MouseCursorHidden = false;
|
bd->MouseCursorHidden = false;
|
||||||
[NSCursor unhide];
|
[NSCursor unhide];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -553,15 +571,18 @@ static void ImGui_ImplOSX_UpdateGamepads()
|
|||||||
|
|
||||||
static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view)
|
static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view)
|
||||||
{
|
{
|
||||||
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if (io.WantTextInput)
|
if (io.WantTextInput)
|
||||||
[g_KeyEventResponder updateImePosWithView:view];
|
[bd->KeyEventResponder updateImePosWithView:view];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplOSX_NewFrame(NSView* view)
|
void ImGui_ImplOSX_NewFrame(NSView* view)
|
||||||
{
|
{
|
||||||
// Setup display size
|
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Setup display size
|
||||||
if (view)
|
if (view)
|
||||||
{
|
{
|
||||||
const float dpi = (float)[view.window backingScaleFactor];
|
const float dpi = (float)[view.window backingScaleFactor];
|
||||||
@ -570,14 +591,14 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup time step
|
// Setup time step
|
||||||
if (g_Time == 0.0)
|
if (bd->Time == 0.0)
|
||||||
{
|
{
|
||||||
InitHostClockPeriod();
|
InitHostClockPeriod();
|
||||||
g_Time = GetMachAbsoluteTimeInSeconds();
|
bd->Time = GetMachAbsoluteTimeInSeconds();
|
||||||
}
|
}
|
||||||
double current_time = GetMachAbsoluteTimeInSeconds();
|
double current_time = GetMachAbsoluteTimeInSeconds();
|
||||||
io.DeltaTime = (float)(current_time - g_Time);
|
io.DeltaTime = (float)(current_time - bd->Time);
|
||||||
g_Time = current_time;
|
bd->Time = current_time;
|
||||||
|
|
||||||
ImGui_ImplOSX_UpdateMouseCursor();
|
ImGui_ImplOSX_UpdateMouseCursor();
|
||||||
ImGui_ImplOSX_UpdateGamepads();
|
ImGui_ImplOSX_UpdateGamepads();
|
||||||
|
@ -99,6 +99,8 @@ Other Changes:
|
|||||||
- Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu]
|
- Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu]
|
||||||
- Backends: SDL, OpenGL3: Fixes to facilitate building on AmigaOS4. (#5190) [@afxgroup]
|
- Backends: SDL, OpenGL3: Fixes to facilitate building on AmigaOS4. (#5190) [@afxgroup]
|
||||||
- Backends: OSX: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) [@thedmd]
|
- Backends: OSX: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) [@thedmd]
|
||||||
|
- Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with
|
||||||
|
multiple contexts. (#5203, #5221, #4141) [@noisewuwei]
|
||||||
- Examples: Emscripten+WebGPU: Fix building for latest WebGPU specs. (#3632)
|
- Examples: Emscripten+WebGPU: Fix building for latest WebGPU specs. (#3632)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user