make the modifier key code a lot better...

1) it can handle more user cases.
2) it can handle binding more modifier keys with their keysym names like Hyper and Super. W is a shortcut for Super, cuz the windows key is generally bound to it.
3) if you change your keymap bindings and reconfigure openbox it will learn your changes.
and i dunno.. its just nice and stuff now.. you can actually read it I think..
This commit is contained in:
Dana Jansens 2007-05-04 01:10:03 +00:00
parent 5784f11132
commit 7e946f68d9
7 changed files with 243 additions and 87 deletions

View file

@ -182,6 +182,8 @@ openbox_openbox_SOURCES = \
openbox/menu.c \
openbox/menu.h \
openbox/misc.h \
openbox/modkeys.c \
openbox/modkeys.h \
openbox/mouse.c \
openbox/mouse.h \
openbox/moveresize.c \

View file

@ -31,6 +31,7 @@
#include "menu.h"
#include "menuframe.h"
#include "keyboard.h"
#include "modkeys.h"
#include "mouse.h"
#include "mainloop.h"
#include "framerender.h"
@ -93,21 +94,7 @@ static gboolean menu_hide_delay_func(gpointer data);
/* The time for the current event being processed */
Time event_curtime = CurrentTime;
/*! The value of the mask for the NumLock modifier */
guint NumLockMask;
/*! The value of the mask for the ScrollLock modifier */
guint ScrollLockMask;
/*! The key codes for the modifier keys */
static XModifierKeymap *modmap;
/*! Table of the constant modifier masks */
static const gint mask_table[] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
static gint mask_table_size;
static guint ignore_enter_focus = 0;
static gboolean menu_can_hide;
#ifdef USE_SM
@ -136,31 +123,6 @@ void event_startup(gboolean reconfig)
{
if (reconfig) return;
mask_table_size = sizeof(mask_table) / sizeof(mask_table[0]);
/* get lock masks that are defined by the display (not constant) */
modmap = XGetModifierMapping(ob_display);
g_assert(modmap);
if (modmap && modmap->max_keypermod > 0) {
size_t cnt;
const size_t size = mask_table_size * modmap->max_keypermod;
/* get the values of the keyboard lock modifiers
Note: Caps lock is not retrieved the same way as Scroll and Num
lock since it doesn't need to be. */
const KeyCode num_lock = XKeysymToKeycode(ob_display, XK_Num_Lock);
const KeyCode scroll_lock = XKeysymToKeycode(ob_display,
XK_Scroll_Lock);
for (cnt = 0; cnt < size; ++cnt) {
if (! modmap->modifiermap[cnt]) continue;
if (num_lock == modmap->modifiermap[cnt])
NumLockMask = mask_table[cnt / modmap->max_keypermod];
if (scroll_lock == modmap->modifiermap[cnt])
ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
}
}
ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
#ifdef USE_SM
@ -179,7 +141,6 @@ void event_shutdown(gboolean reconfig)
#endif
client_remove_destructor(focus_delay_client_dest);
XFreeModifiermap(modmap);
}
static Window event_get_window(XEvent *e)
@ -271,54 +232,34 @@ static void event_set_curtime(XEvent *e)
event_curtime = t;
}
#define STRIP_MODS(s) \
s &= ~(LockMask | NumLockMask | ScrollLockMask), \
/* kill off the Button1Mask etc, only want the modifiers */ \
s &= (ControlMask | ShiftMask | Mod1Mask | \
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) \
static void event_hack_mods(XEvent *e)
{
#ifdef XKB
XkbStateRec xkb_state;
#endif
KeyCode *kp;
gint i, k;
switch (e->type) {
case ButtonPress:
case ButtonRelease:
STRIP_MODS(e->xbutton.state);
e->xbutton.state = modkeys_only_modifier_masks(e->xbutton.state);
break;
case KeyPress:
STRIP_MODS(e->xkey.state);
e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
break;
case KeyRelease:
STRIP_MODS(e->xkey.state);
/* remove from the state the mask of the modifier being released, if
it is a modifier key being released (this is a little ugly..) */
e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
#ifdef XKB
if (XkbGetState(ob_display, XkbUseCoreKbd, &xkb_state) == Success) {
e->xkey.state = xkb_state.compat_state;
break;
}
#endif
kp = modmap->modifiermap;
for (i = 0; i < mask_table_size; ++i) {
for (k = 0; k < modmap->max_keypermod; ++k) {
if (*kp == e->xkey.keycode) { /* found the keycode */
/* remove the mask for it */
e->xkey.state &= ~mask_table[i];
/* cause the first loop to break; */
i = mask_table_size;
break; /* get outta here! */
}
++kp;
}
}
/* remove from the state the mask of the modifier key being released,
if it is a modifier key being released that is */
e->xkey.state &= ~modkeys_keycode_to_mask(e->xkey.keycode);
break;
case MotionNotify:
STRIP_MODS(e->xmotion.state);
e->xmotion.state = modkeys_only_modifier_masks(e->xmotion.state);
/* compress events */
{
XEvent ce;

View file

@ -18,6 +18,7 @@
*/
#include "grab.h"
#include "modkeys.h"
#include "openbox.h"
#include "event.h"
#include "xerror.h"
@ -135,17 +136,20 @@ gint grab_server(gboolean grab)
void grab_startup(gboolean reconfig)
{
guint i = 0;
guint num, caps, scroll;
if (reconfig) return;
num = modkeys_key_to_mask(OB_MODKEY_KEY_NUMLOCK);
caps = modkeys_key_to_mask(OB_MODKEY_KEY_CAPSLOCK);
scroll = modkeys_key_to_mask(OB_MODKEY_KEY_SCROLLLOCK);
mask_list[i++] = 0;
mask_list[i++] = LockMask;
mask_list[i++] = NumLockMask;
mask_list[i++] = LockMask | NumLockMask;
mask_list[i++] = ScrollLockMask;
mask_list[i++] = ScrollLockMask | LockMask;
mask_list[i++] = ScrollLockMask | NumLockMask;
mask_list[i++] = ScrollLockMask | LockMask | NumLockMask;
mask_list[i++] = num;
mask_list[i++] = caps;
mask_list[i++] = scroll;
mask_list[i++] = num | caps;
mask_list[i++] = num | scroll;
mask_list[i++] = caps | scroll;
mask_list[i++] = num | caps | scroll;
g_assert(i == MASK_LIST_SIZE);
}

133
openbox/modkeys.c Normal file
View file

@ -0,0 +1,133 @@
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
modkeys.c for the Openbox window manager
Copyright (c) 2007 Dana Jansens
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file for a copy of the GNU General Public License.
*/
#include "modkeys.h"
#include "openbox.h"
#include <X11/Xlib.h>
/* These masks are constants and the modifier keys are bound to them as
anyone sees fit:
ShiftMask (1<<0), LockMask (1<<1), ControlMask (1<<2), Mod1Mask (1<<3),
Mod2Mask (1<<4), Mod3Mask (1<<5), Mod4Mask (1<<6), Mod5Mask (1<<7)
*/
#define NUM_MASKS 8
#define ALL_MASKS 0xf /* an or'ing of all 8 keyboard masks */
/* Get the bitflag for the n'th modifier mask */
#define nth_mask(n) (1 << n)
static void set_modkey_mask(guchar mask, KeySym sym);
static XModifierKeymap *modmap;
/* This is a bitmask of the different masks for each modifier key */
static guchar modkeys_keys[OB_MODKEY_NUM_KEYS];
void modkeys_startup(gboolean reconfigure)
{
/* keycodes for the modifier keys which will be bound to the masks */
gint i, j, k;
modmap = XGetModifierMapping(ob_display);
g_assert(modmap->max_keypermod > 0);
/* reset the keys to not be bound to any masks */
for (i = 0; i < OB_MODKEY_NUM_KEYS; ++i)
modkeys_keys[i] = 0;
/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */
for (i = 0; i < NUM_MASKS; ++i) {
/* go through each keycode that is bound to the mask */
for (j = 0; j < modmap->max_keypermod; ++j) {
KeySym sym;
/* get a keycode that is bound to the mask (i) */
KeyCode keycode = modmap->modifiermap[i*modmap->max_keypermod + j];
/* go through each keysym bound to the given keycode */
for (k = 0; ; ++k) {
sym = XKeycodeToKeysym(ob_display, keycode, k);
if (sym == NoSymbol) break;
/* bind the key to the mask (e.g. Alt_L => Mod1Mask) */
set_modkey_mask(nth_mask(i), sym);
}
}
}
}
void modkeys_shutdown(gboolean reconfigure)
{
XFreeModifiermap(modmap);
}
guint modkeys_keycode_to_mask(guint keycode)
{
gint i, j;
guint mask = 0;
if (keycode == NoSymbol) return 0;
/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */
for (i = 0; i < NUM_MASKS; ++i) {
/* go through each keycode that is bound to the mask */
for (j = 0; j < modmap->max_keypermod; ++j) {
/* compare with a keycode that is bound to the mask (i) */
if (modmap->modifiermap[i*modmap->max_keypermod + j] == keycode)
mask |= nth_mask(i);
}
}
return mask;
}
guint modkeys_only_modifier_masks(guint mask)
{
mask &= ALL_MASKS;
/* strip off these lock keys. they shouldn't affect key bindings */
mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_CAPSLOCK);
mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_NUMLOCK);
mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_SCROLLLOCK);
return mask;
}
guint modkeys_key_to_mask(ObModkeysKey key)
{
return modkeys_keys[key];
}
static void set_modkey_mask(guchar mask, KeySym sym)
{
/* find what key this is, and bind it to the mask */
if (sym == XK_Num_Lock)
modkeys_keys[OB_MODKEY_KEY_NUMLOCK] |= mask;
else if (sym == XK_Scroll_Lock)
modkeys_keys[OB_MODKEY_KEY_SCROLLLOCK] |= mask;
else if (sym == XK_Caps_Lock)
modkeys_keys[OB_MODKEY_KEY_CAPSLOCK] |= mask;
else if (sym == XK_Shift_L || sym == XK_Shift_R)
modkeys_keys[OB_MODKEY_KEY_SHIFT] |= mask;
else if (sym == XK_Control_L || sym == XK_Control_R)
modkeys_keys[OB_MODKEY_KEY_CONTROL] |= mask;
else if (sym == XK_Super_L || sym == XK_Super_R)
modkeys_keys[OB_MODKEY_KEY_SUPER] |= mask;
else if (sym == XK_Hyper_L || sym == XK_Hyper_R)
modkeys_keys[OB_MODKEY_KEY_HYPER] |= mask;
else if (sym == XK_Alt_L || sym == XK_Alt_R)
modkeys_keys[OB_MODKEY_KEY_ALT] |= mask;
else if (sym == XK_Meta_L || sym == XK_Meta_R)
modkeys_keys[OB_MODKEY_KEY_META] |= mask;
}

54
openbox/modkeys.h Normal file
View file

@ -0,0 +1,54 @@
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
masks.h for the Openbox window manager
Copyright (c) 2007 Dana Jansens
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file for a copy of the GNU General Public License.
*/
#ifndef ob__modkeys_h
#define ob__modkeys_h
#include <glib.h>
/*! These keys are bound to the modifier masks in any fashion */
typedef enum {
OB_MODKEY_KEY_CAPSLOCK,
OB_MODKEY_KEY_NUMLOCK,
OB_MODKEY_KEY_SCROLLLOCK,
OB_MODKEY_KEY_SHIFT,
OB_MODKEY_KEY_CONTROL,
OB_MODKEY_KEY_SUPER,
OB_MODKEY_KEY_HYPER,
OB_MODKEY_KEY_META,
OB_MODKEY_KEY_ALT,
OB_MODKEY_NUM_KEYS
} ObModkeysKey;
void modkeys_startup(gboolean reconfigure);
void modkeys_shutdown(gboolean reconfigure);
/*! Get the modifier masks for a keycode. (eg. a keycode bound to Alt_L could
return a mask of (Mod1Mask | Mask3Mask)) */
guint modkeys_keycode_to_mask(guint keycode);
/*! Strip off all modifiers except for the modifier keys. This strips stuff
like Button1Mask, and also LockMask, NumLockMask, and ScrollLockMask */
guint modkeys_only_modifier_masks(guint mask);
/*! Get the modifier masks for a modifier key. This includes both the left and
right keys when there are both. */
guint modkeys_key_to_mask(ObModkeysKey key);
#endif

View file

@ -21,6 +21,7 @@
#include "openbox.h"
#include "session.h"
#include "dock.h"
#include "modkeys.h"
#include "event.h"
#include "menu.h"
#include "client.h"
@ -215,6 +216,8 @@ gint main(gint argc, gchar **argv)
xmlDocPtr doc;
xmlNodePtr node;
modkeys_startup(reconfigure);
/* startup the parsing so everything can register sections
of the rc */
i = parse_startup();
@ -320,6 +323,7 @@ gint main(gint argc, gchar **argv)
window_shutdown(reconfigure);
event_shutdown(reconfigure);
config_shutdown();
modkeys_shutdown(reconfigure);
} while (reconfigure);
}

View file

@ -19,6 +19,7 @@
#include "openbox.h"
#include "mouse.h"
#include "modkeys.h"
#include "gettext.h"
#include <glib.h>
#include <string.h>
@ -26,20 +27,37 @@
static guint translate_modifier(gchar *str)
{
if (!g_ascii_strcasecmp("Mod1", str) ||
!g_ascii_strcasecmp("A", str)) return Mod1Mask;
else if (!g_ascii_strcasecmp("Mod2", str)) return Mod2Mask;
else if (!g_ascii_strcasecmp("Mod3", str) ||
!g_ascii_strcasecmp("M", str)) return Mod3Mask;
else if (!g_ascii_strcasecmp("Mod4", str) ||
!g_ascii_strcasecmp("W", str)) return Mod4Mask;
else if (!g_ascii_strcasecmp("Mod5", str)) return Mod5Mask;
guint mask = 0;
if (!g_ascii_strcasecmp("Mod1", str)) mask = Mod1Mask;
else if (!g_ascii_strcasecmp("Mod2", str)) mask = Mod2Mask;
else if (!g_ascii_strcasecmp("Mod3", str)) mask = Mod3Mask;
else if (!g_ascii_strcasecmp("Mod4", str)) mask = Mod4Mask;
else if (!g_ascii_strcasecmp("Mod5", str)) mask = Mod5Mask;
else if (!g_ascii_strcasecmp("Control", str) ||
!g_ascii_strcasecmp("C", str)) return ControlMask;
!g_ascii_strcasecmp("C", str))
mask = modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL);
else if (!g_ascii_strcasecmp("Alt", str) ||
!g_ascii_strcasecmp("A", str))
mask = modkeys_key_to_mask(OB_MODKEY_KEY_ALT);
else if (!g_ascii_strcasecmp("Meta", str) ||
!g_ascii_strcasecmp("M", str))
mask = modkeys_key_to_mask(OB_MODKEY_KEY_META);
/* W = windows key, is linked to the Super_L/R buttons */
else if (!g_ascii_strcasecmp("Super", str) ||
!g_ascii_strcasecmp("W", str))
mask = modkeys_key_to_mask(OB_MODKEY_KEY_SUPER);
else if (!g_ascii_strcasecmp("Shift", str) ||
!g_ascii_strcasecmp("S", str)) return ShiftMask;
g_message(_("Invalid modifier key '%s' in key/pointer binding"), str);
return 0;
!g_ascii_strcasecmp("S", str))
mask = modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT);
else if (!g_ascii_strcasecmp("Hyper", str) ||
!g_ascii_strcasecmp("H", str))
mask = modkeys_key_to_mask(OB_MODKEY_KEY_HYPER);
else
g_message(_("Invalid modifier key '%s' in key/pointer binding"), str);
return mask;
}
gboolean translate_button(const gchar *str, guint *state, guint *button)