summaryrefslogtreecommitdiff
path: root/i3lock.c
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2012-03-10 16:41:42 +0100
committerMichael Stapelberg <michael@stapelberg.de>2012-03-10 16:42:10 +0100
commitb5bbd2fe048e8aa44c619cd8ec8c2691ee142d2d (patch)
treeb23767df60cea5d53802f096e7e5e70e53abc3f6 /i3lock.c
parent6cb93c9bd89cb64243fc7201a15c760ac95aa19d (diff)
Properly handle Caps Lock (Thanks Damien)
Diffstat (limited to 'i3lock.c')
-rw-r--r--i3lock.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/i3lock.c b/i3lock.c
index 30922eb..e3d1e76 100644
--- a/i3lock.c
+++ b/i3lock.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <security/pam_appl.h>
/* FIXME: can we get rid of this header? */
+#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <getopt.h>
#include <string.h>
@@ -51,6 +52,8 @@ static bool modeswitch_active = false;
static bool iso_level3_shift_active = false;
static bool iso_level5_shift_active = false;
static int numlockmask;
+static int shiftlockmask;
+static int capslockmask;
static bool beep = false;
static bool debug_mode = false;
static bool dpms = false;
@@ -282,13 +285,47 @@ static void handle_key_press(xcb_key_press_event_t *event) {
if ((input_position + 8) >= sizeof(password))
return;
+ /* Whether the user currently holds down the shift key. */
+ bool shift = (event->state & XCB_MOD_MASK_SHIFT);
+
+ /* Whether Caps Lock (all lowercase alphabetic keys will be replaced by
+ * their uppercase variant) is active at the moment. */
+ bool capslock = (event->state & capslockmask);
+
+ /* Whether Shift Lock (shift state is reversed) is active at the moment. */
+ bool shiftlock = (event->state & shiftlockmask);
+
+ /* Whether Caps Lock or Shift Lock is active at the moment. */
+ bool lock = (capslock || shiftlock);
+
+ DEBUG("shift = %d, lock = %d, capslock = %d, shiftlock = %d\n",
+ shift, lock, capslock, shiftlock);
+
if ((event->state & numlockmask) && xcb_is_keypad_key(sym1)) {
/* this key was a keypad key */
- if ((event->state & XCB_MOD_MASK_SHIFT))
+ if (shift || shiftlock)
sym = sym0;
else sym = sym1;
} else {
- if ((event->state & XCB_MOD_MASK_SHIFT))
+ xcb_keysym_t upper, lower;
+ XConvertCase(sym0, (KeySym*)&lower, (KeySym*)&upper);
+ DEBUG("sym0 = %c (%d), sym1 = %c (%d), lower = %c (%d), upper = %c (%d)\n",
+ sym0, sym0, sym1, sym1, lower, lower, upper, upper);
+ /* If there is no difference between the uppercase and lowercase
+ * variant of this key, we consider Caps Lock off — it is only relevant
+ * for alphabetic keys, unlike Shift Lock. */
+ if (lower == upper) {
+ capslock = false;
+ lock = (capslock || shiftlock);
+ DEBUG("lower == upper, now shift = %d, lock = %d, capslock = %d, shiftlock = %d\n",
+ shift, lock, capslock, shiftlock);
+ }
+
+ /* In two different cases we need to use the uppercase keysym:
+ * 1) The user holds shift, no lock is active.
+ * 2) Any of the two locks is active.
+ */
+ if ((shift && !lock) || (!shift && lock))
sym = sym1;
else sym = sym0;
}
@@ -667,6 +704,11 @@ int main(int argc, char *argv[]) {
symbols = xcb_key_symbols_alloc(conn);
numlockmask = get_mod_mask(conn, symbols, XK_Num_Lock);
+ shiftlockmask = get_mod_mask(conn, symbols, XK_Shift_Lock);
+ capslockmask = get_mod_mask(conn, symbols, XK_Caps_Lock);
+
+ DEBUG("shift lock mask = %d\n", shiftlockmask);
+ DEBUG("caps lock mask = %d\n", capslockmask);
if (dpms)
dpms_turn_off_screen(conn);