Re: [gtk-osx-users] global menu (with quartz accelerators) precedence over widget key bindings

On Jan 11, 2012, at 4:16 AM, Jesse van den Kieboom wrote:

2012/1/9 John Ralls <jralls ceridwen us>

On Jan 9, 2012, at 5:30 AM, Jesse van den Kieboom wrote:

> When enabling quartz accelerators, the menu actions have priority over widget keybindings (since the menu accelerators are activated from the gdk event filter). However, normally in gtk+ the widget key bindings have priority over the menu of the window. I understand that in OS X, the menu is working slightly different and that the menu's sensitivity is based on the widget and which actions apply on that widget. However, I think it would be more consistent with the application currently to have keybindings activate prior to the menu. Would this be possible (or is it maybe better in this case not to use the quartz accelerators?)

I'm leaning towards it's better not to use the quartz accelerators, though that messes with the "Quit" handling because the quit menu item is presently provided by Quartz... so it goes to the NSApplicationDelegate stuff. If you have quartz accelerators disabled, then cmd-Q goes to the (hidden) Gtk menu item and doesn't go through NSApplicationDelegate. It's pretty easy to fix the main menu item, but the dock menu and "shutdown" signals from Finder are a bit harder.

I haven't tested it, but I think that even on a native Cocoa app a widget keybinding would override a menu accelerator, provided that the widget in question had focus and so was first in the NSResponder chain, or that the NSWindow parent of the widget had a handler that forwarded the event to the widget. I don't offhand see a good way to replicate that with Quartz handlers.

Thanks for the reply. I have been working a bit on this and finally settled on a slightly different approach. What I would like is to have events first be handled by gtk+ (but not the menu accelerators). Then if the event is not handled by anything in gtk, pass the event to the NSApp. Like this we have widget binding precedence, but at the same time that accelerators on the menu are properly flashed when activated (since they go through OS X). A nice side effect of this also is that some other key bindings which are handled in NSApp now also work (like Cmd+~ to cycle through windows).

I didn't find "good" way to implement this behavior, but I did find a "dirty" way. I guess at some point we will have this code for menus properly residing in gtk+ so that it's not needed anymore. Until that time I currently will use a global key snooper (gtk_key_snooper_install, which is executed just before events are handed to gtk+ widgets). In this snooper I replicate the event propagation method in gtk+ (a small amount of copy/pasted code) to emit the events on the appropriate widget. I can't use gtk+ methods for this because I need to know if the event was handled or not. In the case that the event is not actually handled in the end, I pass it to nsapp. In addition, I remove the accel group corresponding to the menu from the window so that menu accelerators are not handled by gtk+.

Anyway, for me it seems to work quite nicely and is I think closer to native behavior (even though the snooper stuff is quite a hack).

I don't think I'd want to publish anything like that! ;-)

ISTM a more profitable approach would be to get the "Quit" Apple events handled correctly with Gdk handling the accelerators, which does produce a more reasonable behavior.

Have you looked at the new menu code Ryan landed in gio a couple of weeks ago? I haven't had time yet.

John Ralls

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]