nitpicker: equip hover report with 'active' info

This patch supplements the existing 'hover' report with the information
whether or not the user has recently moved the pointer. This works
analogously to how the 'focus' report features the information about
recent button/keyboard activity.

Together, the 'hover' and 'focus' reports may be combined to observe
prolonged user inactivity, e.g. to activate a lock screen.
This commit is contained in:
Norman Feske 2017-11-20 20:23:41 +01:00 committed by Christian Helmuth
parent 544274feb9
commit b05ad847b9
3 changed files with 50 additions and 32 deletions

View File

@ -323,7 +323,8 @@ struct Nitpicker::Main : Focus_updater
/**
* Period counter when the user was active the last time
*/
unsigned _last_active_period = 0;
unsigned _last_button_activity_period = 0,
_last_motion_activity_period = 0;
/**
* Number of periods after the last user activity when we regard the user
@ -332,12 +333,17 @@ struct Nitpicker::Main : Focus_updater
unsigned _activity_threshold = 50;
/**
* True if the user was recently active
* True if the user has recently interacted with buttons or keys
*
* This state is reported as part of focus reports to allow the clipboard
* to dynamically adjust its information-flow policy to the user activity.
*/
bool _user_active = false;
bool _button_activity = false;
/**
* True if the user recently moved the pointer
*/
bool _motion_activity = false;
/**
* Perform redraw and flush pixels to the framebuffer
@ -370,16 +376,22 @@ void Nitpicker::Main::_handle_input()
{
_period_cnt++;
bool const old_user_active = _user_active;
bool const old_button_activity = _button_activity;
bool const old_motion_activity = _motion_activity;
/* handle batch of pending events */
User_state::Handle_input_result const result =
_user_state.handle_input_events(_ev_ds.local_addr<Input::Event>(),
_input.flush());
if (result.user_active) {
_last_active_period = _period_cnt;
_user_active = true;
if (result.button_activity) {
_last_button_activity_period = _period_cnt;
_button_activity = true;
}
if (result.motion_activity) {
_last_motion_activity_period = _period_cnt;
_motion_activity = true;
}
/*
@ -404,29 +416,33 @@ void Nitpicker::Main::_handle_input()
_view_stack.update_all_views();
/* flag user as inactive after activity threshold is reached */
if (_period_cnt == _last_active_period + _activity_threshold)
_user_active = false;
if (_period_cnt == _last_button_activity_period + _activity_threshold)
_button_activity = false;
if (_period_cnt == _last_motion_activity_period + _activity_threshold)
_motion_activity = false;
/* report mouse-position updates */
if (_pointer_reporter.enabled() && result.pointer_position_changed) {
if (_pointer_reporter.enabled() && result.motion_activity) {
Reporter::Xml_generator xml(_pointer_reporter, [&] () {
_user_state.report_pointer_position(xml); });
}
/* report hover changes */
if (_hover_reporter.enabled() && !result.key_pressed && result.hover_changed) {
if (_hover_reporter.enabled() && !result.key_pressed
&& (result.hover_changed || (old_motion_activity != _motion_activity))) {
Reporter::Xml_generator xml(_hover_reporter, [&] () {
_user_state.report_hovered_view_owner(xml); });
_user_state.report_hovered_view_owner(xml, _motion_activity); });
}
/* report focus changes */
if (result.focus_changed || (old_user_active != _user_active)) {
if (result.focus_changed || (old_button_activity != _button_activity)) {
Reporter::Xml_generator xml(_focus_reporter, [&] () {
_user_state.report_focused_view_owner(xml, _user_active); });
_user_state.report_focused_view_owner(xml, _button_activity); });
}
/* update pointer position */
if (result.pointer_position_changed)
if (result.motion_activity)
_view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area()));
/* perform redraw and flush pixels to the framebuffer */
@ -539,7 +555,7 @@ void Nitpicker::Main::_handle_config()
/* update focus report since the domain colors might have changed */
Reporter::Xml_generator xml(_focus_reporter, [&] () {
_user_state.report_focused_view_owner(xml, _user_active); });
_user_state.report_focused_view_owner(xml, _button_activity); });
}

View File

@ -287,7 +287,7 @@ User_state::handle_input_events(Input::Event const * const ev_buf,
View_owner const * const old_input_receiver = _input_receiver;
View_owner const * const old_last_clicked = _last_clicked;
bool user_active = false;
bool button_activity = false;
if (num_ev > 0) {
/*
@ -320,7 +320,7 @@ User_state::handle_input_events(Input::Event const * const ev_buf,
* we regard the user as active. This check captures the presence
* of press-release combinations within one batch of input events.
*/
user_active |= _key_pressed();
button_activity |= _key_pressed();
/* pass event to user state */
_handle_input_event(curr);
@ -337,7 +337,7 @@ User_state::handle_input_events(Input::Event const * const ev_buf,
/*
* If at least one key is kept pressed, we regard the user as active.
*/
user_active |= _key_pressed();
button_activity |= _key_pressed();
bool key_state_affected = false;
for (unsigned i = 0; i < num_ev; i++)
@ -347,14 +347,14 @@ User_state::handle_input_events(Input::Event const * const ev_buf,
_apply_pending_focus_change();
return {
.pointer_position_changed = _pointer_pos != old_pointer_pos,
.hover_changed = _hovered != old_hovered,
.focus_changed = (_focused != old_focused) ||
(_input_receiver != old_input_receiver),
.key_state_affected = key_state_affected,
.user_active = user_active,
.key_pressed = _key_pressed(),
.last_clicked_changed = (_last_clicked != old_last_clicked)
.hover_changed = _hovered != old_hovered,
.focus_changed = (_focused != old_focused) ||
(_input_receiver != old_input_receiver),
.key_state_affected = key_state_affected,
.button_activity = button_activity,
.motion_activity = (_pointer_pos != old_pointer_pos),
.key_pressed = _key_pressed(),
.last_clicked_changed = (_last_clicked != old_last_clicked)
};
}
@ -373,10 +373,12 @@ void User_state::report_pointer_position(Xml_generator &xml) const
}
void User_state::report_hovered_view_owner(Xml_generator &xml) const
void User_state::report_hovered_view_owner(Xml_generator &xml, bool active) const
{
if (_hovered)
_hovered->report(xml);
if (active) xml.attribute("active", "yes");
}

View File

@ -196,11 +196,11 @@ class Nitpicker::User_state : public Focus_controller
struct Handle_input_result
{
bool const pointer_position_changed;
bool const hover_changed;
bool const focus_changed;
bool const key_state_affected;
bool const user_active;
bool const button_activity;
bool const motion_activity;
bool const key_pressed;
bool const last_clicked_changed;
};
@ -215,8 +215,8 @@ class Nitpicker::User_state : public Focus_controller
void report_keystate(Xml_generator &) const;
void report_pointer_position(Xml_generator &) const;
void report_hovered_view_owner(Xml_generator &) const;
void report_focused_view_owner(Xml_generator &, bool user_active) const;
void report_hovered_view_owner(Xml_generator &, bool motion_active) const;
void report_focused_view_owner(Xml_generator &, bool button_active) const;
void report_last_clicked_view_owner(Xml_generator &) const;
Point pointer_pos() { return _pointer_pos; }