ui/cocoa: add option to swap Option and Command

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>
Message-Id: <20220306121119.45631-3-akihiko.odaki@gmail.com>
Reviewed-by: Will Cohen <wwcohen@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
Gustavo Noronha Silva 2022-03-06 21:11:19 +09:00 committed by Philippe Mathieu-Daudé
parent f844cdb997
commit 4797adce5f
3 changed files with 46 additions and 12 deletions

View File

@ -1275,12 +1275,17 @@
# a global grab on key events. (default: off)
# See https://support.apple.com/en-in/guide/mac-help/mh32356/mac
#
# @swap-opt-cmd: 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: 7.0
##
{ 'struct': 'DisplayCocoa',
'data': {
'*left-command-key': 'bool',
'*full-grab': 'bool'
'*full-grab': 'bool',
'*swap-opt-cmd': 'bool'
} }
##

View File

@ -1917,7 +1917,7 @@ 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][,swap-opt-cmd=on|off]\n"
#endif
#if defined(CONFIG_OPENGL)
"-display egl-headless[,rendernode=<file>]\n"

View File

@ -96,6 +96,7 @@ static DisplayChangeListener dcl = {
static int last_buttons;
static int cursor_hide = 1;
static int left_command_key_enabled = 1;
static bool swap_opt_cmd;
static int gArgc;
static char **gArgv;
@ -854,12 +855,22 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
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 (swap_opt_cmd) {
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 (swap_opt_cmd) {
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]) {
@ -891,29 +902,44 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
case kVK_Option:
if (!!(modifiers & NSEventModifierFlagOption)) {
[self toggleKey:Q_KEY_CODE_ALT];
if (swap_opt_cmd) {
[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 (swap_opt_cmd) {
[self toggleKey:Q_KEY_CODE_META_R];
} else {
[self toggleKey:Q_KEY_CODE_ALT_R];
}
}
break;
/* Don't pass command key changes to guest unless mouse is grabbed */
case kVK_Command:
if (isMouseGrabbed &&
!!(modifiers & NSEventModifierFlagCommand) &&
left_command_key_enabled) {
[self toggleKey:Q_KEY_CODE_META_L];
!!(modifiers & NSEventModifierFlagCommand)) {
if (swap_opt_cmd) {
[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 (swap_opt_cmd) {
[self toggleKey:Q_KEY_CODE_ALT_R];
} else {
[self toggleKey:Q_KEY_CODE_META_R];
}
}
break;
}
@ -2068,6 +2094,9 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
if (opts->has_show_cursor && opts->show_cursor) {
cursor_hide = 0;
}
if (opts->u.cocoa.has_swap_opt_cmd) {
swap_opt_cmd = opts->u.cocoa.swap_opt_cmd;
}
if (opts->u.cocoa.has_left_command_key && !opts->u.cocoa.left_command_key) {
left_command_key_enabled = 0;