mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
parent
66c520cdae
commit
7932c76d85
@ -7,4 +7,5 @@ timer_session
|
||||
framebuffer_session
|
||||
gui_session
|
||||
capture_session
|
||||
event_session
|
||||
report_session
|
||||
|
82
repos/os/src/server/nitpicker/event_session.h
Normal file
82
repos/os/src/server/nitpicker/event_session.h
Normal file
@ -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 <base/session_object.h>
|
||||
#include <event_session/event_session.h>
|
||||
|
||||
/* local includes */
|
||||
#include "user_state.h"
|
||||
|
||||
namespace Nitpicker { class Event_session; }
|
||||
|
||||
|
||||
class Nitpicker::Event_session : public Session_object<Event::Session, Event_session>
|
||||
{
|
||||
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<Input::Event>(),
|
||||
.count = min(count, max_events) };
|
||||
|
||||
_handler.handle_input_events(batch);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _EVENT_SESSION_H_ */
|
@ -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<Capture_session>
|
||||
};
|
||||
|
||||
|
||||
/*****************************************
|
||||
** Implementation of the event service **
|
||||
*****************************************/
|
||||
|
||||
class Nitpicker::Event_root : public Root_component<Event_session>
|
||||
{
|
||||
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<Event_session>(&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<Main> _timer_handler = { _env.ep(), *this, &Main::_handle_input };
|
||||
Signal_handler<Main> _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<Main> _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<Main> _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<Main> _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::Event>(),
|
||||
_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<Input::Event>(),
|
||||
.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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user