diff --git a/vstgui/lib/events.h b/vstgui/lib/events.h index 69ef4d39f..88956e10e 100644 --- a/vstgui/lib/events.h +++ b/vstgui/lib/events.h @@ -479,6 +479,9 @@ enum class VirtualKey : uint32_t Equals, // DO NOT CHANGE THE ORDER ABOVE + SuperModifier, // The Control key on macOS + CapsLockModifier, + FunctionModifier, // The Function (fn) key on macOS }; //------------------------------------------------------------------------ @@ -497,6 +500,15 @@ enum class ModifierKey : uint32_t platforms)*/ Super = 1 << 3, + /** (macOS only) The Caps Lock key */ + CapsLock = 1 << 4, + /** (macOS only) A key in the numeric keypad or an arrow key */ + NumPad = 1 << 5, + /** (macOS only) The Help key */ + Help = 1 << 6, + /** (macOS only) The function key */ + Fn = 1 << 7, + None = 0 }; diff --git a/vstgui/lib/platform/mac/cocoa/cocoahelpers.h b/vstgui/lib/platform/mac/cocoa/cocoahelpers.h index 48880ff7e..27c901052 100644 --- a/vstgui/lib/platform/mac/cocoa/cocoahelpers.h +++ b/vstgui/lib/platform/mac/cocoa/cocoahelpers.h @@ -18,6 +18,7 @@ #define HIDDEN __attribute__((__visibility__("hidden"))) //------------------------------------------------------------------------------------ +extern HIDDEN void SetModifierFlags (NSUInteger modifiers, VSTGUI::KeyboardEvent& event); extern HIDDEN bool CreateKeyboardEventFromNSEvent (NSEvent* theEvent, VSTGUI::KeyboardEvent& event); extern HIDDEN NSString* GetVirtualKeyCodeString (VSTGUI::VirtualKey virtualKey); extern HIDDEN int32_t eventButton (NSEvent* theEvent); @@ -78,12 +79,20 @@ struct MacEventModifier ShiftKeyMask = NSEventModifierFlagShift, CommandKeyMask = NSEventModifierFlagCommand, AlternateKeyMask = NSEventModifierFlagOption, - ControlKeyMask = NSEventModifierFlagControl + ControlKeyMask = NSEventModifierFlagControl, + CapsLockKeyMask = NSEventModifierFlagCapsLock, + NumericPadKeyMask = NSEventModifierFlagNumericPad, + HelpKeyMask = NSEventModifierFlagHelp, + FunctionKeyMask = NSEventModifierFlagFunction #else ShiftKeyMask = NSShiftKeyMask, CommandKeyMask = NSCommandKeyMask, AlternateKeyMask = NSAlternateKeyMask, - ControlKeyMask = NSControlKeyMask + ControlKeyMask = NSControlKeyMask, + CapsLockKeyMask = NSAlphaShiftKeyMask, + NumericPadKeyMask = NSNumericPadKeyMask, + HelpKeyMask = NSHelpKeyMask, + FunctionKeyMask = NSFunctionKeyMask #endif }; }; diff --git a/vstgui/lib/platform/mac/cocoa/cocoahelpers.mm b/vstgui/lib/platform/mac/cocoa/cocoahelpers.mm index 8905a992a..3b3481c22 100644 --- a/vstgui/lib/platform/mac/cocoa/cocoahelpers.mm +++ b/vstgui/lib/platform/mac/cocoa/cocoahelpers.mm @@ -17,18 +17,83 @@ //------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------ +HIDDEN void SetModifierFlags (NSUInteger modifiers, KeyboardEvent& event) +{ + if (modifiers & MacEventModifier::ShiftKeyMask) + event.modifiers.add (ModifierKey::Shift); + if (modifiers & MacEventModifier::CommandKeyMask) + event.modifiers.add (ModifierKey::Control); + if (modifiers & MacEventModifier::AlternateKeyMask) + event.modifiers.add (ModifierKey::Alt); + if (modifiers & MacEventModifier::ControlKeyMask) + event.modifiers.add (ModifierKey::Super); + + if (modifiers & MacEventModifier::CapsLockKeyMask) + event.modifiers.add (ModifierKey::CapsLock); + if (modifiers & MacEventModifier::NumericPadKeyMask) + event.modifiers.add (ModifierKey::NumPad); + if (modifiers & MacEventModifier::HelpKeyMask) + event.modifiers.add (ModifierKey::Help); + if (modifiers & MacEventModifier::FunctionKeyMask) + event.modifiers.add (ModifierKey::Fn); + + if (event.modifiers.is(ModifierKey::Shift)) + event.virt = VirtualKey::ShiftModifier; + if (event.modifiers.is(ModifierKey::Control)) + event.virt = VirtualKey::ControlModifier; + if (event.modifiers.is(ModifierKey::Alt)) + event.virt = VirtualKey::AltModifier; + if (event.modifiers.is(ModifierKey::Super)) + event.virt = VirtualKey::SuperModifier; + + if (event.modifiers.is(ModifierKey::CapsLock)) + event.virt = VirtualKey::CapsLockModifier; + if (event.modifiers.is(ModifierKey::Help)) + event.virt = VirtualKey::Help; + if (event.modifiers.is(ModifierKey::Fn)) + event.virt = VirtualKey::FunctionModifier; +} + HIDDEN bool CreateKeyboardEventFromNSEvent (NSEvent* theEvent, KeyboardEvent& event) { if (theEvent.type == NSEventTypeKeyUp) event.type = EventType::KeyUp; - else if (theEvent.type == NSEventTypeKeyDown || theEvent.type == NSEventTypeFlagsChanged) + else if (theEvent.type == NSEventTypeKeyDown) { event.type = EventType::KeyDown; if (theEvent.ARepeat) event.isRepeat = true; } + else if (theEvent.type == NSEventTypeFlagsChanged) + { + event.type = EventType::KeyDown; + } else return false; + + NSUInteger modifiers = [theEvent modifierFlags]; + SetModifierFlags (modifiers, event); + + if (theEvent.type == NSEventTypeFlagsChanged) + { + static Modifiers lastModifiers; + static VirtualKey lastVirtKey; + + Modifiers currentModifiers = event.modifiers; + VirtualKey currentVirtKey = event.virt; + + // Simulate KeyUp when flags snap back to 0 + if (currentModifiers.empty() && !lastModifiers.empty()) { + event.type = EventType::KeyUp; + event.modifiers = lastModifiers; + event.virt = lastVirtKey; + } + + lastModifiers = currentModifiers; + lastVirtKey = currentVirtKey; + return true; + } + NSString *s = [theEvent charactersIgnoringModifiers]; if ([s length] == 1) { @@ -118,16 +183,6 @@ HIDDEN bool CreateKeyboardEventFromNSEvent (NSEvent* theEvent, KeyboardEvent& ev } } - NSUInteger modifiers = [theEvent modifierFlags]; - if (modifiers & MacEventModifier::ShiftKeyMask) - event.modifiers.add (ModifierKey::Shift); - if (modifiers & MacEventModifier::CommandKeyMask) - event.modifiers.add (ModifierKey::Control); - if (modifiers & MacEventModifier::AlternateKeyMask) - event.modifiers.add (ModifierKey::Alt); - if (modifiers & MacEventModifier::ControlKeyMask) - event.modifiers.add (ModifierKey::Super); - return true; } @@ -194,6 +249,9 @@ HIDDEN bool CreateKeyboardEventFromNSEvent (NSEvent* theEvent, KeyboardEvent& ev case VirtualKey::ShiftModifier: break; case VirtualKey::ControlModifier: break; case VirtualKey::AltModifier: break; + case VirtualKey::SuperModifier: break; + case VirtualKey::CapsLockModifier: break; + case VirtualKey::FunctionModifier: break; case VirtualKey::None: break; } if (character != 0) diff --git a/vstgui/lib/platform/mac/cocoa/cocoaopenglview.mm b/vstgui/lib/platform/mac/cocoa/cocoaopenglview.mm index d19432b30..1b81e3920 100644 --- a/vstgui/lib/platform/mac/cocoa/cocoaopenglview.mm +++ b/vstgui/lib/platform/mac/cocoa/cocoaopenglview.mm @@ -46,10 +46,28 @@ static Class CreateClass () .addMethod (@selector (mouseMoved:), MouseXXX) .addMethod (@selector (rightMouseDown:), MouseXXX) .addMethod (@selector (rightMouseUp:), MouseXXX) + .addMethod (@selector (acceptsFirstResponder), acceptsFirstResponder) + .addMethod (@selector (becomeFirstResponder), becomeFirstResponder) + .addMethod (@selector (resignFirstResponder), resignFirstResponder) .addIvar (cocoaOpenGLViewVarName) .finalize (); } + static BOOL acceptsFirstResponder (id self, SEL _cmd) + { + return YES; + } + + static BOOL becomeFirstResponder (id self, SEL _cmd) + { + return YES; + } + + static BOOL resignFirstResponder (id self, SEL _cmd) + { + return YES; + } + //----------------------------------------------------------------------------- static id Init (id self, SEL _cmd, NSRect frameRect, NSOpenGLPixelFormat* format, CocoaOpenGLView* callback) @@ -306,6 +324,10 @@ static void MouseXXX (id self, SEL _cmd, NSEvent* theEvent) { [parent addSubview:platformView]; } + else + { + [[platformView window] makeFirstResponder:parent]; + } unlockContext (); } } diff --git a/vstgui/lib/platform/mac/cocoa/nsviewframe.mm b/vstgui/lib/platform/mac/cocoa/nsviewframe.mm index f79821af4..e373356a7 100644 --- a/vstgui/lib/platform/mac/cocoa/nsviewframe.mm +++ b/vstgui/lib/platform/mac/cocoa/nsviewframe.mm @@ -216,6 +216,7 @@ static Class CreateClass () .addMethod (@selector (performKeyEquivalent:), performKeyEquivalent) .addMethod (@selector (keyDown:), keyDown) .addMethod (@selector (keyUp:), keyUp) + .addMethod (@selector (flagsChanged:), flagsChanged) .addMethod (@selector (magnifyWithEvent:), magnifyWithEvent) .addMethod (@selector (focusRingType), focusRingType) .addMethod (@selector (draggingEntered:), draggingEntered) @@ -683,6 +684,24 @@ static void keyUp (id self, SEL _cmd, NSEvent* theEvent) [[self nextResponder] keyUp:theEvent]; } + //------------------------------------------------------------------------------------ + static void flagsChanged (id self, SEL _cmd, NSEvent* theEvent) + { + IPlatformFrameCallback* _vstguiframe = getFrame (self); + if (!_vstguiframe) + return; + + KeyboardEvent keyEvent; + keyEvent.timestamp = static_cast (theEvent.timestamp * 1000.); + if (CreateKeyboardEventFromNSEvent (theEvent, keyEvent)) + { + _vstguiframe->platformOnEvent (keyEvent); + if (keyEvent.consumed) + return; + } + [[self nextResponder] flagsChanged:theEvent]; + } + //------------------------------------------------------------------------------------ static void magnifyWithEvent (id self, SEL _cmd, NSEvent* theEvent) {