]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/server/src/mag.lua
8ac3c5ba2646e638ac44e0cbb2f8f62e614afcff
[l4.git] / l4 / pkg / mag / server / src / mag.lua
1 -------------------------------------------------
2 -- exported functions used by the mag logic
3 -------------------------------------------------
4
5 Mag.user_state = Mag.get_user_state();
6
7 -- handle an incoming event
8 function handle_event(ev)
9   -- 1: type, 2: code, 3: value, 4: time, 5: device_id, 6: source
10   local source = ev[6];
11   local stream = ev[5];
12   local ddh = Mag.sources[source];
13   if not ddh then
14     Mag.sources[source] = {};
15     ddh =  Mag.sources[source];
16   end
17
18   local dh = ddh[stream];
19   if not dh then
20     dh = Mag.create_input_device(source, stream);
21   end
22
23   -- print ("EV: ", ev[1], ev[2], ev[3], ev[4], ev[5], ev[6]);
24   -- print(string.format("src=[%s:%s]: type=%x code=%x val=%x (time=%d)", tostring(ev[6]), tostring(ev[5]), ev[1], ev[2], ev[3], ev[4]));
25   return dh:process_event(ev);
26 end
27
28 -- mag requests infos about a specific input event stream
29 function input_source_info(global_id)
30   local device = Mag.streams[global_id];
31   if not device then
32     return -22;
33   end
34
35   return device.handler.get_stream_info(device);
36 end
37
38 -- mag requests infos about a specific input event stream
39 function input_source_abs_info(global_id, ...)
40   local device = Mag.streams[global_id];
41   if not device then
42     return -22;
43   end
44
45   return device.handler.get_abs_info(device, ...);
46 end
47
48
49
50 -------------------------------------------------
51 -- The internals of our event handling module
52 -------------------------------------------------
53 module("Mag", package.seeall)
54
55 -- mag will initialize the variable 'user_state' to refer to
56 -- mag's user state object.
57
58 Event = {
59   Type   = 1,
60   Code   = 2,
61   Value  = 3,
62   Time   = 4,
63   Device = 5,
64   Stream = 6,
65
66   SYN = 0;
67   KEY = 1;
68   REL = 2;
69   ABS = 3;
70   MSC = 4;
71   SW  = 5;
72
73   Syn = {
74     REPORT    = 0,
75     CONFIG    = 1,
76     MT_REPORT = 2,
77   };
78
79   Key = {
80     RESERVED         = 0,
81     ESC              = 1,
82     KEY_1            = 2,
83     KEY_2            = 3,
84     KEY_3            = 4,
85     KEY_4            = 5,
86     KEY_5            = 6,
87     KEY_6            = 7,
88     KEY_7            = 8,
89     KEY_8            = 9,
90     KEY_9            = 10,
91     KEY_0            = 11,
92     MINUS            = 12,
93     EQUAL            = 13,
94     BACKSPACE        = 14,
95     TAB              = 15,
96     Q                = 16,
97     W                = 17,
98     E                = 18,
99     R                = 19,
100     T                = 20,
101     Y                = 21,
102     U                = 22,
103     I                = 23,
104     O                = 24,
105     P                = 25,
106     LEFTBRACE        = 26,
107     RIGHTBRACE       = 27,
108     ENTER            = 28,
109     LEFTCTRL         = 29,
110     A                = 30,
111     S                = 31,
112     D                = 32,
113     F                = 33,
114     G                = 34,
115     H                = 35,
116     J                = 36,
117     K                = 37,
118     L                = 38,
119     SEMICOLON        = 39,
120     APOSTROPHE       = 40,
121     GRAVE            = 41,
122     LEFTSHIFT        = 42,
123     BACKSLASH        = 43,
124     Z                = 44,
125     X                = 45,
126     C                = 46,
127     V                = 47,
128     B                = 48,
129     N                = 49,
130     M                = 50,
131     COMMA            = 51,
132     DOT              = 52,
133     SLASH            = 53,
134     RIGHTSHIFT       = 54,
135     KPASTERISK       = 55,
136     LEFTALT          = 56,
137     SPACE            = 57,
138     CAPSLOCK         = 58,
139     F1               = 59,
140     F2               = 60,
141     F3               = 61,
142     F4               = 62,
143     F5               = 63,
144     F6               = 64,
145     F7               = 65,
146     F8               = 66,
147     F9               = 67,
148     F10              = 68,
149     NUMLOCK          = 69,
150     SCROLLLOCK       = 70,
151     KP7              = 71,
152     KP8              = 72,
153     KP9              = 73,
154     KPMINUS          = 74,
155     KP4              = 75,
156     KP5              = 76,
157     KP6              = 77,
158     KPPLUS           = 78,
159     KP1              = 79,
160     KP2              = 80,
161     KP3              = 81,
162     KP0              = 82,
163     KPDOT            = 83,
164     ZENKAKUHANKAKU   = 85,
165     KEY_102ND        = 86,
166     F11              = 87,
167     F12              = 88,
168     RO               = 89,
169     KATAKANA         = 90,
170     HIRAGANA         = 91,
171     HENKAN           = 92,
172     KATAKANAHIRAGANA = 93,
173     MUHENKAN         = 94,
174     KPJPCOMMA        = 95,
175     KPENTER          = 96,
176     RIGHTCTRL        = 97,
177     KPSLASH          = 98,
178     SYSRQ            = 99,
179     RIGHTALT         = 100,
180     LINEFEED         = 101,
181     HOME             = 102,
182     UP               = 103,
183     PAGEUP           = 104,
184     LEFT             = 105,
185     RIGHT            = 106,
186     END              = 107,
187     DOWN             = 108,
188     PAGEDOWN         = 109,
189     INSERT           = 110,
190     DELETE           = 111,
191     MACRO            = 112,
192     MUTE             = 113,
193     VOLUMEDOWN       = 114,
194     VOLUMEUP         = 115,
195     POWER            = 116,
196     KPEQUAL          = 117,
197     KPPLUSMINUS      = 118,
198     PAUSE            = 119,
199     KPCOMMA          = 121,
200     HANGEUL          = 122,
201     HANGUEL          = 122,
202     HANJA            = 123,
203     YEN              = 124,
204     LEFTMETA         = 125,
205     RIGHTMETA        = 126,
206     COMPOSE          = 127,
207     STOP             = 128,
208     AGAIN            = 129,
209     PROPS            = 130,
210     UNDO             = 131,
211     FRONT            = 132,
212     COPY             = 133,
213     OPEN             = 134,
214     PASTE            = 135,
215     FIND             = 136,
216     CUT              = 137,
217     HELP             = 138,
218     MENU             = 139,
219     CALC             = 140,
220     SETUP            = 141,
221     SLEEP            = 142,
222     WAKEUP           = 143,
223     FILE             = 144,
224     SENDFILE         = 145,
225     DELETEFILE       = 146,
226     XFER             = 147,
227     PROG1            = 148,
228     PROG2            = 149,
229     WWW              = 150,
230     MSDOS            = 151,
231     COFFEE           = 152,
232     DIRECTION        = 153,
233     CYCLEWINDOWS     = 154,
234     MAIL             = 155,
235     BOOKMARKS        = 156,
236     COMPUTER         = 157,
237     BACK             = 158,
238     FORWARD          = 159,
239     CLOSECD          = 160,
240     EJECTCD          = 161,
241     EJECTCLOSECD     = 162,
242     NEXTSONG         = 163,
243     PLAYPAUSE        = 164,
244     PREVIOUSSONG     = 165,
245     STOPCD           = 166,
246     RECORD           = 167,
247     REWIND           = 168,
248     PHONE            = 169,
249     ISO              = 170,
250     CONFIG           = 171,
251     HOMEPAGE         = 172,
252     REFRESH          = 173,
253     EXIT             = 174,
254     MOVE             = 175,
255     EDIT             = 176,
256     SCROLLUP         = 177,
257     SCROLLDOWN       = 178,
258     KPLEFTPAREN      = 179,
259     KPRIGHTPAREN     = 180,
260     NEW              = 181,
261     REDO             = 182,
262     F13              = 183,
263     F14              = 184,
264     F15              = 185,
265     F16              = 186,
266     F17              = 187,
267     F18              = 188,
268     F19              = 189,
269     F20              = 190,
270     F21              = 191,
271     F22              = 192,
272     F23              = 193,
273     F24              = 194,
274     PLAYCD           = 200,
275     PAUSECD          = 201,
276     PROG3            = 202,
277     PROG4            = 203,
278     SUSPEND          = 205,
279     CLOSE            = 206,
280     PLAY             = 207,
281     FASTFORWARD      = 208,
282     BASSBOOST        = 209,
283     PRINT            = 210,
284     HP               = 211,
285     CAMERA           = 212,
286     SOUND            = 213,
287     QUESTION         = 214,
288     EMAIL            = 215,
289     CHAT             = 216,
290     SEARCH           = 217,
291     CONNECT          = 218,
292     FINANCE          = 219,
293     SPORT            = 220,
294     SHOP             = 221,
295     ALTERASE         = 222,
296     CANCEL           = 223,
297     BRIGHTNESSDOWN   = 224,
298     BRIGHTNESSUP     = 225,
299     MEDIA            = 226,
300     SWITCHVIDEOMODE  = 227,
301     KBDILLUMTOGGLE   = 228,
302     KBDILLUMDOWN     = 229,
303     KBDILLUMUP       = 230,
304     SEND             = 231,
305     REPLY            = 232,
306     FORWARDMAIL      = 233,
307     SAVE             = 234,
308     DOCUMENTS        = 235,
309     UNKNOWN          = 240,
310     OK               = 0x160,
311     SELECT           = 0x161,
312     GOTO             = 0x162,
313     CLEAR            = 0x163,
314     POWER2           = 0x164,
315     OPTION           = 0x165,
316     INFO             = 0x166,
317     TIME             = 0x167,
318     VENDOR           = 0x168,
319     ARCHIVE          = 0x169,
320     PROGRAM          = 0x16a,
321     CHANNEL          = 0x16b,
322     FAVORITES        = 0x16c,
323     EPG              = 0x16d,
324     PVR              = 0x16e,
325     MHP              = 0x16f,
326     LANGUAGE         = 0x170,
327     TITLE            = 0x171,
328     SUBTITLE         = 0x172,
329     ANGLE            = 0x173,
330     ZOOM             = 0x174,
331     MODE             = 0x175,
332     KEYBOARD         = 0x176,
333     SCREEN           = 0x177,
334     PC               = 0x178,
335     TV               = 0x179,
336     TV2              = 0x17a,
337     VCR              = 0x17b,
338     VCR2             = 0x17c,
339     SAT              = 0x17d,
340     SAT2             = 0x17e,
341     CD               = 0x17f,
342     TAPE             = 0x180,
343     RADIO            = 0x181,
344     TUNER            = 0x182,
345     PLAYER           = 0x183,
346     TEXT             = 0x184,
347     DVD              = 0x185,
348     AUX              = 0x186,
349     MP3              = 0x187,
350     AUDIO            = 0x188,
351     VIDEO            = 0x189,
352     DIRECTORY        = 0x18a,
353     LIST             = 0x18b,
354     MEMO             = 0x18c,
355     CALENDAR         = 0x18d,
356     RED              = 0x18e,
357     GREEN            = 0x18f,
358     YELLOW           = 0x190,
359     BLUE             = 0x191,
360     CHANNELUP        = 0x192,
361     CHANNELDOWN      = 0x193,
362     FIRST            = 0x194,
363     LAST             = 0x195,
364     AB               = 0x196,
365     NEXT             = 0x197,
366     RESTART          = 0x198,
367     SLOW             = 0x199,
368     SHUFFLE          = 0x19a,
369     BREAK            = 0x19b,
370     PREVIOUS         = 0x19c,
371     DIGITS           = 0x19d,
372     TEEN             = 0x19e,
373     TWEN             = 0x19f,
374     DEL_EOL          = 0x1c0,
375     DEL_EOS          = 0x1c1,
376     INS_LINE         = 0x1c2,
377     DEL_LINE         = 0x1c3,
378     FN               = 0x1d0,
379     FN_ESC           = 0x1d1,
380     FN_F1            = 0x1d2,
381     FN_F2            = 0x1d3,
382     FN_F3            = 0x1d4,
383     FN_F4            = 0x1d5,
384     FN_F5            = 0x1d6,
385     FN_F6            = 0x1d7,
386     FN_F7            = 0x1d8,
387     FN_F8            = 0x1d9,
388     FN_F9            = 0x1da,
389     FN_F10           = 0x1db,
390     FN_F11           = 0x1dc,
391     FN_F12           = 0x1dd,
392     FN_1             = 0x1de,
393     FN_2             = 0x1df,
394     FN_D             = 0x1e0,
395     FN_E             = 0x1e1,
396     FN_F             = 0x1e2,
397     FN_S             = 0x1e3,
398     FN_B             = 0x1e4,
399     MAX              = 0x1ff,
400   };
401
402   Rel = {
403     X      = 0x00,
404     Y      = 0x01,
405     Z      = 0x02,
406     RX     = 0x03,
407     RY     = 0x04,
408     RZ     = 0x05,
409     HWHEEL = 0x06,
410     DIAL   = 0x07,
411     WHEEL  = 0x08,
412     MISC   = 0x09,
413     MAX    = 0x0f,
414   };
415
416   Abs = {
417     X          = 0x00,
418     Y          = 0x01,
419     Z          = 0x02,
420     RX         = 0x03,
421     RY         = 0x04,
422     RZ         = 0x05,
423     THROTTLE   = 0x06,
424     RUDDER     = 0x07,
425     WHEEL      = 0x08,
426     GAS        = 0x09,
427     BRAKE      = 0x0a,
428     HAT0X      = 0x10,
429     HAT0Y      = 0x11,
430     HAT1X      = 0x12,
431     HAT1Y      = 0x13,
432     HAT2X      = 0x14,
433     HAT2Y      = 0x15,
434     HAT3X      = 0x16,
435     HAT3Y      = 0x17,
436     PRESSURE   = 0x18,
437     DISTANCE   = 0x19,
438     TILT_X     = 0x1a,
439     TILT_Y     = 0x1b,
440     TOOL_WIDTH = 0x1c,
441     VOLUME     = 0x20,
442     MISC       = 0x28,
443     MT_SLOT        = 0x2f,
444     MT_TOUCH_MAJOR = 0x30,
445     MT_TOUCH_MINOR = 0x31,
446     MT_WIDTH_MAJOR = 0x32,
447     MT_WIDTH_MINOR = 0x33,
448     MT_ORIENTATION = 0x34,
449     MT_POSITION_X  = 0x35,
450     MT_POSITION_Y  = 0x36,
451     MT_TOOL_TYPE   = 0x37,
452     MT_BLOB_ID     = 0x38,
453     MT_TRACKING_ID = 0x39,
454     MT_PRESSURE    = 0x3a,
455     MT_DISTANCE    = 0x3b,
456     MAX        = 0x3f,
457   };
458
459   Btn = {
460     MISC           = 0x100,
461     BTN_0          = 0x100,
462     BTN_1          = 0x101,
463     BTN_2          = 0x102,
464     BTN_3          = 0x103,
465     BTN_4          = 0x104,
466     BTN_5          = 0x105,
467     BTN_6          = 0x106,
468     BTN_7          = 0x107,
469     BTN_8          = 0x108,
470     BTN_9          = 0x109,
471     MOUSE          = 0x110,
472     LEFT           = 0x110,
473     RIGHT          = 0x111,
474     MIDDLE         = 0x112,
475     SIDE           = 0x113,
476     EXTRA          = 0x114,
477     FORWARD        = 0x115,
478     BACK           = 0x116,
479     TASK           = 0x117,
480     JOYSTICK       = 0x120,
481     TRIGGER        = 0x120,
482     THUMB          = 0x121,
483     THUMB2         = 0x122,
484     TOP            = 0x123,
485     TOP2           = 0x124,
486     PINKIE         = 0x125,
487     BASE           = 0x126,
488     BASE2          = 0x127,
489     BASE3          = 0x128,
490     BASE4          = 0x129,
491     BASE5          = 0x12a,
492     BASE6          = 0x12b,
493     DEAD           = 0x12f,
494     GAMEPAD        = 0x130,
495     A              = 0x130,
496     B              = 0x131,
497     C              = 0x132,
498     X              = 0x133,
499     Y              = 0x134,
500     Z              = 0x135,
501     TL             = 0x136,
502     TR             = 0x137,
503     TL2            = 0x138,
504     TR2            = 0x139,
505     SELECT         = 0x13a,
506     START          = 0x13b,
507     MODE           = 0x13c,
508     THUMBL         = 0x13d,
509     THUMBR         = 0x13e,
510     DIGI           = 0x140,
511     TOOL_PEN       = 0x140,
512     TOOL_RUBBER    = 0x141,
513     TOOL_BRUSH     = 0x142,
514     TOOL_PENCIL    = 0x143,
515     TOOL_AIRBRUSH  = 0x144,
516     TOOL_FINGER    = 0x145,
517     TOOL_MOUSE     = 0x146,
518     TOOL_LENS      = 0x147,
519     TOUCH          = 0x14a,
520     STYLUS         = 0x14b,
521     STYLUS2        = 0x14c,
522     TOOL_DOUBLETAP = 0x14d,
523     TOOL_TRIPLETAP = 0x14e,
524     WHEEL          = 0x150,
525     GEAR_DOWN      = 0x150,
526     GEAR_UP        = 0x151,
527   };
528 };
529
530 -- stores all kown input devices
531 streams = {};
532 sources = {};
533 Input_device = {
534   Devs = {};
535   quirks = {};
536   Bus = {
537     [0x01] = "pci",
538     [0x02] = "isapnp",
539     [0x03] = "usb",
540     [0x04] = "hil",
541     [0x05] = "bluetooth",
542     [0x06] = "virtual",
543
544     [0x10] = "isa",
545     [0x11] = "i8042",
546     [0x12] = "xtkbd",
547     [0x13] = "rs232",
548     [0x14] = "gameport",
549     [0x15] = "parport",
550     [0x16] = "amiga",
551     [0x17] = "adb",
552     [0x18] = "i2c",
553     [0x19] = "host",
554     [0x1A] = "gsc",
555     [0x1B] = "atari",
556
557     PCI         = 0x01,
558     ISAPNP      = 0x02,
559     USB         = 0x03,
560     HIL         = 0x04,
561     BLUETOOTH   = 0x05,
562     VIRTUAL     = 0x06,
563
564     ISA         = 0x10,
565     I8042       = 0x11,
566     XTKBD       = 0x12,
567     RS232       = 0x13,
568     GAMEPORT    = 0x14,
569     PARPORT     = 0x15,
570     AMIGA       = 0x16,
571     ADB         = 0x17,
572     I2C         = 0x18,
573     HOST        = 0x19,
574     GSC         = 0x1A,
575     ATARI       = 0x1B,
576   };
577 };
578
579 function Input_device:drop_event(e)
580   return true;
581 end
582
583 function Input_device:get_stream_info()
584   return self.source:get_stream_info(self.stream);
585 end
586
587 function Input_device:get_abs_info(...)
588   return self.source:get_abs_info(self.stream, ...);
589 end
590
591
592 function Input_device:init()
593   self.current_report = Hid_report(self.global_id, 0x10, 0x29, 0x8, 0x10, 0x10 );
594 end
595
596 function Input_device:process_event(ev)
597   local r = self.current_report;
598   local t = ev[1];
599   local c = ev[2];
600   if t == 3 then
601     if c < 0x2f then
602       r:set(3, c, ev[3]);
603     else
604       r:mt_set(c, ev[3]);
605     end
606   elseif t == 1 then
607     r:add_key(c, ev[3]);
608   elseif t > 1 and t <=5 then
609     r:set(t, c, ev[3]);
610   elseif t == 0 and c == 2 then -- mt sync
611     r:submit_mt();
612   elseif t == 0 and c == 0 then -- full sync
613     r:sync(ev[4]);
614     self:process(r);
615     r:clear();
616   end
617 end
618
619 -- ----------------------------------------------------------------------
620 --  Generic pointer device handling.
621 --
622 --  Handles absolute and relative motion events and the buttons
623 --  corresponding to a pointer device, suahc as a mouse.
624 -- ----------------------------------------------------------------------
625 Input_device.Devs.pointer = {};
626
627 Input_device.Devs.pointer.drag_focus    = View_proxy(user_state);
628
629 function Input_device.new_virt_ctrl(_axes, _core)
630   local ctrl = { axes = _axes, core = _core };
631   for _, a in pairs(_axes) do
632     a.ctrl = ctrl;
633   end
634   return ctrl;
635 end
636
637 local screen_width, screen_height = user_state:screen_size()
638
639 Input_device.core_ctrl = Input_device.new_virt_ctrl(
640   { x = { idx = Event.Abs.X, min = 0, max = screen_width,
641           fuzz = 0, flat = 0, mode = 1, v = 0 },
642     y = { idx = Event.Abs.Y, min = 0, max = screen_height,
643           fuzz = 0, flat = 0, mode = 2, v = 0 } }, true);
644
645 function Input_device.Devs.pointer:init()
646   Input_device.init(self);
647   self.pointed_view  = View_proxy(user_state);
648
649   -- get core pointer control descriptions for x and y axis
650   local core_ctrl = Input_device.core_ctrl;
651
652   self.xfrm_abs_axes = {};
653   
654   local d_info = self.info;
655
656   if d_info:get_absbit(0) and d_info:get_absbit(1) then
657     -- we transfrom the absolute x and y axes of this device to core control
658     -- coordinates
659     self.xfrm_abs_axes[#self.xfrm_abs_axes] =
660       { x = Event.Abs.X, y = Event.Abs.Y,
661         -- we have our abs x and abs y axis controling our core pointer
662         core_x = core_ctrl.axes.x, core_y = core_ctrl.axes.y,
663         xfrm = self:get_pointer_transform_func(Event.Abs.X, Event.Abs.Y) };
664   end
665
666   self.virt_ctrls = { core_ctrl };
667
668   self.vaxes = { [Event.Abs.X] = core_ctrl.axes.x,
669                  [Event.Abs.Y] = core_ctrl.axes.y };
670
671   self.rel_to_abs_axes = { [Event.Rel.X] = { va = core_ctrl.axes.x, ctrl = core_ctrl },
672                            [Event.Rel.Y] = { va = core_ctrl.axes.y, ctrl = core_ctrl } };
673
674   local abs_info = Axis_info_vector(0x40);
675   self.current_report:set_abs_info(abs_info);
676   self.abs_info = abs_info;
677   for a = 0, 0x3f do
678     if d_info:get_absbit(a) then
679       local r, i = self:get_abs_info(a);
680       if r == 0 then
681         abs_info:set(a, i);
682       end
683     end
684   end
685
686   if abs_info[0] then
687     abs_info[0].mode = 1;
688   end
689   if abs_info[1] then
690     abs_info[1].mode = 2;
691   end
692
693   if d_info:get_absbit(0x35) and d_info:get_absbit(0x36) then
694     local mt_ctrl = Input_device.new_virt_ctrl(
695       { x = { idx = 0x35, min = 0, max = screen_width,
696               fuzz = 0, flat = 0, mode = 1, v = 0 },
697         y = { idx = 0x36, min = 0, max = screen_height,
698               fuzz = 0, flat = 0, mode = 2, v = 0 } })
699     self.xfrm_abs_axes[#self.xfrm_abs_axes + 1] =
700       { x = 0x35, y = 0x36, xfrm = self:get_pointer_transform_func(0x35, 0x36) };
701     self.vaxes[0x35] = mt_ctrl.axes.x;
702     self.vaxes[0x36] = mt_ctrl.axes.y;
703     abs_info[0x35].mode = 1;
704     abs_info[0x36].mode = 2;
705   end
706 end
707
708 function Input_device.Devs.pointer:get_stream_info()
709   local r, info = self:get_stream_info();
710
711   if r < 0 then
712     return r;
713   end
714
715   -- This device is translated to a core pointer
716   -- this means it sends always absolute X,Y axis pairs
717   if self.vaxes then
718     info:set_evbit(Event.ABS, true);
719     for a, _ in pairs(self.vaxes) do
720       info:set_absbit(a, true);
721     end
722   end
723
724   if self.rel_to_abs_axes then
725     for a, _ in pairs(self.rel_to_abs_axes) do
726       info:set_relbit(a, false);
727     end
728   end
729
730   return r, info;
731 end
732
733 function Input_device.Devs.pointer:get_abs_info(...)
734   local axes = {...};
735   local pass = true;
736   local vaxes = self.vaxes;
737   local r = {};
738
739   for _, s in ipairs(axes) do
740     if vaxes[s] then
741       r[_] = vaxes[s];
742     else
743       r[_] = self.abs_info[s];
744       if not r[_] then
745         return -22;
746       end
747     end
748   end
749   return (vaxes ~= nil), unpack(r);
750 end
751
752 -- generic transformationof absolute pointer events to screen coordinates
753 function Input_device:get_pointer_transform_func(ax, ay)
754   -- transformation of raw coordinates to screen coordinates
755   local w, h = user_state:screen_size();
756   return function(self, p)
757     if self.abs_info then
758       return p[1] * w / self.abs_info[ax].delta,
759              p[2] * h / self.abs_info[ay].delta;
760     else
761       return p[1], p[2];
762     end
763   end;
764 end
765
766 -- ----------------------------------------------------------------
767 -- sync a set of events from a pointer device
768 --
769 -- - converts motion events to the core mouse pointer of mag
770 -- - manages dragging and keyboard focus
771
772
773 Input_device.Default = {};
774
775 function Input_device.Default:axis_xfrm(report)
776   local function do_xfrm_axes(xfrm_axes, axes)
777     if not axes then return end
778     for i, cax in pairs(xfrm_axes) do
779       local x = axes[cax.x];
780       local y = axes[cax.y];
781       if x and y then
782         x, y = cax.xfrm(self, {x, y});
783         axes[cax.x] = x;
784         axes[cax.y] = y;
785         local ca = cax.core_x;
786         if ca then
787           ca.v = x;
788           ca.ctrl.update = true;
789         end
790         local ca = cax.core_y;
791         if ca then
792           ca.v = y;
793           ca.ctrl.update = true;
794         end
795       end
796     end
797   end
798
799   -- scale and rotate absolute axes
800   local abs = report[3];
801   do_xfrm_axes(self.xfrm_abs_axes, abs);
802   for id = 0, 10 do
803     do_xfrm_axes(self.xfrm_abs_axes, report:get_mt_vals(id));
804   end
805
806   -- transform relative to absolute axes if needed
807   local rel = report[2];
808   if rel then
809     for a, inf in pairs(self.rel_to_abs_axes) do
810       local v = rel[a];
811       if v then
812         rel:inv(a);
813         local vctrl = inf.ctrl;
814         local va = inf.va;
815         v = va.v + v;
816         if v < va.min then
817           v = va.min;
818         end
819         if v > va.max then
820           v = va.max;
821         end
822         va.v = v;
823         vctrl.dirty = true;
824       end
825     end
826   end
827
828   -- write back virtual controls if they are dirty
829   if abs then
830     for c, vc in pairs(self.virt_ctrls) do
831         for i, va in pairs(vc.axes) do
832           abs:set(va.idx, va.v);
833         end
834       if vc.dirty then
835         vc.update = true; -- if its a core control we need an update
836         vc.dirty = false;
837       end
838     end
839   end
840 end
841
842 function Input_device.Default:foreach_key(report, func)
843   local i = 0;
844   while true do
845     local c, v = report:get_key_event(i);
846     if not c then
847       break;
848     end
849     if func(self, c, v) then
850       return true;
851     end
852     i = i + 1;
853   end
854 end
855
856 function Input_device.Default:do_core_ctrl()
857   local cctrl = Input_device.core_ctrl;
858   if cctrl.update then
859     cctrl.update = false;
860     local x, y = cctrl.axes.x.v, cctrl.axes.y.v;
861     user_state:set_pointer(x, y, self.hide_cursor or false);
862     user_state:find_pointed_view(self.pointed_view); -- should need x and y here
863   end
864 end
865
866 function Input_device.Default:core_keys(report)
867   local toggle_mode = 0;
868   local function xray_key(s, c, v)
869     if v ~= 1 then
870       return false;
871     end
872     return (c == 70) or (c == Event.Key.NEXTSONG);
873   end
874
875   local function kill_key(s, c, v)
876     if v ~= 1 then
877       return false;
878     end
879     return (c == 210) or (c == 99);
880   end
881
882   local fek = Input_device.Default.foreach_key;
883
884   if fek(self, report, xray_key) then
885     toggle_mode = 1;
886   elseif fek(self, report, kill_key) then
887     toggle_mode = 2;
888   end
889   if toggle_mode ~= 0 then
890     user_state:toggle_mode(toggle_mode);
891     return true;
892   end
893   return false;
894 end
895
896 function Input_device.Default:dnd_handling()
897   local ptr = Input_device.Devs.pointer;
898   if ptr.dragging then
899     if ptr.dragging == self and self.stop_drag then
900       ptr.dragging = false;
901     end
902     self.stop_drag = false;
903     return ptr.drag_focus;
904   else
905     return self.pointed_view;
906   end
907 end
908
909 function Input_device.Devs.pointer:hook(report)
910   local n_press = 0;
911   local n_release = 0;
912   local function k(s, c, v)
913     if v == 1 then
914       n_press = n_press + 1;
915     elseif v == 0 then
916       n_release = n_release + 1;
917     end
918   end
919   Input_device.Default.foreach_key(self, report, k);
920
921   local n = self.pressed_keys + n_press - n_release;
922   if n < 0 then
923     n = 0;
924   end
925
926   self.pressed_keys = n;
927
928   local ptr = Input_device.Devs.pointer;
929
930   if (not ptr.dragging) and n_press > 0 and n == n_press then
931     ptr.dragging = self;
932     ptr.drag_focus:set(self.pointed_view);
933     self.set_focus = true;
934   elseif n_release > 0 and n == 0 then
935     self.stop_drag = true;
936   end
937 end
938
939 function Input_device.Devs.pointer:process(report)
940   local update = false;
941   local sink;
942   local dfl = Input_device.Default;
943
944   dfl.axis_xfrm(self, report);
945   dfl.do_core_ctrl(self);
946
947   if self.handler.hook then
948     self.handler.hook(self, report);
949   end
950
951   sink = dfl.dnd_handling(self);
952   -- for keyboards: update = dfl.core_keys(self, report);
953   if self.set_focus then
954     update = user_state:set_kbd_focus(self.pointed_view) or update;
955     self.set_focus = false;
956   end
957   user_state:post_event(sink, report, update, true);
958 end
959
960
961 Input_device.Devs.touchscreen = {};
962 setmetatable(Input_device.Devs.touchscreen, { __index = Input_device.Devs.pointer});
963
964 function Input_device.Devs.touchscreen:init()
965   Input_device.Devs.pointer.init(self);
966   self.hide_cursor = true;
967 end
968
969 function Input_device.Devs.touchscreen:get_stream_info()
970   local r, info = Input_device.Devs.pointer.get_stream_info(self);
971
972   if r < 0 then
973     return r;
974   end
975
976   -- additionally we have a left button, but no longer the touch button
977   --info:set_keybit(Event.Btn.TOUCH, false);
978   --info:set_keybit(Event.Btn.LEFT, true);
979   return r, info;
980 end
981
982 function Input_device.Devs.touchscreen:button(e)
983   local c = e[2];
984   local v = e[3];
985   if c == Event.Btn.TOUCH then
986     e[2] = Event.Btn.LEFT;
987   end
988   Input_device.Devs.pointer.button(self, e);
989 end
990
991 -- ----------------------------------------------------------------------
992 --  Touchpad pointing device handling
993 --  Inherits from pointer device and adds functionality to:
994 --  - transform absolute finger positions to relative movements
995 --  - tapping button emulation (missing)
996 --  - scroll wheel emulation etc (missing)
997 -- ----------------------------------------------------------------------
998 Input_device.Devs.touchpad = {};
999 setmetatable(Input_device.Devs.touchpad, { __index = Input_device.Devs.pointer});
1000
1001 function Input_device.Devs.touchpad:init()
1002   Input_device.Devs.pointer.init(self);
1003   self.touchdev = {
1004     touch      = false;
1005     release    = false;
1006     touch_drag = false;
1007     tap_time   = 150 * 1000; -- 150 ms
1008     btn_report = Hid_report(self.global_id,0,0,0,0,0);
1009   };
1010   local tdev = self.touchdev;
1011   tdev.p    = { Axis_buf(4), Axis_buf(4) };
1012   tdev.pkts = 0;
1013 end
1014
1015 function Input_device.Devs.touchpad:get_stream_info()
1016   local r, info = Input_device.Devs.pointer.get_stream_info(self);
1017
1018   if r < 0 then
1019     return r;
1020   end
1021
1022   -- additionally we have a left button, but no longer the touch button
1023   info:set_keybit(Event.Btn.LEFT, true);
1024   info:set_keybit(Event.Btn.TOOL_FINGER, false);
1025   info:set_keybit(Event.Btn.TOOL_PEN, true);
1026
1027   -- hm, X does not like to have MT values if we do not send them
1028   info:set_absbit(0x2f, false);
1029   info:set_absbit(0x30, false);
1030   info:set_absbit(0x31, false);
1031   info:set_absbit(0x32, false);
1032   info:set_absbit(0x33, false);
1033   info:set_absbit(0x34, false);
1034   info:set_absbit(0x35, false);
1035   info:set_absbit(0x36, false);
1036   info:set_absbit(0x37, false);
1037   info:set_absbit(0x38, false);
1038   info:set_absbit(0x39, false);
1039   info:set_absbit(0x3a, false);
1040   info:set_absbit(0x3b, false);
1041
1042   return r, info;
1043 end
1044
1045 function Input_device.Devs.touchpad:button(r)
1046   local c, v = r:find_key_event(Event.Btn.TOUCH);
1047   if not v or v == 2 then
1048     return
1049   end
1050
1051   local time = r:time();
1052   local p = self.touchdev;
1053
1054   -- drop the touch event, we convert it to left mouse button
1055   --r[1][Event.Btn.TOUCH] = nil;
1056   r:remove_key_event(Event.Btn.TOOL_FINGER);
1057
1058   if v == 1 then
1059     if p.release and p.release + p.tap_time > time then
1060       p.touch_drag = true;
1061       r:add_key(Event.Btn.LEFT, 1);
1062     end
1063     p.touch = time;
1064     p.release = false;
1065   else
1066     if p.touch_drag then
1067       p.touch_drag = false;
1068       r:add_key(Event.Btn.LEFT, 0);
1069     elseif p.touch and p.touch + p.tap_time > time then
1070       p.release = time;
1071
1072       local dr = p.btn_report;
1073
1074       dr:clear();
1075       dr:sync(time);
1076       dr:add_key(Event.Btn.LEFT, 1);
1077       self:process(dr);
1078
1079       r:add_key(Event.Btn.LEFT, 0);
1080     end
1081     p.pkts = 0;
1082     p.touch = false;
1083   end
1084 end
1085
1086 function Input_device.Devs.touchpad:motion(r)
1087   local p = self.touchdev;
1088   if not p.touch then
1089     -- drop event, if not touched
1090     r[2]:clear();
1091     r[3]:clear();
1092     return
1093   end
1094
1095   local abs = r[3];
1096   for c = 1, 2 do
1097     local v = abs[c-1];
1098     if v then
1099       local cnt = p.pkts;
1100       p.p[c][cnt] = v;
1101       if cnt >= 2 then
1102         local size = self.abs_info[c-1].delta;
1103         r[2]:set(c-1, (v - p.p[c]:get(cnt - 2)) * 256 / size);
1104       end
1105       abs:inv(c-1);
1106     end
1107   end
1108
1109   local nc = p.pkts + 1;
1110   p.pkts = nc;
1111   p.p[1]:copy(nc, nc - 1);
1112   p.p[2]:copy(nc, nc - 1);
1113 end
1114
1115 function Input_device.Devs.touchpad:process(r)
1116   Input_device.Devs.touchpad.button(self, r);
1117   Input_device.Devs.touchpad.motion(self, r);
1118   Input_device.Devs.pointer.process(self, r)
1119 end
1120
1121 -- ----------------------------------------------------------------------
1122 --  Keyboard device handling
1123 -- ----------------------------------------------------------------------
1124 Input_device.Devs.keyboard = {};
1125 setmetatable(Input_device.Devs.keyboard, { __index = Input_device });
1126
1127 function Input_device.Devs.keyboard:get_stream_info()
1128   return self:get_stream_info();
1129 end
1130
1131 function Input_device.Devs.keyboard:get_abs_info(...)
1132   return self:get_abs_info(...);
1133 end
1134
1135 function Input_device.Devs.keyboard:process(report)
1136   local dfl = Input_device.Default;
1137
1138   if self.handler.hook then
1139     self.handler.hook(self, report);
1140   end
1141   local update = dfl.core_keys(self, report);
1142   user_state:post_event(nil, report, update, true);
1143 end
1144
1145 Input_device.Devs.unknown = Input_device;
1146
1147 function Input_device:find_device_type()
1148   local bus, vend, prod, ver = self.info:get_device_id();
1149   self.dev_id = { bus = bus, vendor = vend, product = prod, version = ver };
1150   local id = bus .. "_" .. vend .. "_" .. prod;
1151
1152   self.dev_type = "unknown";
1153
1154   if self.quirks[id] and self.quirks[id](self, id) then
1155     return;
1156   end
1157
1158   id = id .. "_" .. ver;
1159
1160   if self.quirks[id] and self.quirks[id](self, id) then
1161     return;
1162   end
1163
1164   local have_keys = self.info:get_evbit(1);
1165   if (have_keys and self.info:get_evbit(2)) then
1166     -- we have relative axes, can be a mouse
1167     if (self.info:get_relbit(0) and self.info:get_relbit(1)
1168         and self.info:get_keybit(0x110)) then
1169       -- x and y axis and at least the left mouse button found
1170       self.dev_type = "pointer";
1171     end
1172   end
1173   if (have_keys and self.info:get_evbit(3)) then
1174     -- we have absolute axes, can be a mouse
1175     if self.info:get_absbit(0) and self.info:get_absbit(1) then
1176       if self.info:get_keybit(0x110) then
1177         -- x and y axis and at least the left mouse button found
1178         self.dev_type = "pointer";
1179       end
1180       if self.info:get_keybit(Event.Btn.TOUCH)
1181          and not self.info:get_keybit(0x110) then
1182         -- x and y axis and at least touch button found
1183         self.dev_type = "touchscreen";
1184       end
1185     end
1186   end
1187
1188   if self.dev_type == "pointer" then
1189     if self.info:get_keybit(Event.Btn.TOOL_FINGER) then
1190       self.dev_type = "touchpad";
1191     end
1192   end
1193
1194   if (have_keys) then
1195     local k;
1196     for k = 0, 199 do
1197       if (self.info:get_keybit(k)) then
1198         self.dev_type = "keyboard";
1199         return;
1200       end
1201     end
1202   end
1203 end
1204
1205
1206 -- -----------------------------------------------------------------------
1207 --  Create a input device (stream) object.
1208 --  A single input stream is managed by a device specific set of
1209 --  methods and data structures.
1210 -- -----------------------------------------------------------------------
1211 local input_device_mt = { __index = Input_device };
1212
1213 function create_input_device(source, stream)
1214   local dh = {
1215     -- the device handle itself
1216     source        = source,
1217     stream        = stream,
1218     global_id     = #streams + 1;
1219
1220     -- number of keys currently pressed on this device
1221     pressed_keys  = 0,
1222
1223     -- data according to the current bundle of events (one comound event)
1224     -- need to set the focus to the pointed view
1225     set_focus     = false,
1226     -- the current events stop dragging mode
1227     stop_drag     = false,
1228     -- the events to pass to the applications
1229     events        = {},
1230     -- event handler for the device
1231     process       = Input_device.drop_event
1232   };
1233
1234   setmetatable(dh, input_device_mt);
1235
1236   local r;
1237   r, dh.info = dh:get_stream_info();
1238
1239   sources[source][stream] = dh;
1240   streams[dh.global_id] = dh;
1241
1242   dh:find_device_type();
1243   dh.handler = Input_device.Devs[dh.dev_type] or {};
1244   dh.process = dh.handler.process or Input_device.drop_event;
1245   if dh.handler.init then dh.handler.init(dh); end
1246
1247   local pdev;
1248   function pdev(dh)
1249     local a, b, c, d = dh.info:get_device_id();
1250     if Input_device.Bus[a] then
1251       return Input_device.Bus[a], b, c, d;
1252     end
1253     return "bus " .. a, b, c, d;
1254   end
1255
1256   print (string.format([==[Input: new %s device (src='%s' stream='%s')
1257                            bus='%s' vendor=0x%x product=0x%x version=%d]==],
1258                        dh.dev_type, tostring(dh.source), tostring(dh.stream),
1259                        pdev(dh)));
1260   return dh;
1261 end