eolian: rename is_ref API to is_ptr to match syntax
[platform/upstream/efl.git] / src / lib / ecore_x / xlib / ecore_x_xi2.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4
5 #include <string.h>
6 #include <math.h>
7
8 #include "Ecore.h"
9 #include "ecore_x_private.h"
10 #include "Ecore_X.h"
11
12 #ifdef ECORE_XI2
13 #include "Ecore_Input.h"
14 #endif /* ifdef ECORE_XI2 */
15
16 int _ecore_x_xi2_opcode = -1;
17
18 #ifndef XIPointerEmulated
19 #define XIPointerEmulated (1 << 16)
20 #endif
21
22 #ifdef ECORE_XI2
23 #ifdef ECORE_XI2_2
24 #ifndef XITouchEmulatingPointer
25 #define XITouchEmulatingPointer (1 << 17)
26 #endif
27
28 typedef struct _Ecore_X_Touch_Device_Info
29 {
30    EINA_INLIST;
31    int devid;
32    int mode;
33    const char *name;
34    int max_touch;
35    int *slot;
36 } Ecore_X_Touch_Device_Info;
37 #endif /* ifdef ECORE_XI2_2 */
38
39 static XIDeviceInfo *_ecore_x_xi2_devs = NULL;
40 static int _ecore_x_xi2_num = 0;
41 #ifdef ECORE_XI2_2
42 static Eina_Inlist *_ecore_x_xi2_touch_info_list = NULL;
43 #endif /* ifdef ECORE_XI2_2 */
44 static Eina_List *_ecore_x_xi2_grabbed_devices_list;
45 #endif /* ifdef ECORE_XI2 */
46
47 void
48 _ecore_x_input_init(void)
49 {
50 #ifdef ECORE_XI2
51    int event, error;
52    int major = XI_2_Major, minor = XI_2_Minor;
53
54    if (!XQueryExtension(_ecore_x_disp, "XInputExtension",
55                         &_ecore_x_xi2_opcode, &event, &error))
56      {
57         _ecore_x_xi2_opcode = -1;
58         return;
59      }
60
61    if (XIQueryVersion(_ecore_x_disp, &major, &minor) == BadRequest)
62      {
63         _ecore_x_xi2_opcode = -1;
64         return;
65      }
66
67    _ecore_x_xi2_devs = XIQueryDevice(_ecore_x_disp, XIAllDevices,
68                                      &_ecore_x_xi2_num);
69 #endif /* ifdef ECORE_XI2 */
70 }
71
72 #ifdef ECORE_XI2
73 #ifdef ECORE_XI2_2
74 static void
75 _ecore_x_input_touch_info_clear(void)
76 {
77    Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
78    Ecore_X_Touch_Device_Info *info = NULL;
79
80    while (l)
81      {
82         info = EINA_INLIST_CONTAINER_GET(l, Ecore_X_Touch_Device_Info);
83         l = eina_inlist_remove(l, l);
84         if (info->slot) free(info->slot);
85         free(info);
86      }
87
88    _ecore_x_xi2_touch_info_list = NULL;
89 }
90 #endif /* ifdef ECORE_XI2_2 */
91 #endif /* ifdef ECORE_XI2 */
92
93 #ifdef ECORE_XI2
94 static Atom
95 _ecore_x_input_get_axis_label(char *axis_name)
96 {
97    static Atom *atoms = NULL;
98    static char *names[] =
99      {
100         "Abs X", "Abs Y", "Abs Pressure",
101         "Abs Distance", "Abs Rotary Z",
102         "Abs Wheel", "Abs Tilt X", "Abs Tilt Y",
103         "Rel X", "Rel Y", "Rel Dial", "Rel Horiz Wheel", "Rel Vert Wheel"
104      };
105    int n = sizeof(names) / sizeof(names[0]);
106    int i;
107
108    if (EINA_UNLIKELY(atoms == NULL))
109      {
110         atoms = calloc(n, sizeof(Atom));
111         if (!atoms) return 0;
112
113         if (!XInternAtoms(_ecore_x_disp, names, n, 1, atoms))
114           {
115              free(atoms);
116              atoms = NULL;
117              return 0;
118           }
119      }
120
121    for (i = 0; i < n; i++)
122      {
123         if (!strcmp(axis_name, names[i])) return atoms[i];
124      }
125
126    return 0;
127 }
128 #endif /* ifdef ECORE_XI2 */
129
130 void
131 _ecore_x_input_shutdown(void)
132 {
133 #ifdef ECORE_XI2
134    if (_ecore_x_xi2_devs)
135      {
136         XIFreeDeviceInfo(_ecore_x_xi2_devs);
137         _ecore_x_xi2_devs = NULL;
138 #ifdef ECORE_XI2_2
139         _ecore_x_input_touch_info_clear();
140 #endif /* ifdef ECORE_XI2_2 */
141      }
142
143    _ecore_x_xi2_num = 0;
144    _ecore_x_xi2_opcode = -1;
145
146    if (_ecore_x_xi2_grabbed_devices_list)
147      eina_list_free(_ecore_x_xi2_grabbed_devices_list);
148    _ecore_x_xi2_grabbed_devices_list = NULL;
149 #endif /* ifdef ECORE_XI2 */
150 }
151
152 #ifdef ECORE_XI2
153 #ifdef ECORE_XI2_2
154
155 # ifdef XI_TouchCancel
156 static Eina_Bool
157 _ecore_x_input_touch_device_check(int devid)
158 {
159    Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
160    Ecore_X_Touch_Device_Info *info = NULL;
161
162    if ((!_ecore_x_xi2_devs) || (!_ecore_x_xi2_touch_info_list))
163      return EINA_FALSE;
164
165    EINA_INLIST_FOREACH(l, info)
166      if (info->devid == devid) return EINA_TRUE;
167    return EINA_FALSE;
168 }
169 #endif
170
171 static int
172 _ecore_x_input_touch_index_get(int devid, int detail, int event_type)
173 {
174    int i;
175    Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
176    Ecore_X_Touch_Device_Info *info = NULL;
177
178    if ((!_ecore_x_xi2_devs) || (!_ecore_x_xi2_touch_info_list))
179      return 0;
180
181    EINA_INLIST_FOREACH(l, info)
182      if (info->devid == devid) break;
183
184    if ((!info) || (!info->slot)) return 0;
185
186    for (i = 0; i < info->max_touch ; i++)
187      {
188         int *p = &(info->slot[i]);
189
190         if ((event_type == XI_TouchBegin) && (*p < 0))
191           {
192              *p = detail;
193              return i;
194           }
195        else if (*p == detail)
196          {
197             return i;
198          }
199      }
200
201    return 0;
202 }
203
204 static void
205 _ecore_x_input_touch_index_clear(int devid, int idx)
206 {
207    Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
208    Ecore_X_Touch_Device_Info *info = NULL;
209
210    if ((!_ecore_x_xi2_devs) || (!_ecore_x_xi2_touch_info_list))
211      return;
212
213    EINA_INLIST_FOREACH(l, info)
214      {
215         if ((info->devid == devid) && (info->slot))
216           {
217              info->slot[idx] = -1;
218              return;
219           }
220      }
221 }
222
223 static Ecore_X_Touch_Device_Info *
224 _ecore_x_input_touch_info_get(XIDeviceInfo *dev)
225 {
226    int k;
227    int *slot = NULL;
228    XITouchClassInfo *t = NULL;
229    Ecore_X_Touch_Device_Info *info = NULL;
230
231    if (!dev)
232      return NULL;
233
234    for (k = 0; k < dev->num_classes; k++)
235      {
236         XIAnyClassInfo *clas = dev->classes[k];
237
238         if (clas && (clas->type == XITouchClass))
239           {
240              t = (XITouchClassInfo *)clas;
241              break;
242           }
243      }
244
245    if (t && (t->type == XITouchClass))
246      {
247         info = calloc(1, sizeof(Ecore_X_Touch_Device_Info));
248         if (!info) return NULL;
249
250         slot = malloc(sizeof(int) * (t->num_touches + 1));
251         if (!slot)
252           {
253              free(info);
254              return NULL;
255           }
256
257         info->devid = dev->deviceid;
258         info->max_touch = t->num_touches + 1;
259         info->mode = t->mode;
260         info->name = dev->name;
261         memset(slot, -1, sizeof(int) * info->max_touch);
262         info->slot = slot;
263      }
264
265    return info;
266 }
267 #endif /* ifdef ECORE_XI2_2 */
268 #endif
269
270 void
271 _ecore_x_input_raw_handler(XEvent *xevent)
272 {
273 #ifdef ECORE_XI2
274    if (xevent->type != GenericEvent) return;
275
276    switch (xevent->xcookie.evtype)
277      {
278 #ifdef XI_RawButtonPress
279       case XI_RawButtonPress:
280          ecore_event_add(ECORE_X_RAW_BUTTON_PRESS, NULL, NULL, NULL);
281          break;
282 #endif
283 #ifdef XI_RawButtonRelease
284       case XI_RawButtonRelease:
285          ecore_event_add(ECORE_X_RAW_BUTTON_RELEASE, NULL, NULL, NULL);
286          break;
287 #endif
288 #ifdef XI_RawMotion
289       case XI_RawMotion:
290          ecore_event_add(ECORE_X_RAW_MOTION, NULL, NULL, NULL);
291          break;
292 #endif
293      }
294 #endif /* ifdef ECORE_XI2 */
295 }
296
297 #ifdef ECORE_XI2_2
298 static Eina_Bool
299 _ecore_x_input_grabbed_is(int deviceId)
300 {
301    void *id;
302    Eina_List *l;
303
304    EINA_LIST_FOREACH(_ecore_x_xi2_grabbed_devices_list, l, id)
305      {
306         if (deviceId == (intptr_t)id)
307           return EINA_TRUE;
308      }
309
310    return EINA_FALSE;
311 }
312 #endif /* ifdef ECORE_XI2_2 */
313
314 void
315 _ecore_x_input_mouse_handler(XEvent *xevent)
316 {
317 #ifdef ECORE_XI2
318    if (xevent->type != GenericEvent) return;
319
320    XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
321    int devid = evd->deviceid;
322
323    switch (xevent->xcookie.evtype)
324      {
325       case XI_Motion:
326         INF("Handling XI_Motion");
327         _ecore_mouse_move
328           (evd->time,
329           0,   // state
330           evd->event_x, evd->event_y,
331           evd->root_x, evd->root_y,
332           evd->event,
333           (evd->child ? evd->child : evd->event),
334           evd->root,
335           1,   // same_screen
336           devid, 1, 1,
337           1.0,   // pressure
338           0.0,   // angle
339           evd->event_x, evd->event_y,
340           evd->root_x, evd->root_y);
341         break;
342
343       case XI_ButtonPress:
344         INF("ButtonEvent:multi press time=%u x=%d y=%d devid=%d", (unsigned int)evd->time, (int)evd->event_x, (int)evd->event_y, devid);
345         _ecore_mouse_button
346           (ECORE_EVENT_MOUSE_BUTTON_DOWN,
347           evd->time,
348           0,   // state
349           0,   // button
350           evd->event_x, evd->event_y,
351           evd->root_x, evd->root_y,
352           evd->event,
353           (evd->child ? evd->child : evd->event),
354           evd->root,
355           1,   // same_screen
356           devid, 1, 1,
357           1.0,   // pressure
358           0.0,   // angle
359           evd->event_x, evd->event_y,
360           evd->root_x, evd->root_y);
361         break;
362
363       case XI_ButtonRelease:
364         INF("ButtonEvent:multi release time=%u x=%d y=%d devid=%d", (unsigned int)evd->time, (int)evd->event_x, (int)evd->event_y, devid);
365         _ecore_mouse_button
366           (ECORE_EVENT_MOUSE_BUTTON_UP,
367           evd->time,
368           0,   // state
369           0,   // button
370           evd->event_x, evd->event_y,
371           evd->root_x, evd->root_y,
372           evd->event,
373           (evd->child ? evd->child : evd->event),
374           evd->root,
375           1,   // same_screen
376           devid, 1, 1,
377           1.0,   // pressure
378           0.0,   // angle
379           evd->event_x, evd->event_y,
380           evd->root_x, evd->root_y);
381         break;
382       }
383 #endif /* ifdef ECORE_XI2 */
384 }
385
386 //XI_TouchUpdate, XI_TouchBegin, XI_TouchEnd only available in XI2_2
387 //So it is better using ECORE_XI2_2 define than XI_TouchXXX defines.
388 void
389 _ecore_x_input_multi_handler(XEvent *xevent)
390 {
391 #ifdef ECORE_XI2
392    if (xevent->type != GenericEvent) return;
393
394    switch (xevent->xcookie.evtype)
395      {
396 #ifdef ECORE_XI2_2
397       case XI_TouchUpdate:
398           {
399              XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
400              int devid = evd->deviceid;
401              int i = _ecore_x_input_touch_index_get(devid, evd->detail, XI_TouchUpdate);
402              if ((i == 0) && (evd->flags & XITouchEmulatingPointer) && !_ecore_x_input_grabbed_is(devid)) return;
403              INF("Handling XI_TouchUpdate");
404              _ecore_mouse_move(evd->time,
405                                0,   // state
406                                evd->event_x, evd->event_y,
407                                evd->root_x, evd->root_y,
408                                evd->event,
409                                (evd->child ? evd->child : evd->event),
410                                evd->root,
411                                1,   // same_screen
412                                i, 1, 1,
413                                1.0,   // pressure
414                                0.0,   // angle
415                                evd->event_x, evd->event_y,
416                                evd->root_x, evd->root_y);
417           }
418         break;
419
420       case XI_TouchBegin:
421           {
422              XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
423              int devid = evd->deviceid;
424              int i = _ecore_x_input_touch_index_get(devid, evd->detail, XI_TouchBegin);
425              if ((i == 0) && (evd->flags & XITouchEmulatingPointer) && !_ecore_x_input_grabbed_is(devid)) return;
426              INF("Handling XI_TouchBegin");
427              _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN,
428                                  evd->time,
429                                  0,   // state
430                                  0,   // button
431                                  evd->event_x, evd->event_y,
432                                  evd->root_x, evd->root_y,
433                                  evd->event,
434                                  (evd->child ? evd->child : evd->event),
435                                  evd->root,
436                                  1,   // same_screen
437                                  i, 1, 1,
438                                  1.0,   // pressure
439                                  0.0,   // angle
440                                  evd->event_x, evd->event_y,
441                                  evd->root_x, evd->root_y);
442           }
443         break;
444
445       case XI_TouchEnd:
446           {
447              XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
448              int devid = evd->deviceid;
449              int i = _ecore_x_input_touch_index_get(devid, evd->detail, XI_TouchEnd);
450              if ((i == 0) && (evd->flags & XITouchEmulatingPointer) && !_ecore_x_input_grabbed_is(devid))
451                {
452                   _ecore_x_input_touch_index_clear(devid,  i);
453                   return;
454                }
455              INF("Handling XI_TouchEnd");
456              _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP,
457                                  evd->time,
458                                  0,   // state
459                                  0,   // button
460                                  evd->event_x, evd->event_y,
461                                  evd->root_x, evd->root_y,
462                                  evd->event,
463                                  (evd->child ? evd->child : evd->event),
464                                  evd->root,
465                                  1,   // same_screen
466                                  i, 1, 1,
467                                  1.0,   // pressure
468                                  0.0,   // angle
469                                  evd->event_x, evd->event_y,
470                                  evd->root_x, evd->root_y);
471              _ecore_x_input_touch_index_clear(devid,  i);
472           }
473         break;
474 #endif /* ifdef ECORE_XI2_2 */
475       default:
476         break;
477       }
478 #endif /* ifdef ECORE_XI2 */
479 }
480
481 #ifdef ECORE_XI2
482 static unsigned int
483 _ecore_x_count_bits(unsigned long n)
484 {
485    unsigned int c; /* c accumulates the total bits set in v */
486    for (c = 0; n; c++) n &= n - 1; /* clear the least significant bit set */
487    return c;
488 }
489 #endif
490
491 #ifdef ECORE_XI2
492 void
493 _ecore_x_input_axis_handler(XEvent *xevent, XIDeviceInfo *dev)
494 {
495    if (xevent->type != GenericEvent) return;
496    XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
497    unsigned int n = _ecore_x_count_bits(*evd->valuators.mask) + 4;
498    int i;
499    int j = 0;
500    double tiltx = 0, tilty = 0;
501    Eina_Bool compute_tilt = EINA_FALSE;
502    Ecore_Axis *axis = calloc(n, sizeof(Ecore_Axis));
503    if (!axis) return;
504    Ecore_Axis *axis_ptr = axis;
505    Ecore_Axis *shrunk_axis;
506
507    for (i = 0; i < dev->num_classes; i++)
508      {
509         if (dev->classes[i]->type == XIValuatorClass)
510           {
511              XIValuatorClassInfo *inf = ((XIValuatorClassInfo *)dev->classes[i]);
512
513              if (*evd->valuators.mask & (1 << inf->number))
514                {
515                   if (inf->label == _ecore_x_input_get_axis_label("Abs X"))
516                     {
517                        int x = evd->valuators.values[j];
518                        axis_ptr->label = ECORE_AXIS_LABEL_X;
519                        axis_ptr->value = x;
520                        axis_ptr++;
521                        if (inf->max > inf->min)
522                          {
523                             axis_ptr->label = ECORE_AXIS_LABEL_NORMAL_X;
524                             axis_ptr->value = (x - inf->min) / (inf->max - inf->min);
525                             axis_ptr++;
526                          }
527                     }
528                   else if (inf->label == _ecore_x_input_get_axis_label("Abs Y"))
529                     {
530                        int y = evd->valuators.values[j];
531                        axis_ptr->label = ECORE_AXIS_LABEL_Y;
532                        axis_ptr->value = y;
533                        axis_ptr++;
534                        if (inf->max > inf->min)
535                          {
536                             axis_ptr->label = ECORE_AXIS_LABEL_NORMAL_Y;
537                             axis_ptr->value = (y - inf->min) / (inf->max - inf->min);
538                             axis_ptr++;
539                          }
540                     }
541                   else if (inf->label == _ecore_x_input_get_axis_label("Abs Pressure"))
542                     {
543                        axis_ptr->label = ECORE_AXIS_LABEL_PRESSURE;
544                        axis_ptr->value = (evd->valuators.values[j] - inf->min) / (inf->max - inf->min);
545                        axis_ptr++;
546                     }
547                   else if (inf->label == _ecore_x_input_get_axis_label("Abs Distance"))
548                     {
549                        axis_ptr->label = ECORE_AXIS_LABEL_DISTANCE;
550                        axis_ptr->value = (evd->valuators.values[j] - inf->min) / (inf->max - inf->min);
551                        axis_ptr++;
552                     }
553                   else if ((inf->label == _ecore_x_input_get_axis_label("Abs Rotary Z")) ||
554                            (inf->label == _ecore_x_input_get_axis_label("Abs Wheel")))
555                     {
556                        axis_ptr->label = ECORE_AXIS_LABEL_TWIST;
557                        if (inf->resolution == 1)
558                          {
559                             /* some wacom drivers do not correctly report resolution, so pre-normalize */
560                             axis_ptr->value = 2*((evd->valuators.values[j] - inf->min) / (inf->max - inf->min)) - 1;
561                             axis_ptr->value *= M_PI;
562                          }
563                        else
564                          {
565                             axis_ptr->value = evd->valuators.values[j] / inf->resolution;
566                          }
567                        axis_ptr++;
568                     }
569                   else if (inf->label == _ecore_x_input_get_axis_label("Abs Tilt X"))
570                     {
571                        tiltx = evd->valuators.values[j] / inf->resolution;
572                        compute_tilt = EINA_TRUE;
573                        /* don't increment axis_ptr */
574                     }
575                   else if (inf->label == _ecore_x_input_get_axis_label("Abs Tilt Y"))
576                     {
577                        tilty = -evd->valuators.values[j] / inf->resolution;
578                        compute_tilt = EINA_TRUE;
579                        /* don't increment axis_ptr */
580                     }
581                   else if ((inf->label == _ecore_x_input_get_axis_label("Rel X")) ||
582                            (inf->label == _ecore_x_input_get_axis_label("Rel Y")) ||
583                            (inf->label == _ecore_x_input_get_axis_label("Rel Vert Wheel")) ||
584                            (inf->label == _ecore_x_input_get_axis_label("Rel Horiz Wheel")) ||
585                            (inf->label == _ecore_x_input_get_axis_label("Rel Dial")))
586                     {
587                        /* Ignore those: mouse. Values are in fact not relative.
588                         * No idea what is a "dial" event. */
589                     }
590                   else
591                     {
592                        axis_ptr->label = ECORE_AXIS_LABEL_UNKNOWN;
593                        axis_ptr->value = evd->valuators.values[j];
594                        axis_ptr++;
595                     }
596                   j++;
597                }
598           }
599      }
600
601    if ((compute_tilt) && ((axis_ptr + 2) <= (axis + n)))
602      {
603         double x = sin(tiltx);
604         double y = sin(tilty);
605         axis_ptr->label = ECORE_AXIS_LABEL_TILT;
606         axis_ptr->value = asin(sqrt((x * x) + (y * y)));
607         axis_ptr++;
608
609         /* note: the value of atan2(0,0) is implementation-defined */
610         axis_ptr->label = ECORE_AXIS_LABEL_AZIMUTH;
611         axis_ptr->value = atan2(y, x);
612         axis_ptr++;
613      }
614
615    /* update n to reflect actual count and realloc array to free excess */
616    n = (axis_ptr - axis);
617    if (n > 0)
618      {
619         /* event position in the window - most useful */
620         axis_ptr->label = ECORE_AXIS_LABEL_WINDOW_X;
621         axis_ptr->value = evd->event_x;
622         axis_ptr++;
623         axis_ptr->label = ECORE_AXIS_LABEL_WINDOW_Y;
624         axis_ptr->value = evd->event_y;
625         axis_ptr++;
626         n += 2;
627
628         shrunk_axis = realloc(axis, n * sizeof(Ecore_Axis));
629         if (shrunk_axis != NULL) axis = shrunk_axis;
630         _ecore_x_axis_update(evd->child ? evd->child : evd->event,
631                              evd->event, evd->root, evd->time, evd->deviceid,
632                              evd->detail, n, axis);
633      }
634    else
635      free(axis);
636 }
637 #endif /* ifdef ECORE_XI2 */
638
639 #ifdef ECORE_XI2
640 static XIDeviceInfo *
641 _ecore_x_input_device_lookup(int deviceid)
642 {
643    XIDeviceInfo *dev;
644    int i;
645
646    if (_ecore_x_xi2_devs)
647      {
648         for (i = 0; i < _ecore_x_xi2_num; i++)
649           {
650              dev = &(_ecore_x_xi2_devs[i]);
651              if (deviceid == dev->deviceid) return dev;
652           }
653      }
654    return NULL;
655 }
656 #endif
657
658 void
659 _ecore_x_input_handler(XEvent *xevent)
660 {
661 #ifdef ECORE_XI2
662    if (xevent->type != GenericEvent) return;
663
664    switch (xevent->xcookie.evtype)
665      {
666       case XI_RawMotion:
667       case XI_RawButtonPress:
668       case XI_RawButtonRelease:
669         _ecore_x_input_raw_handler(xevent);
670         break;
671
672       case XI_Motion:
673       case XI_ButtonPress:
674       case XI_ButtonRelease:
675 #ifdef ECORE_XI2_2
676       case XI_TouchUpdate:
677       case XI_TouchBegin:
678       case XI_TouchEnd:
679 #endif
680           {
681              XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
682              XIDeviceInfo *dev = _ecore_x_input_device_lookup(evd->deviceid);
683
684              if (!dev) return;
685
686              if ((dev->use == XISlavePointer) &&
687                  !(evd->flags & XIPointerEmulated))
688                {
689                   _ecore_x_input_multi_handler(xevent);
690                }
691              else if (dev->use == XIFloatingSlave)
692                _ecore_x_input_mouse_handler(xevent);
693
694              if (dev->use != XIMasterPointer)
695                _ecore_x_input_axis_handler(xevent, dev);
696           }
697         break;
698 #ifdef XI_TouchCancel
699       case XI_TouchCancel:
700           {
701              XITouchCancelEvent *evd = (XITouchCancelEvent *)(xevent->xcookie.data);
702              int devid = evd->deviceid;
703
704              if(!_ecore_x_input_touch_device_check(devid)) return;
705
706              INF("Handling XI_TouchCancel device(%d)", devid);
707
708              /* Currently X sends only one cancel event according to the touch device.
709                 But in the future, it maybe need several cancel events according to the touch.
710                 So it is better use button structure instead of creating new cancel structure.
711               */
712              _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_CANCEL,
713                                  evd->time,
714                                  0,   // state
715                                  0,   // button
716                                  0, 0,
717                                  0, 0,
718                                  evd->event,
719                                 (evd->child ? evd->child : evd->event),
720                                  evd->root,
721                                  1,   // same_screen
722                                  0, 1, 1,
723                                  0.0,   // pressure
724                                  0.0,   // angle
725                                  0, 0,
726                                  0, 0);
727           }
728         break;
729 #endif
730       default:
731         break;
732      }
733 #endif /* ifdef ECORE_XI2 */
734 }
735
736 EAPI Eina_Bool
737 ecore_x_input_multi_select(Ecore_X_Window win)
738 {
739 #ifdef ECORE_XI2
740    int i;
741    Eina_Bool find = EINA_FALSE;
742
743    if (!_ecore_x_xi2_devs)
744      return EINA_FALSE;
745
746    LOGFN(__FILE__, __LINE__, __FUNCTION__);
747    for (i = 0; i < _ecore_x_xi2_num; i++)
748      {
749         XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]);
750         XIEventMask eventmask;
751         unsigned char mask[4] = { 0 };
752         int update = 0;
753
754         eventmask.deviceid = dev->deviceid;
755         eventmask.mask_len = sizeof(mask);
756         eventmask.mask = mask;
757
758         if ((dev->use == XIFloatingSlave) || (dev->use == XISlavePointer))
759           {
760              XISetMask(mask, XI_ButtonPress);
761              XISetMask(mask, XI_ButtonRelease);
762              XISetMask(mask, XI_Motion);
763
764 #ifdef ECORE_XI2_2
765              Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
766              Ecore_X_Touch_Device_Info *info;
767              info = _ecore_x_input_touch_info_get(dev);
768
769              if (info)
770                {
771                   XISetMask(mask, XI_TouchUpdate);
772                   XISetMask(mask, XI_TouchBegin);
773                   XISetMask(mask, XI_TouchEnd);
774 #ifdef XI_TouchCancel
775                   XISetMask(mask, XI_TouchCancel);
776 #endif
777                   update = 1;
778
779                   l = eina_inlist_append(l, (Eina_Inlist *)info);
780                   _ecore_x_xi2_touch_info_list = l;
781                }
782 #endif /* #ifdef ECORE_XI2_2 */
783              update = 1;
784           }
785
786         if (update)
787           {
788              XISelectEvents(_ecore_x_disp, win, &eventmask, 1);
789              if (_ecore_xlib_sync) ecore_x_sync();
790              find = EINA_TRUE;
791           }
792      }
793
794    return find;
795 #else /* ifdef ECORE_XI2 */
796    return EINA_FALSE;
797 #endif /* ifdef ECORE_XI2 */
798 }
799
800 EAPI Eina_Bool
801 ecore_x_input_raw_select(Ecore_X_Window win)
802 {
803 #ifdef ECORE_XI2
804    XIEventMask emask;
805    unsigned char mask[4] = { 0 };
806
807    if (!_ecore_x_xi2_devs)
808      return EINA_FALSE;
809
810    LOGFN(__FILE__, __LINE__, __FUNCTION__);
811    emask.deviceid = XIAllMasterDevices;
812    emask.mask_len = sizeof(mask);
813    emask.mask = mask;
814 #ifdef XI_RawButtonPress
815    XISetMask(emask.mask, XI_RawButtonPress);
816 #endif
817 #ifdef XI_RawButtonRelease
818    XISetMask(emask.mask, XI_RawButtonRelease);
819 #endif
820 #ifdef XI_RawMotion
821    XISetMask(emask.mask, XI_RawMotion);
822 #endif
823
824    XISelectEvents(_ecore_x_disp, win, &emask, 1);
825    if (_ecore_xlib_sync) ecore_x_sync();
826
827    return EINA_TRUE;
828 #else
829    return EINA_FALSE;
830 #endif
831 }
832
833 EAPI Eina_Bool
834 _ecore_x_input_touch_devices_grab(Ecore_X_Window grab_win, Eina_Bool grab)
835 {
836 #ifdef ECORE_XI2
837    int i;
838
839    if (!_ecore_x_xi2_devs)
840      return EINA_FALSE;
841
842    Eina_Bool status = EINA_FALSE;
843
844    LOGFN(__FILE__, __LINE__, __FUNCTION__);
845    for (i = 0; i < _ecore_x_xi2_num; i++)
846      {
847         XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]);
848         int update = 0;
849         XIEventMask eventmask;
850         unsigned char mask[4] = { 0 };
851
852         eventmask.deviceid = XISlavePointer;
853         eventmask.mask_len = sizeof(mask);
854         eventmask.mask = mask;
855
856         if (dev->use == XISlavePointer)
857           {
858 #ifdef ECORE_XI2_2
859              Ecore_X_Touch_Device_Info *info;
860              info = _ecore_x_input_touch_info_get(dev);
861
862              if (info)
863                {
864                   XISetMask(mask, XI_TouchUpdate);
865                   XISetMask(mask, XI_TouchBegin);
866                   XISetMask(mask, XI_TouchEnd);
867 #ifdef XI_TouchCancel
868                   XISetMask(mask, XI_TouchCancel);
869 #endif
870                   update = 1;
871                   free(info);
872                }
873 #endif /* #ifdef ECORE_XI2_2 */
874           }
875
876         if (update)
877           {
878              if (grab) {
879                 status |= (XIGrabDevice(_ecore_x_disp, dev->deviceid, grab_win, CurrentTime,
880                            None, GrabModeAsync, GrabModeAsync, False, &eventmask) == GrabSuccess);
881                 _ecore_x_xi2_grabbed_devices_list = eina_list_append(_ecore_x_xi2_grabbed_devices_list, (void*)(intptr_t)dev->deviceid);
882              }
883              else {
884                 status |= (XIUngrabDevice(_ecore_x_disp, dev->deviceid, CurrentTime) == Success);
885                 _ecore_x_xi2_grabbed_devices_list = eina_list_remove(_ecore_x_xi2_grabbed_devices_list, (void*)(intptr_t)dev->deviceid);
886              }
887              if (_ecore_xlib_sync) ecore_x_sync();
888           }
889      }
890
891    return status;
892 #endif
893    return EINA_FALSE;
894 }
895
896 EAPI Eina_Bool
897 ecore_x_input_touch_devices_grab(Ecore_X_Window grab_win)
898 {
899    return _ecore_x_input_touch_devices_grab(grab_win, EINA_TRUE);
900 }
901
902 EAPI Eina_Bool
903 ecore_x_input_touch_devices_ungrab(void)
904 {
905    return _ecore_x_input_touch_devices_grab(0, EINA_FALSE);
906 }