From 4eebd140b0bc6e49fc7bdfad7b5c35434a68f300 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 27 Oct 2017 12:14:48 +0200 Subject: [PATCH] nitpicker: report current key state Fixes #2552 --- repos/os/src/server/nitpicker/README | 1 + repos/os/src/server/nitpicker/main.cc | 28 ++++++++++++++--- repos/os/src/server/nitpicker/mode.h | 2 +- repos/os/src/server/nitpicker/user_state.cc | 26 ++++++++++++++-- repos/os/src/server/nitpicker/user_state.h | 34 +++++++++++++++++++++ 5 files changed, 82 insertions(+), 9 deletions(-) diff --git a/repos/os/src/server/nitpicker/README b/repos/os/src/server/nitpicker/README index 95daa9a343..6de5a58966 100644 --- a/repos/os/src/server/nitpicker/README +++ b/repos/os/src/server/nitpicker/README @@ -213,3 +213,4 @@ The 'hover' attribute enables the reporting of the currently hovered session. The 'focus' attribute enables the reporting of the currently focused session. The 'pointer' attribute enables the reporting of the current absolute pointer position. +The 'keystate' attribute enables the reporting of the currently pressed keys. diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index b8d8f4041f..c00377c18c 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -1179,9 +1179,10 @@ struct Nitpicker::Main */ Genode::Sliced_heap sliced_heap { env.ram(), env.rm() }; - Genode::Reporter pointer_reporter = { env, "pointer" }; - Genode::Reporter hover_reporter = { env, "hover" }; - Genode::Reporter focus_reporter = { env, "focus" }; + Genode::Reporter pointer_reporter = { env, "pointer" }; + Genode::Reporter hover_reporter = { env, "hover" }; + Genode::Reporter focus_reporter = { env, "focus" }; + Genode::Reporter keystate_reporter = { env, "keystate" }; Genode::Attached_rom_dataspace config { env, "config" }; @@ -1273,11 +1274,28 @@ void Nitpicker::Main::handle_input() bool const old_user_active = user_active; /* handle batch of pending events */ - if (import_input_events(ev_buf, input.flush(), user_state)) { + unsigned const num_events = input.flush(); + if (import_input_events(ev_buf, num_events, user_state)) { last_active_period = period_cnt; user_active = true; } + /* + * Report information about currently pressed keys whenever the key state + * is affected by the incoming events. + */ + if (keystate_reporter.enabled()) { + + bool key_state_affected = false; + for (unsigned i = 0; i < num_events; i++) + key_state_affected |= (ev_buf[i].type() == Input::Event::PRESS) || + (ev_buf[i].type() == Input::Event::RELEASE); + + if (key_state_affected) + Genode::Reporter::Xml_generator xml(keystate_reporter, [&] () { + user_state.report_keystate(xml); }); + } + user_state.Mode::apply_pending_focus_change(); Point const new_pointer_pos = user_state.pointer_pos(); @@ -1293,7 +1311,6 @@ void Nitpicker::Main::handle_input() /* report mouse-position updates */ if (pointer_reporter.enabled() && old_pointer_pos != new_pointer_pos) { - Genode::Reporter::Xml_generator xml(pointer_reporter, [&] () { xml.attribute("xpos", new_pointer_pos.x()); @@ -1364,6 +1381,7 @@ void Nitpicker::Main::handle_config() configure_reporter(config.xml(), pointer_reporter); configure_reporter(config.xml(), hover_reporter); configure_reporter(config.xml(), focus_reporter); + configure_reporter(config.xml(), keystate_reporter); /* update domain registry and session policies */ for (::Session *s = session_list.first(); s; s = s->next()) diff --git a/repos/os/src/server/nitpicker/mode.h b/repos/os/src/server/nitpicker/mode.h index 01b8a5b497..1418301586 100644 --- a/repos/os/src/server/nitpicker/mode.h +++ b/repos/os/src/server/nitpicker/mode.h @@ -49,7 +49,7 @@ class Mode void inc_key_cnt() { _key_cnt++; } void dec_key_cnt() { _key_cnt--; } - bool has_key_cnt(unsigned cnt) const { return cnt == _key_cnt; } + unsigned key_cnt() const { return _key_cnt; } bool key_pressed() const { return _key_cnt > 0; } diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index d9d0b16dfc..cbe4c634f2 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -87,6 +87,19 @@ void User_state::handle_event(Input::Event ev) if (type == Event::PRESS) Mode::inc_key_cnt(); if (type == Event::RELEASE && Mode::drag()) Mode::dec_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); + } + + if (type == Event::RELEASE) { + if (!_key_array.pressed(keycode)) + Genode::warning("suspicious double release of ", Input::key_name(keycode)); + _key_array.pressed(keycode, false); + } + View const * const pointed_view = find_view(_pointer_pos); ::Session * const pointed_session = pointed_view ? &pointed_view->session() : 0; @@ -123,7 +136,7 @@ void User_state::handle_event(Input::Event ev) /* * Handle start of a key sequence */ - if (type == Event::PRESS && Mode::has_key_cnt(1)) { + if (type == Event::PRESS && (Mode::key_cnt() == 1)) { ::Session *global_receiver = nullptr; @@ -188,7 +201,7 @@ void User_state::handle_event(Input::Event ev) */ if (type == Event::MOTION || type == Event::WHEEL || type == Event::TOUCH) { - if (Mode::has_key_cnt(0)) { + if (Mode::key_cnt() == 0) { if (_pointed_session) { @@ -232,7 +245,7 @@ void User_state::handle_event(Input::Event ev) /* * Detect end of global key sequence */ - if (ev.type() == Event::RELEASE && Mode::has_key_cnt(0) && _global_key_sequence) { + if (ev.type() == Event::RELEASE && (Mode::key_cnt() == 0) && _global_key_sequence) { _input_receiver = Mode::focused_session(); @@ -243,6 +256,13 @@ void User_state::handle_event(Input::Event ev) } +void User_state::report_keystate(Genode::Xml_generator &xml) +{ + xml.attribute("count", Mode::key_cnt()); + _key_array.report_state(xml); +} + + /******************** ** Mode interface ** ********************/ diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index cbfbc1a587..4a59edc5ce 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -18,6 +18,8 @@ #ifndef _USER_STATE_H_ #define _USER_STATE_H_ +#include + #include "mode.h" #include "view_stack.h" #include "global_keys.h" @@ -48,6 +50,36 @@ class User_state : public Mode, public View_stack void _update_all(); + /** + * Array for tracking the state of each key + */ + struct Key_array + { + struct State { bool pressed = false; }; + + State _states[Input::KEY_MAX + 1]; + + void pressed(Input::Keycode key, bool pressed) + { + if (key <= Input::KEY_MAX) + _states[key].pressed = pressed; + } + + bool pressed(Input::Keycode key) const + { + return (key <= Input::KEY_MAX) && _states[key].pressed; + } + + void report_state(Genode::Xml_generator &xml) const + { + for (unsigned i = 0; i <= Input::KEY_MAX; i++) + if (_states[i].pressed) + xml.node("pressed", [&] () { + xml.attribute("key", Input::key_name((Input::Keycode)i)); }); + } + + } _key_array; + public: /** @@ -63,6 +95,8 @@ class User_state : public Mode, public View_stack */ void handle_event(Input::Event ev); + void report_keystate(Genode::Xml_generator &); + /** * Accessors */