From d7830a0ce6bfb030f8d26f8079a82ad888eebcc6 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 3 Oct 2024 17:46:32 +0200 Subject: [PATCH] Add Input::Session::exclusive() interface This interface allows a GUI client to express the intent to exclusively observe relative motion events while locking the absolute pointer position. This patch merely extends the interface without implementing it. As this change touches os/include/input/component.h, it moves the manage/dissolve operations into the class, ensuring the call of dissolve at destruction time. Issue #5355 --- .../src/server/liquid_framebuffer/main.cc | 14 ++++++- repos/gems/src/app/sculpt_manager/gui.cc | 17 +++++--- .../gems/src/lib/dialog/sandboxed_runtime.cc | 12 ++++-- repos/gems/src/server/wm/decorator_gui.h | 18 ++++----- repos/gems/src/server/wm/gui.h | 38 +++++++++--------- repos/os/include/input/component.h | 39 ++++++++++++++----- repos/os/include/input_session/client.h | 22 ++++++----- .../os/include/input_session/input_session.h | 28 +++++++++---- repos/os/src/server/gui_fb/main.cc | 15 +++++-- repos/os/src/server/nitpicker/input_session.h | 2 + 10 files changed, 136 insertions(+), 69 deletions(-) diff --git a/repos/demo/src/server/liquid_framebuffer/main.cc b/repos/demo/src/server/liquid_framebuffer/main.cc index f3ef47dd00..01955f9c89 100644 --- a/repos/demo/src/server/liquid_framebuffer/main.cc +++ b/repos/demo/src/server/liquid_framebuffer/main.cc @@ -125,7 +125,8 @@ namespace Liquid_fb { } -class Liquid_fb::Main : public Scout::Event_handler +class Liquid_fb::Main : public Scout::Event_handler, + private Input::Session_component::Action { private: @@ -162,7 +163,16 @@ class Liquid_fb::Main : public Scout::Event_handler _graphics_backend { _env.rm(), _gui, _heap, _max_size, _initial_position, _initial_size }; - Input::Session_component _input_session_component { _env, _env.ram() }; + Input::Session_component _input_session_component { + _env.ep(), _env.ram(), _env.rm(), *this }; + + /** + * Input::Session_component::Action interface + */ + void exclusive_input_requested(bool enabled) override + { + _gui.input.exclusive(enabled); + } bool const _window_content_initialized = (init_window_content(_env.ram(), _env.rm(), _heap, _input_session_component, diff --git a/repos/gems/src/app/sculpt_manager/gui.cc b/repos/gems/src/app/sculpt_manager/gui.cc index ea4b1813d9..1ceb254509 100644 --- a/repos/gems/src/app/sculpt_manager/gui.cc +++ b/repos/gems/src/app/sculpt_manager/gui.cc @@ -49,7 +49,8 @@ static bool clack(Input::Event const &event) } -struct Gui::Session_component : Rpc_object +struct Gui::Session_component : Rpc_object, + private Input::Session_component::Action { Env &_env; @@ -63,7 +64,16 @@ struct Gui::Session_component : Rpc_object Input::Session_client _gui_input { _env.rm(), _gui_session.input() }; - Input::Session_component _input_component { _env, _env.ram() }; + Input::Session_component _input_component { + _env.ep(), _env.ram(), _env.rm(), *this }; + + /** + * Input::Session_component::Action interface + */ + void exclusive_input_requested(bool enabled) override + { + _gui_input.exclusive(enabled); + } Signal_handler _input_handler { _env.ep(), *this, &Session_component::_handle_input }; @@ -104,12 +114,9 @@ struct Gui::Session_component : Rpc_object _connection(env, session_label_from_args(args), Ram_quota { 36*1024 }, { }) { _gui_input.sigh(_input_handler); - _env.ep().manage(_input_component); _input_component.event_queue().enabled(true); } - ~Session_component() { _env.ep().dissolve(_input_component); } - void upgrade(Session::Resources const &resources) { _connection.upgrade(resources); diff --git a/repos/gems/src/lib/dialog/sandboxed_runtime.cc b/repos/gems/src/lib/dialog/sandboxed_runtime.cc index 554f02369d..d8e204ae14 100644 --- a/repos/gems/src/lib/dialog/sandboxed_runtime.cc +++ b/repos/gems/src/lib/dialog/sandboxed_runtime.cc @@ -66,7 +66,14 @@ struct Sandboxed_runtime::Gui_session : Session_object Input::Session_client _gui_input { _env.rm(), _gui_session.input() }; - Input::Session_component _input_component { _env, _env.ram() }; + struct Input_action : Input::Session_component::Action + { + void exclusive_input_requested(bool) override { }; + + } _input_action { }; + + Input::Session_component _input_component { + _env.ep(), _env.ram(), _env.rm(), _input_action }; Signal_handler _input_handler { _env.ep(), *this, &Gui_session::_handle_input }; @@ -109,12 +116,9 @@ struct Sandboxed_runtime::Gui_session : Session_object _connection(env, _label, Ram_quota { 36*1024 }, { }) { _gui_input.sigh(_input_handler); - _env.ep().manage(_input_component); _input_component.event_queue().enabled(true); } - ~Gui_session() { _env.ep().dissolve(_input_component); } - void upgrade(Session::Resources const &resources) { _connection.upgrade(resources); diff --git a/repos/gems/src/server/wm/decorator_gui.h b/repos/gems/src/server/wm/decorator_gui.h index d85a06cf08..43ad1fe9d6 100644 --- a/repos/gems/src/server/wm/decorator_gui.h +++ b/repos/gems/src/server/wm/decorator_gui.h @@ -94,10 +94,15 @@ struct Wm::Decorator_gui_session : Session_object, Decorator_content_callback &_content_callback; + struct Dummy_input_action : Input::Session_component::Action + { + void exclusive_input_requested(bool) override { }; + + } _input_action { }; + /* Gui::Connection requires a valid input session */ - Input::Session_component _dummy_input_component { _env, _env.ram() }; - Input::Session_capability _dummy_input_component_cap = - _env.ep().manage(_dummy_input_component); + Input::Session_component _dummy_input_component { + _env.ep(), _env.ram(), _env.rm(), _input_action }; Signal_handler _input_handler { _env.ep(), *this, &Decorator_gui_session::_handle_input }; @@ -126,11 +131,6 @@ struct Wm::Decorator_gui_session : Session_object, _input_session.sigh(_input_handler); } - ~Decorator_gui_session() - { - _env.ep().dissolve(_dummy_input_component); - } - void upgrade_local_or_remote(Resources const &resources) { _upgrade_local_or_remote(resources, *this, _real_gui); @@ -219,7 +219,7 @@ struct Wm::Decorator_gui_session : Session_object, * Deny input to the decorator. User input referring to the * window decorations is routed to the window manager. */ - return _dummy_input_component_cap; + return _dummy_input_component.cap(); } Info_result info() override diff --git a/repos/gems/src/server/wm/gui.h b/repos/gems/src/server/wm/gui.h index 882c76879c..bd9b53e46a 100644 --- a/repos/gems/src/server/wm/gui.h +++ b/repos/gems/src/server/wm/gui.h @@ -496,7 +496,8 @@ class Wm::Gui::Session_component : public Session_object, private List::Element, private Input_origin_changed_handler, private Upgradeable, - private Dynamic_rom_session::Xml_producer + private Dynamic_rom_session::Xml_producer, + private Input::Session_component::Action { public: @@ -556,21 +557,15 @@ class Wm::Gui::Session_component : public Session_object, List _child_views { }; View_ids _view_ids { }; - struct Input_session : Input::Session_component - { - Entrypoint &_ep; + Input::Session_component _input_session { + _env.ep(), _ram, _env.rm(), *this }; - Input_session(Env &env, Ram_allocator &ram) - : Input::Session_component(env, ram), _ep(env.ep()) - { - _ep.manage(*this); - } + /** + * Input::Session_component::Action interface + */ + void exclusive_input_requested(bool) override { } - ~Input_session() { _ep.dissolve(*this); } - }; - - Input_session _input_session { _env, _ram }; - Click_handler &_click_handler; + Click_handler &_click_handler; struct Info_rom_session : Dynamic_rom_session { @@ -1281,8 +1276,9 @@ class Wm::Gui::Session_component : public Session_object, }; -class Wm::Gui::Root : public Rpc_object >, - public Decorator_content_callback +class Wm::Gui::Root : public Rpc_object >, + public Decorator_content_callback, + private Input::Session_component::Action { private: @@ -1306,9 +1302,13 @@ class Wm::Gui::Root : public Rpc_object >, Window_registry &_window_registry; - Input::Session_component _window_layouter_input { _env, _env.ram() }; + Input::Session_component _window_layouter_input { + _env.ep(), _env.ram(), _env.rm(), *this }; - Input::Session_capability _window_layouter_input_cap { _env.ep().manage(_window_layouter_input) }; + /** + * Input::Session_component::Action interface + */ + void exclusive_input_requested(bool) override { } /* handler that forwards clicks into unfocused windows to the layouter */ struct Click_handler : Gui::Click_handler @@ -1475,7 +1475,7 @@ class Wm::Gui::Root : public Rpc_object >, { _layouter_session = new (_sliced_heap) Layouter_gui_session(_env, resources, label, diag, - _window_layouter_input_cap); + _window_layouter_input.cap()); return _layouter_session->cap(); } diff --git a/repos/os/include/input/component.h b/repos/os/include/input/component.h index c606823e89..e21f802583 100644 --- a/repos/os/include/input/component.h +++ b/repos/os/include/input/component.h @@ -25,11 +25,21 @@ namespace Input { class Session_component; } -class Input::Session_component : public Genode::Rpc_object +class Input::Session_component : public Rpc_object { + public: + + struct Action : Interface + { + virtual void exclusive_input_requested(bool) = 0; + }; + private: - Genode::Attached_ram_dataspace _ds; + Entrypoint &_ep; + Action &_action; + + Attached_ram_dataspace _ds; Event_queue _event_queue { }; @@ -38,12 +48,18 @@ class Input::Session_component : public Genode::Rpc_object /** * Constructor * - * \param ram allocator for the session buffer + * \param ram allocator for the shared-memory input buffer */ - Session_component(Genode::Env &env, Genode::Ram_allocator &ram) + Session_component(Entrypoint &ep, Ram_allocator &ram, + Region_map &rm, Action &action) : - _ds(ram, env.rm(), Event_queue::QUEUE_SIZE*sizeof(Input::Event)) - { } + _ep(ep), _action(action), + _ds(ram, rm, Event_queue::QUEUE_SIZE*sizeof(Input::Event)) + { + _ep.manage(*this); + } + + ~Session_component() { _ep.dissolve(*this); } /** * Return reference to event queue of the session @@ -58,7 +74,7 @@ class Input::Session_component : public Genode::Rpc_object try { _event_queue.add(event); } catch (Input::Event_queue::Overflow) { - Genode::warning("input overflow - resetting queue"); + warning("input overflow - resetting queue"); _event_queue.reset(); } } @@ -68,7 +84,7 @@ class Input::Session_component : public Genode::Rpc_object ** Input::Session interface ** ******************************/ - Genode::Dataspace_capability dataspace() override { return _ds.cap(); } + Dataspace_capability dataspace() override { return _ds.cap(); } bool pending() const override { return !_event_queue.empty(); } @@ -83,10 +99,15 @@ class Input::Session_component : public Genode::Rpc_object return cnt; } - void sigh(Genode::Signal_context_capability sigh) override + void sigh(Signal_context_capability sigh) override { _event_queue.sigh(sigh); } + + void exclusive(bool enabled) override + { + _action.exclusive_input_requested(enabled); + } }; #endif /* _INCLUDE__INPUT__COMPONENT_H_ */ diff --git a/repos/os/include/input_session/client.h b/repos/os/include/input_session/client.h index 633bc98d3d..f24aa3e32c 100644 --- a/repos/os/include/input_session/client.h +++ b/repos/os/include/input_session/client.h @@ -22,26 +22,25 @@ namespace Input { struct Session_client; } -class Input::Session_client : public Genode::Rpc_client +class Input::Session_client : public Rpc_client { private: - Genode::Attached_dataspace _event_ds; + Attached_dataspace _event_ds; - Genode::size_t const _max_events = - _event_ds.size() / sizeof(Input::Event); + size_t const _max_events = _event_ds.size() / sizeof(Input::Event); friend class Input::Binding; public: - Session_client(Genode::Region_map &local_rm, Session_capability session) + Session_client(Region_map &local_rm, Session_capability session) : - Genode::Rpc_client(session), + Rpc_client(session), _event_ds(local_rm, call()) { } - Genode::Dataspace_capability dataspace() override { + Dataspace_capability dataspace() override { return call(); } bool pending() const override { @@ -50,9 +49,12 @@ class Input::Session_client : public Genode::Rpc_client int flush() override { return call(); } - void sigh(Genode::Signal_context_capability sigh) override { + void sigh(Signal_context_capability sigh) override { call(sigh); } + void exclusive(bool enabled) override { + call(enabled); } + /** * Flush and apply functor to pending events * @@ -61,10 +63,10 @@ class Input::Session_client : public Genode::Rpc_client */ void for_each_event(auto const &fn) { - Genode::size_t const n = Genode::min((Genode::size_t)call(), _max_events); + size_t const n = min((size_t)call(), _max_events); Event const *ev_buf = _event_ds.local_addr(); - for (Genode::size_t i = 0; i < n; ++i) + for (size_t i = 0; i < n; ++i) fn(ev_buf[i]); } }; diff --git a/repos/os/include/input_session/input_session.h b/repos/os/include/input_session/input_session.h index 5532896bd0..d53ba4f9e3 100644 --- a/repos/os/include/input_session/input_session.h +++ b/repos/os/include/input_session/input_session.h @@ -19,7 +19,12 @@ #include #include -namespace Input { struct Session; } +namespace Input { + + using namespace Genode; + + struct Session; +} struct Input::Session : Genode::Session @@ -41,7 +46,7 @@ struct Input::Session : Genode::Session /** * Return capability to event buffer dataspace */ - virtual Genode::Dataspace_capability dataspace() = 0; + virtual Dataspace_capability dataspace() = 0; /** * Request input state @@ -60,19 +65,26 @@ struct Input::Session : Genode::Session /** * Register signal handler to be notified on arrival of new input */ - virtual void sigh(Genode::Signal_context_capability) = 0; + virtual void sigh(Signal_context_capability) = 0; + + /** + * Express intent to receive relative pointer events exclusively + */ + virtual void exclusive(bool) = 0; /********************* ** RPC declaration ** *********************/ - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); - GENODE_RPC(Rpc_pending, bool, pending); - GENODE_RPC(Rpc_flush, int, flush); - GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability); + GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace); + GENODE_RPC(Rpc_pending, bool, pending); + GENODE_RPC(Rpc_flush, int, flush); + GENODE_RPC(Rpc_sigh, void, sigh, Signal_context_capability); + GENODE_RPC(Rpc_exclusive, void, exclusive, bool); - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_pending, Rpc_flush, Rpc_sigh); + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_pending, Rpc_flush, Rpc_sigh, + Rpc_exclusive); }; #endif /* _INCLUDE__INPUT_SESSION__INPUT_SESSION_H_ */ diff --git a/repos/os/src/server/gui_fb/main.cc b/repos/os/src/server/gui_fb/main.cc index b9eda42db7..57957d44bf 100644 --- a/repos/os/src/server/gui_fb/main.cc +++ b/repos/os/src/server/gui_fb/main.cc @@ -247,7 +247,7 @@ struct Framebuffer::Session_component : Genode::Rpc_object ** Main program ** ******************/ -struct Gui_fb::Main : View_updater +struct Gui_fb::Main : View_updater, Input::Session_component::Action { Env &_env; @@ -316,10 +316,19 @@ struct Gui_fb::Main : View_updater /* * Input and framebuffer sessions provided to our client */ - Input::Session_component _input_session { _env, _env.ram() }; + Input::Session_component _input_session { _env.ep(), _env.ram(), _env.rm(), *this }; + + /** + * Input::Session_component::Action interface + */ + void exclusive_input_requested(bool enabled) override + { + _gui.input.exclusive(enabled); + } + Framebuffer::Session_component _fb_session { _env.pd(), _gui, *this, _initial_mode() }; - Static_root _input_root { _env.ep().manage(_input_session) }; + Static_root _input_root { _input_session.cap() }; /* * Attach root interfaces to the entry point diff --git a/repos/os/src/server/nitpicker/input_session.h b/repos/os/src/server/nitpicker/input_session.h index 520fd11edf..da940e79ab 100644 --- a/repos/os/src/server/nitpicker/input_session.h +++ b/repos/os/src/server/nitpicker/input_session.h @@ -113,6 +113,8 @@ class Input::Session_component : public Rpc_object } void sigh(Signal_context_capability sigh) override { _sigh = sigh; } + + void exclusive(bool) override { } }; #endif /* _INPUT_SESSION_COMPONENT_H_ */