diff --git a/repos/os/src/server/nitpicker/focus.h b/repos/os/src/server/nitpicker/focus.h index 22eff0842e..6aad016bb9 100644 --- a/repos/os/src/server/nitpicker/focus.h +++ b/repos/os/src/server/nitpicker/focus.h @@ -20,6 +20,7 @@ namespace Nitpicker { struct Focus; struct Focus_updater : Interface { virtual void update_focus() = 0; }; + struct Hover_updater : Interface { virtual void update_hover() = 0; }; } diff --git a/repos/os/src/server/nitpicker/gui_session.cc b/repos/os/src/server/nitpicker/gui_session.cc index 85217edae5..5d51bfd21e 100644 --- a/repos/os/src/server/nitpicker/gui_session.cc +++ b/repos/os/src/server/nitpicker/gui_session.cc @@ -337,6 +337,8 @@ void Gui_session::destroy_view(View_handle handle) break; } } + + _hover_updater.update_hover(); } @@ -386,6 +388,7 @@ void Gui_session::execute() catch (View_handle_registry::Lookup_failed) { warning("view lookup failed during command execution"); } } + _hover_updater.update_hover(); } @@ -446,6 +449,8 @@ void Gui_session::session_control(Label suffix, Session_control control) _view_stack.to_front(Label(label(), suffix).string()); break; } + + _hover_updater.update_hover(); } diff --git a/repos/os/src/server/nitpicker/gui_session.h b/repos/os/src/server/nitpicker/gui_session.h index bac1fdb037..25c4cd3bae 100644 --- a/repos/os/src/server/nitpicker/gui_session.h +++ b/repos/os/src/server/nitpicker/gui_session.h @@ -104,6 +104,7 @@ class Nitpicker::Gui_session : public Session_object, View_stack &_view_stack; Focus_updater &_focus_updater; + Hover_updater &_hover_updater; Signal_context_capability _mode_sigh { }; @@ -174,6 +175,7 @@ class Nitpicker::Gui_session : public Session_object, Diag const &diag, View_stack &view_stack, Focus_updater &focus_updater, + Hover_updater &hover_updater, View &pointer_origin, View &builtin_background, bool provides_default_bg, @@ -185,7 +187,8 @@ class Nitpicker::Gui_session : public Session_object, _ram(env.ram(), _ram_quota_guard(), _cap_quota_guard()), _session_alloc(_ram, env.rm()), _framebuffer_session_component(view_stack, *this, *this), - _view_stack(view_stack), _focus_updater(focus_updater), + _view_stack(view_stack), + _focus_updater(focus_updater), _hover_updater(hover_updater), _pointer_origin(pointer_origin), _builtin_background(builtin_background), _framebuffer_session_cap(_env.ep().manage(_framebuffer_session_component)), diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 558f99884b..3402b48705 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -83,6 +83,7 @@ class Nitpicker::Gui_root : public Root_component, Reporter &_focus_reporter; Reporter &_hover_reporter; Focus_updater &_focus_updater; + Hover_updater &_hover_updater; protected: @@ -95,8 +96,8 @@ class Nitpicker::Gui_root : public Root_component, Gui_session *session = new (md_alloc()) Gui_session(_env, session_resources_from_args(args), label, - session_diag_from_args(args), - _view_stack, _focus_updater, _pointer_origin, + session_diag_from_args(args), _view_stack, + _focus_updater, _hover_updater, _pointer_origin, _builtin_background, provides_default_bg, _focus_reporter, *this); @@ -104,6 +105,7 @@ class Nitpicker::Gui_root : public Root_component, _session_list.insert(session); _global_keys.apply_config(_config.xml(), _session_list); _focus_updater.update_focus(); + _hover_updater.update_hover(); return session; } @@ -128,11 +130,8 @@ class Nitpicker::Gui_root : public Root_component, Genode::destroy(md_alloc(), session); - /* report hover changes */ - if (_hover_reporter.enabled() && result.hover_changed) { - Reporter::Xml_generator xml(_hover_reporter, [&] () { - _user_state.report_hovered_view_owner(xml, false); }); - } + if (result.hover_changed) + _hover_updater.update_hover(); /* report focus changes */ if (_focus_reporter.enabled() && result.focus_changed) { @@ -158,7 +157,8 @@ class Nitpicker::Gui_root : public Root_component, Allocator &md_alloc, Reporter &focus_reporter, Reporter &hover_reporter, - Focus_updater &focus_updater) + Focus_updater &focus_updater, + Hover_updater &hover_updater) : Root_component(&env.ep().rpc_ep(), &md_alloc), _env(env), _config(config), _session_list(session_list), @@ -167,7 +167,7 @@ class Nitpicker::Gui_root : public Root_component, _pointer_origin(pointer_origin), _builtin_background(builtin_background), _focus_reporter(focus_reporter), _hover_reporter(hover_reporter), - _focus_updater(focus_updater) + _focus_updater(focus_updater), _hover_updater(hover_updater) { } @@ -343,7 +343,7 @@ class Nitpicker::Event_root : public Root_component }; -struct Nitpicker::Main : Focus_updater, +struct Nitpicker::Main : Focus_updater, Hover_updater, View_stack::Damage, Capture_session::Handler, Event_session::Handler @@ -467,12 +467,20 @@ struct Nitpicker::Main : Focus_updater, Gui_root _gui_root { _env, _config_rom, _session_list, *_domain_registry, _global_keys, _view_stack, _user_state, _pointer_origin, _builtin_background, _sliced_heap, - _focus_reporter, _hover_reporter, *this }; + _focus_reporter, _hover_reporter, *this, *this }; Capture_root _capture_root { _env, _sliced_heap, _view_stack, *this }; Event_root _event_root { _env, _sliced_heap, *this }; + void _generate_hover_report() + { + if (_hover_reporter.enabled()) { + Reporter::Xml_generator xml(_hover_reporter, [&] () { + _user_state.report_hovered_view_owner(xml, false); }); + } + } + /** * View_stack::Damage interface */ @@ -536,6 +544,17 @@ struct Nitpicker::Main : Focus_updater, */ void update_focus() override { _handle_focus(); } + /** + * Hover_updater interface + * + * Called whenever the view composition changes. + */ + void update_hover() override + { + if (_user_state.update_hover().hover_changed) + _generate_hover_report(); + } + /* * Configuration-update handler, executed in the context of the RPC * entrypoint. diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 41741b1c3c..f681036887 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -124,23 +124,8 @@ void User_state::_handle_input_event(Input::Event ev) _key_array.pressed(key, false); }); - View const * const pointed_view = _view_stack.find_view(_pointer_pos); - - View_owner * const hovered = pointed_view ? &pointed_view->owner() : 0; - - /* - * Deliver a leave event if pointed-to session changed, notify newly - * hovered session about the current pointer position. - */ - if (hovered != _hovered) { - if (_hovered) - _hovered->submit_input_event(Hover_leave()); - - if (hovered && _key_cnt == 0) - hovered->submit_input_event(Absolute_motion{_pointer_pos.x(), - _pointer_pos.y()}); - _hovered = hovered; - } + if (ev.absolute_motion() || ev.relative_motion()) + update_hover(); /* * Handle start of a key sequence @@ -411,17 +396,13 @@ User_state::Handle_forget_result User_state::forget(View_owner const &owner) _focus.forget(owner); bool const need_to_update_all_views = (&owner == _focused); - bool const hover_changed = &owner == _hovered; bool const focus_changed = &owner == _focused; if (&owner == _focused) _focused = nullptr; if (&owner == _next_focused) _next_focused = nullptr; if (&owner == _last_clicked) _last_clicked = nullptr; - if (_hovered == &owner) { - View * const pointed_view = _view_stack.find_view(_pointer_pos); - _hovered = pointed_view ? &pointed_view->owner() : nullptr; - } + Update_hover_result const update_hover_result = update_hover(); if (_input_receiver == &owner) _input_receiver = nullptr; @@ -430,12 +411,36 @@ User_state::Handle_forget_result User_state::forget(View_owner const &owner) _view_stack.update_all_views(); return { - .hover_changed = hover_changed, + .hover_changed = update_hover_result.hover_changed, .focus_changed = focus_changed, }; } +User_state::Update_hover_result User_state::update_hover() +{ + View_owner * const old_hovered = _hovered; + View const * const pointed_view = _view_stack.find_view(_pointer_pos); + + _hovered = pointed_view ? &pointed_view->owner() : nullptr; + + /* + * Deliver a leave event if pointed-to session changed, notify newly + * hovered session about the current pointer position. + */ + if (old_hovered != _hovered) { + if (old_hovered) + old_hovered->submit_input_event(Hover_leave()); + + if (_hovered && _key_cnt == 0) + _hovered->submit_input_event(Absolute_motion{_pointer_pos.x(), + _pointer_pos.y()}); + } + + return { .hover_changed = (_hovered != old_hovered) }; +} + + void User_state::_focus_view_owner_via_click(View_owner &owner) { _next_focused = &owner; diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index e0873c09b2..a462cf4b69 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -252,8 +252,13 @@ class Nitpicker::User_state bool const hover_changed; bool const focus_changed; }; + Handle_forget_result forget(View_owner const &); + struct Update_hover_result { bool const hover_changed; }; + + Update_hover_result update_hover(); + void report_keystate(Xml_generator &) const; void report_pointer_position(Xml_generator &) const; void report_hovered_view_owner(Xml_generator &, bool motion_active) const;