Re: [PATCH to panel] popup menu and "run" dialog independant of the state of ScrollLock and NumLock



On Wed, 28 Feb 2001, Vlad Harchev wrote:

 Hi, 

> 
> On 27 Feb 2001, Havoc Pennington wrote:
> 
> > 
> > Vlad Harchev <hvv hippo ru> writes: 
> > >  I just tried to really work with a patched panel. If "Run.." dialog is
> > > invokable via Ximian's "Ctrl-Mod4-r", then I CAN NOT TYPE "r" in any widget of
> > > any window! ( use safwish as wm, and when I press 'r', the window it's typed
> > > in quivers. It appears this is how X works :( So, don't apply this patch yet -
> > > it breaks things.
> > > 
> > >  So, to work around this X's limitation, we can grab all possible combinations
> > > of "uninteresting" modifiers (combined with a fixed value for combination of
> > > "interesting"), and the fewer uninteresting combinations we
> > > have, the better (i.e. it's our intereset to not support supersets of
> > > "meaningful" modifiers - i.e. if the original binding is "ctrl-alt-r", it
> > > shouldn't be activated if "ctrl-alt-super-r" is pressed IMO). But with this
> > > approach there is still a need to know which modifiers are not meaningful
> > > (which ones correspond to keys treated as numlock and scrolllock). I think
> > > that we should hardcode typical values a usual 105-key keyboard has, and check
> > > some environment variable for a mask containing all "not meaningful
> > > modifiers" - if it's defined, then use its value as a bitset of "not
> > > meaningful" modifiers.
> 
>  As for this - I will try whether returning the even to the event queue (via
> XSendEvent) will work  since this approach is much more attractive than
> grabbing all possible combinations of modifier keys), and will report it here.

 Playing with XSendEvent didn't help at all.

> > >  What do you think?
> > > 
> > 
> > If you look at gtk+/gdk/x11/gdkkeys-x11.c in the unstable GTK tree,
> > there's code which finds the "mode switch" modifier, you could use the
> > same code to determine the modifier corresponding to NumLock and
> > ScrollLock.
> 
>  Thanks for the hint. I'll look into this.

 I decided that it's tolerable to invoke actions independant of the state 
"extra" modifiers (among which are scrollock and numlock).

 So, here is a final, tested patch that works by grabbing all possible
combinations of "extra" modifers, when "interesting" modifiers down. 
Patched panel works fine indpendantly of ScrollLock, CapsLock, NumLock and
current XKB group.

 What do you think about it? Will it go to 1.4?

 I will submit bugreport with it to make tracking easier.

 Best regards,
  -Vlad
diff -ru panel~/global-keys.c panel/global-keys.c
--- panel~/global-keys.c	Tue Jan 30 20:59:56 2001
+++ panel/global-keys.c	Thu Mar  1 14:14:43 2001
@@ -13,6 +13,81 @@
 extern GSList *panel_list;
 extern GSList *panels;
 
+#define N_BITS 32 /*all modifier masks fit into it */
+typedef void (*bits_callback_t)(guint value,gpointer user_data);
+static void all_combinations(guint mask_to_traverse,bits_callback_t callback,
+	gpointer user_data)
+{
+    int indexes[N_BITS];/*indexes of bits we need to flip*/
+    int i,bit,bits_set_cnt;
+    
+    {
+	bit = 0;
+	for(i=0;i<N_BITS;++i)
+	    if (mask_to_traverse & (1<<i))
+		indexes[bit++]=i;
+	bits_set_cnt = bit;
+    };
+    {
+	int uppervalue = 1<<bits_set_cnt;
+	for(i=0;i<uppervalue;++i) {
+	    int j,result=0;
+	    
+	    for(j=0;j<bits_set_cnt;++j) {
+		if (i & (1<<j))
+		    result |= (1<<indexes[j]);
+	    }
+	    callback(result,user_data);
+	};
+    }
+};
+
+typedef struct mod_and_key_
+{
+	guint mods;
+	guint key;
+} mod_and_key;
+
+static void do_grab_key(guint mod,mod_and_key* data)
+{
+	XGrabKey (GDK_DISPLAY(), data->key, mod | data->mods,
+			  GDK_ROOT_WINDOW(), True,
+			  GrabModeAsync, GrabModeAsync);
+};
+
+/*we exclude shift, GDK_CONTROL_MASK and GDK_MOD1_MASK since we know what 
+ these modifiers mean */
+#define ALL_MODS 0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK  | \
+    GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK 
+    
+static void grab_key(guint mod,guint key)
+{
+    mod_and_key data;
+    int other_mods = ALL_MODS & (~mod);
+    
+    data.mods = mod;
+    data.key = key;
+    
+    all_combinations(other_mods, do_grab_key,&data);
+};
+
+static void do_ungrab_key(guint mod,mod_and_key* data)
+{
+	XUngrabKey (GDK_DISPLAY(), data->key, mod | data->mods,
+			GDK_ROOT_WINDOW());
+};
+
+static void ungrab_key(guint mod,guint key)
+{
+    mod_and_key data;
+    int other_mods = ALL_MODS & (~mod);    
+    
+    data.mods = mod;
+    data.key = key;
+    
+    all_combinations(other_mods, do_ungrab_key,&data);
+};
+
 void
 panel_global_keys_setup(void)
 {
@@ -27,11 +102,9 @@
 
 	gdk_error_trap_push();
 	if (lastkey_menu)
-		XUngrabKey (GDK_DISPLAY(), lastkey_menu, laststate_menu,
-			    GDK_ROOT_WINDOW());
+		ungrab_key(laststate_menu, lastkey_menu);
 	if (lastkey_run && !same)
-		XUngrabKey (GDK_DISPLAY(), lastkey_run, laststate_run,
-			    GDK_ROOT_WINDOW());
+		ungrab_key(laststate_run, lastkey_run);
 	
 	if (global_config.keys_enabled && 
 	    global_config.menu_keysym) {
@@ -39,9 +112,7 @@
 						global_config.menu_keysym);
 		laststate_menu = global_config.menu_state;
 		if(lastkey_menu)
-			XGrabKey (GDK_DISPLAY(), lastkey_menu, laststate_menu, 
-				  GDK_ROOT_WINDOW(), True,
-				  GrabModeAsync, GrabModeAsync);
+			grab_key(laststate_menu, lastkey_menu);
 	} else
 		lastkey_menu = 0;
 
@@ -53,9 +124,7 @@
 		if(lastkey_run &&
 		   (lastkey_menu != lastkey_run ||
 		    laststate_menu != laststate_run))
-			XGrabKey (GDK_DISPLAY(), lastkey_run, laststate_run, 
-				  GDK_ROOT_WINDOW(), True,
-				  GrabModeAsync, GrabModeAsync);
+		    	grab_key(laststate_run, lastkey_run);
 	} else
 		lastkey_run = 0;
 	gdk_flush ();
@@ -87,7 +156,7 @@
 	run_state = global_config.run_state;
 
 	if (keycode == menu_keycode &&
-	    state == menu_state) {
+	    (state & menu_state) == menu_state) {
 		PanelWidget *panel;
 		GtkWidget *menu, *basep;
 		/* check if anybody else has a grab */
@@ -110,7 +179,7 @@
 				NULL, NULL, 0, GDK_CURRENT_TIME);
 		return GDK_FILTER_REMOVE;
 	} else if (keycode == run_keycode &&
-		   state == run_state) {
+		   (state & run_state) == run_state) {
 		/* check if anybody else has a grab */
 		if (gdk_pointer_grab (GDK_ROOT_PARENT(), FALSE, 
 				      0, NULL, NULL, GDK_CURRENT_TIME)


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