diff options
Diffstat (limited to 'src/input.c')
-rw-r--r-- | src/input.c | 231 |
1 files changed, 182 insertions, 49 deletions
diff --git a/src/input.c b/src/input.c index 64725d9..d64135f 100644 --- a/src/input.c +++ b/src/input.c @@ -28,6 +28,89 @@ #include "ratpoison.h" +/* Figure out what keysyms are attached to what modifiers */ +void +init_modifier_map () +{ + unsigned int modmasks[] = + { Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; + int row, col; /* The row and column in the modifier table. */ + XModifierKeymap *mods; + +/* rp_modifier_info.mode_switch_mask = 0; */ + rp_modifier_info.meta_mod_mask = 0; + rp_modifier_info.alt_mod_mask = 0; + rp_modifier_info.super_mod_mask = 0; + rp_modifier_info.hyper_mod_mask = 0; + + mods = XGetModifierMapping (dpy); + + for (row=3; row < 8; row++) + for (col=0; col < mods->max_keypermod; col++) + { + KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col]; + + if (code == 0) continue; + + switch (XKeycodeToKeysym(dpy, code, 0)) + { + case XK_Meta_L: + case XK_Meta_R: + rp_modifier_info.meta_mod_mask |= modmasks[row - 3]; + PRINT_DEBUG ("Found Meta on %d\n", + rp_modifier_info.meta_mod_mask); + break; + + case XK_Alt_L: + case XK_Alt_R: + rp_modifier_info.alt_mod_mask |= modmasks[row - 3]; + PRINT_DEBUG ("Found Alt on %d\n", + rp_modifier_info.alt_mod_mask); + break; + + case XK_Super_L: + case XK_Super_R: + rp_modifier_info.super_mod_mask |= modmasks[row - 3]; + PRINT_DEBUG ("Found Super on %d\n", + rp_modifier_info.super_mod_mask); + break; + + case XK_Hyper_L: + case XK_Hyper_R: + rp_modifier_info.hyper_mod_mask |= modmasks[row - 3]; + PRINT_DEBUG ("Found Hyper on %d\n", + rp_modifier_info.hyper_mod_mask); + break; + +/* case XK_Mode_switch: */ +/* rp_modifier_info.mode_switch_mask |= modmasks[row - 3]; */ +/* PRINT_DEBUG ("Found Mode_switch on %d\n", */ +/* rp_modifier_info.mode_switch_mask); */ +/* break; */ + + default: + break; + } + } + + /* Stolen from Emacs 21.0.90 - xterm.c */ + /* If we couldn't find any meta keys, accept any alt keys as meta keys. */ + if (! rp_modifier_info.meta_mod_mask) + { + rp_modifier_info.meta_mod_mask = rp_modifier_info.alt_mod_mask; + rp_modifier_info.alt_mod_mask = 0; + } + + /* If some keys are both alt and meta, + make them just meta, not alt. */ + if (rp_modifier_info.alt_mod_mask & rp_modifier_info.meta_mod_mask) + { + rp_modifier_info.alt_mod_mask &= ~rp_modifier_info.meta_mod_mask; + } + + XFreeModifiermap (mods); +} + /* Return the name of the keysym. caller must free returned pointer */ char * keysym_to_string (KeySym keysym, unsigned int modifier) @@ -63,63 +146,107 @@ keysym_to_string (KeySym keysym, unsigned int modifier) /* Cooks a keycode + modifier into a keysym + modifier. This should be used anytime meaningful key information is to be extracted from a - KeyPress or KeyRelease event. */ -void -cook_keycode (KeyCode keycode, KeySym *keysym, unsigned int *mod) + KeyPress or KeyRelease event. + + returns the number of bytes in keysym_name. If you are not + interested in the keysym name pass in NULL for keysym_name and 0 + for len. */ +int +cook_keycode (XKeyEvent *ev, KeySym *keysym, unsigned int *mod, char *keysym_name, int len) { - KeySym normal, shifted; +int nbytes; - normal = XKeycodeToKeysym(dpy, keycode, 0); - shifted = XKeycodeToKeysym(dpy, keycode, 1); + nbytes = XLookupString (ev, keysym_name, len, keysym, NULL); - /* FIXME: eew, this looks gross. */ - if (*mod & (ShiftMask | LockMask)) - { - /* if the shifted code is not defined, then we use the normal - keysym and keep the shift mask */ - if (shifted == NoSymbol) - { - *keysym = normal; - } - /* But if the shifted code is defined, we use it and remove the - shift mask */ - else if (*mod & ShiftMask) - { - *keysym = shifted; - *mod &= ~(ShiftMask | LockMask); - } - /* If caps lock is on, use shifted for alpha keys */ - else if (normal >= XK_a - && normal <= XK_z - && *mod & LockMask) - { - *keysym = shifted; - } - else - { - *keysym = normal; - } - } - else - { - *keysym = normal; - } + *mod = ev->state; + *mod &= (rp_modifier_info.meta_mod_mask + | rp_modifier_info.alt_mod_mask + | rp_modifier_info.hyper_mod_mask + | rp_modifier_info.super_mod_mask + | ControlMask ); - PRINT_DEBUG ("cooked keysym: %ld '%c' mask: %d\n", - *keysym, (char)*keysym, *mod); + return nbytes; } -void -read_key (KeySym *keysym, unsigned int *modifiers) +/* void */ +/* cook_keycode (KeyCode keycode, KeySym *keysym, unsigned int *mod) */ +/* { */ +/* KeySym normal, shifted; */ + +/* /\* FIXME: Although this should theoretically work, the mod that */ +/* mode_switch is on doesn't seem to get activated. Instead the */ +/* 2<<13 bit gets set! It doesn't seem to matter which mod I put */ +/* Mode_switch on. So if this doesn't work try uncommented the line */ +/* below and commented the current one. *\/ */ + +/* /\* if (*mod & 8192) *\/ */ +/* if (*mod & rp_modifier_info.mode_switch_mask) */ +/* { */ +/* normal = XKeycodeToKeysym(dpy, keycode, 2); */ +/* if (normal == NoSymbol) normal = XKeycodeToKeysym(dpy, keycode, 0); */ +/* shifted = XKeycodeToKeysym(dpy, keycode, 3); */ +/* if (shifted == NoSymbol) shifted = XKeycodeToKeysym(dpy, keycode, 1); */ + +/* /\* Remove the mode switch modifier since we have dealt with it. *\/ */ +/* *mod &= ~rp_modifier_info.mode_switch_mask; */ +/* } */ +/* else */ +/* { */ +/* normal = XKeycodeToKeysym(dpy, keycode, 0); */ +/* shifted = XKeycodeToKeysym(dpy, keycode, 1); */ +/* } */ + +/* /\* FIXME: eew, this looks gross. *\/ */ +/* if (*mod & (ShiftMask | LockMask)) */ +/* { */ +/* /\* if the shifted code is not defined, then we use the normal */ +/* keysym and keep the shift mask *\/ */ +/* if (shifted == NoSymbol) */ +/* { */ +/* *keysym = normal; */ +/* } */ +/* /\* But if the shifted code is defined, we use it and remove the */ +/* shift mask *\/ */ +/* else if (*mod & ShiftMask) */ +/* { */ +/* *keysym = shifted; */ +/* *mod &= ~(ShiftMask | LockMask); */ +/* } */ +/* /\* If caps lock is on, use shifted for alpha keys *\/ */ +/* else if (normal >= XK_a */ +/* && normal <= XK_z */ +/* && *mod & LockMask) */ +/* { */ +/* *keysym = shifted; */ +/* } */ +/* else */ +/* { */ +/* *keysym = normal; */ +/* } */ +/* } */ +/* else */ +/* { */ +/* *keysym = normal; */ +/* } */ + +/* PRINT_DEBUG ("cooked keysym: %ld '%c' mask: %d\n", */ +/* *keysym, (char)*keysym, *mod); */ +/* } */ + +int +read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) { XEvent ev; + int nbytes; do { XMaskEvent (dpy, KeyPressMask, &ev); *modifiers = ev.xkey.state; - cook_keycode (ev.xkey.keycode, keysym, modifiers); + nbytes = cook_keycode (&ev.xkey, keysym, modifiers, keysym_name, len); } while (IsModifierKey (*keysym)); + + return nbytes; } static void @@ -162,6 +289,10 @@ get_input (char *prompt) char * get_more_input (char *prompt, char *preinput) { + /* Emacs 21 uses a 513 byte string to store the keysym name. */ + char keysym_buf[513]; + int keysym_bufsize = sizeof (keysym_buf); + int nbytes; screen_info *s = current_screen (); int cur_len = 0; /* Current length of the string. */ int allocated_len=100; /* The amount of memory we allocated for str */ @@ -192,7 +323,7 @@ get_more_input (char *prompt, char *preinput) /* XSync (dpy, False); */ - read_key (&ch, &modifier); + nbytes = read_key (&ch, &modifier, keysym_buf, keysym_bufsize); while (ch != XK_Return) { PRINT_DEBUG ("key %ld\n", ch); @@ -203,18 +334,20 @@ get_more_input (char *prompt, char *preinput) } else { - if (cur_len > allocated_len - 1) + if (cur_len + nbytes > allocated_len - 1) { - allocated_len += 100; + allocated_len += nbytes + 100; str = xrealloc ( str, allocated_len ); } - str[cur_len] = ch; - cur_len++; + + strncpy (&str[cur_len], keysym_buf, nbytes); +/* str[cur_len] = ch; */ + cur_len+=nbytes; update_input_window(s, prompt, str, cur_len); } - read_key (&ch, &modifier); + nbytes = read_key (&ch, &modifier, keysym_buf, keysym_bufsize); } str[cur_len] = 0; |