1
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3
modkeys.c for the Openbox window manager
4
Copyright (c) 2007 Dana Jansens
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
See the COPYING file for a copy of the GNU General Public License.
23
#include <X11/keysym.h>
25
/* These masks are constants and the modifier keys are bound to them as
27
ShiftMask (1<<0), LockMask (1<<1), ControlMask (1<<2), Mod1Mask (1<<3),
28
Mod2Mask (1<<4), Mod3Mask (1<<5), Mod4Mask (1<<6), Mod5Mask (1<<7)
31
#define ALL_MASKS 0xff /* an or'ing of all 8 keyboard masks */
33
/* Get the bitflag for the n'th modifier mask */
34
#define nth_mask(n) (1 << n)
36
static void set_modkey_mask(guchar mask, KeySym sym);
38
static XModifierKeymap *modmap;
39
static KeySym *keymap;
40
static gint min_keycode, max_keycode, keysyms_per_keycode;
41
/* This is a bitmask of the different masks for each modifier key */
42
static guchar modkeys_keys[OB_MODKEY_NUM_KEYS];
44
static gboolean alt_l = FALSE;
45
static gboolean meta_l = FALSE;
46
static gboolean super_l = FALSE;
47
static gboolean hyper_l = FALSE;
49
void modkeys_startup(gboolean reconfigure)
53
/* reset the keys to not be bound to any masks */
54
for (i = 0; i < OB_MODKEY_NUM_KEYS; ++i)
57
modmap = XGetModifierMapping(ob_display);
58
g_assert(modmap->max_keypermod > 0);
60
XDisplayKeycodes(ob_display, &min_keycode, &max_keycode);
61
keymap = XGetKeyboardMapping(ob_display, min_keycode,
62
max_keycode - min_keycode + 1,
63
&keysyms_per_keycode);
65
alt_l = meta_l = super_l = hyper_l = FALSE;
67
/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */
68
for (i = 0; i < NUM_MASKS; ++i) {
69
/* go through each keycode that is bound to the mask */
70
for (j = 0; j < modmap->max_keypermod; ++j) {
72
/* get a keycode that is bound to the mask (i) */
73
KeyCode keycode = modmap->modifiermap[i*modmap->max_keypermod + j];
75
/* go through each keysym bound to the given keycode */
76
for (k = 0; k < keysyms_per_keycode; ++k) {
77
sym = keymap[(keycode-min_keycode) * keysyms_per_keycode +
79
if (sym != NoSymbol) {
80
/* bind the key to the mask (e.g. Alt_L => Mod1Mask) */
81
set_modkey_mask(nth_mask(i), sym);
88
/* CapsLock, Shift, and Control are special and hard-coded */
89
modkeys_keys[OB_MODKEY_KEY_CAPSLOCK] = LockMask;
90
modkeys_keys[OB_MODKEY_KEY_SHIFT] = ShiftMask;
91
modkeys_keys[OB_MODKEY_KEY_CONTROL] = ControlMask;
94
void modkeys_shutdown(gboolean reconfigure)
96
XFreeModifiermap(modmap);
100
guint modkeys_keycode_to_mask(guint keycode)
105
if (keycode == NoSymbol) return 0;
107
/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */
108
for (i = 0; i < NUM_MASKS; ++i) {
109
/* go through each keycode that is bound to the mask */
110
for (j = 0; j < modmap->max_keypermod; ++j) {
111
/* compare with a keycode that is bound to the mask (i) */
112
if (modmap->modifiermap[i*modmap->max_keypermod + j] == keycode)
119
guint modkeys_only_modifier_masks(guint mask)
122
/* strip off these lock keys. they shouldn't affect key bindings */
123
mask &= ~LockMask; /* use the LockMask, not what capslock is bound to,
124
because you could bind it to something else and it
125
should work as that modifier then. i think capslock
127
mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_NUMLOCK);
128
mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_SCROLLLOCK);
132
guint modkeys_key_to_mask(ObModkeysKey key)
134
return modkeys_keys[key];
137
static void set_modkey_mask(guchar mask, KeySym sym)
139
/* find what key this is, and bind it to the mask */
141
if (sym == XK_Num_Lock)
142
modkeys_keys[OB_MODKEY_KEY_NUMLOCK] |= mask;
143
else if (sym == XK_Scroll_Lock)
144
modkeys_keys[OB_MODKEY_KEY_SCROLLLOCK] |= mask;
146
else if (sym == XK_Super_L && super_l)
147
modkeys_keys[OB_MODKEY_KEY_SUPER] |= mask;
148
else if (sym == XK_Super_L && !super_l)
149
/* left takes precident over right, so erase any masks the right
151
modkeys_keys[OB_MODKEY_KEY_SUPER] = mask, super_l = TRUE;
152
else if (sym == XK_Super_R && !super_l)
153
modkeys_keys[OB_MODKEY_KEY_SUPER] |= mask;
155
else if (sym == XK_Hyper_L && hyper_l)
156
modkeys_keys[OB_MODKEY_KEY_HYPER] |= mask;
157
else if (sym == XK_Hyper_L && !hyper_l)
158
modkeys_keys[OB_MODKEY_KEY_HYPER] = mask, hyper_l = TRUE;
159
else if (sym == XK_Hyper_R && !hyper_l)
160
modkeys_keys[OB_MODKEY_KEY_HYPER] |= mask;
162
else if (sym == XK_Alt_L && alt_l)
163
modkeys_keys[OB_MODKEY_KEY_ALT] |= mask;
164
else if (sym == XK_Alt_L && !alt_l)
165
modkeys_keys[OB_MODKEY_KEY_ALT] = mask, alt_l = TRUE;
166
else if (sym == XK_Alt_R && !alt_l)
167
modkeys_keys[OB_MODKEY_KEY_ALT] |= mask;
169
else if (sym == XK_Meta_L && meta_l)
170
modkeys_keys[OB_MODKEY_KEY_META] |= mask;
171
else if (sym == XK_Meta_L && !meta_l)
172
modkeys_keys[OB_MODKEY_KEY_META] = mask, meta_l = TRUE;
173
else if (sym == XK_Meta_R && !meta_l)
174
modkeys_keys[OB_MODKEY_KEY_META] |= mask;
176
/* CapsLock, Shift, and Control are special and hard-coded */
179
KeyCode* modkeys_sym_to_code(KeySym sym)
184
ret = g_new(KeyCode, 1);
188
/* go through each keycode and look for the keysym */
189
for (i = min_keycode; i <= max_keycode; ++i)
190
for (j = 0; j < keysyms_per_keycode; ++j)
191
if (sym == keymap[(i-min_keycode) * keysyms_per_keycode + j]) {
192
ret = g_renew(KeyCode, ret, ++n + 1);