After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 711019 - Globally defined keyboard shortcuts should pass through to the system
Globally defined keyboard shortcuts should pass through to the system
Status: RESOLVED OBSOLETE
Product: gtk+
Classification: Platform
Component: Backend: Quartz
unspecified
Other Mac OS
: Normal normal
: ---
Assigned To: gtk-quartz maintainers
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2013-10-28 16:14 UTC by Cody Russell
Modified: 2018-05-02 15:51 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Simple patch (1012 bytes, patch)
2013-10-28 16:14 UTC, Cody Russell
none Details | Review
Let globally defined hotkeys pass through (1.94 KB, patch)
2013-10-29 01:53 UTC, Cody Russell
none Details | Review
Quite a bit simpler than my previous patch :) (357 bytes, patch)
2013-10-31 01:43 UTC, Cody Russell
rejected Details | Review
Make global hotkeys work (9.86 KB, patch)
2014-01-23 17:37 UTC, andriusr
none Details | Review

Description Cody Russell 2013-10-28 16:14:47 UTC
Created attachment 258314 [details] [review]
Simple patch

I have a simple patch that fixes this, but I don't know if there are other "standard" key combinations that should also be ignored, or if there is some way to mark a window so that it doesn't trap these types of things.
Comment 1 John Ralls 2013-10-28 16:45:22 UTC
Why?

What's so special about ctrl-F2? The SysPrefs Keyboard pane maps ctrl-F1 through ctrl-F7 by default, along with a ton of other keys. What if the user has disabled that shortcut?

You *might* make a case that the Prefs-defined-and-enabled shortcut keys should all be ignored, but you haven't made any case at all.
Comment 2 Cody Russell 2013-10-28 17:48:22 UTC
I had some trouble finding the right API to get the preferences-defined shortcuts, but I found it and I'm writing a new patch now that will handle those.
Comment 3 John Ralls 2013-10-28 18:00:05 UTC
You still need to make a case for the change. This has the potential to break any application that uses an accelerator or binding which conflicts.

BTW, based on the line numbers from your first patch I guess that you're working with gtk-2-24 and not master. You should work primarily with master and provide backporting patches to other branches.
Comment 4 Cody Russell 2013-10-29 01:53:29 UTC
Created attachment 258385 [details] [review]
Let globally defined hotkeys pass through

Here's a patch that actually checks if the key is among the hotkeys in the system, and is enabled, and allows that keystroke to pass through.

There may be some modifiers missing here.  Cocoa defines NSAlternateKeyMask while Carbon defines optionKeyBit.  I think those may represent the same modifier, but I'm not sure yet so I didn't add it.  I'm also not sure what alpha lock is, but there's an alphaLockBit in Carbon and NSAlphaShiftKeyMask in Cocoa.  I'll amend the patch as needed, and also of course provide a patch that builds against gtk+ master.  I'm currently building against 2.x out of personal convenience.
Comment 5 Cody Russell 2013-10-29 02:21:03 UTC
Also, I was thinking about the issue you brought up that this has the potential to break applications.  I wondered what happens when I define Cmd-N (or some other common hotkey) in the system preferences.. would the system respond to it, or would the focused app?

I set Cmd-N to be the "Show Launchpad" hotkey, focused the Twitter Mac app, hit Cmd-N... and the Launchpad was shown, Twitter app didn't get to respond to it.

So I think gtk+ apps should behave the same way.  If someone sets Cmd-Q as a global hotkey then it should override the gtk app's quit command.  Hopefully nobody does that though. :)
Comment 6 Michael Natterer 2013-10-29 15:02:16 UTC
I think the application breakage is secondary. It's the same on X11:
if the window manager steals a shortcut, that's purely the window
manager's or the user's fault (if the user configured it).

What I'm wondering about here is why we get the key events in the
first place? Is there really code in the Cocoa classes all native
apps are using that checks each key stroke with some API, and sends
it back to the system if it's globally taken?
Comment 7 Michael Natterer 2013-10-29 15:03:39 UTC
Where did my last line go... here it is:

...If this is the case, we should do the same and return these
events back to the system unhandled.
Comment 8 Cody Russell 2013-10-29 16:43:02 UTC
Yeah, I was wondering the same thing but I just don't have enough experience with MacOS yet to answer that question yet.  I will investigate further.
Comment 9 John Ralls 2013-10-29 21:08:29 UTC
I think we're grabbing the event before anything else gets a chance to see it. That's why returning GDK_NOTHING lets it go on to the Quartz handlers.
Comment 10 Cody Russell 2013-10-30 23:19:45 UTC
Okay, I think I've learned a little bit more about this and I believe I have some idea why gtk+ is getting the events before the system handles them.  gdkeventloop-quartz.c has the answer I think.

Our poll function calls [NSApp nextEventMatchingMask: NSAnyEventMask, ..., dequeue: YES] and queues that event.

https://developer.apple.com/library/mac/documentation/cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/NSApplication/nextEventMatchingMask:untilDate:inMode:dequeue:

The docs say, "You can use this method to short circuit normal event dispatching and get your own events." which sounds exactly like something that may cause the situation we're talking about.
Comment 11 John Ralls 2013-10-30 23:28:24 UTC
Yup. We're real familiar with that bit of code: See bug 701571.
Comment 12 Michael Natterer 2013-10-31 00:01:09 UTC
Since we are not an application that uses the normal native toolkit
but our own toolkit, we hardly have a choice but processing all
events ourselves. That kindof answers my own question, it seems
pretty obvious that the handling of these global shortcuts is implemented
somewhere in NSApp or NSWindow, so in the application process, and
we should probably do the same.
Comment 13 Cody Russell 2013-10-31 01:43:45 UTC
Created attachment 258627 [details] [review]
Quite a bit simpler than my previous patch :)

This fixes the issue as well, and it's quite a bit simpler.  I was wondering if doing this would just queue the event back up in Cocoa, only to be retrieved against from gtk+ in a future mainloop iteration.. but that ended up not happening.
Comment 14 John Ralls 2013-10-31 02:51:44 UTC
(In reply to comment #12)
> Since we are not an application that uses the normal native toolkit
> but our own toolkit, we hardly have a choice but processing all
> events ourselves. That kindof answers my own question, it seems
> pretty obvious that the handling of these global shortcuts is implemented
> somewhere in NSApp or NSWindow, so in the application process, and
> we should probably do the same.

I think it's neither. See https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW11

It might be worthwhile to make a little test application in pure cocoa to see if a global action, e.g. shifting focus to the menu bar, is overridden if the NSApplication or NSWindow defines a handler for the key sequence. The "bottom-up" chain described in the reference suggests that might be the case.
Comment 15 Cody Russell 2013-10-31 03:28:42 UTC
Comment on attachment 258627 [details] [review]
Quite a bit simpler than my previous patch :)

Uhh, nevermind.  This definitely does queue the events back into Cocoa or something.
Comment 16 Cody Russell 2013-10-31 16:13:05 UTC
John, I did read that link you provided already.  But if you read what I wrote about [NSApp nextEventMatchingMask:], the docs talk about using this method to short-circuit normal event dispatch.  I think the link in your comment is describing that normal event dispatch that we're short-circuiting.
Comment 17 John Ralls 2013-11-01 00:35:13 UTC
(In reply to comment #16)
> John, I did read that link you provided already.  But if you read what I wrote
> about [NSApp nextEventMatchingMask:], the docs talk about using this method to
> short-circuit normal event dispatch.  I think the link in your comment is
> describing that normal event dispatch that we're short-circuiting.

Yes, that's correct. The point is that your proposed change is to emulate what you believe to be the native normal dispatch. I think that we need to test that belief with a native test program, because the documentation says that the responder chain is bottom-up. When I wrote it, I thought that we'd need to write a test program, but I just now remembered that iTerm, the terminal emulator I use, allows mapping keys outside of System Preferences, so I mapped ^F2 to "scroll page down". iTerm handles the key event, masking the Sys Prefs setting.

Therefore the correct behavior is *not* to prevent globally-mapped key events from getting to the Gtk application, it's to process them through the Gtk application and if they haven't been handled to *then* pass them back to the OS for action. That's not going to be a trivial fix.
Comment 18 Cody Russell 2013-11-01 02:37:23 UTC
I don't really see how that's possible to do with the current design.  Unless I'm missing something, and I may be.  But when we dispatch the event it goes from gdk_event_dispatch() to gtk_main_do_event() and I don't think there's any way in gdk to know whether gtk actually does anything with that event.
Comment 19 John Ralls 2013-11-01 03:51:36 UTC
Yeah, some flavors of handlers have return values to indicate if further processing is required, but GdkEventFuncs don't. That makes it a bit more complicated. OTOH, if there isn't a registered handler, maybe we can detect that without affecting ABI and still leave the event for the CFMainLoop to handle.
Comment 20 Cody Russell 2013-11-01 15:02:22 UTC
You could detect that from within gtk I think (I'm not exactly sure how yet, I'd need to read some more code), but there's currently no way to communicate that back to gdk.  In order to do what you're talking about it seems like we would need to push a GdkEvent back into gdk, along with a flag or something that says "gtk doesn't care about this event".  Then X11/Win32/Wayland backends would just dequeue that event and do nothing with it, and the Mac backend would convert it back into an NSEvent and [NSApp sendEvent] it (or something like that).  I don't really know how doable that is, or if it would really work.  I can try to cook up a patch this weekend to test this theory out if you'd like.
Comment 21 andriusr 2013-11-03 16:43:30 UTC
Probably this is one more egg and chicken case, but I just want some clarity.
There are number of system-wide shortcuts that should be never overriden. Like making screenshots, switching desktops, hiding doc - the list is really long. 
I think user should expect that these shortcuts will work independent of application. So, in my opinion it would be better if OS shortcuts would have priority over application shortcuts. 
Of course, the user can setup system wide Cmd+C shortcut to to something different, but that would be an user fault, not gtk+. There is no cure for this.
Andrius
Comment 22 andriusr 2013-11-10 11:22:55 UTC
Have few more additional questions.
I am building bluefish using gtk+3.6.4. I added to 3.6.4 source recent native OSX input commit and subsequent patches (see https://git.gnome.org/browse/gtk+/commit/gdk/quartz?id=155caad4267e6e59b9c4859ab448c96875df4404 or https://bugzilla.gnome.org/show_bug.cgi?id=694273). Native IME is nice addition and works really well.
Most of global shortcuts also was working well. Except two:
1. Select next source in Input menu (Alt+Cmd+Space by default) did nothing, the flag icon in the status bar did not changes. What is interesting similar shorcut Select the previous input source (Cmd+Space) works as it should- in switches languages, and menu for language selection appears on the screen.
I tried to assign several different key combinations, but none of them works. 
2. Move focus to next window (Cmd+` by default) also did not works.
I am sure that none of these shortcuts are defined in bf, so the system shortcuts should take preference.
Switching languages or windows I think is reasonable to ask from text editor, so I decided to apply Cody patch and check what would happen.
The patch solved Cmd+` problem. Now I can change the windows. However, it did not solved Alt+Cmd+Space issue. Actually, behavior is quite strange now. Alt+Cmd+Space changes the icon (small flag) in the status menu, however, the actual input language and keyboard layout remains the same. Only when I click on icon and select language from dropdown, the language input changes. So, even if icon shows hiragana I still enter in english or vice versa.
The similar behavior I also noticed in gedit 3.2.6 that was build using gtk+3.2.3.
I also compiled bluefish without gtk-mac-integration and got the same behavior. gtk-demo also behaves the same way.
What is so special about this shortcut? Is there any way to fix it?
Comment 23 John Ralls 2013-11-10 16:11:14 UTC
Comment on attachment 258385 [details] [review]
Let globally defined hotkeys pass through


>+	  if (CFBooleanGetValue (enabled) && keycode == tmp_keycode)
>+	    {
>+	      if ((!!(mod_value & (1 << cmdKeyBit)) == !!(flags & NSCommandKeyMask)) &&
>+		  (!!(mod_value & (1 << controlKeyBit)) == !!(flags & NSControlKeyMask)) &&
>+		  (!!(mod_value & (1 << shiftKeyBit)) == !!(flags & NSShiftKeyMask)))
>+		{
>+		  return GDK_NOTHING;
>+		}
>+

What's the !! about?
Comment 24 Michael Natterer 2013-11-11 07:21:44 UTC
It turns the random bit from (flags & foo) into a boolean value.
Comment 25 andriusr 2013-11-11 14:45:36 UTC
I put g_warning in 
input_sources_changed_notification() in gdkkeys-quartz.c.
In seems that when i push Alt+Cmd+Space the AppleSelectedInputSourcesChangedNotification event is not firing. While when I push Cmd+Space I am getting this event.
Looking for g_warnings in the gtk-demo console.
Comment 26 John Ralls 2013-11-11 17:58:11 UTC
(In reply to comment #24)
> It turns the random bit from (flags & foo) into a boolean value.

Got it, thanks.
Comment 27 andriusr 2014-01-23 17:37:09 UTC
Created attachment 267066 [details] [review]
Make global hotkeys work

I would like to provide some feedback from real-world application. I am working on Bluefish MacOSX port. 
There was discussion on gtk-osx-users-list preceding this post: http://comments.gmane.org/gmane.comp.gnome.gtk2.osx.user/394 . John suggested to re-post it here.

Here is short summary how keyboard event processing works currently.
1. We are grabbing OSX events using [NSApp nextEventMatchingMask:]. Normally all grabbed events are fed to gtk, which decides what to do with them. If gtk do not process the event, it is simply dropped. If we return GDK_NOTHING in _gdk_quartz_keys_event_type() (in gdkkeys-quartz.c), then this event is dispatched back to Quartz using [NSApp sendEvent:nsevent].
 
2. There was notice, that [NSApp nextEventMatchingMask:] grabs all events before anybody can see them. This is mostly true, but not for all events. For example Cmd+Space ("Select previous input source") is processed before we grab it. There is some inconsistency in Apple design, since shortcut with similar action Alt+Cmd+Space ("Select next source in Input menu") is not processed before we grab it, and it is also not processed properly if we feed it back to Quartz.
 
3. gtk-mac-integration package allows (when gtkosx_application_set_use_quartz_accelerators () is set to TRUE) to direct some well known OSX system shortcuts, like Cmd+M ("Minimize window") and others back to Quartz handlers, however, there is one issue with it, as John wrote: "The problem with it is that if there’s a binding overloading an accelerator, as is common with Cmd-(X|C|V), the accelerator is fired instead of the binding. This causes the owner of the menu to respond to the event rather than the widget with current keyboard focus, preventing you from e.g. cutting or pasting into dialog boxes." This means that when system shortcuts are working, widget bindings do not, and vice versa. gtk-mac-integration also does not handles Alt+Cmd+Space or focus switching (Cmd+`) events.

4. Wanting to make gtk-osx application that does not feels one-legged, first we need to decide what global hotkeys we want to be working. My list is below, feel free to add Your own entries:
Cmd+H (Hide Application);
Cmd+M (Minimize Window);
Alt+Cmd+H (Hide Others);
Cmd+` (Move focus to next window).
Alt+Cmd+Space (Select next source in Input menu).

5. Most difficult probably is Alt+Cmd+Space. As I reported above, Cody patch is not handling it properly. In addition, CopySymbolicHotKeys() this patch is using cannot determine what hotkey performs what action. As it is stated is Apple docs: "There is currently no way to determine which hotkey in the Keyboards preference pane corresponds to a specific dictionary". Apple also mentions that "do not call this function unnecessarily or in highly performance-sensitive code". Hard to say what it does means...
In the patch attached I would like to show how this particular problem of Alt+Cmd+Space not working on gtk-osx applications can be solved. It shows how to switch keyboard layouts manually, using Carbon framework. 
Just few comments how Alt+Cmd+Space in proposed patch works. At first, I should mention, that there is no standard function that would give You list of keyboard inputs that are active, identical to the one we can get by clicking on the flag in app bar (You are getting "flag dropdown" here).
Next, ordering on keyboard inputs depends on ordering of Language Preferences that are accessible from Settings. The higher some language is in preference, the higher it is located in the flag dropdown. Unfortunately, there is one issue that I did not managed to solve. Input modes (like Romaji and Hiragana for Japanese input) does not follow this rule - it seems there is some lookup table with priorities. So, for making this hack complete we would need to add lookup table for input modes.
In addition to Alt+Cmd+Space, this patch also enables other hotkeys in my list in #4, while keeping widget bindings intact, so user can copy/paste in dialog boxes and GtkEntry'ies.
The drawback of this patch is obvious- hotkeys are hardcoded and user cannot change it in Preferences pane. I guess this is price to pay fpr being "not an application that uses the normal native toolkit but our own toolkit". 
Hope this will be useful for other projects making ports for MacOSX.
Andrius
Comment 28 Matthias Clasen 2018-02-10 05:00:50 UTC
We're moving to gitlab! As part of this move, we are moving bugs to NEEDINFO if they haven't seen activity in more than a year. If this issue is still important to you and still relevant with GTK+ 3.22 or master, please reopen it and we will migrate it to gitlab.
Comment 29 Matthias Clasen 2018-04-15 00:13:17 UTC
As announced a while ago, we are migrating to gitlab, and bugs that haven't seen activity in the last year or so will be not be migrated, but closed out in bugzilla.

If this bug is still relevant to you, you can open a new issue describing the symptoms and how to reproduce it with gtk 3.22.x or master in gitlab:

https://gitlab.gnome.org/GNOME/gtk/issues/new
Comment 30 Michael Natterer 2018-04-16 17:09:04 UTC
This is still a very real issue, reopening.
Comment 31 GNOME Infrastructure Team 2018-05-02 15:51:16 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gtk/issues/453.