Skip to content

Commit

Permalink
Fix OSX backend threading issues
Browse files Browse the repository at this point in the history
  • Loading branch information
marzent committed Jun 19, 2023
1 parent 1949161 commit dfc6bd2
Showing 1 changed file with 68 additions and 29 deletions.
97 changes: 68 additions & 29 deletions backends/imgui_impl_osx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-06-19: Fixed threading issues with io.SetClipboardTextFn(), io.GetClipboardTextFn() and io.SetPlatformImeDataFn().
// 2023-04-09: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_Pen.
// 2023-02-01: Fixed scroll wheel scaling for devices emitting events with hasPreciseScrollingDeltas==false (e.g. non-Apple mices).
// 2022-11-02: Fixed mouse coordinates before clicking the host window.
Expand Down Expand Up @@ -412,30 +413,57 @@ bool ImGui_ImplOSX_Init(NSView* view)
// 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.
// Since we are already in ObjC land here, it is easy for us to add a clipboard handler using the NSPasteboard api.
// The events below may be blocking until dispatched when not invoked from the main thread (usually in the realm of 0.6 to 2ms). See #6527.
io.SetClipboardTextFn = [](void*, const char* str) -> void
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
[pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
[pasteboard setString:[NSString stringWithUTF8String:str] forType:NSPasteboardTypeString];
void (*setClipboardText)(const char*) = [](const char* str) -> void
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
[pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
[pasteboard setString:[NSString stringWithUTF8String:str] forType:NSPasteboardTypeString];
};

if ([NSThread isMainThread])
return setClipboardText(str);

dispatch_sync(dispatch_get_main_queue(),
^{
setClipboardText(str);
});
};

io.GetClipboardTextFn = [](void*) -> const char*
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
NSString* available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:NSPasteboardTypeString]];
if (![available isEqualToString:NSPasteboardTypeString])
return nullptr;

NSString* string = [pasteboard stringForType:NSPasteboardTypeString];
if (string == nil)
return nullptr;

const char* string_c = (const char*)[string UTF8String];
size_t string_len = strlen(string_c);
static ImVector<char> s_clipboard;
s_clipboard.resize((int)string_len + 1);
strcpy(s_clipboard.Data, string_c);
return s_clipboard.Data;
const char* (*getClipboardText)(void) = [](void) -> const char*
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
NSString* available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:NSPasteboardTypeString]];
if (![available isEqualToString:NSPasteboardTypeString])
return nullptr;

NSString* string = [pasteboard stringForType:NSPasteboardTypeString];
if (string == nil)
return nullptr;

const char* string_c = (const char*)[string UTF8String];
size_t string_len = strlen(string_c);
static ImVector<char> s_clipboard;
s_clipboard.resize((int)string_len + 1);
strcpy(s_clipboard.Data, string_c);
return s_clipboard.Data;
};

if ([NSThread isMainThread])
return getClipboardText();

__block const char* clipboardText;

dispatch_sync(dispatch_get_main_queue(),
^{
clipboardText = getClipboardText();
});

return clipboardText;
};

[[NSNotificationCenter defaultCenter] addObserver:bd->Observer
Expand All @@ -456,18 +484,29 @@ bool ImGui_ImplOSX_Init(NSView* view)

io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void
{
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
if (data->WantVisible)
{
[bd->InputContext activate];
}
else
void (*setPlatformImeData)(ImGuiPlatformImeData*) = [](ImGuiPlatformImeData* data) -> void
{
[bd->InputContext discardMarkedText];
[bd->InputContext invalidateCharacterCoordinates];
[bd->InputContext deactivate];
}
[bd->KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight];
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
if (data->WantVisible)
{
[bd->InputContext activate];
}
else
{
[bd->InputContext discardMarkedText];
[bd->InputContext invalidateCharacterCoordinates];
[bd->InputContext deactivate];
}
[bd->KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight];
};

if ([NSThread isMainThread])
return setPlatformImeData(data);

dispatch_sync(dispatch_get_main_queue(),
^{
setPlatformImeData(data);
});
};

return true;
Expand Down

0 comments on commit dfc6bd2

Please sign in to comment.