GNOME Bugzilla – Bug 605799
Option (MOD1) and Command (SUPER) modifiers are switched
Last modified: 2011-09-27 12:00:48 UTC
Created attachment 150604 [details] [review] Switch Alt/Command mapping It seems in mapping the modifier codes, Option/Alt and Command/Windows/Super are switched. Patch provided.
moving to right component
the switch to MOD1 for Alt looks right to me. I prefer to use META for Command, but in truth, its a toss up between the two.
Well, I proposed SUPER because the windows key which I associate with the command key is usually mapped to SUPER. That said, if you look at the actual layout of the keyboard, probably mapping ALT to command seems right (but for me it's unintuitive). I'm not an expert here.
Given that OS X documentation alternately refers to Alt and Option as the same key (i.e. "Alt" is a legitimate apple name for this key), it seems unwise to me to make a key that is *labelled* "Alt" do something other than "Alt", even though its true that from a keyboard layout perspective that might make sense. Notice that if you plug a non-Apple keyboard into OS X, the Alt key functions as "Alt" and the Start/Windows key functions as Command, out of the box - I believe that GTK should be emulating that. The only real question is what GTK modifier to use to indicate Command. I have a small preference for Meta, but I don't think that any particular choice is defensible.
I am no expert on this either and this is a hard problem. Currently, command is bound to MOD1 and activates mnemonics and accelerators (acts like ALT on Linux). The patch proposes to bind Alt/Option to MOD1 and bind Super (or something else) to command. In [1] it is stated that Command is the first modifier key on Mac platforms (I guess just like MOD1). It is used when activating menu items. This is consistent with what Quartz GTK+ does currently. In the Java implementation on Mac the "ALT_MASK modifier" is the option key. This is probably where the confusion starts, because binding ALT_MASK to the option key makes sense, but it conflicts because ALT is used on Linux for activating menu items etc. I have asked Richard about why command was bound to activate menu items originally and not alt. He told me that the other way didn't work because of things that are hardcoded in GTK+ here and there. He suggested that the best way to fix this requiress some work first to make GTK+ itself more generic when it comes to modifiers. From what I remember a bug is already open on making GTK+ more generic for this, but can't recall the number so quickly. [1] http://developer.apple.com/mac/library/documentation/Java/Conceptual/Java14Development/07-NativePlatformIntegration/NativePlatformIntegration.html
Command is not like Alt/Mod1. Command on OS X is like Control in the sense that its the most common modifier used to create shortcuts. The default modifier for all menu items is Command - in fact, if you use Carbon you must explicitly turn it off if the modified does not include Command because its there by default. In addition, all recent Macs (for about 8 years at least) have had a key labelled Alt/Option, and it seems wise to make this key generate the same modifier (Mod1) that it would do under X11 and Windows. The bug you are looking for is: https://bugzilla.gnome.org/show_bug.cgi?id=601863
Kristian - put another way .... on OS X there is no distinction between shortcuts and activating menu items (an unfortunate complication that GTK has introduced). As a result its rather typical to find an X11 GTK app using Ctrl-x/Ctrl-v/Ctrl-c and many other Ctrl-<foo> shortcuts alongside Alt-<foo> "accelerators" for menus. Under OS X, this really doesn't occur: most OS X apps use Command-<foo> for most shortcuts, and then extend to Alt/Option-<foo> if they need more.
(In reply to comment #6) > Command is not like Alt/Mod1. Command on OS X is like Control in the sense that > its the most common modifier used to create shortcuts. The default modifier for > all menu items is Command - in fact, if you use Carbon you must explicitly turn > it off if the modified does not include Command because its there by default. I wanted to refer to MOD1 thinking it also meant "first modifier", but I guess this is not true. > In addition, all recent Macs (for about 8 years at least) have had a key > labelled Alt/Option, and it seems wise to make this key generate the same > modifier (Mod1) that it would do under X11 and Windows. Yes, I agree with that. So from what I understand, the following is needed: 1) The Alt/Option key should be coupled to the same modifier as X11/Windows (that is, MOD1) 2) Command should be activating menu shortcuts to be consistent with the Mac platform. For 2) we need the bug you refer to resolved. 1) can be fixed anytime of course, but I think we want to have 2) fixed before we change that. > The bug you are looking for is: > https://bugzilla.gnome.org/show_bug.cgi?id=601863 Ah yes, it is. Thanks!
(In reply to comment #7) > Kristian - put another way .... on OS X there is no distinction between > shortcuts and activating menu items (an unfortunate complication that GTK has > introduced). As a result its rather typical to find an X11 GTK app using > Ctrl-x/Ctrl-v/Ctrl-c and many other Ctrl-<foo> shortcuts alongside Alt-<foo> > "accelerators" for menus. Under OS X, this really doesn't occur: most OS X apps > use Command-<foo> for most shortcuts, and then extend to Alt/Option-<foo> if > they need more. Ah, right, the alt accelerators for menus don't exist on Mac platforms, it is just about the shortcuts (that are triggered with ctrl on X as you say). I have been confusing menu mnemonics and shortcuts here ... Another problem with using ALT for mnemonics is that it might mess up the native Mac IM, maybe we want to disable mnemonics on Mac altogether ...
> 2) Command should be activating menu shortcuts to be consistent with the Mac > platform. I don't see things in these terms. I don't think of "Alt activating menu shortcuts". I think of shortcuts (GTK likes to call them accelerators, right?) that use MOD1 as a modifier. You can have shortcuts that use CONTROL as a modifier too, or both, or SHIFT or whatever. This is all true on OS X as well. The only difference is the set of available modifiers: OS X (Cocoa): Command, Alt/Option, Control, Shift, NumericKeyPad, GTK: Control, Shift, NumLock, MOD1 .. MOD5, SUPER, META, HYPER (and of course, alas, the last 3 don't really exist but are actually one of MODn) So the problem is mapping from the GTK set to the Cocoa set. The mapping that I use in Ardour is shown below (this code assumes that the Alt/Option) key is mapped to MOD1 and the Command key is mapped to META): if (key->accel_mods || modifiers) { if (key->accel_mods & GDK_SHIFT_MASK) { modifiers |= NSShiftKeyMask; } if (key->accel_mods & (GDK_MOD1_MASK)) { modifiers |= NSAlternateKeyMask; } if (key->accel_mods & GDK_CONTROL_MASK) { modifiers |= NSControlKeyMask; } if (key->accel_mods & GDK_META_MASK) { modifiers |= NSCommandKeyMask; } }
(In reply to comment #9) > Ah, right, the alt accelerators for menus don't exist on Mac platforms, it is > just about the shortcuts (that are triggered with ctrl on X as you say). I > have been confusing menu mnemonics and shortcuts here ... yes, this is precisely right. personally, i'd be happy if GTK disposed of acclerators entirely :) > Another problem with using ALT for mnemonics is that it might mess up the > native Mac IM, maybe we want to disable mnemonics on Mac altogether ... sounds right to me. its a totally non-native approach to user/menu interaction.
The native Mac IM behaviour and the opt key is totally broken in GTK anyway. Opt is supposed to allow composed chars and shortcuts (accelerators), but currently GTK swallows it up at a very low level, making these things impossible. In MonoDevelop we have a hack to decompose the keys using the keymap and check the group in order to determine if option/alt is pressed, for keybindings. And there is no way at all we can access it from a mouse event. The "correct" way to handle opt for non-composed chars IMO would be gdk_keymap_translate_keyboard_state which would consume the alt modifier. However, the modifier should still be available to those who want it. Or it could be handled by a Mac IM method - which would be needed for the compose behaviour anyway. The Mac key rc is also *completely* broken because of the opt/alt (unbindable) and meta/mod1 (switched) modifier issues. It's full of alt and meta mappings, but none of them work. Well, the alt ones "work" with command key, but that's just wrong. Confusingly, command key by itself results in meta *key* but as a modifier it's mod1 *modifier*. My suggestion to fix this completely would be a) Map Command modifier to Meta b) Disable mnemonics, they aren't Mac-ish and just confuse things c) Map Opt modifier to Alt (Mod1) d) Don't consume the Opt modifier at the lowest level - either don't handle it at all, or handle it in the keymap or IM method.
I'm not sure that I'd agree that the "opt key is totally broken in GTK". The breakage, such as it is, comes from the mismatching model of what Opt-<key> is supposed to do on OS X: its a very different answer than the question of what Alt-<key> does on X11 or Windows systems. From the outset, OS X has always defined a fairly large set of Opt-<key> combinations as being for entering various characters (I wouldn't characterize them as "composed", since thats an artifact of *nix-ish systems, mostly). Along come some apps (Ardour is one of them) that want Opt-<key> for other purposes, and all hell breaks loose. But I agree with your summary of suggestions entirely.
Well, there are 2 usages of the opt key - direct combinations, like you mention, and compose. Try opt-u u (on 10.6, at least). That looks like a compose sequence to me. Probably the best solution is to use both a keymap (for direct combinations) and an IM (both for compose, and more exotic stuff). The Mac gdk keymap already seems to have mapped opt cleanly to the group (which is how in same cases we can unmap it) so it shouldn't be hard to have the keymap consume the modifier properly. I imagine the IM is a lot harder to do correctly, but it can be done later.
Created attachment 166427 [details] [review] Partial patch based on comment 12 Patch is against 2.20 branch.
I like everything about the patch from comment 15 except for the hiding of the Alt/Opt key as Mod5. However, since we patch GTK+ for distribution anyway, that's not a big issue for us, and having the builtin key bindings fixed for OS X would be a huge win anyway.
Actually I had initially made it Mod1 per comment 12, but it gave unexpected results for a lot of printable characters in my testing (curly brackets and others iirc).
Want kind of stuff broke? I imagine you would need to fix comment 12 part (d) before part (c) would work properly.
Just wanted to add my impact to this bug. I've added gtk_osxapplication based menu integration to a pygtk application. The menu accelerators initially used the CONTROL modifier, which I adjust to META when the application is run on a mac. However, there is then some collision between the menu accelerators and gtk stock button accelerators (i.e., CMD-"O" for "Open Form" collides with "OK" in a dialog using stock "gtk-ok", where the modifier for the latter should be Alt, but is Cmd due to this bug)
(In reply to comment #16) > I like everything about the patch from comment 15 except for the hiding of the > Alt/Opt key as Mod5. However, since we patch GTK+ for distribution anyway, > that's not a big issue for us, and having the builtin key bindings fixed for OS > X would be a huge win anyway. It looks to me like this patch blindly replaces all instances of GDK_CONTROL_MASK with the GTK_DEFAULT_ACCEL_MOD_MASK that Yevgen Muntyan introduced in http://git.gnome.org/browse/gtk+/commit/?id=3c510f028f9a399c80851d2cb8c230e930abd4ff (committed by Javier Jardon). The problem is that Command isn't used in all cases: For example, Linux uses Ctrl-right|left (arrow) to move one word in text. OSX uses Option-right|left for this, but the patch in hand would make it Cmd-right|left, which in OSX normally moves to the beginning or end of the line (analogous to Ctrl-a|e, which work in some places in OSX, though not in this Firefox text field). http://git.gnome.org/browse/gtk+/commit/?id=4ff709c24b8d4b3e26b3d513fde0676e9c43f897 (same author and committer) provided gtkrc.key.mac which provides much finer grained control. A better approach, I think. (I'll also note that fill_key_event has mapped GDK_Alt_R|L to GDK_MOD5_MASK since 2.12, when the function was called create_key_event. Mapping it there in the other direction isn't really a change.)
The first part of the comment-12-patch, which remaps NSCommandKeyMask and GDK_Meta_L|R from GDK_MOD1_MASK to GDK_META_MASK fixes some accelerator weirdness in the face of dynamically installed menus that's been driving me nuts for several days, so I'd like to see it checked in. (In the meantime, I'll just provide it as a patch for Gtk-OSX stable like too many other patches.) The weirdness involved an accelerator map file with different accel-paths for similar actions -- but which in the context of the different plugins needed to behave differently. For example, cut/copy/paste need to have different implementations depending upon which sort of display page has focus. It's obviously desirable that the different implementations have the same accelerator, and in the case of cut/copy/paste, it should be cmd-x, cmd-c, and cmd-v in line with the Apple HIG. So I have an accel-map which remaps those accelerators from control-foo. The weird thing was that when NSCommandKeyMask was mapped to Mod1, the first plugin displayed would show ctrl-x, cmd-c, and ctrl-v, while subsequent ones would show cmd-x, cmd-c, and cmd-v as they should. Change the order that the plugins displayed and the behavior would switch to whichever was first. That sort of confirms in a different way Levi's trouble with having Option mapped to Mod1. There's something wrong with the mod1 mapping.
> The problem is that Command isn't used in all cases: For example, Linux uses > Ctrl-right|left (arrow) to move one word in text. OSX uses Option-right|left > for this, but the patch in hand would make it Cmd-right|left, which in OSX > normally moves to the beginning or end of the line (analogous to Ctrl-a|e, > which work in some places in OSX, though not in this Firefox text field). > > http://git.gnome.org/browse/gtk+/commit/?id=4ff709c24b8d4b3e26b3d513fde0676e9c43f897 > (same author and committer) provided gtkrc.key.mac which provides much finer > grained control. A better approach, I think. That's an issue with the patch, which can be fixed. The gtkrc.key.mac doesn't work for me, at all.
Our copy of gtkrc.key.mac is locally patched to replace the "meta" bindings by "alt", because the Command modifier key is currently (inconsistently and brokenly) mapped to Mod1, as I described in Comment 12. Although this is a hack, it works.
Try what I reported in comment 21. I found that works well with accelerator maps, while using <Alt> in the maps (which translated to Command) was, as you say, inconsistent and broken.
Created attachment 169606 [details] [review] Remove & ~(v|x)mods from modifiers side of modifiers test in gtk_key_hash_lookup() (In reply to comment #21) > The first part of the comment-12-patch, which remaps NSCommandKeyMask and > GDK_Meta_L|R from GDK_MOD1_MASK to GDK_META_MASK fixes some accelerator > weirdness Further testing shows this not to be true. I did a git bisect and found that the weirdness is from http://git.gnome.org/browse/gtk+/commit/?id=03b179c5e8311591f1487a650fec6f20a136e9ca, "Try harder to handle accelerators involving virtual modifiers". This patch, which reverses part of that change, fixes the problem with the accelerators misbehaving. It doesn't seem to get the bindings working, though, so it's not the whole solution.
John, there's another bugzilla report in which i discussed this with Matthias: https://bugzilla.gnome.org/show_bug.cgi?id=607115
Thanks, Paul. I'd missed that one. It seems to me that these two issues are closely coupled, but I'll add my observations about "vmods" and "xmods" on 607115.
I've written a new patch and posted it against #607115. It seems to fix both the accelerator and keybinding problems, and allows the already-installed Mac keybindings to work as well. Please test it on your own applications.
Created attachment 196436 [details] [review] Patch with a complete solution to the modifier confusion Attached new patch obsoletes all previous patches and does the following: - maps Alt/Option to MOD1 as on all other platrforms - maps Command to MOD2 - maps MOD2 to the virtual META - fixes (?) group handling in gdkkeys-quartz.c - fixes text input by adding GTK_NO_TEXT_INPUT_MOD_MASK instead of hardcoding something that doesn't match a Mac - disables mnemonics - sets the default accel modifier to META on quartz - adds <Primary> as possible modifier to GtkAccelGroup which automatically maps to Control or Meta, depending on the platform - fixes GtkCellRendererAccel to recognize virtual modifiers - changes default stock items to GTK_NO_TEXT_INPUT_MOD_MASK instead of hardcoding GDK_CONTROL_MASK
I forgot one thing that is not working: For some reason it's impossible to invoke Command+Option+foo modifiers, I suspect group handling is not quite right yet.
s/modifiers/accelerators/
this detail: - adds <Primary> as possible modifier to GtkAccelGroup which automatically is exceedingly nice. any particular reason you stopped there? is there a reason to map Command to both MOD2 and META? do we really have any reason to continue supporting this "virtual modifier" stuff if you're also adding a concept like <Primary> ?
Created attachment 196450 [details] Menu issues This seems to be against gtk-2-24; it doesn't apply cleanly to master. Wow. This is a huge improvement and works really well. The only remaining issue I see has to do with accelerator display on the menu: * Accelerators set by the application or an acclerator map display <alt>foo as one would expect: For example <alt>v shows as ⌥V, and the Apple-supplied accelerator command-M displays correctly as well. But, as you can see from the screenshot, applying accelerators via the highlight-and-keypress method show the "extended" value of the key (though still with the ⌥ next to it) for option-foo, and don't display a ⌘ next to command-foo accelerators (the W was entered as command-W). * Option-foo accelerators don't work if they map to an extended key, but they display on the menu anyway. It's good that they don't work, accelerators that work sometimes would be confusing. It's not so good that they display, that will frustrate users. * Command-foo accelerators display and work correctly if they're provided via an accel-map (as <meta>foo). They neither display correctly nor work if they're added via the gui. But I don't think many users modify their accelerators via the gui, and it doesn't work with mac-integrated menus anyway. I think this should go into master, and into 2-24 if it's not too big a change for a stable branch.
Paul: I tried for a week to make it work without going for real/virtual, but only after mapping Command to MOD2 and MOD2 to the virtual META, things started to work. Note that this works without your patch in bug #607115. When I tried treatig META as a real modifier, I needed the patch, and things would still not work properly. I guess we have no choice without a bigger refactoring here, which is no option for 2.24.. I stopped with <Primary> because I didn't want to go over the top, and the secondary command modifier in <Shift> on all platforms anyway. Please suggest a better handling if you have one, there are still some minor glitches in the GIMP menus that don't magically go away when I simply replace control by primary, and I would love to have a way to write shortcuts that work on app platforms automatically. John: I saw the problem in the GtkMenu code, but since this is a gross hack that's not going to work on the global menu, I simply ignored it. The problem with option-foo is likely a bug I missed in the keymap levels and groups handling. Command+Option+anything accels don't work at all either btw, probably the same issue. I'm pretty sure this is just a minor glitch in gdkkeys-quartz.c since I verified that the delivered key events do contain the right group now. And the patch is against 2-24 because I'm confident that GIMP works fine on that version, and I needed a complex app for testing. Once this patch gets in, I will port it to master.
(In reply to comment #29) > Created an attachment (id=196436) [details] [review] > Patch with a complete solution to the modifier confusion > > Attached new patch obsoletes all previous patches and does > the following: I agree with the taken approach and the Quartz backend bits seem straightforward. Except for the gdkkeys-quartz.c patch; I have to admit I have no clue about this file :) I do expect a follow-up patch for the issue you raised in comment 30. For the GTK+ part, you are going to need review from (likely) Matthias. I am fine with committing the Quartz parts in 2-24 and master.
(In reply to comment #33) > * Option-foo accelerators don't work if they map to an extended key, but they > display on the menu anyway. It's good that they don't work, accelerators that > work sometimes would be confusing. It's not so good that they display, that > will frustrate users. I would say we try to do things like Cocoa does. Option-foo accelerators then only do not work in text fields, when extended keyboard keys can be pressed. When another control has focus (e.g. a TableView), then the option-foo accelerators do work. In Cocoa, accelerators that are overridden by the extended keyboard when a text field has focus are shown in the menu as usual, even when though they do not always work.
"Option-foo accelerators then only do not work in text fields" please be VERY careful going down this path. its not necessarily the toolkit's decision to make, though its not necessarily a bad starting point. it is also very hard to make GTK do the right thing with unmodified accelerators already (i've often pointed people to the code i use to handle the ambiguity that they cause); building the rule above into GTK might make it even harder.
(In reply to comment #37) > "Option-foo accelerators then only do not work in text fields" > > please be VERY careful going down this path. its not necessarily the toolkit's > decision to make, though its not necessarily a bad starting point. > > it is also very hard to make GTK do the right thing with unmodified > accelerators already (i've often pointed people to the code i use to handle the > ambiguity that they cause); building the rule above into GTK might make it even > harder. I think we would want the IM method the make sure the extended keyboard works properly, which is mainly what I meant to say.
Actually, I figured the problem with Option-foo modifiers in the meantime, it has nothing to do with GDK but rather with the way GTK resolves accelerators. It's built around the user expectation on X11/Win32, which is different from the user expectation on OSX. GDK and GTK are doing exactly what they are supposed to do, and we need to fix gtkkeyhash.c to do something different on OSX. I discussed this with Matthias on IRC and he confirmed my findings, but we both agreed that it's hairy. So, no follow-up patch for that issue in GDK, but rather in GTK.
Review of attachment 196436 [details] [review]: ::: gtk/gtkaccelgroup.c @@ +1370,3 @@ + l += sizeof (text_primary) - 1; + accelerator_mods &= ~GTK_DEFAULT_ACCEL_MOD_MASK; /* consume the default accel */ + } So this will change Meta-foo accels to Primary-foo accels on X11, I guess ? Is that intended ? I don't know if 'Primary' is really something that we want to see there at all, ever. On X11, at least - not sure what the expectations are on OS X. Also: why primary, but no secondary ? ::: gtk/gtkcellrendereraccel.c @@ +429,3 @@ + accel_mods = event->state; + gdk_keymap_add_virtual_modifiers (gdk_keymap_get_for_display (display), &accel_mods); I'm not 100% sure why, but this may not be necessary ? I was just trying testaccel with master, and Super came out just fine without this. ::: gtk/gtkimcontextsimple.c @@ +872,3 @@ !is_hex_start && !is_hex_end && !is_escape && !is_backspace)) { + if (event->state & GTK_NO_TEXT_INPUT_MOD_MASK || This seems fine. ::: gtk/gtkstock.c @@ +328,3 @@ { GTK_STOCK_CDROM, NC_("Stock label", "_CD-Rom"), 0, 0, GETTEXT_PACKAGE }, { GTK_STOCK_CLEAR, NC_("Stock label", "_Clear"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_CLOSE, NC_("Stock label", "_Close"), GTK_DEFAULT_ACCEL_MOD_MASK, 'w', GETTEXT_PACKAGE }, Looks ok, if that is what is expected on OS X.
Review of attachment 196436 [details] [review]: I would recommend to split this up into a number of separate patches: - use defaul-accel-mod-mask - introduce and use no-input-mask - quartz backend changes - the primary thing - etc
(In reply to comment #40) > So this will change Meta-foo accels to Primary-foo accels on X11, I guess ? > Is that intended ? I don't know if 'Primary' is really something that we want > to see there at all, ever. On X11, at least - not sure what the expectations > are on OS X. i suppose that the question breaks down into several parts 1) names of the mask macro constants used in GTK 2) names of mask macro constants used by app developers 3) tokens used in accelerator binding definitions 4) displayed of modifier names in the GUI what we did in ardour addressed just 2 and 3 (by defining, effectively, new macro constants for Primary/Secondary and so on. these are then the only references to modifiers in both the code, and in a file that gets processed to generate a platform specific binding file). users never see Primary, but developers do, enforcing cross-platform goodness. > Also: why primary, but no secondary ? as mitch explained above, on all platforms, its Shift. not sure if this is a good enough reason but its not bad.
The misunderstandings have been resolved on IRC, will push in parts.
Patch pushed to 2-24 in logical units. Paul: for master, I'll come up with proper public API and change the patch to use it, so GTK+ and apps end up using exactly the same.
Created attachment 196811 [details] [review] Start abstracting selection modifying modifier keys I'm simply abusing this bug to post related patches, this one is for taking care of the fact that on the Mac, Command-click modifies selections, not Control-click.
This is fixed in gtk-2-24, gtk-3-2 and master.