summaryrefslogtreecommitdiff
path: root/mcwm.c
diff options
context:
space:
mode:
authorMichael Cardell Widerkrantz <mc@hack.org>2011-03-28 15:02:36 +0200
committerMichael Cardell Widerkrantz <mc@hack.org>2011-03-28 15:18:38 +0200
commitb41b1c184ad1c51435c70a1ad5e05a48c14afe89 (patch)
treeec2f744df3d86e31bead44deddafac8e7cf68ac4 /mcwm.c
parent8722badc3d883a04433c7782e5b2d23063edd525 (diff)
downloadmcwm-b41b1c184ad1c51435c70a1ad5e05a48c14afe89.zip
Removed USERKEY_MOD and KEY_ALT special handling. Now asks X server
for keycodes with MODKEY mask instead and checks for those. Also stops tabbing around not only when MODKEY keys are released, but also when another MODKEY command is pressed.
Diffstat (limited to 'mcwm.c')
-rw-r--r--mcwm.c230
1 files changed, 177 insertions, 53 deletions
diff --git a/mcwm.c b/mcwm.c
index 76a6c30..0f0dc8e 100644
--- a/mcwm.c
+++ b/mcwm.c
@@ -7,7 +7,8 @@
* MC, mc at the domain hack.org
* http://hack.org/mc/
*
- * Copyright (c) 2010 Michael Cardell Widerkrantz, mc at the domain hack.org.
+ * Copyright (c) 2010,2011 Michael Cardell Widerkrantz, mc at the
+ * domain hack.org.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -119,7 +120,6 @@ typedef enum {
KEY_B,
KEY_N,
KEY_END,
- KEY_ALT,
KEY_MAX
} key_enum_t;
@@ -210,9 +210,19 @@ struct keys
{ USERKEY_BOTLEFT, 0 },
{ USERKEY_BOTRIGHT, 0 },
{ USERKEY_DELETE, 0 },
- { USERKEY_MOD, 0 },
};
+/* All keycodes generating our MODKEY mask. */
+struct modkeycodes
+{
+ xcb_keycode_t *keycodes;
+ unsigned len;
+} modkeys =
+{
+ NULL,
+ 0
+};
+
/* Global configuration. */
struct conf
{
@@ -235,6 +245,8 @@ xcb_atom_t wm_protocols; /* WM_PROTOCOLS. */
/* Functions declerations. */
+void finishtabbing(void);
+struct modkeycodes getmodkeys(xcb_mod_mask_t modmask);
void cleanup(int code);
void arrangewindows(uint16_t rootwidth, uint16_t rootheight);
void setwmdesktop(xcb_drawable_t win, uint32_t ws);
@@ -283,6 +295,108 @@ void sigcatch(int sig);
/* Function bodies. */
/*
+ * MODKEY was released after tabbing around the
+ * workspace window ring. This means this mode is
+ * finished and we have found a new focus window.
+ *
+ * We need to move first the window we used to focus
+ * on to the head of the window list and then move the
+ * new focus to the head of the list as well. The list
+ * should always start with the window we're focusing
+ * on.
+ */
+void finishtabbing(void)
+{
+
+ mode = 0;
+
+ if (NULL != lastfocuswin)
+ {
+ movetohead(&wslist[curws], lastfocuswin->wsitem[curws]);
+ lastfocuswin = NULL;
+ }
+
+ movetohead(&wslist[curws], focuswin->wsitem[curws]);
+}
+
+/*
+ * Find out what keycode modmask is bound to. Returns a struct. If the
+ * len in the struct is 0 something went wrong.
+ */
+struct modkeycodes getmodkeys(xcb_mod_mask_t modmask)
+{
+ xcb_get_modifier_mapping_cookie_t cookie;
+ xcb_get_modifier_mapping_reply_t *reply;
+ xcb_keycode_t *modmap;
+ struct modkeycodes keycodes = {
+ NULL,
+ 0
+ };
+ int mask;
+ unsigned i;
+ const xcb_mod_mask_t masks[8] = { XCB_MOD_MASK_SHIFT,
+ XCB_MOD_MASK_LOCK,
+ XCB_MOD_MASK_CONTROL,
+ XCB_MOD_MASK_1,
+ XCB_MOD_MASK_2,
+ XCB_MOD_MASK_3,
+ XCB_MOD_MASK_4,
+ XCB_MOD_MASK_5 };
+
+ cookie = xcb_get_modifier_mapping_unchecked(conn);
+
+ if ((reply = xcb_get_modifier_mapping_reply(conn, cookie, NULL)) == NULL)
+ {
+ return keycodes;
+ }
+
+ if (NULL == (keycodes.keycodes = calloc(reply->keycodes_per_modifier,
+ sizeof (xcb_keycode_t))))
+ {
+ PDEBUG("Out of memory.\n");
+ return keycodes;
+ }
+
+ modmap = xcb_get_modifier_mapping_keycodes(reply);
+
+ /*
+ * The modmap now contains keycodes.
+ *
+ * The number of keycodes in the list is 8 *
+ * keycodes_per_modifier. The keycodes are divided into eight
+ * sets, with each set containing keycodes_per_modifier elements.
+ *
+ * Each set corresponds to a modifier in masks[] in the order
+ * specified above.
+ *
+ * The keycodes_per_modifier value is chosen arbitrarily by the
+ * server. Zeroes are used to fill in unused elements within each
+ * set.
+ */
+ for (mask = 0; mask < 8; mask ++)
+ {
+ if (masks[mask] == modmask)
+ {
+ for (i = 0; i < reply->keycodes_per_modifier; i ++)
+ {
+ if (0 != modmap[mask * reply->keycodes_per_modifier + i])
+ {
+ keycodes.keycodes[i]
+ = modmap[mask * reply->keycodes_per_modifier + i];
+ keycodes.len ++;
+ }
+ }
+
+ PDEBUG("Got %d keycodes.\n", keycodes.len);
+ }
+ } /* for mask */
+
+ free(reply);
+
+ return keycodes;
+}
+
+/*
* Map all windows we know about. Set keyboard focus to be wherever
* the mouse pointer is. Then exit.
*/
@@ -995,11 +1109,40 @@ xcb_keycode_t keysymtokeycode(xcb_keysym_t keysym, xcb_key_symbols_t *keysyms)
int setupkeys(void)
{
xcb_key_symbols_t *keysyms;
- int i;
+ unsigned i;
/* Get all the keysymbols. */
keysyms = xcb_key_symbols_alloc(conn);
+
+ /*
+ * Find out what keys generates our MODKEY mask. Unfortunately it
+ * might be several keys.
+ */
+ if (NULL != modkeys.keycodes)
+ {
+ free(modkeys.keycodes);
+ }
+ modkeys = getmodkeys(MODKEY);
+
+ if (0 == modkeys.len)
+ {
+ fprintf(stderr, "We couldn't find any keycodes to our main modifier "
+ "key!\n");
+ return -1;
+ }
+
+ for (i = 0; i < modkeys.len; i ++)
+ {
+ /*
+ * Grab the keys that are bound to MODKEY mask with any other
+ * modifier.
+ */
+ xcb_grab_key(conn, 1, screen->root, XCB_MOD_MASK_ANY,
+ modkeys.keycodes[i],
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
+ }
+ /* Now grab the rest of the keys with the MODKEY modifier. */
for (i = KEY_F; i < KEY_MAX; i ++)
{
keys[i].keycode = keysymtokeycode(keys[i].keysym, keysyms);
@@ -1012,34 +1155,18 @@ int setupkeys(void)
return -1;
}
+
+ /* Grab other keys with a modifier mask. */
+ xcb_grab_key(conn, 1, screen->root, MODKEY, keys[i].keycode,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
- if (i == KEY_ALT)
- {
- /*
- * Grab Alt with all modifiers.
- *
- * FIXME: We can ask the X server for the keycode that
- * gives us the MODKEY mask with the GetModifierMapping
- * request.
- */
- xcb_grab_key(conn, 1, screen->root, XCB_MOD_MASK_ANY,
- keys[KEY_ALT].keycode,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
- }
- else
- {
- /* Grab other keys with a modifier mask. */
- xcb_grab_key(conn, 1, screen->root, MODKEY, keys[i].keycode,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
-
- /*
- * XXX Also grab it's shifted counterpart. A bit ugly here
- * because we grab all of them not just the ones we want.
- */
- xcb_grab_key(conn, 1, screen->root, MODKEY | SHIFTMOD,
- keys[i].keycode,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
- }
+ /*
+ * XXX Also grab it's shifted counterpart. A bit ugly here
+ * because we grab all of them not just the ones we want.
+ */
+ xcb_grab_key(conn, 1, screen->root, MODKEY | SHIFTMOD,
+ keys[i].keycode,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
} /* for */
/* Need this to take effect NOW! */
@@ -2317,8 +2444,8 @@ void handle_keypress(xcb_key_press_event_t *ev)
if (MCWM_TABBING == mode && key != KEY_TAB)
{
- /* We don't allow any other key while in this mode. */
- return;
+ /* First finish tabbing around. Then deal with the next key. */
+ finishtabbing();
}
/* Is it shifted? */
@@ -2823,32 +2950,29 @@ void events(void)
case XCB_KEY_RELEASE:
{
xcb_key_release_event_t *e = (xcb_key_release_event_t *)ev;
+ unsigned i;
PDEBUG("Key %d released.\n", e->detail);
- if (e->detail == keys[KEY_ALT].keycode && MCWM_TABBING == mode)
+ if (MCWM_TABBING == mode)
{
- /* MODKEY was released after tabbing around the
- * workspace window ring. This means this mode is
- * finished and we have found a new focus window.
- *
- * We need to move first the window we used to focus
- * on to the head of the window list and then move the
- * new focus to the head of the list as well. The list
- * should always start with the window we're focusing
- * on.
+ /*
+ * Check if it's the that was released was a key
+ * generating the MODKEY mask.
*/
-
- mode = 0;
-
- if (NULL != lastfocuswin)
+ for (i = 0; i < modkeys.len; i ++)
{
- movetohead(&wslist[curws], lastfocuswin->wsitem[curws]);
- lastfocuswin = NULL;
- }
-
- movetohead(&wslist[curws], focuswin->wsitem[curws]);
- } /* if KEY_ALT */
+ PDEBUG("Is it %d?\n", modkeys.keycodes[i]);
+
+ if (e->detail == modkeys.keycodes[i])
+ {
+ finishtabbing();
+
+ /* Get out of for... */
+ break;
+ }
+ } /* for keycodes. */
+ } /* if tabbing. */
}
break;