Message ID | 20220306111114.18285-3-akihiko.odaki@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | cocoa: keyboard quality of life | expand |
On Sun, 6 Mar 2022, Akihiko Odaki wrote: > From: Gustavo Noronha Silva <gustavo@noronha.dev.br> > > On Mac OS X the Option key maps to Alt and Command to Super/Meta. This change > swaps them around so that Alt is the key closer to the space bar and Meta/Super > is between Control and Alt, like on non-Mac keyboards. > > It is a cocoa display option, disabled by default. > > Acked-by: Markus Armbruster <armbru@redhat.com> > Signed-off-by: Gustavo Noronha Silva <gustavo@noronha.dev.br> > Message-Id: <20210713213200.2547-3-gustavo@noronha.dev.br> > Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com> > --- > qapi/ui.json | 8 ++++++- > qemu-options.hx | 3 ++- > ui/cocoa.m | 64 ++++++++++++++++++++++++++++++++++++++++++------- > 3 files changed, 65 insertions(+), 10 deletions(-) > > diff --git a/qapi/ui.json b/qapi/ui.json > index 1e9893419fe..b082e1a7dee 100644 > --- a/qapi/ui.json > +++ b/qapi/ui.json > @@ -1270,10 +1270,16 @@ > # a global grab on key events. (default: off) > # See https://support.apple.com/en-in/guide/mac-help/mh32356/mac > # > +# @swap-option-command: Swap the Option and Command keys so that their key > +# codes match their position on non-Mac keyboards and > +# you can use Meta/Super and Alt where you expect them. > +# (default: off) > +# > # Since: 6.1 > ## > { 'struct' : 'DisplayCocoa', > - 'data' : { '*full-grab' : 'bool' } } > + 'data' : { '*full-grab' : 'bool', > + '*swap-option-command' : 'bool' } } This option name is too long to type. Could we abbreviate it somehow? Like swap-opt-cmd or swap-alt-meta? Regards, BALATON Zoltan > ## > # @DisplayType: > diff --git a/qemu-options.hx b/qemu-options.hx > index 4df9ccc3446..8431445e9c0 100644 > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -1917,7 +1917,8 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, > "-display curses[,charset=<encoding>]\n" > #endif > #if defined(CONFIG_COCOA) > - "-display cocoa[,full_grab=on|off]\n" > + "-display cocoa[,full-grab=on|off]\n" > + " [,swap-option-command=on|off]\n" > #endif > #if defined(CONFIG_OPENGL) > "-display egl-headless[,rendernode=<file>]\n" > diff --git a/ui/cocoa.m b/ui/cocoa.m > index c41bc615d33..b152d3a1563 100644 > --- a/ui/cocoa.m > +++ b/ui/cocoa.m > @@ -73,6 +73,7 @@ > typedef struct { > int width; > int height; > + bool swap_option_command; > } QEMUScreen; > > static void cocoa_update(DisplayChangeListener *dcl, > @@ -329,6 +330,7 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled; > */ > - (BOOL) isMouseGrabbed; > - (BOOL) isAbsoluteEnabled; > +- (BOOL) isSwapOptionCommandEnabled; > - (float) cdx; > - (float) cdy; > - (QEMUScreen) gscreen; > @@ -704,6 +706,13 @@ - (void) setFullGrab:(id)sender > CFRelease(tapEventsSrc); > } > > +- (void) setSwapOptionCommand:(id)sender > +{ > + COCOA_DEBUG("QemuCocoaView: setSwapOptionCommand\n"); > + > + screen.swap_option_command = true; > +} > + > - (void) toggleKey: (int)keycode { > qkbd_state_key_event(kbd, keycode, !qkbd_state_key_get(kbd, keycode)); > } > @@ -853,12 +862,22 @@ - (bool) handleEventLocked:(NSEvent *)event > qkbd_state_key_event(kbd, Q_KEY_CODE_CTRL_R, false); > } > if (!(modifiers & NSEventModifierFlagOption)) { > - qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); > - qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); > + if ([self isSwapOptionCommandEnabled]) { > + qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); > + qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); > + } else { > + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); > + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); > + } > } > if (!(modifiers & NSEventModifierFlagCommand)) { > - qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); > - qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); > + if ([self isSwapOptionCommandEnabled]) { > + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); > + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); > + } else { > + qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); > + qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); > + } > } > > switch ([event type]) { > @@ -890,13 +909,21 @@ - (bool) handleEventLocked:(NSEvent *)event > > case kVK_Option: > if (!!(modifiers & NSEventModifierFlagOption)) { > - [self toggleKey:Q_KEY_CODE_ALT]; > + if ([self isSwapOptionCommandEnabled]) { > + [self toggleKey:Q_KEY_CODE_META_L]; > + } else { > + [self toggleKey:Q_KEY_CODE_ALT]; > + } > } > break; > > case kVK_RightOption: > if (!!(modifiers & NSEventModifierFlagOption)) { > - [self toggleKey:Q_KEY_CODE_ALT_R]; > + if ([self isSwapOptionCommandEnabled]) { > + [self toggleKey:Q_KEY_CODE_META_R]; > + } else { > + [self toggleKey:Q_KEY_CODE_ALT_R]; > + } > } > break; > > @@ -904,14 +931,22 @@ - (bool) handleEventLocked:(NSEvent *)event > case kVK_Command: > if (isMouseGrabbed && > !!(modifiers & NSEventModifierFlagCommand)) { > - [self toggleKey:Q_KEY_CODE_META_L]; > + if ([self isSwapOptionCommandEnabled]) { > + [self toggleKey:Q_KEY_CODE_ALT]; > + } else { > + [self toggleKey:Q_KEY_CODE_META_L]; > + } > } > break; > > case kVK_RightCommand: > if (isMouseGrabbed && > !!(modifiers & NSEventModifierFlagCommand)) { > - [self toggleKey:Q_KEY_CODE_META_R]; > + if ([self isSwapOptionCommandEnabled]) { > + [self toggleKey:Q_KEY_CODE_ALT_R]; > + } else { > + [self toggleKey:Q_KEY_CODE_META_R]; > + } > } > break; > } > @@ -1146,6 +1181,7 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled { > } > - (BOOL) isMouseGrabbed {return isMouseGrabbed;} > - (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;} > +- (BOOL) isSwapOptionCommandEnabled {return screen.swap_option_command;} > - (float) cdx {return cdx;} > - (float) cdy {return cdy;} > - (QEMUScreen) gscreen {return screen;} > @@ -1338,6 +1374,13 @@ - (void) setFullGrab:(id)sender > [cocoaView setFullGrab:sender]; > } > > +- (void) setSwapOptionCommand:(id)sender > +{ > + COCOA_DEBUG("QemuCocoaAppController: setSwapOptionCommand\n"); > + > + [cocoaView setSwapOptionCommand:sender]; > +} > + > /* Tries to find then open the specified filename */ > - (void) openDocumentation: (NSString *) filename > { > @@ -2127,6 +2170,11 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) > [controller setFullGrab: nil]; > }); > } > + if (opts->u.cocoa.has_swap_option_command && opts->u.cocoa.swap_option_command) { > + dispatch_async(dispatch_get_main_queue(), ^{ > + [controller setSwapOptionCommand: nil]; > + }); > + } > if (opts->has_show_cursor && opts->show_cursor) { > cursor_hide = 0; > } >
BALATON Zoltan <balaton@eik.bme.hu> writes: > On Sun, 6 Mar 2022, Akihiko Odaki wrote: >> From: Gustavo Noronha Silva <gustavo@noronha.dev.br> >> >> On Mac OS X the Option key maps to Alt and Command to Super/Meta. This change >> swaps them around so that Alt is the key closer to the space bar and Meta/Super >> is between Control and Alt, like on non-Mac keyboards. >> >> It is a cocoa display option, disabled by default. >> >> Acked-by: Markus Armbruster <armbru@redhat.com> >> Signed-off-by: Gustavo Noronha Silva <gustavo@noronha.dev.br> >> Message-Id: <20210713213200.2547-3-gustavo@noronha.dev.br> >> Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com> >> --- >> qapi/ui.json | 8 ++++++- >> qemu-options.hx | 3 ++- >> ui/cocoa.m | 64 ++++++++++++++++++++++++++++++++++++++++++------- >> 3 files changed, 65 insertions(+), 10 deletions(-) >> >> diff --git a/qapi/ui.json b/qapi/ui.json >> index 1e9893419fe..b082e1a7dee 100644 >> --- a/qapi/ui.json >> +++ b/qapi/ui.json >> @@ -1270,10 +1270,16 @@ >> # a global grab on key events. (default: off) >> # See https://support.apple.com/en-in/guide/mac-help/mh32356/mac >> # >> +# @swap-option-command: Swap the Option and Command keys so that their key >> +# codes match their position on non-Mac keyboards and >> +# you can use Meta/Super and Alt where you expect them. >> +# (default: off) >> +# >> # Since: 6.1 >> ## >> { 'struct' : 'DisplayCocoa', >> - 'data' : { '*full-grab' : 'bool' } } >> + 'data' : { '*full-grab' : 'bool', >> + '*swap-option-command' : 'bool' } } > > This option name is too long to type. Could we abbreviate it somehow? We've largely avoided abbreviations in the QAPI schema, for better or worse. > Like swap-opt-cmd or swap-alt-meta? We should stick to how the keys are generally called on this platform. I can't say (I'm not using it).
On 2022/03/07 16:17, Markus Armbruster wrote: > BALATON Zoltan <balaton@eik.bme.hu> writes: > >> On Sun, 6 Mar 2022, Akihiko Odaki wrote: >>> From: Gustavo Noronha Silva <gustavo@noronha.dev.br> >>> >>> On Mac OS X the Option key maps to Alt and Command to Super/Meta. This change >>> swaps them around so that Alt is the key closer to the space bar and Meta/Super >>> is between Control and Alt, like on non-Mac keyboards. >>> >>> It is a cocoa display option, disabled by default. >>> >>> Acked-by: Markus Armbruster <armbru@redhat.com> >>> Signed-off-by: Gustavo Noronha Silva <gustavo@noronha.dev.br> >>> Message-Id: <20210713213200.2547-3-gustavo@noronha.dev.br> >>> Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com> >>> --- >>> qapi/ui.json | 8 ++++++- >>> qemu-options.hx | 3 ++- >>> ui/cocoa.m | 64 ++++++++++++++++++++++++++++++++++++++++++------- >>> 3 files changed, 65 insertions(+), 10 deletions(-) >>> >>> diff --git a/qapi/ui.json b/qapi/ui.json >>> index 1e9893419fe..b082e1a7dee 100644 >>> --- a/qapi/ui.json >>> +++ b/qapi/ui.json >>> @@ -1270,10 +1270,16 @@ >>> # a global grab on key events. (default: off) >>> # See https://support.apple.com/en-in/guide/mac-help/mh32356/mac >>> # >>> +# @swap-option-command: Swap the Option and Command keys so that their key >>> +# codes match their position on non-Mac keyboards and >>> +# you can use Meta/Super and Alt where you expect them. >>> +# (default: off) >>> +# >>> # Since: 6.1 >>> ## >>> { 'struct' : 'DisplayCocoa', >>> - 'data' : { '*full-grab' : 'bool' } } >>> + 'data' : { '*full-grab' : 'bool', >>> + '*swap-option-command' : 'bool' } } >> >> This option name is too long to type. Could we abbreviate it somehow? > > We've largely avoided abbreviations in the QAPI schema, for better or > worse. > >> Like swap-opt-cmd or swap-alt-meta? > > We should stick to how the keys are generally called on this platform. > I can't say (I'm not using it). > The patch series is now in: https://patchew.org/QEMU/20220306231753.50277-1-philippe.mathieu.daude@gmail.com/ It uses swap-opt-cmd for the name. Please reply to the series if it is problematic. Regards, Akihiko Odaki
On Mon, 7 Mar 2022, Akihiko Odaki wrote: > On 2022/03/07 16:17, Markus Armbruster wrote: >> BALATON Zoltan <balaton@eik.bme.hu> writes: >> >>> On Sun, 6 Mar 2022, Akihiko Odaki wrote: >>>> From: Gustavo Noronha Silva <gustavo@noronha.dev.br> >>>> >>>> On Mac OS X the Option key maps to Alt and Command to Super/Meta. This >>>> change >>>> swaps them around so that Alt is the key closer to the space bar and >>>> Meta/Super >>>> is between Control and Alt, like on non-Mac keyboards. >>>> >>>> It is a cocoa display option, disabled by default. >>>> >>>> Acked-by: Markus Armbruster <armbru@redhat.com> >>>> Signed-off-by: Gustavo Noronha Silva <gustavo@noronha.dev.br> >>>> Message-Id: <20210713213200.2547-3-gustavo@noronha.dev.br> >>>> Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com> >>>> --- >>>> qapi/ui.json | 8 ++++++- >>>> qemu-options.hx | 3 ++- >>>> ui/cocoa.m | 64 ++++++++++++++++++++++++++++++++++++++++++------- >>>> 3 files changed, 65 insertions(+), 10 deletions(-) >>>> >>>> diff --git a/qapi/ui.json b/qapi/ui.json >>>> index 1e9893419fe..b082e1a7dee 100644 >>>> --- a/qapi/ui.json >>>> +++ b/qapi/ui.json >>>> @@ -1270,10 +1270,16 @@ >>>> # a global grab on key events. (default: off) >>>> # See >>>> https://support.apple.com/en-in/guide/mac-help/mh32356/mac >>>> # >>>> +# @swap-option-command: Swap the Option and Command keys so that their >>>> key >>>> +# codes match their position on non-Mac keyboards >>>> and >>>> +# you can use Meta/Super and Alt where you expect >>>> them. >>>> +# (default: off) >>>> +# >>>> # Since: 6.1 >>>> ## >>>> { 'struct' : 'DisplayCocoa', >>>> - 'data' : { '*full-grab' : 'bool' } } >>>> + 'data' : { '*full-grab' : 'bool', >>>> + '*swap-option-command' : 'bool' } } >>> >>> This option name is too long to type. Could we abbreviate it somehow? >> >> We've largely avoided abbreviations in the QAPI schema, for better or >> worse. There are already some abreviated options in this file and since users will need to use it to switch this on it's better to have something that can be typed without too much hassle and result in a command that still fits in a window... >>> Like swap-opt-cmd or swap-alt-meta? >> >> We should stick to how the keys are generally called on this platform. >> I can't say (I'm not using it). >> > > The patch series is now in: > https://patchew.org/QEMU/20220306231753.50277-1-philippe.mathieu.daude@gmail.com/ > > It uses swap-opt-cmd for the name. Please reply to the series if it is > problematic. The more common name for these keys on macOS is option and command although the opt key sometimes also has alt written on it and the code seems to use meta instead of command but I think swap-opt-cmd is simple and clear so unless it's mandatory to have very long options that's not practical for users I'd go with swap-opt-cmd (which is what's in the last patch from Philippe so it should be OK). Regards, BALATON Zoltan
diff --git a/qapi/ui.json b/qapi/ui.json index 1e9893419fe..b082e1a7dee 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1270,10 +1270,16 @@ # a global grab on key events. (default: off) # See https://support.apple.com/en-in/guide/mac-help/mh32356/mac # +# @swap-option-command: Swap the Option and Command keys so that their key +# codes match their position on non-Mac keyboards and +# you can use Meta/Super and Alt where you expect them. +# (default: off) +# # Since: 6.1 ## { 'struct' : 'DisplayCocoa', - 'data' : { '*full-grab' : 'bool' } } + 'data' : { '*full-grab' : 'bool', + '*swap-option-command' : 'bool' } } ## # @DisplayType: diff --git a/qemu-options.hx b/qemu-options.hx index 4df9ccc3446..8431445e9c0 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1917,7 +1917,8 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, "-display curses[,charset=<encoding>]\n" #endif #if defined(CONFIG_COCOA) - "-display cocoa[,full_grab=on|off]\n" + "-display cocoa[,full-grab=on|off]\n" + " [,swap-option-command=on|off]\n" #endif #if defined(CONFIG_OPENGL) "-display egl-headless[,rendernode=<file>]\n" diff --git a/ui/cocoa.m b/ui/cocoa.m index c41bc615d33..b152d3a1563 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -73,6 +73,7 @@ typedef struct { int width; int height; + bool swap_option_command; } QEMUScreen; static void cocoa_update(DisplayChangeListener *dcl, @@ -329,6 +330,7 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled; */ - (BOOL) isMouseGrabbed; - (BOOL) isAbsoluteEnabled; +- (BOOL) isSwapOptionCommandEnabled; - (float) cdx; - (float) cdy; - (QEMUScreen) gscreen; @@ -704,6 +706,13 @@ - (void) setFullGrab:(id)sender CFRelease(tapEventsSrc); } +- (void) setSwapOptionCommand:(id)sender +{ + COCOA_DEBUG("QemuCocoaView: setSwapOptionCommand\n"); + + screen.swap_option_command = true; +} + - (void) toggleKey: (int)keycode { qkbd_state_key_event(kbd, keycode, !qkbd_state_key_get(kbd, keycode)); } @@ -853,12 +862,22 @@ - (bool) handleEventLocked:(NSEvent *)event qkbd_state_key_event(kbd, Q_KEY_CODE_CTRL_R, false); } if (!(modifiers & NSEventModifierFlagOption)) { - qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); - qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); + if ([self isSwapOptionCommandEnabled]) { + qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); + } else { + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); + } } if (!(modifiers & NSEventModifierFlagCommand)) { - qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); - qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); + if ([self isSwapOptionCommandEnabled]) { + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); + } else { + qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); + } } switch ([event type]) { @@ -890,13 +909,21 @@ - (bool) handleEventLocked:(NSEvent *)event case kVK_Option: if (!!(modifiers & NSEventModifierFlagOption)) { - [self toggleKey:Q_KEY_CODE_ALT]; + if ([self isSwapOptionCommandEnabled]) { + [self toggleKey:Q_KEY_CODE_META_L]; + } else { + [self toggleKey:Q_KEY_CODE_ALT]; + } } break; case kVK_RightOption: if (!!(modifiers & NSEventModifierFlagOption)) { - [self toggleKey:Q_KEY_CODE_ALT_R]; + if ([self isSwapOptionCommandEnabled]) { + [self toggleKey:Q_KEY_CODE_META_R]; + } else { + [self toggleKey:Q_KEY_CODE_ALT_R]; + } } break; @@ -904,14 +931,22 @@ - (bool) handleEventLocked:(NSEvent *)event case kVK_Command: if (isMouseGrabbed && !!(modifiers & NSEventModifierFlagCommand)) { - [self toggleKey:Q_KEY_CODE_META_L]; + if ([self isSwapOptionCommandEnabled]) { + [self toggleKey:Q_KEY_CODE_ALT]; + } else { + [self toggleKey:Q_KEY_CODE_META_L]; + } } break; case kVK_RightCommand: if (isMouseGrabbed && !!(modifiers & NSEventModifierFlagCommand)) { - [self toggleKey:Q_KEY_CODE_META_R]; + if ([self isSwapOptionCommandEnabled]) { + [self toggleKey:Q_KEY_CODE_ALT_R]; + } else { + [self toggleKey:Q_KEY_CODE_META_R]; + } } break; } @@ -1146,6 +1181,7 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled { } - (BOOL) isMouseGrabbed {return isMouseGrabbed;} - (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;} +- (BOOL) isSwapOptionCommandEnabled {return screen.swap_option_command;} - (float) cdx {return cdx;} - (float) cdy {return cdy;} - (QEMUScreen) gscreen {return screen;} @@ -1338,6 +1374,13 @@ - (void) setFullGrab:(id)sender [cocoaView setFullGrab:sender]; } +- (void) setSwapOptionCommand:(id)sender +{ + COCOA_DEBUG("QemuCocoaAppController: setSwapOptionCommand\n"); + + [cocoaView setSwapOptionCommand:sender]; +} + /* Tries to find then open the specified filename */ - (void) openDocumentation: (NSString *) filename { @@ -2127,6 +2170,11 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) [controller setFullGrab: nil]; }); } + if (opts->u.cocoa.has_swap_option_command && opts->u.cocoa.swap_option_command) { + dispatch_async(dispatch_get_main_queue(), ^{ + [controller setSwapOptionCommand: nil]; + }); + } if (opts->has_show_cursor && opts->show_cursor) { cursor_hide = 0; }