소스 검색

Backends: OSX: Removed ImGui_ImplOSX_HandleEvent() from backend API. Move event tracking (desktop only) to OSX backend. (#4821)

Fix using NSKeyUp (#5268).
stuartcarnie 3 년 전
부모
커밋
e66fc22057
6개의 변경된 파일58개의 추가작업 그리고 56개의 파일을 삭제
  1. 0 1
      backends/imgui_impl_osx.h
  2. 37 10
      backends/imgui_impl_osx.mm
  3. 5 0
      docs/CHANGELOG.txt
  4. 15 25
      examples/example_apple_metal/main.mm
  5. 0 20
      examples/example_apple_opengl2/main.mm
  6. 1 0
      imgui.cpp

+ 0 - 1
backends/imgui_impl_osx.h

@@ -22,4 +22,3 @@
 IMGUI_IMPL_API bool     ImGui_ImplOSX_Init(NSView* _Nonnull view);
 IMGUI_IMPL_API bool     ImGui_ImplOSX_Init(NSView* _Nonnull view);
 IMGUI_IMPL_API void     ImGui_ImplOSX_Shutdown();
 IMGUI_IMPL_API void     ImGui_ImplOSX_Shutdown();
 IMGUI_IMPL_API void     ImGui_ImplOSX_NewFrame(NSView* _Nullable view);
 IMGUI_IMPL_API void     ImGui_ImplOSX_NewFrame(NSView* _Nullable view);
-IMGUI_IMPL_API bool     ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view);

+ 37 - 10
backends/imgui_impl_osx.mm

@@ -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-05-03: Inputs: Removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend automatically handling event capture.
 //  2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts.
 //  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.
@@ -66,6 +67,7 @@ struct ImGui_ImplOSX_Data
     ImGuiObserver*          Observer;
     ImGuiObserver*          Observer;
     KeyEventResponder*      KeyEventResponder;
     KeyEventResponder*      KeyEventResponder;
     NSTextInputContext*     InputContext;
     NSTextInputContext*     InputContext;
+    id                      Monitor;
 
 
     ImGui_ImplOSX_Data()    { memset(this, 0, sizeof(*this)); }
     ImGui_ImplOSX_Data()    { memset(this, 0, sizeof(*this)); }
 };
 };
@@ -76,6 +78,10 @@ static void                 ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui
 
 
 static inline CFTimeInterval GetMachAbsoluteTimeInSeconds()    { return static_cast<CFTimeInterval>(static_cast<double>(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); }
 static inline CFTimeInterval GetMachAbsoluteTimeInSeconds()    { return static_cast<CFTimeInterval>(static_cast<double>(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); }
 
 
+// Forward Declarations
+static void ImGui_ImplOSX_AddTrackingArea(NSView* _Nonnull view);
+static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view);
+
 // Undocumented methods for creating cursors.
 // Undocumented methods for creating cursors.
 @interface NSCursor()
 @interface NSCursor()
 + (id)_windowResizeNorthWestSouthEastCursor;
 + (id)_windowResizeNorthWestSouthEastCursor;
@@ -429,15 +435,7 @@ bool ImGui_ImplOSX_Init(NSView* view)
     bd->KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
     bd->KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
     bd->InputContext = [[NSTextInputContext alloc] initWithClient:bd->KeyEventResponder];
     bd->InputContext = [[NSTextInputContext alloc] initWithClient:bd->KeyEventResponder];
     [view addSubview:bd->KeyEventResponder];
     [view addSubview:bd->KeyEventResponder];
-
-    // 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.
-    NSEventMask eventMask = NSEventMaskFromType(NSKeyUp) | NSEventMaskFlagsChanged;
-    [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event)
-    {
-        ImGui_ImplOSX_HandleEvent(event, bd->KeyEventResponder);
-        return event;
-    }];
+    ImGui_ImplOSX_AddTrackingArea(view);
 
 
     io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void
     io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void
     {
     {
@@ -462,6 +460,11 @@ void ImGui_ImplOSX_Shutdown()
 {
 {
     ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
     ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
     bd->Observer = NULL;
     bd->Observer = NULL;
+    if (bd->Monitor != NULL)
+    {
+        [NSEvent removeMonitor:bd->Monitor];
+        bd->Monitor = NULL;
+    }
     ImGui_ImplOSX_DestroyBackendData();
     ImGui_ImplOSX_DestroyBackendData();
 }
 }
 
 
@@ -591,7 +594,7 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
     ImGui_ImplOSX_UpdateImePosWithView(view);
     ImGui_ImplOSX_UpdateImePosWithView(view);
 }
 }
 
 
-bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
+static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
 {
 {
     ImGuiIO& io = ImGui::GetIO();
     ImGuiIO& io = ImGui::GetIO();
 
 
@@ -716,3 +719,27 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
 
 
     return false;
     return false;
 }
 }
+
+static void ImGui_ImplOSX_AddTrackingArea(NSView* _Nonnull view)
+{
+    // If we want to receive key events, we either need to be in the responder chain of the key view,
+    // or else we can install a local monitor. The consequence of this heavy-handed approach is that
+    // we receive events for all controls, not just Dear ImGui widgets. If we had native controls in our
+    // window, we'd want to be much more careful than just ingesting the complete event stream.
+    // To match the behavior of other backends, we pass every event down to the OS.
+    ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
+    if (bd->Monitor)
+        return;
+    NSEventMask eventMask = 0;
+    eventMask |= NSEventMaskMouseMoved | NSEventMaskScrollWheel;
+    eventMask |= NSEventMaskLeftMouseDown | NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
+    eventMask |= NSEventMaskRightMouseDown | NSEventMaskRightMouseUp | NSEventMaskRightMouseDragged;
+    eventMask |= NSEventMaskOtherMouseDown | NSEventMaskOtherMouseUp | NSEventMaskOtherMouseDragged;
+    eventMask |= NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged;
+    bd->Monitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask
+                                                        handler:^NSEvent* _Nullable(NSEvent* event)
+    {
+        ImGui_ImplOSX_HandleEvent(event, view);
+        return event;
+    }];
+}

+ 5 - 0
docs/CHANGELOG.txt

@@ -39,6 +39,10 @@ Breaking changes:
 
 
 - Renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete).
 - Renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete).
   (This was never used in public API functions but technically present in imgui.h and ImGuiIO).
   (This was never used in public API functions but technically present in imgui.h and ImGuiIO).
+- Backends: OSX: Removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend
+  automatically handling event capture. Examples that are using the OSX backend have removed
+  all the now-unnecessary calls to ImGui_ImplOSX_HandleEvent(), applications can do as well.
+  [@stuartcarnie] (#4821)
 
 
 Other Changes:
 Other Changes:
 
 
@@ -105,6 +109,7 @@ Other Changes:
 - Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with
 - Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with
   multiple contexts. (#5203, #5221, #4141) [@noisewuwei]
   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)
+- Examples: OSX+Metal, OSX+OpenGL: Removed now-unnecessary calls to ImGui_ImplOSX_HandleEvent(). (#4821)
 
 
 
 
 -----------------------------------------------------------------------
 -----------------------------------------------------------------------

+ 15 - 25
examples/example_apple_metal/main.mm

@@ -17,7 +17,7 @@
 #include "imgui_impl_metal.h"
 #include "imgui_impl_metal.h"
 #if TARGET_OS_OSX
 #if TARGET_OS_OSX
 #include "imgui_impl_osx.h"
 #include "imgui_impl_osx.h"
-@interface AppViewController : NSViewController
+@interface AppViewController : NSViewController<NSWindowDelegate>
 @end
 @end
 #else
 #else
 @interface AppViewController : UIViewController
 @interface AppViewController : UIViewController
@@ -100,15 +100,8 @@
     self.mtkView.delegate = self;
     self.mtkView.delegate = self;
 
 
 #if TARGET_OS_OSX
 #if TARGET_OS_OSX
-    // Add a tracking area in order to receive mouse events whenever the mouse is within the bounds of our view
-    NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
-                                                                options:NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
-                                                                  owner:self
-                                                               userInfo:nil];
-    [self.view addTrackingArea:trackingArea];
-
     ImGui_ImplOSX_Init(self.view);
     ImGui_ImplOSX_Init(self.view);
-
+    [NSApp activateIgnoringOtherApps:YES];
 #endif
 #endif
 }
 }
 
 
@@ -209,20 +202,18 @@
 
 
 #if TARGET_OS_OSX
 #if TARGET_OS_OSX
 
 
-// Forward Mouse events to Dear ImGui OSX backend.
--(void)mouseDown:(NSEvent *)event           { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)rightMouseDown:(NSEvent *)event      { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)otherMouseDown:(NSEvent *)event      { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)mouseUp:(NSEvent *)event             { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)rightMouseUp:(NSEvent *)event        { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)otherMouseUp:(NSEvent *)event        { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)mouseMoved:(NSEvent *)event          { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)mouseDragged:(NSEvent *)event        { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)rightMouseMoved:(NSEvent *)event     { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)rightMouseDragged:(NSEvent *)event   { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)otherMouseMoved:(NSEvent *)event     { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)otherMouseDragged:(NSEvent *)event   { ImGui_ImplOSX_HandleEvent(event, self.view); }
--(void)scrollWheel:(NSEvent *)event         { ImGui_ImplOSX_HandleEvent(event, self.view); }
+- (void)viewWillAppear
+{
+    [super viewWillAppear];
+    self.view.window.delegate = self;
+}
+
+- (void)windowWillClose:(NSNotification *)notification
+{
+    ImGui_ImplMetal_Shutdown();
+    ImGui_ImplOSX_Shutdown();
+    ImGui::DestroyContext();
+}
 
 
 #else
 #else
 
 
@@ -286,9 +277,8 @@
                                                     backing:NSBackingStoreBuffered
                                                     backing:NSBackingStoreBuffered
                                                       defer:NO];
                                                       defer:NO];
         self.window.contentViewController = rootViewController;
         self.window.contentViewController = rootViewController;
-        [self.window orderFront:self];
         [self.window center];
         [self.window center];
-        [self.window becomeKeyWindow];
+        [self.window makeKeyAndOrderFront:self];
     }
     }
     return self;
     return self;
 }
 }

+ 0 - 20
examples/example_apple_opengl2/main.mm

@@ -142,26 +142,6 @@
 -(void)animationTimerFired:(NSTimer*)timer  { [self setNeedsDisplay:YES]; }
 -(void)animationTimerFired:(NSTimer*)timer  { [self setNeedsDisplay:YES]; }
 -(void)dealloc                              { animationTimer = nil; }
 -(void)dealloc                              { animationTimer = nil; }
 
 
-//-----------------------------------------------------------------------------------
-// Input processing
-//-----------------------------------------------------------------------------------
-
-// Forward Mouse/Keyboard events to Dear ImGui OSX backend.
-// Other events are registered via addLocalMonitorForEventsMatchingMask()
--(void)mouseDown:(NSEvent *)event           { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)rightMouseDown:(NSEvent *)event      { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)otherMouseDown:(NSEvent *)event      { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)mouseUp:(NSEvent *)event             { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)rightMouseUp:(NSEvent *)event        { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)otherMouseUp:(NSEvent *)event        { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)mouseMoved:(NSEvent *)event          { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)mouseDragged:(NSEvent *)event        { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)rightMouseMoved:(NSEvent *)event     { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)rightMouseDragged:(NSEvent *)event   { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)otherMouseMoved:(NSEvent *)event     { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)otherMouseDragged:(NSEvent *)event   { ImGui_ImplOSX_HandleEvent(event, self); }
--(void)scrollWheel:(NSEvent *)event         { ImGui_ImplOSX_HandleEvent(event, self); }
-
 @end
 @end
 
 
 //-----------------------------------------------------------------------------------
 //-----------------------------------------------------------------------------------

+ 1 - 0
imgui.cpp

@@ -386,6 +386,7 @@ CODE
  When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
  When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
  You can read releases logs https://github.com/ocornut/imgui/releases for more details.
  You can read releases logs https://github.com/ocornut/imgui/releases for more details.
 
 
+ - 2022/05/03 (1.88) - backends: osx: removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend automatically handling event capture. All ImGui_ImplOSX_HandleEvent() calls should be removed as they are now unnecessary.
  - 2022/04/05 (1.88) - inputs: renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete). This was never used in public API functions but technically present in imgui.h and ImGuiIO.
  - 2022/04/05 (1.88) - inputs: renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete). This was never used in public API functions but technically present in imgui.h and ImGuiIO.
  - 2022/01/20 (1.87) - inputs: reworded gamepad IO.
  - 2022/01/20 (1.87) - inputs: reworded gamepad IO.
                         - Backend writing to io.NavInputs[]            -> backend should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX values.
                         - Backend writing to io.NavInputs[]            -> backend should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX values.