Hi,

On 03/06/2012 06:13 PM, Roland Stigge wrote:
> this bug is well reproducible, while looking around in the github code,
> I couldn't find a commit that fixes the problem, unfortunately.

The fixes from the github branch "wip-fix-xkb" fix it for me. :-)

I backported them, attaching the patch for the Debian package.

Roland
--- keybinder-0.2.2.orig/libkeybinder/keybinder.h
+++ keybinder-0.2.2/libkeybinder/keybinder.h
@@ -32,6 +32,8 @@ typedef void (* KeybinderHandler) (const
 
 void keybinder_init (void);
 
+void keybinder_set_use_cooked_accelerators (gboolean use_cooked);
+
 gboolean keybinder_bind (const char *keystring,
                          KeybinderHandler  handler,
                          void *user_data);
--- keybinder-0.2.2.orig/libkeybinder/bind.c
+++ keybinder-0.2.2/libkeybinder/bind.c
@@ -71,6 +71,8 @@ struct Binding {
 static GSList *bindings = NULL;
 static guint32 last_event_time = 0;
 static gboolean processing_event = FALSE;
+static gboolean detected_xkb_extension = FALSE;
+static gboolean use_xkb_extension = FALSE;
 
 /* Return the modifier mask that needs to be pressed to produce key in the
  * given group (keyboard layout) and level ("shift level").
@@ -191,13 +193,15 @@ grab_ungrab (GdkWindow *rootwin,
 	int k;
 	GdkKeymapKey *keys;
 	gint n_keys;
-	GdkModifierType add_modifiers;
-	XkbDescPtr xmap;
+	GdkModifierType add_modifiers = 0;
+	XkbDescPtr xmap = NULL;
 	gboolean success = FALSE;
 
-	xmap = XkbGetMap(GDK_WINDOW_XDISPLAY(rootwin),
-	                 XkbAllClientInfoMask,
-	                 XkbUseCoreKbd);
+	if (use_xkb_extension) {
+		xmap = XkbGetMap(GDK_WINDOW_XDISPLAY(rootwin),
+		                 XkbAllClientInfoMask,
+		                 XkbUseCoreKbd);
+	}
 
 	gdk_keymap_get_entries_for_keyval(NULL, keyval, &keys, &n_keys);
 
@@ -213,16 +217,24 @@ grab_ungrab (GdkWindow *rootwin,
 			continue;
 		}
 
-		add_modifiers = FinallyGetModifiersForKeycode(xmap,
+
+		TRACE (g_print("grab/ungrab keycode: %d, lev: %d, grp: %d, ",
+			keys[k].keycode, keys[k].level, keys[k].group));
+		if (use_xkb_extension) {
+			add_modifiers = FinallyGetModifiersForKeycode(xmap,
 		                                              keys[k].keycode,
 		                                              keys[k].group,
 		                                              keys[k].level);
+		} else if (keys[k].level > 0) {
+			/* skip shifted/modified keys in non-xkb mode
+			 * this might mean the key can't be bound at all
+			 */
+			continue;
+		}
 
 		if (add_modifiers == MODIFIERS_ERROR) {
 			continue;
 		}
-		TRACE (g_print("grab/ungrab keycode: %d, lev: %d, grp: %d, ",
-			keys[k].keycode, keys[k].level, keys[k].group));
 		TRACE (g_print("modifiers: 0x%x (consumed: 0x%x)\n",
 		               add_modifiers | modifiers, add_modifiers));
 		if (grab_ungrab_with_ignorable_modifiers(rootwin,
@@ -240,7 +252,9 @@ grab_ungrab (GdkWindow *rootwin,
 
 	}
 	g_free(keys);
-	XkbFreeClientMap(xmap, 0, TRUE);
+	if (xmap) {
+		XkbFreeClientMap(xmap, 0, TRUE);
+	}
 
 	return success;
 }
@@ -357,7 +371,8 @@ filter_func (GdkXEvent *gdk_xevent, GdkE
 				xevent->xkey.keycode, 
 				xevent->xkey.state));
 
-		gdk_keymap_translate_keyboard_state(
+		if (use_xkb_extension) {
+			gdk_keymap_translate_keyboard_state(
 				keymap,
 				xevent->xkey.keycode,
 				modifiers,
@@ -366,6 +381,10 @@ filter_func (GdkXEvent *gdk_xevent, GdkE
 				 */
 				WE_ONLY_USE_ONE_GROUP,
 				&keyval, NULL, NULL, &consumed);
+		} else {
+			consumed = 0;
+			keyval = XLookupKeysym(&xevent->xkey, 0);
+		}
 
 		/* Map non-virtual to virtual modifiers */
 		modifiers &= ~consumed;
@@ -431,6 +450,26 @@ keybinder_init ()
 {
 	GdkKeymap *keymap = gdk_keymap_get_default ();
 	GdkWindow *rootwin = gdk_get_default_root_window ();
+	Display *disp;
+	int xkb_opcode;
+	int xkb_event_base;
+	int xkb_error_base;
+	int majver = XkbMajorVersion;
+	int minver = XkbMinorVersion;
+
+	if (!(disp = XOpenDisplay(NULL))) {
+		g_warning("keybinder_init: Unable to open display");
+		return;
+	}
+
+	detected_xkb_extension = XkbQueryExtension(disp,
+	                                           &xkb_opcode,
+	                                           &xkb_event_base,
+	                                           &xkb_error_base,
+	                                           &majver, &minver);
+
+	use_xkb_extension = detected_xkb_extension;
+	TRACE(g_print("XKB: %d, version: %d, %d\n", use_xkb_extension, majver, minver));
 
 	gdk_window_add_filter (rootwin, filter_func, NULL);
 
@@ -448,6 +487,12 @@ keybinder_init ()
 			  NULL);
 }
 
+void
+keybinder_set_use_cooked_accelerators (gboolean use_cooked)
+{
+       use_xkb_extension = use_cooked && detected_xkb_extension;
+}
+
 gboolean
 keybinder_bind (const char *keystring,
                 KeybinderHandler handler,

Reply via email to