$OpenBSD: patch-src_keys_c,v 1.1 2002/03/24 22:23:06 couderc Exp $
--- src/keys.c.orig	Sun Mar 24 13:12:35 2002
+++ src/keys.c	Sun Mar 24 13:39:24 2002
@@ -28,6 +28,8 @@
  */
 #include "wm.h"
 
+u_int numlock_mask, scroll_mask;
+
 /* our list of keys that we bind */
 static SLIST_HEAD(, keybind) keys_list = SLIST_HEAD_INITIALIZER(keys_list);
 
@@ -57,7 +59,7 @@ void keys_shutdown() {
 }
 
 /* add a key binding */
-keybind_t *keys_add(int keycode, int modifiers, int action, void* dat) {
+keybind_t *keys_add(int keycode, u_int modifiers, int action, void* dat) {
 	keybind_t *key;
 
 	key = malloc(sizeof(keybind_t));
@@ -72,13 +74,90 @@ keybind_t *keys_add(int keycode, int mod
 	return key;
 }
 
+static __inline void gethackmods() {
+	static int masks[8] = {
+		ShiftMask, LockMask, ControlMask, Mod1Mask,
+		Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
+	};
+	XModifierKeymap *modmap;
+	KeyCode ncode, scode;
+	int i;
+ 
+	/* determine modifier mappings for the below hack */
+	modmap = XGetModifierMapping(display);
+	if (modmap) {
+		numlock_mask = scroll_mask = 0;
+		ncode = XKeysymToKeycode(display, XK_Num_Lock);
+		scode = XKeysymToKeycode(display, XK_Scroll_Lock);
+		for (i = 0; i < 8 * modmap->max_keypermod; i++)
+			if (ncode && modmap->modifiermap[i] == ncode)
+				numlock_mask = masks[i / modmap->max_keypermod];
+			else if (scode && modmap->modifiermap[i] == scode)
+				scroll_mask = masks[i / modmap->max_keypermod];
+			XFreeModifiermap(modmap);
+	} else
+		numlock_mask = scroll_mask = 0;
+}
+
+static __inline void grabhack(Window win, int keycode, u_int modifiers) {
+	if (numlock_mask) {
+		XGrabKey(display, keycode, modifiers | numlock_mask,
+			win, 1, GrabModeAsync, GrabModeAsync);
+		XGrabKey(display, keycode, modifiers | numlock_mask | LockMask,
+			win, 1, GrabModeAsync, GrabModeAsync);
+	}
+	if (scroll_mask) {
+		XGrabKey(display, keycode, modifiers | scroll_mask,
+			win, 1, GrabModeAsync, GrabModeAsync);
+		XGrabKey(display, keycode, modifiers | scroll_mask | LockMask,
+			win, 1, GrabModeAsync, GrabModeAsync);
+	}
+	if (numlock_mask && scroll_mask) {
+		XGrabKey(display, keycode, modifiers | numlock_mask | scroll_mask,
+			win, 1, GrabModeAsync, GrabModeAsync);
+		XGrabKey(display, keycode, modifiers | numlock_mask | scroll_mask | LockMask,
+			win, 1, GrabModeAsync, GrabModeAsync);
+	}
+	XGrabKey(display, keycode, modifiers | LockMask, win, 1,
+		GrabModeAsync, GrabModeAsync);
+	XGrabKey(display, keycode, modifiers, win, 1,
+		GrabModeAsync, GrabModeAsync);
+}
+ 
+void buttongrabhack(Window win, int button, u_int modifiers) {
+	if (numlock_mask) {
+		XGrabButton(display, AnyButton, modifiers | numlock_mask, win,
+			1, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
+		XGrabButton(display, AnyButton, modifiers | numlock_mask | LockMask, win,
+			1, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
+	}
+	if (scroll_mask){
+		XGrabButton(display, AnyButton, modifiers | scroll_mask, win,
+			1, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
+		XGrabButton(display, AnyButton, modifiers | scroll_mask | LockMask, win,
+			1, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
+	}
+	if (numlock_mask && scroll_mask) {
+		XGrabButton(display, AnyButton, modifiers | numlock_mask | scroll_mask,
+			win, 1, ButtonPressMask, GrabModeSync, GrabModeAsync,
+			None, None);
+		XGrabButton(display, AnyButton, modifiers | numlock_mask | scroll_mask | LockMask,
+			win, 1, ButtonPressMask, GrabModeSync, GrabModeAsync,
+			None, None);
+	}
+	XGrabButton(display, AnyButton, modifiers | LockMask, win, 1, ButtonPressMask,
+		GrabModeSync, GrabModeAsync, None, None);
+	XGrabButton(display, AnyButton, modifiers, win, 1, ButtonPressMask,
+		GrabModeSync, GrabModeAsync, None, None);
+}
+
 /* do grabs on the root window of screen */
 void keys_grab(screen_t *screen) {
 	keybind_t *key;
 
+	gethackmods();
 	SLIST_FOREACH(key, &keys_list, k_list)
-		XGrabKey(display, key->keycode, key->modifiers,
-			screen->root, 1, GrabModeAsync, GrabModeAsync);
+		grabhack(screen->root, key->keycode, key->modifiers);
 }
 
 /* move the viewport */
@@ -332,7 +411,8 @@ void keys_press(screen_t *screen, XKeyEv
 
 	SLIST_FOREACH(key, &keys_list, k_list)
 		if (e->keycode == key->keycode
-				&& e->state == key->modifiers) {
+				&& (e->state & ~(numlock_mask |
+				scroll_mask | LockMask)) == key->modifiers) {
 			keys_action(screen, key);
 			return;
 		}
