keys.c (3571B)
1 #include <limits.h> 2 3 #include <X11/Xlib.h> 4 #include <X11/Xutil.h> 5 #include <X11/keysym.h> 6 #include <X11/XF86keysym.h> 7 #include <pango/pangoxft.h> 8 #include <X11/extensions/Xdbe.h> 9 10 #include "memory.h" 11 #include "common.h" 12 #include "txtbuf.h" 13 #include "window.h" 14 #include "keys.h" 15 16 /* FIXME: Does this break anything? */ 17 /* FIXME: ShiftMask is currently masked away when the key contains text - is this correct? */ 18 /* FIXME: The Mod*Masks can be remapped, so it isn't really clear what is what */ 19 /* LockMask and Mod2Mask in particular are disabled (caps lock and numlock usually) */ 20 static unsigned int importantmod = ShiftMask | ControlMask | Mod1Mask | Mod3Mask | Mod4Mask | Mod5Mask; 21 22 #define KEY_TEXT_INITIAL_SIZE 32 23 static char *key_text = NULL; 24 static size_t key_text_alloc = 0; 25 26 void 27 key_processing_cleanup(void) { 28 free(key_text); 29 } 30 31 int 32 match_key(unsigned int mask, unsigned int state) 33 { 34 return mask == XK_ANY_MOD || mask == (state & importantmod); 35 } 36 37 #ifdef X_HAVE_UTF8_STRING 38 #define LOOKUP_STRING_FUNC Xutf8LookupString 39 #else 40 #define LOOKUP_STRING_FUNC XmbLookupString 41 #endif 42 43 void 44 preprocess_key( 45 ledit_window *window, XKeyEvent *event, KeySym *sym_ret, 46 char **buf_ret, int *buf_len_ret) { 47 /* 48 * FIXME: I don't understand how key handling works with different keymaps. 49 * If, for instance, you run "setxkbmap pk" and then type "Ctrl+c", the 50 * keysym will be "0x1000686, Arabic_tcheh" and the appropriate string will 51 * be returned by XmbLookupString (tested also using xev). 52 * If, however, you run "setxkbmap -layout "us,pk" -option grp:shifts_toggle" 53 * and type "Ctrl+c" after switching to the pk layout, the keysym will just 54 * be "0x63, c" and XmbLookupString will return the control code sent by 55 * Ctrl+c (ascii 03). This means the handling is different depending on how 56 * the keymap is switched to, and I have no clue what the proper way to 57 * handle this would be, since the shortcuts are explicitly supposed to work 58 * properly in all language maps. My current solution is to just ignore the 59 * control key in the state so the text found by Xutf8LookupString is correct 60 * and the modifier mask can be checked separately. Please tell me if you 61 * know the proper way to do this. 62 */ 63 /* 64 * Note on the above: I guess XKB tries to be smart and map the keys back to 65 * the first language when control is pressed and multiple languages are 66 * configured. This is completely useless for ledit, though, because most 67 * keys don't use control in normal mode, and it just messes with all the 68 * keys that do use control because ledit does its own mapping. 69 */ 70 if (key_text_alloc == 0) { 71 key_text = ledit_malloc(KEY_TEXT_INITIAL_SIZE); 72 key_text_alloc = KEY_TEXT_INITIAL_SIZE; 73 } 74 event->state &= ~ControlMask; 75 76 int len = 0; 77 Status status; 78 if (window->xic && event->type == KeyPress) { 79 len = LOOKUP_STRING_FUNC(window->xic, event, key_text, key_text_alloc - 1, sym_ret, &status); 80 if (status == XBufferOverflow) { 81 key_text_alloc = ideal_array_size(key_text_alloc, len + 1); 82 key_text = ledit_realloc(key_text, key_text_alloc); 83 len = LOOKUP_STRING_FUNC(window->xic, event, key_text, key_text_alloc - 1, sym_ret, &status); 84 } 85 } else { 86 /* FIXME: anything equivalent to XBufferOverflow here? */ 87 len = XLookupString(event, key_text, key_text_alloc - 1, sym_ret, NULL); 88 status = XLookupBoth; 89 } 90 *buf_len_ret = len >= (int)key_text_alloc ? (int)key_text_alloc - 1 : len; 91 key_text[*buf_len_ret] = '\0'; 92 if (status != XLookupBoth && status != XLookupKeySym) 93 *sym_ret = NoSymbol; 94 *buf_ret = key_text; 95 }