]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/server/src/mag.lua
fbd87e8ed79cbb583b44be2b8c766553a011a566
[l4.git] / l4 / pkg / mag / server / src / mag.lua
1 function handle_event(ev)
2   local device = ev[6];
3   local stream = ev[5];
4   local ddh = Mag.devices[device];
5   if not ddh then
6     Mag.devices[device] = {};
7     ddh =  Mag.devices[device];
8   end
9
10   local dh = ddh[stream];
11   if not dh then
12     dh = Mag.create_input_device(device, stream);
13   end
14
15   -- print ("EV: ", ev[1], ev[2], ev[3], ev[4], ev[5], ev[6]);
16   return dh:process(ev);
17 end
18
19
20 module("Mag", package.seeall);
21
22 Event = {
23   Type   = 1,
24   Code   = 2,
25   Value  = 3,
26   Time   = 4,
27   Device = 5,
28   Stream = 6,
29
30   SYN = 0;
31   KEY = 1;
32   REL = 2;
33   ABS = 3;
34   MSC = 4;
35   SW  = 5;
36
37   Syn = {
38     REPORT    = 0,
39     CONFIG    = 1,
40     MT_REPORT = 2,
41   };
42
43   Key = {
44     RESERVED         = 0,
45     ESC              = 1,
46     KEY_1            = 2,
47     KEY_2            = 3,
48     KEY_3            = 4,
49     KEY_4            = 5,
50     KEY_5            = 6,
51     KEY_6            = 7,
52     KEY_7            = 8,
53     KEY_8            = 9,
54     KEY_9            = 10,
55     KEY_0            = 11,
56     MINUS            = 12,
57     EQUAL            = 13,
58     BACKSPACE        = 14,
59     TAB              = 15,
60     Q                = 16,
61     W                = 17,
62     E                = 18,
63     R                = 19,
64     T                = 20,
65     Y                = 21,
66     U                = 22,
67     I                = 23,
68     O                = 24,
69     P                = 25,
70     LEFTBRACE        = 26,
71     RIGHTBRACE       = 27,
72     ENTER            = 28,
73     LEFTCTRL         = 29,
74     A                = 30,
75     S                = 31,
76     D                = 32,
77     F                = 33,
78     G                = 34,
79     H                = 35,
80     J                = 36,
81     K                = 37,
82     L                = 38,
83     SEMICOLON        = 39,
84     APOSTROPHE       = 40,
85     GRAVE            = 41,
86     LEFTSHIFT        = 42,
87     BACKSLASH        = 43,
88     Z                = 44,
89     X                = 45,
90     C                = 46,
91     V                = 47,
92     B                = 48,
93     N                = 49,
94     M                = 50,
95     COMMA            = 51,
96     DOT              = 52,
97     SLASH            = 53,
98     RIGHTSHIFT       = 54,
99     KPASTERISK       = 55,
100     LEFTALT          = 56,
101     SPACE            = 57,
102     CAPSLOCK         = 58,
103     F1               = 59,
104     F2               = 60,
105     F3               = 61,
106     F4               = 62,
107     F5               = 63,
108     F6               = 64,
109     F7               = 65,
110     F8               = 66,
111     F9               = 67,
112     F10              = 68,
113     NUMLOCK          = 69,
114     SCROLLLOCK       = 70,
115     KP7              = 71,
116     KP8              = 72,
117     KP9              = 73,
118     KPMINUS          = 74,
119     KP4              = 75,
120     KP5              = 76,
121     KP6              = 77,
122     KPPLUS           = 78,
123     KP1              = 79,
124     KP2              = 80,
125     KP3              = 81,
126     KP0              = 82,
127     KPDOT            = 83,
128     ZENKAKUHANKAKU   = 85,
129     KEY_102ND        = 86,
130     F11              = 87,
131     F12              = 88,
132     RO               = 89,
133     KATAKANA         = 90,
134     HIRAGANA         = 91,
135     HENKAN           = 92,
136     KATAKANAHIRAGANA = 93,
137     MUHENKAN         = 94,
138     KPJPCOMMA        = 95,
139     KPENTER          = 96,
140     RIGHTCTRL        = 97,
141     KPSLASH          = 98,
142     SYSRQ            = 99,
143     RIGHTALT         = 100,
144     LINEFEED         = 101,
145     HOME             = 102,
146     UP               = 103,
147     PAGEUP           = 104,
148     LEFT             = 105,
149     RIGHT            = 106,
150     END              = 107,
151     DOWN             = 108,
152     PAGEDOWN         = 109,
153     INSERT           = 110,
154     DELETE           = 111,
155     MACRO            = 112,
156     MUTE             = 113,
157     VOLUMEDOWN       = 114,
158     VOLUMEUP         = 115,
159     POWER            = 116,
160     KPEQUAL          = 117,
161     KPPLUSMINUS      = 118,
162     PAUSE            = 119,
163     KPCOMMA          = 121,
164     HANGEUL          = 122,
165     HANGUEL          = 122,
166     HANJA            = 123,
167     YEN              = 124,
168     LEFTMETA         = 125,
169     RIGHTMETA        = 126,
170     COMPOSE          = 127,
171     STOP             = 128,
172     AGAIN            = 129,
173     PROPS            = 130,
174     UNDO             = 131,
175     FRONT            = 132,
176     COPY             = 133,
177     OPEN             = 134,
178     PASTE            = 135,
179     FIND             = 136,
180     CUT              = 137,
181     HELP             = 138,
182     MENU             = 139,
183     CALC             = 140,
184     SETUP            = 141,
185     SLEEP            = 142,
186     WAKEUP           = 143,
187     FILE             = 144,
188     SENDFILE         = 145,
189     DELETEFILE       = 146,
190     XFER             = 147,
191     PROG1            = 148,
192     PROG2            = 149,
193     WWW              = 150,
194     MSDOS            = 151,
195     COFFEE           = 152,
196     DIRECTION        = 153,
197     CYCLEWINDOWS     = 154,
198     MAIL             = 155,
199     BOOKMARKS        = 156,
200     COMPUTER         = 157,
201     BACK             = 158,
202     FORWARD          = 159,
203     CLOSECD          = 160,
204     EJECTCD          = 161,
205     EJECTCLOSECD     = 162,
206     NEXTSONG         = 163,
207     PLAYPAUSE        = 164,
208     PREVIOUSSONG     = 165,
209     STOPCD           = 166,
210     RECORD           = 167,
211     REWIND           = 168,
212     PHONE            = 169,
213     ISO              = 170,
214     CONFIG           = 171,
215     HOMEPAGE         = 172,
216     REFRESH          = 173,
217     EXIT             = 174,
218     MOVE             = 175,
219     EDIT             = 176,
220     SCROLLUP         = 177,
221     SCROLLDOWN       = 178,
222     KPLEFTPAREN      = 179,
223     KPRIGHTPAREN     = 180,
224     NEW              = 181,
225     REDO             = 182,
226     F13              = 183,
227     F14              = 184,
228     F15              = 185,
229     F16              = 186,
230     F17              = 187,
231     F18              = 188,
232     F19              = 189,
233     F20              = 190,
234     F21              = 191,
235     F22              = 192,
236     F23              = 193,
237     F24              = 194,
238     PLAYCD           = 200,
239     PAUSECD          = 201,
240     PROG3            = 202,
241     PROG4            = 203,
242     SUSPEND          = 205,
243     CLOSE            = 206,
244     PLAY             = 207,
245     FASTFORWARD      = 208,
246     BASSBOOST        = 209,
247     PRINT            = 210,
248     HP               = 211,
249     CAMERA           = 212,
250     SOUND            = 213,
251     QUESTION         = 214,
252     EMAIL            = 215,
253     CHAT             = 216,
254     SEARCH           = 217,
255     CONNECT          = 218,
256     FINANCE          = 219,
257     SPORT            = 220,
258     SHOP             = 221,
259     ALTERASE         = 222,
260     CANCEL           = 223,
261     BRIGHTNESSDOWN   = 224,
262     BRIGHTNESSUP     = 225,
263     MEDIA            = 226,
264     SWITCHVIDEOMODE  = 227,
265     KBDILLUMTOGGLE   = 228,
266     KBDILLUMDOWN     = 229,
267     KBDILLUMUP       = 230,
268     SEND             = 231,
269     REPLY            = 232,
270     FORWARDMAIL      = 233,
271     SAVE             = 234,
272     DOCUMENTS        = 235,
273     UNKNOWN          = 240,
274     OK               = 0x160,
275     SELECT           = 0x161,
276     GOTO             = 0x162,
277     CLEAR            = 0x163,
278     POWER2           = 0x164,
279     OPTION           = 0x165,
280     INFO             = 0x166,
281     TIME             = 0x167,
282     VENDOR           = 0x168,
283     ARCHIVE          = 0x169,
284     PROGRAM          = 0x16a,
285     CHANNEL          = 0x16b,
286     FAVORITES        = 0x16c,
287     EPG              = 0x16d,
288     PVR              = 0x16e,
289     MHP              = 0x16f,
290     LANGUAGE         = 0x170,
291     TITLE            = 0x171,
292     SUBTITLE         = 0x172,
293     ANGLE            = 0x173,
294     ZOOM             = 0x174,
295     MODE             = 0x175,
296     KEYBOARD         = 0x176,
297     SCREEN           = 0x177,
298     PC               = 0x178,
299     TV               = 0x179,
300     TV2              = 0x17a,
301     VCR              = 0x17b,
302     VCR2             = 0x17c,
303     SAT              = 0x17d,
304     SAT2             = 0x17e,
305     CD               = 0x17f,
306     TAPE             = 0x180,
307     RADIO            = 0x181,
308     TUNER            = 0x182,
309     PLAYER           = 0x183,
310     TEXT             = 0x184,
311     DVD              = 0x185,
312     AUX              = 0x186,
313     MP3              = 0x187,
314     AUDIO            = 0x188,
315     VIDEO            = 0x189,
316     DIRECTORY        = 0x18a,
317     LIST             = 0x18b,
318     MEMO             = 0x18c,
319     CALENDAR         = 0x18d,
320     RED              = 0x18e,
321     GREEN            = 0x18f,
322     YELLOW           = 0x190,
323     BLUE             = 0x191,
324     CHANNELUP        = 0x192,
325     CHANNELDOWN      = 0x193,
326     FIRST            = 0x194,
327     LAST             = 0x195,
328     AB               = 0x196,
329     NEXT             = 0x197,
330     RESTART          = 0x198,
331     SLOW             = 0x199,
332     SHUFFLE          = 0x19a,
333     BREAK            = 0x19b,
334     PREVIOUS         = 0x19c,
335     DIGITS           = 0x19d,
336     TEEN             = 0x19e,
337     TWEN             = 0x19f,
338     DEL_EOL          = 0x1c0,
339     DEL_EOS          = 0x1c1,
340     INS_LINE         = 0x1c2,
341     DEL_LINE         = 0x1c3,
342     FN               = 0x1d0,
343     FN_ESC           = 0x1d1,
344     FN_F1            = 0x1d2,
345     FN_F2            = 0x1d3,
346     FN_F3            = 0x1d4,
347     FN_F4            = 0x1d5,
348     FN_F5            = 0x1d6,
349     FN_F6            = 0x1d7,
350     FN_F7            = 0x1d8,
351     FN_F8            = 0x1d9,
352     FN_F9            = 0x1da,
353     FN_F10           = 0x1db,
354     FN_F11           = 0x1dc,
355     FN_F12           = 0x1dd,
356     FN_1             = 0x1de,
357     FN_2             = 0x1df,
358     FN_D             = 0x1e0,
359     FN_E             = 0x1e1,
360     FN_F             = 0x1e2,
361     FN_S             = 0x1e3,
362     FN_B             = 0x1e4,
363     MAX              = 0x1ff,
364   };
365
366   Rel = {
367     X      = 0x00,
368     Y      = 0x01,
369     Z      = 0x02,
370     RX     = 0x03,
371     RY     = 0x04,
372     RZ     = 0x05,
373     HWHEEL = 0x06,
374     DIAL   = 0x07,
375     WHEEL  = 0x08,
376     MISC   = 0x09,
377     MAX    = 0x0f,
378   };
379
380   Abs = {
381     X          = 0x00,
382     Y          = 0x01,
383     Z          = 0x02,
384     RX         = 0x03,
385     RY         = 0x04,
386     RZ         = 0x05,
387     THROTTLE   = 0x06,
388     RUDDER     = 0x07,
389     WHEEL      = 0x08,
390     GAS        = 0x09,
391     BRAKE      = 0x0a,
392     HAT0X      = 0x10,
393     HAT0Y      = 0x11,
394     HAT1X      = 0x12,
395     HAT1Y      = 0x13,
396     HAT2X      = 0x14,
397     HAT2Y      = 0x15,
398     HAT3X      = 0x16,
399     HAT3Y      = 0x17,
400     PRESSURE   = 0x18,
401     DISTANCE   = 0x19,
402     TILT_X     = 0x1a,
403     TILT_Y     = 0x1b,
404     TOOL_WIDTH = 0x1c,
405     VOLUME     = 0x20,
406     MISC       = 0x28,
407     MT_TOUCH_MAJOR = 0x30,
408     MT_TOUCH_MINOR = 0x31,
409     MT_WIDTH_MAJOR = 0x32,
410     MT_WIDTH_MINOR = 0x33,
411     MT_ORIENTATION = 0x34,
412     MT_POSITION_X  = 0x35,
413     MT_POSITION_Y  = 0x36,
414     MT_TOOL_TYPE   = 0x37,
415     MT_BLOB_ID     = 0x38,
416     MT_TRACKING_ID = 0x39,
417     MAX        = 0x3f,
418   };
419
420   Btn = {
421     MISC           = 0x100,
422     BTN_0          = 0x100,
423     BTN_1          = 0x101,
424     BTN_2          = 0x102,
425     BTN_3          = 0x103,
426     BTN_4          = 0x104,
427     BTN_5          = 0x105,
428     BTN_6          = 0x106,
429     BTN_7          = 0x107,
430     BTN_8          = 0x108,
431     BTN_9          = 0x109,
432     MOUSE          = 0x110,
433     LEFT           = 0x110,
434     RIGHT          = 0x111,
435     MIDDLE         = 0x112,
436     SIDE           = 0x113,
437     EXTRA          = 0x114,
438     FORWARD        = 0x115,
439     BACK           = 0x116,
440     TASK           = 0x117,
441     JOYSTICK       = 0x120,
442     TRIGGER        = 0x120,
443     THUMB          = 0x121,
444     THUMB2         = 0x122,
445     TOP            = 0x123,
446     TOP2           = 0x124,
447     PINKIE         = 0x125,
448     BASE           = 0x126,
449     BASE2          = 0x127,
450     BASE3          = 0x128,
451     BASE4          = 0x129,
452     BASE5          = 0x12a,
453     BASE6          = 0x12b,
454     DEAD           = 0x12f,
455     GAMEPAD        = 0x130,
456     A              = 0x130,
457     B              = 0x131,
458     C              = 0x132,
459     X              = 0x133,
460     Y              = 0x134,
461     Z              = 0x135,
462     TL             = 0x136,
463     TR             = 0x137,
464     TL2            = 0x138,
465     TR2            = 0x139,
466     SELECT         = 0x13a,
467     START          = 0x13b,
468     MODE           = 0x13c,
469     THUMBL         = 0x13d,
470     THUMBR         = 0x13e,
471     DIGI           = 0x140,
472     TOOL_PEN       = 0x140,
473     TOOL_RUBBER    = 0x141,
474     TOOL_BRUSH     = 0x142,
475     TOOL_PENCIL    = 0x143,
476     TOOL_AIRBRUSH  = 0x144,
477     TOOL_FINGER    = 0x145,
478     TOOL_MOUSE     = 0x146,
479     TOOL_LENS      = 0x147,
480     TOUCH          = 0x14a,
481     STYLUS         = 0x14b,
482     STYLUS2        = 0x14c,
483     TOOL_DOUBLETAP = 0x14d,
484     TOOL_TRIPLETAP = 0x14e,
485     WHEEL          = 0x150,
486     GEAR_DOWN      = 0x150,
487     GEAR_UP        = 0x151,
488   };
489 };
490
491 -- stores all kown input devices
492
493 devices = {};
494 Input_device = {
495   Devs = {};
496   quirks = {};
497   Bus = {
498     [0x01] = "pci",
499     [0x02] = "isapnp",
500     [0x03] = "usb",
501     [0x04] = "hil",
502     [0x05] = "bluetooth",
503     [0x06] = "virtual",
504
505     [0x10] = "isa",
506     [0x11] = "i8042",
507     [0x12] = "xtkbd",
508     [0x13] = "rs232",
509     [0x14] = "gameport",
510     [0x15] = "parport",
511     [0x16] = "amiga",
512     [0x17] = "adb",
513     [0x18] = "i2c",
514     [0x19] = "host",
515     [0x1A] = "gsc",
516     [0x1B] = "atari",
517
518     PCI         = 0x01,
519     ISAPNP      = 0x02,
520     USB         = 0x03,
521     HIL         = 0x04,
522     BLUETOOTH   = 0x05,
523     VIRTUAL     = 0x06,
524     
525     ISA         = 0x10,
526     I8042       = 0x11,
527     XTKBD       = 0x12,
528     RS232       = 0x13,
529     GAMEPORT    = 0x14,
530     PARPORT     = 0x15,
531     AMIGA       = 0x16,
532     ADB         = 0x17,
533     I2C         = 0x18,
534     HOST        = 0x19,
535     GSC         = 0x1A,
536     ATARI       = 0x1B,
537   };
538 };
539
540 function Input_device:drop_event(e)
541   return true;
542 end
543
544 -- ----------------------------------------------------------------------
545 --  Generic pointer device handling.
546 --
547 --  Handles absolute and relative motion events and the buttons
548 --  corresponding to a pointer device, suahc as a mouse.
549 -- ----------------------------------------------------------------------
550 Input_device.Devs.pointer = {};
551
552 function Input_device.Devs.pointer:init()
553   -- raw position of an absolute device
554   self.raw_pos       = { 0, 0 };
555   self.motion        = { 0, 0 };
556   -- transformation of raw coordinates to screen coordinates
557   self.transform_pos = self:get_pointer_transform_func();
558   self.drag_focus    = user_state:create_view_proxy();
559   self.pointed_view  = user_state:create_view_proxy();
560
561   if (self.info:get_absbit(0) and self.info:get_absbit(1)) then
562     local res, x, y = self.device:get_abs_info(self.stream, 0, 1);
563     if res == 0 then
564       x.delta = x.max - x.min;
565       y.delta = y.max - y.min;
566       self.abs_info = { x, y };
567     end
568   end
569 end
570
571 -- generic transformationof absolute pointer events to screen coordinates
572 function Input_device:get_pointer_transform_func()
573   -- transformation of raw coordinates to screen coordinates
574   return function(self, x, y)
575     if self.abs_info then
576       return x * user_state.width / self.abs_info[1].delta,
577              y * user_state.height / self.abs_info[2].delta;
578     else
579       return x, y;
580     end
581   end;
582 end
583
584
585 function Input_device.Devs.pointer:motion(e)
586   local t = e[1];
587   local c = e[2];
588   if t == Event.REL and (c == 0 or c == 1) then
589     self.motion[c + 1] = e[3];
590     self.core_motion = 1;
591     return true; -- cosnumed event
592   elseif t == Event.ABS and (c == 0 or c == 1) then
593     self.raw_pos[c + 1] = e[3];
594     self.core_motion = 2;
595     return true; -- consumed event
596   end
597   return false; -- did not consume event (pass on)
598 end
599
600 function Input_device.Devs.pointer:button(e)
601   local c = e[2];
602   local v = e[3];
603   if v == 1 then
604     if self.pressed_keys == 0 then
605       self.set_focus = true;
606       self.start_drag = true;
607     end
608     self.pressed_keys = self.pressed_keys + 1;
609
610     if c == 70 then
611       self.toggle_mode = 1;
612     elseif c == 210 or c == 99 then
613       self.toggle_mode = 2;
614     end
615   elseif v == 0 then
616     self.pressed_keys = self.pressed_keys - 1;
617     if self.pressed_keys == 0 then
618       self.stop_drag = true;
619     end
620   end
621 end
622
623 -- ----------------------------------------------------------------
624 -- sync a set of events from a pointer device
625 --
626 -- - converts motion events to the core mouse pointer of mag
627 -- - manages dragging and keyboard focus
628
629 function Input_device.Devs.pointer:sync(ev)
630   local update = false;
631   local sink;
632
633   if self.stop_drag or self.pressed_keys > 0 then
634     sink = self.drag_focus;
635   else
636     sink = self.pointed_view;
637   end
638
639   if self.toggle_mode ~= 0 then
640     user_state:toggle_mode(self.toggle_mode);
641     update = true;
642   end
643   if self.core_motion == 2 then
644     local x, y = self:transform_pos(self.raw_pos[1], self.raw_pos[2]);
645     user_state:set_pointer(x, y);
646   elseif self.core_motion == 1 then
647     user_state:move_pointer(self.motion[1], self.motion[2]);
648     self.motion = { 0, 0 };
649   end
650
651   user_state:find_pointed_view(self.pointed_view);
652
653   if self.start_drag then
654     self.drag_focus:set(self.pointed_view);
655     self.start_drag = false;
656   end
657
658   -- print ("core_motion", self.core_motion);
659   if self.core_motion and self.core_motion ~= 0 then
660     if self.set_focus then
661       update = user_state:set_kbd_focus(self.pointed_view) or update;
662       self.set_focus = false;
663     end
664     user_state:post_pointer_event(sink, self.stream, ev[4]);
665     self.core_motion = 0;
666   elseif self.set_focus then
667     update = user_state:set_kbd_focus(self.pointed_view) or update;
668     self.set_focus = false;
669   end
670
671   for index = 1, #self.events do
672     local e = self.events[index];
673     user_state:post_event(sink, self.stream, ev[4], e[1], e[2], e[3]);
674   end
675
676   -- post syn event
677   user_state:post_event(sink, self.stream, ev[4], ev[1], ev[2], ev[3], update);
678
679   self.stop_drag = false;
680   self.toggle_mode = 0;
681   self.events = {}; -- clear old events
682 end
683
684 function Input_device.Devs.pointer:process(ev)
685 --  print ("got event:", time, device.stream, "f", device.can_set_focus, "f", t, c, v);
686
687   if ev[1] == 0 and ev[2] == 0 then
688     self.handler.sync(self, ev);
689     return;
690   end
691
692   if ev[1] == 1 then
693     if self.handler.button(self, ev) then
694       return;
695     end
696   elseif self.handler.motion(self, ev) then
697     return;
698   end
699
700   self.events[#self.events + 1] = ev;
701 end
702
703
704 Input_device.Devs.touchscreen = {};
705 setmetatable(Input_device.Devs.touchscreen, { __index = Input_device.Devs.pointer});
706
707 function Input_device.Devs.touchscreen:init()
708   Input_device.Devs.pointer.init(self);
709 end
710
711 function Input_device.Devs.touchscreen:button(e)
712   local c = e[2];
713   local v = e[3];
714   if c == Event.Btn.TOUCH then
715     e[2] = Event.Btn.LEFT;
716   end
717   Input_device.Devs.pointer.button(self, e);
718 end
719
720 -- ----------------------------------------------------------------------
721 --  Touchpad pointing device handling
722 --  Inherits from pointer device and adds functionality to:
723 --  - transform absolute finger positions to relative movements
724 --  - tapping button emulation (missing)
725 --  - scroll wheel emulation etc (missing)
726 -- ----------------------------------------------------------------------
727 Input_device.Devs.touchpad = {};
728 setmetatable(Input_device.Devs.touchpad, { __index = Input_device.Devs.pointer});
729
730 function Input_device.Devs.touchpad:init()
731   Input_device.Devs.pointer.init(self);
732   self.touchdev = {
733     touch      = false;
734     release    = false;
735     touch_drag = false;
736     tap_time   = 150 * 1000; -- 150 ms
737   };
738   local tdev = self.touchdev;
739   tdev.p    = { Mag.Axis_buf(4), Mag.Axis_buf(4) };
740   tdev.pkts = 0;
741 end
742
743 function Input_device.Devs.touchpad:button(e)
744   local c = e[2];
745   local v = e[3];
746   Input_device.Devs.pointer.button(self, e);
747   if c == Event.Btn.TOUCH and v ~= 2 then
748     local time = e[4];
749     local p = self.touchdev;
750     if v == 1 then
751       if p.release and p.release + p.tap_time > time then
752         p.touch_drag = true;
753         self:process({ Event.KEY, Event.Btn.LEFT, 1, p.touch, e[5], e[6] });
754       end
755       p.touch = time;
756       p.release = false;
757     else
758       if p.touch_drag then
759         p.touch_drag = false;
760         self:process({ Event.KEY, Event.Btn.LEFT, 0, time, e[5], e[6] });
761       elseif p.touch and p.touch + p.tap_time > time then
762         p.release = time;
763         self:process({ Event.KEY, Event.Btn.LEFT, 1, p.touch, e[5], e[6] });
764         self:process({ Event.KEY, Event.Btn.LEFT, 0, time, e[5], e[6] });
765       end
766       p.pkts = 0;
767       p.touch = false;
768     end
769   end
770 end
771
772 function Input_device.Devs.touchpad:motion(e)
773   local t = e[1];
774   local c = e[2];
775   local p = self.touchdev;
776   if not p.touch then
777     return true; -- drop event, if not touched
778   end
779
780   if t == Event.REL and (c == 0 or c == 1) then
781     self.motion[c + 1] = e[3];
782     self.core_motion = 1;
783     return true; -- cosnumed event
784   elseif t == Event.ABS and (c == 0 or c == 1) then
785     c = c + 1;
786     local v = e[3];
787     local cnt = p.pkts;
788     p.p[c][cnt] = v;
789     if cnt >= 2 then
790       local size = self.abs_info[c].delta;
791       self.motion[c] = (v - p.p[c]:get(cnt - 2)) * 256 / size;
792       self.core_motion = 1;
793     end
794     return true; -- cosnumed event
795   end
796   return false; -- did not consume event (pass on)
797 end
798
799 function Input_device.Devs.touchpad:sync(ev)
800   local p = self.touchdev;
801   if p.touch then
802     local nc = p.pkts + 1;
803     p.pkts = nc;
804     p.p[1]:copy(nc, nc - 1);
805     p.p[2]:copy(nc, nc - 1);
806   end
807   Input_device.Devs.pointer.sync(self, ev);
808 end
809
810 -- ----------------------------------------------------------------------
811 --  Keyboard device handling
812 -- ----------------------------------------------------------------------
813 Input_device.Devs.keyboard = {};
814
815 function Input_device.Devs.keyboard:process(ev)
816   local c = ev[2];
817   local v = ev[3];
818   local toggle_mode = 0;
819   if v == 1 then
820     self.pressed_keys = self.pressed_keys + 1;
821     if c == 70 then
822       toggle_mode = 1;
823     elseif c == 210 or c == 99 then
824       toggle_mode = 2;
825     end
826   elseif v == 0 then
827     self.pressed_keys = self.pressed_keys - 1;
828   end
829   local update = false;
830   if toggle_mode ~= 0 then
831     user_state:toggle_mode(toggle_mode);
832     update = true;
833   end
834   user_state:post_event(nil, self.stream, ev[4], ev[1], ev[2], ev[3], update);
835 end
836
837 function Input_device:find_device_type()
838   local bus, vend, prod, ver = self.info:get_device_id();
839   self.dev_id = { bus = bus, vendor = vend, product = prod, version = ver };
840   local id = bus .. "_" .. vend .. "_" .. prod;
841
842   self.dev_type = "unknown";
843
844   if self.quirks[id] and self.quirks[id](self, id) then
845     return;
846   end
847
848   id = id .. "_" .. ver;
849
850   if self.quirks[id] and self.quirks[id](self, id) then
851     return;
852   end
853
854   local have_keys = self.info:get_evbit(1);
855   if (have_keys and self.info:get_evbit(2)) then
856     -- we have relative axes, can ba a mouse
857     if (self.info:get_relbit(0) and self.info:get_relbit(1)
858         and self.info:get_keybit(0x110)) then
859       -- x and y axis and at least the left mouse button found
860       self.dev_type = "pointer";
861     end
862   end
863   if (have_keys and self.info:get_evbit(3)) then
864     -- we have absolute axes, can ba a mouse
865     if self.info:get_absbit(0) and self.info:get_absbit(1) then
866       if self.info:get_keybit(0x110) then
867         -- x and y axis and at least the left mouse button found
868         self.dev_type = "pointer";
869       end
870       if self.info:get_keybit(Event.Btn.TOUCH)
871          and not self.info:get_keybit(0x110) then
872         -- x and y axis and at least the left mouse button found
873         self.dev_type = "touchscreen";
874       end
875     end
876   end
877
878   if self.dev_type == "pointer" then
879     if self.info:get_keybit(Event.Btn.TOOL_FINGER) then
880       self.dev_type = "touchpad";
881     end
882   end
883
884   if (have_keys) then
885     local k;
886     for k = 0, 199 do
887       if (self.info:get_keybit(k)) then
888         self.dev_type = "keyboard";
889         return;
890       end
891     end
892   end
893 end
894
895
896 -- -----------------------------------------------------------------------
897 --  Create a input device (stream) object.
898 --  A single input stream is managed by a device specific set of
899 --  methods and data structures.
900 -- -----------------------------------------------------------------------
901 function create_input_device(device, stream)
902   local dh = {
903     -- the device handle itself
904     device        = device,
905     stream        = stream,
906
907     -- number of keys currently pressed on this device
908     pressed_keys  = 0,
909
910     -- data according to the current bundle of events (one comound event)
911     -- need to set the focus to the pointed view
912     set_focus     = false,
913     -- the current events stop dragging mode
914     stop_drag     = false,
915     -- the current events toggle kill and x-ray mode
916     toggle_mode   = 0,
917     -- the events to pass to the applications
918     events        = {},
919     -- event handler for the device
920     process       = Input_device.drop_event
921   };
922
923   local r;
924   r, dh.info = device:get_stream_info(stream);
925
926   local meta_table = meta_table or { __index = Input_device };
927   setmetatable(dh, meta_table);
928   devices[device][stream] = dh;
929
930   dh:find_device_type();
931   dh.handler = Input_device.Devs[dh.dev_type] or {};
932   dh.process = dh.handler.process or Input_device.drop_event;
933   if dh.handler.init then dh.handler.init(dh); end
934
935   local pdev;
936   function pdev(dh)
937     local a, b, c, d = dh.info:get_device_id();
938     return Input_device.Bus[a], b, c, d;
939   end
940
941   print (string.format([==[Input: new %s device (src='%s' stream='%s')
942                            bus='%s' vendor=0x%x product=0x%x version=%d]==],
943                        dh.dev_type, tostring(dh.device), tostring(dh.stream),
944                        pdev(dh)));
945   return dh;
946 end