mirror of
https://github.com/Drezil/imgui.git
synced 2025-03-31 08:22:44 +00: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:
parent
f71ee5203e
commit
1b6b8602c1
@ -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; }
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user