Tizen 2.1 base
[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         ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
373      }
374    else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_DOWN)
375      {
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;
380         ev->root.x = ev->x;
381         ev->root.y = ev->y;
382         ev->buttons = 1;
383         ev->timestamp = ecore_loop_time_get() * 1000.0;
384         ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
385      }
386    else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_UP)
387      {
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;
392         ev->root.x = ev->x;
393         ev->root.y = ev->y;
394         ev->buttons = 1;
395         ev->timestamp = ecore_loop_time_get() * 1000.0;
396         ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
397      }
398 }
399
400 static Eina_Bool
401 _ecore_fb_li_device_fd_callback(void *data, Ecore_Fd_Handler *fdh __UNUSED__)
402 {
403    Ecore_Fb_Input_Device *dev;
404    struct input_event ev[64];
405    int len;
406    int i;
407
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++)
412      {
413         switch(ev[i].type)
414           {
415           case EV_SYN:
416              _ecore_fb_li_device_event_syn(dev, &ev[i]);
417              break;
418           case EV_ABS:
419              _ecore_fb_li_device_event_abs(dev, &ev[i]);
420              break;
421           case EV_REL:
422              _ecore_fb_li_device_event_rel(dev, &ev[i]);
423              break;
424           case EV_KEY:
425              _ecore_fb_li_device_event_key(dev, &ev[i]);
426              break;
427           default:
428              break;
429           }
430      }
431    return EINA_TRUE;
432 }
433
434 /**
435  * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions.
436  *
437  * @{
438  */
439
440 /**
441  * @brief Set the listen mode for an input device .
442  *
443  * @param dev The device to set the mode of.
444  * @param listen @c EINA_FALSE to disable listening mode, @c EINA_TRUE to
445  * enable it.
446  *
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.
450  */
451 EAPI void
452 ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, Eina_Bool listen)
453 {
454    if (!dev) return;
455    if ((listen && dev->listen) || (!listen && !dev->listen)) return;
456    if (listen)
457      {
458         /* if the device already had a handler */
459         if (!dev->handler)
460            dev->handler = ecore_main_fd_handler_add(dev->fd, ECORE_FD_READ, _ecore_fb_li_device_fd_callback, dev, NULL, NULL);
461
462      }
463    dev->listen = listen;
464 }
465
466 #ifndef EV_CNT
467 # define EV_CNT (EV_MAX+1)
468 #endif
469
470 /**
471  * @brief Associates an input device with the given @ref Ecore_Evas_Group.
472  *
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.
476  *
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:
481  *
482  * @code
483  * Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 800, 600, NULL);
484  *
485  * ecore_evas_input_event_register(ee);
486  *
487  * device = ecore_fb_input_device_open(device_path);
488  * if (device)
489  *   ecore_fb_input_device_window_set(device, ee);
490  *
491  * @endcode
492  *
493  * On the previous code, all input captured on the mentioned device will be
494  * delivered to the @c Ecore_Evas @c ee.
495  *
496  * @since 1.1
497  */
498 EAPI void
499 ecore_fb_input_device_window_set(Ecore_Fb_Input_Device *dev, void *window)
500 {
501    if (!dev) return;
502
503    dev->window = window;
504 }
505
506 /**
507  * @brief Open an input device.
508  *
509  * @param dev The device to open.
510  * @return The @ref Ecore_Fb_Input_Device object that has been opened.
511  *
512  * This function opens the input device named @p dev and returns the
513  * object for it, or returns @c NULL on failure.
514  */
515 EAPI Ecore_Fb_Input_Device *
516 ecore_fb_input_device_open(const char *dev)
517 {
518    Ecore_Fb_Input_Device *device;
519    unsigned long event_type_bitmask[EV_CNT / 32 + 1];
520    int event_type;
521    int fd;
522
523    if (!dev) return NULL;
524    device = calloc(1, sizeof(Ecore_Fb_Input_Device));
525    if (!device) return NULL;
526
527    if ((fd = open(dev, O_RDONLY, O_NONBLOCK)) < 0)
528      {
529         fprintf(stderr, "[ecore_fb_li:device_open] %s %s", dev, strerror(errno));
530         goto error_open;
531      }
532    /* query capabilities */
533    if (ioctl(fd, EVIOCGBIT(0, EV_MAX), event_type_bitmask) < 0)
534      {
535         fprintf(stderr,"[ecore_fb_li:device_open] query capabilities %s %s", dev, strerror(errno));
536         goto error_caps;
537      }
538    /* query name */
539    device->info.name = calloc(256, sizeof(char));
540    if (ioctl(fd, EVIOCGNAME(sizeof(char) * 256), device->info.name) < 0)
541      {
542         fprintf(stderr, "[ecore_fb_li:device_open] get name %s %s", dev, strerror(errno));
543         strcpy(device->info.name, "Unknown");
544      }
545    device->fd = fd;
546    device->info.dev = strdup(dev);
547    /* common */
548    device->mouse.threshold = CLICK_THRESHOLD_DEFAULT;
549
550    /* set info */
551    for (event_type = 0; event_type < EV_MAX; event_type++)
552      {
553         if (!test_bit(event_type, event_type_bitmask))
554           continue;
555         switch (event_type)
556           {
557           case EV_SYN:
558              break;
559           case EV_KEY:
560              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS;
561              break;
562           case EV_REL:
563              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_RELATIVE;
564              break;
565           case EV_ABS:
566              device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE;
567              break;
568           case EV_MSC:
569           case EV_LED:
570           case EV_SND:
571           case EV_REP:
572           case EV_FF :
573           case EV_FF_STATUS:
574           case EV_PWR:
575           default:
576                 break;
577           }
578      }
579
580    _ecore_fb_li_devices = eina_list_append(_ecore_fb_li_devices, device);
581    return device;
582
583 error_caps:
584    close(fd);
585 error_open:
586    free(device);
587    return NULL;
588 }
589
590 /**
591  * @brief Close the given device.
592  *
593  * @param dev The device to close
594  *
595  * This function closes the device @p dev. If @p dev is @c NULL, this
596  * function does nothing.
597  */
598 EAPI void
599 ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev)
600 {
601    if (!dev || dev->fd < 0) return;
602    /* close the fd */
603    close(dev->fd);
604    /* remove the element from the list */
605    _ecore_fb_li_devices = eina_list_remove(_ecore_fb_li_devices, dev);
606    free(dev);
607 }
608
609
610 /**
611  * @brief Set the axis size of the given device.
612  *
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.
616  *
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.
621  */
622 EAPI void
623 ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h)
624 {
625    if (!dev) return;
626    if ((w < 0) || (h < 0)) return;
627    /* FIXME
628     * this code is for a touchscreen device,
629     * make it configurable (ABSOLUTE | RELATIVE)
630     */
631    if (dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE)
632      {
633         /* FIXME looks like some kernels dont include this struct */
634         struct input_absinfo abs_features;
635
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);
639
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);
643      }
644    else if (!(dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE))
645       return;
646
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;
650    dev->mouse.w = w;
651    dev->mouse.h = h;
652 }
653
654 /**
655  * @brief Retrieve the name of the given device.
656  *
657  * @param dev The device to get the name from.
658  * @return The name of the device.
659  *
660  * This function returns the name of the device @p dev. If @p dev is
661  * @c NULL, this function returns @c NULL.
662  */
663 EAPI const char *
664 ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev)
665 {
666    if (!dev) return NULL;
667    return dev->info.name;
668 }
669
670 /**
671  * @brief Retrieve the capability of the given device.
672  *
673  * @param dev The device to get the name from.
674  * @return The capability of the device.
675  *
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.
678  */
679 EAPI Ecore_Fb_Input_Device_Cap
680 ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev)
681 {
682    if (!dev) return ECORE_FB_INPUT_DEVICE_CAP_NONE;
683    return dev->info.cap;
684 }
685
686 /**
687  * @brief Set the threshold of mouse clicks of the given device.
688  *
689  * @param dev The device to set the threshodl mouse click to.
690  * @param threshold The threshold value.
691  *
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
694  * nothing.
695  */
696 EAPI void
697 ecore_fb_input_device_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold)
698 {
699    if (!dev) return;
700    if ((threshold == dev->mouse.threshold) || (threshold == 0)) return;
701    dev->mouse.threshold = threshold;
702 }
703
704 /**
705  * @brief Get the threshold of mouse clicks of the given device.
706  *
707  * @param dev The device to set the threshodl mouse click from.
708  * @return The threshold value.
709  *
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.
712  */
713 EAPI double
714 ecore_fb_input_device_threshold_click_get(Ecore_Fb_Input_Device *dev)
715 {
716    if (!dev) return 0;
717    return dev->mouse.threshold;
718 }
719
720 /**
721  * @}
722  */