mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Backends: OSX: Fix keyboard support. Handle scroll cancel. Don't set mouse cursor shape unconditionally. (#4759, #4253, #1873)
Note the original FIXME: refered to GLFWs Cocoa implementation, which is largely what this commit provides.
This commit is contained in:
		| @@ -6,10 +6,9 @@ | |||||||
| //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. | //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. | ||||||
| //  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). | //  [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: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. | ||||||
| // Issues: | //  [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space). | ||||||
| //  [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters].. |  | ||||||
|  |  | ||||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.  | // 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. | // 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. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | ||||||
| // Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | ||||||
| @@ -19,7 +18,7 @@ | |||||||
| @class NSEvent; | @class NSEvent; | ||||||
| @class NSView; | @class NSView; | ||||||
|  |  | ||||||
| IMGUI_IMPL_API bool     ImGui_ImplOSX_Init(); | 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); | IMGUI_IMPL_API bool     ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view); | ||||||
|   | |||||||
| @@ -6,22 +6,23 @@ | |||||||
| //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. | //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. | ||||||
| //  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). | //  [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: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. | ||||||
| // Issues: | //  [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space). | ||||||
| //  [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters].. |  | ||||||
|  |  | ||||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. | // 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. | // 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. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | ||||||
| // Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | ||||||
|  |  | ||||||
| #include "imgui.h" | #import "imgui.h" | ||||||
| #include "imgui_impl_osx.h" | #import "imgui_impl_osx.h" | ||||||
| #import <Cocoa/Cocoa.h> | #import <Cocoa/Cocoa.h> | ||||||
| #include <mach/mach_time.h> | #import <mach/mach_time.h> | ||||||
|  | #import <Carbon/Carbon.h> | ||||||
| #import <GameController/GameController.h> | #import <GameController/GameController.h> | ||||||
|  |  | ||||||
| // 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) | ||||||
|  | //  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. | //  2021-12-13: Add game controller support. | ||||||
| //  2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards. | //  2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards. | ||||||
| //  2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events. | //  2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events. | ||||||
| @@ -40,15 +41,17 @@ | |||||||
| //  2018-07-07: Initial version. | //  2018-07-07: Initial version. | ||||||
|  |  | ||||||
| @class ImFocusObserver; | @class ImFocusObserver; | ||||||
|  | @class KeyEventResponder; | ||||||
|  |  | ||||||
| // Data | // Data | ||||||
| static double         g_HostClockPeriod = 0.0; | static double               g_HostClockPeriod = 0.0; | ||||||
| static double         g_Time = 0.0; | static double               g_Time = 0.0; | ||||||
| static NSCursor*      g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; | static NSCursor*            g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; | ||||||
| static bool           g_MouseCursorHidden = false; | static bool                 g_MouseCursorHidden = false; | ||||||
| static bool           g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; | static bool                 g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; | ||||||
| static bool           g_MouseDown[ImGuiMouseButton_COUNT] = {}; | static bool                 g_MouseDown[ImGuiMouseButton_COUNT] = {}; | ||||||
| static ImFocusObserver* g_FocusObserver = NULL; | static ImFocusObserver*     g_FocusObserver = nil; | ||||||
|  | static KeyEventResponder*   g_KeyEventResponder = nil; | ||||||
|  |  | ||||||
| // Undocumented methods for creating cursors. | // Undocumented methods for creating cursors. | ||||||
| @interface NSCursor() | @interface NSCursor() | ||||||
| @@ -77,6 +80,102 @@ static void resetKeys() | |||||||
|     io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false; |     io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  KeyEventResponder implements the NSTextInputClient protocol as is required by the macOS text input manager. | ||||||
|  |  | ||||||
|  |  The macOS text input manager is invoked by calling the interpretKeyEvents method from the keyDown method. | ||||||
|  |  Keyboard events are then evaluated by the macOS input manager and valid text input is passed back via the | ||||||
|  |  insertText:replacementRange method. | ||||||
|  |  | ||||||
|  |  This is the same approach employed by other cross-platform libraries such as SDL2: | ||||||
|  |   https://github.com/spurious/SDL-mirror/blob/e17aacbd09e65a4fd1e166621e011e581fb017a8/src/video/cocoa/SDL_cocoakeyboard.m#L53 | ||||||
|  |  and GLFW: | ||||||
|  |   https://github.com/glfw/glfw/blob/b55a517ae0c7b5127dffa79a64f5406021bf9076/src/cocoa_window.m#L722-L723 | ||||||
|  |  */ | ||||||
|  | @interface KeyEventResponder: NSView<NSTextInputClient> | ||||||
|  | @end | ||||||
|  |  | ||||||
|  | @implementation KeyEventResponder | ||||||
|  |  | ||||||
|  | - (void)viewDidMoveToWindow | ||||||
|  | { | ||||||
|  |     // Ensure self is a first responder to receive the input events. | ||||||
|  |     [self.window makeFirstResponder:self]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (void)keyDown:(NSEvent*)event | ||||||
|  | { | ||||||
|  |     // Call to the macOS input manager system. | ||||||
|  |     [self interpretKeyEvents:@[event]]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange | ||||||
|  | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |  | ||||||
|  |     NSString* characters; | ||||||
|  |     if ([aString isKindOfClass:[NSAttributedString class]]) | ||||||
|  |         characters = [aString string]; | ||||||
|  |     else | ||||||
|  |         characters = (NSString*)aString; | ||||||
|  |  | ||||||
|  |     io.AddInputCharactersUTF8(characters.UTF8String); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (BOOL)acceptsFirstResponder | ||||||
|  | { | ||||||
|  |     return YES; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (void)doCommandBySelector:(SEL)myselector | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (nullable NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange | ||||||
|  | { | ||||||
|  |     return nil; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (NSUInteger)characterIndexForPoint:(NSPoint)point | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange | ||||||
|  | { | ||||||
|  |     return NSZeroRect; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (BOOL)hasMarkedText | ||||||
|  | { | ||||||
|  |     return NO; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (NSRange)markedRange | ||||||
|  | { | ||||||
|  |     return NSMakeRange(NSNotFound, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (NSRange)selectedRange | ||||||
|  | { | ||||||
|  |     return NSMakeRange(NSNotFound, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (void)setMarkedText:(nonnull id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (void)unmarkText | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | - (nonnull NSArray<NSAttributedStringKey>*)validAttributesForMarkedText | ||||||
|  | { | ||||||
|  |     return @[]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @end | ||||||
|  |  | ||||||
| @interface ImFocusObserver : NSObject | @interface ImFocusObserver : NSObject | ||||||
|  |  | ||||||
| - (void)onApplicationBecomeActive:(NSNotification*)aNotification; | - (void)onApplicationBecomeActive:(NSNotification*)aNotification; | ||||||
| @@ -106,7 +205,7 @@ static void resetKeys() | |||||||
| @end | @end | ||||||
|  |  | ||||||
| // Functions | // Functions | ||||||
| bool ImGui_ImplOSX_Init() | bool ImGui_ImplOSX_Init(NSView* view) | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |  | ||||||
| @@ -118,29 +217,28 @@ bool ImGui_ImplOSX_Init() | |||||||
|     io.BackendPlatformName = "imgui_impl_osx"; |     io.BackendPlatformName = "imgui_impl_osx"; | ||||||
|  |  | ||||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array. |     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array. | ||||||
|     const int offset_for_function_keys = 256 - 0xF700; |     io.KeyMap[ImGuiKey_Tab]             = kVK_Tab; | ||||||
|     io.KeyMap[ImGuiKey_Tab]             = '\t'; |     io.KeyMap[ImGuiKey_LeftArrow]       = kVK_LeftArrow; | ||||||
|     io.KeyMap[ImGuiKey_LeftArrow]       = NSLeftArrowFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_RightArrow]      = kVK_RightArrow; | ||||||
|     io.KeyMap[ImGuiKey_RightArrow]      = NSRightArrowFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_UpArrow]         = kVK_UpArrow; | ||||||
|     io.KeyMap[ImGuiKey_UpArrow]         = NSUpArrowFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_DownArrow]       = kVK_DownArrow; | ||||||
|     io.KeyMap[ImGuiKey_DownArrow]       = NSDownArrowFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_PageUp]          = kVK_PageUp; | ||||||
|     io.KeyMap[ImGuiKey_PageUp]          = NSPageUpFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_PageDown]        = kVK_PageDown; | ||||||
|     io.KeyMap[ImGuiKey_PageDown]        = NSPageDownFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_Home]            = kVK_Home; | ||||||
|     io.KeyMap[ImGuiKey_Home]            = NSHomeFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_End]             = kVK_End; | ||||||
|     io.KeyMap[ImGuiKey_End]             = NSEndFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_Insert]          = kVK_F13; | ||||||
|     io.KeyMap[ImGuiKey_Insert]          = NSInsertFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_Delete]          = kVK_ForwardDelete; | ||||||
|     io.KeyMap[ImGuiKey_Delete]          = NSDeleteFunctionKey + offset_for_function_keys; |     io.KeyMap[ImGuiKey_Backspace]       = kVK_Delete; | ||||||
|     io.KeyMap[ImGuiKey_Backspace]       = 127; |     io.KeyMap[ImGuiKey_Space]           = kVK_Space; | ||||||
|     io.KeyMap[ImGuiKey_Space]           = 32; |     io.KeyMap[ImGuiKey_Enter]           = kVK_Return; | ||||||
|     io.KeyMap[ImGuiKey_Enter]           = 13; |     io.KeyMap[ImGuiKey_Escape]          = kVK_Escape; | ||||||
|     io.KeyMap[ImGuiKey_Escape]          = 27; |     io.KeyMap[ImGuiKey_KeyPadEnter]     = kVK_ANSI_KeypadEnter; | ||||||
|     io.KeyMap[ImGuiKey_KeyPadEnter]     = 3; |     io.KeyMap[ImGuiKey_A]               = kVK_ANSI_A; | ||||||
|     io.KeyMap[ImGuiKey_A]               = 'A'; |     io.KeyMap[ImGuiKey_C]               = kVK_ANSI_C; | ||||||
|     io.KeyMap[ImGuiKey_C]               = 'C'; |     io.KeyMap[ImGuiKey_V]               = kVK_ANSI_V; | ||||||
|     io.KeyMap[ImGuiKey_V]               = 'V'; |     io.KeyMap[ImGuiKey_X]               = kVK_ANSI_X; | ||||||
|     io.KeyMap[ImGuiKey_X]               = 'X'; |     io.KeyMap[ImGuiKey_Y]               = kVK_ANSI_Y; | ||||||
|     io.KeyMap[ImGuiKey_Y]               = 'Y'; |     io.KeyMap[ImGuiKey_Z]               = kVK_ANSI_Z; | ||||||
|     io.KeyMap[ImGuiKey_Z]               = 'Z'; |  | ||||||
|  |  | ||||||
|     // Load cursors. Some of them are undocumented. |     // Load cursors. Some of them are undocumented. | ||||||
|     g_MouseCursorHidden = false; |     g_MouseCursorHidden = false; | ||||||
| @@ -193,6 +291,11 @@ bool ImGui_ImplOSX_Init() | |||||||
|                                                  name:NSApplicationDidResignActiveNotification |                                                  name:NSApplicationDidResignActiveNotification | ||||||
|                                                object:nil]; |                                                object:nil]; | ||||||
|  |  | ||||||
|  |     // Add the NSTextInputClient to the view hierarchy, | ||||||
|  |     // to receive keyboard events and translate them to input text. | ||||||
|  |     g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect]; | ||||||
|  |     [view addSubview:g_KeyEventResponder]; | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -227,8 +330,12 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons() | |||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         // Show OS mouse cursor |         NSCursor* desired = g_MouseCursors[imgui_cursor] ?: g_MouseCursors[ImGuiMouseCursor_Arrow]; | ||||||
|         [g_MouseCursors[g_MouseCursors[imgui_cursor] ? imgui_cursor : ImGuiMouseCursor_Arrow] set]; |         // -[NSCursor set] generates measureable overhead if called unconditionally. | ||||||
|  |         if (desired != NSCursor.currentCursor) | ||||||
|  |         { | ||||||
|  |             [desired set]; | ||||||
|  |         } | ||||||
|         if (g_MouseCursorHidden) |         if (g_MouseCursorHidden) | ||||||
|         { |         { | ||||||
|             g_MouseCursorHidden = false; |             g_MouseCursorHidden = false; | ||||||
| @@ -306,17 +413,22 @@ void ImGui_ImplOSX_NewFrame(NSView* view) | |||||||
|     ImGui_ImplOSX_UpdateGamepads(); |     ImGui_ImplOSX_UpdateGamepads(); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int mapCharacterToKey(int c) | NSString* NSStringFromPhase(NSEventPhase phase) | ||||||
| { | { | ||||||
|     if (c >= 'a' && c <= 'z') |     static NSString* strings[] = | ||||||
|         return c - 'a' + 'A'; |     { | ||||||
|     if (c == 25) // SHIFT+TAB -> TAB |         @"none", | ||||||
|         return 9; |         @"began", | ||||||
|     if (c >= 0 && c < 256) |         @"stationary", | ||||||
|         return c; |         @"changed", | ||||||
|     if (c >= 0xF700 && c < 0xF700 + 256) |         @"ended", | ||||||
|         return c - 0xF700 + 256; |         @"cancelled", | ||||||
|     return -1; |         @"mayBegin", | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     int pos = phase == NSEventPhaseNone ? 0 : __builtin_ctzl((NSUInteger)phase) + 1; | ||||||
|  |  | ||||||
|  |     return strings[pos]; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) | bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) | ||||||
| @@ -349,6 +461,21 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) | |||||||
|  |  | ||||||
|     if (event.type == NSEventTypeScrollWheel) |     if (event.type == NSEventTypeScrollWheel) | ||||||
|     { |     { | ||||||
|  |         // Ignore canceled events. | ||||||
|  |         // | ||||||
|  |         // From macOS 12.1, scrolling with two fingers and then decelerating | ||||||
|  |         // by tapping two fingers results in two events appearing: | ||||||
|  |         // | ||||||
|  |         // 1. A scroll wheel NSEvent, with a phase == NSEventPhaseMayBegin, when the user taps | ||||||
|  |         // two fingers to decelerate or stop the scroll events. | ||||||
|  |         // | ||||||
|  |         // 2. A scroll wheel NSEvent, with a phase == NSEventPhaseCancelled, when the user releases the | ||||||
|  |         // two-finger tap. It is this event that sometimes contains large values for scrollingDeltaX and | ||||||
|  |         // scrollingDeltaY. When these are added to the current x and y positions of the scrolling view, | ||||||
|  |         // it appears to jump up or down. It can be observed in Preview, various JetBrains IDEs and here. | ||||||
|  |         if (event.phase == NSEventPhaseCancelled) | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|         double wheel_dx = 0.0; |         double wheel_dx = 0.0; | ||||||
|         double wheel_dy = 0.0; |         double wheel_dy = 0.0; | ||||||
|  |  | ||||||
| @@ -370,6 +497,8 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) | |||||||
|             wheel_dy = [event deltaY]; |             wheel_dy = [event deltaY]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         //NSLog(@"dx=%0.3ff, dy=%0.3f, phase=%@", wheel_dx, wheel_dy, NSStringFromPhase(event.phase)); | ||||||
|  |  | ||||||
|         if (fabs(wheel_dx) > 0.0) |         if (fabs(wheel_dx) > 0.0) | ||||||
|             io.MouseWheelH += (float)wheel_dx * 0.1f; |             io.MouseWheelH += (float)wheel_dx * 0.1f; | ||||||
|         if (fabs(wheel_dy) > 0.0) |         if (fabs(wheel_dy) > 0.0) | ||||||
| @@ -377,57 +506,37 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) | |||||||
|         return io.WantCaptureMouse; |         return io.WantCaptureMouse; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // FIXME: All the key handling is wrong and broken. Refer to GLFW's cocoa_init.mm and cocoa_window.mm. |     if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp) | ||||||
|     if (event.type == NSEventTypeKeyDown) |  | ||||||
|     { |     { | ||||||
|         NSString* str = [event characters]; |         unsigned short code = event.keyCode; | ||||||
|         NSUInteger len = [str length]; |         IM_ASSERT(code >= 0 && code < IM_ARRAYSIZE(io.KeysDown)); | ||||||
|         for (NSUInteger i = 0; i < len; i++) |         io.KeysDown[code] = event.type == NSEventTypeKeyDown; | ||||||
|         { |         NSEventModifierFlags flags = event.modifierFlags; | ||||||
|             int c = [str characterAtIndex:i]; |         io.KeyCtrl  = (flags & NSEventModifierFlagControl) != 0; | ||||||
|             if (!io.KeySuper && !(c >= 0xF700 && c <= 0xFFFF) && c != 127) |         io.KeyShift = (flags & NSEventModifierFlagShift) != 0; | ||||||
|                 io.AddInputCharacter((unsigned int)c); |         io.KeyAlt   = (flags & NSEventModifierFlagOption) != 0; | ||||||
|  |         io.KeySuper = (flags & NSEventModifierFlagCommand) != 0; | ||||||
|             // We must reset in case we're pressing a sequence of special keys while keeping the command pressed |  | ||||||
|             int key = mapCharacterToKey(c); |  | ||||||
|             if (key != -1 && key < 256 && !io.KeySuper) |  | ||||||
|                 resetKeys(); |  | ||||||
|             if (key != -1) |  | ||||||
|                 io.KeysDown[key] = true; |  | ||||||
|         } |  | ||||||
|         return io.WantCaptureKeyboard; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (event.type == NSEventTypeKeyUp) |  | ||||||
|     { |  | ||||||
|         NSString* str = [event characters]; |  | ||||||
|         NSUInteger len = [str length]; |  | ||||||
|         for (NSUInteger i = 0; i < len; i++) |  | ||||||
|         { |  | ||||||
|             int c = [str characterAtIndex:i]; |  | ||||||
|             int key = mapCharacterToKey(c); |  | ||||||
|             if (key != -1) |  | ||||||
|                 io.KeysDown[key] = false; |  | ||||||
|         } |  | ||||||
|         return io.WantCaptureKeyboard; |         return io.WantCaptureKeyboard; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (event.type == NSEventTypeFlagsChanged) |     if (event.type == NSEventTypeFlagsChanged) | ||||||
|     { |     { | ||||||
|         unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; |         NSEventModifierFlags flags = event.modifierFlags; | ||||||
|  |         switch (event.keyCode) | ||||||
|         bool oldKeyCtrl = io.KeyCtrl; |         { | ||||||
|         bool oldKeyShift = io.KeyShift; |         case kVK_Control: | ||||||
|         bool oldKeyAlt = io.KeyAlt; |             io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0; | ||||||
|         bool oldKeySuper = io.KeySuper; |             break; | ||||||
|         io.KeyCtrl      = flags & NSEventModifierFlagControl; |         case kVK_Shift: | ||||||
|         io.KeyShift     = flags & NSEventModifierFlagShift; |             io.KeyShift = (flags & NSEventModifierFlagShift) != 0; | ||||||
|         io.KeyAlt       = flags & NSEventModifierFlagOption; |             break; | ||||||
|         io.KeySuper     = flags & NSEventModifierFlagCommand; |         case kVK_Option: | ||||||
|  |             io.KeyAlt = (flags & NSEventModifierFlagOption) != 0; | ||||||
|         // We must reset them as we will not receive any keyUp event if they where pressed with a modifier |             break; | ||||||
|         if ((oldKeyShift && !io.KeyShift) || (oldKeyCtrl && !io.KeyCtrl) || (oldKeyAlt && !io.KeyAlt) || (oldKeySuper && !io.KeySuper)) |         case kVK_Command: | ||||||
|             resetKeys(); |             io.KeySuper = (flags & NSEventModifierFlagCommand) != 0; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|         return io.WantCaptureKeyboard; |         return io.WantCaptureKeyboard; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,6 +38,9 @@ Breaking Changes: | |||||||
|  |  | ||||||
| - Removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges. | - Removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges. | ||||||
|   Please open an issue if you think you really need this function. (#3841) |   Please open an issue if you think you really need this function. (#3841) | ||||||
|  | - Backends: OSX: Added NSView* parameter to ImGui_ImplOSX_Init(). (#4759) [@stuartcarnie] | ||||||
|  |   Updated Apple+Metal and Apple+GL example applications accordingly. | ||||||
|  |  | ||||||
|  |  | ||||||
| Other Changes: | Other Changes: | ||||||
|  |  | ||||||
| @@ -105,6 +108,9 @@ Other Changes: | |||||||
| - Backends: DX12: Fixed DRAW_EMPTY_SCISSOR_RECTANGLE warnings. (#4775) | - Backends: DX12: Fixed DRAW_EMPTY_SCISSOR_RECTANGLE warnings. (#4775) | ||||||
| - Backends: SDL_Renderer: Added support for large meshes (64k+ vertices) with 16-bit indices, | - Backends: SDL_Renderer: Added support for large meshes (64k+ vertices) with 16-bit indices, | ||||||
|   enabling 'ImGuiBackendFlags_RendererHasVtxOffset' in the backend. (#3926) [@rokups] |   enabling 'ImGuiBackendFlags_RendererHasVtxOffset' in the backend. (#3926) [@rokups] | ||||||
|  | - Backends: OSX: Generally fix keyboard support. Keyboard arrays indexed using kVK_* codes, e.g. | ||||||
|  |   ImGui::IsKeyPressed(kVK_Space). Don't set mouse cursor shape unconditionally. Handle two fingers scroll | ||||||
|  |   cancel event. (#4759, #4253, #1873) [@stuartcarnie] | ||||||
| - Backends: OSX: Add Game Controller support (need linking GameController framework) (#4759) [@stuartcarnie] | - Backends: OSX: Add Game Controller support (need linking GameController framework) (#4759) [@stuartcarnie] | ||||||
| - Backends: WebGPU: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer() and | - Backends: WebGPU: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer() and | ||||||
|   wgpuRenderPassEncoderSetIndexBuffer() functions as validation layers appears to not do what the |   wgpuRenderPassEncoderSetIndexBuffer() functions as validation layers appears to not do what the | ||||||
|   | |||||||
| @@ -119,7 +119,7 @@ | |||||||
|         return event; |         return event; | ||||||
|     }]; |     }]; | ||||||
|  |  | ||||||
|     ImGui_ImplOSX_Init(); |     ImGui_ImplOSX_Init(self.view); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ | |||||||
|     //ImGui::StyleColorsClassic(); |     //ImGui::StyleColorsClassic(); | ||||||
|  |  | ||||||
|     // Setup Platform/Renderer backends |     // Setup Platform/Renderer backends | ||||||
|     ImGui_ImplOSX_Init(); |     ImGui_ImplOSX_Init(self); | ||||||
|     ImGui_ImplOpenGL2_Init(); |     ImGui_ImplOpenGL2_Init(); | ||||||
|  |  | ||||||
|     // Load Fonts |     // Load Fonts | ||||||
| @@ -149,9 +149,6 @@ | |||||||
| -(void)reshape                              { [[self openGLContext] update]; [self updateAndDrawDemoView]; } | -(void)reshape                              { [[self openGLContext] update]; [self updateAndDrawDemoView]; } | ||||||
| -(void)drawRect:(NSRect)bounds              { [self updateAndDrawDemoView]; } | -(void)drawRect:(NSRect)bounds              { [self updateAndDrawDemoView]; } | ||||||
| -(void)animationTimerFired:(NSTimer*)timer  { [self setNeedsDisplay:YES]; } | -(void)animationTimerFired:(NSTimer*)timer  { [self setNeedsDisplay:YES]; } | ||||||
| -(BOOL)acceptsFirstResponder                { return (YES); } |  | ||||||
| -(BOOL)becomeFirstResponder                 { return (YES); } |  | ||||||
| -(BOOL)resignFirstResponder                 { return (YES); } |  | ||||||
| -(void)dealloc                              { animationTimer = nil; } | -(void)dealloc                              { animationTimer = nil; } | ||||||
|  |  | ||||||
| //----------------------------------------------------------------------------------- | //----------------------------------------------------------------------------------- | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user