diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 6b24c9b5f..e398156c7 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -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.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); }); } diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 0d942073a..7aad35538 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -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"); } diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index becc1a1fb..9d9ba3ca1 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -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; }