From 92227df62428df658d877c9213a46a6410acf483 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Sun, 6 Oct 2024 14:00:48 +0200 Subject: [PATCH] nitpicker: handle Input::Session::exclusive While the focused client has enabled exclusive input, nitpicker does not translate relative motion to absolute motion but routes relative motion directly to the client. Additionally, the pointer origin is forcibly moved to a position outside the screen boundaries, making the pointer invisible. Issue #5355 --- repos/os/src/server/nitpicker/gui_session.h | 25 +++++++++- repos/os/src/server/nitpicker/input_session.h | 16 ++++-- repos/os/src/server/nitpicker/main.cc | 21 ++++++++ repos/os/src/server/nitpicker/user_state.cc | 50 ++++++++++--------- repos/os/src/server/nitpicker/user_state.h | 6 +++ repos/os/src/server/nitpicker/view_owner.h | 2 + 6 files changed, 92 insertions(+), 28 deletions(-) diff --git a/repos/os/src/server/nitpicker/gui_session.h b/repos/os/src/server/nitpicker/gui_session.h index ea653f03ed..a1e2caa09c 100644 --- a/repos/os/src/server/nitpicker/gui_session.h +++ b/repos/os/src/server/nitpicker/gui_session.h @@ -44,7 +44,8 @@ class Nitpicker::Gui_session : public Session_object, public View_owner, public Buffer_provider, private Session_list::Element, - private Dynamic_rom_session::Xml_producer + private Dynamic_rom_session::Xml_producer, + private Input::Session_component::Action { public: @@ -54,6 +55,8 @@ class Nitpicker::Gui_session : public Session_object, * \param rect domain-specific panorama rectangle */ virtual void gen_capture_info(Xml_generator &xml, Rect rect) const = 0; + + virtual void exclusive_input_changed() = 0; }; private: @@ -116,7 +119,7 @@ class Nitpicker::Gui_session : public Session_object, bool const _input_session_accounted = ( withdraw(Ram_quota{Input::Session_component::ev_ds_size()}), true ); - Input::Session_component _input_session_component { _env }; + Input::Session_component _input_session_component { _env, *this }; View_stack &_view_stack; @@ -201,6 +204,19 @@ class Nitpicker::Gui_session : public Session_object, */ void produce_xml(Xml_generator &) override; + bool _exclusive_input_requested = false; + + /** + * Input::Session_component::Action interface + */ + void exclusive_input_requested(bool const requested) override + { + bool const orig = _exclusive_input_requested; + _exclusive_input_requested = requested; + if (orig != requested) + _action.exclusive_input_changed(); + } + public: Gui_session(Env &env, @@ -318,6 +334,11 @@ class Nitpicker::Gui_session : public Session_object, void submit_input_event(Input::Event e) override; + bool exclusive_input_requested() const override + { + return _exclusive_input_requested; + } + void report(Xml_generator &xml) const override { xml.attribute("label", _label); diff --git a/repos/os/src/server/nitpicker/input_session.h b/repos/os/src/server/nitpicker/input_session.h index da940e79ab..796d06686d 100644 --- a/repos/os/src/server/nitpicker/input_session.h +++ b/repos/os/src/server/nitpicker/input_session.h @@ -32,6 +32,11 @@ class Input::Session_component : public Rpc_object { public: + struct Action : Interface + { + virtual void exclusive_input_requested(bool) = 0; + }; + enum { MAX_EVENTS = 200 }; static size_t ev_ds_size() { @@ -40,6 +45,7 @@ class Input::Session_component : public Rpc_object private: Entrypoint &_ep; + Action &_action; /* * Exported event buffer dataspace @@ -58,9 +64,10 @@ class Input::Session_component : public Rpc_object public: - Session_component(Env &env) + Session_component(Env &env, Action &action) : - _ep(env.ep()), _ev_ram_ds(env.ram(), env.rm(), ev_ds_size()) + _ep(env.ep()), _action(action), + _ev_ram_ds(env.ram(), env.rm(), ev_ds_size()) { _ep.manage(*this); } @@ -114,7 +121,10 @@ class Input::Session_component : public Rpc_object void sigh(Signal_context_capability sigh) override { _sigh = sigh; } - void exclusive(bool) override { } + void exclusive(bool requested) override + { + _action.exclusive_input_requested(requested); + } }; #endif /* _INPUT_SESSION_COMPONENT_H_ */ diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 1706852412..acd52b554f 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -760,6 +760,22 @@ struct Nitpicker::Main : Focus_updater, Hover_updater, capture_buffer_size_changed(); } + bool _exclusive_input = false; + + /** + * Input::Session_component::Action interface + */ + void exclusive_input_changed() override + { + if (_user_state.exclusive_input() != _exclusive_input) { + _exclusive_input = _user_state.exclusive_input(); + + /* toggle pointer visibility */ + _update_pointer_position(); + _view_stack.update_all_views(); + } + } + /** * Signal handler for externally triggered focus changes */ @@ -797,6 +813,11 @@ struct Nitpicker::Main : Focus_updater, Hover_updater, void _update_pointer_position() { + /* move pointer out of the way while a client receives exclusive input */ + if (_user_state.exclusive_input()) { + _view_stack.geometry(_pointer_origin, Rect { { -1000*1000, 0 }, { } }); + return; + } _user_state.pointer().with_result( [&] (Point p) { _view_stack.geometry(_pointer_origin, Rect(p, Area{})); }, diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 3d12891ad2..a1c88adf99 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -93,13 +93,13 @@ void User_state::_handle_input_event(Input::Event ev) _last_seq_number.construct(seq); }); /* transparently convert relative into absolute motion event */ - ev.handle_relative_motion([&] (int x, int y) { - _pointer.with_result( - [&] (Point orig_pos) { - Point const p = orig_pos + Point { x, y }; - ev = Absolute_motion { p.x, p.y }; }, - [&] (Nowhere) { }); - }); + if (!exclusive_input()) + ev.handle_relative_motion([&] (int x, int y) { + _pointer.with_result( + [&] (Point orig_pos) { + Point const p = orig_pos + Point { x, y }; + ev = Absolute_motion { p.x, p.y }; }, + [&] (Nowhere) { }); }); /* respond to motion events by updating the pointer position */ ev.handle_absolute_motion([&] (int x, int y) { @@ -249,27 +249,31 @@ void User_state::_handle_input_event(Input::Event ev) /* * Deliver event to session */ - bool const forward_to_session = (ev.absolute_motion() || ev.wheel() || - ev.touch() || ev.touch_release() || - ev.seq_number()); + bool const forward_to_session = ev.absolute_motion() || ev.relative_motion() + || ev.touch() || ev.touch_release() + || ev.wheel() || ev.seq_number(); if (forward_to_session) { - if (_key_cnt == 0) { + View_owner *receiver = _input_receiver; - if (_hovered) { + if (_key_cnt == 0 && _hovered) { + /* + * Unless the domain of the pointed session is configured to + * always receive hover events, we deliver motion events only + * to the focused domain. + */ + if (_hovered->hover_always() || _hovered->has_same_domain(_focused)) + receiver = _hovered; + } - /* - * Unless the domain of the pointed session is configured to - * always receive hover events, we deliver motion events only - * to the focused domain. - */ - if (_hovered->hover_always() - || _hovered->has_same_domain(_focused)) - _hovered->submit_input_event(ev); - } + /* + * Route relative motion (exclusive input) to the focused client + */ + if (ev.relative_motion() && _focused) + receiver = _focused; - } else if (_input_receiver) - _input_receiver->submit_input_event(ev); + if (receiver) + receiver->submit_input_event(ev); } /* diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index 083f2f66f9..7a852d4f07 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -252,6 +252,12 @@ class Nitpicker::User_state Handle_input_result handle_input_events(Input_batch); + bool exclusive_input() const + { + return (_focused && _focused->exclusive_input_requested()) + || (_input_receiver && _input_receiver->exclusive_input_requested()); + } + /** * Discard all references to specified view owner */ diff --git a/repos/os/src/server/nitpicker/view_owner.h b/repos/os/src/server/nitpicker/view_owner.h index 57f2cfac38..6252dfe00c 100644 --- a/repos/os/src/server/nitpicker/view_owner.h +++ b/repos/os/src/server/nitpicker/view_owner.h @@ -86,6 +86,8 @@ struct Nitpicker::View_owner : Interface virtual void submit_input_event(Input::Event) { } + virtual bool exclusive_input_requested() const { return false; } + /** * Produce report with the owner's information */