ARB
AW_xkey.cxx
Go to the documentation of this file.
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
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
47 static 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 
80 struct awModDef {
81  int xmod;
82  const char *xstr_prefix;
84 };
85 
86 static 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 
98 const int FIXEDMOD = TERMINATED_ARRAY_ELEMS(awxkeymap);
99 const int MODFREE = TERMINATED_ARRAY_ELEMS(awxkeymap_modfree);
100 const int MODS = ARRAY_ELEMS(moddef);
101 
104 static int generatedKeymaps_count = -1;
106 
107 
108 const int MAPPED_KEYS = MODFREE*MODS+FIXEDMOD;
109 
110 #if defined(ASSERTION_USED)
111 static int mappedKeys = 0;
112 #endif // ASSERTION_USED
113 
114 static 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 
134 void 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 
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 
196 const 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 
string result
AW_key_mod awmod
Definition: aw_xkey.hxx:12
int xmod
Definition: AW_xkey.cxx:81
void aw_install_xkeys(Display *display)
Definition: AW_xkey.cxx:134
static GB_HASH * awxkeymap_string_2_key_hash
Definition: AW_xkey.cxx:102
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
Definition: adhash.cxx:457
static GB_NUMHASH * awxkeymap_xkey_2_key_hash
Definition: AW_xkey.cxx:103
const int MODFREE
Definition: AW_xkey.cxx:99
const int MAPPED_KEYS
Definition: AW_xkey.cxx:108
#define TERMINATED_ARRAY_ELEMS(array)
Definition: arb_defs.h:20
int xmod
Definition: aw_xkey.hxx:9
#define aw_assert(bed)
Definition: AW_xkey.cxx:23
static awModDef moddef[]
Definition: AW_xkey.cxx:86
long GBS_write_numhash(GB_NUMHASH *hs, long key, long val)
Definition: adhash.cxx:690
const char * xstr_prefix
Definition: AW_xkey.cxx:82
GB_NUMHASH * GBS_create_numhash(size_t estimated_elements)
Definition: adhash.cxx:671
const int FIXEDMOD
Definition: AW_xkey.cxx:98
void GBS_free_hash(GB_HASH *hs)
Definition: adhash.cxx:541
#define ARRAY_ELEMS(array)
Definition: arb_defs.h:19
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
static struct aisc_static_set_mem md
static awXKeymap awxkeymap[]
Definition: AW_xkey.cxx:47
static int generatedKeymaps_count
Definition: AW_xkey.cxx:104
long GBS_read_numhash(GB_NUMHASH *hs, long key)
Definition: adhash.cxx:682
AW_key_code awkey
Definition: aw_xkey.hxx:20
int xkey
Definition: aw_xkey.hxx:10
const awXKeymap * aw_xkey_2_awkey(XKeyEvent *xkeyevent)
Definition: AW_xkey.cxx:196
static awXKeymap_modfree awxkeymap_modfree[]
Definition: AW_xkey.cxx:31
void GBS_free_numhash(GB_NUMHASH *hs)
Definition: adhash.cxx:745
TYPE * ARB_calloc(size_t nelem)
Definition: arb_mem.h:81
const size_t BUFFERSIZE
static awXKeymap * generatedKeymaps
Definition: AW_xkey.cxx:105
static int mappedKeys
Definition: AW_xkey.cxx:111
void aw_message(const char *msg)
Definition: AW_status.cxx:932
#define NULp
Definition: cxxforward.h:97
AW_key_mod
Definition: aw_keysym.hxx:46
const char * xstr_suffix
Definition: aw_xkey.hxx:19
void aw_uninstall_xkeys()
Definition: AW_xkey.cxx:178
const int MODS
Definition: AW_xkey.cxx:100
static void map_awXKey(Display *display, const awXKeymap *awxk)
Definition: AW_xkey.cxx:114
AW_key_code awkey
Definition: aw_xkey.hxx:13
const char * xstr
Definition: aw_xkey.hxx:11
char * awstr
Definition: aw_xkey.hxx:14
long GBS_read_hash(const GB_HASH *hs, const char *key)
Definition: adhash.cxx:395
AW_key_mod awmod
Definition: AW_xkey.cxx:83
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:195
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)
Definition: adhash.cxx:253