using Gtk; static Gtk.Menu menu; /* Compile with valac --pkg gtk+-3.0 --pkg gdk-x11-3.0 --pkg x11 gtk-popup-issue.vala This really quick examples shows that the gtk menu does not popup if another xevent follows after the popup. */ int main (string[] args) { Gtk.init (ref args); var window = new Window (); window.title = "First GTK+ Program"; window.border_width = 10; window.window_position = WindowPosition.CENTER; window.set_default_size (350, 70); window.destroy.connect (Gtk.main_quit); var button = new Button.with_label ("Click me!"); button.clicked.connect (() => { button.label = "Thank you"; }); window.add (button); window.show_all (); menu = new Gtk.Menu(); var item = new Gtk.MenuItem.with_label("Test"); menu.append(item); menu.show_all(); Gdk.Window rootwin = Gdk.get_default_root_window(); if(rootwin != null) { rootwin.add_filter(event_filter); } bind("V"); Gtk.main (); return 0; } Gdk.FilterReturn event_filter(Gdk.XEvent gdk_xevent, Gdk.Event gdk_event) { X.Event* xevent = (X.Event*) gdk_xevent; if(xevent->type == X.EventType.KeyPress) { warning("Press event received"); menu.popup(null, null, null, 0, Gtk.get_current_event_time()); warning("Popup should be shown now"); return Gdk.FilterReturn.REMOVE; } else if (xevent->type == X.EventType.KeyRelease) { warning("Key release event received"); } return Gdk.FilterReturn.CONTINUE; } void bind(string accelerator) { uint[] lock_modifiers = { 0, Gdk.ModifierType.MOD2_MASK, // NUM_LOCK Gdk.ModifierType.LOCK_MASK, // CAPS_LOCK Gdk.ModifierType.MOD5_MASK, // SCROLL_LOCK Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK, Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.MOD5_MASK, Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK, Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK }; // convert accelerator uint keysym; Gdk.ModifierType modifiers; Gtk.accelerator_parse(accelerator, out keysym, out modifiers); unowned X.Display display = Gdk.x11_get_default_xdisplay(); int keycode = display.keysym_to_keycode(keysym); if(keycode != 0) { X.Window root_window = Gdk.x11_get_default_root_xwindow(); // trap XErrors to avoid closing of application // even when grabing of key fails Gdk.error_trap_push(); // grab key finally // also grab all keys which are combined with a lock key such NumLock foreach(uint lock_modifier in lock_modifiers) { display.grab_key(keycode, modifiers|lock_modifier, root_window, false, X.GrabMode.Async, X.GrabMode.Async); } // wait until all X request have been processed Gdk.flush(); } }