97a5f9c97aec19f027ecfd6301ba1113951135ea
[expresskeys.git] / src-server / event_loop.c
1 /*
2  * event_loop.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
3  *
4  * Copyright (C) 2005 - Mats Johannesson
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
19  *
20  */
21
22 #include "globals.h"
23
24 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
25 /* Function waits perpetually for the X server to deliver information */
26 /* about events from the input device. Receipt of an event that we've */
27 /* registered for (button press/release and motion) triggers a good deal */
28 /* of activity in a setup phase, after which we send the fake key press */
29 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
30
31 int use_events(Display *display)
32 {
33
34         XClassHint *class_hint;
35
36         Window focus_window;
37         int focus_state;
38
39         Window root, parent;
40         Window *children;
41         unsigned int num_children;
42
43         struct program *p;
44         int in_list;
45
46         int elder_rotation = 4097; /* Set the Touch Strip state histories to */
47         int old_rotation = 4097;   /* their max values. This is to ensure */
48         int elder_throttle = 4097; /* that no action is taken on the very */
49         int old_throttle = 4097;   /* first touch before a real history is */
50         int rotation;              /* recorded. Bottom is 4097. Top is 2 */
51         int throttle;
52
53         XDeviceMotionEvent *motion;
54         XDeviceButtonEvent *button;
55
56         XEvent Event;
57
58         while(1) {
59
60                 XNextEvent(display, &Event);
61
62                 class_hint = XAllocClassHint(); /* Memory allocation. Free it later! */
63
64                 focus_window = None;
65                 in_list = 0;
66
67 /* Locate which window that currently has the focus and get its list of */
68 /* related windows. Then pull its ClassHint into our allocated structure */
69
70                 XGetInputFocus(display, &focus_window, &focus_state);
71                 XQueryTree(display, focus_window, &root, &parent, &children, &num_children);
72                 XGetClassHint(display, focus_window, class_hint);
73
74 /* If the class hint (aka WM_CLASS) contains no class string we free the */
75 /* allocated memory for each structure member and get the ClassHint of the */
76 /* window parent, if it has one. Observe that we must skip the root window */
77
78                 if ((!class_hint->res_class) && (parent) && (focus_window != root)) {
79                         XFree(class_hint->res_class);
80                         XFree(class_hint->res_name);
81                         XGetClassHint(display, parent, class_hint);
82                 }
83
84 /* If the root window had the focus, or if the active window or its parent */
85 /* had no class string at all, we use the top ("default") program definition */
86 /* from the read in configuration file when evaluating the event. Otherwise */
87 /* we start scanning for a match between the class strings in our list and */
88 /* the found window class. Set a flag if a match is encountered */
89
90                 if ((focus_window == root) || (class_hint->res_class == NULL)) {
91                         p = external_list;
92                 } else {
93                         for (p = external_list; p < external_list + num_list; p++)
94                                 if (strcmp (class_hint->res_class, p->class_name) == 0) {
95                                         in_list = 1;
96                                         break;
97                                 }
98                         }
99
100 /* Any program not found in our configuration gets the "default" treatment */
101
102                 if (!in_list) {
103                         p = external_list;
104                 }
105
106 /* The allocated memory for the ClassHint structure, and each of its */
107 /* members, must be freed here. Also, the call to XQueryTree to get a */
108 /* list of related windows might have allocated memory for child entries. */
109 /* It must be released as well */
110                 
111                 XFree(class_hint->res_class);
112                 XFree(class_hint->res_name);
113                 XFree(class_hint);
114                 if (children) XFree((char *)children);
115
116 /* Finally start to look at the actual event. Touch Strips come first */
117
118                 if (Event.type == motion_type) {
119
120                         if (p->handle_touch) {
121
122                         motion = (XDeviceMotionEvent *) &Event;
123
124                                 rotation = motion->axis_data[3];
125                                 throttle = motion->axis_data[4];
126
127 /* As can be analyzed with Frederic Lepied's excellent xinput-1.2 program */
128 /* the touch strip data comes in on axis 3 and 4 (left and right strips). */
129 /* The pad device never uses x-axis [0], y-axis [1] or wheel [5]. The value */
130 /* is always 0 there. The pressure [2], rotation [3] and throttle [4] all */
131 /* rest with a value of 1. Touch strips send data about the finger position */
132 /* in 13 steps. Furthest down is 4097 while the top is 2. Template: */
133 /* 4097, 2049, 1025, 513, 257, 129, 65, 33, 17, 9, 5, 3, 2. We don't care */
134 /* about those numbers per se (for now at least ;-), but just stick them */
135 /* in history buffers. The present value is then compared to an old and */
136 /* an even older one to determine direction of the finger movement. Observe */
137 /* that when we finally send a fake keypress, it has two parts - true and */
138 /* false. It corresponds with a key press and a key release. Order is key ;-) */
139
140 /* Left Touch Strip */
141
142                                 if (rotation > 1) {
143                                         if ((rotation < old_rotation) && (old_rotation <= elder_rotation)) {
144                                                 if (p->l_touch_up) {
145                                                         XTestFakeKeyEvent(display, p->l_touch_up, True, CurrentTime);
146                                                         if (p->l_touch_up_plus) {
147                                                                 XTestFakeKeyEvent(display, p->l_touch_up_plus, True, CurrentTime);
148                                                                 XTestFakeKeyEvent(display, p->l_touch_up_plus, False, CurrentTime);
149                                                         }
150                                                         XTestFakeKeyEvent(display, p->l_touch_up, False, CurrentTime);
151                                                 }
152                                         } else if ((rotation > old_rotation) && (old_rotation >= elder_rotation)) {
153                                                 if (p->l_touch_down) {
154                                                         XTestFakeKeyEvent(display, p->l_touch_down, True, CurrentTime);
155                                                         if (p->l_touch_down_plus) {
156                                                                 XTestFakeKeyEvent(display, p->l_touch_down_plus, True, CurrentTime);
157                                                                 XTestFakeKeyEvent(display, p->l_touch_down_plus, False, CurrentTime);
158                                                         }
159                                                         XTestFakeKeyEvent(display, p->l_touch_down, False, CurrentTime);
160                                                 }
161                                         }
162                                 elder_rotation = old_rotation;
163                                 old_rotation = rotation;
164                                 }
165
166 /* Right Touch Strip */
167
168                                 if (throttle > 1) {
169                                         if ((throttle < old_throttle) && (old_throttle <= elder_throttle)) {
170                                                 if (p->r_touch_up) {
171                                                         XTestFakeKeyEvent(display, p->r_touch_up, True, CurrentTime);
172                                                         if (p->r_touch_up_plus) {
173                                                                 XTestFakeKeyEvent(display, p->r_touch_up_plus, True, CurrentTime);
174                                                                 XTestFakeKeyEvent(display, p->r_touch_up_plus, False, CurrentTime);
175                                                         }
176                                                         XTestFakeKeyEvent(display, p->r_touch_up, False, CurrentTime);
177                                                 }
178                                         } else if ((throttle > old_throttle) && (old_throttle >= elder_throttle)) {
179                                                 if (p->r_touch_down) {
180                                                         XTestFakeKeyEvent(display, p->r_touch_down, True, CurrentTime);
181                                                         if (p->r_touch_down_plus) {
182                                                                 XTestFakeKeyEvent(display, p->r_touch_down_plus, True, CurrentTime);
183                                                                 XTestFakeKeyEvent(display, p->r_touch_down_plus, False, CurrentTime);
184                                                         }
185                                                         XTestFakeKeyEvent(display, p->r_touch_down, False, CurrentTime);
186                                                 }
187                                         }
188                                 elder_throttle = old_throttle;
189                                 old_throttle = throttle;
190                                 }
191                         }
192                 }
193
194 /* Now see if the event concerned the pad buttons. Not much to talk about. */
195 /* We follow the configuration definitions, and handle a pen if requested */
196 /* to do so. The switch routine is ugly and easy to get wrong, but it */
197 /* works! Ah yes, the xinput-1.2 program reveals Wacom to have numbered the */
198 /* buttons 9, 10, 11, 12 on the left side and 13, 14, 15, 16 on the right. */
199 /* Template: */
200 /*
201 Left ExpressKey Pad
202 ------------ 
203 |  |   |   |            Wacom Intuos3 defaults are:
204 |  | 9 | T |
205 |11|---| O |            Key 9  = (left) Shift   = keycode 50
206 |  |10 | U |            Key 10 = (left) Alt     = keycode 64
207 |------| C |            Key 11 = (left) Control = keycode 37
208 |  12  | H |            Key 12 = Space          = keycode 65
209 ------------
210
211 Right ExpressKey Pad
212 ------------ 
213 |   |   |  |            Wacom Intuos3 defaults are:
214 | T |13 |  |
215 | O |---|15|            Key 13 = (left) Shift   = keycode 50
216 | U |14 |  |            Key 14 = (left) Alt     = keycode 64
217 | C |------|            Key 15 = (left) Control = keycode 37
218 | H |  16  |            Key 16 = Space          = keycode 65
219 ------------
220 */
221
222 /* Pad Button Press */
223
224                 if (Event.type == button_press_type) {
225
226                         button = (XDeviceButtonEvent *) &Event;
227
228                         switch (button->button) {
229
230                                 case 9:
231                                 if (p->key_9 == TOGGLE_PEN)
232                                         if (handle_pen)
233                                                 toggle_pen_mode(display, pen_name);
234                                         else
235                                         break;
236                                 else
237                                 if (p->key_9)
238                                         XTestFakeKeyEvent(display, p->key_9, True, CurrentTime );
239                                         if (p->key_9_plus)
240                                                 XTestFakeKeyEvent(display, p->key_9_plus, True, CurrentTime );
241                                         else
242                                         break;
243                                 break;
244
245                                 case 10:
246                                 if (p->key_10 == TOGGLE_PEN)
247                                         if (handle_pen)
248                                                 toggle_pen_mode(display, pen_name);
249                                         else
250                                         break;
251                                 else
252                                 if (p->key_10)
253                                         XTestFakeKeyEvent(display, p->key_10, True, CurrentTime );
254                                         if (p->key_10_plus)
255                                                 XTestFakeKeyEvent(display, p->key_10_plus, True, CurrentTime );
256                                         else
257                                         break;
258                                 break;
259
260                                 case 11:
261                                 if (p->key_11 == TOGGLE_PEN)
262                                         if (handle_pen)
263                                                 toggle_pen_mode(display, pen_name);
264                                         else
265                                         break;
266                                 else
267                                 if (p->key_11)
268                                         XTestFakeKeyEvent(display, p->key_11, True, CurrentTime );
269                                         if (p->key_11_plus)
270                                                 XTestFakeKeyEvent(display, p->key_11_plus, True, CurrentTime );
271                                         else
272                                         break;
273                                 break;
274
275                                 case 12:
276                                 if (p->key_12 == TOGGLE_PEN)
277                                         if (handle_pen)
278                                                 toggle_pen_mode(display, pen_name);
279                                         else
280                                         break;
281                                 else
282                                 if (p->key_12)
283                                         XTestFakeKeyEvent(display, p->key_12, True, CurrentTime );
284                                         if (p->key_12_plus)
285                                                 XTestFakeKeyEvent(display, p->key_12_plus, True, CurrentTime );
286                                         else
287                                         break;
288                                 break;
289
290                                 case 13:
291                                 if (p->key_13 == TOGGLE_PEN)
292                                         if (handle_pen)
293                                                 toggle_pen_mode(display, pen_name);
294                                         else
295                                         break;
296                                 else
297                                 if (p->key_13)
298                                         XTestFakeKeyEvent(display, p->key_13, True, CurrentTime );
299                                         if (p->key_13_plus)
300                                                 XTestFakeKeyEvent(display, p->key_13_plus, True, CurrentTime );
301                                         else
302                                         break;
303                                 break;
304
305                                 case 14:
306                                 if (p->key_14 == TOGGLE_PEN)
307                                         if (handle_pen)
308                                                 toggle_pen_mode(display, pen_name);
309                                         else
310                                         break;
311                                 else
312                                 if (p->key_14)
313                                         XTestFakeKeyEvent(display, p->key_14, True, CurrentTime );
314                                         if (p->key_14_plus)
315                                                 XTestFakeKeyEvent(display, p->key_14_plus, True, CurrentTime );
316                                         else
317                                         break;
318                                 break;
319
320                                 case 15:
321                                 if (p->key_15 == TOGGLE_PEN)
322                                         if (handle_pen)
323                                                 toggle_pen_mode(display, pen_name);
324                                         else
325                                         break;
326                                 else
327                                 if (p->key_15)
328                                         XTestFakeKeyEvent(display, p->key_15, True, CurrentTime );
329                                         if (p->key_15_plus)
330                                                 XTestFakeKeyEvent(display, p->key_15_plus, True, CurrentTime );
331                                         else
332                                         break;
333                                 break;
334
335                                 case 16:
336                                 if (p->key_16 == TOGGLE_PEN)
337                                         if (handle_pen)
338                                                 toggle_pen_mode(display, pen_name);
339                                         else
340                                         break;
341                                 else
342                                 if (p->key_16)
343                                         XTestFakeKeyEvent(display, p->key_16, True, CurrentTime );
344                                         if (p->key_16_plus)
345                                                 XTestFakeKeyEvent(display, p->key_16_plus, True, CurrentTime );
346                                         else
347                                         break;
348                                 break;                  
349
350                                 default:
351                                 break;
352                         }
353                 }
354
355 /* Pad Button Release */
356
357 /* There is just an exit point below */
358 /* this switch routine by the way */
359
360                 if (Event.type == button_release_type) {
361
362                         button = (XDeviceButtonEvent *) &Event;
363
364                         switch (button->button) {
365
366                                 case 9:
367                                 if (p->key_9 == TOGGLE_PEN)
368                                         break;
369                                 else
370                                 if (p->key_9_plus)
371                                         XTestFakeKeyEvent(display, p->key_9_plus, False, CurrentTime );
372                                         if (p->key_9)
373                                                 XTestFakeKeyEvent(display, p->key_9, False, CurrentTime );
374                                         else
375                                         break;
376                                 break;
377
378                                 case 10:
379                                 if (p->key_10 == TOGGLE_PEN)            
380                                         break;
381                                 else
382                                 if (p->key_10_plus)
383                                         XTestFakeKeyEvent(display, p->key_10_plus, False, CurrentTime );
384                                         if (p->key_10)
385                                                 XTestFakeKeyEvent(display, p->key_10, False, CurrentTime );
386                                         else
387                                         break;
388                                 break;
389
390                                 case 11:
391                                 if (p->key_11 == TOGGLE_PEN)
392                                         break;
393                                 else
394                                 if (p->key_11_plus)
395                                         XTestFakeKeyEvent(display, p->key_11_plus, False, CurrentTime );
396                                         if (p->key_11)
397                                                 XTestFakeKeyEvent(display, p->key_11, False, CurrentTime );
398                                         else
399                                         break;
400                                 break;
401
402                                 case 12:
403                                 if (p->key_12 == TOGGLE_PEN)
404                                         break;
405                                 else
406                                 if (p->key_12_plus)
407                                         XTestFakeKeyEvent(display, p->key_12_plus, False, CurrentTime );
408                                         if (p->key_12)
409                                                 XTestFakeKeyEvent(display, p->key_12, False, CurrentTime );
410                                         else
411                                         break;
412                                 break;
413
414                                 case 13:
415                                 if (p->key_13 == TOGGLE_PEN)
416                                         break;
417                                 else
418                                 if (p->key_13_plus)             
419                                         XTestFakeKeyEvent(display, p->key_13_plus, False, CurrentTime );
420                                         if (p->key_13)
421                                                 XTestFakeKeyEvent(display, p->key_13, False, CurrentTime );
422                                         else
423                                         break;
424                                 break;
425
426                                 case 14:
427                                 if (p->key_14 == TOGGLE_PEN)
428                                         break;
429                                 else
430                                 if (p->key_14_plus)
431                                         XTestFakeKeyEvent(display, p->key_14_plus, False, CurrentTime );
432                                         if (p->key_14)
433                                                 XTestFakeKeyEvent(display, p->key_14, False, CurrentTime );
434                                         else
435                                         break;
436                                 break;
437
438                                 case 15:
439                                 if (p->key_15 == TOGGLE_PEN)
440                                         break;
441                                 else
442                                 if (p->key_15_plus)
443                                         XTestFakeKeyEvent(display, p->key_15_plus, False, CurrentTime );
444                                         if (p->key_15)
445                                                 XTestFakeKeyEvent(display, p->key_15, False, CurrentTime );
446                                         else
447                                         break;
448                                 break;
449
450                                 case 16:
451                                 if (p->key_16 == TOGGLE_PEN)
452                                         break;
453                                 else
454                                 if (p->key_16_plus)
455                                         XTestFakeKeyEvent(display, p->key_16_plus, False, CurrentTime );
456                                         if (p->key_16)
457                                                 XTestFakeKeyEvent(display, p->key_16, False, CurrentTime );
458                                         else
459                                         break;
460                                 break;
461
462                                 default:
463                                 break;
464                         }
465                 }
466         }
467         exit(EXIT_OK);
468 }
469
470 /* End code */
471