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