diff --git a/repos/os/recipes/src/nitpicker/used_apis b/repos/os/recipes/src/nitpicker/used_apis index a589901020..4864b65475 100644 --- a/repos/os/recipes/src/nitpicker/used_apis +++ b/repos/os/recipes/src/nitpicker/used_apis @@ -7,4 +7,5 @@ timer_session framebuffer_session gui_session capture_session +event_session report_session diff --git a/repos/os/src/server/nitpicker/event_session.h b/repos/os/src/server/nitpicker/event_session.h new file mode 100644 index 0000000000..3114a1b06f --- /dev/null +++ b/repos/os/src/server/nitpicker/event_session.h @@ -0,0 +1,82 @@ +/* + * \brief Event session component + * \author Norman Feske + * \date 2020-07-14 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _EVENT_SESSION_H_ +#define _EVENT_SESSION_H_ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include "user_state.h" + +namespace Nitpicker { class Event_session; } + + +class Nitpicker::Event_session : public Session_object +{ + public: + + struct Handler : Interface + { + virtual void handle_input_events(User_state::Input_batch) = 0; + }; + + private: + + Handler &_handler; + + Constrained_ram_allocator _ram; + + Attached_ram_dataspace _ds; + + public: + + Event_session(Env &env, + Resources const &resources, + Label const &label, + Diag const &diag, + Handler &handler) + : + Session_object(env.ep(), resources, label, diag), + _handler(handler), + _ram(env.ram(), _ram_quota_guard(), _cap_quota_guard()), + _ds(_ram, env.rm(), 4096) + { } + + ~Event_session() { } + + + /***************************** + ** Event session interface ** + *****************************/ + + Dataspace_capability dataspace() { return _ds.cap(); } + + void submit_batch(unsigned const count) + { + size_t const max_events = _ds.size() / sizeof(Input::Event); + + if (count > max_events) + warning("number of events exceeds dataspace capacity"); + + User_state::Input_batch const batch { + .events = _ds.local_addr(), + .count = min(count, max_events) }; + + _handler.handle_input_events(batch); + } +}; + +#endif /* _EVENT_SESSION_H_ */ diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index bdccd8fed8..c600cfabeb 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -33,10 +33,12 @@ #include "pointer_origin.h" #include "domain_registry.h" #include "capture_session.h" +#include "event_session.h" namespace Nitpicker { class Gui_root; class Capture_root; + class Event_root; struct Main; } @@ -293,15 +295,64 @@ class Nitpicker::Capture_root : public Root_component }; +/***************************************** + ** Implementation of the event service ** + *****************************************/ + +class Nitpicker::Event_root : public Root_component +{ + private: + + Env &_env; + + Event_session::Handler &_handler; + + protected: + + Event_session *_create_session(const char *args) override + { + return new (md_alloc()) + Event_session(_env, + session_resources_from_args(args), + session_label_from_args(args), + session_diag_from_args(args), + _handler); + } + + void _upgrade_session(Event_session *s, const char *args) override + { + s->upgrade(ram_quota_from_args(args)); + s->upgrade(cap_quota_from_args(args)); + } + + void _destroy_session(Event_session *session) override + { + Genode::destroy(md_alloc(), session); + } + + public: + + /** + * Constructor + */ + Event_root(Env &env, Allocator &md_alloc, Event_session::Handler &handler) + : + Root_component(&env.ep().rpc_ep(), &md_alloc), + _env(env), _handler(handler) + { } +}; + + struct Nitpicker::Main : Focus_updater, View_stack::Damage, - Capture_session::Handler + Capture_session::Handler, + Event_session::Handler { Env &_env; Timer::Connection _timer { _env }; - Signal_handler
_timer_handler = { _env.ep(), *this, &Main::_handle_input }; + Signal_handler
_timer_handler = { _env.ep(), *this, &Main::_handle_period }; unsigned long _timer_period_ms = 10; @@ -420,6 +471,8 @@ struct Nitpicker::Main : Focus_updater, Capture_root _capture_root { _env, _sliced_heap, _view_stack, *this }; + Event_root _event_root { _env, _sliced_heap, *this }; + /** * View_stack::Damage interface */ @@ -502,11 +555,16 @@ struct Nitpicker::Main : Focus_updater, Signal_handler
_focus_handler = { _env.ep(), *this, &Main::_handle_focus }; /** - * Signal handler invoked on the reception of user input + * Event_session::Handler interface */ - void _handle_input(); + void handle_input_events(User_state::Input_batch) override; - Signal_handler
_input_handler = { _env.ep(), *this, &Main::_handle_input }; + /** + * Signal handler periodically invoked for the reception of user input and redraw + */ + void _handle_period(); + + Signal_handler
_input_period = { _env.ep(), *this, &Main::_handle_period }; /** * Counter that is incremented periodically @@ -562,30 +620,28 @@ struct Nitpicker::Main : Focus_updater, if (_config_rom.xml().has_sub_node("capture")) _env.parent().announce(_env.ep().manage(_capture_root)); + if (_config_rom.xml().has_sub_node("event")) + _env.parent().announce(_env.ep().manage(_event_root)); + /* * Detect initial motion activity such that the first hover report * contains the boot-time activity of the user in the very first * report. */ - _handle_input(); + _handle_period(); _report_displays(); } }; -void Nitpicker::Main::_handle_input() +void Nitpicker::Main::handle_input_events(User_state::Input_batch batch) { - _period_cnt++; - bool const old_button_activity = _button_activity; bool const old_motion_activity = _motion_activity; - /* handle batch of pending events */ - User_state::Handle_input_result const result = _input.constructed() - ? _user_state.handle_input_events(_input->ev_ds.local_addr(), - _input->connection.flush()) - : User_state::Handle_input_result { }; + User_state::Handle_input_result const result = + _user_state.handle_input_events(batch); if (result.button_activity) { _last_button_activity_period = _period_cnt; @@ -647,6 +703,24 @@ void Nitpicker::Main::_handle_input() /* update pointer position */ if (result.motion_activity) _update_pointer_position(); +} + + +void Nitpicker::Main::_handle_period() +{ + _period_cnt++; + + /* handle batch of pending events */ + if (_input.constructed()) { + + size_t const max_events = _input->ev_ds.size() / sizeof(Input::Event); + + User_state::Input_batch const batch { + .events = _input->ev_ds.local_addr(), + .count = min(max_events, (size_t)_input->connection.flush()) }; + + handle_input_events(batch); + } /* perform redraw */ if (_framebuffer.constructed() && _fb_screen.constructed()) { @@ -812,7 +886,7 @@ void Nitpicker::Main::_handle_fb_mode() if (_request_framebuffer && !_framebuffer.constructed()) { _framebuffer.construct(_env, Framebuffer::Mode{}); _framebuffer->mode_sigh(_fb_mode_handler); - _framebuffer->sync_sigh(_input_handler); + _framebuffer->sync_sigh(_timer_handler); _timer.trigger_periodic(0); } diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 092e0a0180..41741b1c3c 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -277,8 +277,7 @@ void User_state::_handle_input_event(Input::Event ev) User_state::Handle_input_result -User_state::handle_input_events(Input::Event const * const ev_buf, - unsigned const num_ev) +User_state::handle_input_events(Input_batch batch) { Point const old_pointer_pos = _pointer_pos; View_owner * const old_hovered = _hovered; @@ -289,18 +288,18 @@ User_state::handle_input_events(Input::Event const * const ev_buf, bool button_activity = false; - if (num_ev > 0) { + if (batch.count > 0) { /* * Take events from input event buffer, merge consecutive motion * events, and pass result to the user state. */ - for (unsigned src_ev_cnt = 0; src_ev_cnt < num_ev; src_ev_cnt++) { + for (unsigned src_ev_cnt = 0; src_ev_cnt < batch.count; src_ev_cnt++) { - Input::Event const *e = &ev_buf[src_ev_cnt]; + Input::Event const *e = &batch.events[src_ev_cnt]; Input::Event curr = *e; if (e->absolute_motion() || e->relative_motion()) { - unsigned const n = num_consecutive_events(e, num_ev - src_ev_cnt); + unsigned const n = num_consecutive_events(e, batch.count - src_ev_cnt); curr = merge_motion_events(e, n); /* skip merged events */ @@ -332,8 +331,8 @@ User_state::handle_input_events(Input::Event const * const ev_buf, button_activity |= _key_pressed(); bool key_state_affected = false; - for (unsigned i = 0; i < num_ev; i++) - key_state_affected |= (ev_buf[i].press() || ev_buf[i].release()); + for (unsigned i = 0; i < batch.count; i++) + key_state_affected |= (batch.events[i].press() || batch.events[i].release()); _apply_pending_focus_change(); diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index ad99fe2dd4..e0873c09b2 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -229,6 +229,8 @@ class Nitpicker::User_state ** Interface used by the main program ** ****************************************/ + struct Input_batch { Input::Event *events; size_t count; }; + struct Handle_input_result { bool const hover_changed; @@ -240,8 +242,7 @@ class Nitpicker::User_state bool const last_clicked_changed; }; - Handle_input_result handle_input_events(Input::Event const *ev_buf, - unsigned num_ev); + Handle_input_result handle_input_events(Input_batch); /** * Discard all references to specified view owner