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