nitpicker: report current key state

Fixes #2552
This commit is contained in:
Norman Feske 2017-10-27 12:14:48 +02:00 committed by Christian Helmuth
parent 547cc06976
commit 4eebd140b0
5 changed files with 82 additions and 9 deletions

View File

@ -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.

View File

@ -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())

View File

@ -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; }

View File

@ -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 **
********************/

View File

@ -18,6 +18,8 @@
#ifndef _USER_STATE_H_
#define _USER_STATE_H_
#include <util/xml_generator.h>
#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
*/