23599c9edebef3e798b32ebe58258161b635dfa8
[framework/uifw/ecore.git] / src / lib / ecore_fb / ecore_fb_li.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6
7 #include "Ecore_Fb.h"
8 #include "ecore_fb_private.h"
9
10 #define CLICK_THRESHOLD_DEFAULT 0.25
11
12 static Eina_List *_ecore_fb_li_devices = NULL;
13
14 static const char *_ecore_fb_li_kbd_syms[128 * 7] =
15 {
16 #include "ecore_fb_keytable.h"
17 };
18
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
26  * size.
27  *                                                - bigeasy
28  */
29 extern int long_has_neither_32_nor_64_bits(void);
30 static inline int
31 test_bit(int bit, unsigned long *array)
32 {
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();
38 }
39
40 static void
41 _ecore_fb_li_device_event_key(Ecore_Fb_Input_Device *dev, struct input_event *iev)
42 {
43    if (!dev->listen) return;
44
45    /* check for basic keyboard keys */
46    if ((iev->code >= KEY_ESC) && (iev->code <= KEY_COMPOSE))
47      {
48         int offset = 0;
49         const char *keyname = _ecore_fb_li_kbd_syms[iev->code * 7];
50         
51         /* check the key table */
52         if (iev->value)
53           {
54              /* its a repeated key, dont increment */
55              if (iev->value != 2)
56                {
57                   if (!strcmp(keyname, "Control_L"))
58                     dev->keyboard.ctrl++;
59                   else if (!strcmp(keyname, "Control_R"))
60                     dev->keyboard.ctrl++;
61                   else if (!strcmp(keyname, "Alt_L"))
62                     dev->keyboard.alt++;
63                   else if (!strcmp(keyname, "Alt_R"))
64                     dev->keyboard.alt++;
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;
75                }
76           }
77         else
78           {
79              if (!strcmp(keyname, "Control_L"))
80                 dev->keyboard.ctrl--;
81              else if (!strcmp(keyname, "Control_R"))
82                 dev->keyboard.ctrl--;
83              else if (!strcmp(keyname, "Alt_L"))
84                 dev->keyboard.alt--;
85              else if (!strcmp(keyname, "Alt_R"))
86                 dev->keyboard.alt--;
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;
95           }
96
97         /* sending ecore_input_evas events */
98         Ecore_Event_Key *e;
99
100         if (dev->keyboard.shift) offset = 1;
101         else if (dev->keyboard.lock) offset = 2;
102
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];
105         
106         if (dev->keyboard.ctrl)
107           {
108              const char *ts = _ecore_fb_li_kbd_syms[(iev->code * 7) + 3 + 3];
109              
110              if (ts) compose = ts;
111           }
112
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;
119
120         strcpy((char *)e->keyname, keyname);
121         strcpy((char *)e->key, key);
122         if (compose)
123           strcpy((char *)e->compose, compose);
124
125         e->modifiers = 0;
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;
131
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;
136         e->same_screen = 1;
137
138         if (iev->value)
139           ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
140         else
141           ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
142      }
143    /* check for mouse button events */
144    else if ((iev->code >= BTN_MOUSE) && (iev->code < BTN_JOYSTICK))
145      {
146         int button;
147         Ecore_Event_Mouse_Button *e;
148         double current = ecore_loop_time_get();
149
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;
154         if (iev->value)
155           {
156              dev->mouse.did_double = EINA_FALSE;
157              dev->mouse.did_triple = EINA_FALSE;
158
159              if (((current - dev->mouse.prev) <= dev->mouse.threshold) &&
160                  (button == dev->mouse.prev_button))
161                {
162                   dev->mouse.did_double = EINA_TRUE;
163                   if (((current - dev->mouse.last) <= (2 * dev->mouse.threshold)) &&
164                       (button == dev->mouse.last_button))
165                     {
166                        dev->mouse.did_triple = EINA_TRUE;
167                        /* reset */
168                        dev->mouse.prev = 0;
169                        dev->mouse.last = 0;
170                        current = 0;
171                     }
172                }
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;
177           }
178
179         e = calloc(1, sizeof(Ecore_Event_Mouse_Button));
180         if (!e)
181           return;
182
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;
187         e->same_screen = 1;
188
189         e->modifiers = 0;
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;
195
196         e->x = dev->mouse.x;
197         e->y = dev->mouse.y;
198         e->root.x = e->x;
199         e->root.y = e->y;
200         e->buttons = button;
201
202         if (dev->mouse.did_double)
203           e->double_click = 1;
204         if (dev->mouse.did_triple)
205           e->triple_click = 1;
206
207         if (iev->value)
208           ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL);
209         else
210           ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL);
211      }
212 }
213
214 static void
215 _ecore_fb_li_device_event_rel(Ecore_Fb_Input_Device *dev, struct input_event *iev)
216 {
217    if (!dev->listen) return;
218    /* dispatch the button events if they are queued */
219    switch (iev->code)
220      {
221      case REL_X:
222      case REL_Y:
223           {
224              Ecore_Event_Mouse_Move *e;
225              if (iev->code == REL_X)
226                {
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)
231                     dev->mouse.x = 0;
232                }
233              else
234                {
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)
239                     dev->mouse.y = 0;
240                }
241
242              e = calloc(1, sizeof(Ecore_Event_Mouse_Move));
243              if (!e)
244                return;
245
246              e->window = (Ecore_Window)dev->window;
247              e->event_window = (Ecore_Window)dev->window;
248              e->root_window = (Ecore_Window)dev->window;
249              e->same_screen = 1;
250
251              e->modifiers = 0;
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;
256
257              e->x = dev->mouse.x;
258              e->y = dev->mouse.y;
259              e->root.x = e->x;
260              e->root.y = e->y;
261
262              e->timestamp = ecore_loop_time_get() * 1000.0;
263
264              ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
265
266              break;
267           }
268      case REL_WHEEL:
269      case REL_HWHEEL:
270           {
271              Ecore_Event_Mouse_Wheel *e;
272
273              e = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
274              if (!e)
275                return;
276
277              e->x = dev->mouse.x;
278              e->y = dev->mouse.y;
279              if (iev->code == REL_HWHEEL) e->direction = 1;
280              e->z = iev->value;
281              e->root.x = dev->mouse.x;
282              e->root.y = dev->mouse.y;
283
284              e->window = (Ecore_Window)dev->window;
285              e->event_window = (Ecore_Window)dev->window;
286              e->root_window = (Ecore_Window)dev->window;
287              e->same_screen = 1;
288
289              e->modifiers = 0;
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;
294
295              e->timestamp = ecore_loop_time_get() * 1000.0;
296
297              ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL);
298
299              break;
300           }
301      default:
302         break;
303      }
304 }
305
306 static void
307 _ecore_fb_li_device_event_abs(Ecore_Fb_Input_Device *dev, struct input_event *iev)
308 {
309    static int prev_pressure = 0;
310    int pressure;
311
312    if (!dev->listen) return;
313    switch (iev->code)
314      {
315      case ABS_X:
316         if (dev->mouse.w != 0)
317           {
318              int tmp;
319
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;
325           }
326         break;
327
328      case ABS_Y:
329         if (dev->mouse.h != 0)
330           {
331              int tmp;
332
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;
338           }
339         break;
340
341      case ABS_PRESSURE:
342         pressure = iev->value;
343         if ((pressure) && (!prev_pressure))
344           {
345              /* DOWN: mouse is down, but was not before */
346              dev->mouse.event = ECORE_EVENT_MOUSE_BUTTON_DOWN;
347           }
348         else if ((!pressure) && (prev_pressure))
349           {
350              /* UP: mouse was down, but is not now */
351              dev->mouse.event = ECORE_EVENT_MOUSE_BUTTON_UP;
352           }
353         prev_pressure = pressure;
354         break;
355      }
356 }
357
358 static void
359 _ecore_fb_li_device_event_syn(Ecore_Fb_Input_Device *dev, struct input_event *iev __UNUSED__)
360 {
361    if (!dev->listen) return;
362
363    if (dev->mouse.event == ECORE_EVENT_MOUSE_MOVE)
364      {
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;
369         ev->root.x = ev->x;
370         ev->root.y = ev->y;
371         ev->timestamp = ecore_loop_time_get() * 1000.0;
372      }
373    else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_DOWN)
374      {
375         Ecore_Event_Mouse_Button *ev;
376         ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
377         ev->x = dev->mouse.x;
378         ev->y = dev->mouse.y;
379         ev->root.x = ev->x;
380         ev->root.y = ev->y;
381         ev->buttons = 1;
382         ev->timestamp = ecore_loop_time_get() * 1000.0;
383         ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
384      }
385    else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_UP)
386      {
387         Ecore_Event_Mouse_Button *ev;
388         ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
389         ev->x = dev->mouse.x;
390         ev->y = dev->mouse.y;
391         ev->root.x = ev->x;
392         ev->root.y = ev->y;
393         ev->buttons = 1;
394         ev->timestamp = ecore_loop_time_get() * 1000.0;
395         ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
396      }
397 }
398
399 static Eina_Bool
400 _ecore_fb_li_device_fd_callback(void *data, Ecore_Fd_Handler *fdh __UNUSED__)
401 {
402    Ecore_Fb_Input_Device *dev;
403    struct input_event ev[64];
404    int len;
405    int i;
406
407    dev = (Ecore_Fb_Input_Device*)data;
408    /* read up to 64 events at once */
409    len = read(dev->fd, &ev, sizeof(ev));
410    for(i = 0; i < (int)(len / sizeof(ev[0])); i++)
411      {
412         switch(ev[i].type)
413           {
414           case EV_SYN:
415              _ecore_fb_li_device_event_syn(dev, &ev[i]);
416              break;
417           case EV_ABS:
418              _ecore_fb_li_device_event_abs(dev, &ev[i]);
419              break;
420           case EV_REL:
421              _ecore_fb_li_device_event_rel(dev, &ev[i]);
422              break;
423           case EV_KEY:
424              _ecore_fb_li_device_event_key(dev, &ev[i]);
425              break;
426           default:
427              break;
428           }
429      }
430    return EINA_TRUE;
431 }
432
433 /**
434  * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions.
435  *
436  * @{
437  */
438
439 /**
440  * @brief Set the listen mode for an input device .
441  *
442  * @param dev The device to set the mode of.
443  * @param listen @c EINA_FALSE to disable listening mode, @c EINA_TRUE to
444  * enable it.
445  *
446  * This function enables or disables listening on the input device @p dev.
447  * If @p listen is @c EINA_FALSE, listening mode is disabled, if it is
448  * @c EINA_TRUE, it is enabled.
449  */
450 EAPI void
451 ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, Eina_Bool listen)
452 {
453    if (!dev) return;
454    if ((listen && dev->listen) || (!listen && !dev->listen)) return;
455    if (listen)
456      {
457         /* if the device already had a handler */
458         if (!dev->handler)
459            dev->handler = ecore_main_fd_handler_add(dev->fd, ECORE_FD_READ, _ecore_fb_li_device_fd_callback, dev, NULL, NULL);
460
461      }
462    dev->listen = listen;
463 }
464
465 #ifndef EV_CNT
466 # define EV_CNT (EV_MAX+1)
467 #endif
468
469 /**
470  * @brief Associates an input device with the given @ref Ecore_Evas_Group.
471  *
472  * @param dev The input being associated with an @ref Ecore_Evas_Group (not @c NULL).
473  * @param window The window which this input is being associated to.
474  * @c NULL will remove any previous association.
475  *
476  * Events generated by this device will have a pointer to @p window. If this @p
477  * window is registered with ecore_event_window_register() or
478  * ecore_evas_input_event_register(), respective evas events will be delivered
479  * by the ecore_input_evas system. An example can be seen in the following code:
480  *
481  * @code
482  * Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 800, 600, NULL);
483  *
484  * ecore_evas_input_event_register(ee);
485  *
486  * device = ecore_fb_input_device_open(device_path);
487  * if (device)
488  *   ecore_fb_input_device_window_set(device, ee);
489  *
490  * @endcode
491  *
492  * On the previous code, all input captured on the mentioned device will be
493  * delivered to the @c Ecore_Evas @c ee.
494  *
495  * @since 1.1
496  */
497 EAPI void
498 ecore_fb_input_device_window_set(Ecore_Fb_Input_Device *dev, void *window)
499 {
500    if (!dev) return;
501
502    dev->window = window;
503 }
504
505 /**
506  * @brief Open an input device.
507  *
508  * @param dev The device to open.
509  * @return The @ref Ecore_Fb_Input_Device object that has been opened.
510  *
511  * This function opens the input device named @p dev and returns the
512  * object for it, or returns @c NULL on failure.
513  */
514 EAPI Ecore_Fb_Input_Device *
515 ecore_fb_input_device_open(const char *dev)
516 {
517    Ecore_Fb_Input_Device *device;
518    unsigned long event_type_bitmask[EV_CNT / 32 + 1];
519    int event_type;
520    int fd;
521
522    if (!dev) return NULL;
523    device = calloc(1, sizeof(Ecore_Fb_Input_Device));
524    if (!device) return NULL;
525
526    if ((fd = open(dev, O_RDONLY, O_NONBLOCK)) < 0)
527      {
528         fprintf(stderr, "[ecore_fb_li:device_open] %s %s", dev, strerror(errno));
529         goto error_open;
530      }
531    /* query capabilities */
532    if (ioctl(fd, EVIOCGBIT(0, EV_MAX), event_type_bitmask) < 0)
533      {
534         fprintf(stderr,"[ecore_fb_li:device_open] query capabilities %s %s", dev, strerror(errno));
535         goto error_caps;
536      }
537    /* query name */
538    device->info.name = calloc(256, sizeof(char));
539    if (ioctl(fd, EVIOCGNAME(sizeof(char) * 256), device->info.name) < 0)
540      {
541         fprintf(stderr, "[ecore_fb_li:device_open] get name %s %s", dev, strerror(errno));
542         strcpy(device->info.name, "Unknown");
543      }
544    device->fd = fd;
545    device->info.dev = strdup(dev);
546    /* common */
547    device->mouse.threshold = CLICK_THRESHOLD_DEFAULT;
548
549    /* set info */
550    for (event_type = 0; event_type < EV_MAX; event_type++)
551      {
552         if (!test_bit(event_type, event_type_bitmask))
553           continue;
554         switch (event_type)
555           {
556           case EV_SYN:
557              break;
558           case EV_KEY:
559              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS;
560              break;
561           case EV_REL:
562              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_RELATIVE;
563              break;
564           case EV_ABS:
565              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE;
566              break;
567           case EV_MSC:
568           case EV_LED:
569           case EV_SND:
570           case EV_REP:
571           case EV_FF :
572           case EV_FF_STATUS:
573           case EV_PWR:
574           default:
575                 break;
576           }
577      }
578
579    _ecore_fb_li_devices = eina_list_append(_ecore_fb_li_devices, device);
580    return device;
581
582 error_caps:
583    close(fd);
584 error_open:
585    free(device);
586    return NULL;
587 }
588
589 /**
590  * @brief Close the given device.
591  *
592  * @param dev The device to close
593  *
594  * This function closes the device @p dev. If @p dev is @c NULL, this
595  * function does nothing.
596  */
597 EAPI void
598 ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev)
599 {
600    if (!dev || dev->fd < 0) return;
601    /* close the fd */
602    close(dev->fd);
603    /* remove the element from the list */
604    _ecore_fb_li_devices = eina_list_remove(_ecore_fb_li_devices, dev);
605    free(dev);
606 }
607
608
609 /**
610  * @brief Set the axis size of the given device.
611  *
612  * @param dev The device to set the axis size to.
613  * @param w The width of the axis.
614  * @param h The height of the axis.
615  *
616  * This function sets set the width @p w and height @p h of the axis
617  * of device @p dev. If @p dev is a relative input device, a width and
618  * height must set for it. If its absolute set the ioctl correctly, if
619  * not, unsupported device.
620  */
621 EAPI void
622 ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h)
623 {
624    if (!dev) return;
625    if ((w < 0) || (h < 0)) return;
626    /* FIXME
627     * this code is for a touchscreen device,
628     * make it configurable (ABSOLUTE | RELATIVE)
629     */
630    if (dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE)
631      {
632         /* FIXME looks like some kernels dont include this struct */
633         struct input_absinfo abs_features;
634
635         ioctl(dev->fd, EVIOCGABS(ABS_X), &abs_features);
636         dev->mouse.min_w = abs_features.minimum;
637         dev->mouse.rel_w = (double)(abs_features.maximum - abs_features.minimum)/(double)(w);
638
639         ioctl(dev->fd, EVIOCGABS(ABS_Y), &abs_features);
640         dev->mouse.min_h = abs_features.minimum;
641         dev->mouse.rel_h = (double)(abs_features.maximum - abs_features.minimum)/(double)(h);
642      }
643    else if (!(dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE))
644       return;
645
646    /* update the local values */
647    if (dev->mouse.x > w - 1) dev->mouse.x = w -1;
648    if (dev->mouse.y > h - 1) dev->mouse.y = h -1;
649    dev->mouse.w = w;
650    dev->mouse.h = h;
651 }
652
653 /**
654  * @brief Retrieve the name of the given device.
655  *
656  * @param dev The device to get the name from.
657  * @return The name of the device.
658  *
659  * This function returns the name of the device @p dev. If @p dev is
660  * @c NULL, this function returns @c NULL.
661  */
662 EAPI const char *
663 ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev)
664 {
665    if (!dev) return NULL;
666    return dev->info.name;
667 }
668
669 /**
670  * @brief Retrieve the capability of the given device.
671  *
672  * @param dev The device to get the name from.
673  * @return The capability of the device.
674  *
675  * This function returns the capability of the device @p dev. If @p dev is
676  * @c NULL, this function returns ECORE_FB_INPUT_DEVICE_CAP_NONE.
677  */
678 EAPI Ecore_Fb_Input_Device_Cap
679 ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev)
680 {
681    if (!dev) return ECORE_FB_INPUT_DEVICE_CAP_NONE;
682    return dev->info.cap;
683 }
684
685 /**
686  * @brief Set the threshold of mouse clicks of the given device.
687  *
688  * @param dev The device to set the threshodl mouse click to.
689  * @param threshold The threshold value.
690  *
691  * This function sets the threshold of mouse clicks of the device
692  * @p dev to @p threshold. If @p dev is @c NULL, this function does
693  * nothing.
694  */
695 EAPI void
696 ecore_fb_input_device_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold)
697 {
698    if (!dev) return;
699    if ((threshold == dev->mouse.threshold) || (threshold == 0)) return;
700    dev->mouse.threshold = threshold;
701 }
702
703 /**
704  * @brief Get the threshold of mouse clicks of the given device.
705  *
706  * @param dev The device to set the threshodl mouse click from.
707  * @return The threshold value.
708  *
709  * This function returns the threshold of mouse clicks of the device
710  * @p dev. If @p dev is @c NULL, this function returns 0.0.
711  */
712 EAPI double
713 ecore_fb_input_device_threshold_click_get(Ecore_Fb_Input_Device *dev)
714 {
715    if (!dev) return 0;
716    return dev->mouse.threshold;
717 }
718
719 /**
720  * @}
721  */