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_Delete, "Delete", AW_KEY_DELETE }, // was same as BackSpace in the past -- 2007/11/15
39 
40  { 0, NULp, AW_KEY_NONE },
41 };
42 
43 // manual key defs
44 // keys where all (or most) modifiers don't work should go here
45 static awXKeymap awxkeymap[] = {
46  // sun keypad ?
47  { XK_Shift_R, XK_R10, "Shift-Left", AW_KEYMODE_SHIFT, AW_KEY_LEFT, NULp },
48  { XK_Shift_R, XK_R12, "Shift-Right", AW_KEYMODE_SHIFT, AW_KEY_RIGHT, NULp },
49  { XK_Shift_L, XK_R10, "Shift-Left", AW_KEYMODE_SHIFT, AW_KEY_LEFT, NULp },
50  { XK_Shift_L, XK_R12, "Shift-Right", AW_KEYMODE_SHIFT, AW_KEY_RIGHT, NULp },
51  { 0, XK_R7, "Home", AW_KEYMODE_NONE, AW_KEY_HOME, NULp },
52  { 0, XK_R13, "End", AW_KEYMODE_NONE, AW_KEY_END, NULp },
53 
54  // functions keys
55  { 0, XK_F1, NULp, AW_KEYMODE_NONE, AW_KEY_F1, NULp },
56  { 0, XK_F2, NULp, AW_KEYMODE_NONE, AW_KEY_F2, NULp },
57  { 0, XK_F3, NULp, AW_KEYMODE_NONE, AW_KEY_F3, NULp },
58  { 0, XK_F4, NULp, AW_KEYMODE_NONE, AW_KEY_F4, NULp },
59  { 0, XK_F5, NULp, AW_KEYMODE_NONE, AW_KEY_F5, NULp },
60  { 0, XK_F6, NULp, AW_KEYMODE_NONE, AW_KEY_F6, NULp },
61  { 0, XK_F7, NULp, AW_KEYMODE_NONE, AW_KEY_F7, NULp },
62  { 0, XK_F8, NULp, AW_KEYMODE_NONE, AW_KEY_F8, NULp },
63  { 0, XK_F9, NULp, AW_KEYMODE_NONE, AW_KEY_F9, NULp },
64  { 0, XK_F10, NULp, AW_KEYMODE_NONE, AW_KEY_F10, NULp },
65  { 0, XK_F11, NULp, AW_KEYMODE_NONE, AW_KEY_F11, NULp },
66  { 0, XK_F12, NULp, AW_KEYMODE_NONE, AW_KEY_F12, NULp },
67 
68  // other
69  { 0, XK_BackSpace, "BackSpace", AW_KEYMODE_NONE, AW_KEY_BACKSPACE, NULp },
70  { 0, XK_Help, NULp, AW_KEYMODE_NONE, AW_KEY_HELP, NULp },
71  { 0, XK_Escape, NULp, AW_KEYMODE_NONE, AW_KEY_ESCAPE, NULp },
72  { 0, XK_Return, NULp, AW_KEYMODE_NONE, AW_KEY_RETURN, NULp },
73  { 0, XK_Tab, NULp, AW_KEYMODE_NONE, AW_KEY_RETURN, NULp }, // done to accept input-field-changes via TAB, also disables inserting tabs
74 
75  { 0, 0, (char*)1, AW_KEYMODE_NONE, AW_KEY_NONE, NULp }
76 };
77 
78 struct awModDef {
79  int xmod;
80  const char *xstr_prefix;
82 };
83 
84 static awModDef moddef[] = {
85  { XK_Shift_L, "Shift", AW_KEYMODE_SHIFT },
86  { XK_Shift_R, "Shift", AW_KEYMODE_SHIFT },
87  { XK_Meta_L, "Meta", AW_KEYMODE_ALT }, // handle Meta as Alt
88  { XK_Meta_R, "Meta", AW_KEYMODE_ALT },
89  { XK_Alt_L, "Alt", AW_KEYMODE_ALT },
90  { XK_Alt_R, "Alt", AW_KEYMODE_ALT },
91  { XK_Control_L, "Control", AW_KEYMODE_CONTROL },
92  { XK_Control_R, "Control", AW_KEYMODE_CONTROL },
93  { 0, NULp, AW_KEYMODE_NONE }, // "no modifier" (this is NO array terminator!)
94 };
95 
96 const int FIXEDMOD = TERMINATED_ARRAY_ELEMS(awxkeymap);
97 const int MODFREE = TERMINATED_ARRAY_ELEMS(awxkeymap_modfree);
98 const int MODS = ARRAY_ELEMS(moddef);
99 
102 static int generatedKeymaps_count = -1;
104 
105 
106 const int MAPPED_KEYS = MODFREE*MODS+FIXEDMOD;
107 
108 #if defined(ASSERTION_USED)
109 static int mappedKeys = 0;
110 #endif // ASSERTION_USED
111 
112 static void map_awXKey(Display *display, const awXKeymap *awxk) {
113  if (awxk->xstr) {
114  KeySym modlist[2];
115  int modsize;
116 
117  modlist[0] = awxk->xmod;
118  modsize = modlist[0] ? 1 : 0;
119 
120  XRebindKeysym(display, awxk->xkey, modlist, modsize,
121  (unsigned char*)awxk->xstr, strlen(awxk->xstr));
122 
123  GBS_write_hash(awxkeymap_string_2_key_hash, awxk->xstr, (long)awxk);
124  }
125  GBS_write_numhash(awxkeymap_xkey_2_key_hash, awxk->xkey, (long)awxk);
126 
127 #if defined(ASSERTION_USED)
128  ++mappedKeys;
129 #endif // ASSERTION_USED
130 }
131 
132 void aw_install_xkeys(Display *display) {
133  int i;
134 
135  awxkeymap_string_2_key_hash = GBS_create_hash(MAPPED_KEYS, GB_MIND_CASE);
136  awxkeymap_xkey_2_key_hash = GBS_create_numhash(MAPPED_KEYS);
137 
138  // auto-generate all key/modifier combinations for keys in awxkeymap_modfree
139  for (i=0; ; ++i) {
140  if (!awxkeymap_modfree[i].xstr_suffix) break;
141  }
142 
143  int modfree = i;
144 
145  aw_assert(!generatedKeymaps); // oops - called twice
146 
147  generatedKeymaps_count = modfree*MODS;
148  ARB_calloc(generatedKeymaps, generatedKeymaps_count);
149 
150  for (i=0; i<modfree; ++i) {
151  const awXKeymap_modfree *mf = awxkeymap_modfree+i;
152  for (int j = 0; j<MODS; ++j) {
153  awXKeymap *km = generatedKeymaps+i*MODS+j;
154  awModDef *md = moddef+j;
155 
156  km->xmod = md->xmod;
157  km->xkey = mf->xkey;
158  km->xstr = md->xstr_prefix ? GBS_global_string_copy("%s-%s", md->xstr_prefix, mf->xstr_suffix) : mf->xstr_suffix;
159  km->awmod = md->awmod;
160  km->awkey = mf->awkey;
161  km->awstr = NULp;
162 
163  map_awXKey(display, km);
164  }
165  }
166 
167  // add manually defined keys
168  for (i=0; ; ++i) {
169  if (awxkeymap[i].xstr == (char*)1) break;
170  map_awXKey(display, awxkeymap+i);
171  }
172 
173  aw_assert(mappedKeys == MAPPED_KEYS);
174 }
175 
177  for (int i = 0; i<generatedKeymaps_count; ++i) {
178  awXKeymap& km = generatedKeymaps[i];
179  int j = i%MODS;
180  awModDef& md = moddef[j];
181 
182  if (md.xstr_prefix) free((char*)km.xstr);
183  }
184  free(generatedKeymaps); generatedKeymaps = NULp;
185 
186  if (awxkeymap_xkey_2_key_hash) { GBS_free_numhash(awxkeymap_xkey_2_key_hash); awxkeymap_xkey_2_key_hash = NULp; }
187  if (awxkeymap_string_2_key_hash) { GBS_free_hash (awxkeymap_string_2_key_hash); awxkeymap_string_2_key_hash = NULp; }
188 }
189 
190 #if defined(DEBUG)
191 // #define DUMP_KEYEVENTS
192 #endif // DEBUG
193 
194 const awXKeymap *aw_xkey_2_awkey(XKeyEvent *xkeyevent) {
195  awXKeymap *result;
196  static awXKeymap singlekey = { 0, 0, NULp, AW_KEYMODE_NONE, AW_KEY_NONE, NULp };
197  bool numlockwason = false;
198 
199  if (xkeyevent->state & AW_KEYMODE_NUMLOCK) { // numlock is active
200  xkeyevent->state &= ~AW_KEYMODE_NUMLOCK; // ignore NUMLOCK
201  numlockwason = true;
202  }
203 
204  const int BUFFERSIZE = 256;;
205  static char buffer[BUFFERSIZE];
206  KeySym keysym;
207  int count = XLookupString(xkeyevent, buffer, BUFFERSIZE, &keysym, NULp);
208  buffer[count] = 0;
209 
210  if (!buffer[0] && count) {
211 #if defined(DUMP_KEYEVENTS)
212  printf("special case: Ctrl-Space\n");
213 #endif
214  aw_assert(keysym == XK_space);
215  buffer[0] = ' ';
216  }
217 
218 #if defined(DUMP_KEYEVENTS)
219  printf("state=%u keycode=%u name='%s' ", xkeyevent->state, xkeyevent->keycode, buffer);
220 #endif // DUMP_KEYEVENTS
221 
222  if (keysym >= XK_space && keysym <= XK_asciitilde) {
223  singlekey.awkey = AW_KEY_ASCII;
224  singlekey.awmod = (AW_key_mod)(xkeyevent->state & (AW_KEYMODE_CONTROL|AW_KEYMODE_ALT)); // forward ctrl and alt state
225  singlekey.awstr = buffer;
226  aw_assert(buffer[0]);
227 
228  result = &singlekey;
229 
230  if (numlockwason && (xkeyevent->state & AW_KEYMODE_ALT)) {
231  static bool warned = false;
232  if (!warned) {
233  aw_message("Warning: Accelerator keys only work if NUMLOCK is off!");
234  warned = true;
235  }
236  }
237 
238 #if defined(DUMP_KEYEVENTS)
239  printf("AW_KEY_ASCII:");
240 #endif // DUMP_KEYEVENTS
241  }
242  else {
243  long ptr;
244 
245  if (count && (ptr = GBS_read_hash(awxkeymap_string_2_key_hash, buffer))) {
246  result = (awXKeymap*)ptr;
247 
248 #if defined(DUMP_KEYEVENTS)
249  printf("_awxkeymap_string_2_key_hash['%s']=", buffer);
250 #endif // DUMP_KEYEVENTS
251  }
252  else if ((ptr = GBS_read_numhash(awxkeymap_xkey_2_key_hash, keysym))) {
253  result = (awXKeymap*)ptr;
254 
255 #if defined(DUMP_KEYEVENTS)
256  printf("_awxkeymap_xkey_2_key_hash['%x']='%s'", (unsigned)keysym, result->xstr);
257 #endif // DUMP_KEYEVENTS
258  }
259  else {
260  singlekey.awkey = AW_KEY_NONE;
261  singlekey.awmod = AW_KEYMODE_NONE;
262  singlekey.awstr = NULp;
263 
264  result = &singlekey;
265 
266 #if defined(DUMP_KEYEVENTS)
267  printf("Undefined key (keysym=%x)", (unsigned)keysym);
268  if (count) printf(" name='%s'", buffer);
269 #endif // DUMP_KEYEVENTS
270  }
271  }
272 #if defined(DUMP_KEYEVENTS)
273  printf(" key='%u' mod='%u' awstr='%s'\n", result->awkey, result->awmod, result->awstr);
274 #endif // DUMP_KEYEVENTS
275 
276  return result;
277 }
278 
string result
AW_key_mod awmod
Definition: aw_xkey.hxx:12
int xmod
Definition: AW_xkey.cxx:79
void aw_install_xkeys(Display *display)
Definition: AW_xkey.cxx:132
static GB_HASH * awxkeymap_string_2_key_hash
Definition: AW_xkey.cxx:100
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:101
const int MODFREE
Definition: AW_xkey.cxx:97
const int MAPPED_KEYS
Definition: AW_xkey.cxx:106
#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:84
long GBS_write_numhash(GB_NUMHASH *hs, long key, long val)
Definition: adhash.cxx:690
const char * xstr_prefix
Definition: AW_xkey.cxx:80
GB_NUMHASH * GBS_create_numhash(size_t estimated_elements)
Definition: adhash.cxx:671
const int FIXEDMOD
Definition: AW_xkey.cxx:96
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:45
static int generatedKeymaps_count
Definition: AW_xkey.cxx:102
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:194
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:103
static int mappedKeys
Definition: AW_xkey.cxx:109
void aw_message(const char *msg)
Definition: AW_status.cxx:932
#define NULp
Definition: cxxforward.h:97
AW_key_mod
Definition: aw_keysym.hxx:44
const char * xstr_suffix
Definition: aw_xkey.hxx:19
void aw_uninstall_xkeys()
Definition: AW_xkey.cxx:176
const int MODS
Definition: AW_xkey.cxx:98
static void map_awXKey(Display *display, const awXKeymap *awxk)
Definition: AW_xkey.cxx:112
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:81
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