summaryrefslogtreecommitdiff
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
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.
-rw-r--r--NEWS10
-rw-r--r--config.h8
-rw-r--r--mcwm.c230
-rw-r--r--mcwm.man13
4 files changed, 196 insertions, 65 deletions
diff --git a/NEWS b/NEWS
index cded7ce..591be72 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,16 @@
User visible changes
+2011-03-26
+
+ * You don't have to tell mcwm what keycode generates the MODKEY
+ mask anymore (USERKEY_MOD in config.h is gone). mcwm now asks the
+ X server what keys generate the mask and also supports several
+ keys generating the mask.
+
+ * Stops tabbing around not only if a key generating MODKEY mask is
+ lifted but also if another command key is pressed.
+
2011-03-18
* Now handles keyboard remapping.
diff --git a/config.h b/config.h
index 66be029..c21ffc6 100644
--- a/config.h
+++ b/config.h
@@ -9,12 +9,7 @@
/*
* Use this modifier combined with other keys to control wm from
* keyboard. Default is Mod4, which on my keyboard is the Alt key but
- * is usually the Windows key on more normal keyboard layout.
- *
- * NOTA BENE! Also remember to define the key that generates this
- * modifier as USERKEY_MOD below, otherwise the MODKEY + Tab function
- * won't work properly. This is a bit of a kluge, I know, and will be
- * fixed.
+ * is usually the Windows key on more normal keyboard layouts.
*/
#define MODKEY XCB_MOD_MASK_4
@@ -81,4 +76,3 @@
#define USERKEY_BOTLEFT XK_B
#define USERKEY_BOTRIGHT XK_N
#define USERKEY_DELETE XK_End
-#define USERKEY_MOD XK_Alt_L
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;
diff --git a/mcwm.man b/mcwm.man
index 1af04b7..58f4df3 100644
--- a/mcwm.man
+++ b/mcwm.man
@@ -1,4 +1,4 @@
-.TH mcwm 1 "Mar 18, 2011" "" ""
+.TH mcwm 1 "Mar 26, 2011" "" ""
.SH NAME
mcwm \- MC's Window Manager for X11.
.SH SYNOPSIS
@@ -39,9 +39,11 @@ are visible on all workspaces.
.SH USE
Nota bene: For mcwm to be at all useful you need to know how what keys
-generate the Mod1 and Mod4 modifier masks. If you don't know, use
+generate the Mod1 and Mod4 modifier masks (default). If you don't
+know, use
.B xmodmap(1)
-with the \-pm option to list them.
+with the \-pm option to list them. You can change the modifiers in
+config.h and recompiling.
With the the default configuration, use mcwm like this.
.PP
@@ -99,8 +101,9 @@ start terminal
.IP \(bu 2
.B Tab
go to next window in the current workspace window ring. If you release
-MODKEY mcwm will change focus. A new press of MODKEY + Tab will bring
-you back to the window where you last had focus.
+MODKEY or press another command key mcwm will change focus to the new
+window. A new press of MODKEY + Tab will bring you back to the window
+where you last had focus.
.IP \(bu 2
.B f
fix window so it is visible on all workspaces. Toggles. Press again to