From afcad2a9688fb02f78a8b7a317d779e84e50ba18 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 20 Apr 2018 14:27:45 +0200 Subject: [PATCH] os: new Input::Event representation This commit changes the 'Input::Event' type to be more safe and to deliver symbolic character information along with press events. Issue #2761 Fixes #2786 --- repos/dde_linux/run/usb_hid.run | 30 +- .../src/lib/usb/input/input_component.cc | 39 +- repos/demo/include/scout/platform.h | 27 +- .../src/server/liquid_framebuffer/services.cc | 21 +- repos/demo/src/server/nitlog/main.cc | 24 +- .../key_sequence_tracker.h | 22 +- .../app/floating_window_layouter/user_state.h | 39 +- repos/gems/src/app/launcher/context_dialog.h | 15 +- repos/gems/src/app/launcher/main.cc | 11 +- repos/gems/src/app/launcher/menu_dialog.h | 16 +- repos/gems/src/app/launcher/panel_dialog.h | 19 +- repos/gems/src/app/menu_view/main.cc | 10 +- repos/gems/src/server/terminal/main.cc | 33 +- .../gems/src/server/wm/decorator_nitpicker.h | 10 +- repos/gems/src/server/wm/nitpicker.h | 59 +-- repos/libports/run/qt5_drivers.inc | 3 + repos/libports/src/app/pdf_view/main.cc | 8 +- .../src/app/qt5/qt_avplay/control_bar.cpp | 8 +- .../nitpicker/qnitpickerplatformwindow.cpp | 362 ++++++++++-------- .../nitpicker/qnitpickerplatformwindow.h | 19 +- .../src/lib/sdl/video/SDL_genode_fb_events.cc | 82 ++-- repos/libports/src/server/acpi_input/main.cc | 7 +- repos/os/include/input/event.h | 261 ++++++++----- repos/os/run/input_filter.run | 32 +- repos/os/src/app/global_keys_handler/main.cc | 31 +- .../src/drivers/framebuffer/spec/sdl/input.cc | 46 +-- .../src/drivers/input/spec/imx53/egalax_ts.h | 12 +- .../os/src/drivers/input/spec/imx53/mpr121.h | 8 +- .../src/drivers/input/spec/ps2/ps2_keyboard.h | 13 +- .../os/src/drivers/input/spec/ps2/ps2_mouse.h | 14 +- .../server/input_filter/accelerate_source.h | 23 +- .../input_filter/button_scroll_source.h | 43 +-- .../src/server/input_filter/chargen_source.h | 97 ++--- repos/os/src/server/input_filter/connection.h | 4 +- .../os/src/server/input_filter/remap_source.h | 23 +- repos/os/src/server/loader/input.h | 17 +- repos/os/src/server/nit_fb/main.cc | 49 +-- .../src/server/nitpicker/session_component.cc | 14 +- repos/os/src/server/nitpicker/user_state.cc | 171 ++++----- repos/os/src/test/audio_out_click/main.cc | 10 +- repos/os/src/test/input/test.cc | 66 +--- repos/os/src/test/input_filter/main.cc | 124 +++--- repos/os/src/test/nitpicker/test.cc | 28 +- repos/ports/src/app/seoul/console.cc | 75 ++-- .../ports/src/virtualbox/frontend/console.cc | 177 ++++----- .../ports/src/virtualbox5/frontend/console.cc | 177 ++++----- 46 files changed, 1170 insertions(+), 1209 deletions(-) diff --git a/repos/dde_linux/run/usb_hid.run b/repos/dde_linux/run/usb_hid.run index 74fb1a8a3..9718367f4 100644 --- a/repos/dde_linux/run/usb_hid.run +++ b/repos/dde_linux/run/usb_hid.run @@ -200,12 +200,12 @@ if { [have_include "power_on/qemu"] || ![get_cmd_switch --autopilot] } { run_gen # autopilot test -run_genode_until {\[init -\> test-input\] Input event #1\t} 60 +run_genode_until {\[init -\> test-input\] Input event #0\t} 60 # remove everything before the first interesting line -regexp {(\[init -\> test-input\] Input event #1\t.*)} $output all output +regexp {(\[init -\> test-input\] Input event #0\t.*)} $output all output -run_genode_until {\[init -\> test-input\] Input event #12.*\n} 40 [output_spawn_id] +run_genode_until {\[init -\> test-input\] Input event #11.*\n} 40 [output_spawn_id] # pay only attention to the output of init and its children grep_output {^\[init } @@ -220,22 +220,22 @@ filter_out_color_escape_sequences trim_lines compare_output_to { -[init -> test-input] Input event #1 type=PRESS code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=1 KEY_X -[init -> test-input] Input event #2 type=RELEASE code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=0 KEY_X -[init -> test-input] Input event #3 type=PRESS code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=1 BTN_LEFT -[init -> test-input] Input event #4 type=MOTION code=0 rx=-1 ry=0 ax=0 ay=0 key_cnt=1 -[init -> test-input] Input event #5 type=MOTION code=0 rx=0 ry=1 ax=0 ay=0 key_cnt=1 -[init -> test-input] Input event #6 type=RELEASE code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=0 BTN_LEFT +[init -> test-input] Input event #0 PRESS KEY_X 0 +[init -> test-input] Input event #1 RELEASE KEY_X +[init -> test-input] Input event #2 PRESS BTN_LEFT 0 +[init -> test-input] Input event #3 REL_MOTION -1+0 +[init -> test-input] Input event #4 REL_MOTION +0+1 +[init -> test-input] Input event #5 RELEASE BTN_LEFT [init -> usb_drv] dev_info: USB disconnect, device [init -> usb_drv] dev_info: new full-speed USB device [init -> usb_drv] dev_info: D L [init -> usb_drv] dev_info: input: USB HID v1.11 Keyboard [D L] [init -> usb_drv] dev_info: D L [init -> usb_drv] dev_info: input: USB HID v1.11 Mouse [D L] -[init -> test-input] Input event #7 type=PRESS code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=1 KEY_X -[init -> test-input] Input event #8 type=RELEASE code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=0 KEY_X -[init -> test-input] Input event #9 type=PRESS code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=1 BTN_LEFT -[init -> test-input] Input event #10 type=MOTION code=0 rx=-1 ry=0 ax=0 ay=0 key_cnt=1 -[init -> test-input] Input event #11 type=MOTION code=0 rx=0 ry=1 ax=0 ay=0 key_cnt=1 -[init -> test-input] Input event #12 type=RELEASE code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=0 BTN_LEFT +[init -> test-input] Input event #6 PRESS KEY_X 0 +[init -> test-input] Input event #7 RELEASE KEY_X +[init -> test-input] Input event #8 PRESS BTN_LEFT 0 +[init -> test-input] Input event #9 REL_MOTION -1+0 +[init -> test-input] Input event #10 REL_MOTION +0+1 +[init -> test-input] Input event #11 RELEASE BTN_LEFT } diff --git a/repos/dde_linux/src/lib/usb/input/input_component.cc b/repos/dde_linux/src/lib/usb/input/input_component.cc index 13e0d13de..77a672c3b 100644 --- a/repos/dde_linux/src/lib/usb/input/input_component.cc +++ b/repos/dde_linux/src/lib/usb/input/input_component.cc @@ -41,22 +41,33 @@ static Genode::Constructible _input_root; * Input event call-back function */ static void input_callback(enum input_event_type type, - unsigned code, - int absolute_x, int absolute_y, - int relative_x, int relative_y) + unsigned code, int ax, int ay, int rx, int ry) { - Input::Event::Type t = Input::Event::INVALID; - switch (type) { - case EVENT_TYPE_PRESS: t = Input::Event::PRESS; break; - case EVENT_TYPE_RELEASE: t = Input::Event::RELEASE; break; - case EVENT_TYPE_MOTION: t = Input::Event::MOTION; break; - case EVENT_TYPE_WHEEL: t = Input::Event::WHEEL; break; - case EVENT_TYPE_TOUCH: t = Input::Event::TOUCH; break; - } + using namespace Input; - _input_session->submit(Input::Event(t, code, - absolute_x, absolute_y, - relative_x, relative_y)); + auto submit = [&] (Event const &ev) { _input_session->submit(ev); }; + + switch (type) { + case EVENT_TYPE_PRESS: submit(Press{Keycode(code)}); break; + case EVENT_TYPE_RELEASE: submit(Release{Keycode(code)}); break; + case EVENT_TYPE_MOTION: + if (rx == 0 && ry == 0) + submit(Absolute_motion{ax, ay}); + else + submit(Relative_motion{rx, ry}); + break; + case EVENT_TYPE_WHEEL: submit(Wheel{rx, ry}); break; + case EVENT_TYPE_TOUCH: + { + Touch_id const id { (int)code }; + + if (rx == -1 && ry == -1) + submit(Touch_release{id}); + else + submit(Touch{id, (float)ax, (float)ay}); + break; + } + } } diff --git a/repos/demo/include/scout/platform.h b/repos/demo/include/scout/platform.h index aaac7bc3a..d7d4034d8 100644 --- a/repos/demo/include/scout/platform.h +++ b/repos/demo/include/scout/platform.h @@ -95,28 +95,25 @@ class Scout::Platform { if (_input.pending() == false) return; - for (int i = 0, num = _input.flush(); i < num; i++) - { + for (int i = 0, num = _input.flush(); i < num; i++) { Event ev; Input::Event e = _ev_buf[i]; _event_pending = i + 1 < num; - if (e.type() == Input::Event::RELEASE - || e.type() == Input::Event::PRESS) { - _mx = e.ax(); - _my = e.ay(); - ev.assign(e.type() == Input::Event::PRESS ? Event::PRESS : Event::RELEASE, - e.ax(), e.ay(), e.code()); - _handle_event(ev); - } + e.handle_press([&] (Input::Keycode key, Genode::Codepoint) { + ev.assign(Event::PRESS, _mx, _my, key); }); - if (e.type() == Input::Event::MOTION) { - _mx = e.ax(); - _my = e.ay(); - ev.assign(Event::MOTION, e.ax(), e.ay(), e.code()); + e.handle_release([&] (Input::Keycode key) { + ev.assign(Event::RELEASE, _mx, _my, key); }); + + e.handle_absolute_motion([&] (int x, int y) { + _mx = x; _my = y; + ev.assign(Event::MOTION, _mx, _my, 0); + }); + + if (ev.type != Event::UNDEFINED) _handle_event(ev); - } } } diff --git a/repos/demo/src/server/liquid_framebuffer/services.cc b/repos/demo/src/server/liquid_framebuffer/services.cc index 260471bdf..b887b5749 100644 --- a/repos/demo/src/server/liquid_framebuffer/services.cc +++ b/repos/demo/src/server/liquid_framebuffer/services.cc @@ -61,23 +61,16 @@ class Window_content : public Scout::Element Point mouse_position = ev.mouse_position - _element->abs_position(); - int code = 0; + auto motion = [&] (Point p) { return Input::Absolute_motion{p.x(), p.y()}; }; - if (ev.type == Event::PRESS || ev.type == Event::RELEASE) - code = ev.code; + if (ev.type == Event::MOTION) + _input_session.submit(motion(mouse_position)); - Input::Event::Type type; + if (ev.type == Event::PRESS) + _input_session.submit(Input::Press{Input::Keycode(ev.code)}); - type = (ev.type == Event::MOTION) ? Input::Event::MOTION - : (ev.type == Event::PRESS) ? Input::Event::PRESS - : (ev.type == Event::RELEASE) ? Input::Event::RELEASE - : Input::Event::INVALID; - - if (type != Input::Event::INVALID) - _input_session.submit(Input::Event(type, code, mouse_position.x(), - mouse_position.y(), - mouse_position.x() - _old_mouse_position.x(), - mouse_position.y() - _old_mouse_position.y())); + if (ev.type == Event::RELEASE) + _input_session.submit(Input::Release{Input::Keycode(ev.code)}); _old_mouse_position = mouse_position; } diff --git a/repos/demo/src/server/nitlog/main.cc b/repos/demo/src/server/nitlog/main.cc index 68d588592..e609137fa 100644 --- a/repos/demo/src/server/nitlog/main.cc +++ b/repos/demo/src/server/nitlog/main.cc @@ -448,7 +448,9 @@ struct Nitlog::Main Attached_dataspace _ev_ds { _env.rm(), _nitpicker.input()->dataspace() }; - Nitpicker::Point _old_mouse_pos { }; + Nitpicker::Point const _initial_mouse_pos { -1, -1 }; + + Nitpicker::Point _old_mouse_pos = _initial_mouse_pos; unsigned _key_cnt = 0; @@ -463,20 +465,24 @@ struct Nitlog::Main Input::Event const &ev = ev_buf[i]; - if (ev.type() == Input::Event::PRESS) _key_cnt++; - if (ev.type() == Input::Event::RELEASE) _key_cnt--; - - Nitpicker::Point mouse_pos(ev.ax(), ev.ay()); + if (ev.press()) _key_cnt++; + if (ev.release()) _key_cnt--; /* move view */ - if (ev.type() == Input::Event::MOTION && _key_cnt > 0) - _view.move(_view.pos() + mouse_pos - _old_mouse_pos); + ev.handle_absolute_motion([&] (int x, int y) { + + Nitpicker::Point const mouse_pos(x, y); + + if (_key_cnt && _old_mouse_pos != _initial_mouse_pos) + _view.move(_view.pos() + mouse_pos - _old_mouse_pos); + + _old_mouse_pos = mouse_pos; + }); /* find selected view and bring it to front */ - if (ev.type() == Input::Event::PRESS && _key_cnt == 1) + if (ev.press() && _key_cnt == 1) _view.top(); - _old_mouse_pos = mouse_pos; } } diff --git a/repos/gems/src/app/floating_window_layouter/key_sequence_tracker.h b/repos/gems/src/app/floating_window_layouter/key_sequence_tracker.h index 290134890..30c40bf85 100644 --- a/repos/gems/src/app/floating_window_layouter/key_sequence_tracker.h +++ b/repos/gems/src/app/floating_window_layouter/key_sequence_tracker.h @@ -206,24 +206,24 @@ class Floating_window_layouter::Key_sequence_tracker * to preserver the invariant that each key is present only * once. */ - if (ev.type() == Input::Event::PRESS) { - _stack.flush(Stack::Entry(Stack::Entry::PRESS, ev.keycode())); - _stack.flush(Stack::Entry(Stack::Entry::RELEASE, ev.keycode())); - } + ev.handle_press([&] (Input::Keycode key, Codepoint) { + _stack.flush(Stack::Entry(Stack::Entry::PRESS, key)); + _stack.flush(Stack::Entry(Stack::Entry::RELEASE, key)); + }); Xml_node curr_node = _xml_by_path(config); - if (ev.type() == Input::Event::PRESS) { + ev.handle_press([&] (Input::Keycode key, Codepoint) { - Stack::Entry const entry(Stack::Entry::PRESS, ev.keycode()); + Stack::Entry const entry(Stack::Entry::PRESS, key); _execute_action(_matching_sub_node(curr_node, entry), func); _stack.push(entry); - } + }); - if (ev.type() == Input::Event::RELEASE) { + ev.handle_release([&] (Input::Keycode key) { - Stack::Entry const entry(Stack::Entry::RELEASE, ev.keycode()); + Stack::Entry const entry(Stack::Entry::RELEASE, key); Xml_node const next_node = _matching_sub_node(curr_node, entry); @@ -239,10 +239,10 @@ class Floating_window_layouter::Key_sequence_tracker } else { - Stack::Entry entry(Stack::Entry::PRESS, ev.keycode()); + Stack::Entry entry(Stack::Entry::PRESS, key); _stack.flush(entry); } - } + }); } }; diff --git a/repos/gems/src/app/floating_window_layouter/user_state.h b/repos/gems/src/app/floating_window_layouter/user_state.h index 5482f0bac..feaa906c7 100644 --- a/repos/gems/src/app/floating_window_layouter/user_state.h +++ b/repos/gems/src/app/floating_window_layouter/user_state.h @@ -75,13 +75,22 @@ class Floating_window_layouter::User_state Focus_history &_focus_history; + /* + * Return true if key is potentially part of a key sequence + */ + static bool _key(Input::Keycode key) { return key != Input::BTN_LEFT; } + bool _key(Input::Event const &ev) const { - if (ev.type() != Input::Event::PRESS - && ev.type() != Input::Event::RELEASE) - return false; + bool relevant = false; - return ev.keycode() != Input::BTN_LEFT; + ev.handle_press([&] (Input::Keycode key, Codepoint) { + relevant |= _key(key); }); + + ev.handle_release([&] (Input::Keycode key) { + relevant |= _key(key); }); + + return relevant; } inline void _handle_event(Input::Event const &, Xml_node); @@ -214,10 +223,10 @@ class Floating_window_layouter::User_state void Floating_window_layouter::User_state::_handle_event(Input::Event const &e, Xml_node config) { - if (e.type() == Input::Event::MOTION - || e.type() == Input::Event::FOCUS) { + e.handle_absolute_motion([&] (int x, int y) { + _pointer_curr = Point(x, y); }); - _pointer_curr = Point(e.ax(), e.ay()); + if (e.absolute_motion() || e.focus_enter()) { if (_drag_state && _drag_init_done) _operations.drag(_dragged_window_id, _dragged_element, @@ -225,13 +234,11 @@ void Floating_window_layouter::User_state::_handle_event(Input::Event const &e, } /* track number of pressed buttons/keys */ - if (e.type() == Input::Event::PRESS) _key_cnt++; - if (e.type() == Input::Event::RELEASE) _key_cnt--; + if (e.press()) _key_cnt++; + if (e.release()) _key_cnt--; /* handle pointer click */ - if (e.type() == Input::Event::PRESS - && e.keycode() == Input::BTN_LEFT - && _key_cnt == 1) { + if (e.key_press(Input::BTN_LEFT) && _key_cnt == 1) { /* * Initiate drag operation if possible @@ -266,9 +273,7 @@ void Floating_window_layouter::User_state::_handle_event(Input::Event const &e, } /* detect end of drag operation */ - if (e.type() == Input::Event::RELEASE - && _key_cnt == 0 - && _dragged_window_id.valid()) { + if (e.release() && _key_cnt == 0 && _dragged_window_id.valid()) { _drag_state = false; @@ -288,7 +293,7 @@ void Floating_window_layouter::User_state::_handle_event(Input::Event const &e, /* handle key sequences */ if (_key(e)) { - if (e.type() == Input::Event::PRESS && _key_cnt == 1) + if (e.press() && _key_cnt == 1) _key_sequence_tracker.reset(); _key_sequence_tracker.apply(e, config, [&] (Action action) { @@ -320,7 +325,7 @@ void Floating_window_layouter::User_state::_handle_event(Input::Event const &e, } /* update focus history after key/button action is completed */ - if (e.type() == Input::Event::RELEASE && _key_cnt == 0) + if (e.release() && _key_cnt == 0) _focus_history.focus(_focused_window_id); } diff --git a/repos/gems/src/app/launcher/context_dialog.h b/repos/gems/src/app/launcher/context_dialog.h index 3bb651051..19ce8ff24 100644 --- a/repos/gems/src/app/launcher/context_dialog.h +++ b/repos/gems/src/app/launcher/context_dialog.h @@ -169,7 +169,7 @@ class Launcher::Context_dialog : Input_event_handler, Dialog_generator, */ bool handle_input_event(Input::Event const &ev) override { - if (ev.type() == Input::Event::MOTION) { + if (ev.absolute_motion()) { /* * Re-enable the visibility of the menu if we detect motion @@ -182,17 +182,15 @@ class Launcher::Context_dialog : Input_event_handler, Dialog_generator, return true; } - if (ev.type() == Input::Event::LEAVE) { + if (ev.hover_leave()) { visible(false); return true; } - if (ev.type() == Input::Event::PRESS) _key_cnt++; - if (ev.type() == Input::Event::RELEASE) _key_cnt--; + if (ev.press()) _key_cnt++; + if (ev.release()) _key_cnt--; - if (ev.type() == Input::Event::PRESS - && ev.keycode() == Input::BTN_LEFT - && _key_cnt == 1) { + if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) { Label const hovered = _hovered(); @@ -202,8 +200,7 @@ class Launcher::Context_dialog : Input_event_handler, Dialog_generator, dialog_changed(); } - if (ev.type() == Input::Event::RELEASE - && _click_in_progress && _key_cnt == 0) { + if (ev.release() && _click_in_progress && _key_cnt == 0) { Label const hovered = _hovered(); diff --git a/repos/gems/src/app/launcher/main.cc b/repos/gems/src/app/launcher/main.cc index a83978013..25bd18bb8 100644 --- a/repos/gems/src/app/launcher/main.cc +++ b/repos/gems/src/app/launcher/main.cc @@ -137,8 +137,8 @@ void Launcher::Main::_handle_config() void Launcher::Main::_handle_input() { _nitpicker.input()->for_each_event([&] (Input::Event const &e) { - if (e.type() == Input::Event::PRESS) _key_cnt++; - if (e.type() == Input::Event::RELEASE) _key_cnt--; + if (e.press()) _key_cnt++; + if (e.release()) _key_cnt--; /* * The _key_cnt can become 2 only when the global key (as configured @@ -146,11 +146,8 @@ void Launcher::Main::_handle_input() * Hence, the following condition triggers on key combinations with * the global modifier key, whatever the global modifier key is. */ - if (e.type() == Input::Event::PRESS && _key_cnt == 2) { - - if (e.keycode() == Input::KEY_TAB) - _panel_dialog.focus_next(); - } + if (e.key_press(Input::KEY_TAB) && _key_cnt == 2) + _panel_dialog.focus_next(); }); } diff --git a/repos/gems/src/app/launcher/menu_dialog.h b/repos/gems/src/app/launcher/menu_dialog.h index 59a68c249..64290c801 100644 --- a/repos/gems/src/app/launcher/menu_dialog.h +++ b/repos/gems/src/app/launcher/menu_dialog.h @@ -185,12 +185,12 @@ class Launcher::Menu_dialog : Input_event_handler, Dialog_generator, */ bool handle_input_event(Input::Event const &ev) override { - if (ev.type() == Input::Event::LEAVE) { + if (ev.hover_leave()) { _response_handler.handle_menu_leave(); return false; } - if (ev.type() == Input::Event::MOTION) { + if (ev.absolute_motion()) { _response_handler.handle_menu_motion(); @@ -205,15 +205,11 @@ class Launcher::Menu_dialog : Input_event_handler, Dialog_generator, return true; } - if (ev.type() == Input::Event::PRESS) _key_cnt++; - if (ev.type() == Input::Event::RELEASE) _key_cnt--; + if (ev.press()) _key_cnt++; + if (ev.release()) _key_cnt--; - if (ev.type() == Input::Event::PRESS - && ev.keycode() == Input::BTN_LEFT - && _key_cnt == 1) { - - _response_handler.handle_selection(_hovered()); - } + if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) + _response_handler.handle_selection(_hovered()); return false; } diff --git a/repos/gems/src/app/launcher/panel_dialog.h b/repos/gems/src/app/launcher/panel_dialog.h index 8ab3195bf..8628aa443 100644 --- a/repos/gems/src/app/launcher/panel_dialog.h +++ b/repos/gems/src/app/launcher/panel_dialog.h @@ -345,7 +345,7 @@ class Launcher::Panel_dialog : Input_event_handler, Dialog_generator, */ bool handle_input_event(Input::Event const &ev) override { - if (ev.type() == Input::Event::LEAVE) { + if (ev.hover_leave()) { /* * Let menu dialog disappear when the panel is unhovered. One @@ -362,15 +362,13 @@ class Launcher::Panel_dialog : Input_event_handler, Dialog_generator, return true; } - if (ev.type() == Input::Event::MOTION) + if (ev.absolute_motion()) return true; - if (ev.type() == Input::Event::PRESS) _key_cnt++; - if (ev.type() == Input::Event::RELEASE) _key_cnt--; + if (ev.press()) _key_cnt++; + if (ev.release()) _key_cnt--; - if (ev.type() == Input::Event::PRESS - && ev.keycode() == Input::BTN_LEFT - && _key_cnt == 1) { + if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) { _context_dialog.visible(false); @@ -412,9 +410,7 @@ class Launcher::Panel_dialog : Input_event_handler, Dialog_generator, /* * Open context dialog on right click */ - if (ev.type() == Input::Event::PRESS - && ev.keycode() == Input::BTN_RIGHT - && _key_cnt == 1) { + if (ev.key_press(Input::BTN_RIGHT) && _key_cnt == 1) { Element *hovered = _hovered(); @@ -422,8 +418,7 @@ class Launcher::Panel_dialog : Input_event_handler, Dialog_generator, _open_context_dialog(hovered->label); } - if (ev.type() == Input::Event::RELEASE - && _click_in_progress && _key_cnt == 0) { + if (ev.release() && _click_in_progress && _key_cnt == 0) { Element *hovered = _hovered(); diff --git a/repos/gems/src/app/menu_view/main.cc b/repos/gems/src/app/menu_view/main.cc index e4514c97b..928bfb98c 100644 --- a/repos/gems/src/app/menu_view/main.cc +++ b/repos/gems/src/app/menu_view/main.cc @@ -234,9 +234,9 @@ void Menu_view::Main::_handle_config() void Menu_view::Main::_handle_input() { _nitpicker.input()->for_each_event([&] (Input::Event const &ev) { - if (ev.absolute_motion()) { + ev.handle_absolute_motion([&] (int x, int y) { - Point const at = Point(ev.ax(), ev.ay()) - _position; + Point const at = Point(x, y) - _position; Widget::Unique_id const new_hovered = _root_widget.hovered(at); if (_hovered != new_hovered) { @@ -249,14 +249,12 @@ void Menu_view::Main::_handle_input() _hovered = new_hovered; } - } + }); /* * Reset hover model when losing the focus */ - if ((ev.type() == Input::Event::FOCUS && ev.code() == 0) - || (ev.type() == Input::Event::LEAVE)) { - + if (ev.focus_leave() || ev.hover_leave()) { _hovered = Widget::Unique_id(); if (_hover_reporter.enabled()) { diff --git a/repos/gems/src/server/terminal/main.cc b/repos/gems/src/server/terminal/main.cc index 32a1ca7ee..84147764e 100644 --- a/repos/gems/src/server/terminal/main.cc +++ b/repos/gems/src/server/terminal/main.cc @@ -220,11 +220,30 @@ void Terminal::Main::_handle_input() { _input.for_each_event([&] (Input::Event const &event) { - if (event.type() == Input::Event::CHARACTER) { - Input::Event::Utf8 const utf8 = event.utf8(); + event.handle_press([&] (Input::Keycode, Codepoint codepoint) { - char const sequence[] { (char)utf8.b0, (char)utf8.b1, - (char)utf8.b2, (char)utf8.b3, 0 }; + struct Utf8 { char b0, b1, b2, b3, b4; }; + + auto utf8_from_codepoint = [] (unsigned c) { + + /* extract 'n' bits 'at' bit position of value 'c' */ + auto bits = [c] (unsigned at, unsigned n) { + return (c >> at) & ((1 << n) - 1); }; + + return (c < 2<<7) ? Utf8 { char(bits( 0, 7)), 0, 0, 0, 0 } + : (c < 2<<11) ? Utf8 { char(bits( 6, 5) | 0xc0), + char(bits( 0, 6) | 0x80), 0, 0, 0 } + : (c < 2<<16) ? Utf8 { char(bits(12, 4) | 0xe0), + char(bits( 6, 6) | 0x80), + char(bits( 0, 6) | 0x80), 0, 0 } + : (c < 2<<21) ? Utf8 { char(bits(18, 3) | 0xf0), + char(bits(12, 6) | 0x80), + char(bits( 6, 6) | 0x80), + char(bits( 0, 6) | 0x80), 0 } + : Utf8 { }; + }; + + Utf8 const sequence = utf8_from_codepoint(codepoint.value); /* function-key unicodes */ enum { @@ -241,8 +260,6 @@ void Terminal::Main::_handle_input() CODEPOINT_PAGEUP = 0xf72c, CODEPOINT_PAGEDOWN = 0xf72d, }; - Codepoint const codepoint = Utf8_ptr(sequence).codepoint(); - char const *special_sequence = nullptr; switch (codepoint.value) { case CODEPOINT_UP: special_sequence = "\EOA"; break; @@ -272,8 +289,8 @@ void Terminal::Main::_handle_input() if (special_sequence) _read_buffer.add(special_sequence); else - _read_buffer.add(sequence); - } + _read_buffer.add(&sequence.b0); + }); }); } diff --git a/repos/gems/src/server/wm/decorator_nitpicker.h b/repos/gems/src/server/wm/decorator_nitpicker.h index 170a2b73e..5eb48e356 100644 --- a/repos/gems/src/server/wm/decorator_nitpicker.h +++ b/repos/gems/src/server/wm/decorator_nitpicker.h @@ -225,18 +225,18 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object, while (_nitpicker_session.input()->pending()) _nitpicker_session.input()->for_each_event([&] (Input::Event const &ev) { - if (ev.type() == Input::Event::MOTION) { + ev.handle_absolute_motion([&] (int x, int y) { _last_motion = LAST_MOTION_DECORATOR; Reporter::Xml_generator xml(_pointer_reporter, [&] () { - xml.attribute("xpos", ev.ax()); - xml.attribute("ypos", ev.ay()); + xml.attribute("xpos", x); + xml.attribute("ypos", y); }); - } + }); - if (ev.type() == Input::Event::LEAVE) { + if (ev.hover_leave()) { /* * Invalidate pointer as reported to the decorator if the diff --git a/repos/gems/src/server/wm/nitpicker.h b/repos/gems/src/server/wm/nitpicker.h index 9473952a4..8e1aedf40 100644 --- a/repos/gems/src/server/wm/nitpicker.h +++ b/repos/gems/src/server/wm/nitpicker.h @@ -451,6 +451,8 @@ class Wm::Nitpicker::Session_component : public Rpc_object, Area _requested_size; bool _resize_requested = false; bool _has_alpha = false; + Point const _initial_pointer_pos { -1, -1 }; + Point _pointer_pos = _initial_pointer_pos; /* * Command buffer @@ -492,34 +494,14 @@ class Wm::Nitpicker::Session_component : public Rpc_object, /** * Translate input event to the client's coordinate system */ - Input::Event _translate_event(Input::Event const ev, Point const input_origin) + Input::Event _translate_event(Input::Event ev, Point const origin) { - switch (ev.type()) { + ev.handle_absolute_motion([&] (int x, int y) { + Point p = Point(x, y) + origin; + ev = Input::Absolute_motion{p.x(), p.y()}; + }); - case Input::Event::MOTION: - case Input::Event::PRESS: - case Input::Event::RELEASE: - case Input::Event::FOCUS: - case Input::Event::LEAVE: - { - Point abs_pos = Point(ev.ax(), ev.ay()) + input_origin; - return Input::Event(ev.type(), ev.code(), - abs_pos.x(), abs_pos.y(), 0, 0); - } - - case Input::Event::TOUCH: - case Input::Event::CHARACTER: - case Input::Event::WHEEL: - { - Point abs_pos = Point(ev.ax(), ev.ay()) + input_origin; - return Input::Event(ev.type(), ev.code(), - abs_pos.x(), abs_pos.y(), ev.rx(), ev.ry()); - } - - case Input::Event::INVALID: - return ev; - } - return Input::Event(); + return ev; } bool _click_into_unfocused_view(Input::Event const ev) @@ -530,7 +512,7 @@ class Wm::Nitpicker::Session_component : public Rpc_object, * Right now, we report more butten events to the layouter * than the layouter really needs. */ - if (ev.type() == Input::Event::PRESS && ev.keycode() == Input::BTN_LEFT) + if (ev.key_press(Input::BTN_LEFT)) return true; return false; @@ -555,20 +537,24 @@ class Wm::Nitpicker::Session_component : public Rpc_object, Input::Event const ev = events[i]; + /* keep track of pointer position */ + ev.handle_absolute_motion([&] (int x, int y) { + _pointer_pos = Point(x, y); }); + /* propagate layout-affecting events to the layouter */ if (_click_into_unfocused_view(ev)) - _click_handler.handle_click(Point(ev.ax(), ev.ay())); + _click_handler.handle_click(_pointer_pos); /* * Reset pointer model for the decorator once the pointer * enters the application area of a window. */ - if (ev.type() == Input::Event::MOTION && _first_motion) { - _click_handler.handle_enter(Point(ev.ax(), ev.ay())); + if (ev.absolute_motion() && _first_motion) { + _click_handler.handle_enter(_pointer_pos); _first_motion = false; } - if (ev.type() == Input::Event::LEAVE) + if (ev.hover_leave()) _first_motion = true; /* submit event to the client */ @@ -1016,12 +1002,6 @@ class Wm::Nitpicker::Root : public Genode::Rpc_object @@ -222,6 +223,7 @@ proc drivers_start_nodes { feature_arg } { append start_nodes " " append start_nodes { + @@ -310,6 +312,7 @@ proc drivers_boot_modules { feature_arg } { lappend_if [use_gpio_drv feature] boot_modules [gpio_drv] lappend_if [use_input_filter feature] boot_modules input_filter lappend_if [use_input_filter feature] boot_modules [language_chargen].chargen + lappend_if [use_input_filter feature] boot_modules special.chargen lappend_if [use_nic_drv feature] boot_modules [nic_drv_binary] lappend_if [use_ps2_drv feature] boot_modules ps2_drv lappend_if [use_timer feature] boot_modules timer diff --git a/repos/libports/src/app/pdf_view/main.cc b/repos/libports/src/app/pdf_view/main.cc index 020be5174..2b5258cdc 100644 --- a/repos/libports/src/app/pdf_view/main.cc +++ b/repos/libports/src/app/pdf_view/main.cc @@ -377,12 +377,10 @@ struct Main void _handle_input() { _input.for_each_event([&] (Input::Event const &ev) { - - if (ev.type() == Input::Event::PRESS) { - - int const ascii = keycode_to_ascii(ev.code()); + ev.handle_press([&] (Input::Keycode key, Genode::Codepoint) { + int const ascii = keycode_to_ascii(key); if (ascii) { _pdf_view.handle_key(ascii); } - } + }); }); } diff --git a/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp b/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp index 8e652d8a6..5e158d44a 100644 --- a/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp +++ b/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp @@ -24,15 +24,15 @@ void Control_bar::_rewind() { /* mouse click at horizontal position 0 */ - _input.submit(Input::Event(Input::Event::PRESS, Input::BTN_LEFT, 0, 0, 0, 0)); - _input.submit(Input::Event(Input::Event::RELEASE, Input::BTN_LEFT, 0, 0, 0, 0)); + _input.submit(Input::Press {Input::BTN_LEFT}); + _input.submit(Input::Release{Input::BTN_LEFT}); } void Control_bar::_pause_resume() { - _input.submit(Input::Event(Input::Event::PRESS, Input::KEY_SPACE, 0, 0, 0, 0)); - _input.submit(Input::Event(Input::Event::RELEASE, Input::KEY_SPACE, 0, 0, 0, 0)); + _input.submit(Input::Press {Input::KEY_SPACE}); + _input.submit(Input::Release{Input::KEY_SPACE}); _playing = !_playing; if (_playing) diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp index 88794aba4..e0e63f450 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp @@ -53,130 +53,133 @@ void QNitpickerPlatformWindow::_process_touch_events(QList const & QList touch_points; for (QList::const_iterator i = events.begin(); i != events.end(); ++i) { - /* - * Coordinates must be normalized to positions of the platform window. - * We lack information about the value ranges (min and max) of touch - * coordinates to normalize ourselves. - */ - QPointF const pos((qreal)i->ax(), (qreal)i->ay() ); + i->handle_touch([&] (Input::Touch_id id, int x, int y) { - QWindowSystemInterface::TouchPoint &otp = _touch_points[i->code()]; - QWindowSystemInterface::TouchPoint tp; + if (id.value >= _touch_points.size()) { + Genode::warning("drop touch input, out of bounds"); + return; + } - tp.id = i->code(); - tp.area = QRectF(QPointF(0, 0), QSize(1, 1)); + QWindowSystemInterface::TouchPoint &otp = _touch_points[id.value]; + QWindowSystemInterface::TouchPoint tp; - /* report 1x1 rectangular area centered at screen coordinates */ - tp.area.moveCenter(QPointF(i->ax(), i->ay())); + tp.id = id.value; + tp.area = QRectF(QPointF(0, 0), QSize(1, 1)); + + /* report 1x1 rectangular area centered at screen coordinates */ + tp.area.moveCenter(QPointF(x, y)); - if (i->rx() == -1 && i->ry() == -1) { - tp.state = Qt::TouchPointReleased; - tp.pressure = 0; - } else { tp.state = otp.state == Qt::TouchPointReleased ? Qt::TouchPointPressed : Qt::TouchPointMoved; tp.pressure = 1; - } - otp = tp; - touch_points.push_back(tp); + otp = tp; + touch_points.push_back(tp); + }); + + i->handle_touch_release([&] (Input::Touch_id id) { + + if (id.value >= _touch_points.size()) { + Genode::warning("drop touch input, out of bounds"); + return; + } + + QWindowSystemInterface::TouchPoint &otp = _touch_points[id.value]; + QWindowSystemInterface::TouchPoint tp; + + tp.id = id.value; + tp.area = QRectF(QPointF(0, 0), QSize(1, 1)); + tp.state = Qt::TouchPointReleased; + tp.pressure = 0; + + otp = tp; + touch_points.push_back(tp); + }); } QWindowSystemInterface::handleTouchEvent(0, _touch_device, touch_points); } -void QNitpickerPlatformWindow::_process_mouse_event(Input::Event const &ev) + +static Qt::Key translate_keycode(Input::Keycode key) { - QPoint global_position(ev.ax(), ev.ay()); - QPoint local_position(global_position.x() - geometry().x(), - global_position.y() - geometry().y()); - - switch (ev.type()) { - - case Input::Event::PRESS: - - /* make this window the focused window */ - requestActivateWindow(); - - switch (ev.code()) { - case Input::BTN_LEFT: - _mouse_button_state |= Qt::LeftButton; - break; - case Input::BTN_RIGHT: - _mouse_button_state |= Qt::RightButton; - break; - case Input::BTN_MIDDLE: - _mouse_button_state |= Qt::MidButton; - break; - case Input::BTN_SIDE: - _mouse_button_state |= Qt::XButton1; - break; - case Input::BTN_EXTRA: - _mouse_button_state |= Qt::XButton2; - break; - } - break; - - case Input::Event::RELEASE: - - switch (ev.code()) { - case Input::BTN_LEFT: - _mouse_button_state &= ~Qt::LeftButton; - break; - case Input::BTN_RIGHT: - _mouse_button_state &= ~Qt::RightButton; - break; - case Input::BTN_MIDDLE: - _mouse_button_state &= ~Qt::MidButton; - break; - case Input::BTN_SIDE: - _mouse_button_state &= ~Qt::XButton1; - break; - case Input::BTN_EXTRA: - _mouse_button_state &= ~Qt::XButton2; - break; - } - break; - - case Input::Event::WHEEL: - - QWindowSystemInterface::handleWheelEvent(window(), - local_position, - local_position, - ev.ry() * 120, - Qt::Vertical); - return; - - default: - break; - } - - QWindowSystemInterface::handleMouseEvent(window(), - local_position, - global_position, - _mouse_button_state); -} - - -void QNitpickerPlatformWindow::_process_key_event(Input::Event const &ev) -{ - const bool pressed = (ev.type() == Input::Event::PRESS); - const int keycode = ev.code(); - - if (pressed) { - _last_keycode = keycode; - _key_repeat_timer->start(KEY_REPEAT_DELAY_MS); - } else - _key_repeat_timer->stop(); - - _keyboard_handler.processKeycode(keycode, pressed, false); -} - - -void QNitpickerPlatformWindow::_key_repeat() -{ - _key_repeat_timer->start(KEY_REPEAT_RATE_MS); - _keyboard_handler.processKeycode(_last_keycode, true, true); + switch (key) { + case Input::KEY_ENTER: return Qt::Key_Return; + case Input::KEY_ESC: return Qt::Key_Escape; + case Input::KEY_TAB: return Qt::Key_Tab; + case Input::KEY_BACKSPACE: return Qt::Key_Backspace; + case Input::KEY_INSERT: return Qt::Key_Insert; + case Input::KEY_DELETE: return Qt::Key_Delete; + case Input::KEY_PRINT: return Qt::Key_Print; + case Input::KEY_CLEAR: return Qt::Key_Clear; + case Input::KEY_HOME: return Qt::Key_Home; + case Input::KEY_END: return Qt::Key_End; + case Input::KEY_LEFT: return Qt::Key_Left; + case Input::KEY_UP: return Qt::Key_Up; + case Input::KEY_RIGHT: return Qt::Key_Right; + case Input::KEY_DOWN: return Qt::Key_Down; + case Input::KEY_PAGEUP: return Qt::Key_PageUp; + case Input::KEY_PAGEDOWN: return Qt::Key_PageDown; + case Input::KEY_LEFTSHIFT: return Qt::Key_Shift; + case Input::KEY_LEFTCTRL: return Qt::Key_Control; + case Input::KEY_LEFTMETA: return Qt::Key_Meta; + case Input::KEY_LEFTALT: return Qt::Key_Alt; + case Input::KEY_RIGHTALT: return Qt::Key_AltGr; + case Input::KEY_CAPSLOCK: return Qt::Key_CapsLock; + case Input::KEY_F1: return Qt::Key_F1; + case Input::KEY_F2: return Qt::Key_F2; + case Input::KEY_F3: return Qt::Key_F3; + case Input::KEY_F4: return Qt::Key_F4; + case Input::KEY_F5: return Qt::Key_F5; + case Input::KEY_F6: return Qt::Key_F6; + case Input::KEY_F7: return Qt::Key_F7; + case Input::KEY_F8: return Qt::Key_F8; + case Input::KEY_F9: return Qt::Key_F9; + case Input::KEY_F10: return Qt::Key_F10; + case Input::KEY_F11: return Qt::Key_F11; + case Input::KEY_F12: return Qt::Key_F12; + case Input::KEY_SPACE: return Qt::Key_Space; + case Input::KEY_0: return Qt::Key_0; + case Input::KEY_1: return Qt::Key_1; + case Input::KEY_2: return Qt::Key_2; + case Input::KEY_3: return Qt::Key_3; + case Input::KEY_4: return Qt::Key_4; + case Input::KEY_5: return Qt::Key_5; + case Input::KEY_6: return Qt::Key_6; + case Input::KEY_7: return Qt::Key_7; + case Input::KEY_8: return Qt::Key_8; + case Input::KEY_9: return Qt::Key_9; + case Input::KEY_A: return Qt::Key_A; + case Input::KEY_B: return Qt::Key_B; + case Input::KEY_C: return Qt::Key_C; + case Input::KEY_D: return Qt::Key_D; + case Input::KEY_E: return Qt::Key_E; + case Input::KEY_F: return Qt::Key_F; + case Input::KEY_G: return Qt::Key_G; + case Input::KEY_H: return Qt::Key_H; + case Input::KEY_I: return Qt::Key_I; + case Input::KEY_J: return Qt::Key_J; + case Input::KEY_K: return Qt::Key_K; + case Input::KEY_L: return Qt::Key_L; + case Input::KEY_M: return Qt::Key_M; + case Input::KEY_N: return Qt::Key_N; + case Input::KEY_O: return Qt::Key_O; + case Input::KEY_P: return Qt::Key_P; + case Input::KEY_Q: return Qt::Key_Q; + case Input::KEY_R: return Qt::Key_R; + case Input::KEY_S: return Qt::Key_S; + case Input::KEY_T: return Qt::Key_T; + case Input::KEY_U: return Qt::Key_U; + case Input::KEY_V: return Qt::Key_V; + case Input::KEY_W: return Qt::Key_W; + case Input::KEY_X: return Qt::Key_X; + case Input::KEY_Y: return Qt::Key_Y; + case Input::KEY_Z: return Qt::Key_Z; + case Input::KEY_BACK: return Qt::Key_Back; + case Input::KEY_FORWARD: return Qt::Key_Forward; + default: break; + }; + return Qt::Key_unknown; } @@ -186,55 +189,106 @@ void QNitpickerPlatformWindow::_handle_input(unsigned int) _input_session.for_each_event([&] (Input::Event const &event) { - bool const is_key_event = event.type() == Input::Event::PRESS || - event.type() == Input::Event::RELEASE; + QPoint const orig_mouse_position = _mouse_position; + Qt::MouseButtons const orig_mouse_button_state = _mouse_button_state; - bool const is_mouse_button_event = - is_key_event && (event.code() == Input::BTN_LEFT || - event.code() == Input::BTN_MIDDLE || - event.code() == Input::BTN_RIGHT); + event.handle_absolute_motion([&] (int x, int y) { + _mouse_position = QPoint(x, y); }); - if (event.type() == Input::Event::MOTION || - event.type() == Input::Event::WHEEL || - is_mouse_button_event) { + event.handle_press([&] (Input::Keycode key, Genode::Codepoint codepoint) { - _process_mouse_event(event); - - } else if (event.type() == Input::Event::TOUCH) { - - touch_events.push_back(event); - - } else if (event.type() == Input::Event::CHARACTER) { - - Input::Event::Utf8 const utf8 = event.utf8(); - - if ((utf8.b0 >= 1) && (utf8.b0 <= 26)) { - - /* Ctrl-A .. Ctrl-Z */ - - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, - Qt::Key_A + (utf8.b0 - 1), - Qt::ControlModifier); - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, - Qt::Key_A + (utf8.b0 - 1), - Qt::ControlModifier); - } else { - - char const utf8_string[] = { (char)utf8.b0, (char)utf8.b1, - (char)utf8.b2, (char)utf8.b3, - '\0' }; - - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, 0, 0, - QString::fromUtf8(utf8_string)); - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, 0, 0, - QString::fromUtf8(utf8_string)); + switch (key) { + case Input::BTN_LEFT: _mouse_button_state |= Qt::LeftButton; break; + case Input::BTN_RIGHT: _mouse_button_state |= Qt::RightButton; break; + case Input::BTN_MIDDLE: _mouse_button_state |= Qt::MidButton; break; + case Input::BTN_SIDE: _mouse_button_state |= Qt::XButton1; break; + case Input::BTN_EXTRA: _mouse_button_state |= Qt::XButton2; break; + default: break; } - } else if (is_key_event && (event.code() < 128)) { + /* on mouse click, make this window the focused window */ + if (_mouse_button_state != orig_mouse_button_state) + requestActivateWindow(); - _process_key_event(event); + QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, + translate_keycode(key), 0, + QString() + QChar(codepoint.value)); + }); + /* handle repeat of special keys */ + event.handle_repeat([&] (Genode::Codepoint codepoint) { + + /* function-key unicodes */ + enum { + CODEPOINT_UP = 0xf700, CODEPOINT_DOWN = 0xf701, + CODEPOINT_LEFT = 0xf702, CODEPOINT_RIGHT = 0xf703, + CODEPOINT_HOME = 0xf729, CODEPOINT_INSERT = 0xf727, + CODEPOINT_DELETE = 0xf728, CODEPOINT_END = 0xf72b, + CODEPOINT_PAGEUP = 0xf72c, CODEPOINT_PAGEDOWN = 0xf72d, + CODEPOINT_BACKSPACE = 8, CODEPOINT_LINEFEED = 10, + }; + + Qt::Key repeated_key = Qt::Key_unknown; + switch (codepoint.value) { + case CODEPOINT_UP: repeated_key = Qt::Key_Up; break; + case CODEPOINT_DOWN: repeated_key = Qt::Key_Down; break; + case CODEPOINT_LEFT: repeated_key = Qt::Key_Left; break; + case CODEPOINT_RIGHT: repeated_key = Qt::Key_Right; break; + case CODEPOINT_HOME: repeated_key = Qt::Key_Home; break; + case CODEPOINT_INSERT: repeated_key = Qt::Key_Insert; break; + case CODEPOINT_DELETE: repeated_key = Qt::Key_Delete; break; + case CODEPOINT_END: repeated_key = Qt::Key_End; break; + case CODEPOINT_PAGEUP: repeated_key = Qt::Key_PageUp; break; + case CODEPOINT_PAGEDOWN: repeated_key = Qt::Key_PageDown; break; + case CODEPOINT_BACKSPACE: repeated_key = Qt::Key_Backspace; break; + case CODEPOINT_LINEFEED: repeated_key = Qt::Key_Return; break; + default: return /* from lambda */; + }; + + /* + * A key repeat is triggered while a key is already pressed. We + * respond to it by simulating a tempoary release of the key. + */ + QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, + repeated_key, 0, QString()); + QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, + repeated_key, 0, QString()); + }); + + event.handle_release([&] (Input::Keycode key) { + + switch (key) { + case Input::BTN_LEFT: _mouse_button_state &= ~Qt::LeftButton; break; + case Input::BTN_RIGHT: _mouse_button_state &= ~Qt::RightButton; break; + case Input::BTN_MIDDLE: _mouse_button_state &= ~Qt::MidButton; break; + case Input::BTN_SIDE: _mouse_button_state &= ~Qt::XButton1; break; + case Input::BTN_EXTRA: _mouse_button_state &= ~Qt::XButton2; break; + default: break; + } + + QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, + translate_keycode(key), + 0, QString()); + }); + + event.handle_wheel([&] (int x, int y) { + QWindowSystemInterface::handleWheelEvent(window(), + _local_position(), + _local_position(), + y * 120, + Qt::Vertical); }); + + if (_mouse_button_state != orig_mouse_button_state + || _mouse_position != orig_mouse_position) { + + QWindowSystemInterface::handleMouseEvent(window(), + _local_position(), + _mouse_position, + _mouse_button_state); } + + if (event.touch() || event.touch_release()) + touch_events.push_back(event); }); /* process all gathered touch events */ @@ -338,12 +392,9 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(Genode::Env &env, QWindow *wi _view_handle(_create_view()), _input_session(env.rm(), _nitpicker_session.input_session()), _ev_buf(env.rm(), _input_session.dataspace()), - _keyboard_handler("", _evdevkeyboard_fd, false, false, ""), _resize_handle(!window->flags().testFlag(Qt::Popup)), _decoration(!window->flags().testFlag(Qt::Popup)), _egl_surface(EGL_NO_SURFACE), - _key_repeat_timer(this), - _last_keycode(0), _input_signal_dispatcher(_signal_receiver, *this, &QNitpickerPlatformWindow::_input), _mode_changed_signal_dispatcher(_signal_receiver, *this, @@ -375,9 +426,6 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(Genode::Env &env, QWindow *wi connect(this, SIGNAL(_mode_changed(unsigned int)), this, SLOT(_handle_mode_changed(unsigned int)), Qt::QueuedConnection); - - connect(_key_repeat_timer, SIGNAL(timeout()), - this, SLOT(_key_repeat())); } QWindow *QNitpickerPlatformWindow::window() const diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h index 1537cb7c7..768cf36f4 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h @@ -39,11 +39,6 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow private: - enum { - KEY_REPEAT_DELAY_MS = 500, /* 500 ms delay before first repetition */ - KEY_REPEAT_RATE_MS = 50 /* 50 ms delay between repetitions */ - }; - Genode::Env &_env; Nitpicker::Connection _nitpicker_session; Framebuffer::Session_client _framebuffer_session; @@ -55,15 +50,18 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow Nitpicker::Session::View_handle _view_handle; Input::Session_client _input_session; Genode::Attached_dataspace _ev_buf; + QPoint _mouse_position; Qt::MouseButtons _mouse_button_state; - QFdContainer _evdevkeyboard_fd { -1 }; - QEvdevKeyboardHandler _keyboard_handler; QByteArray _title; bool _resize_handle; bool _decoration; EGLSurface _egl_surface; - QMember _key_repeat_timer; - int _last_keycode; + + QPoint _local_position() const + { + return QPoint(_mouse_position.x() - geometry().x(), + _mouse_position.y() - geometry().y()); + } Genode::Signal_dispatcher _input_signal_dispatcher; Genode::Signal_dispatcher _mode_changed_signal_dispatcher; @@ -72,8 +70,6 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow QTouchDevice *_touch_device; QTouchDevice * _init_touch_device(); - void _process_mouse_event(Input::Event const &ev); - void _process_key_event(Input::Event const &ev); void _process_touch_events(QList const &events); Nitpicker::Session::View_handle _create_view(); @@ -83,7 +79,6 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow void _handle_input(unsigned int); void _handle_mode_changed(unsigned int); - void _key_repeat(); Q_SIGNALS: diff --git a/repos/libports/src/lib/sdl/video/SDL_genode_fb_events.cc b/repos/libports/src/lib/sdl/video/SDL_genode_fb_events.cc index bbe8d58a0..e082cc256 100644 --- a/repos/libports/src/lib/sdl/video/SDL_genode_fb_events.cc +++ b/repos/libports/src/lib/sdl/video/SDL_genode_fb_events.cc @@ -77,13 +77,13 @@ extern "C" { static int buttonmap[KEYNUM_MAX]; - inline SDL_keysym *Genode_Fb_TranslateKey(int keycode, SDL_keysym *k) + inline SDL_keysym Genode_Fb_TranslateKey(Input::Keycode keycode, + Genode::Codepoint codepoint) { - k->scancode = keycode; - k->sym = keymap[keycode]; - k->mod = SDL_GetModState(); - k->unicode = keymap[keycode]; - return k; + return SDL_keysym { .scancode = (uint8_t)keycode, + .sym = keymap[keycode], + .mod = SDL_GetModState(), + .unicode = (uint16_t)codepoint.value }; } @@ -101,43 +101,39 @@ extern "C" { return; input->for_each_event([&] (Input::Event const &curr) { - SDL_keysym ksym; - switch(curr.type()) - { - case Input::Event::MOTION: - if (curr.absolute_motion()) - SDL_PrivateMouseMotion(0, 0, curr.ax(), curr.ay()); - else - SDL_PrivateMouseMotion(0, 1, curr.rx(), curr.ry()); - break; - case Input::Event::PRESS: - if(curr.code() >= Input::BTN_MISC && - curr.code() <= Input::BTN_GEAR_UP) - SDL_PrivateMouseButton(SDL_PRESSED, - buttonmap[curr.code()], - 0, 0); - else - SDL_PrivateKeyboard(SDL_PRESSED, - Genode_Fb_TranslateKey(curr.code(), - &ksym)); - break; - case Input::Event::RELEASE: - if(curr.code() >= Input::BTN_MISC && - curr.code() <= Input::BTN_GEAR_UP) - SDL_PrivateMouseButton(SDL_RELEASED, - buttonmap[curr.code()], - 0, 0); - else - SDL_PrivateKeyboard(SDL_RELEASED, - Genode_Fb_TranslateKey(curr.code(), - &ksym)); - break; - case Input::Event::WHEEL: - Genode::warning("mouse wheel, not implemented yet"); - break; - default: - break; - } + + curr.handle_absolute_motion([&] (int x, int y) { + SDL_PrivateMouseMotion(0, 0, x, y); }); + + curr.handle_relative_motion([&] (int x, int y) { + SDL_PrivateMouseMotion(0, 1, x, y); }); + + /* return true if keycode refers to a button */ + auto mouse_button = [] (Input::Keycode key) { + return key >= Input::BTN_MISC && key <= Input::BTN_GEAR_UP; }; + + curr.handle_press([&] (Input::Keycode key, Genode::Codepoint codepoint) { + + if (mouse_button(key)) + SDL_PrivateMouseButton(SDL_PRESSED, buttonmap[key], 0, 0); + + else { + SDL_keysym ksym = Genode_Fb_TranslateKey(key, codepoint); + SDL_PrivateKeyboard(SDL_PRESSED, &ksym); + } + }); + + curr.handle_release([&] (Input::Keycode key) { + + if (mouse_button(key)) + SDL_PrivateMouseButton(SDL_RELEASED, buttonmap[key], 0, 0); + + else { + Genode::Codepoint const invalid { Genode::Codepoint::INVALID }; + SDL_keysym ksym = Genode_Fb_TranslateKey(key, invalid); + SDL_PrivateKeyboard(SDL_RELEASED, &ksym); + } + }); }); } diff --git a/repos/libports/src/server/acpi_input/main.cc b/repos/libports/src/server/acpi_input/main.cc index 3a5522dc6..e9aeedcb2 100644 --- a/repos/libports/src/server/acpi_input/main.cc +++ b/repos/libports/src/server/acpi_input/main.cc @@ -298,12 +298,11 @@ struct Transform::Main { if (key->type() == Keys::Type::PRESS_RELEASE || key->type() == Keys::Type::PRESS) - _session.submit(Input::Event(Input::Event::PRESS, key->key_code(), - 0, 0, 0, 0)); + _session.submit(Input::Press{key->key_code()}); + if (key->type() == Keys::Type::PRESS_RELEASE || key->type() == Keys::Type::RELEASE) - _session.submit(Input::Event(Input::Event::RELEASE, - key->key_code(), 0, 0, 0, 0)); + _session.submit(Input::Release{key->key_code()}); } void check_acpi_fixed() diff --git a/repos/os/include/input/event.h b/repos/os/include/input/event.h index e27876e13..fb9d355f7 100644 --- a/repos/os/include/input/event.h +++ b/repos/os/include/input/event.h @@ -14,127 +14,198 @@ #ifndef _INCLUDE__INPUT__EVENT_H_ #define _INCLUDE__INPUT__EVENT_H_ +#include #include +#include +#include -namespace Input { class Event; } +namespace Input { + + typedef Genode::Codepoint Codepoint; + + struct Touch_id { int value; }; + + /* + * Event attributes + */ + struct Press { Keycode key; }; + struct Press_char { Keycode key; Codepoint codepoint; }; + struct Release { Keycode key; }; + struct Wheel { int x, y; }; + struct Focus_enter { }; + struct Focus_leave { }; + struct Hover_leave { }; + struct Absolute_motion { int x, y; }; + struct Relative_motion { int x, y; }; + struct Touch { Touch_id id; float x, y; }; + struct Touch_release { Touch_id id; }; + + class Event; +} class Input::Event { - public: - - enum Type { INVALID, MOTION, PRESS, RELEASE, WHEEL, FOCUS, LEAVE, TOUCH, - CHARACTER }; - private: + enum Type { INVALID, PRESS, RELEASE, REL_MOTION, ABS_MOTION, WHEEL, + FOCUS_ENTER, FOCUS_LEAVE, HOVER_LEAVE, TOUCH, TOUCH_RELEASE }; + Type _type = INVALID; - /* - * For PRESS and RELEASE events, '_code' contains the key code. - * For FOCUS events, '_code' is set to 1 (focus) or 0 (unfocus). - */ - int _code = 0; + struct Attr + { + union { + Press_char press; + Release release; + Wheel wheel; + Absolute_motion abs_motion; + Relative_motion rel_motion; + Touch touch; + Touch_release touch_release; + }; + } _attr { }; - /* - * Absolute pointer position coordinates - */ - int _ax = 0, _ay = 0; + static bool _valid(Keycode key) { return key > KEY_RESERVED && key < KEY_MAX; } - /* - * Relative pointer motion vector + /** + * Return point representation of attribute 'a' */ - int _rx = 0, _ry = 0; + template + static Genode::Point _xy(T const &a) { return Genode::Point(a.x, a.y); } public: - /** - * UTF8-encoded symbolic character - */ - struct Utf8 - { - typedef unsigned char byte; - - byte b0, b1, b2, b3; - - Utf8(byte b0, byte b1 = 0, byte b2 = 0, byte b3 = 0) - : b0(b0), b1(b1), b2(b2), b3(b3) { } - }; - /** * Default constructor creates an invalid event + * + * This constructor can be used for creating an array of events. */ Event() { } - /** - * Constructor creates a low-level event - */ - Event(Type type, int code, int ax, int ay, int rx, int ry): - _type(type), _code(code), - _ax(ax), _ay(ay), _rx(rx), _ry(ry) { } - - /** - * Constructor creates a symbolic character event - */ - Event(Utf8 const &utf8) - : - _type(CHARACTER), - _code(((unsigned)utf8.b3 << 24) | ((unsigned)utf8.b2 << 16) | - ((unsigned)utf8.b1 << 8) | ((unsigned)utf8.b0 << 0)) - { } - - /** - * Return event type - */ - Type type() const - { - /* prevent obnoxious events from being processed by clients */ - if ((_type == PRESS || _type == RELEASE) - && (_code <= KEY_RESERVED || _code >= KEY_UNKNOWN)) - return INVALID; - - return _type; - } - - /** - * Accessors - */ - int code() const { return _code; } - int ax() const { return _ax; } - int ay() const { return _ay; } - int rx() const { return _rx; } - int ry() const { return _ry; } - - /** - * Return symbolic character encoded as UTF8 byte sequence - * - * This method must only be called if type is CHARACTER. - */ - Utf8 utf8() const { return Utf8(_code, _code >> 8, _code >> 16, _code >> 24); } - - /** - * Return key code for press/release events - */ - Keycode keycode() const - { - return _type == PRESS || _type == RELEASE ? (Keycode)_code : KEY_UNKNOWN; - } - - bool absolute_motion() const { return _type == MOTION && !_rx && !_ry; } - bool relative_motion() const { return _type == MOTION && (_rx || _ry); } - bool touch_release() const { return _type == TOUCH && (_rx == -1) && (_ry == -1); } - /* - * \deprecated use methods without the 'is_' prefix instead + * Constructors for creating input events of various types + * + * These constructors can be used implicitly for the given attribute + * types for assignments or for passing an event as return value. */ - bool is_absolute_motion() const { return absolute_motion(); } - bool is_relative_motion() const { return relative_motion(); } - bool is_touch_release() const { return touch_release(); } + Event(Press_char arg) : _type(PRESS) { _attr.press = arg; } + Event(Press arg) : Event(Press_char{arg.key, Codepoint{INVALID}}) { } + Event(Release arg) : _type(RELEASE) { _attr.release = arg; } + Event(Relative_motion arg) : _type(REL_MOTION) { _attr.rel_motion = arg; } + Event(Absolute_motion arg) : _type(ABS_MOTION) { _attr.abs_motion = arg; } + Event(Wheel arg) : _type(WHEEL) { _attr.wheel = arg; } + Event(Focus_enter) : _type(FOCUS_ENTER) { } + Event(Focus_leave) : _type(FOCUS_LEAVE) { } + Event(Hover_leave) : _type(HOVER_LEAVE) { } + Event(Touch arg) : _type(TOUCH) { _attr.touch = arg; } + Event(Touch_release arg) : _type(TOUCH_RELEASE) { _attr.touch_release = arg; } - static Event create_touch_event(int ax, int ay, int id, bool last = false) + + /************************************ + ** Methods for handling the event ** + ************************************/ + + bool valid() const { return _type != INVALID; } + bool press() const { return _type == PRESS; } + bool release() const { return _type == RELEASE; } + bool absolute_motion() const { return _type == ABS_MOTION; } + bool relative_motion() const { return _type == REL_MOTION; } + bool wheel() const { return _type == WHEEL; } + bool focus_enter() const { return _type == FOCUS_ENTER; } + bool focus_leave() const { return _type == FOCUS_LEAVE; } + bool hover_leave() const { return _type == HOVER_LEAVE; } + bool touch() const { return _type == TOUCH; } + bool touch_release() const { return _type == TOUCH_RELEASE; } + + bool key_press(Keycode key) const { - return Event(Type::TOUCH, id, ax, ay, last ? -1 : 0, last ? -1 : 0); + return press() && _attr.press.key == key; } + + bool key_release(Keycode key) const + { + return release() && _attr.release.key == key; + } + + template + void handle_press(FN const &fn) const + { + if (press() && _valid(_attr.press.key)) + fn(_attr.press.key, _attr.press.codepoint); + } + + template + void handle_repeat(FN const &fn) const + { + if (key_press(KEY_UNKNOWN) && _attr.press.codepoint.value) + fn(_attr.press.codepoint); + } + + template + void handle_release(FN const &fn) const + { + if (release() && _valid(_attr.release.key)) + fn(_attr.release.key); + } + + template + void handle_relative_motion(FN const &fn) const + { + if (relative_motion()) + fn(_attr.rel_motion.x, _attr.rel_motion.y); + } + + template + void handle_absolute_motion(FN const &fn) const + { + if (absolute_motion()) + fn(_attr.abs_motion.x, _attr.abs_motion.y); + } + + template + void handle_wheel(FN const &fn) const + { + if (wheel()) + fn(_attr.wheel.x, _attr.wheel.y); + } + + template + void handle_touch(FN const &fn) const + { + if (touch()) + fn(_attr.touch.id, _attr.touch.x, _attr.touch.y); + } + + template + void handle_touch_release(FN const &fn) const + { + if (touch_release()) + fn(_attr.touch_release.id); + } + + inline void print(Genode::Output &out) const; }; + +void Input::Event::print(Genode::Output &out) const +{ + using Genode::print; + switch (_type) { + case INVALID: print(out, "INVALID"); break; + case PRESS: print(out, "PRESS ", key_name(_attr.press.key), + " ", _attr.press.codepoint.value); break; + case RELEASE: print(out, "RELEASE ", key_name(_attr.release.key)); break; + case REL_MOTION: print(out, "REL_MOTION ", _xy(_attr.rel_motion)); break; + case ABS_MOTION: print(out, "ABS_MOTION ", _xy(_attr.abs_motion)); break; + case WHEEL: print(out, "WHEEL ", _xy(_attr.wheel)); break; + case FOCUS_ENTER: print(out, "FOCUS_ENTER"); break; + case FOCUS_LEAVE: print(out, "FOCUS_LEAVE"); break; + case HOVER_LEAVE: print(out, "HOVER_LEAVE"); break; + case TOUCH_RELEASE: print(out, "TOUCH_RELEASE ", _attr.touch.id.value); break; + case TOUCH: print(out, "TOUCH ", _attr.touch.id.value, " ", + _xy(_attr.touch)); break; + }; +} + #endif /* _INCLUDE__INPUT__EVENT_H_ */ diff --git a/repos/os/run/input_filter.run b/repos/os/run/input_filter.run index 8d25aa7f4..173177f91 100644 --- a/repos/os/run/input_filter.run +++ b/repos/os/run/input_filter.run @@ -184,17 +184,14 @@ append config { - - + - - + - - + } @@ -219,13 +216,12 @@ append_if [test_char_repeat] config { - - - - - - - + + + + + + } @@ -257,15 +253,15 @@ append config { - + - + - + @@ -418,7 +414,7 @@ append config { - + @@ -428,7 +424,7 @@ append config { - + diff --git a/repos/os/src/app/global_keys_handler/main.cc b/repos/os/src/app/global_keys_handler/main.cc index 099340ef8..3373c57bf 100644 --- a/repos/os/src/app/global_keys_handler/main.cc +++ b/repos/os/src/app/global_keys_handler/main.cc @@ -292,19 +292,15 @@ void Global_keys_handler::Main::_apply_input_events(unsigned num_ev, Input::Event const &ev = events[i]; - if (ev.type() != Input::Event::PRESS - && ev.type() != Input::Event::RELEASE) + if (!ev.press() && !ev.release()) continue; - if (ev.type() == Input::Event::PRESS) _key_cnt++; - if (ev.type() == Input::Event::RELEASE) _key_cnt--; + if (ev.press()) _key_cnt++; + if (ev.release()) _key_cnt--; /* ignore key combinations */ if (_key_cnt > 1) continue; - typedef String<32> Key_name; - Key_name const ev_key_name(Input::key_name(ev.keycode())); - typedef Xml_node Xml_node; auto lambda = [&] (Xml_node node) { @@ -312,17 +308,24 @@ void Global_keys_handler::Main::_apply_input_events(unsigned num_ev, if (!node.has_type("press") && !node.has_type("release")) return; - if (node.has_type("press") && ev.type() != Input::Event::PRESS) - return; - - if (node.has_type("release") && ev.type() != Input::Event::RELEASE) - return; - /* * XML node applies for current event type, check if the key * matches. */ - if (node.attribute_value("name", Key_name()) != ev_key_name) + typedef String<32> Key_name; + Key_name const expected = node.attribute_value("name", Key_name()); + + bool key_matches = false; + + if (node.has_type("press")) + ev.handle_press([&] (Input::Keycode key, Codepoint) { + key_matches = (expected == Input::key_name(key)); }); + + if (node.has_type("release")) + ev.handle_release([&] (Input::Keycode key) { + key_matches = (expected == Input::key_name(key)); }); + + if (!key_matches) return; /* diff --git a/repos/os/src/drivers/framebuffer/spec/sdl/input.cc b/repos/os/src/drivers/framebuffer/spec/sdl/input.cc index 786be9d06..c3f897dad 100644 --- a/repos/os/src/drivers/framebuffer/spec/sdl/input.cc +++ b/repos/os/src/drivers/framebuffer/spec/sdl/input.cc @@ -26,7 +26,7 @@ /** * Convert SDL keycode to Genode keycode */ -static long convert_keycode(int sdl_keycode) +static Input::Keycode convert_keycode(int sdl_keycode) { using namespace Input; @@ -135,7 +135,7 @@ static long convert_keycode(int sdl_keycode) case SDLK_RMETA: return KEY_RIGHTMETA; case SDLK_LMETA: return KEY_LEFTMETA; - default: return 0; + default: return KEY_UNKNOWN; } }; @@ -158,11 +158,11 @@ static Input::Event wait_for_sdl_event() if (ox == mx && oy == my) return Event(); - return Event(Event::MOTION, 0, mx, my, mx - ox, my - oy); + return Absolute_motion{mx, my}; } - /* determine keycode */ - long keycode = 0; + /* determine key code */ + Keycode keycode = KEY_UNKNOWN; switch (event.type) { case SDL_KEYUP: case SDL_KEYDOWN: @@ -177,12 +177,11 @@ static Input::Event wait_for_sdl_event() case SDL_BUTTON_LEFT: keycode = BTN_LEFT; break; case SDL_BUTTON_MIDDLE: keycode = BTN_MIDDLE; break; case SDL_BUTTON_RIGHT: keycode = BTN_RIGHT; break; - default: keycode = 0; + default: break; } } /* determine event type */ - Event::Type type = Event::INVALID; switch (event.type) { case SDL_KEYUP: @@ -192,32 +191,27 @@ static Input::Event wait_for_sdl_event() /* ignore */ return Event(); - type = Event::RELEASE; - break; + return Release{keycode}; case SDL_KEYDOWN: case SDL_MOUSEBUTTONDOWN: - if (event.button.button == SDL_BUTTON_WHEELUP) { - type = Event::WHEEL; - return Event(type, 0, 0, 0, 0, 1); - } else if (event.button.button == SDL_BUTTON_WHEELDOWN) { - type = Event::WHEEL; - return Event(type, 0, 0, 0, 0, -1); - } - type = Event::PRESS; - break; + + if (event.button.button == SDL_BUTTON_WHEELUP) + return Wheel{0, 1}; + + else if (event.button.button == SDL_BUTTON_WHEELDOWN) + return Wheel{0, -1}; + + return Press{keycode}; default: - return Event(); + break; } - - return Event(type, keycode, 0, 0, 0, 0); + return Event(); } -namespace Input { - struct Backend; -} +namespace Input { struct Backend; } struct Input::Backend : Genode::Thread { @@ -237,9 +231,7 @@ struct Input::Backend : Genode::Thread Input::Event e; /* prevent flooding of client with invalid events */ - do { - e = wait_for_sdl_event(); - } while (e.type() == Input::Event::INVALID); + do { e = wait_for_sdl_event(); } while (!e.valid()); handler.event(e); } diff --git a/repos/os/src/drivers/input/spec/imx53/egalax_ts.h b/repos/os/src/drivers/input/spec/imx53/egalax_ts.h index 7b447ce15..4ce3ced0a 100644 --- a/repos/os/src/drivers/input/spec/imx53/egalax_ts.h +++ b/repos/os/src/drivers/input/spec/imx53/egalax_ts.h @@ -81,14 +81,14 @@ class Input::Touchscreen { y = 76800 / (3276700 / y); /* motion event */ - ev_queue.add(Input::Event(Input::Event::MOTION, 0, x, y, 0, 0)); + ev_queue.add(Input::Absolute_motion{x, y}); /* button event */ - if ((down && (_state == RELEASED)) || - (!down && (_state == PRESSED))) { - ev_queue.add(Input::Event(down ? Input::Event::PRESS - : Input::Event::RELEASE, - Input::BTN_LEFT, 0, 0, 0, 0)); + if ((down && (_state == RELEASED)) || (!down && (_state == PRESSED))) { + + if (down) ev_queue.add(Input::Press {Input::BTN_LEFT}); + else ev_queue.add(Input::Release{Input::BTN_LEFT}); + _state = down ? PRESSED : RELEASED; } } diff --git a/repos/os/src/drivers/input/spec/imx53/mpr121.h b/repos/os/src/drivers/input/spec/imx53/mpr121.h index 998140ac5..97b980484 100644 --- a/repos/os/src/drivers/input/spec/imx53/mpr121.h +++ b/repos/os/src/drivers/input/spec/imx53/mpr121.h @@ -95,9 +95,11 @@ class Input::Buttons { for (unsigned i = 0; i < (sizeof(buttons)/sizeof(int)); i++) { if ((_state & buttons[i]) == (buf & buttons[i])) continue; - Input::Event::Type event = (buf & buttons[i]) ? - Input::Event::PRESS : Input::Event::RELEASE; - ev_queue.add(Input::Event(event, codes[i], 0, 0, 0, 0)); + + Input::Keycode const key = Input::Keycode(codes[i]); + + if (buf & buttons[i]) ev_queue.add(Input::Press {key}); + else ev_queue.add(Input::Release{key}); }; _state = buf; } diff --git a/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h b/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h index dd14f63f0..2824b0632 100644 --- a/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h +++ b/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h @@ -467,8 +467,8 @@ class Ps2::Keyboard : public Input_driver if (!_state_machine->ready()) return; - bool press = _state_machine->press(); - unsigned key_code = _state_machine->key_code(); + bool press = _state_machine->press(); + Input::Keycode key_code = Input::Keycode(_state_machine->key_code()); /* * The old key state should not equal the state after the event. @@ -484,7 +484,7 @@ class Ps2::Keyboard : public Input_driver if (_verbose.keyboard) Genode::log("post ", press ? "PRESS" : "RELEASE", ", " - "key_code = ", key_code); + "key_code = ", Input::key_name(key_code)); if (_ev_queue.avail_capacity() == 0) { Genode::warning("event queue overflow - dropping events"); @@ -492,9 +492,10 @@ class Ps2::Keyboard : public Input_driver } /* post event to event queue */ - _ev_queue.add(Input::Event(press ? Input::Event::PRESS - : Input::Event::RELEASE, - key_code, 0, 0, 0, 0)); + if (press) + _ev_queue.add(Input::Press{key_code}); + else + _ev_queue.add(Input::Release{key_code}); /* start with new packet */ _state_machine->reset(); diff --git a/repos/os/src/drivers/input/spec/ps2/ps2_mouse.h b/repos/os/src/drivers/input/spec/ps2/ps2_mouse.h index 9201e654c..0e5f3718d 100644 --- a/repos/os/src/drivers/input/spec/ps2/ps2_mouse.h +++ b/repos/os/src/drivers/input/spec/ps2/ps2_mouse.h @@ -111,9 +111,11 @@ class Ps2::Mouse : public Input_driver _check_for_event_queue_overflow(); - _ev_queue.add(Input::Event(new_state ? Input::Event::PRESS - : Input::Event::RELEASE, - key_code, 0, 0, 0, 0)); + if (new_state) + _ev_queue.add(Input::Press{Input::Keycode(key_code)}); + else + _ev_queue.add(Input::Release{Input::Keycode(key_code)}); + *old_state = new_state; } @@ -242,8 +244,7 @@ class Ps2::Mouse : public Input_driver _check_for_event_queue_overflow(); - _ev_queue.add(Input::Event(Input::Event::MOTION, - 0, 0, 0, rel_x, rel_y)); + _ev_queue.add(Input::Relative_motion{rel_x, rel_y}); } /* generate wheel event */ @@ -264,8 +265,7 @@ class Ps2::Mouse : public Input_driver _check_for_event_queue_overflow(); - _ev_queue.add(Input::Event(Input::Event::WHEEL, - 0, 0, 0, 0, rel_z)); + _ev_queue.add(Input::Wheel{0, rel_z}); } /* detect changes of mouse-button state and post corresponding events */ diff --git a/repos/os/src/server/input_filter/accelerate_source.h b/repos/os/src/server/input_filter/accelerate_source.h index 566b3e7aa..cc0021535 100644 --- a/repos/os/src/server/input_filter/accelerate_source.h +++ b/repos/os/src/server/input_filter/accelerate_source.h @@ -74,11 +74,11 @@ class Input_filter::Accelerate_source : public Source, Source::Sink */ long const _max; - long _apply_acceleration(long v) const + int _apply_acceleration(int v) const { - long const sign = (v < 0) ? -1 : 1, - index = max(0, min(255, (sign*v*_sensitivity_percent)/100)), - accel = (_lut.values[index]*_max)/256; + int const sign = (v < 0) ? -1 : 1, + index = max(0, min(255, (sign*v*_sensitivity_percent)/100)), + accel = (_lut.values[index]*_max)/256; return v + sign*accel; } @@ -88,15 +88,14 @@ class Input_filter::Accelerate_source : public Source, Source::Sink */ void submit_event(Input::Event const &event) override { - /* forward unrelated events */ - if (!event.relative_motion()) { - _destination.submit_event(event); - return; - } + using namespace Input; - _destination.submit_event(Input::Event(Input::Event::MOTION, 0, 0, 0, - _apply_acceleration(event.rx()), - _apply_acceleration(event.ry()))); + Event ev = event; + + ev.handle_relative_motion([&] (int x, int y) { + ev = Relative_motion{_apply_acceleration(x), + _apply_acceleration(y)}; }); + _destination.submit_event(ev); } public: diff --git a/repos/os/src/server/input_filter/button_scroll_source.h b/repos/os/src/server/input_filter/button_scroll_source.h index 5aad803a6..45c2245c6 100644 --- a/repos/os/src/server/input_filter/button_scroll_source.h +++ b/repos/os/src/server/input_filter/button_scroll_source.h @@ -56,18 +56,6 @@ class Input_filter::Button_scroll_source : public Source, Source::Sink */ int _accumulated_motion = 0; - bool _magic_button_press_event(Input::Event const &event) const - { - return (event.type() == Input::Event::PRESS) - && (event.keycode() == _button); - } - - bool _magic_button_release_event(Input::Event const &event) const - { - return (event.type() == Input::Event::RELEASE) - && (event.keycode() == _button); - } - Wheel(Xml_node config) : _button(key_code_by_name(_button_attribute(config).string())), @@ -78,7 +66,7 @@ class Input_filter::Button_scroll_source : public Source, Source::Sink { switch (_state) { case IDLE: - if (_magic_button_press_event(event)) { + if (event.key_press(_button)) { _state = BUTTON_PRESSED; _accumulated_motion = 0; } @@ -103,7 +91,7 @@ class Input_filter::Button_scroll_source : public Source, Source::Sink */ bool handle_deactivation(Input::Event const &event) { - if (_magic_button_release_event(event)) { + if (event.key_release(_button)) { bool const emit_press_release = (_state == BUTTON_PRESSED); _state = IDLE; _accumulated_motion = 0; @@ -144,8 +132,7 @@ class Input_filter::Button_scroll_source : public Source, Source::Sink bool suppressed(Input::Event const event) { return (_state == ACTIVE && event.relative_motion()) - || _magic_button_press_event(event) - || _magic_button_release_event(event); + || event.key_press(_button); } }; @@ -167,18 +154,17 @@ class Input_filter::Button_scroll_source : public Source, Source::Sink _vertical_wheel .handle_activation(event); _horizontal_wheel.handle_activation(event); - if (event.relative_motion()) { - _vertical_wheel .apply_relative_motion(event.ry()); - _horizontal_wheel.apply_relative_motion(event.rx()); - } + event.handle_relative_motion([&] (int x, int y) { + _vertical_wheel .apply_relative_motion(y); + _horizontal_wheel.apply_relative_motion(x); + }); /* emit artificial wheel event */ int const wheel_x = _horizontal_wheel.pending_motion(), wheel_y = _vertical_wheel .pending_motion(); if (wheel_x || wheel_y) - _destination.submit_event(Event(Event::WHEEL, 0, 0, 0, - wheel_x, wheel_y)); + _destination.submit_event(Input::Wheel{wheel_x, wheel_y}); /* * Submit both press event and release event of magic button at @@ -188,19 +174,18 @@ class Input_filter::Button_scroll_source : public Source, Source::Sink * both conditions regardless of the result of the first call of * 'handle_activation'. */ - if (_vertical_wheel .handle_deactivation(event) - | _horizontal_wheel.handle_deactivation(event)) { + event.handle_release([&] (Input::Keycode key) { + if (_vertical_wheel .handle_deactivation(event) + | _horizontal_wheel.handle_deactivation(event)) { - _destination.submit_event(Event(Event::PRESS, event.code(), 0, 0, 0, 0)); - _destination.submit_event(event); - return; - } + _destination.submit_event(Input::Press{key}); + } + }); /* hide consumed relative motion and magic-button press events */ if (_vertical_wheel .suppressed(event)) return; if (_horizontal_wheel.suppressed(event)) return; - /* forward unrelated events */ _destination.submit_event(event); } diff --git a/repos/os/src/server/input_filter/chargen_source.h b/repos/os/src/server/input_filter/chargen_source.h index 5442a9868..804290f6e 100644 --- a/repos/os/src/server/input_filter/chargen_source.h +++ b/repos/os/src/server/input_filter/chargen_source.h @@ -29,6 +29,8 @@ class Input_filter::Chargen_source : public Source, Source::Sink { private: + typedef Input::Event Event; + Allocator &_alloc; Timer_accessor &_timer_accessor; Include_accessor &_include_accessor; @@ -179,11 +181,11 @@ class Input_filter::Chargen_source : public Source, Source::Sink Conditions const _conditions; - Input::Event::Utf8 const _character; + Codepoint const _character; - Rule(Registry ®istry, - Conditions conditions, - Input::Event::Utf8 character) + Rule(Registry ®istry, + Conditions conditions, + Codepoint character) : _reg_elem(registry, *this), _conditions(conditions), @@ -205,19 +207,19 @@ class Input_filter::Chargen_source : public Source, Source::Sink return 1 + _conditions.num_modifier_constraints(); } - Input::Event::Utf8 character() const { return _character; } + Codepoint character() const { return _character; } }; Registry rules { }; /** - * Call functor 'fn' with the 'Input::Event::Utf8' character - * defined for the best matching rule + * Call functor 'fn' with the codepoint of the character defined + * for the best matching rule */ template void apply_best_matching_rule(Modifier_map const &mod_map, FN const &fn) const { - Input::Event::Utf8 best_match { 0 }; + Codepoint best_match { Codepoint::INVALID }; unsigned max_score = 0; @@ -291,10 +293,13 @@ class Input_filter::Chargen_source : public Source, Source::Sink * * \throw Missing_character_definition */ - static Input::Event::Utf8 _utf8_from_xml_node(Xml_node node) + static Codepoint _codepoint_from_xml_node(Xml_node node) { if (node.has_attribute("ascii")) - return Input::Event::Utf8(node.attribute_value("ascii", 0UL)); + return Codepoint { node.attribute_value("ascii", 0) }; + + if (node.has_attribute("code")) + return Codepoint { node.attribute_value("code", 0) }; if (node.has_attribute("char")) { @@ -304,7 +309,7 @@ class Input_filter::Chargen_source : public Source, Source::Sink unsigned char const ascii = value.string()[0]; if (ascii < 128) - return Input::Event::Utf8(ascii); + return Codepoint { ascii }; warning("char attribute with non-ascii character " "'", value, "'"); @@ -312,12 +317,13 @@ class Input_filter::Chargen_source : public Source, Source::Sink } if (node.has_attribute("b0")) { - unsigned char const b0 = node.attribute_value("b0", 0UL), - b1 = node.attribute_value("b1", 0UL), - b2 = node.attribute_value("b2", 0UL), - b3 = node.attribute_value("b3", 0UL); + char const b0 = node.attribute_value("b0", 0L), + b1 = node.attribute_value("b1", 0L), + b2 = node.attribute_value("b2", 0L), + b3 = node.attribute_value("b3", 0L); - return Input::Event::Utf8(b0, b1, b2, b3); + char const buf[5] { b0, b1, b2, b3, 0 }; + return Utf8_ptr(buf).codepoint(); } throw Missing_character_definition(); @@ -340,7 +346,7 @@ class Input_filter::Chargen_source : public Source, Source::Sink Input::Keycode const code = key_code_by_name(name); new (_alloc) Key::Rule(key(code).rules, cond, - _utf8_from_xml_node(key_node)); + _codepoint_from_xml_node(key_node)); }); } @@ -377,14 +383,16 @@ class Input_filter::Chargen_source : public Source, Source::Sink Microseconds const _delay; Microseconds const _rate; - Input::Event::Utf8 _curr_character { 0 }; + Codepoint _curr_character { Codepoint::INVALID }; enum State { IDLE, REPEAT } _state { IDLE }; void _handle_timeout(Duration) { if (_state == REPEAT) { - _destination.submit_event(Input::Event(_curr_character)); + _destination.submit_event(Input::Press_char{Input::KEY_UNKNOWN, + _curr_character}); + _destination.submit_event(Input::Release{Input::KEY_UNKNOWN}); _timeout.schedule(_rate); } } @@ -400,7 +408,7 @@ class Input_filter::Chargen_source : public Source, Source::Sink _rate (node.attribute_value("rate_ms", 0UL)*1000) { } - void schedule_repeat(Input::Event::Utf8 character) + void schedule_repeat(Codepoint character) { _curr_character = character; _state = REPEAT; @@ -410,7 +418,7 @@ class Input_filter::Chargen_source : public Source, Source::Sink void cancel() { - _curr_character = Input::Event::Utf8(0); + _curr_character = Codepoint { Codepoint::INVALID }; _state = IDLE; } }; @@ -420,43 +428,40 @@ class Input_filter::Chargen_source : public Source, Source::Sink /** * Sink interface (called from our child node) */ - void submit_event(Input::Event const &event) override + void submit_event(Event const &event) override { - using Input::Event; + Event ev = event; - /* forward event as is */ - _destination.submit_event(event); + ev.handle_press([&] (Input::Keycode keycode, Codepoint /* ignored */) { - /* don't do anything for non-press/release events */ - if (event.type() != Event::PRESS && event.type() != Event::RELEASE) - return; + Key &key = _key_map.key(keycode); + key.state = Key::PRESSED; - Key &key = _key_map.key(event.keycode()); + if (key.type == Key::MODIFIER) _update_modifier_state(); - /* track key state */ - if (event.type() == Event::PRESS) key.state = Key::PRESSED; - if (event.type() == Event::RELEASE) key.state = Key::RELEASED; + /* supplement codepoint information to press event */ + key.apply_best_matching_rule(_mod_map, [&] (Codepoint codepoint) { - if (key.type == Key::MODIFIER) { - _update_modifier_state(); - - /* never emit a character when pressing a modifier key */ - return; - } - - if (event.type() == Event::PRESS) { - key.apply_best_matching_rule(_mod_map, [&] (Event::Utf8 utf8) { - - _destination.submit_event(Event(utf8)); + ev = Event(Input::Press_char{keycode, codepoint}); if (_char_repeater.constructed()) - _char_repeater->schedule_repeat(utf8); + _char_repeater->schedule_repeat(codepoint); }); - } + }); + + ev.handle_release([&] (Input::Keycode keycode) { + + Key &key = _key_map.key(keycode); + key.state = Key::RELEASED; + + if (key.type == Key::MODIFIER) _update_modifier_state(); - if (event.type() == Event::RELEASE) if (_char_repeater.constructed()) _char_repeater->cancel(); + }); + + /* forward filtered event */ + _destination.submit_event(ev); } Source &_source; diff --git a/repos/os/src/server/input_filter/connection.h b/repos/os/src/server/input_filter/connection.h index 3a4368705..a8611d6e0 100644 --- a/repos/os/src/server/input_filter/connection.h +++ b/repos/os/src/server/input_filter/connection.h @@ -82,8 +82,8 @@ class Input_filter::Input_connection auto update_key_cnt = [&] (Input::Event const &event) { - if (event.type() == Input::Event::PRESS) _key_cnt++; - if (event.type() == Input::Event::RELEASE) _key_cnt--; + if (event.press()) _key_cnt++; + if (event.release()) _key_cnt--; }; for_each_event(update_key_cnt); diff --git a/repos/os/src/server/input_filter/remap_source.h b/repos/os/src/server/input_filter/remap_source.h index 4e297b07f..b28fcbc6c 100644 --- a/repos/os/src/server/input_filter/remap_source.h +++ b/repos/os/src/server/input_filter/remap_source.h @@ -51,22 +51,25 @@ class Input_filter::Remap_source : public Source, Source::Sink { using Input::Event; - bool const key_event = - event.type() == Event::PRESS || event.type() == Event::RELEASE; - - bool const code_valid = - event.keycode() >= 0 && event.keycode() < Input::KEY_MAX; - /* forward events that are unrelated to the remapper */ - if (!key_event || !code_valid) { + if (!event.press() && !event.release()) { _destination.submit_event(event); return; } - /* remap the key code */ - Key &key = _keys[event.keycode()]; + /* + * remap the key code for press and release events + * + * The range of the 'key' is checked by the 'Event' handle methods, + * so it is safe to use as array index. + */ + auto remap = [&] (Input::Keycode key) { return _keys[key].code; }; - _destination.submit_event(Event(event.type(), key.code, 0, 0, 0, 0)); + event.handle_press([&] (Input::Keycode key, Codepoint codepoint) { + _destination.submit_event(Input::Press_char{remap(key), codepoint}); }); + + event.handle_release([&] (Input::Keycode key) { + _destination.submit_event(Input::Release{remap(key)}); }); } void _apply_config(Xml_node const config, unsigned const max_recursion = 4) diff --git a/repos/os/src/server/loader/input.h b/repos/os/src/server/loader/input.h index 42f062a28..4c510a477 100644 --- a/repos/os/src/server/loader/input.h +++ b/repos/os/src/server/loader/input.h @@ -85,19 +85,10 @@ class Input::Session_component : public Rpc_object Input::Event &ev = _ev_buf[i]; - if ((ev.type() == Input::Event::MOTION) - || (ev.type() == Input::Event::WHEEL) - || (ev.code() == Input::BTN_LEFT) - || (ev.code() == Input::BTN_RIGHT) - || (ev.code() == Input::BTN_MIDDLE)) { - - ev = Input::Event(ev.type(), - ev.code(), - ev.ax() + delta.x(), - ev.ay() + delta.y(), - ev.rx(), - ev.ry()); - } + ev.handle_absolute_motion([&] (int x, int y) { + Point<> p = Point<>(x, y) + delta; + ev = Input::Absolute_motion{p.x(), p.y()}; + }); } return num_ev; diff --git a/repos/os/src/server/nit_fb/main.cc b/repos/os/src/server/nit_fb/main.cc index 77b9925b4..5ffdee5f3 100644 --- a/repos/os/src/server/nit_fb/main.cc +++ b/repos/os/src/server/nit_fb/main.cc @@ -42,42 +42,31 @@ namespace Nit_fb { /** * Translate input event */ -static Input::Event translate_event(Input::Event const ev, +static Input::Event translate_event(Input::Event ev, Nit_fb::Point const input_origin, Nit_fb::Area const boundary) { - switch (ev.type()) { + using Nit_fb::Point; - case Input::Event::MOTION: - case Input::Event::PRESS: - case Input::Event::RELEASE: - case Input::Event::FOCUS: - case Input::Event::LEAVE: - case Input::Event::TOUCH: - { - Nit_fb::Point abs_pos = Nit_fb::Point(ev.ax(), ev.ay()) - - input_origin; + /* function to clamp point to bounday */ + auto clamp = [boundary] (Point p) { + return Point(Genode::min((int)boundary.w() - 1, Genode::max(0, p.x())), + Genode::min((int)boundary.h() - 1, Genode::max(0, p.y()))); }; - using Genode::min; - using Genode::max; - using Input::Event; + /* function to translate point to 'input_origin' */ + auto translate = [input_origin] (Point p) { return p - input_origin; }; - int const ax = min((int)boundary.w() - 1, max(0, abs_pos.x())); - int const ay = min((int)boundary.h() - 1, max(0, abs_pos.y())); + ev.handle_absolute_motion([&] (int x, int y) { + Point p = clamp(translate(Point(x, y))); + ev = Input::Absolute_motion{p.x(), p.y()}; + }); - if (ev.type() == Event::TOUCH) - return Event::create_touch_event(ax, ay, ev.code(), - ev.is_touch_release()); + ev.handle_touch([&] (Input::Touch_id id, float x, float y) { + Point p = clamp(translate(Point(x, y))); + ev = Input::Touch{id, (float)p.x(), (float)p.y()}; + }); - return Event(ev.type(), ev.code(), ax, ay, 0, 0); - } - - case Input::Event::INVALID: - case Input::Event::WHEEL: - case Input::Event::CHARACTER: - return ev; - } - return Input::Event(); + return ev; } @@ -424,9 +413,7 @@ struct Nit_fb::Main : View_updater bool update = false; for (unsigned i = 0; i < num; i++) { - if (events[i].type() == Input::Event::FOCUS) - update = events[i].code(); - + update |= events[i].focus_enter(); input_session.submit(translate_event(events[i], position, fb_session.size())); } diff --git a/repos/os/src/server/nitpicker/session_component.cc b/repos/os/src/server/nitpicker/session_component.cc index 77bd8cc23..9284d47f1 100644 --- a/repos/os/src/server/nitpicker/session_component.cc +++ b/repos/os/src/server/nitpicker/session_component.cc @@ -238,14 +238,14 @@ void Session_component::submit_input_event(Input::Event e) Point const origin_offset = _phys_pos(Point(0, 0), _view_stack.size()); /* - * Transpose absolute coordinates by session-specific vertical - * offset. + * Transpose absolute coordinates by session-specific vertical offset. */ - if (e.ax() || e.ay()) - e = Event(e.type(), e.code(), - max(0, e.ax() - origin_offset.x()), - max(0, e.ay() - origin_offset.y()), - e.rx(), e.ry()); + e.handle_absolute_motion([&] (int x, int y) { + e = Absolute_motion{max(0, x - origin_offset.x()), + max(0, y - origin_offset.y())}; }); + e.handle_touch([&] (Touch_id id, float x, float y) { + e = Touch{ id, max(0.0f, x - origin_offset.x()), + max(0.0f, y - origin_offset.y())}; }); _input_session_component.submit(&e); } diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 23e618e8e..8aecf70c1 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -37,16 +37,16 @@ static inline bool _mouse_button(Keycode keycode) { static unsigned num_consecutive_events(Input::Event const *ev, unsigned max) { if (max < 1) return 0; - if (ev->type() != Input::Event::MOTION) return 1; - bool const first_absolute = ev->absolute_motion(); + bool const first_is_absolute_motion = ev->absolute_motion(); + bool const first_is_relative_motion = ev->relative_motion(); - /* iterate until we get a different event type, start at second */ unsigned cnt = 1; for (ev++ ; cnt < max; cnt++, ev++) { - if (ev->type() != Input::Event::MOTION) break; - if (first_absolute != ev->absolute_motion()) break; - } + if (first_is_absolute_motion && ev->absolute_motion()) continue; + if (first_is_relative_motion && ev->relative_motion()) continue; + break; + }; return cnt; } @@ -60,11 +60,26 @@ static unsigned num_consecutive_events(Input::Event const *ev, unsigned max) */ static Input::Event merge_motion_events(Input::Event const *ev, unsigned n) { - Input::Event res; - for (unsigned i = 0; i < n; i++, ev++) - res = Input::Event(Input::Event::MOTION, 0, ev->ax(), ev->ay(), - res.rx() + ev->rx(), res.ry() + ev->ry()); - return res; + if (n == 0) return Event(); + + if (ev->relative_motion()) { + int rx = 0, ry = 0; + for (unsigned i = 0; i < n; i++, ev++) + ev->handle_relative_motion([&] (int x, int y) { rx += x; ry += y; }); + + if (rx || ry) + return Relative_motion{rx, ry}; + } + + if (ev->absolute_motion()) { + int ax = 0, ay = 0; + for (unsigned i = 0; i < n; i++, ev++) + ev->handle_absolute_motion([&] (int x, int y) { ax = x; ay = y; }); + + return Absolute_motion{ax, ay}; + } + + return Event(); } @@ -74,62 +89,40 @@ static Input::Event merge_motion_events(Input::Event const *ev, unsigned n) void User_state::_handle_input_event(Input::Event ev) { - Input::Keycode const keycode = ev.keycode(); - Input::Event::Type const type = ev.type(); + /* transparently convert relative into absolute motion event */ + ev.handle_relative_motion([&] (int x, int y) { - /* - * Mangle incoming events - */ - int ax = _pointer_pos.x(), ay = _pointer_pos.y(); - int rx = 0, ry = 0; /* skip info about relative motion by default */ + int const ox = _pointer_pos.x(), + oy = _pointer_pos.y(); - /* transparently handle absolute and relative motion events */ - if (type == Event::MOTION) { - if ((ev.rx() || ev.ry()) && ev.ax() == 0 && ev.ay() == 0) { - ax = max(0, min((int)_view_stack.size().w() - 1, ax + ev.rx())); - ay = max(0, min((int)_view_stack.size().h() - 1, ay + ev.ry())); - } else { - ax = ev.ax(); - ay = ev.ay(); - } - } + int const ax = max(0, min((int)_view_stack.size().w() - 1, ox + x)), + ay = max(0, min((int)_view_stack.size().h() - 1, oy + y)); - /* propagate relative motion for wheel events */ - if (type == Event::WHEEL) { - rx = ev.rx(); - ry = ev.ry(); - } + ev = Absolute_motion{ax, ay}; + }); - if (type == Event::TOUCH) { - ax = ev.ax(); - ay = ev.ay(); - ev = Input::Event::create_touch_event(ax, ay, ev.code(), - ev.touch_release()); - } else if (type == Event::CHARACTER) { - ev = Input::Event(type, ev.code(), ax, ay, rx, ry); - } else - ev = Input::Event(type, keycode, ax, ay, rx, ry); - - _pointer_pos = Point(ax, ay); + /* respond to motion events by updating the pointer position */ + ev.handle_absolute_motion([&] (int x, int y) { + _pointer_pos = Point(x, y); }); bool const drag = _key_cnt > 0; /* count keys */ - if (type == Event::PRESS) _key_cnt++; - if (type == Event::RELEASE && drag) _key_cnt--; + if (ev.press()) _key_cnt++; + if (ev.release() && drag) _key_cnt--; /* track key states */ - if (type == Event::PRESS) { - if (_key_array.pressed(keycode)) - Genode::warning("suspicious double press of ", Input::key_name(keycode)); - _key_array.pressed(keycode, true); - } + ev.handle_press([&] (Keycode key, Codepoint) { + if (_key_array.pressed(key)) + Genode::warning("suspicious double press of ", Input::key_name(key)); + _key_array.pressed(key, true); + }); - if (type == Event::RELEASE) { - if (!_key_array.pressed(keycode)) - Genode::warning("suspicious double release of ", Input::key_name(keycode)); - _key_array.pressed(keycode, false); - } + ev.handle_release([&] (Keycode key) { + if (!_key_array.pressed(key)) + Genode::warning("suspicious double release of ", Input::key_name(key)); + _key_array.pressed(key, false); + }); View_component const * const pointed_view = _view_stack.find_view(_pointer_pos); @@ -138,18 +131,18 @@ void User_state::_handle_input_event(Input::Event ev) /* * Deliver a leave event if pointed-to session changed */ - if (_hovered && (hovered != _hovered)) { - - Input::Event leave_ev(Input::Event::LEAVE, 0, ax, ay, 0, 0); - _hovered->submit_input_event(leave_ev); - } + if (_hovered && (hovered != _hovered)) + _hovered->submit_input_event(Hover_leave()); _hovered = hovered; /* * Handle start of a key sequence */ - if (type == Event::PRESS && (_key_cnt == 1)) { + ev.handle_press([&] (Keycode keycode, Codepoint) { + + if (_key_cnt != 1) + return; View_owner *global_receiver = nullptr; @@ -163,14 +156,13 @@ void User_state::_handle_input_event(Input::Event ev) /* * Notify both the old focused session and the new one. */ - if (_focused) { - Input::Event unfocus_ev(Input::Event::FOCUS, 0, ax, ay, 0, 0); - _focused->submit_input_event(unfocus_ev); - } + if (_focused) + _focused->submit_input_event(Focus_leave()); if (_hovered) { - Input::Event focus_ev(Input::Event::FOCUS, 1, ax, ay, 0, 0); - _hovered->submit_input_event(focus_ev); + _hovered->submit_input_event(Absolute_motion{_pointer_pos.x(), + _pointer_pos.y()}); + _hovered->submit_input_event(Focus_enter()); } if (_hovered->has_transient_focusable_domain()) { @@ -219,12 +211,12 @@ void User_state::_handle_input_event(Input::Event ev) */ if (!global_receiver) _input_receiver = _focused; - } + }); /* * Deliver event to session */ - if (type == Event::MOTION || type == Event::WHEEL || type == Event::TOUCH) { + if (ev.absolute_motion() || ev.wheel() || ev.touch() || ev.touch_release()) { if (_key_cnt == 0) { @@ -248,30 +240,28 @@ void User_state::_handle_input_event(Input::Event ev) * Deliver press/release event to focused session or the receiver of global * key. */ - if ((type == Event::PRESS) && _input_receiver) { - if (!_mouse_button(ev.keycode()) + ev.handle_press([&] (Keycode key, Codepoint) { + + if (!_input_receiver) + return; + + if (!_mouse_button(key) || (_hovered && (_hovered->has_focusable_domain() || _hovered->has_same_domain(_focused)))) _input_receiver->submit_input_event(ev); else _input_receiver = nullptr; - } + }); - if ((type == Event::RELEASE) && _input_receiver) - _input_receiver->submit_input_event(ev); - - /* - * Forward character events - */ - if (type == Event::CHARACTER && _input_receiver) + if (ev.release() && _input_receiver) _input_receiver->submit_input_event(ev); /* * Detect end of global key sequence */ - if (ev.type() == Event::RELEASE && (_key_cnt == 0) && _global_key_sequence) { - _input_receiver = _focused; + if (ev.release() && (_key_cnt == 0) && _global_key_sequence) { + _input_receiver = _focused; _global_key_sequence = false; } } @@ -299,22 +289,14 @@ User_state::handle_input_events(Input::Event const * const ev_buf, Input::Event const *e = &ev_buf[src_ev_cnt]; Input::Event curr = *e; - if (e->type() == Input::Event::MOTION) { - unsigned n = num_consecutive_events(e, num_ev - src_ev_cnt); + if (e->absolute_motion() || e->relative_motion()) { + unsigned const n = num_consecutive_events(e, num_ev - src_ev_cnt); curr = merge_motion_events(e, n); /* skip merged events */ src_ev_cnt += n - 1; } - /* - * If subsequential relative motion events are merged to - * a zero-motion event, drop it. Otherwise, it would be - * misinterpreted as absolute event pointing to (0, 0). - */ - if (e->relative_motion() && curr.rx() == 0 && curr.ry() == 0) - continue; - /* * If we detect a pressed key sometime during the event processing, * we regard the user as active. This check captures the presence @@ -331,7 +313,7 @@ User_state::handle_input_events(Input::Event const * const ev_buf, * updates the pointed session, which might have changed by other * means, for example view movement. */ - _handle_input_event(Input::Event()); + _handle_input_event(Event()); } /* @@ -341,8 +323,7 @@ User_state::handle_input_events(Input::Event const * const ev_buf, bool key_state_affected = false; for (unsigned i = 0; i < num_ev; i++) - key_state_affected |= (ev_buf[i].type() == Input::Event::PRESS) || - (ev_buf[i].type() == Input::Event::RELEASE); + key_state_affected |= (ev_buf[i].press() || ev_buf[i].release()); _apply_pending_focus_change(); diff --git a/repos/os/src/test/audio_out_click/main.cc b/repos/os/src/test/audio_out_click/main.cc index 0e6f0c7e1..c4c9679a2 100644 --- a/repos/os/src/test/audio_out_click/main.cc +++ b/repos/os/src/test/audio_out_click/main.cc @@ -133,13 +133,9 @@ struct Main void _handle() { - for (int i = 0, num_ev = _input.flush(); i < num_ev; ++i) { - Input::Event const ev = _ev_ds.local_addr()[i]; - if (ev.type() == Input::Event::PRESS) { - _click.play(); - break; - } - } + _input.for_each_event([&] (Input::Event const &ev) { + if (ev.press()) + _click.play(); }); } Main(Env & env) : _env(env) diff --git a/repos/os/src/test/input/test.cc b/repos/os/src/test/input/test.cc index d4c0ae6eb..215c87581 100644 --- a/repos/os/src/test/input/test.cc +++ b/repos/os/src/test/input/test.cc @@ -19,69 +19,25 @@ using namespace Genode; -static char const * ev_type(Input::Event::Type type) -{ - switch (type) { - case Input::Event::INVALID: return "INVALID"; - case Input::Event::MOTION: return "MOTION "; - case Input::Event::PRESS: return "PRESS "; - case Input::Event::RELEASE: return "RELEASE"; - case Input::Event::WHEEL: return "WHEEL "; - case Input::Event::FOCUS: return "FOCUS "; - case Input::Event::LEAVE: return "LEAVE "; - case Input::Event::TOUCH: return "TOUCH "; - case Input::Event::CHARACTER: return "CHARACTER"; - } - - return ""; -} - - -static char const * key_name(Input::Event const &ev) -{ - if (ev.type() == Input::Event::MOTION) - return ""; - - return Input::key_name(static_cast(ev.code())); -} - - struct Main { - Env &env; - Input::Connection input { env }; - Signal_handler
input_sigh { env.ep(), *this, &Main::handle_input }; - int key_cnt { 0 }; - unsigned event_cnt { 0 }; + Env &_env; + Input::Connection _input { _env }; + Signal_handler
_input_sigh { _env.ep(), *this, &Main::_handle_input }; + unsigned _event_cnt { 0 }; - void handle_input(); + void _handle_input() + { + _input.for_each_event([&] (Input::Event const &ev) { + log("Input event #", _event_cnt++, "\t", ev); }); + } - Main(Env &env) : env(env) + Main(Env &env) : _env(env) { log("--- Input test ---"); - input.sigh(input_sigh); + _input.sigh(_input_sigh); } }; -void Main::handle_input() -{ - input.for_each_event([&] (Input::Event const &ev) { - event_cnt++; - - if (ev.type() == Input::Event::PRESS) key_cnt++; - if (ev.type() == Input::Event::RELEASE) key_cnt--; - - log("Input event #", event_cnt, "\t" - "type=", ev_type(ev.type()), "\t" - "code=", ev.code(), "\t" - "rx=", ev.rx(), "\t" - "ry=", ev.ry(), "\t" - "ax=", ev.ax(), "\t" - "ay=", ev.ay(), "\t" - "key_cnt=", key_cnt, "\t", key_name(ev)); - }); -} - - void Component::construct(Env &env) { static Main main(env); } diff --git a/repos/os/src/test/input_filter/main.cc b/repos/os/src/test/input_filter/main.cc index 7dfae2090..ab3d286b5 100644 --- a/repos/os/src/test/input_filter/main.cc +++ b/repos/os/src/test/input_filter/main.cc @@ -31,28 +31,7 @@ namespace Test { class Input_root; class Main; using namespace Genode; -} - - -namespace Genode { - - static inline void print(Output &output, Input::Event const &ev) - { - switch (ev.type()) { - case Input::Event::INVALID: print(output, "INVALID"); break; - case Input::Event::MOTION: print(output, "MOTION"); break; - case Input::Event::PRESS: print(output, "PRESS"); break; - case Input::Event::RELEASE: print(output, "RELEASE"); break; - case Input::Event::WHEEL: print(output, "WHEEL"); break; - case Input::Event::FOCUS: print(output, "FOCUS"); break; - case Input::Event::LEAVE: print(output, "LEAVE"); break; - case Input::Event::TOUCH: print(output, "TOUCH"); break; - case Input::Event::CHARACTER: print(output, "CHARACTER"); break; - }; - - if (ev.type() == Input::Event::PRESS || ev.type() == Input::Event::RELEASE) - print(output, " (", Input::key_name(ev.keycode()), ")"); - } + using Input::Event; } @@ -62,7 +41,7 @@ class Test::Input_from_filter struct Event_handler : Interface { - virtual void handle_event_from_filter(Input::Event const &) = 0; + virtual void handle_event_from_filter(Event const &) = 0; }; private: @@ -82,7 +61,7 @@ class Test::Input_from_filter _handle_input_in_progress = true; if (_input_expected) - _connection.for_each_event([&] (Input::Event const &event) { + _connection.for_each_event([&] (Event const &event) { _event_handler.handle_event_from_filter(event); }); _handle_input_in_progress = false; @@ -211,24 +190,28 @@ class Test::Input_to_filter step.for_each_sub_node([&] (Xml_node node) { - Input::Event::Type const type = - node.type() == "press" ? Input::Event::PRESS : - node.type() == "release" ? Input::Event::RELEASE : - node.type() == "motion" ? Input::Event::MOTION : - Input::Event::INVALID; + bool const press = node.has_type("press"), + release = node.has_type("release"); + + if (press || release) { - if (type == Input::Event::PRESS || type == Input::Event::RELEASE) { Key_name const key_name = node.attribute_value("code", Key_name()); - dst.submit(Input::Event(type, _code(key_name), 0, 0, 0, 0)); + + if (press) dst.submit(Input::Press {_code(key_name)}); + if (release) dst.submit(Input::Release{_code(key_name)}); } - if (type == Input::Event::MOTION) { - dst.submit(Input::Event(type, 0, - node.attribute_value("ax", 0L), - node.attribute_value("ay", 0L), - node.attribute_value("rx", 0L), - node.attribute_value("ry", 0L))); - } + bool const motion = node.has_type("motion"); + bool const rel = node.has_attribute("rx") || node.has_attribute("ry"); + bool const abs = node.has_attribute("ax") || node.has_attribute("ay"); + + if (motion && abs) + dst.submit(Input::Absolute_motion{(int)node.attribute_value("ax", 0L), + (int)node.attribute_value("ay", 0L)}); + + if (motion && rel) + dst.submit(Input::Relative_motion{(int)node.attribute_value("rx", 0L), + (int)node.attribute_value("ry", 0L)}); }); } }; @@ -379,52 +362,53 @@ struct Test::Main : Input_from_filter::Event_handler /** * Input_to_filter::Event_handler interface */ - void handle_event_from_filter(Input::Event const &ev) override + void handle_event_from_filter(Event const &ev) override { typedef Genode::String<20> Value; Xml_node const step = _curr_step_xml(); - switch (ev.type()) { - case Input::Event::PRESS: + bool step_succeeded = false; + + ev.handle_press([&] (Input::Keycode key, Codepoint codepoint) { + + auto codepoint_of_step = [] (Xml_node step) { + return Utf8_ptr(step.attribute_value("char", Value()).string()).codepoint(); }; + if (step.type() == "expect_press" - && step.attribute_value("code", Value()) == Input::key_name(ev.keycode())) - break; + && step.attribute_value("code", Value()) == Input::key_name(key) + && (!step.has_attribute("char") || + codepoint_of_step(step).value == codepoint.value)) + step_succeeded = true; + }); - case Input::Event::RELEASE: + ev.handle_release([&] (Input::Keycode key) { if (step.type() == "expect_release" - && step.attribute_value("code", Value()) == Input::key_name(ev.keycode())) - break; + && step.attribute_value("code", Value()) == Input::key_name(key)) + step_succeeded = true; }); - case Input::Event::WHEEL: + ev.handle_wheel([&] (int x, int y) { if (step.type() == "expect_wheel" - && step.attribute_value("rx", 0L) == ev.rx() - && step.attribute_value("ry", 0L) == ev.ry()) - break; + && step.attribute_value("rx", 0L) == x + && step.attribute_value("ry", 0L) == y) + step_succeeded = true; }); - case Input::Event::MOTION: + ev.handle_relative_motion([&] (int x, int y) { if (step.type() == "expect_motion" - && (!step.has_attribute("rx") || step.attribute_value("rx", 0L) == ev.rx()) - && (!step.has_attribute("ry") || step.attribute_value("ry", 0L) == ev.ry()) - && (!step.has_attribute("ax") || step.attribute_value("ax", 0L) == ev.ax()) - && (!step.has_attribute("ay") || step.attribute_value("ay", 0L) == ev.ay())) - break; + && (!step.has_attribute("rx") || step.attribute_value("rx", 0L) == x) + && (!step.has_attribute("ry") || step.attribute_value("ry", 0L) == y)) + step_succeeded = true; }); - case Input::Event::CHARACTER: - if (step.type() == "expect_char" - && step.attribute_value("char", Value()) == Value(Char(ev.utf8().b0))) - break; + ev.handle_absolute_motion([&] (int x, int y) { + if (step.type() == "expect_motion" + && (!step.has_attribute("ax") || step.attribute_value("ax", 0L) == x) + && (!step.has_attribute("ay") || step.attribute_value("ay", 0L) == y)) + step_succeeded = true; }); - case Input::Event::INVALID: - case Input::Event::FOCUS: - case Input::Event::LEAVE: - case Input::Event::TOUCH: - error("unexpected event: ", ev); - throw Exception(); - }; - - _advance_step(); - _execute_curr_step(); + if (step_succeeded) { + _advance_step(); + _execute_curr_step(); + } } void _handle_timer() diff --git a/repos/os/src/test/nitpicker/test.cc b/repos/os/src/test/nitpicker/test.cc index 457b7a3e5..9fe6e3f5e 100644 --- a/repos/os/src/test/nitpicker/test.cc +++ b/repos/os/src/test/nitpicker/test.cc @@ -203,30 +203,32 @@ void Component::construct(Genode::Env &env) /* * Handle input events */ - int omx = 0, omy = 0, key_cnt = 0; - Test_view *tv = 0; + int mx = 0, my = 0, key_cnt = 0; + Test_view *tv = nullptr; while (1) { while (!nitpicker.input()->pending()) timer.msleep(20); nitpicker.input()->for_each_event([&] (Input::Event const &ev) { - if (ev.type() == Input::Event::PRESS) key_cnt++; - if (ev.type() == Input::Event::RELEASE) key_cnt--; - /* move selected view */ - if (ev.type() == Input::Event::MOTION && key_cnt > 0 && tv) - tv->move(tv->x() + ev.ax() - omx, tv->y() + ev.ay() - omy); + if (ev.press()) key_cnt++; + if (ev.release()) key_cnt--; + + ev.handle_absolute_motion([&] (int x, int y) { + + /* move selected view */ + if (key_cnt > 0 && tv) + tv->move(tv->x() + x - mx, tv->y() + y - my); + + mx = x; my = y; + }); /* find selected view and bring it to front */ - if (ev.type() == Input::Event::PRESS && key_cnt == 1) { - - tv = tvs.find(ev.ax(), ev.ay()); - + if (ev.press() && key_cnt == 1) { + tv = tvs.find(mx, my); if (tv) tvs.top(tv); } - - omx = ev.ax(); omy = ev.ay(); }); } diff --git a/repos/ports/src/app/seoul/console.cc b/repos/ports/src/app/seoul/console.cc index c5148c5cb..56de9f4de 100644 --- a/repos/ports/src/app/seoul/console.cc +++ b/repos/ports/src/app/seoul/console.cc @@ -66,17 +66,22 @@ struct Ps2_mouse_packet : Genode::Register<32> static bool mouse_event(Input::Event const &ev) { - using Input::Event; - if (ev.type() == Event::PRESS || ev.type() == Event::RELEASE) { - if (ev.code() == Input::BTN_LEFT) return true; - if (ev.code() == Input::BTN_MIDDLE) return true; - if (ev.code() == Input::BTN_RIGHT) return true; - } + using namespace Input; - if (ev.type() == Event::MOTION) - return true; + bool result = false; - return false; + auto mouse_button = [] (Keycode key) { + return key == BTN_LEFT || key == BTN_MIDDLE || key == BTN_RIGHT; }; + + ev.handle_press([&] (Keycode key, Genode::Codepoint) { + result |= mouse_button(key); }); + + ev.handle_release([&] (Keycode key) { + result |= mouse_button(key); }); + + result |= ev.absolute_motion() || ev.relative_motion(); + + return result; } @@ -88,26 +93,25 @@ static bool mouse_event(Input::Event const &ev) unsigned Seoul::Console::_input_to_ps2mouse(Input::Event const &ev) { /* track state of mouse buttons */ - using Input::Event; - if (ev.type() == Event::PRESS || ev.type() == Event::RELEASE) { - bool const pressed = ev.type() == Event::PRESS; - if (ev.code() == Input::BTN_LEFT) _left = pressed; - if (ev.code() == Input::BTN_MIDDLE) _middle = pressed; - if (ev.code() == Input::BTN_RIGHT) _right = pressed; - } + auto apply_button = [] (Input::Event const &ev, Input::Keycode key, bool &state) { + if (ev.key_press (key)) state = true; + if (ev.key_release(key)) state = false; + }; - int rx; - int ry; + apply_button(ev, Input::BTN_LEFT, _left); + apply_button(ev, Input::BTN_MIDDLE, _middle); + apply_button(ev, Input::BTN_RIGHT, _right); - if (ev.absolute_motion()) { - static Input::Event last_event; - rx = ev.ax() - last_event.ax(); - ry = ev.ay() - last_event.ay(); - last_event = ev; - } else { - rx = ev.rx(); - ry = ev.ry(); - } + int rx = 0; + int ry = 0; + + ev.handle_absolute_motion([&] (int x, int y) { + static int ox = 0, oy = 0; + rx = x - ox; ry = y - oy; + ox = x; oy = y; + }); + + ev.handle_relative_motion([&] (int x, int y) { rx = x; ry = y; }); /* clamp relative motion vector to bounds */ int const boundary = 200; @@ -316,16 +320,13 @@ void Seoul::Console::_handle_input() _motherboard()->bus_input.send(msg); } - if (ev.type() == Input::Event::PRESS) { - if (ev.code() <= 0xee) { - _vkeyb.handle_keycode_press(ev.code()); - } - } - if (ev.type() == Input::Event::RELEASE) { - if (ev.code() <= 0xee) { /* keyboard event */ - _vkeyb.handle_keycode_release(ev.code()); - } - } + ev.handle_press([&] (Input::Keycode key, Genode::Codepoint) { + if (key <= 0xee) + _vkeyb.handle_keycode_press(key); }); + + ev.handle_release([&] (Input::Keycode key) { + if (key <= 0xee) + _vkeyb.handle_keycode_release(key); }); }); } diff --git a/repos/ports/src/virtualbox/frontend/console.cc b/repos/ports/src/virtualbox/frontend/console.cc index 907ec0297..0380aa100 100644 --- a/repos/ports/src/virtualbox/frontend/console.cc +++ b/repos/ports/src/virtualbox/frontend/console.cc @@ -203,18 +203,11 @@ void GenodeConsole::handle_input() if (!_vbox_keyboard || !_vbox_mouse) return; - bool const press = ev.type() == Input::Event::PRESS; - bool const release = ev.type() == Input::Event::RELEASE; - bool const key = press || release; - bool const motion = ev.type() == Input::Event::MOTION; - bool const wheel = ev.type() == Input::Event::WHEEL; - bool const touch = ev.type() == Input::Event::TOUCH; + auto keyboard_submit = [&] (Input::Keycode key, bool release) { - if (key) { - Scan_code scan_code(ev.keycode()); + Scan_code scan_code(key); - unsigned char const release_bit = - (ev.type() == Input::Event::RELEASE) ? 0x80 : 0; + unsigned char const release_bit = release ? 0x80 : 0; if (scan_code.normal()) _vbox_keyboard->PutScancode(scan_code.code() | release_bit); @@ -223,122 +216,116 @@ void GenodeConsole::handle_input() _vbox_keyboard->PutScancode(0xe0); _vbox_keyboard->PutScancode(scan_code.ext() | release_bit); } - } + }; - /* - * Track press/release status of keys and buttons. Currently, - * only the mouse-button states are actually used. - */ - if (press) - _key_status[ev.keycode()] = true; + /* obtain bit mask of currently pressed mouse buttons */ + auto curr_mouse_button_bits = [&] () { + return (_key_status[Input::BTN_LEFT] ? MouseButtonState_LeftButton : 0) + | (_key_status[Input::BTN_RIGHT] ? MouseButtonState_RightButton : 0) + | (_key_status[Input::BTN_MIDDLE] ? MouseButtonState_MiddleButton : 0); + }; - if (release) - _key_status[ev.keycode()] = false; + unsigned const old_mouse_button_bits = curr_mouse_button_bits(); - bool const mouse_button_event = - key && _mouse_button(ev.keycode()); + ev.handle_press([&] (Input::Keycode key, Genode::Codepoint) { + keyboard_submit(key, false); + _key_status[key] = true; + }); - bool const mouse_event = mouse_button_event || motion; + ev.handle_release([&] (Input::Keycode key) { + keyboard_submit(key, true); + _key_status[key] = false; + }); - if (mouse_event) { - unsigned const buttons = (_key_status[Input::BTN_LEFT] ? MouseButtonState_LeftButton : 0) - | (_key_status[Input::BTN_RIGHT] ? MouseButtonState_RightButton : 0) - | (_key_status[Input::BTN_MIDDLE] ? MouseButtonState_MiddleButton : 0); - if (ev.absolute_motion()) { + unsigned const mouse_button_bits = curr_mouse_button_bits(); - _last_received_motion_event_was_absolute = true; + if (mouse_button_bits != old_mouse_button_bits) { - /* transform absolute to relative if guest is so odd */ - if (!guest_abs && guest_rel) { - int const boundary = 20; - int rx = ev.ax() - _ax; - int ry = ev.ay() - _ay; - rx = Genode::min(boundary, Genode::max(-boundary, rx)); - ry = Genode::min(boundary, Genode::max(-boundary, ry)); - _vbox_mouse->PutMouseEvent(rx, ry, 0, 0, buttons); - } else - _vbox_mouse->PutMouseEventAbsolute(ev.ax(), ev.ay(), 0, - 0, buttons); - - _ax = ev.ax(); - _ay = ev.ay(); - - } else if (ev.relative_motion()) { - - _last_received_motion_event_was_absolute = false; - - /* prefer relative motion event */ + if (_last_received_motion_event_was_absolute) { + /* prefer absolute button event */ + if (guest_abs) + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, mouse_button_bits); + else if (guest_rel) + _vbox_mouse->PutMouseEvent(0, 0, 0, 0, mouse_button_bits); + } else { + /* prefer relative button event */ if (guest_rel) - _vbox_mouse->PutMouseEvent(ev.rx(), ev.ry(), 0, 0, buttons); - else if (guest_abs) { - _ax += ev.rx(); - _ay += ev.ry(); - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons); - } - } - /* only the buttons changed */ - else { - - if (_last_received_motion_event_was_absolute) { - /* prefer absolute button event */ - if (guest_abs) - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons); - else if (guest_rel) - _vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons); - } else { - /* prefer relative button event */ - if (guest_rel) - _vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons); - else if (guest_abs) - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons); - } - + _vbox_mouse->PutMouseEvent(0, 0, 0, 0, mouse_button_bits); + else if (guest_abs) + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, mouse_button_bits); } } - if (wheel) { + ev.handle_absolute_motion([&] (int x, int y) { + + _last_received_motion_event_was_absolute = true; + + /* transform absolute to relative if guest is so odd */ + if (!guest_abs && guest_rel) { + int const boundary = 20; + int rx = x - _ax; + int ry = y - _ay; + rx = Genode::min(boundary, Genode::max(-boundary, rx)); + ry = Genode::min(boundary, Genode::max(-boundary, ry)); + _vbox_mouse->PutMouseEvent(rx, ry, 0, 0, mouse_button_bits); + } else + _vbox_mouse->PutMouseEventAbsolute(x, y, 0, 0, mouse_button_bits); + + _ax = x; + _ay = y; + }); + + ev.handle_relative_motion([&] (int x, int y) { + + _last_received_motion_event_was_absolute = false; + + /* prefer relative motion event */ + if (guest_rel) + _vbox_mouse->PutMouseEvent(x, y, 0, 0, mouse_button_bits); + else if (guest_abs) { + _ax += x; + _ay += y; + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, mouse_button_bits); + } + }); + + ev.handle_wheel([&] (int x, int y) { + if (_last_received_motion_event_was_absolute) - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, -ev.ry(), -ev.rx(), 0); + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, -y, -x, 0); else - _vbox_mouse->PutMouseEvent(0, 0, -ev.ry(), -ev.rx(), 0); - } + _vbox_mouse->PutMouseEvent(0, 0, -y, -x, 0); + }); + + ev.handle_touch([&] (Input::Touch_id id, int x, int y) { - if (touch) { /* if multitouch queue is full - send it */ if (mt_number >= sizeof(mt_events) / sizeof(mt_events[0])) { _vbox_mouse->PutEventMultiTouch(mt_number, mt_number, - mt_events, RTTimeMilliTS()); + mt_events, RTTimeMilliTS()); mt_number = 0; } - int x = ev.ax(); - int y = ev.ay(); - int slot = ev.code(); - /* Mouse::putEventMultiTouch drops values of 0 */ if (x <= 0) x = 1; if (y <= 0) y = 1; - enum MultiTouch { - None = 0x0, - InContact = 0x01, - InRange = 0x02 - }; + enum { IN_CONTACT = 0x01, IN_RANGE = 0x02 }; - int status = MultiTouch::InContact | MultiTouch::InRange; - if (ev.touch_release()) - status = MultiTouch::None; - - uint16_t const s = RT_MAKE_U16(slot, status); + uint16_t const s = RT_MAKE_U16(id.value, IN_CONTACT | IN_RANGE); mt_events[mt_number++] = RT_MAKE_U64_FROM_U16(x, y, s, 0); - } + }); + ev.handle_touch_release([&] (Input::Touch_id id) { + uint16_t const s = RT_MAKE_U16(id.value, 0); + mt_events[mt_number++] = RT_MAKE_U64_FROM_U16(0, 0, s, 0); + }); }); - /* if there are elements - send it */ + /* if there are elements in multi-touch queue - send it */ if (mt_number) _vbox_mouse->PutEventMultiTouch(mt_number, mt_number, mt_events, - RTTimeMilliTS()); + RTTimeMilliTS()); } void GenodeConsole::handle_mode_change() diff --git a/repos/ports/src/virtualbox5/frontend/console.cc b/repos/ports/src/virtualbox5/frontend/console.cc index a033f12a1..89e0acb3e 100644 --- a/repos/ports/src/virtualbox5/frontend/console.cc +++ b/repos/ports/src/virtualbox5/frontend/console.cc @@ -148,18 +148,11 @@ void GenodeConsole::handle_input() if (!_vbox_keyboard || !_vbox_mouse) return; - bool const press = ev.type() == Input::Event::PRESS; - bool const release = ev.type() == Input::Event::RELEASE; - bool const key = press || release; - bool const motion = ev.type() == Input::Event::MOTION; - bool const wheel = ev.type() == Input::Event::WHEEL; - bool const touch = ev.type() == Input::Event::TOUCH; + auto keyboard_submit = [&] (Input::Keycode key, bool release) { - if (key) { - Scan_code scan_code(ev.keycode()); + Scan_code scan_code(key); - unsigned char const release_bit = - (ev.type() == Input::Event::RELEASE) ? 0x80 : 0; + unsigned char const release_bit = release ? 0x80 : 0; if (scan_code.normal()) _vbox_keyboard->PutScancode(scan_code.code() | release_bit); @@ -168,122 +161,116 @@ void GenodeConsole::handle_input() _vbox_keyboard->PutScancode(0xe0); _vbox_keyboard->PutScancode(scan_code.ext() | release_bit); } - } + }; - /* - * Track press/release status of keys and buttons. Currently, - * only the mouse-button states are actually used. - */ - if (press) - _key_status[ev.keycode()] = true; + /* obtain bit mask of currently pressed mouse buttons */ + auto curr_mouse_button_bits = [&] () { + return (_key_status[Input::BTN_LEFT] ? MouseButtonState_LeftButton : 0) + | (_key_status[Input::BTN_RIGHT] ? MouseButtonState_RightButton : 0) + | (_key_status[Input::BTN_MIDDLE] ? MouseButtonState_MiddleButton : 0); + }; - if (release) - _key_status[ev.keycode()] = false; + unsigned const old_mouse_button_bits = curr_mouse_button_bits(); - bool const mouse_button_event = - key && _mouse_button(ev.keycode()); + ev.handle_press([&] (Input::Keycode key, Genode::Codepoint) { + keyboard_submit(key, false); + _key_status[key] = true; + }); - bool const mouse_event = mouse_button_event || motion; + ev.handle_release([&] (Input::Keycode key) { + keyboard_submit(key, true); + _key_status[key] = false; + }); - if (mouse_event) { - unsigned const buttons = (_key_status[Input::BTN_LEFT] ? MouseButtonState_LeftButton : 0) - | (_key_status[Input::BTN_RIGHT] ? MouseButtonState_RightButton : 0) - | (_key_status[Input::BTN_MIDDLE] ? MouseButtonState_MiddleButton : 0); - if (ev.absolute_motion()) { + unsigned const mouse_button_bits = curr_mouse_button_bits(); - _last_received_motion_event_was_absolute = true; + if (mouse_button_bits != old_mouse_button_bits) { - /* transform absolute to relative if guest is so odd */ - if (!guest_abs && guest_rel) { - int const boundary = 20; - int rx = ev.ax() - _ax; - int ry = ev.ay() - _ay; - rx = Genode::min(boundary, Genode::max(-boundary, rx)); - ry = Genode::min(boundary, Genode::max(-boundary, ry)); - _vbox_mouse->PutMouseEvent(rx, ry, 0, 0, buttons); - } else - _vbox_mouse->PutMouseEventAbsolute(ev.ax(), ev.ay(), 0, - 0, buttons); - - _ax = ev.ax(); - _ay = ev.ay(); - - } else if (ev.relative_motion()) { - - _last_received_motion_event_was_absolute = false; - - /* prefer relative motion event */ + if (_last_received_motion_event_was_absolute) { + /* prefer absolute button event */ + if (guest_abs) + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, mouse_button_bits); + else if (guest_rel) + _vbox_mouse->PutMouseEvent(0, 0, 0, 0, mouse_button_bits); + } else { + /* prefer relative button event */ if (guest_rel) - _vbox_mouse->PutMouseEvent(ev.rx(), ev.ry(), 0, 0, buttons); - else if (guest_abs) { - _ax += ev.rx(); - _ay += ev.ry(); - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons); - } - } - /* only the buttons changed */ - else { - - if (_last_received_motion_event_was_absolute) { - /* prefer absolute button event */ - if (guest_abs) - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons); - else if (guest_rel) - _vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons); - } else { - /* prefer relative button event */ - if (guest_rel) - _vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons); - else if (guest_abs) - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons); - } - + _vbox_mouse->PutMouseEvent(0, 0, 0, 0, mouse_button_bits); + else if (guest_abs) + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, mouse_button_bits); } } - if (wheel) { + ev.handle_absolute_motion([&] (int x, int y) { + + _last_received_motion_event_was_absolute = true; + + /* transform absolute to relative if guest is so odd */ + if (!guest_abs && guest_rel) { + int const boundary = 20; + int rx = x - _ax; + int ry = y - _ay; + rx = Genode::min(boundary, Genode::max(-boundary, rx)); + ry = Genode::min(boundary, Genode::max(-boundary, ry)); + _vbox_mouse->PutMouseEvent(rx, ry, 0, 0, mouse_button_bits); + } else + _vbox_mouse->PutMouseEventAbsolute(x, y, 0, 0, mouse_button_bits); + + _ax = x; + _ay = y; + }); + + ev.handle_relative_motion([&] (int x, int y) { + + _last_received_motion_event_was_absolute = false; + + /* prefer relative motion event */ + if (guest_rel) + _vbox_mouse->PutMouseEvent(x, y, 0, 0, mouse_button_bits); + else if (guest_abs) { + _ax += x; + _ay += y; + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, mouse_button_bits); + } + }); + + ev.handle_wheel([&] (int x, int y) { + if (_last_received_motion_event_was_absolute) - _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, -ev.ry(), -ev.rx(), 0); + _vbox_mouse->PutMouseEventAbsolute(_ax, _ay, -y, -x, 0); else - _vbox_mouse->PutMouseEvent(0, 0, -ev.ry(), -ev.rx(), 0); - } + _vbox_mouse->PutMouseEvent(0, 0, -y, -x, 0); + }); + + ev.handle_touch([&] (Input::Touch_id id, int x, int y) { - if (touch) { /* if multitouch queue is full - send it */ if (mt_number >= sizeof(mt_events) / sizeof(mt_events[0])) { _vbox_mouse->PutEventMultiTouch(mt_number, mt_number, - mt_events, RTTimeMilliTS()); + mt_events, RTTimeMilliTS()); mt_number = 0; } - int x = ev.ax(); - int y = ev.ay(); - int slot = ev.code(); - /* Mouse::putEventMultiTouch drops values of 0 */ if (x <= 0) x = 1; if (y <= 0) y = 1; - enum MultiTouch { - None = 0x0, - InContact = 0x01, - InRange = 0x02 - }; + enum { IN_CONTACT = 0x01, IN_RANGE = 0x02 }; - int status = MultiTouch::InContact | MultiTouch::InRange; - if (ev.touch_release()) - status = MultiTouch::None; - - uint16_t const s = RT_MAKE_U16(slot, status); + uint16_t const s = RT_MAKE_U16(id.value, IN_CONTACT | IN_RANGE); mt_events[mt_number++] = RT_MAKE_U64_FROM_U16(x, y, s, 0); - } + }); + ev.handle_touch_release([&] (Input::Touch_id id) { + uint16_t const s = RT_MAKE_U16(id.value, 0); + mt_events[mt_number++] = RT_MAKE_U64_FROM_U16(0, 0, s, 0); + }); }); - /* if there are elements - send it */ + /* if there are elements in multi-touch queue - send it */ if (mt_number) _vbox_mouse->PutEventMultiTouch(mt_number, mt_number, mt_events, - RTTimeMilliTS()); + RTTimeMilliTS()); } void GenodeConsole::handle_mode_change()