"Fossies" - the Fresh Open Source Software Archive

Member "dosemu-1.4.0/src/plugin/X/keyb_X.c" (4 May 2007, 10078 Bytes) of package /linux/misc/old/dosemu-1.4.0.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "keyb_X.c" see the Fossies "Dox" file reference documentation.

    1 /* 
    2  * All modifications in this file to the original code are
    3  * (C) Copyright 1992, ..., 2007 the "DOSEMU-Development-Team".
    4  *
    5  * for details see file COPYING.DOSEMU in the DOSEMU distribution
    6  */
    7 
    8 /*
    9 This file contains X keyboard tables and handling routines
   10 for dosemu. 
   11   exports:  X_process_key(XKeyEvent *)
   12             X_process_keys(XKmapmapEvent *);
   13   uses:     putkey(t_scancode scan, Boolean make, uchar charcode)
   14     
   15 ******************************************************************
   16   
   17 Part of the original code in this file was taken from pcemu written by David Hedley 
   18 (hedley@cs.bris.ac.uk).
   19 
   20 Since this code has been totally rewritten the pcemu license no longer applies
   21 ***********************************************************************
   22 */
   23 
   24 #include "config.h"
   25 #include <X11/X.h>
   26 #include <X11/Xlib.h>
   27 #include <X11/Xutil.h>
   28 #include <X11/keysym.h>
   29 #if HAVE_XKB
   30 #include <X11/XKBlib.h>
   31 #endif
   32 
   33 #include "X.h"
   34 #include "emu.h"
   35 #include "keyb_clients.h"
   36 #include "keyboard.h"
   37 #include "video.h"
   38 #include "translate.h"
   39 #include "keysym_attributes.h"
   40 #include "keyb_X.h"
   41 #include "translate.h"
   42 
   43 struct modifier_info X_mi;
   44 static struct char_set_state X_charset;
   45 
   46 static int get_modifier_mask(XModifierKeymap *map, int keycode)
   47 {
   48     int i;
   49     KeyCode *kcp;
   50     kcp = map->modifiermap;
   51     for(i = 0; i < 8; i++) {
   52         int j;
   53         for(j = 0; j < map->max_keypermod; j++, kcp++) {
   54             if (*kcp == 0) 
   55                 continue;
   56             if (*kcp == keycode)
   57                 return 1 << i;
   58         }
   59     }
   60     return 0;
   61 }
   62 
   63 static void X_modifier_info_init(Display *display)
   64 {
   65     XModifierKeymap *map;
   66 
   67     /* Initialize the modifier info */
   68     /* Only the CapsLockMask is precomputed */
   69     X_mi.CapsLockMask = LockMask;
   70     X_mi.CapsLockKeycode = XKeysymToKeycode(display, XK_Caps_Lock);
   71     X_mi.NumLockMask = 0; 
   72     X_mi.NumLockKeycode = XKeysymToKeycode(display, XK_Num_Lock);
   73     X_mi.ScrollLockMask = 0; 
   74     X_mi.ScrollLockKeycode = XKeysymToKeycode(display, XK_Scroll_Lock);
   75     X_mi.AltMask = 0;
   76     X_mi.AltGrMask = 0;
   77     X_mi.InsLockMask = 0;
   78     
   79 
   80     map = XGetModifierMapping(display);
   81 
   82     X_mi.NumLockMask = get_modifier_mask(map, X_mi.NumLockKeycode);
   83     X_mi.ScrollLockMask = get_modifier_mask(map, X_mi.ScrollLockKeycode);
   84 
   85     if (!X_mi.AltMask) {
   86         X_mi.AltMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_Alt_L));
   87     }
   88     if (!X_mi.AltMask) {
   89         X_mi.AltMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_Alt_R));
   90     }
   91     if (!X_mi.AltMask) {
   92         X_mi.AltMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_Meta_L));
   93     }
   94     if (!X_mi.AltMask) {
   95         X_mi.AltMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_Meta_R));
   96     }
   97     if (!X_mi.AltGrMask) {
   98         X_mi.AltGrMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_Mode_switch));
   99     }
  100     if (!X_mi.AltGrMask) {
  101         X_mi.AltGrMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_Multi_key));
  102     }
  103     if (!X_mi.InsLockMask) {
  104         X_mi.InsLockMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_Insert));
  105     }
  106     if (!X_mi.InsLockMask) {
  107         X_mi.InsLockMask = get_modifier_mask(map, XKeysymToKeycode(display, XK_KP_Insert));
  108     }
  109     
  110 
  111     X_printf("X: CapsLockMask = 0x%x\n", X_mi.CapsLockMask);
  112     X_printf("X: CapsLockKeycode = 0x%x\n", X_mi.CapsLockKeycode);
  113     X_printf("X: NumLockMask = 0x%x\n", X_mi.NumLockMask);
  114     X_printf("X: NumLockKeycode = 0x%x\n", X_mi.NumLockKeycode);
  115     X_printf("X: ScrollLockMask = 0x%x\n", X_mi.ScrollLockMask);
  116     X_printf("X: ScrollLockKeycode = 0x%x\n", X_mi.ScrollLockKeycode);
  117     X_printf("X: AltMask = 0x%x\n", X_mi.AltMask);
  118     X_printf("X: AltGrMask = 0x%x\n", X_mi.AltGrMask);
  119     X_printf("X: InsLockMask = 0x%x\n", X_mi.InsLockMask);
  120 
  121     XFreeModifiermap(map);
  122 }
  123 
  124 static void keyb_X_init(Display *display)
  125 {
  126     X_modifier_info_init(display);
  127     init_charset_state(&X_charset, lookup_charset("X_keysym"));
  128 }
  129 
  130 static int use_move_key(t_keysym key)
  131 {
  132     int result = FALSE;
  133     /* If it's some kind of function key move it
  134      * otherwise just make sure it gets pressed
  135      */
  136     if (is_keysym_function(key) ||
  137         is_keysym_dosemu_key(key) ||
  138         is_keypad_keysym(key) ||
  139         (key == KEY_TAB) ||
  140         (key == KEY_RETURN) ||
  141         (key == KEY_BKSP)) {
  142         result = TRUE;
  143     }
  144     return result;
  145 }
  146 
  147 static t_modifiers map_X_modifiers(unsigned int e_state)
  148 {
  149     t_modifiers modifiers = 0;
  150     if (e_state & ShiftMask) {
  151         modifiers |= MODIFIER_SHIFT;
  152     }
  153     if (e_state & ControlMask) {
  154         modifiers |= MODIFIER_CTRL;
  155     }
  156     if (e_state & X_mi.AltMask) {
  157         modifiers |= MODIFIER_ALT;
  158     }
  159     if (e_state & X_mi.AltGrMask) {
  160         modifiers |= MODIFIER_ALTGR;
  161     }
  162     if (e_state & X_mi.CapsLockMask) {
  163         modifiers |= MODIFIER_CAPS;
  164     }
  165     if (e_state & X_mi.NumLockMask) {
  166         modifiers |= MODIFIER_NUM;
  167     }
  168     if (e_state & X_mi.ScrollLockMask) {
  169         modifiers |= MODIFIER_SCR;
  170     }
  171     if (e_state & X_mi.InsLockMask) {
  172         modifiers |= MODIFIER_INS;
  173     }
  174     return modifiers;
  175 }
  176 
  177 void X_sync_shiftstate(Boolean make, KeyCode kc, unsigned int e_state)
  178 {
  179     t_modifiers shiftstate = get_shiftstate();
  180 
  181     /* caps&num&scroll lock are special in the core X protocol: press/release means
  182        turning lock on/off, not pressing/releasing the key.
  183        With XKB they are no longer special.  To handle it correclty every time,
  184        and to make the code simple we just sync up the shiftstates before the
  185        keys are pressed.
  186        Note:
  187        The reason we don't generate extra internal key events when doing this
  188        is that for shift keys, X doesn't report the new shift state until
  189        the next key event.  So unless gets off somewhere (missed key events
  190        or the strange event handling for the core X protocol, this code will
  191        never have anything to do).
  192        Note2:
  193        This does depend upon Numlock, CapsLock, & co all being bound to
  194        X modifiers, but this assumption is rarely violated.
  195        Note3:
  196        For NumLock & CapsLock the state doesn't change until after the release
  197        event, for the disable.  So we don't sync on the release event to prevent
  198        unnecessary key events from being sent.
  199     */
  200     
  201     /* Check for modifiers released outside this window */
  202     if (!!(shiftstate & MODIFIER_SHIFT) != !!(e_state & ShiftMask)) {
  203         shiftstate ^= MODIFIER_SHIFT;
  204     }
  205     if (!!(shiftstate & MODIFIER_CTRL) != !!(e_state & ControlMask)) {
  206         shiftstate ^= MODIFIER_CTRL;
  207     }
  208     if (X_mi.AltMask && (
  209         !!(shiftstate & MODIFIER_ALT) != !!(e_state & X_mi.AltMask))) {
  210         shiftstate ^= MODIFIER_ALT;
  211     }
  212 
  213     if (!config.X_keycode) {
  214     /* NOTE: AltGr usually performs a layout switching, so we don't touch
  215      * it here for X_keycode
  216      */
  217       if (X_mi.AltGrMask && (
  218         !!(shiftstate & MODIFIER_ALTGR) != !!(e_state & X_mi.AltGrMask))) {
  219         shiftstate ^= MODIFIER_ALTGR;
  220       }
  221     }
  222 
  223     if (X_mi.CapsLockMask && 
  224         (!!(shiftstate & MODIFIER_CAPS) != !!(e_state & X_mi.CapsLockMask))
  225         && (make || (kc != X_mi.CapsLockKeycode))) {
  226         shiftstate ^= MODIFIER_CAPS;
  227     }
  228     if (X_mi.NumLockMask &&
  229         (!!(shiftstate & MODIFIER_NUM) != !!(e_state & X_mi.NumLockMask))
  230         && (make || (kc != X_mi.NumLockKeycode))) {
  231         shiftstate ^= MODIFIER_NUM;
  232     }
  233     if (X_mi.ScrollLockMask &&
  234         (!!(shiftstate & MODIFIER_SCR) != !!(e_state & X_mi.ScrollLockMask))
  235         && (make || (kc != X_mi.ScrollLockKeycode))) {
  236         shiftstate ^= MODIFIER_SCR;
  237     }
  238     if (X_mi.InsLockMask && (
  239         !!(shiftstate & MODIFIER_INS) != !!(e_state & X_mi.InsLockMask))) {
  240         shiftstate ^= MODIFIER_INS;
  241     }
  242     set_shiftstate(shiftstate);
  243 }
  244 
  245 static int initialized= 0;
  246 void X_process_keys(XKeymapEvent *e)
  247 {
  248     if (!initialized) {
  249         keyb_X_init(display);
  250         initialized = 1;
  251     }
  252     if (config.X_keycode) {
  253         X_keycode_process_keys(e);
  254         return;
  255     }
  256 }
  257 
  258 void map_X_event(Display *display, XKeyEvent *e, struct mapped_X_event *result)
  259 {
  260     KeySym xkey;
  261     unsigned int modifiers;
  262     /* modifiers should be set to the (currently active) modifiers that were not used
  263      * to generate the X KeySym.  This allows for cases like Ctrl-A to be generate
  264      * the correct codes for dos, even though X does not for explicit support for
  265      * that combination.
  266      */
  267 
  268     if (!USING_XKB) {
  269         #define MAXCHARS 3
  270         unsigned char chars[MAXCHARS];
  271         int count;
  272         static XComposeStatus compose_status = {NULL, 0};
  273 
  274         count = XLookupString(e, chars, MAXCHARS, &xkey, &compose_status);
  275         /* Guess all modifiers were not used in generating the symbol.
  276          * If the dos keyboard layout and the X keyboard layout are
  277          * the same this has no ill effects.  If the layouts are
  278          * different this is only wrong half the time.
  279          * Using XKB we can do better.
  280          */
  281         modifiers = e->state;
  282     }
  283 #if HAVE_XKB
  284     else {
  285         xkey = XK_VoidSymbol;
  286         modifiers = 0; /* get set to the modifers to clear... */
  287 
  288         XkbLookupKeySym(display, e->keycode, e->state, &modifiers, &xkey);
  289         modifiers = e->state & (~modifiers);
  290     }
  291 #endif
  292     charset_to_unicode(&X_charset, &result->key, 
  293         (const char *)&xkey, sizeof(xkey));
  294     result->make = (e->type == KeyPress);
  295     result->modifiers = map_X_modifiers(modifiers);
  296     X_printf("X: key_event: %02x %08x %8s sym: %04x -> %04x %08x\n",
  297         e->keycode,
  298         e->state,
  299         result->make?"pressed":"released",
  300         (unsigned)xkey,
  301         result->key,
  302         result->modifiers);
  303 }
  304 
  305 void X_process_key(XKeyEvent *e)
  306 {
  307     struct mapped_X_event event;
  308     
  309     if (!initialized) {
  310         keyb_X_init(display);
  311         initialized = 1;
  312     }
  313     if (config.X_keycode) {
  314         X_keycode_process_key(e);
  315         return;
  316     }
  317     map_X_event(display, e, &event);
  318 
  319     X_sync_shiftstate(event.make, e->keycode, e->state);
  320     /* If the key is just a ``function'' key just wiggle the key
  321      * with the appropriate keysym in the dos keyboard layout.
  322      * This allows for full interpretation of currently active modifiers.
  323      *
  324      * Otherwise if the key can host multiple keysyms and is not fixed,
  325      * make an educated guess on how to press the key.  This allows
  326      * much more limited freedom for interpreting the modifiers.
  327      */
  328     if (!use_move_key(event.key) || (move_key(event.make, event.key) < 0)) {
  329         put_modified_symbol(event.make, event.modifiers, event.key);
  330     }
  331 }
  332 
  333 static int probe_X_keyb(void)
  334 {
  335     int result = FALSE;
  336     if (Video == &Video_X) {
  337         result = TRUE;
  338     }
  339     return result;
  340 }
  341 
  342 struct keyboard_client Keyboard_X =  {
  343     "X11",          /* name */
  344     probe_X_keyb,       /* probe */
  345     NULL,           /* init */
  346     NULL,           /* reset */
  347     NULL,           /* close */
  348     NULL,           /* run */       /* the X11 event handler is run seperately */
  349     NULL,           /* set_leds */
  350 };