From 4cad1a87df84826ded839900ea650f1ad67b1c0e Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 1 Jul 2020 18:14:00 +0200 Subject: [PATCH] nitpicker: make framebuffer and input optional Nitpicker used to unconditionally request a framebuffer and input session. With the transition to the new capture/event session interfaces, this built-in policy does no longer suffice. This patch introduces the attributes 'request_framebuffer="yes"' and 'request_input="yes"' (with the default values shown) to nitpicker's node. If setting those attributes to "no", nitpicker won't request a "Framebuffer" and "Input" session respectively. Issue #3812 --- repos/os/src/server/nitpicker/main.cc | 102 ++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 14 deletions(-) diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 53f93fe2e..bdccd8fed 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,19 @@ class Nitpicker::Capture_root : public Root_component _sessions.for_each([&] (Capture_session &session) { session.mark_as_damaged(rect); }); } + + void report_displays(Xml_generator &xml) const + { + Area const size = bounding_box(); + + if (size.count() == 0) + return; + + xml.node("display", [&] () { + xml.attribute("width", size.w()); + xml.attribute("height", size.h()); + }); + } }; @@ -285,11 +299,25 @@ struct Nitpicker::Main : Focus_updater, { Env &_env; - Framebuffer::Connection _framebuffer { _env, Framebuffer::Mode { } }; + Timer::Connection _timer { _env }; - Input::Connection _input { _env }; + Signal_handler
_timer_handler = { _env.ep(), *this, &Main::_handle_input }; - Attached_dataspace _ev_ds { _env.rm(), _input.dataspace() }; + unsigned long _timer_period_ms = 10; + + Constructible _framebuffer { }; + + struct Input_connection + { + Input::Connection connection; + + Attached_dataspace ev_ds; + + Input_connection(Env &env) + : connection(env), ev_ds(env.rm(), connection.dataspace()) { } + }; + + Constructible _input { }; typedef Pixel_rgb888 PT; /* physical pixel type */ @@ -326,6 +354,9 @@ struct Nitpicker::Main : Focus_updater, } }; + bool _request_framebuffer = false; + bool _request_input = false; + Constructible _fb_screen { }; void _handle_fb_mode(); @@ -401,6 +432,12 @@ struct Nitpicker::Main : Focus_updater, _capture_root.mark_as_damaged(rect); } + void _update_input_connection() + { + bool const output_present = (_view_stack.size().count() > 0); + _input.conditional(_request_input && output_present, _env); + } + /** * Capture_session::Handler interface */ @@ -435,6 +472,8 @@ struct Nitpicker::Main : Focus_updater, _report_displays(); } + + _update_input_connection(); } /** @@ -514,10 +553,9 @@ struct Nitpicker::Main : Focus_updater, _config_rom.sigh(_config_handler); _handle_config(); - _framebuffer.sync_sigh(_input_handler); + _timer.sigh(_timer_handler); _handle_fb_mode(); - _framebuffer.mode_sigh(_fb_mode_handler); _env.parent().announce(_env.ep().manage(_gui_root)); @@ -544,9 +582,10 @@ void Nitpicker::Main::_handle_input() bool const old_motion_activity = _motion_activity; /* handle batch of pending events */ - User_state::Handle_input_result const result = - _user_state.handle_input_events(_ev_ds.local_addr(), - _input.flush()); + 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 { }; if (result.button_activity) { _last_button_activity_period = _period_cnt; @@ -610,7 +649,7 @@ void Nitpicker::Main::_handle_input() _update_pointer_position(); /* perform redraw */ - if (_fb_screen.constructed()) { + if (_framebuffer.constructed() && _fb_screen.constructed()) { /* call 'Dirty_rect::flush' on a copy to preserve the state */ Dirty_rect dirty_rect = _fb_screen->dirty_rect; dirty_rect.flush([&] (Rect const &rect) { @@ -618,9 +657,9 @@ void Nitpicker::Main::_handle_input() /* flush pixels to the framebuffer, reset dirty_rect */ _fb_screen->dirty_rect.flush([&] (Rect const &rect) { - _framebuffer.refresh(rect.x1(), rect.y1(), - rect.w(), rect.h()); }); -} + _framebuffer->refresh(rect.x1(), rect.y1(), + rect.w(), rect.h()); }); + } /* deliver framebuffer synchronization events */ for (Gui_session *s = _session_list.first(); s; s = s->next()) @@ -731,6 +770,22 @@ void Nitpicker::Main::_handle_config() /* update focus report since the domain colors might have changed */ Reporter::Xml_generator xml(_focus_reporter, [&] () { _user_state.report_focused_view_owner(xml, _button_activity); }); + + /* update framebuffer output back end */ + bool const request_framebuffer = config.attribute_value("request_framebuffer", true); + if (request_framebuffer != _request_framebuffer) { + _request_framebuffer = request_framebuffer; + _handle_fb_mode(); + } + + /* + * Update input back end + * + * Defer input session creation until at least one capture client + * (framebuffer driver) is present. + */ + _request_input = config.attribute_value("request_input", true); + _update_input_connection(); } @@ -746,14 +801,33 @@ void Nitpicker::Main::_report_displays() xml.attribute("height", _fb_screen->size.h()); }); } + + _capture_root.report_displays(xml); }); } void Nitpicker::Main::_handle_fb_mode() { - /* reconstruct framebuffer screen and menu bar */ - _fb_screen.construct(_env.rm(), _framebuffer); + if (_request_framebuffer && !_framebuffer.constructed()) { + _framebuffer.construct(_env, Framebuffer::Mode{}); + _framebuffer->mode_sigh(_fb_mode_handler); + _framebuffer->sync_sigh(_input_handler); + _timer.trigger_periodic(0); + } + + if (_request_framebuffer && !_fb_screen.constructed()) + _fb_screen.construct(_env.rm(), *_framebuffer); + + if (!_request_framebuffer && _fb_screen.constructed()) + _fb_screen.destruct(); + + if (!_request_framebuffer && _framebuffer.constructed()) { + _framebuffer.destruct(); + } + + if (!_request_framebuffer) + _timer.trigger_periodic(_timer_period_ms*1000); capture_buffer_size_changed(); }