8 #include "ecore_fb_private.h"
10 #define CLICK_THRESHOLD_DEFAULT 0.25
12 static Eina_List *_ecore_fb_li_devices = NULL;
14 static const char *_ecore_fb_li_kbd_syms[128 * 7] =
16 #include "ecore_fb_keytable.h"
19 /* Initial Copyright (C) Brad Hards (1999-2002),
20 * this function is used to tell if "bit" is set in "array"
21 * it selects a byte from the array, and does a boolean AND
22 * operation with a byte that only has the relevant bit set.
23 * eg. to check for the 12th bit, we do (array[1] & 1<<4).
24 * Moved to static inline in order to force compiler to otimized
25 * the unsued part away or force a link error if long has an unexpected
29 extern int long_has_neither_32_nor_64_bits(void);
31 test_bit(int bit, unsigned long *array)
33 if (sizeof(long) == 4)
34 return array[bit / 32] & (1 << (bit % 32));
35 else if (sizeof(long) == 8)
36 return array[bit / 64] & (1 << (bit % 64));
37 else long_has_neither_32_nor_64_bits();
41 _ecore_fb_li_device_event_key(Ecore_Fb_Input_Device *dev, struct input_event *iev)
43 if (!dev->listen) return;
45 /* check for basic keyboard keys */
46 if ((iev->code >= KEY_ESC) && (iev->code <= KEY_COMPOSE))
49 const char *keyname = _ecore_fb_li_kbd_syms[iev->code * 7];
51 /* check the key table */
54 /* its a repeated key, dont increment */
57 if (!strcmp(keyname, "Control_L"))
59 else if (!strcmp(keyname, "Control_R"))
61 else if (!strcmp(keyname, "Alt_L"))
63 else if (!strcmp(keyname, "Alt_R"))
65 else if (!strcmp(keyname, "Shift_L"))
66 dev->keyboard.shift++;
67 else if (!strcmp(keyname, "Shift_R"))
68 dev->keyboard.shift++;
69 else if (!strcmp(keyname, "Caps_Lock"))
70 dev->keyboard.lock = !dev->keyboard.lock;
71 if (dev->keyboard.ctrl > 2) dev->keyboard.ctrl = 2;
72 if (dev->keyboard.alt > 2) dev->keyboard.alt = 2;
73 if (dev->keyboard.shift > 2) dev->keyboard.shift = 2;
74 if (dev->keyboard.lock > 1) dev->keyboard.lock = 1;
79 if (!strcmp(keyname, "Control_L"))
81 else if (!strcmp(keyname, "Control_R"))
83 else if (!strcmp(keyname, "Alt_L"))
85 else if (!strcmp(keyname, "Alt_R"))
87 else if (!strcmp(keyname, "Shift_L"))
88 dev->keyboard.shift--;
89 else if (!strcmp(keyname, "Shift_R"))
90 dev->keyboard.shift--;
91 if (dev->keyboard.ctrl < 0) dev->keyboard.ctrl = 0;
92 if (dev->keyboard.alt < 0) dev->keyboard.alt = 0;
93 if (dev->keyboard.shift < 0) dev->keyboard.shift = 0;
94 if (dev->keyboard.lock < 0) dev->keyboard.lock = 0;
97 /* sending ecore_input_evas events */
100 if (dev->keyboard.shift) offset = 1;
101 else if (dev->keyboard.lock) offset = 2;
103 const char *key = _ecore_fb_li_kbd_syms[(iev->code * 7) + offset];
104 const char *compose = _ecore_fb_li_kbd_syms[(iev->code * 7) + 3 + offset];
106 if (dev->keyboard.ctrl)
108 const char *ts = _ecore_fb_li_kbd_syms[(iev->code * 7) + 3 + 3];
110 if (ts) compose = ts;
113 e = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) +
114 strlen(keyname) + (compose ? strlen(compose) : 0) + 3);
115 e->keyname = (char *)(e + 1);
116 e->key = e->keyname + strlen(keyname) + 1;
117 e->compose = (compose) ? e->key + strlen(key) + 1 : NULL;
118 e->string = e->compose;
120 strcpy((char *)e->keyname, keyname);
121 strcpy((char *)e->key, key);
123 strcpy((char *)e->compose, compose);
126 if (dev->keyboard.shift)
127 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
128 if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
129 if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
130 if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS;
132 e->timestamp = ecore_loop_time_get() * 1000.0;
133 e->window = (Ecore_Window)dev->window;
134 e->event_window = (Ecore_Window)dev->window;
135 e->root_window = (Ecore_Window)dev->window;
139 ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
141 ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
143 /* check for mouse button events */
144 else if ((iev->code >= BTN_MOUSE) && (iev->code < BTN_JOYSTICK))
147 Ecore_Event_Mouse_Button *e;
148 double current = ecore_loop_time_get();
150 button = ((iev->code & 0x00F) + 1);
151 // swap 2 and 3 to make middle and right butotn work right.
152 if (button == 3) button = 2;
153 else if (button == 2) button = 3;
156 dev->mouse.did_double = EINA_FALSE;
157 dev->mouse.did_triple = EINA_FALSE;
159 if (((current - dev->mouse.prev) <= dev->mouse.threshold) &&
160 (button == dev->mouse.prev_button))
162 dev->mouse.did_double = EINA_TRUE;
163 if (((current - dev->mouse.last) <= (2 * dev->mouse.threshold)) &&
164 (button == dev->mouse.last_button))
166 dev->mouse.did_triple = EINA_TRUE;
173 dev->mouse.last = dev->mouse.prev;
174 dev->mouse.prev = current;
175 dev->mouse.last_button = dev->mouse.prev_button;
176 dev->mouse.prev_button = button;
179 e = calloc(1, sizeof(Ecore_Event_Mouse_Button));
183 e->timestamp = current * 1000.0;
184 e->window = (Ecore_Window)dev->window;
185 e->event_window = (Ecore_Window)dev->window;
186 e->root_window = (Ecore_Window)dev->window;
190 if (dev->keyboard.shift)
191 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
192 if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
193 if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
194 if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS;
202 if (dev->mouse.did_double)
204 if (dev->mouse.did_triple)
208 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL);
210 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL);
215 _ecore_fb_li_device_event_rel(Ecore_Fb_Input_Device *dev, struct input_event *iev)
217 if (!dev->listen) return;
218 /* dispatch the button events if they are queued */
224 Ecore_Event_Mouse_Move *e;
225 if (iev->code == REL_X)
227 dev->mouse.x += iev->value;
228 if (dev->mouse.x > dev->mouse.w - 1)
229 dev->mouse.x = dev->mouse.w;
230 else if(dev->mouse.x < 0)
235 dev->mouse.y += iev->value;
236 if (dev->mouse.y > dev->mouse.h - 1)
237 dev->mouse.y = dev->mouse.h;
238 else if(dev->mouse.y < 0)
242 e = calloc(1, sizeof(Ecore_Event_Mouse_Move));
246 e->window = (Ecore_Window)dev->window;
247 e->event_window = (Ecore_Window)dev->window;
248 e->root_window = (Ecore_Window)dev->window;
252 if (dev->keyboard.shift) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
253 if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
254 if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
255 if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS;
262 e->timestamp = ecore_loop_time_get() * 1000.0;
264 ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
271 Ecore_Event_Mouse_Wheel *e;
273 e = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
279 if (iev->code == REL_HWHEEL) e->direction = 1;
281 e->root.x = dev->mouse.x;
282 e->root.y = dev->mouse.y;
284 e->window = (Ecore_Window)dev->window;
285 e->event_window = (Ecore_Window)dev->window;
286 e->root_window = (Ecore_Window)dev->window;
290 if (dev->keyboard.shift) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
291 if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
292 if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
293 if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS;
295 e->timestamp = ecore_loop_time_get() * 1000.0;
297 ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL);
307 _ecore_fb_li_device_event_abs(Ecore_Fb_Input_Device *dev, struct input_event *iev)
309 static int prev_pressure = 0;
312 if (!dev->listen) return;
316 if (dev->mouse.w != 0)
320 tmp = (int)((double)(iev->value - dev->mouse.min_w) / dev->mouse.rel_w);
321 if (tmp < 0) dev->mouse.x = 0;
322 else if (tmp > dev->mouse.w) dev->mouse.x = dev->mouse.w;
323 else dev->mouse.x = tmp;
324 dev->mouse.event = ECORE_EVENT_MOUSE_MOVE;
329 if (dev->mouse.h != 0)
333 tmp = (int)((double)(iev->value - dev->mouse.min_h) / dev->mouse.rel_h);
334 if (tmp < 0) dev->mouse.y = 0;
335 else if (tmp > dev->mouse.h) dev->mouse.y = dev->mouse.h;
336 else dev->mouse.y = tmp;
337 dev->mouse.event = ECORE_EVENT_MOUSE_MOVE;
342 pressure = iev->value;
343 if ((pressure) && (!prev_pressure))
345 /* DOWN: mouse is down, but was not before */
346 dev->mouse.event = ECORE_EVENT_MOUSE_BUTTON_DOWN;
348 else if ((!pressure) && (prev_pressure))
350 /* UP: mouse was down, but is not now */
351 dev->mouse.event = ECORE_EVENT_MOUSE_BUTTON_UP;
353 prev_pressure = pressure;
359 _ecore_fb_li_device_event_syn(Ecore_Fb_Input_Device *dev, struct input_event *iev __UNUSED__)
361 if (!dev->listen) return;
363 if (dev->mouse.event == ECORE_EVENT_MOUSE_MOVE)
365 Ecore_Event_Mouse_Move *ev;
366 ev = calloc(1,sizeof(Ecore_Event_Mouse_Move));
367 ev->x = dev->mouse.x;
368 ev->y = dev->mouse.y;
371 ev->timestamp = ecore_loop_time_get() * 1000.0;
372 ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
374 else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_DOWN)
376 Ecore_Event_Mouse_Button *ev;
377 ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
378 ev->x = dev->mouse.x;
379 ev->y = dev->mouse.y;
383 ev->timestamp = ecore_loop_time_get() * 1000.0;
384 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
386 else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_UP)
388 Ecore_Event_Mouse_Button *ev;
389 ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
390 ev->x = dev->mouse.x;
391 ev->y = dev->mouse.y;
395 ev->timestamp = ecore_loop_time_get() * 1000.0;
396 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
401 _ecore_fb_li_device_fd_callback(void *data, Ecore_Fd_Handler *fdh __UNUSED__)
403 Ecore_Fb_Input_Device *dev;
404 struct input_event ev[64];
408 dev = (Ecore_Fb_Input_Device*)data;
409 /* read up to 64 events at once */
410 len = read(dev->fd, &ev, sizeof(ev));
411 for(i = 0; i < (int)(len / sizeof(ev[0])); i++)
416 _ecore_fb_li_device_event_syn(dev, &ev[i]);
419 _ecore_fb_li_device_event_abs(dev, &ev[i]);
422 _ecore_fb_li_device_event_rel(dev, &ev[i]);
425 _ecore_fb_li_device_event_key(dev, &ev[i]);
435 * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions.
441 * @brief Set the listen mode for an input device .
443 * @param dev The device to set the mode of.
444 * @param listen @c EINA_FALSE to disable listening mode, @c EINA_TRUE to
447 * This function enables or disables listening on the input device @p dev.
448 * If @p listen is @c EINA_FALSE, listening mode is disabled, if it is
449 * @c EINA_TRUE, it is enabled.
452 ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, Eina_Bool listen)
455 if ((listen && dev->listen) || (!listen && !dev->listen)) return;
458 /* if the device already had a handler */
460 dev->handler = ecore_main_fd_handler_add(dev->fd, ECORE_FD_READ, _ecore_fb_li_device_fd_callback, dev, NULL, NULL);
463 dev->listen = listen;
467 # define EV_CNT (EV_MAX+1)
471 * @brief Associates an input device with the given @ref Ecore_Evas_Group.
473 * @param dev The input being associated with an @ref Ecore_Evas_Group (not @c NULL).
474 * @param window The window which this input is being associated to.
475 * @c NULL will remove any previous association.
477 * Events generated by this device will have a pointer to @p window. If this @p
478 * window is registered with ecore_event_window_register() or
479 * ecore_evas_input_event_register(), respective evas events will be delivered
480 * by the ecore_input_evas system. An example can be seen in the following code:
483 * Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 800, 600, NULL);
485 * ecore_evas_input_event_register(ee);
487 * device = ecore_fb_input_device_open(device_path);
489 * ecore_fb_input_device_window_set(device, ee);
493 * On the previous code, all input captured on the mentioned device will be
494 * delivered to the @c Ecore_Evas @c ee.
499 ecore_fb_input_device_window_set(Ecore_Fb_Input_Device *dev, void *window)
503 dev->window = window;
507 * @brief Open an input device.
509 * @param dev The device to open.
510 * @return The @ref Ecore_Fb_Input_Device object that has been opened.
512 * This function opens the input device named @p dev and returns the
513 * object for it, or returns @c NULL on failure.
515 EAPI Ecore_Fb_Input_Device *
516 ecore_fb_input_device_open(const char *dev)
518 Ecore_Fb_Input_Device *device;
519 unsigned long event_type_bitmask[EV_CNT / 32 + 1];
523 if (!dev) return NULL;
524 device = calloc(1, sizeof(Ecore_Fb_Input_Device));
525 if (!device) return NULL;
527 if ((fd = open(dev, O_RDONLY, O_NONBLOCK)) < 0)
529 fprintf(stderr, "[ecore_fb_li:device_open] %s %s", dev, strerror(errno));
532 /* query capabilities */
533 if (ioctl(fd, EVIOCGBIT(0, EV_MAX), event_type_bitmask) < 0)
535 fprintf(stderr,"[ecore_fb_li:device_open] query capabilities %s %s", dev, strerror(errno));
539 device->info.name = calloc(256, sizeof(char));
540 if (ioctl(fd, EVIOCGNAME(sizeof(char) * 256), device->info.name) < 0)
542 fprintf(stderr, "[ecore_fb_li:device_open] get name %s %s", dev, strerror(errno));
543 strcpy(device->info.name, "Unknown");
546 device->info.dev = strdup(dev);
548 device->mouse.threshold = CLICK_THRESHOLD_DEFAULT;
551 for (event_type = 0; event_type < EV_MAX; event_type++)
553 if (!test_bit(event_type, event_type_bitmask))
560 device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS;
563 device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_RELATIVE;
566 device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE;
580 _ecore_fb_li_devices = eina_list_append(_ecore_fb_li_devices, device);
591 * @brief Close the given device.
593 * @param dev The device to close
595 * This function closes the device @p dev. If @p dev is @c NULL, this
596 * function does nothing.
599 ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev)
601 if (!dev || dev->fd < 0) return;
604 /* remove the element from the list */
605 _ecore_fb_li_devices = eina_list_remove(_ecore_fb_li_devices, dev);
611 * @brief Set the axis size of the given device.
613 * @param dev The device to set the axis size to.
614 * @param w The width of the axis.
615 * @param h The height of the axis.
617 * This function sets set the width @p w and height @p h of the axis
618 * of device @p dev. If @p dev is a relative input device, a width and
619 * height must set for it. If its absolute set the ioctl correctly, if
620 * not, unsupported device.
623 ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h)
626 if ((w < 0) || (h < 0)) return;
628 * this code is for a touchscreen device,
629 * make it configurable (ABSOLUTE | RELATIVE)
631 if (dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE)
633 /* FIXME looks like some kernels dont include this struct */
634 struct input_absinfo abs_features;
636 ioctl(dev->fd, EVIOCGABS(ABS_X), &abs_features);
637 dev->mouse.min_w = abs_features.minimum;
638 dev->mouse.rel_w = (double)(abs_features.maximum - abs_features.minimum)/(double)(w);
640 ioctl(dev->fd, EVIOCGABS(ABS_Y), &abs_features);
641 dev->mouse.min_h = abs_features.minimum;
642 dev->mouse.rel_h = (double)(abs_features.maximum - abs_features.minimum)/(double)(h);
644 else if (!(dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE))
647 /* update the local values */
648 if (dev->mouse.x > w - 1) dev->mouse.x = w -1;
649 if (dev->mouse.y > h - 1) dev->mouse.y = h -1;
655 * @brief Retrieve the name of the given device.
657 * @param dev The device to get the name from.
658 * @return The name of the device.
660 * This function returns the name of the device @p dev. If @p dev is
661 * @c NULL, this function returns @c NULL.
664 ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev)
666 if (!dev) return NULL;
667 return dev->info.name;
671 * @brief Retrieve the capability of the given device.
673 * @param dev The device to get the name from.
674 * @return The capability of the device.
676 * This function returns the capability of the device @p dev. If @p dev is
677 * @c NULL, this function returns ECORE_FB_INPUT_DEVICE_CAP_NONE.
679 EAPI Ecore_Fb_Input_Device_Cap
680 ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev)
682 if (!dev) return ECORE_FB_INPUT_DEVICE_CAP_NONE;
683 return dev->info.cap;
687 * @brief Set the threshold of mouse clicks of the given device.
689 * @param dev The device to set the threshodl mouse click to.
690 * @param threshold The threshold value.
692 * This function sets the threshold of mouse clicks of the device
693 * @p dev to @p threshold. If @p dev is @c NULL, this function does
697 ecore_fb_input_device_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold)
700 if ((threshold == dev->mouse.threshold) || (threshold == 0)) return;
701 dev->mouse.threshold = threshold;
705 * @brief Get the threshold of mouse clicks of the given device.
707 * @param dev The device to set the threshodl mouse click from.
708 * @return The threshold value.
710 * This function returns the threshold of mouse clicks of the device
711 * @p dev. If @p dev is @c NULL, this function returns 0.0.
714 ecore_fb_input_device_threshold_click_get(Ecore_Fb_Input_Device *dev)
717 return dev->mouse.threshold;