source: branches/stable/WINDOW/AW_xkey.cxx

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