[gnome-panel/gnome-2-30] Allow Windows key as valid mouse modifier



commit 7732c43b2a47365ca24f3f02e935bda0d9820124
Author: Ray Strode <rstrode redhat com>
Date:   Thu Jul 15 13:58:14 2010 -0400

    Allow Windows key as valid mouse modifier
    
    gnome-panel uses metacity's mouse modifier gconf key to figure
    out which key to listen to when moving panels around.  This
    works fine for Alt, but the more exotic "virtual" modifiers fall
    over.
    
    This commit fixes that problem by mapping the virtual modifiers back
    to their real counterparts. This gives us a value that can be
    directly compared with the event->state field from button press
    events.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=624572
    (cherry picked from commit e5d7a17fb7fa028e618f3728d06770a26d3cb29f)

 gnome-panel/panel-bindings.c |    3 +-
 gnome-panel/panel-toplevel.c |    2 +-
 gnome-panel/panel-xutils.c   |   83 ++++++++++++++++++++++++++++++++++++++++++
 gnome-panel/panel-xutils.h   |    2 +
 4 files changed, 88 insertions(+), 2 deletions(-)
---
diff --git a/gnome-panel/panel-bindings.c b/gnome-panel/panel-bindings.c
index e8fbff5..9dbc858 100644
--- a/gnome-panel/panel-bindings.c
+++ b/gnome-panel/panel-bindings.c
@@ -31,6 +31,7 @@
 
 #include "panel-gconf.h"
 #include "panel-profile.h"
+#include "panel-xutils.h"
 
 #define BINDINGS_PREFIX    "/apps/metacity/window_keybindings"
 #define MOUSE_MODIFIER_DIR "/apps/metacity/general"
@@ -298,5 +299,5 @@ panel_bindings_get_mouse_button_modifier_keymask (void)
 	if (!initialised)
 		panel_bindings_initialise ();
 
-	return mouse_button_modifier_keymask;
+	return panel_get_real_modifier_mask (mouse_button_modifier_keymask);
 }
diff --git a/gnome-panel/panel-toplevel.c b/gnome-panel/panel-toplevel.c
index 8470591..e8a98de 100644
--- a/gnome-panel/panel-toplevel.c
+++ b/gnome-panel/panel-toplevel.c
@@ -3259,7 +3259,7 @@ panel_toplevel_button_press_event (GtkWidget      *widget,
 	 * moves are considered. We don't this for non-expanded panels since we
 	 * only have the handles that the user can grab. */
 	if ((toplevel->priv->expand || toplevel->priv->attached) &&
-	    (event->state & gtk_accelerator_get_default_mod_mask ()) != panel_bindings_get_mouse_button_modifier_keymask ())
+	    (event->state & GDK_MODIFIER_MASK) != panel_bindings_get_mouse_button_modifier_keymask ())
 		return FALSE;
 
 	gdk_window_get_user_data (event->window, (gpointer)&event_widget);
diff --git a/gnome-panel/panel-xutils.c b/gnome-panel/panel-xutils.c
index 9173b68..16cdf67 100644
--- a/gnome-panel/panel-xutils.c
+++ b/gnome-panel/panel-xutils.c
@@ -170,3 +170,86 @@ panel_warp_pointer (GdkWindow *gdk_window,
 	XWarpPointer (display, None, window, 0, 0, 0, 0, x, y);
 	gdk_error_trap_pop ();
 }
+
+guint
+panel_get_real_modifier_mask (guint mask)
+{
+	guint real_mask;
+	int i, min_keycode, max_keycode, keysyms_per_keycode;
+	int max_keycodes_per_modifier;
+	KeySym *keysyms_for_keycodes;
+	XModifierKeymap *modifier_keymap;
+
+	real_mask = mask & ((Mod5Mask << 1) - 1);
+
+	/* Already real */
+	if (mask == real_mask) {
+		return mask;
+	}
+
+	XDisplayKeycodes (GDK_DISPLAY (), &min_keycode, &max_keycode);
+	keysyms_for_keycodes = XGetKeyboardMapping (GDK_DISPLAY (),
+						    min_keycode,
+						    max_keycode - min_keycode + 1,
+						    &keysyms_per_keycode);
+
+	modifier_keymap = XGetModifierMapping (GDK_DISPLAY ());
+	max_keycodes_per_modifier = modifier_keymap->max_keypermod;
+
+	/* Loop through all the modifiers and find out which "real"
+	 * (Mod2..Mod5) modifiers Super, Hyper, and Meta are mapped to.
+	 * Note, Mod1 is used by the Alt modifier */
+	for (i = Mod2MapIndex * max_keycodes_per_modifier;
+	     i < (Mod5MapIndex + 1) * max_keycodes_per_modifier;
+	     i++) {
+		int keycode;
+		int j;
+		KeySym *keysyms_for_keycode;
+		int map_index;
+		int map_mask;
+
+		keycode = modifier_keymap->modifiermap[i];
+
+		/* The array is sparse, there may be some
+		 * empty entries.  Filter those out
+		 * (along with any invalid entries) */
+		if (keycode < min_keycode || keycode > max_keycode)
+			continue;
+
+		keysyms_for_keycode = keysyms_for_keycodes +
+		                      (keycode - min_keycode) * keysyms_per_keycode;
+
+		map_index = i / max_keycodes_per_modifier;
+
+		g_assert (map_index <= Mod5MapIndex);
+
+		map_mask = 1 << map_index;
+
+		for (j = 0; j < keysyms_per_keycode; j++) {
+			switch (keysyms_for_keycode[j]) {
+				case XK_Super_L:
+				case XK_Super_R:
+					if (mask & GDK_SUPER_MASK)
+						real_mask |= map_mask;
+					break;
+				case XK_Hyper_L:
+				case XK_Hyper_R:
+					if (mask & GDK_HYPER_MASK)
+						real_mask |= map_mask;
+					break;
+				case XK_Meta_L:
+				case XK_Meta_R:
+					if (mask & GDK_META_MASK)
+						real_mask |= map_mask;
+					break;
+				default:
+					break;
+			}
+		}
+	}
+
+	XFreeModifiermap (modifier_keymap);
+	XFree (keysyms_for_keycodes);
+
+	return real_mask;
+}
diff --git a/gnome-panel/panel-xutils.h b/gnome-panel/panel-xutils.h
index f73a1a0..10e3f62 100644
--- a/gnome-panel/panel-xutils.h
+++ b/gnome-panel/panel-xutils.h
@@ -53,6 +53,8 @@ void panel_warp_pointer           (GdkWindow             *gdk_window,
 				   int                    x,
 				   int                    y);
 
+guint panel_get_real_modifier_mask (guint modifier_mask);
+
 G_END_DECLS
 
 #endif /* __PANEL_XUTILS_H__ */



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