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 */