Browse Source

Backends: OSX: Adedd basic IME support for macOS. (#3108, #2598)

Liu Liu 3 years ago
parent
commit
457d4b7b72
3 changed files with 54 additions and 2 deletions
  1. 2 1
      backends/imgui_impl_osx.h
  2. 51 1
      backends/imgui_impl_osx.mm
  3. 1 0
      docs/CHANGELOG.txt

+ 2 - 1
backends/imgui_impl_osx.h

@@ -7,7 +7,8 @@
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
 //  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-
+//  [X] Platform: IME support.
+//
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.

+ 51 - 1
backends/imgui_impl_osx.mm

@@ -7,6 +7,7 @@
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
 //  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+//  [X] Platform: IME support.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -22,6 +23,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2022-01-12: Inputs: Added basic Platform IME support, hooking the io.SetPlatformImeDataFn() function.
 //  2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
 //  2021-12-13: *BREAKING CHANGE* Add NSView parameter to ImGui_ImplOSX_Init(). Generally fix keyboard support. Using kVK_* codes for keyboard keys.
 //  2021-12-13: Add game controller support.
@@ -54,6 +56,7 @@ static bool                 g_MouseDown[ImGuiMouseButton_COUNT] = {};
 static ImGuiKeyModFlags     g_KeyModifiers = ImGuiKeyModFlags_None;
 static ImFocusObserver*     g_FocusObserver = nil;
 static KeyEventResponder*   g_KeyEventResponder = nil;
+static NSTextInputContext*  g_InputContext = nil;
 
 // Undocumented methods for creating cursors.
 @interface NSCursor()
@@ -91,6 +94,29 @@ static double GetMachAbsoluteTimeInSeconds()
 @end
 
 @implementation KeyEventResponder
+{
+    float _posX;
+    float _posY;
+    NSRect _imeRect;
+}
+
+#pragma mark - Public
+
+- (void)setImePosX:(float)posX imePosY:(float)posY
+{
+    _posX = posX;
+    _posY = posY;
+}
+
+- (void)updateImePosWithView:(NSView *)view
+{
+    NSWindow *window = view.window;
+    if (!window)
+        return;
+    NSRect contentRect = [window contentRectForFrameRect:window.frame];
+    NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
+    _imeRect = [window convertRectToScreen:rect];
+}
 
 - (void)viewDidMoveToWindow
 {
@@ -145,7 +171,7 @@ static double GetMachAbsoluteTimeInSeconds()
 
 - (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
 {
-    return NSZeroRect;
+    return _imeRect;
 }
 
 - (BOOL)hasMarkedText
@@ -390,6 +416,7 @@ bool ImGui_ImplOSX_Init(NSView* view)
     // Add the NSTextInputClient to the view hierarchy,
     // to receive keyboard events and translate them to input text.
     g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
+    g_InputContext = [[NSTextInputContext alloc] initWithClient:g_KeyEventResponder];
     [view addSubview:g_KeyEventResponder];
 
     // Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down).
@@ -401,6 +428,21 @@ bool ImGui_ImplOSX_Init(NSView* view)
         return event;
     }];
 
+    io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void
+    {
+        if (data->WantVisible)
+        {
+            [g_InputContext activate];
+        }
+        else
+        {
+            [g_InputContext discardMarkedText];
+            [g_InputContext invalidateCharacterCoordinates];
+            [g_InputContext deactivate];
+        }
+        [g_KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight];
+    };
+
     return true;
 }
 
@@ -499,6 +541,13 @@ static void ImGui_ImplOSX_UpdateKeyModifiers()
     io.AddKeyModsEvent(g_KeyModifiers);
 }
 
+static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view)
+{
+    ImGuiIO& io = ImGui::GetIO();
+    if (io.WantTextInput)
+        [g_KeyEventResponder updateImePosWithView:view];
+}
+
 void ImGui_ImplOSX_NewFrame(NSView* view)
 {
     // Setup display size
@@ -523,6 +572,7 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
     ImGui_ImplOSX_UpdateKeyModifiers();
     ImGui_ImplOSX_UpdateMouseCursorAndButtons();
     ImGui_ImplOSX_UpdateGamepads();
+    ImGui_ImplOSX_UpdateImePosWithView(view);
 }
 
 bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)

+ 1 - 0
docs/CHANGELOG.txt

@@ -104,6 +104,7 @@ Other Changes:
   Enable with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file.
 - Backends: Metal: Ignore ImDrawCmd where ElemCount == 0, which are normally not emitted by the library but
   can theorically be created by user code manipulating a ImDrawList. (#4857)
+- Backends: OSX: Added basic Platform IME support. (#3108, #2598) [@liuliu]
 - Backends: WebGPU: Fixed incorrect size parameters in wgpuRenderPassEncoderSetIndexBuffer() and
   wgpuRenderPassEncoderSetVertexBuffer() calls. (#4891) [@FeepsDev]