mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
nitpicker: update hovering on view-stack changes
With the change of nitpicker to the event session interface, the formerly periodic hovering updates moved to the - now sporadic - input processing. This has the unfortunate side effect that hovering changes caused by non-user-input, in particular view-stack changes issued by the GUI clients that change the view under the current pointer position, would no longer be reported immediately but only after receiving the next incoming input event. This patch reworks the hover handling such that potential hovering changes due to view-stack operations are evaluated immediately by those operations, covering the update of the hover report and the generation of artificial enter/motion events. Issue #3812
This commit is contained in:
parent
ff82dc1ad5
commit
328a4fa644
@ -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; };
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -104,6 +104,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
||||
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<Gui::Session>,
|
||||
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<Gui::Session>,
|
||||
_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)),
|
||||
|
@ -83,6 +83,7 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>,
|
||||
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>,
|
||||
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<Gui_session>,
|
||||
_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<Gui_session>,
|
||||
|
||||
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<Gui_session>,
|
||||
Allocator &md_alloc,
|
||||
Reporter &focus_reporter,
|
||||
Reporter &hover_reporter,
|
||||
Focus_updater &focus_updater)
|
||||
Focus_updater &focus_updater,
|
||||
Hover_updater &hover_updater)
|
||||
:
|
||||
Root_component<Gui_session>(&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<Gui_session>,
|
||||
_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<Event_session>
|
||||
};
|
||||
|
||||
|
||||
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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user