3 #endif /* ifdef HAVE_CONFIG_H */
9 #include "ecore_x_private.h"
13 #include "Ecore_Input.h"
14 #endif /* ifdef ECORE_XI2 */
16 int _ecore_x_xi2_opcode = -1;
18 #ifndef XIPointerEmulated
19 #define XIPointerEmulated (1 << 16)
24 #ifndef XITouchEmulatingPointer
25 #define XITouchEmulatingPointer (1 << 17)
28 typedef struct _Ecore_X_Touch_Device_Info
36 } Ecore_X_Touch_Device_Info;
37 #endif /* ifdef ECORE_XI2_2 */
39 static XIDeviceInfo *_ecore_x_xi2_devs = NULL;
40 static int _ecore_x_xi2_num = 0;
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 */
48 _ecore_x_input_init(void)
52 int major = XI_2_Major, minor = XI_2_Minor;
54 if (!XQueryExtension(_ecore_x_disp, "XInputExtension",
55 &_ecore_x_xi2_opcode, &event, &error))
57 _ecore_x_xi2_opcode = -1;
61 if (XIQueryVersion(_ecore_x_disp, &major, &minor) == BadRequest)
63 _ecore_x_xi2_opcode = -1;
67 _ecore_x_xi2_devs = XIQueryDevice(_ecore_x_disp, XIAllDevices,
69 #endif /* ifdef ECORE_XI2 */
75 _ecore_x_input_touch_info_clear(void)
77 Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
78 Ecore_X_Touch_Device_Info *info = NULL;
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);
88 _ecore_x_xi2_touch_info_list = NULL;
90 #endif /* ifdef ECORE_XI2_2 */
91 #endif /* ifdef ECORE_XI2 */
95 _ecore_x_input_get_axis_label(char *axis_name)
97 static Atom *atoms = NULL;
98 static char *names[] =
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"
105 int n = sizeof(names) / sizeof(names[0]);
108 if (EINA_UNLIKELY(atoms == NULL))
110 atoms = calloc(n, sizeof(Atom));
111 if (!atoms) return 0;
113 if (!XInternAtoms(_ecore_x_disp, names, n, 1, atoms))
121 for (i = 0; i < n; i++)
123 if (!strcmp(axis_name, names[i])) return atoms[i];
128 #endif /* ifdef ECORE_XI2 */
131 _ecore_x_input_shutdown(void)
134 if (_ecore_x_xi2_devs)
136 XIFreeDeviceInfo(_ecore_x_xi2_devs);
137 _ecore_x_xi2_devs = NULL;
139 _ecore_x_input_touch_info_clear();
140 #endif /* ifdef ECORE_XI2_2 */
143 _ecore_x_xi2_num = 0;
144 _ecore_x_xi2_opcode = -1;
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 */
155 # ifdef XI_TouchCancel
157 _ecore_x_input_touch_device_check(int devid)
159 Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
160 Ecore_X_Touch_Device_Info *info = NULL;
162 if ((!_ecore_x_xi2_devs) || (!_ecore_x_xi2_touch_info_list))
165 EINA_INLIST_FOREACH(l, info)
166 if (info->devid == devid) return EINA_TRUE;
172 _ecore_x_input_touch_index_get(int devid, int detail, int event_type)
175 Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
176 Ecore_X_Touch_Device_Info *info = NULL;
178 if ((!_ecore_x_xi2_devs) || (!_ecore_x_xi2_touch_info_list))
181 EINA_INLIST_FOREACH(l, info)
182 if (info->devid == devid) break;
184 if ((!info) || (!info->slot)) return 0;
186 for (i = 0; i < info->max_touch ; i++)
188 int *p = &(info->slot[i]);
190 if ((event_type == XI_TouchBegin) && (*p < 0))
195 else if (*p == detail)
205 _ecore_x_input_touch_index_clear(int devid, int idx)
207 Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
208 Ecore_X_Touch_Device_Info *info = NULL;
210 if ((!_ecore_x_xi2_devs) || (!_ecore_x_xi2_touch_info_list))
213 EINA_INLIST_FOREACH(l, info)
215 if ((info->devid == devid) && (info->slot))
217 info->slot[idx] = -1;
223 static Ecore_X_Touch_Device_Info *
224 _ecore_x_input_touch_info_get(XIDeviceInfo *dev)
228 XITouchClassInfo *t = NULL;
229 Ecore_X_Touch_Device_Info *info = NULL;
234 for (k = 0; k < dev->num_classes; k++)
236 XIAnyClassInfo *clas = dev->classes[k];
238 if (clas && (clas->type == XITouchClass))
240 t = (XITouchClassInfo *)clas;
245 if (t && (t->type == XITouchClass))
247 info = calloc(1, sizeof(Ecore_X_Touch_Device_Info));
248 if (!info) return NULL;
250 slot = malloc(sizeof(int) * (t->num_touches + 1));
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);
267 #endif /* ifdef ECORE_XI2_2 */
271 _ecore_x_input_raw_handler(XEvent *xevent)
274 if (xevent->type != GenericEvent) return;
276 switch (xevent->xcookie.evtype)
278 #ifdef XI_RawButtonPress
279 case XI_RawButtonPress:
280 ecore_event_add(ECORE_X_RAW_BUTTON_PRESS, NULL, NULL, NULL);
283 #ifdef XI_RawButtonRelease
284 case XI_RawButtonRelease:
285 ecore_event_add(ECORE_X_RAW_BUTTON_RELEASE, NULL, NULL, NULL);
290 ecore_event_add(ECORE_X_RAW_MOTION, NULL, NULL, NULL);
294 #endif /* ifdef ECORE_XI2 */
299 _ecore_x_input_grabbed_is(int deviceId)
304 EINA_LIST_FOREACH(_ecore_x_xi2_grabbed_devices_list, l, id)
306 if (deviceId == (intptr_t)id)
312 #endif /* ifdef ECORE_XI2_2 */
315 _ecore_x_input_mouse_handler(XEvent *xevent)
318 if (xevent->type != GenericEvent) return;
320 XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
321 int devid = evd->deviceid;
323 switch (xevent->xcookie.evtype)
326 INF("Handling XI_Motion");
330 evd->event_x, evd->event_y,
331 evd->root_x, evd->root_y,
333 (evd->child ? evd->child : evd->event),
339 evd->event_x, evd->event_y,
340 evd->root_x, evd->root_y);
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);
346 (ECORE_EVENT_MOUSE_BUTTON_DOWN,
350 evd->event_x, evd->event_y,
351 evd->root_x, evd->root_y,
353 (evd->child ? evd->child : evd->event),
359 evd->event_x, evd->event_y,
360 evd->root_x, evd->root_y);
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);
366 (ECORE_EVENT_MOUSE_BUTTON_UP,
370 evd->event_x, evd->event_y,
371 evd->root_x, evd->root_y,
373 (evd->child ? evd->child : evd->event),
379 evd->event_x, evd->event_y,
380 evd->root_x, evd->root_y);
383 #endif /* ifdef ECORE_XI2 */
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.
389 _ecore_x_input_multi_handler(XEvent *xevent)
392 if (xevent->type != GenericEvent) return;
394 switch (xevent->xcookie.evtype)
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,
406 evd->event_x, evd->event_y,
407 evd->root_x, evd->root_y,
409 (evd->child ? evd->child : evd->event),
415 evd->event_x, evd->event_y,
416 evd->root_x, evd->root_y);
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,
431 evd->event_x, evd->event_y,
432 evd->root_x, evd->root_y,
434 (evd->child ? evd->child : evd->event),
440 evd->event_x, evd->event_y,
441 evd->root_x, evd->root_y);
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))
452 _ecore_x_input_touch_index_clear(devid, i);
455 INF("Handling XI_TouchEnd");
456 _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP,
460 evd->event_x, evd->event_y,
461 evd->root_x, evd->root_y,
463 (evd->child ? evd->child : evd->event),
469 evd->event_x, evd->event_y,
470 evd->root_x, evd->root_y);
471 _ecore_x_input_touch_index_clear(devid, i);
474 #endif /* ifdef ECORE_XI2_2 */
478 #endif /* ifdef ECORE_XI2 */
483 _ecore_x_count_bits(unsigned long n)
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 */
493 _ecore_x_input_axis_handler(XEvent *xevent, XIDeviceInfo *dev)
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;
500 double tiltx = 0, tilty = 0;
501 Eina_Bool compute_tilt = EINA_FALSE;
502 Ecore_Axis *axis = calloc(n, sizeof(Ecore_Axis));
504 Ecore_Axis *axis_ptr = axis;
505 Ecore_Axis *shrunk_axis;
507 for (i = 0; i < dev->num_classes; i++)
509 if (dev->classes[i]->type == XIValuatorClass)
511 XIValuatorClassInfo *inf = ((XIValuatorClassInfo *)dev->classes[i]);
513 if (*evd->valuators.mask & (1 << inf->number))
515 if (inf->label == _ecore_x_input_get_axis_label("Abs X"))
517 int x = evd->valuators.values[j];
518 axis_ptr->label = ECORE_AXIS_LABEL_X;
521 if (inf->max > inf->min)
523 axis_ptr->label = ECORE_AXIS_LABEL_NORMAL_X;
524 axis_ptr->value = (x - inf->min) / (inf->max - inf->min);
528 else if (inf->label == _ecore_x_input_get_axis_label("Abs Y"))
530 int y = evd->valuators.values[j];
531 axis_ptr->label = ECORE_AXIS_LABEL_Y;
534 if (inf->max > inf->min)
536 axis_ptr->label = ECORE_AXIS_LABEL_NORMAL_Y;
537 axis_ptr->value = (y - inf->min) / (inf->max - inf->min);
541 else if (inf->label == _ecore_x_input_get_axis_label("Abs Pressure"))
543 axis_ptr->label = ECORE_AXIS_LABEL_PRESSURE;
544 axis_ptr->value = (evd->valuators.values[j] - inf->min) / (inf->max - inf->min);
547 else if (inf->label == _ecore_x_input_get_axis_label("Abs Distance"))
549 axis_ptr->label = ECORE_AXIS_LABEL_DISTANCE;
550 axis_ptr->value = (evd->valuators.values[j] - inf->min) / (inf->max - inf->min);
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")))
556 axis_ptr->label = ECORE_AXIS_LABEL_TWIST;
557 if (inf->resolution == 1)
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;
565 axis_ptr->value = evd->valuators.values[j] / inf->resolution;
569 else if (inf->label == _ecore_x_input_get_axis_label("Abs Tilt X"))
571 tiltx = evd->valuators.values[j] / inf->resolution;
572 compute_tilt = EINA_TRUE;
573 /* don't increment axis_ptr */
575 else if (inf->label == _ecore_x_input_get_axis_label("Abs Tilt Y"))
577 tilty = -evd->valuators.values[j] / inf->resolution;
578 compute_tilt = EINA_TRUE;
579 /* don't increment axis_ptr */
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")))
587 /* Ignore those: mouse. Values are in fact not relative.
588 * No idea what is a "dial" event. */
592 axis_ptr->label = ECORE_AXIS_LABEL_UNKNOWN;
593 axis_ptr->value = evd->valuators.values[j];
601 if ((compute_tilt) && ((axis_ptr + 2) <= (axis + n)))
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)));
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);
615 /* update n to reflect actual count and realloc array to free excess */
616 n = (axis_ptr - axis);
619 /* event position in the window - most useful */
620 axis_ptr->label = ECORE_AXIS_LABEL_WINDOW_X;
621 axis_ptr->value = evd->event_x;
623 axis_ptr->label = ECORE_AXIS_LABEL_WINDOW_Y;
624 axis_ptr->value = evd->event_y;
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);
637 #endif /* ifdef ECORE_XI2 */
640 static XIDeviceInfo *
641 _ecore_x_input_device_lookup(int deviceid)
646 if (_ecore_x_xi2_devs)
648 for (i = 0; i < _ecore_x_xi2_num; i++)
650 dev = &(_ecore_x_xi2_devs[i]);
651 if (deviceid == dev->deviceid) return dev;
659 _ecore_x_input_handler(XEvent *xevent)
662 if (xevent->type != GenericEvent) return;
664 switch (xevent->xcookie.evtype)
667 case XI_RawButtonPress:
668 case XI_RawButtonRelease:
669 _ecore_x_input_raw_handler(xevent);
674 case XI_ButtonRelease:
681 XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
682 XIDeviceInfo *dev = _ecore_x_input_device_lookup(evd->deviceid);
686 if ((dev->use == XISlavePointer) &&
687 !(evd->flags & XIPointerEmulated))
689 _ecore_x_input_multi_handler(xevent);
691 else if (dev->use == XIFloatingSlave)
692 _ecore_x_input_mouse_handler(xevent);
694 if (dev->use != XIMasterPointer)
695 _ecore_x_input_axis_handler(xevent, dev);
698 #ifdef XI_TouchCancel
701 XITouchCancelEvent *evd = (XITouchCancelEvent *)(xevent->xcookie.data);
702 int devid = evd->deviceid;
704 if(!_ecore_x_input_touch_device_check(devid)) return;
706 INF("Handling XI_TouchCancel device(%d)", devid);
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.
712 _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_CANCEL,
719 (evd->child ? evd->child : evd->event),
733 #endif /* ifdef ECORE_XI2 */
737 ecore_x_input_multi_select(Ecore_X_Window win)
741 Eina_Bool find = EINA_FALSE;
743 if (!_ecore_x_xi2_devs)
746 LOGFN(__FILE__, __LINE__, __FUNCTION__);
747 for (i = 0; i < _ecore_x_xi2_num; i++)
749 XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]);
750 XIEventMask eventmask;
751 unsigned char mask[4] = { 0 };
754 eventmask.deviceid = dev->deviceid;
755 eventmask.mask_len = sizeof(mask);
756 eventmask.mask = mask;
758 if ((dev->use == XIFloatingSlave) || (dev->use == XISlavePointer))
760 XISetMask(mask, XI_ButtonPress);
761 XISetMask(mask, XI_ButtonRelease);
762 XISetMask(mask, XI_Motion);
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);
771 XISetMask(mask, XI_TouchUpdate);
772 XISetMask(mask, XI_TouchBegin);
773 XISetMask(mask, XI_TouchEnd);
774 #ifdef XI_TouchCancel
775 XISetMask(mask, XI_TouchCancel);
779 l = eina_inlist_append(l, (Eina_Inlist *)info);
780 _ecore_x_xi2_touch_info_list = l;
782 #endif /* #ifdef ECORE_XI2_2 */
788 XISelectEvents(_ecore_x_disp, win, &eventmask, 1);
789 if (_ecore_xlib_sync) ecore_x_sync();
795 #else /* ifdef ECORE_XI2 */
797 #endif /* ifdef ECORE_XI2 */
801 ecore_x_input_raw_select(Ecore_X_Window win)
805 unsigned char mask[4] = { 0 };
807 if (!_ecore_x_xi2_devs)
810 LOGFN(__FILE__, __LINE__, __FUNCTION__);
811 emask.deviceid = XIAllMasterDevices;
812 emask.mask_len = sizeof(mask);
814 #ifdef XI_RawButtonPress
815 XISetMask(emask.mask, XI_RawButtonPress);
817 #ifdef XI_RawButtonRelease
818 XISetMask(emask.mask, XI_RawButtonRelease);
821 XISetMask(emask.mask, XI_RawMotion);
824 XISelectEvents(_ecore_x_disp, win, &emask, 1);
825 if (_ecore_xlib_sync) ecore_x_sync();
834 _ecore_x_input_touch_devices_grab(Ecore_X_Window grab_win, Eina_Bool grab)
839 if (!_ecore_x_xi2_devs)
842 Eina_Bool status = EINA_FALSE;
844 LOGFN(__FILE__, __LINE__, __FUNCTION__);
845 for (i = 0; i < _ecore_x_xi2_num; i++)
847 XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]);
849 XIEventMask eventmask;
850 unsigned char mask[4] = { 0 };
852 eventmask.deviceid = XISlavePointer;
853 eventmask.mask_len = sizeof(mask);
854 eventmask.mask = mask;
856 if (dev->use == XISlavePointer)
859 Ecore_X_Touch_Device_Info *info;
860 info = _ecore_x_input_touch_info_get(dev);
864 XISetMask(mask, XI_TouchUpdate);
865 XISetMask(mask, XI_TouchBegin);
866 XISetMask(mask, XI_TouchEnd);
867 #ifdef XI_TouchCancel
868 XISetMask(mask, XI_TouchCancel);
873 #endif /* #ifdef ECORE_XI2_2 */
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);
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);
887 if (_ecore_xlib_sync) ecore_x_sync();
897 ecore_x_input_touch_devices_grab(Ecore_X_Window grab_win)
899 return _ecore_x_input_touch_devices_grab(grab_win, EINA_TRUE);
903 ecore_x_input_touch_devices_ungrab(void)
905 return _ecore_x_input_touch_devices_grab(0, EINA_FALSE);