1 function handle_event(ev)
4 local ddh = Mag.devices[device];
6 Mag.devices[device] = {};
7 ddh = Mag.devices[device];
10 local dh = ddh[stream];
12 dh = Mag.create_input_device(device, stream);
15 -- print ("EV: ", ev[1], ev[2], ev[3], ev[4], ev[5], ev[6]);
16 return dh:process(ev);
20 module("Mag", package.seeall);
136 KATAKANAHIRAGANA = 93,
261 BRIGHTNESSDOWN = 224,
264 SWITCHVIDEOMODE = 227,
265 KBDILLUMTOGGLE = 228,
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,
416 MT_TRACKING_ID = 0x39,
476 TOOL_AIRBRUSH = 0x144,
483 TOOL_DOUBLETAP = 0x14d,
484 TOOL_TRIPLETAP = 0x14e,
491 -- stores all kown input devices
502 [0x05] = "bluetooth",
540 function Input_device:drop_event(e)
544 -- ----------------------------------------------------------------------
545 -- Generic pointer device handling.
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 = {};
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();
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);
564 x.delta = x.max - x.min;
565 y.delta = y.max - y.min;
566 self.abs_info = { x, y };
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;
585 function Input_device.Devs.pointer:motion(e)
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
597 return false; -- did not consume event (pass on)
600 function Input_device.Devs.pointer:button(e)
604 if self.pressed_keys == 0 then
605 self.set_focus = true;
606 self.start_drag = true;
608 self.pressed_keys = self.pressed_keys + 1;
611 self.toggle_mode = 1;
612 elseif c == 210 or c == 99 then
613 self.toggle_mode = 2;
616 self.pressed_keys = self.pressed_keys - 1;
617 if self.pressed_keys == 0 then
618 self.stop_drag = true;
623 -- ----------------------------------------------------------------
624 -- sync a set of events from a pointer device
626 -- - converts motion events to the core mouse pointer of mag
627 -- - manages dragging and keyboard focus
629 function Input_device.Devs.pointer:sync(ev)
630 local update = false;
633 if self.stop_drag or self.pressed_keys > 0 then
634 sink = self.drag_focus;
636 sink = self.pointed_view;
639 if self.toggle_mode ~= 0 then
640 user_state:toggle_mode(self.toggle_mode);
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 };
651 user_state:find_pointed_view(self.pointed_view);
653 if self.start_drag then
654 self.drag_focus:set(self.pointed_view);
655 self.start_drag = false;
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;
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;
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]);
677 user_state:post_event(sink, self.stream, ev[4], ev[1], ev[2], ev[3], update);
679 self.stop_drag = false;
680 self.toggle_mode = 0;
681 self.events = {}; -- clear old events
684 function Input_device.Devs.pointer:process(ev)
685 -- print ("got event:", time, device.stream, "f", device.can_set_focus, "f", t, c, v);
687 if ev[1] == 0 and ev[2] == 0 then
688 self.handler.sync(self, ev);
693 if self.handler.button(self, ev) then
696 elseif self.handler.motion(self, ev) then
700 self.events[#self.events + 1] = ev;
704 Input_device.Devs.touchscreen = {};
705 setmetatable(Input_device.Devs.touchscreen, { __index = Input_device.Devs.pointer});
707 function Input_device.Devs.touchscreen:init()
708 Input_device.Devs.pointer.init(self);
711 function Input_device.Devs.touchscreen:button(e)
714 if c == Event.Btn.TOUCH then
715 e[2] = Event.Btn.LEFT;
717 Input_device.Devs.pointer.button(self, e);
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});
730 function Input_device.Devs.touchpad:init()
731 Input_device.Devs.pointer.init(self);
736 tap_time = 150 * 1000; -- 150 ms
738 local tdev = self.touchdev;
739 tdev.p = { Mag.Axis_buf(4), Mag.Axis_buf(4) };
743 function Input_device.Devs.touchpad:button(e)
746 Input_device.Devs.pointer.button(self, e);
747 if c == Event.Btn.TOUCH and v ~= 2 then
749 local p = self.touchdev;
751 if p.release and p.release + p.tap_time > time then
753 self:process({ Event.KEY, Event.Btn.LEFT, 1, p.touch, e[5], e[6] });
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
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] });
772 function Input_device.Devs.touchpad:motion(e)
775 local p = self.touchdev;
777 return true; -- drop event, if not touched
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
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;
794 return true; -- cosnumed event
796 return false; -- did not consume event (pass on)
799 function Input_device.Devs.touchpad:sync(ev)
800 local p = self.touchdev;
802 local nc = p.pkts + 1;
804 p.p[1]:copy(nc, nc - 1);
805 p.p[2]:copy(nc, nc - 1);
807 Input_device.Devs.pointer.sync(self, ev);
810 -- ----------------------------------------------------------------------
811 -- Keyboard device handling
812 -- ----------------------------------------------------------------------
813 Input_device.Devs.keyboard = {};
815 function Input_device.Devs.keyboard:process(ev)
818 local toggle_mode = 0;
820 self.pressed_keys = self.pressed_keys + 1;
823 elseif c == 210 or c == 99 then
827 self.pressed_keys = self.pressed_keys - 1;
829 local update = false;
830 if toggle_mode ~= 0 then
831 user_state:toggle_mode(toggle_mode);
834 user_state:post_event(nil, self.stream, ev[4], ev[1], ev[2], ev[3], update);
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;
842 self.dev_type = "unknown";
844 if self.quirks[id] and self.quirks[id](self, id) then
848 id = id .. "_" .. ver;
850 if self.quirks[id] and self.quirks[id](self, id) then
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 be 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";
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";
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";
878 if self.dev_type == "pointer" then
879 if self.info:get_keybit(Event.Btn.TOOL_FINGER) then
880 self.dev_type = "touchpad";
887 if (self.info:get_keybit(k)) then
888 self.dev_type = "keyboard";
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)
903 -- the device handle itself
907 -- number of keys currently pressed on this device
910 -- data according to the current bundle of events (one comound event)
911 -- need to set the focus to the pointed view
913 -- the current events stop dragging mode
915 -- the current events toggle kill and x-ray mode
917 -- the events to pass to the applications
919 -- event handler for the device
920 process = Input_device.drop_event
924 r, dh.info = device:get_stream_info(stream);
926 local meta_table = meta_table or { __index = Input_device };
927 setmetatable(dh, meta_table);
928 devices[device][stream] = dh;
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
937 local a, b, c, d = dh.info:get_device_id();
938 if Input_device.Bus[a] then
939 return Input_device.Bus[a], b, c, d;
941 return "bus " .. a, b, c, d;
944 print (string.format([==[Input: new %s device (src='%s' stream='%s')
945 bus='%s' vendor=0x%x product=0x%x version=%d]==],
946 dh.dev_type, tostring(dh.device), tostring(dh.stream),