source: tags/arb_5.2/WINDOW/AW_xkey.cxx

Last change on this file was 6073, checked in by westram, 15 years ago
  • if NUMLOCK is on and user presses an 'ALT-a .. ALT-z'-key, warn once about NUMLOCK
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1#include <stdio.h>
2#include <string.h>
3
4#include <X11/Xlib.h>
5#include <X11/keysym.h>
6#include <X11/Xutil.h>
7
8#include "aw_keysym.hxx"
9#include "aw_xkey.hxx"
10#include "aw_root.hxx"
11#include <arbdbt.h>
12
13#ifndef aw_assert
14#ifndef ARB_ASSERT_H
15#include <arb_assert.h>
16#endif
17#define aw_assert(bed) arb_assert(bed)
18#endif
19
20// for keysyms see /usr/include/X11/keysymdef.h
21
22
23// each entry in awxkeymap_modfree generates 9 entries : 2*SHIFT, 2*ALT, 2*META, 2*CTRL, 1 unMODified
24// see awModDef below
25static awXKeymap_modfree awxkeymap_modfree[] = {
26    { XK_Left,   "Left",   AW_KEY_LEFT },
27    { XK_Right,  "Right",  AW_KEY_RIGHT },
28    { XK_Up,     "Up",     AW_KEY_UP },
29    { XK_Down,   "Down",   AW_KEY_DOWN },
30    { XK_Home,   "Home",   AW_KEY_HOME },
31    { XK_End,    "End",    AW_KEY_END },
32    { XK_Delete, "Delete", AW_KEY_DELETE }, // was same as BackSpace in the past -- 2007/11/15
33   
34    { 0, 0, AW_KEY_NONE }, 
35};
36
37// manual key defs
38// keys where all (or most) modifiers dont work should go here
39static awXKeymap awxkeymap[] = {
40    // sun keypad ?
41    { XK_Shift_R, XK_R10, "Shift-Left",  AW_KEYMODE_SHIFT, AW_KEY_LEFT,  0},
42    { XK_Shift_R, XK_R12, "Shift-Right", AW_KEYMODE_SHIFT, AW_KEY_RIGHT, 0},
43    { XK_Shift_L, XK_R10, "Shift-Left",  AW_KEYMODE_SHIFT, AW_KEY_LEFT,  0},
44    { XK_Shift_L, XK_R12, "Shift-Right", AW_KEYMODE_SHIFT, AW_KEY_RIGHT, 0},
45    { 0,          XK_R7,  "Home",        AW_KEYMODE_NONE,  AW_KEY_HOME,  0},
46    { 0,          XK_R13, "End",         AW_KEYMODE_NONE,  AW_KEY_END,   0},
47
48    // functions keys
49    { 0, XK_F1,  0, AW_KEYMODE_NONE, AW_KEY_F1,  0},
50    { 0, XK_F2,  0, AW_KEYMODE_NONE, AW_KEY_F2,  0},
51    { 0, XK_F3,  0, AW_KEYMODE_NONE, AW_KEY_F3,  0},
52    { 0, XK_F4,  0, AW_KEYMODE_NONE, AW_KEY_F4,  0},
53    { 0, XK_F5,  0, AW_KEYMODE_NONE, AW_KEY_F5,  0},
54    { 0, XK_F6,  0, AW_KEYMODE_NONE, AW_KEY_F6,  0},
55    { 0, XK_F7,  0, AW_KEYMODE_NONE, AW_KEY_F7,  0},
56    { 0, XK_F8,  0, AW_KEYMODE_NONE, AW_KEY_F8,  0},
57    { 0, XK_F9,  0, AW_KEYMODE_NONE, AW_KEY_F9,  0},
58    { 0, XK_F10, 0, AW_KEYMODE_NONE, AW_KEY_F10, 0},
59    { 0, XK_F11, 0, AW_KEYMODE_NONE, AW_KEY_F11, 0},
60    { 0, XK_F12, 0, AW_KEYMODE_NONE, AW_KEY_F12, 0},
61
62    // other
63    { 0, XK_BackSpace, "BackSpace", AW_KEYMODE_NONE, AW_KEY_BACKSPACE, 0},
64    { 0, XK_Help,      0,           AW_KEYMODE_NONE, AW_KEY_HELP,      0},
65    { 0, XK_Escape,    0,           AW_KEYMODE_NONE, AW_KEY_ESCAPE,    0},
66    { 0, XK_Return,    0,           AW_KEYMODE_NONE, AW_KEY_RETURN,    0},
67    { 0, XK_Tab,       0,           AW_KEYMODE_NONE, AW_KEY_RETURN,    0}, // done to accept input-field-changes via TAB, also disables inserting tabs
68
69    { 0, 0, (char*)1, AW_KEYMODE_NONE, AW_KEY_NONE, 0}
70};
71
72static GB_HASH  *awxkeymap_string_2_key_hash;
73static GB_HASHI *awxkeymap_xkey_2_key_hash;
74
75const int KEYMAX = 100; // size for hashes
76
77#if defined(DEBUG)
78static int mappedKeys = 0;
79#endif
80
81static void map_awXKey(Display *display, const awXKeymap *awxk) {
82    if (awxk->xstr) {
83        KeySym modlist[2];
84        int    modsize;
85
86        modlist[0] = awxk->xmod;
87        modsize    = modlist[0] ? 1 : 0;
88
89        XRebindKeysym(display, awxk->xkey, modlist, modsize,
90                      (unsigned char*)awxk->xstr, strlen(awxk->xstr));
91
92        GBS_write_hash(awxkeymap_string_2_key_hash, awxk->xstr, (long)awxk);
93    }
94    GBS_write_hashi(awxkeymap_xkey_2_key_hash, awxk->xkey, (long)awxk);
95
96#if defined(DEBUG)
97    ++mappedKeys;
98#endif // DEBUG
99}
100
101void aw_install_xkeys(Display *display) {
102    int i;
103   
104    awxkeymap_string_2_key_hash = GBS_create_hash(KEYMAX, GB_MIND_CASE);
105    awxkeymap_xkey_2_key_hash   = GBS_create_hashi(KEYMAX);
106
107    // auto-generate all key/modifier combinations for keys in awxkeymap_modfree
108    for (i=0;;++i) {
109        if (awxkeymap_modfree[i].xstr_suffix == 0) break;
110    }
111
112    const int MODS = 9;         // (2*SHIFT, 2*ALT, 2*META, 2*CTRL, 1 unMODified)
113
114    struct awModDef {
115        int         xmod;
116        const char *xstr_prefix;
117        AW_key_mod  awmod;
118    } 
119    moddef[MODS] = {
120        { XK_Shift_L,   "Shift",   AW_KEYMODE_SHIFT },
121        { XK_Shift_R,   "Shift",   AW_KEYMODE_SHIFT },
122        { XK_Meta_L,    "Meta",    AW_KEYMODE_ALT },     // handle Meta as Alt
123        { XK_Meta_R,    "Meta",    AW_KEYMODE_ALT },
124        { XK_Alt_L,     "Alt",     AW_KEYMODE_ALT },
125        { XK_Alt_R,     "Alt",     AW_KEYMODE_ALT },
126        { XK_Control_L, "Control", AW_KEYMODE_CONTROL },
127        { XK_Control_R, "Control", AW_KEYMODE_CONTROL },
128        { 0,            0,         AW_KEYMODE_NONE },
129    };
130
131    int modfree = i;
132    int gensize = modfree*MODS;
133
134    static awXKeymap *generated = 0;
135
136    aw_assert(generated == 0);  // oops - called twice
137    generated = (awXKeymap*)GB_calloc(gensize, sizeof(*generated)); // never freed (cause hashes refers to it)
138
139    for (i=0;i<modfree;++i) {
140        const awXKeymap_modfree *mf = awxkeymap_modfree+i;
141        for (int j = 0; j<MODS; ++j) {
142            awXKeymap *km = generated+i*MODS+j;
143            awModDef  *md = moddef+j;
144
145            km->xmod  = md->xmod;
146            km->xkey  = mf->xkey;
147            km->xstr  = md->xstr_prefix ? GBS_global_string_copy("%s-%s", md->xstr_prefix, mf->xstr_suffix) : mf->xstr_suffix;
148            km->awmod = md->awmod;
149            km->awkey = mf->awkey;
150            km->awstr = 0;
151
152            map_awXKey(display, km);
153        }
154    }
155
156    // add manually defined keys
157    for (i=0;;++i) {
158        if (awxkeymap[i].xstr== (char*)1) break;
159        map_awXKey(display, awxkeymap+i);
160    }
161
162    aw_assert(mappedKeys<KEYMAX);
163}
164
165#if defined(DEBUG)
166//#define DUMP_KEYEVENTS
167#endif // DEBUG
168
169const awXKeymap *aw_xkey_2_awkey(XKeyEvent *xkeyevent) {
170    awXKeymap *result;
171    static awXKeymap singlekey = { 0,0,0,AW_KEYMODE_NONE,AW_KEY_NONE,0};
172    bool numlockwason = false;
173
174    if (xkeyevent->state & AW_KEYMODE_NUMLOCK) {    // numlock is active
175        xkeyevent->state &= ~AW_KEYMODE_NUMLOCK;    // ignore NUMLOCK
176        numlockwason      = true;
177    }
178
179    static char    buffer[256];
180    KeySym         keysym;
181    XComposeStatus compose;
182    int            count = XLookupString(xkeyevent,buffer,256,&keysym,&compose);
183    buffer[count]        = 0;
184
185#if defined(DUMP_KEYEVENTS)
186    printf("state=%u keycode=%u name='%s' ", xkeyevent->state, xkeyevent->keycode, buffer);
187#endif // DUMP_KEYEVENTS
188
189    if( keysym >= XK_space && keysym <= XK_asciitilde ) {
190        singlekey.awkey = AW_KEY_ASCII;
191        singlekey.awmod = AW_KEYMODE_NONE;
192        singlekey.awstr = buffer;
193
194        result = &singlekey;
195
196        if (numlockwason && (xkeyevent->state & AW_KEYMODE_ALT)) {
197            static bool warned = false;
198            if (!warned){
199                aw_message("Warning: Accelerator keys only work if NUMLOCK is off!");
200                warned = true;
201            }
202        }
203
204#if defined(DUMP_KEYEVENTS)
205        printf("AW_KEY_ASCII:");
206#endif // DUMP_KEYEVENTS
207    }
208    else {
209        long ptr;
210
211        if (count && (ptr = GBS_read_hash(awxkeymap_string_2_key_hash,buffer))){
212            result    = (awXKeymap*)ptr;
213
214#if defined(DUMP_KEYEVENTS)
215            printf("_awxkeymap_string_2_key_hash['%s']=", buffer);
216#endif // DUMP_KEYEVENTS
217        }
218        else if ( (ptr = GBS_read_hashi(awxkeymap_xkey_2_key_hash,keysym))){
219            result    = (awXKeymap*)ptr;
220           
221#if defined(DUMP_KEYEVENTS)
222            printf("_awxkeymap_xkey_2_key_hash['%x']='%s'", (unsigned)keysym, result->xstr);
223#endif // DUMP_KEYEVENTS
224        }
225        else {
226            singlekey.awkey = AW_KEY_NONE;
227            singlekey.awmod = AW_KEYMODE_NONE;
228            singlekey.awstr = 0;
229
230            result = &singlekey;
231
232#if defined(DUMP_KEYEVENTS)
233            printf("Undefined key (keysym=%x)", (unsigned)keysym);
234            if (count) printf(" name='%s'", buffer);
235#endif // DUMP_KEYEVENTS
236        }
237    }
238#if defined(DUMP_KEYEVENTS)
239    printf(" key='%u' mod='%u' awstr='%s'\n", result->awkey, result->awmod, result->awstr);
240#endif // DUMP_KEYEVENTS
241
242    return result;
243}
244
Note: See TracBrowser for help on using the repository browser.