b25c28ee860fca6e491bb029966a5525490b01ed
[profile/ivi/ecore.git] / src / lib / ecore_fb / ecore_fb_li.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include "Ecore_Fb.h"
6 #include "ecore_fb_private.h"
7
8 #define CLICK_THRESHOLD_DEFAULT 0.25
9
10 static Eina_List *_ecore_fb_li_devices = NULL;
11
12 static const char *_ecore_fb_li_kbd_syms[128 * 6] =
13 {
14 #include "ecore_fb_keytable.h"
15 };
16
17 /* Initial Copyright (C) Brad Hards (1999-2002),
18  * this function is used to tell if "bit" is set in "array"
19  * it selects a byte from the array, and does a boolean AND
20  * operation with a byte that only has the relevant bit set.
21  * eg. to check for the 12th bit, we do (array[1] & 1<<4).
22  * Moved to static inline in order to force compiler to otimized
23  * the unsued part away or force a link error if long has an unexpected
24  * size.
25  *                                                - bigeasy
26  */
27 extern int long_has_neither_32_nor_64_bits(void);
28 static inline int
29 test_bit(int bit, unsigned long *array)
30 {
31    if (sizeof(long) == 4)
32       return array[bit / 32] & (1 << (bit % 32));
33    else if (sizeof(long) == 8)
34       return array[bit / 64] & (1 << (bit % 64));
35    else long_has_neither_32_nor_64_bits();
36 }
37
38 static void
39 _ecore_fb_li_event_free_key_down(void *data __UNUSED__, void *ev)
40 {
41    Ecore_Fb_Event_Key_Up *e;
42
43    e = ev;
44    free(e->keyname);
45    if (e->keysymbol) free(e->keysymbol);
46    if (e->key_compose) free(e->key_compose);
47    free(e);
48 }
49
50 static void
51 _ecore_fb_li_event_free_key_up(void *data __UNUSED__, void *ev)
52 {
53    Ecore_Fb_Event_Key_Up *e;
54
55    e = ev;
56    free(e->keyname);
57    if (e->keysymbol) free(e->keysymbol);
58    if (e->key_compose) free(e->key_compose);
59    free(e);
60 }
61
62 static void
63 _ecore_fb_li_device_event_key(Ecore_Fb_Input_Device *dev, struct input_event *iev)
64 {
65    if (!dev->listen) return;
66
67    /* check for basic keyboard keys */
68    if ((iev->code >= KEY_ESC) && (iev->code <= KEY_COMPOSE))
69      {
70         /* check the key table */
71         if (iev->value)
72           {
73              int offset = 0;
74              Ecore_Fb_Event_Key_Down *ev;
75
76              ev = calloc(1, sizeof(Ecore_Fb_Event_Key_Down));
77              if (dev->keyboard.shift) offset = 1;
78              else if (dev->keyboard.lock) offset = 2;
79              ev->keyname = strdup(_ecore_fb_li_kbd_syms[iev->code * 6]);
80
81              ev->keysymbol = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + offset]);
82              ev->key_compose = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + 3 + offset]);
83              ev->dev = dev;
84              ecore_event_add(ECORE_FB_EVENT_KEY_DOWN, ev, _ecore_fb_li_event_free_key_down, NULL);
85              /* its a repeated key, dont increment */
86              if (iev->value == 2)
87                 return;
88              if (!strcmp(ev->keyname, "Control_L"))
89                 dev->keyboard.ctrl++;
90              else if (!strcmp(ev->keyname, "Control_R"))
91                 dev->keyboard.ctrl++;
92              else if (!strcmp(ev->keyname, "Alt_L"))
93                 dev->keyboard.alt++;
94              else if (!strcmp(ev->keyname, "Alt_R"))
95                 dev->keyboard.alt++;
96              else if (!strcmp(ev->keyname, "Shift_L"))
97                 dev->keyboard.shift++;
98              else if (!strcmp(ev->keyname, "Shift_R"))
99                 dev->keyboard.shift++;
100              else if (!strcmp(ev->keyname, "Caps_Lock"))
101                 dev->keyboard.lock++;
102              if (dev->keyboard.ctrl > 2) dev->keyboard.ctrl = 2;
103              if (dev->keyboard.alt > 2) dev->keyboard.alt = 2;
104              if (dev->keyboard.shift > 2) dev->keyboard.shift = 2;
105              if (dev->keyboard.lock > 1) dev->keyboard.lock = 1;
106           }
107         else
108           {
109              int offset = 0;
110              Ecore_Fb_Event_Key_Up *ev;
111
112              ev = calloc(1, sizeof(Ecore_Fb_Event_Key_Up));
113              if (dev->keyboard.shift) offset = 1;
114              else if (dev->keyboard.lock) offset = 2;
115              ev->keyname = strdup(_ecore_fb_li_kbd_syms[iev->code * 6]);
116
117              ev->keysymbol = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + offset]);
118              ev->key_compose = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + 3 + offset]);
119              ev->dev = dev;
120              ecore_event_add(ECORE_FB_EVENT_KEY_UP, ev, _ecore_fb_li_event_free_key_up, NULL);
121              if (!strcmp(ev->keyname, "Control_L"))
122                 dev->keyboard.ctrl--;
123              else if (!strcmp(ev->keyname, "Control_R"))
124                 dev->keyboard.ctrl--;
125              else if (!strcmp(ev->keyname, "Alt_L"))
126                 dev->keyboard.alt--;
127              else if (!strcmp(ev->keyname, "Alt_R"))
128                 dev->keyboard.alt--;
129              else if (!strcmp(ev->keyname, "Shift_L"))
130                 dev->keyboard.shift--;
131              else if (!strcmp(ev->keyname, "Shift_R"))
132                 dev->keyboard.shift--;
133              else if (!strcmp(ev->keyname, "Caps_Lock"))
134                 dev->keyboard.lock--;
135              if (dev->keyboard.ctrl < 0) dev->keyboard.ctrl = 0;
136              if (dev->keyboard.alt < 0) dev->keyboard.alt = 0;
137              if (dev->keyboard.shift < 0) dev->keyboard.shift = 0;
138              if (dev->keyboard.lock < 0) dev->keyboard.lock = 0;
139           }
140      }
141    /* check for mouse button events */
142    else if ((iev->code >= BTN_MOUSE) && (iev->code < BTN_JOYSTICK))
143      {
144         int button;
145
146         button = ((iev->code & 0x00F) + 1);
147         if (iev->value)
148           {
149              Ecore_Fb_Event_Mouse_Button_Down *ev;
150              double current;
151
152              ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down));
153              ev->dev = dev;
154              ev->button = button;
155              ev->x = dev->mouse.x;
156              ev->y = dev->mouse.y;
157
158              current = ecore_time_get();
159              if ((current - dev->mouse.prev) <= dev->mouse.threshold)
160                 ev->double_click = 1;
161              if ((current - dev->mouse.last) <= (2 * dev->mouse.threshold))
162                {
163                   ev->triple_click = 1;
164                   /* reset */
165                   dev->mouse.prev = 0;
166                   dev->mouse.last = 0;
167                   current = 0;
168                }
169              else
170                {
171                   /* update values */
172                   dev->mouse.last = dev->mouse.prev;
173                   dev->mouse.prev = current;
174                }
175              ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, ev, NULL ,NULL);
176           }
177         else
178           {
179              Ecore_Fb_Event_Mouse_Button_Up *ev;
180
181              ev = calloc(1,sizeof(Ecore_Fb_Event_Mouse_Button_Up));
182              ev->dev = dev;
183              ev->button = button;
184              ev->x = dev->mouse.x;
185              ev->y = dev->mouse.y;
186              ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, ev, NULL ,NULL);
187           }
188      }
189 }
190
191 static void
192 _ecore_fb_li_device_event_rel(Ecore_Fb_Input_Device *dev, struct input_event *iev)
193 {
194    if (!dev->listen) return;
195    /* dispatch the button events if they are queued */
196    switch (iev->code)
197      {
198      case REL_X:
199      case REL_Y:
200           {
201              Ecore_Fb_Event_Mouse_Move *ev;
202              if(iev->code == REL_X)
203                {
204                   dev->mouse.x += iev->value;
205                   if(dev->mouse.x > dev->mouse.w - 1)
206                      dev->mouse.x = dev->mouse.w;
207                   else if(dev->mouse.x < 0)
208                      dev->mouse.x = 0;
209                }
210              else
211                {
212                   dev->mouse.y += iev->value;
213                   if(dev->mouse.y > dev->mouse.h - 1)
214                      dev->mouse.y = dev->mouse.h;
215                   else if(dev->mouse.y < 0)
216                      dev->mouse.y = 0;
217                }
218              ev = calloc(1,sizeof(Ecore_Fb_Event_Mouse_Move));
219              ev->x = dev->mouse.x;
220              ev->y = dev->mouse.y;
221              ev->dev = dev;
222
223              ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE,ev,NULL,NULL);
224              break;
225           }
226      case REL_WHEEL:
227      case REL_HWHEEL:
228           {
229              Ecore_Fb_Event_Mouse_Wheel *ev;
230              ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Wheel));
231
232              ev->x = dev->mouse.x;
233              ev->y = dev->mouse.y;
234              if (iev->code == REL_HWHEEL) ev->direction = 1;
235              ev->wheel = iev->value;
236              ev->dev = dev;
237              ecore_event_add(ECORE_FB_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
238              break;
239           }
240      default:
241         break;
242      }
243 }
244
245 static void
246 _ecore_fb_li_device_event_abs(Ecore_Fb_Input_Device *dev, struct input_event *iev)
247 {
248    static int prev_pressure = 0;
249    int pressure;
250
251    if (!dev->listen) return;
252    switch (iev->code)
253      {
254      case ABS_X:
255         if (dev->mouse.w != 0)
256           {
257              int tmp;
258
259              tmp = (int)((double)(iev->value - dev->mouse.min_w) / dev->mouse.rel_w);
260              if (tmp < 0) dev->mouse.x = 0;
261              else if (tmp > dev->mouse.w) dev->mouse.x = dev->mouse.w;
262              else dev->mouse.x = tmp;
263              dev->mouse.event = ECORE_FB_EVENT_MOUSE_MOVE;
264           }
265         break;
266
267      case ABS_Y:
268         if(dev->mouse.h != 0)
269           {
270              int tmp;
271
272              tmp = (int)((double)(iev->value - dev->mouse.min_h) / dev->mouse.rel_h);
273              if (tmp < 0) dev->mouse.y = 0;
274              else if (tmp > dev->mouse.h) dev->mouse.y = dev->mouse.h;
275              else dev->mouse.y = tmp;
276              dev->mouse.event = ECORE_FB_EVENT_MOUSE_MOVE;
277           }
278         break;
279
280      case ABS_PRESSURE:
281         pressure = iev->value;
282         if ((pressure) && (!prev_pressure))
283           {
284              /* DOWN: mouse is down, but was not now */
285              dev->mouse.event = ECORE_FB_EVENT_MOUSE_BUTTON_DOWN;
286           }
287         else if ((!pressure) && (prev_pressure))
288           {
289              /* UP: mouse was down, but is not now */
290              dev->mouse.event = ECORE_FB_EVENT_MOUSE_BUTTON_UP;
291           }
292         prev_pressure = pressure;
293         break;
294      }
295 }
296
297 static void
298 _ecore_fb_li_device_event_syn(Ecore_Fb_Input_Device *dev, struct input_event *iev __UNUSED__)
299 {
300    if (!dev->listen) return;
301
302    if (dev->mouse.event == ECORE_FB_EVENT_MOUSE_MOVE)
303      {
304         Ecore_Fb_Event_Mouse_Move *ev;
305         ev = calloc(1,sizeof(Ecore_Fb_Event_Mouse_Move));
306         ev->x = dev->mouse.x;
307         ev->y = dev->mouse.y;
308         ev->dev = dev;
309         ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE, ev, NULL, NULL);
310      }
311    else if (dev->mouse.event == ECORE_FB_EVENT_MOUSE_BUTTON_DOWN)
312      {
313         Ecore_Fb_Event_Mouse_Button_Down *ev;
314         ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down));
315         ev->x = dev->mouse.x;
316         ev->y = dev->mouse.y;
317         ev->button = 1;
318         ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
319      }
320    else if (dev->mouse.event == ECORE_FB_EVENT_MOUSE_BUTTON_UP)
321      {
322         Ecore_Fb_Event_Mouse_Button_Up *ev;
323         ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Up));
324         ev->x = dev->mouse.x;
325         ev->y = dev->mouse.y;
326         ev->button = 1;
327         ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
328      }
329 }
330
331 static Eina_Bool
332 _ecore_fb_li_device_fd_callback(void *data, Ecore_Fd_Handler *fdh __UNUSED__)
333 {
334    Ecore_Fb_Input_Device *dev;
335    struct input_event ev[64];
336    int len;
337    int i;
338
339    dev = (Ecore_Fb_Input_Device*)data;
340    /* read up to 64 events at once */
341    len = read(dev->fd, &ev, sizeof(ev));
342    // printf("[ecore_fb_li_device:fd_callback] received %d data\n", len);
343    for(i = 0; i < (int)(len / sizeof(ev[0])); i++)
344      {
345         switch(ev[i].type)
346           {
347           case EV_SYN:
348              _ecore_fb_li_device_event_syn(dev, &ev[i]);
349              break;
350           case EV_ABS:
351              _ecore_fb_li_device_event_abs(dev, &ev[i]);
352              break;
353           case EV_REL:
354              _ecore_fb_li_device_event_rel(dev, &ev[i]);
355              break;
356           case EV_KEY:
357              _ecore_fb_li_device_event_key(dev, &ev[i]);
358              break;
359           default:
360              break;
361           }
362      }
363    return EINA_TRUE;
364 }
365
366 /**
367  * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions.
368  *
369  * @{
370  */
371
372 /**
373  * @brief Set the listen mode for an input device .
374  *
375  * @param dev The device to set the mode of.
376  * @param listen EINA_FALSE to disable listening mode, EINA_TRUE to enable it.
377  *
378  * This function enables or disables listening on the input device @p
379  * dev. If @p listen is #EINA_FALSE, listening mode is disabled, if it
380  * is #EINA_TRUE, it is enabled.
381  */
382 EAPI void
383 ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, Eina_Bool listen)
384 {
385    if (!dev) return;
386    if ((listen && dev->listen) || (!listen && !dev->listen)) return;
387    if (listen)
388      {
389         /* if the device already had a handler */
390         if (!dev->handler)
391            dev->handler = ecore_main_fd_handler_add(dev->fd, ECORE_FD_READ, _ecore_fb_li_device_fd_callback, dev, NULL, NULL);
392
393      }
394    dev->listen = listen;
395 }
396
397 #ifndef EV_CNT
398 # define EV_CNT (EV_MAX+1)
399 #endif
400
401 /**
402  * @brief Open an input device.
403  *
404  * @param dev The device to open.
405  * @return The @ref Ecore_Fb_Input_Device object that has been opened.
406  *
407  * This function opens the input device named @p dev and returns the
408  * object for it, or returns @c NULL on failure. 
409  */
410 EAPI Ecore_Fb_Input_Device *
411 ecore_fb_input_device_open(const char *dev)
412 {
413    Ecore_Fb_Input_Device *device;
414    unsigned long event_type_bitmask[EV_CNT / 32 + 1];
415    int event_type;
416    int fd;
417
418    if (!dev) return NULL;
419    device = calloc(1, sizeof(Ecore_Fb_Input_Device));
420    if (!device) return NULL;
421
422    if ((fd = open(dev, O_RDONLY, O_NONBLOCK)) < 0)
423      {
424         fprintf(stderr, "[ecore_fb_li:device_open] %s %s", dev, strerror(errno));
425         goto error_open;
426      }
427    /* query capabilities */
428    if (ioctl(fd, EVIOCGBIT(0, EV_MAX), event_type_bitmask) < 0)
429      {
430         fprintf(stderr,"[ecore_fb_li:device_open] query capabilities %s %s", dev, strerror(errno));
431         goto error_caps;
432      }
433    /* query name */
434    device->info.name = calloc(256, sizeof(char));
435    if (ioctl(fd, EVIOCGNAME(sizeof(char) * 256), device->info.name) < 0)
436      {
437         fprintf(stderr, "[ecore_fb_li:device_open] get name %s %s", dev, strerror(errno));
438         strcpy(device->info.name, "Unknown");
439      }
440    device->fd = fd;
441    device->info.dev = strdup(dev);
442    /* common */
443    device->mouse.threshold = CLICK_THRESHOLD_DEFAULT;
444
445    /* set info */
446    for (event_type = 0; event_type < EV_MAX; event_type++)
447      {
448         if(!test_bit(event_type, event_type_bitmask))
449            continue;
450         switch (event_type)
451           {
452           case EV_SYN:
453              break;
454           case EV_KEY:
455              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS;
456              break;
457           case EV_REL:
458              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_RELATIVE;
459              break;
460           case EV_ABS:
461              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE;
462              break;
463           case EV_MSC:
464           case EV_LED:
465           case EV_SND:
466           case EV_REP:
467           case EV_FF :
468           case EV_FF_STATUS:
469           case EV_PWR:
470           default:
471                 break;
472           }
473      }
474    _ecore_fb_li_devices = eina_list_append(_ecore_fb_li_devices, device);
475    return device;
476
477 error_caps:
478    close(fd);
479 error_open:
480    free(device);
481    return NULL;
482 }
483
484 /**
485  * @brief Close the given device.
486  *
487  * @param dev The device to close
488  *
489  * This function closes the device @p dev. If @p dev is @c NULL, this
490  * function does nothing.
491  */
492 EAPI void
493 ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev)
494 {
495    if (!dev || dev->fd < 0) return;
496    /* close the fd */
497    close(dev->fd);
498    /* remove the element from the list */
499    _ecore_fb_li_devices = eina_list_remove(_ecore_fb_li_devices, dev);
500    free(dev);
501 }
502
503
504 /**
505  * @brief Set the axis size of the given device.
506  *
507  * @param dev The device to set the axis size to.
508  * @param w The width of the axis.
509  * @param h The height of the axis.
510  *
511  * This function sets set the width @p w and height @p h of the axis
512  * of device @p dev. If @p dev is a relative input device, a width and
513  * height must set for it. If its absolute set the ioctl correctly, if
514  * not, unsupported device.
515  */
516 EAPI void
517 ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h)
518 {
519    if (!dev) return;
520    if ((w < 0) || (h < 0)) return;
521    /* FIXME
522     * this code is for a touchscreen device,
523     * make it configurable (ABSOLUTE | RELATIVE)
524     */
525    if (dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE)
526      {
527         /* FIXME looks like some kernels dont include this struct */
528         struct input_absinfo abs_features;
529
530         ioctl(dev->fd, EVIOCGABS(ABS_X), &abs_features);
531         dev->mouse.min_w = abs_features.minimum;
532         dev->mouse.rel_w = (double)(abs_features.maximum - abs_features.minimum)/(double)(w);
533
534         ioctl(dev->fd, EVIOCGABS(ABS_Y), &abs_features);
535         dev->mouse.min_h = abs_features.minimum;
536         dev->mouse.rel_h = (double)(abs_features.maximum - abs_features.minimum)/(double)(h);
537      }
538    else if (!(dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE))
539       return;
540
541    /* update the local values */
542    if (dev->mouse.x > w - 1) dev->mouse.x = w -1;
543    if (dev->mouse.y > h - 1) dev->mouse.y = h -1;
544    dev->mouse.w = w;
545    dev->mouse.h = h;
546 }
547
548 /**
549  * @brief Retrieve the name of the given device.
550  *
551  * @param dev The device to get the name from.
552  * @return The name of the device.
553  *
554  * This function returns the name of the device @p dev. If @p dev is
555  * @c NULL, this function returns @c NULL.
556  */
557 EAPI const char *
558 ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev)
559 {
560    if (!dev) return NULL;
561    return dev->info.name;
562 }
563
564 /**
565  * @brief Retrieve the capability of the given device.
566  *
567  * @param dev The device to get the name from.
568  * @return The capability of the device.
569  *
570  * This function returns the capability of the device @p dev. If @p dev is
571  * @c NULL, this function returns #ECORE_FB_INPUT_DEVICE_CAP_NONE.
572  */
573 EAPI Ecore_Fb_Input_Device_Cap
574 ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev)
575 {
576    if (!dev) return ECORE_FB_INPUT_DEVICE_CAP_NONE;
577    return dev->info.cap;
578 }
579
580 /**
581  * @brief Set the threshold of mouse clicks of the given device.
582  *
583  * @param dev The device to set the threshodl mouse click to.
584  * @param threshold The threshold value.
585  *
586  * This function sets the threshold of mouse clicks of the device
587  * @p dev to @p threshold. If @p dev is @c NULL, this function does
588  * nothing.
589  */
590 EAPI void
591 ecore_fb_input_device_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold)
592 {
593    if (!dev) return;
594    if ((threshold == dev->mouse.threshold) || (threshold == 0)) return;
595    dev->mouse.threshold = threshold;
596 }
597
598 /**
599  * @brief Get the threshold of mouse clicks of the given device.
600  *
601  * @param dev The device to set the threshodl mouse click from.
602  * @return The threshold value.
603  *
604  * This function returns the threshold of mouse clicks of the device
605  * @p dev. If @p dev is @c NULL, this function returns 0.0.
606  */
607 EAPI double
608 ecore_fb_input_device_threshold_click_get(Ecore_Fb_Input_Device *dev)
609 {
610    if (!dev) return 0;
611    return dev->mouse.threshold;
612 }
613
614 /**
615  * @}
616  */