imgui_impl_osx.mm (imgui-1.86) | : | imgui_impl_osx.mm (imgui-1.87) | ||
---|---|---|---|---|
// dear imgui: Platform Backend for OSX / Cocoa | // dear imgui: Platform Backend for OSX / Cocoa | |||
// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, M etal..) | // This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, M etal..) | |||
// [ALPHA] Early backend, not well tested. If you want a portable application, p refer using the GLFW or SDL platform Backends on Mac. | // [ALPHA] Early backend, not well tested. If you want a portable application, p refer using the GLFW or SDL platform Backends on Mac. | |||
// Implemented features: | // Implemented features: | |||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlag s |= ImGuiConfigFlags_NoMouseCursorChange'. | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlag s |= ImGuiConfigFlags_NoMouseCursorChange'. | |||
// [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(Im GuiKey_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: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). | |||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFl ags_NavEnableGamepad'. | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFl ags_NavEnableGamepad'. | |||
// [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPr essed(kVK_Space). | // [X] Platform: IME support. | |||
// You can use unmodified imgui_impl_* files in your project. See examples/ fold er for examples of using this. | // You can use unmodified imgui_impl_* files in your project. See examples/ fold er 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 | |||
#import "imgui.h" | #import "imgui.h" | |||
#import "imgui_impl_osx.h" | #import "imgui_impl_osx.h" | |||
#import <Cocoa/Cocoa.h> | #import <Cocoa/Cocoa.h> | |||
#import <mach/mach_time.h> | #import <mach/mach_time.h> | |||
#import <Carbon/Carbon.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) | |||
// 2022-02-07: Inputs: Forward keyDown/keyUp events to OS when unused by dear i | ||||
mgui. | ||||
// 2022-01-31: Fix building with old Xcode versions that are missing gamepad fe | ||||
atures. | ||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two wee | ||||
ks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusio | ||||
n. | ||||
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, | ||||
instead of writing directly to io.NavInputs[]. | ||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEven | ||||
t(), io.AddMouseWheelEvent() API (1.87+). | ||||
// 2022-01-12: Inputs: Added basic Platform IME support, hooking the io.SetPlat | ||||
formImeDataFn() 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: *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 back wards. | // 2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump back wards. | |||
// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotifi cation/NSApplicationDidResignActiveNotification events. | // 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotifi cation/NSApplicationDidResignActiveNotification events. | |||
// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key. | // 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key. | |||
// 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state wh en CMD-tabbing into different application. | // 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state wh en CMD-tabbing into different application. | |||
// 2021-01-27: Inputs: Added a fix for mouse position not being reported when m ouse buttons other than left one are down. | // 2021-01-27: Inputs: Added a fix for mouse position not being reported when m ouse buttons other than left one are down. | |||
// 2020-10-28: Inputs: Added a fix for handling keypad-enter key. | // 2020-10-28: Inputs: Added a fix for handling keypad-enter key. | |||
// 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with " soft tap". | // 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with " soft tap". | |||
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse curs or. | // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse curs or. | |||
// 2019-10-11: Inputs: Fix using Backspace key. | // 2019-10-11: Inputs: Fix using Backspace key. | |||
// 2019-07-21: Re-added clipboard handlers as they are not enabled by default i n core imgui.cpp (reverted 2019-05-18 change). | // 2019-07-21: Re-added clipboard handlers as they are not enabled by default i n core imgui.cpp (reverted 2019-05-18 change). | |||
// 2019-05-28: Inputs: Added mouse cursor shape and visibility support. | // 2019-05-28: Inputs: Added mouse cursor shape and visibility support. | |||
// 2019-05-18: Misc: Removed clipboard handlers as they are now supported by co re imgui.cpp. | // 2019-05-18: Misc: Removed clipboard handlers as they are now supported by co re imgui.cpp. | |||
// 2019-05-11: Inputs: Don't filter character values before calling AddInputCha racter() apart from 0xF700..0xFFFF range. | // 2019-05-11: Inputs: Don't filter character values before calling AddInputCha racter() apart from 0xF700..0xFFFF range. | |||
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed i n the About Window. | // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed i n the About Window. | |||
// 2018-07-07: Initial version. | // 2018-07-07: Initial version. | |||
#define APPLE_HAS_BUTTON_OPTIONS (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000 || | ||||
__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500 || __TV_OS_VERSION_MIN_REQUIRED >= 130 | ||||
000) | ||||
#define APPLE_HAS_CONTROLLER (__IPHONE_OS_VERSION_MIN_REQUIRED >= 140000 || | ||||
__MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 || __TV_OS_VERSION_MIN_REQUIRED >= 140 | ||||
000) | ||||
#define APPLE_HAS_THUMBSTICKS (__IPHONE_OS_VERSION_MIN_REQUIRED >= 120100 || | ||||
__MAC_OS_X_VERSION_MIN_REQUIRED >= 101401 || __TV_OS_VERSION_MIN_REQUIRED >= 120 | ||||
100) | ||||
@class ImFocusObserver; | @class ImFocusObserver; | |||
@class KeyEventResponder; | @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_MouseDown[ImGuiMouseButton_COUNT] = {}; | ||||
static ImFocusObserver* g_FocusObserver = nil; | static ImFocusObserver* g_FocusObserver = nil; | |||
static KeyEventResponder* g_KeyEventResponder = nil; | static KeyEventResponder* g_KeyEventResponder = nil; | |||
static NSTextInputContext* g_InputContext = nil; | ||||
// Undocumented methods for creating cursors. | // Undocumented methods for creating cursors. | |||
@interface NSCursor() | @interface NSCursor() | |||
+ (id)_windowResizeNorthWestSouthEastCursor; | + (id)_windowResizeNorthWestSouthEastCursor; | |||
+ (id)_windowResizeNorthEastSouthWestCursor; | + (id)_windowResizeNorthEastSouthWestCursor; | |||
+ (id)_windowResizeNorthSouthCursor; | + (id)_windowResizeNorthSouthCursor; | |||
+ (id)_windowResizeEastWestCursor; | + (id)_windowResizeEastWestCursor; | |||
@end | @end | |||
static void InitHostClockPeriod() | static void InitHostClockPeriod() | |||
skipping to change at line 76 | skipping to change at line 87 | |||
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); // Per iod is the reciprocal of frequency. | g_HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Per iod is the reciprocal of frequency. | |||
} | } | |||
static double GetMachAbsoluteTimeInSeconds() | static double GetMachAbsoluteTimeInSeconds() | |||
{ | { | |||
return (double)mach_absolute_time() * g_HostClockPeriod; | return (double)mach_absolute_time() * g_HostClockPeriod; | |||
} | } | |||
static void resetKeys() | ||||
{ | ||||
ImGuiIO& io = ImGui::GetIO(); | ||||
memset(io.KeysDown, 0, sizeof(io.KeysDown)); | ||||
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false; | ||||
} | ||||
/** | /** | |||
KeyEventResponder implements the NSTextInputClient protocol as is required by t he macOS text input manager. | KeyEventResponder implements the NSTextInputClient protocol as is required by t he macOS text input manager. | |||
The macOS text input manager is invoked by calling the interpretKeyEvents metho d from the keyDown method. | The macOS text input manager is invoked by calling the interpretKeyEvents metho d from the keyDown method. | |||
Keyboard events are then evaluated by the macOS input manager and valid text in put is passed back via the | Keyboard events are then evaluated by the macOS input manager and valid text in put is passed back via the | |||
insertText:replacementRange method. | insertText:replacementRange method. | |||
This is the same approach employed by other cross-platform libraries such as SD L2: | This is the same approach employed by other cross-platform libraries such as SD L2: | |||
https://github.com/spurious/SDL-mirror/blob/e17aacbd09e65a4fd1e166621e011e581f b017a8/src/video/cocoa/SDL_cocoakeyboard.m#L53 | https://github.com/spurious/SDL-mirror/blob/e17aacbd09e65a4fd1e166621e011e581f b017a8/src/video/cocoa/SDL_cocoakeyboard.m#L53 | |||
and GLFW: | and GLFW: | |||
https://github.com/glfw/glfw/blob/b55a517ae0c7b5127dffa79a64f5406021bf9076/src /cocoa_window.m#L722-L723 | https://github.com/glfw/glfw/blob/b55a517ae0c7b5127dffa79a64f5406021bf9076/src /cocoa_window.m#L722-L723 | |||
*/ | */ | |||
@interface KeyEventResponder: NSView<NSTextInputClient> | @interface KeyEventResponder: NSView<NSTextInputClient> | |||
@end | @end | |||
@implementation KeyEventResponder | @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 | - (void)viewDidMoveToWindow | |||
{ | { | |||
// Ensure self is a first responder to receive the input events. | // Ensure self is a first responder to receive the input events. | |||
[self.window makeFirstResponder:self]; | [self.window makeFirstResponder:self]; | |||
} | } | |||
- (void)keyDown:(NSEvent*)event | - (void)keyDown:(NSEvent*)event | |||
{ | { | |||
if (!ImGui_ImplOSX_HandleEvent(event, self)) | ||||
[super keyDown:event]; | ||||
// Call to the macOS input manager system. | // Call to the macOS input manager system. | |||
[self interpretKeyEvents:@[event]]; | [self interpretKeyEvents:@[event]]; | |||
} | } | |||
- (void)keyUp:(NSEvent*)event | ||||
{ | ||||
if (!ImGui_ImplOSX_HandleEvent(event, self)) | ||||
[super keyUp:event]; | ||||
} | ||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange | - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange | |||
{ | { | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
NSString* characters; | NSString* characters; | |||
if ([aString isKindOfClass:[NSAttributedString class]]) | if ([aString isKindOfClass:[NSAttributedString class]]) | |||
characters = [aString string]; | characters = [aString string]; | |||
else | else | |||
characters = (NSString*)aString; | characters = (NSString*)aString; | |||
skipping to change at line 146 | skipping to change at line 182 | |||
return nil; | return nil; | |||
} | } | |||
- (NSUInteger)characterIndexForPoint:(NSPoint)point | - (NSUInteger)characterIndexForPoint:(NSPoint)point | |||
{ | { | |||
return 0; | return 0; | |||
} | } | |||
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRang ePointer)actualRange | - (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRang ePointer)actualRange | |||
{ | { | |||
return NSZeroRect; | return _imeRect; | |||
} | } | |||
- (BOOL)hasMarkedText | - (BOOL)hasMarkedText | |||
{ | { | |||
return NO; | return NO; | |||
} | } | |||
- (NSRange)markedRange | - (NSRange)markedRange | |||
{ | { | |||
return NSMakeRange(NSNotFound, 0); | return NSMakeRange(NSNotFound, 0); | |||
skipping to change at line 198 | skipping to change at line 234 | |||
- (void)onApplicationBecomeActive:(NSNotification*)aNotification | - (void)onApplicationBecomeActive:(NSNotification*)aNotification | |||
{ | { | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
io.AddFocusEvent(true); | io.AddFocusEvent(true); | |||
} | } | |||
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification | - (void)onApplicationBecomeInactive:(NSNotification*)aNotification | |||
{ | { | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
io.AddFocusEvent(false); | io.AddFocusEvent(false); | |||
// Unfocused applications do not receive input events, therefore we must man | ||||
ually | ||||
// release any pressed keys when application loses focus, otherwise they wou | ||||
ld remain | ||||
// stuck in a pressed state. https://github.com/ocornut/imgui/issues/3832 | ||||
resetKeys(); | ||||
} | } | |||
@end | @end | |||
// Functions | // Functions | |||
static ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code) | ||||
{ | ||||
switch (key_code) | ||||
{ | ||||
case kVK_ANSI_A: return ImGuiKey_A; | ||||
case kVK_ANSI_S: return ImGuiKey_S; | ||||
case kVK_ANSI_D: return ImGuiKey_D; | ||||
case kVK_ANSI_F: return ImGuiKey_F; | ||||
case kVK_ANSI_H: return ImGuiKey_H; | ||||
case kVK_ANSI_G: return ImGuiKey_G; | ||||
case kVK_ANSI_Z: return ImGuiKey_Z; | ||||
case kVK_ANSI_X: return ImGuiKey_X; | ||||
case kVK_ANSI_C: return ImGuiKey_C; | ||||
case kVK_ANSI_V: return ImGuiKey_V; | ||||
case kVK_ANSI_B: return ImGuiKey_B; | ||||
case kVK_ANSI_Q: return ImGuiKey_Q; | ||||
case kVK_ANSI_W: return ImGuiKey_W; | ||||
case kVK_ANSI_E: return ImGuiKey_E; | ||||
case kVK_ANSI_R: return ImGuiKey_R; | ||||
case kVK_ANSI_Y: return ImGuiKey_Y; | ||||
case kVK_ANSI_T: return ImGuiKey_T; | ||||
case kVK_ANSI_1: return ImGuiKey_1; | ||||
case kVK_ANSI_2: return ImGuiKey_2; | ||||
case kVK_ANSI_3: return ImGuiKey_3; | ||||
case kVK_ANSI_4: return ImGuiKey_4; | ||||
case kVK_ANSI_6: return ImGuiKey_6; | ||||
case kVK_ANSI_5: return ImGuiKey_5; | ||||
case kVK_ANSI_Equal: return ImGuiKey_Equal; | ||||
case kVK_ANSI_9: return ImGuiKey_9; | ||||
case kVK_ANSI_7: return ImGuiKey_7; | ||||
case kVK_ANSI_Minus: return ImGuiKey_Minus; | ||||
case kVK_ANSI_8: return ImGuiKey_8; | ||||
case kVK_ANSI_0: return ImGuiKey_0; | ||||
case kVK_ANSI_RightBracket: return ImGuiKey_RightBracket; | ||||
case kVK_ANSI_O: return ImGuiKey_O; | ||||
case kVK_ANSI_U: return ImGuiKey_U; | ||||
case kVK_ANSI_LeftBracket: return ImGuiKey_LeftBracket; | ||||
case kVK_ANSI_I: return ImGuiKey_I; | ||||
case kVK_ANSI_P: return ImGuiKey_P; | ||||
case kVK_ANSI_L: return ImGuiKey_L; | ||||
case kVK_ANSI_J: return ImGuiKey_J; | ||||
case kVK_ANSI_Quote: return ImGuiKey_Apostrophe; | ||||
case kVK_ANSI_K: return ImGuiKey_K; | ||||
case kVK_ANSI_Semicolon: return ImGuiKey_Semicolon; | ||||
case kVK_ANSI_Backslash: return ImGuiKey_Backslash; | ||||
case kVK_ANSI_Comma: return ImGuiKey_Comma; | ||||
case kVK_ANSI_Slash: return ImGuiKey_Slash; | ||||
case kVK_ANSI_N: return ImGuiKey_N; | ||||
case kVK_ANSI_M: return ImGuiKey_M; | ||||
case kVK_ANSI_Period: return ImGuiKey_Period; | ||||
case kVK_ANSI_Grave: return ImGuiKey_GraveAccent; | ||||
case kVK_ANSI_KeypadDecimal: return ImGuiKey_KeypadDecimal; | ||||
case kVK_ANSI_KeypadMultiply: return ImGuiKey_KeypadMultiply; | ||||
case kVK_ANSI_KeypadPlus: return ImGuiKey_KeypadAdd; | ||||
case kVK_ANSI_KeypadClear: return ImGuiKey_NumLock; | ||||
case kVK_ANSI_KeypadDivide: return ImGuiKey_KeypadDivide; | ||||
case kVK_ANSI_KeypadEnter: return ImGuiKey_KeypadEnter; | ||||
case kVK_ANSI_KeypadMinus: return ImGuiKey_KeypadSubtract; | ||||
case kVK_ANSI_KeypadEquals: return ImGuiKey_KeypadEqual; | ||||
case kVK_ANSI_Keypad0: return ImGuiKey_Keypad0; | ||||
case kVK_ANSI_Keypad1: return ImGuiKey_Keypad1; | ||||
case kVK_ANSI_Keypad2: return ImGuiKey_Keypad2; | ||||
case kVK_ANSI_Keypad3: return ImGuiKey_Keypad3; | ||||
case kVK_ANSI_Keypad4: return ImGuiKey_Keypad4; | ||||
case kVK_ANSI_Keypad5: return ImGuiKey_Keypad5; | ||||
case kVK_ANSI_Keypad6: return ImGuiKey_Keypad6; | ||||
case kVK_ANSI_Keypad7: return ImGuiKey_Keypad7; | ||||
case kVK_ANSI_Keypad8: return ImGuiKey_Keypad8; | ||||
case kVK_ANSI_Keypad9: return ImGuiKey_Keypad9; | ||||
case kVK_Return: return ImGuiKey_Enter; | ||||
case kVK_Tab: return ImGuiKey_Tab; | ||||
case kVK_Space: return ImGuiKey_Space; | ||||
case kVK_Delete: return ImGuiKey_Backspace; | ||||
case kVK_Escape: return ImGuiKey_Escape; | ||||
case kVK_CapsLock: return ImGuiKey_CapsLock; | ||||
case kVK_Control: return ImGuiKey_LeftCtrl; | ||||
case kVK_Shift: return ImGuiKey_LeftShift; | ||||
case kVK_Option: return ImGuiKey_LeftAlt; | ||||
case kVK_Command: return ImGuiKey_LeftSuper; | ||||
case kVK_RightControl: return ImGuiKey_RightCtrl; | ||||
case kVK_RightShift: return ImGuiKey_RightShift; | ||||
case kVK_RightOption: return ImGuiKey_RightAlt; | ||||
case kVK_RightCommand: return ImGuiKey_RightSuper; | ||||
// case kVK_Function: return ImGuiKey_; | ||||
// case kVK_F17: return ImGuiKey_; | ||||
// case kVK_VolumeUp: return ImGuiKey_; | ||||
// case kVK_VolumeDown: return ImGuiKey_; | ||||
// case kVK_Mute: return ImGuiKey_; | ||||
// case kVK_F18: return ImGuiKey_; | ||||
// case kVK_F19: return ImGuiKey_; | ||||
// case kVK_F20: return ImGuiKey_; | ||||
case kVK_F5: return ImGuiKey_F5; | ||||
case kVK_F6: return ImGuiKey_F6; | ||||
case kVK_F7: return ImGuiKey_F7; | ||||
case kVK_F3: return ImGuiKey_F3; | ||||
case kVK_F8: return ImGuiKey_F8; | ||||
case kVK_F9: return ImGuiKey_F9; | ||||
case kVK_F11: return ImGuiKey_F11; | ||||
case kVK_F13: return ImGuiKey_PrintScreen; | ||||
// case kVK_F16: return ImGuiKey_; | ||||
// case kVK_F14: return ImGuiKey_; | ||||
case kVK_F10: return ImGuiKey_F10; | ||||
case 0x6E: return ImGuiKey_Menu; | ||||
case kVK_F12: return ImGuiKey_F12; | ||||
// case kVK_F15: return ImGuiKey_; | ||||
case kVK_Help: return ImGuiKey_Insert; | ||||
case kVK_Home: return ImGuiKey_Home; | ||||
case kVK_PageUp: return ImGuiKey_PageUp; | ||||
case kVK_ForwardDelete: return ImGuiKey_Delete; | ||||
case kVK_F4: return ImGuiKey_F4; | ||||
case kVK_End: return ImGuiKey_End; | ||||
case kVK_F2: return ImGuiKey_F2; | ||||
case kVK_PageDown: return ImGuiKey_PageDown; | ||||
case kVK_F1: return ImGuiKey_F1; | ||||
case kVK_LeftArrow: return ImGuiKey_LeftArrow; | ||||
case kVK_RightArrow: return ImGuiKey_RightArrow; | ||||
case kVK_DownArrow: return ImGuiKey_DownArrow; | ||||
case kVK_UpArrow: return ImGuiKey_UpArrow; | ||||
default: return ImGuiKey_None; | ||||
} | ||||
} | ||||
bool ImGui_ImplOSX_Init(NSView* view) | bool ImGui_ImplOSX_Init(NSView* view) | |||
{ | { | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
// Setup backend capabilities flags | // Setup backend capabilities flags | |||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can ho nor GetMouseCursor() values (optional) | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can ho nor GetMouseCursor() values (optional) | |||
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can ho nor io.WantSetMousePos requests (optional, rarely used) | //io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can ho nor io.WantSetMousePos requests (optional, rarely used) | |||
//io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can cr eate multi-viewports on the Platform side (optional) | //io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can cr eate multi-viewports on the Platform side (optional) | |||
//io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can se t io.MouseHoveredViewport correctly (optional, not easy) | //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can se t io.MouseHoveredViewport correctly (optional, not easy) | |||
io.BackendPlatformName = "imgui_impl_osx"; | io.BackendPlatformName = "imgui_impl_osx"; | |||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.K | ||||
eyDown[] array. | ||||
io.KeyMap[ImGuiKey_Tab] = kVK_Tab; | ||||
io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow; | ||||
io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow; | ||||
io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow; | ||||
io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow; | ||||
io.KeyMap[ImGuiKey_PageUp] = kVK_PageUp; | ||||
io.KeyMap[ImGuiKey_PageDown] = kVK_PageDown; | ||||
io.KeyMap[ImGuiKey_Home] = kVK_Home; | ||||
io.KeyMap[ImGuiKey_End] = kVK_End; | ||||
io.KeyMap[ImGuiKey_Insert] = kVK_F13; | ||||
io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete; | ||||
io.KeyMap[ImGuiKey_Backspace] = kVK_Delete; | ||||
io.KeyMap[ImGuiKey_Space] = kVK_Space; | ||||
io.KeyMap[ImGuiKey_Enter] = kVK_Return; | ||||
io.KeyMap[ImGuiKey_Escape] = kVK_Escape; | ||||
io.KeyMap[ImGuiKey_KeyPadEnter] = kVK_ANSI_KeypadEnter; | ||||
io.KeyMap[ImGuiKey_A] = kVK_ANSI_A; | ||||
io.KeyMap[ImGuiKey_C] = kVK_ANSI_C; | ||||
io.KeyMap[ImGuiKey_V] = kVK_ANSI_V; | ||||
io.KeyMap[ImGuiKey_X] = kVK_ANSI_X; | ||||
io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y; | ||||
io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z; | ||||
// Load cursors. Some of them are undocumented. | // Load cursors. Some of them are undocumented. | |||
g_MouseCursorHidden = false; | g_MouseCursorHidden = false; | |||
g_MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor]; | g_MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor]; | |||
g_MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor]; | g_MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor]; | |||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor]; | g_MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor]; | |||
g_MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor]; | g_MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor]; | |||
g_MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedC ursor]; | g_MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedC ursor]; | |||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@se lector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor ] : [NSCursor resizeUpDownCursor]; | g_MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@se lector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor ] : [NSCursor resizeUpDownCursor]; | |||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@se lector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor]; | g_MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@se lector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor]; | |||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@ selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthE astSouthWestCursor] : [NSCursor closedHandCursor]; | g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@ selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthE astSouthWestCursor] : [NSCursor closedHandCursor]; | |||
skipping to change at line 297 | skipping to change at line 426 | |||
name:NSApplicationDidBecomeActi veNotification | name:NSApplicationDidBecomeActi veNotification | |||
object:nil]; | object:nil]; | |||
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver | [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver | |||
selector:@selector(onApplicationBec omeInactive:) | selector:@selector(onApplicationBec omeInactive:) | |||
name:NSApplicationDidResignActi veNotification | name:NSApplicationDidResignActi veNotification | |||
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]; | g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect]; | |||
g_InputContext = [[NSTextInputContext alloc] initWithClient:g_KeyEventRespon der]; | ||||
[view addSubview: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). | ||||
// This monitor taps into global event stream and captures these events. | ||||
NSEventMask eventMask = NSEventMaskFlagsChanged; | ||||
[NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _ | ||||
Nullable(NSEvent *event) | ||||
{ | ||||
ImGui_ImplOSX_HandleEvent(event, g_KeyEventResponder); | ||||
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; | return true; | |||
} | } | |||
void ImGui_ImplOSX_Shutdown() | void ImGui_ImplOSX_Shutdown() | |||
{ | { | |||
g_FocusObserver = NULL; | g_FocusObserver = NULL; | |||
} | } | |||
static void ImGui_ImplOSX_UpdateMouseCursorAndButtons() | static void ImGui_ImplOSX_UpdateMouseCursor() | |||
{ | { | |||
// Update buttons | ||||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) | ||||
{ | ||||
// If a mouse press event came, always pass it as "mouse held this frame | ||||
", so we don't miss click-release events that are shorter than 1 frame. | ||||
io.MouseDown[i] = g_MouseJustPressed[i] || g_MouseDown[i]; | ||||
g_MouseJustPressed[i] = false; | ||||
} | ||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) | if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) | |||
return; | return; | |||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); | ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); | |||
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 (!g_MouseCursorHidden) | |||
{ | { | |||
g_MouseCursorHidden = true; | g_MouseCursorHidden = true; | |||
skipping to change at line 347 | skipping to change at line 493 | |||
[desired set]; | [desired set]; | |||
} | } | |||
if (g_MouseCursorHidden) | if (g_MouseCursorHidden) | |||
{ | { | |||
g_MouseCursorHidden = false; | g_MouseCursorHidden = false; | |||
[NSCursor unhide]; | [NSCursor unhide]; | |||
} | } | |||
} | } | |||
} | } | |||
void ImGui_ImplOSX_UpdateGamepads() | static void ImGui_ImplOSX_UpdateGamepads() | |||
{ | { | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
memset(io.NavInputs, 0, sizeof(io.NavInputs)); | memset(io.NavInputs, 0, sizeof(io.NavInputs)); | |||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) | if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) | |||
return; | return; | |||
GCController* controller; | #if APPLE_HAS_CONTROLLER | |||
if (@available(macOS 11.0, *)) | GCController* controller = GCController.current; | |||
controller = GCController.current; | #else | |||
else | GCController* controller = GCController.controllers.firstObject; | |||
controller = GCController.controllers.firstObject; | #endif | |||
if (controller == nil || controller.extendedGamepad == nil) | if (controller == nil || controller.extendedGamepad == nil) | |||
{ | { | |||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; | |||
return; | return; | |||
} | } | |||
GCExtendedGamepad* gp = controller.extendedGamepad; | GCExtendedGamepad* gp = controller.extendedGamepad; | |||
#define MAP_BUTTON(NAV_NO, NAME) { io.NavInputs[NAV_NO] = gp.NAME.isPressed ? 1. | // Update gamepad inputs | |||
0 : 0.0; } | #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? | |||
MAP_BUTTON(ImGuiNavInput_Activate, buttonA); | 1.0f : V) | |||
MAP_BUTTON(ImGuiNavInput_Cancel, buttonB); | #define MAP_BUTTON(KEY_NO, BUTTON_NAME) { io.AddKeyEvent(KEY_NO, gp.BU | |||
MAP_BUTTON(ImGuiNavInput_Menu, buttonX); | TTON_NAME.isPressed); } | |||
MAP_BUTTON(ImGuiNavInput_Input, buttonY); | #define MAP_ANALOG(KEY_NO, AXIS_NAME, V0, V1) { float vn = (float)(gp.AXIS_N | |||
MAP_BUTTON(ImGuiNavInput_DpadLeft, dpad.left); | AME.value - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(K | |||
MAP_BUTTON(ImGuiNavInput_DpadRight, dpad.right); | EY_NO, vn > 0.1f, vn); } | |||
MAP_BUTTON(ImGuiNavInput_DpadUp, dpad.up); | const float thumb_dead_zone = 0.0f; | |||
MAP_BUTTON(ImGuiNavInput_DpadDown, dpad.down); | ||||
MAP_BUTTON(ImGuiNavInput_FocusPrev, leftShoulder); | #if APPLE_HAS_BUTTON_OPTIONS | |||
MAP_BUTTON(ImGuiNavInput_FocusNext, rightShoulder); | MAP_BUTTON(ImGuiKey_GamepadBack, buttonOptions); | |||
MAP_BUTTON(ImGuiNavInput_TweakSlow, leftTrigger); | #endif | |||
MAP_BUTTON(ImGuiNavInput_TweakFast, rightTrigger); | MAP_BUTTON(ImGuiKey_GamepadFaceDown, buttonA); // Xbox A | |||
#undef MAP_BUTTON | , PS Cross | |||
MAP_BUTTON(ImGuiKey_GamepadFaceRight, buttonB); // Xbox B | ||||
io.NavInputs[ImGuiNavInput_LStickLeft] = gp.leftThumbstick.left.value; | , PS Circle | |||
io.NavInputs[ImGuiNavInput_LStickRight] = gp.leftThumbstick.right.value; | MAP_BUTTON(ImGuiKey_GamepadFaceLeft, buttonX); // Xbox X | |||
io.NavInputs[ImGuiNavInput_LStickUp] = gp.leftThumbstick.up.value; | , PS Square | |||
io.NavInputs[ImGuiNavInput_LStickDown] = gp.leftThumbstick.down.value; | MAP_BUTTON(ImGuiKey_GamepadFaceUp, buttonY); // Xbox Y | |||
, PS Triangle | ||||
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, dpad.left); | ||||
MAP_BUTTON(ImGuiKey_GamepadDpadRight, dpad.right); | ||||
MAP_BUTTON(ImGuiKey_GamepadDpadUp, dpad.up); | ||||
MAP_BUTTON(ImGuiKey_GamepadDpadDown, dpad.down); | ||||
MAP_ANALOG(ImGuiKey_GamepadL1, leftShoulder, 0.0f, 1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadR1, rightShoulder, 0.0f, 1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadL2, leftTrigger, 0.0f, 1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadR2, rightTrigger, 0.0f, 1.0f); | ||||
#if APPLE_HAS_THUMBSTICKS | ||||
MAP_BUTTON(ImGuiKey_GamepadL3, leftThumbstickButton); | ||||
MAP_BUTTON(ImGuiKey_GamepadR3, rightThumbstickButton); | ||||
#endif | ||||
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, leftThumbstick.xAxis, -thumb_de | ||||
ad_zone, -1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadLStickRight, leftThumbstick.xAxis, +thumb_de | ||||
ad_zone, +1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadLStickUp, leftThumbstick.yAxis, +thumb_de | ||||
ad_zone, +1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadLStickDown, leftThumbstick.yAxis, -thumb_de | ||||
ad_zone, -1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, rightThumbstick.xAxis, -thumb_de | ||||
ad_zone, -1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadRStickRight, rightThumbstick.xAxis, +thumb_de | ||||
ad_zone, +1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadRStickUp, rightThumbstick.yAxis, +thumb_de | ||||
ad_zone, +1.0f); | ||||
MAP_ANALOG(ImGuiKey_GamepadRStickDown, rightThumbstick.yAxis, -thumb_de | ||||
ad_zone, -1.0f); | ||||
#undef MAP_BUTTON | ||||
#undef MAP_ANALOG | ||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad; | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; | |||
} | } | |||
static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view) | ||||
{ | ||||
ImGuiIO& io = ImGui::GetIO(); | ||||
if (io.WantTextInput) | ||||
[g_KeyEventResponder updateImePosWithView:view]; | ||||
} | ||||
void ImGui_ImplOSX_NewFrame(NSView* view) | void ImGui_ImplOSX_NewFrame(NSView* view) | |||
{ | { | |||
// Setup display size | // Setup display size | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
if (view) | if (view) | |||
{ | { | |||
const float dpi = (float)[view.window backingScaleFactor]; | const float dpi = (float)[view.window backingScaleFactor]; | |||
io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bound s.size.height); | io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bound s.size.height); | |||
io.DisplayFramebufferScale = ImVec2(dpi, dpi); | io.DisplayFramebufferScale = ImVec2(dpi, dpi); | |||
} | } | |||
skipping to change at line 412 | skipping to change at line 580 | |||
// Setup time step | // Setup time step | |||
if (g_Time == 0.0) | if (g_Time == 0.0) | |||
{ | { | |||
InitHostClockPeriod(); | InitHostClockPeriod(); | |||
g_Time = GetMachAbsoluteTimeInSeconds(); | g_Time = GetMachAbsoluteTimeInSeconds(); | |||
} | } | |||
double current_time = GetMachAbsoluteTimeInSeconds(); | double current_time = GetMachAbsoluteTimeInSeconds(); | |||
io.DeltaTime = (float)(current_time - g_Time); | io.DeltaTime = (float)(current_time - g_Time); | |||
g_Time = current_time; | g_Time = current_time; | |||
ImGui_ImplOSX_UpdateMouseCursorAndButtons(); | ImGui_ImplOSX_UpdateMouseCursor(); | |||
ImGui_ImplOSX_UpdateGamepads(); | ImGui_ImplOSX_UpdateGamepads(); | |||
} | ImGui_ImplOSX_UpdateImePosWithView(view); | |||
NSString* NSStringFromPhase(NSEventPhase phase) | ||||
{ | ||||
static NSString* strings[] = | ||||
{ | ||||
@"none", | ||||
@"began", | ||||
@"stationary", | ||||
@"changed", | ||||
@"ended", | ||||
@"cancelled", | ||||
@"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) | |||
{ | { | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
if (event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRight MouseDown || event.type == NSEventTypeOtherMouseDown) | if (event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRight MouseDown || event.type == NSEventTypeOtherMouseDown) | |||
{ | { | |||
int button = (int)[event buttonNumber]; | int button = (int)[event buttonNumber]; | |||
if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown)) | if (button >= 0 && button < ImGuiMouseButton_COUNT) | |||
g_MouseDown[button] = g_MouseJustPressed[button] = true; | io.AddMouseButtonEvent(button, true); | |||
return io.WantCaptureMouse; | return io.WantCaptureMouse; | |||
} | } | |||
if (event.type == NSEventTypeLeftMouseUp || event.type == NSEventTypeRightMo useUp || event.type == NSEventTypeOtherMouseUp) | if (event.type == NSEventTypeLeftMouseUp || event.type == NSEventTypeRightMo useUp || event.type == NSEventTypeOtherMouseUp) | |||
{ | { | |||
int button = (int)[event buttonNumber]; | int button = (int)[event buttonNumber]; | |||
if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown)) | if (button >= 0 && button < ImGuiMouseButton_COUNT) | |||
g_MouseDown[button] = false; | io.AddMouseButtonEvent(button, false); | |||
return io.WantCaptureMouse; | return io.WantCaptureMouse; | |||
} | } | |||
if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMous eDragged || event.type == NSEventTypeRightMouseDragged || event.type == NSEventT ypeOtherMouseDragged) | if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMous eDragged || event.type == NSEventTypeRightMouseDragged || event.type == NSEventT ypeOtherMouseDragged) | |||
{ | { | |||
NSPoint mousePoint = event.locationInWindow; | NSPoint mousePoint = event.locationInWindow; | |||
mousePoint = [view convertPoint:mousePoint fromView:nil]; | mousePoint = [view convertPoint:mousePoint fromView:nil]; | |||
mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePo int.y); | mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePo int.y); | |||
io.MousePos = ImVec2((float)mousePoint.x, (float)mousePoint.y); | io.AddMousePosEvent((float)mousePoint.x, (float)mousePoint.y); | |||
} | } | |||
if (event.type == NSEventTypeScrollWheel) | if (event.type == NSEventTypeScrollWheel) | |||
{ | { | |||
// Ignore canceled events. | // Ignore canceled events. | |||
// | // | |||
// From macOS 12.1, scrolling with two fingers and then decelerating | // From macOS 12.1, scrolling with two fingers and then decelerating | |||
// by tapping two fingers results in two events appearing: | // by tapping two fingers results in two events appearing: | |||
// | // | |||
// 1. A scroll wheel NSEvent, with a phase == NSEventPhaseMayBegin, when the user taps | // 1. A scroll wheel NSEvent, with a phase == NSEventPhaseMayBegin, when the user taps | |||
skipping to change at line 499 | skipping to change at line 650 | |||
wheel_dx *= 0.1; | wheel_dx *= 0.1; | |||
wheel_dy *= 0.1; | wheel_dy *= 0.1; | |||
} | } | |||
} | } | |||
else | else | |||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED | #endif // MAC_OS_X_VERSION_MAX_ALLOWED | |||
{ | { | |||
wheel_dx = [event deltaX]; | wheel_dx = [event deltaX]; | |||
wheel_dy = [event deltaY]; | wheel_dy = [event deltaY]; | |||
} | } | |||
if (wheel_dx != 0.0 || wheel_dx != 0.0) | ||||
io.AddMouseWheelEvent((float)wheel_dx * 0.1f, (float)wheel_dy * 0.1f | ||||
); | ||||
//NSLog(@"dx=%0.3ff, dy=%0.3f, phase=%@", wheel_dx, wheel_dy, NSStringFr | ||||
omPhase(event.phase)); | ||||
if (fabs(wheel_dx) > 0.0) | ||||
io.MouseWheelH += (float)wheel_dx * 0.1f; | ||||
if (fabs(wheel_dy) > 0.0) | ||||
io.MouseWheel += (float)wheel_dy * 0.1f; | ||||
return io.WantCaptureMouse; | return io.WantCaptureMouse; | |||
} | } | |||
if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp) | if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp) | |||
{ | { | |||
unsigned short code = event.keyCode; | if ([event isARepeat]) | |||
IM_ASSERT(code >= 0 && code < IM_ARRAYSIZE(io.KeysDown)); | return io.WantCaptureKeyboard; | |||
io.KeysDown[code] = event.type == NSEventTypeKeyDown; | ||||
NSEventModifierFlags flags = event.modifierFlags; | int key_code = (int)[event keyCode]; | |||
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0; | ImGuiKey key = ImGui_ImplOSX_KeyCodeToImGuiKey(key_code); | |||
io.KeyShift = (flags & NSEventModifierFlagShift) != 0; | io.AddKeyEvent(key, event.type == NSEventTypeKeyDown); | |||
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0; | io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexi | |||
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0; | ng (<1.87 user code) | |||
return io.WantCaptureKeyboard; | return io.WantCaptureKeyboard; | |||
} | } | |||
if (event.type == NSEventTypeFlagsChanged) | if (event.type == NSEventTypeFlagsChanged) | |||
{ | { | |||
NSEventModifierFlags flags = event.modifierFlags; | unsigned short key_code = [event keyCode]; | |||
switch (event.keyCode) | NSEventModifierFlags modifier_flags = [event modifierFlags]; | |||
io.AddKeyEvent(ImGuiKey_ModShift, (modifier_flags & NSEventModifierFlagS | ||||
hift) != 0); | ||||
io.AddKeyEvent(ImGuiKey_ModCtrl, (modifier_flags & NSEventModifierFlagC | ||||
ontrol) != 0); | ||||
io.AddKeyEvent(ImGuiKey_ModAlt, (modifier_flags & NSEventModifierFlagO | ||||
ption) != 0); | ||||
io.AddKeyEvent(ImGuiKey_ModSuper, (modifier_flags & NSEventModifierFlagC | ||||
ommand) != 0); | ||||
ImGuiKey key = ImGui_ImplOSX_KeyCodeToImGuiKey(key_code); | ||||
if (key != ImGuiKey_None) | ||||
{ | { | |||
case kVK_Control: | // macOS does not generate down/up event for modifiers. We're trying | |||
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0; | // to use hardware dependent masks to extract that information. | |||
break; | // 'imgui_mask' is left as a fallback. | |||
case kVK_Shift: | NSEventModifierFlags mask = 0; | |||
io.KeyShift = (flags & NSEventModifierFlagShift) != 0; | switch (key) | |||
break; | { | |||
case kVK_Option: | case ImGuiKey_LeftCtrl: mask = 0x0001; break; | |||
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0; | case ImGuiKey_RightCtrl: mask = 0x2000; break; | |||
break; | case ImGuiKey_LeftShift: mask = 0x0002; break; | |||
case kVK_Command: | case ImGuiKey_RightShift: mask = 0x0004; break; | |||
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0; | case ImGuiKey_LeftSuper: mask = 0x0008; break; | |||
break; | case ImGuiKey_RightSuper: mask = 0x0010; break; | |||
case ImGuiKey_LeftAlt: mask = 0x0020; break; | ||||
case ImGuiKey_RightAlt: mask = 0x0040; break; | ||||
default: | ||||
return io.WantCaptureKeyboard; | ||||
} | ||||
NSEventModifierFlags modifier_flags = [event modifierFlags]; | ||||
io.AddKeyEvent(key, (modifier_flags & mask) != 0); | ||||
io.SetKeyEventNativeData(key, key_code, -1); // To support legacy in | ||||
dexing (<1.87 user code) | ||||
} | } | |||
return io.WantCaptureKeyboard; | return io.WantCaptureKeyboard; | |||
} | } | |||
return false; | return false; | |||
} | } | |||
End of changes. 34 change blocks. | ||||
134 lines changed or deleted | 333 lines changed or added |