genode/repos/os/src/server/nitpicker/main.cc

628 lines
18 KiB
C++
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief Nitpicker main program for Genode
* \author Norman Feske
* \date 2006-08-04
*/
/*
* Copyright (C) 2006-2017 Genode Labs GmbH
2011-12-22 16:19:25 +01:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
2011-12-22 16:19:25 +01:00
*/
/* Genode includes */
#include <base/sleep.h>
#include <base/log.h>
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
2011-12-22 16:19:25 +01:00
#include <input/keycodes.h>
#include <root/component.h>
#include <input_session/connection.h>
#include <framebuffer_session/connection.h>
#include <os/session_policy.h>
#include <nitpicker_gfx/tff_font.h>
2011-12-22 16:19:25 +01:00
/* local includes */
#include "types.h"
#include "user_state.h"
2011-12-22 16:19:25 +01:00
#include "background.h"
#include "clip_guard.h"
#include "pointer_origin.h"
#include "domain_registry.h"
2011-12-22 16:19:25 +01:00
2013-09-08 16:20:18 +02:00
namespace Nitpicker {
template <typename> class Root;
struct Main;
}
2014-07-08 17:35:40 +02:00
/*********************************
** Font used for view labeling **
*********************************/
extern char _binary_default_tff_start[];
2011-12-22 16:19:25 +01:00
/************************************
** Framebuffer::Session_component **
************************************/
2011-12-22 16:19:25 +01:00
void Framebuffer::Session_component::refresh(int x, int y, int w, int h)
{
Rect const rect(Point(x, y), Area(w, h));
_view_stack.mark_session_views_as_dirty(_session, rect);
}
2011-12-22 16:19:25 +01:00
/*****************************************
** Implementation of Nitpicker service **
*****************************************/
template <typename PT>
class Nitpicker::Root : public Root_component<Session_component>,
public Visibility_controller
{
private:
2011-12-22 16:19:25 +01:00
Env &_env;
Attached_rom_dataspace const &_config;
Session_list &_session_list;
Domain_registry const &_domain_registry;
Global_keys &_global_keys;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Framebuffer::Mode _scr_mode { };
View_stack &_view_stack;
Font const &_font;
User_state &_user_state;
View_component &_pointer_origin;
View_component &_builtin_background;
Framebuffer::Session &_framebuffer;
Reporter &_focus_reporter;
Reporter &_hover_reporter;
Focus_updater &_focus_updater;
2011-12-22 16:19:25 +01:00
protected:
2011-12-22 16:19:25 +01:00
Session_component *_create_session(const char *args) override
{
Session_label const label = label_from_args(args);
bool const provides_default_bg = (label == "backdrop");
2013-09-07 02:02:26 +02:00
Session_component *session = new (md_alloc())
Session_component(_env,
session_resources_from_args(args), label,
session_diag_from_args(args),
_view_stack, _font, _focus_updater,
_pointer_origin, _builtin_background, _framebuffer,
provides_default_bg,
_focus_reporter, *this);
2011-12-22 16:19:25 +01:00
session->apply_session_policy(_config.xml(), _domain_registry);
_session_list.insert(session);
_global_keys.apply_config(_config.xml(), _session_list);
_focus_updater.update_focus();
2011-12-22 16:19:25 +01:00
return session;
}
2011-12-22 16:19:25 +01:00
void _upgrade_session(Session_component *s, const char *args) override
{
s->upgrade(ram_quota_from_args(args));
s->upgrade(cap_quota_from_args(args));
}
2011-12-22 16:19:25 +01:00
void _destroy_session(Session_component *session) override
{
/* invalidate pointers held by other sessions to the destroyed session */
for (Session_component *s = _session_list.first(); s; s = s->next())
s->forget(*session);
_session_list.remove(session);
_global_keys.apply_config(_config.xml(), _session_list);
session->destroy_all_views();
User_state::Handle_forget_result result = _user_state.forget(*session);
2011-12-22 16:19:25 +01:00
Genode::destroy(md_alloc(), session);
/* report hover changes */
if (_hover_reporter.enabled() && result.hover_changed) {
Reporter::Xml_generator xml(_hover_reporter, [&] () {
_user_state.report_hovered_view_owner(xml, false); });
}
/* report focus changes */
if (_focus_reporter.enabled() && result.focus_changed) {
Reporter::Xml_generator xml(_focus_reporter, [&] () {
_user_state.report_focused_view_owner(xml, false); });
}
}
2011-12-22 16:19:25 +01:00
public:
/**
* Constructor
*/
Root(Env &env, Attached_rom_dataspace const &config,
Session_list &session_list, Domain_registry const &domain_registry,
Global_keys &global_keys, View_stack &view_stack, Font const &font,
User_state &user_state, View_component &pointer_origin,
View_component &builtin_background, Allocator &md_alloc,
Framebuffer::Session &framebuffer, Reporter &focus_reporter,
Reporter &hover_reporter, Focus_updater &focus_updater)
2011-12-22 16:19:25 +01:00
:
Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
_env(env), _config(config), _session_list(session_list),
_domain_registry(domain_registry), _global_keys(global_keys),
_view_stack(view_stack), _font(font), _user_state(user_state),
_pointer_origin(pointer_origin),
_builtin_background(builtin_background),
_framebuffer(framebuffer),
_focus_reporter(focus_reporter), _hover_reporter(hover_reporter),
_focus_updater(focus_updater)
{ }
/*************************************
** Visibility_controller interface **
*************************************/
void _session_visibility(Session_label const &label, Suffix const &suffix,
bool visible)
{
Nitpicker::Session::Label const selector(label, suffix);
for (Session_component *s = _session_list.first(); s; s = s->next())
if (s->matches_session_label(selector))
s->visible(visible);
_view_stack.update_all_views();
}
void hide_matching_sessions(Session_label const &label, Suffix const &suffix) override
{
_session_visibility(label, suffix, false);
}
void show_matching_sessions(Session_label const &label, Suffix const &suffix) override
{
_session_visibility(label, suffix, true);
}
2011-12-22 16:19:25 +01:00
};
struct Nitpicker::Main : Focus_updater
2013-09-06 17:34:16 +02:00
{
Env &_env;
2011-12-22 16:19:25 +01:00
Framebuffer::Connection _framebuffer { _env, Framebuffer::Mode() };
Input::Connection _input { _env };
2011-12-22 16:19:25 +01:00
Attached_dataspace _ev_ds { _env.rm(), _input.dataspace() };
typedef Pixel_rgb565 PT; /* physical pixel type */
2011-12-22 16:19:25 +01:00
/*
* Initialize framebuffer
*
* The framebuffer is encapsulated in a volatile object to allow its
* reconstruction at runtime as a response to resolution changes.
2011-12-22 16:19:25 +01:00
*/
struct Framebuffer_screen
{
Framebuffer::Session &framebuffer;
2011-12-22 16:19:25 +01:00
Framebuffer::Mode const mode = framebuffer.mode();
2013-09-08 16:20:18 +02:00
Attached_dataspace fb_ds;
2011-12-22 16:19:25 +01:00
Canvas<PT> screen = { fb_ds.local_addr<PT>(), Area(mode.width(), mode.height()) };
Area size = screen.size();
2011-12-22 16:19:25 +01:00
/**
* Constructor
*/
Framebuffer_screen(Region_map &rm, Framebuffer::Session &fb)
: framebuffer(fb), fb_ds(rm, framebuffer.dataspace()) { }
};
Reconstructible<Framebuffer_screen> _fb_screen = { _env.rm(), _framebuffer };
Point _initial_pointer_pos()
{
Area const scr_size = _fb_screen->screen.size();
return Point(scr_size.w()/2, scr_size.h()/2);
}
void _handle_fb_mode();
void _report_displays();
2011-12-22 16:19:25 +01:00
Signal_handler<Main> _fb_mode_handler = { _env.ep(), *this, &Main::_handle_fb_mode };
2013-09-08 16:20:18 +02:00
/*
* User-input policy
*/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Global_keys _global_keys { };
2013-09-06 17:34:16 +02:00
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Session_list _session_list { };
2013-09-06 17:34:16 +02:00
/*
* Construct empty domain registry. The initial version will be replaced
* on the first call of 'handle_config'.
*/
Heap _domain_registry_heap { _env.ram(), _env.rm() };
Reconstructible<Domain_registry> _domain_registry {
_domain_registry_heap, Xml_node("<config/>") };
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Focus _focus { };
View_stack _view_stack { _fb_screen->screen.size(), _focus };
User_state _user_state { _focus, _global_keys, _view_stack, _initial_pointer_pos() };
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
View_owner _global_view_owner { };
2011-12-22 16:19:25 +01:00
/*
* Create view stack with default elements
*/
Pointer_origin _pointer_origin { _global_view_owner };
2011-12-22 16:19:25 +01:00
Background _builtin_background = { _global_view_owner, Area(99999, 99999) };
2011-12-22 16:19:25 +01:00
/*
* Initialize Nitpicker root interface
*/
Sliced_heap _sliced_heap { _env.ram(), _env.rm() };
2011-12-22 16:19:25 +01:00
Reporter _pointer_reporter = { _env, "pointer" };
Reporter _hover_reporter = { _env, "hover" };
Reporter _focus_reporter = { _env, "focus" };
Reporter _keystate_reporter = { _env, "keystate" };
Reporter _clicked_reporter = { _env, "clicked" };
Reporter _displays_reporter = { _env, "displays" };
2014-07-08 17:35:40 +02:00
Attached_rom_dataspace _config_rom { _env, "config" };
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Constructible<Attached_rom_dataspace> _focus_rom { };
Tff_font::Static_glyph_buffer<4096> _glyph_buffer { };
Tff_font const _font { _binary_default_tff_start, _glyph_buffer };
Root<PT> _root { _env, _config_rom, _session_list, *_domain_registry,
_global_keys, _view_stack, _font, _user_state, _pointer_origin,
_builtin_background, _sliced_heap, _framebuffer,
_focus_reporter, _hover_reporter, *this };
/**
* Focus_updater interface
*
* Called whenever a new session appears.
*/
void update_focus() override { _handle_focus(); }
2014-01-11 02:14:09 +01:00
2013-09-07 02:17:15 +02:00
/*
* Configuration-update handler, executed in the context of the RPC
* entrypoint.
*
* In addition to installing the signal handler, we trigger first signal
* manually to turn the initial configuration into effect.
2013-09-07 02:17:15 +02:00
*/
void _handle_config();
2013-09-07 02:17:15 +02:00
Signal_handler<Main> _config_handler = { _env.ep(), *this, &Main::_handle_config };
/**
* Signal handler for externally triggered focus changes
*/
void _handle_focus();
Signal_handler<Main> _focus_handler = { _env.ep(), *this, &Main::_handle_focus };
2013-09-08 16:20:18 +02:00
/**
* Signal handler invoked on the reception of user input
*/
void _handle_input();
Signal_handler<Main> _input_handler = { _env.ep(), *this, &Main::_handle_input };
2013-09-08 16:20:18 +02:00
/**
* Counter that is incremented periodically
*/
unsigned _period_cnt = 0;
/**
* Period counter when the user was active the last time
*/
unsigned _last_button_activity_period = 0,
_last_motion_activity_period = 0;
/**
* Number of periods after the last user activity when we regard the user
* as becoming inactive
*/
unsigned _activity_threshold = 50;
/**
* True if the user has recently interacted with buttons or keys
*
* This state is reported as part of focus reports to allow the clipboard
* to dynamically adjust its information-flow policy to the user activity.
*/
bool _button_activity = false;
/**
* True if the user recently moved the pointer
*/
bool _motion_activity = false;
/**
* Perform redraw and flush pixels to the framebuffer
*/
void _draw_and_flush()
{
_view_stack.draw(_fb_screen->screen, _font).flush([&] (Rect const &rect) {
_framebuffer.refresh(rect.x1(), rect.y1(),
rect.w(), rect.h()); });
}
Main(Env &env) : _env(env)
{
_view_stack.default_background(_builtin_background);
_view_stack.stack(_pointer_origin);
_view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area()));
_view_stack.stack(_builtin_background);
_config_rom.sigh(_config_handler);
_handle_config();
_framebuffer.sync_sigh(_input_handler);
_framebuffer.mode_sigh(_fb_mode_handler);
_env.parent().announce(_env.ep().manage(_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();
_report_displays();
2013-09-08 16:20:18 +02:00
}
};
2013-09-07 02:17:15 +02:00
void Nitpicker::Main::_handle_input()
2013-09-08 16:20:18 +02:00
{
_period_cnt++;
bool const old_button_activity = _button_activity;
bool const old_motion_activity = _motion_activity;
2014-09-30 18:18:47 +02:00
/* handle batch of pending events */
User_state::Handle_input_result const result =
_user_state.handle_input_events(_ev_ds.local_addr<Input::Event>(),
_input.flush());
if (result.button_activity) {
_last_button_activity_period = _period_cnt;
_button_activity = true;
}
if (result.motion_activity) {
_last_motion_activity_period = _period_cnt;
_motion_activity = true;
}
2014-01-11 02:14:09 +01:00
/*
* Report information about currently pressed keys whenever the key state
* is affected by the incoming events.
*/
if (_keystate_reporter.enabled() && result.key_state_affected) {
Reporter::Xml_generator xml(_keystate_reporter, [&] () {
_user_state.report_keystate(xml); });
}
/*
* Report whenever a non-focused view owner received a click. This report
* can be consumed by a focus-managing component.
*/
if (_clicked_reporter.enabled() && result.last_clicked_changed) {
Reporter::Xml_generator xml(_clicked_reporter, [&] () {
_user_state.report_last_clicked_view_owner(xml); });
}
if (result.focus_changed)
_view_stack.update_all_views();
/* flag user as inactive after activity threshold is reached */
if (_period_cnt == _last_button_activity_period + _activity_threshold)
_button_activity = false;
if (_period_cnt == _last_motion_activity_period + _activity_threshold)
_motion_activity = false;
/* report mouse-position updates */
if (_pointer_reporter.enabled() && result.motion_activity) {
Reporter::Xml_generator xml(_pointer_reporter, [&] () {
_user_state.report_pointer_position(xml); });
}
/* report hover changes */
if (_hover_reporter.enabled() && !result.key_pressed
&& (result.hover_changed || (old_motion_activity != _motion_activity))) {
Reporter::Xml_generator xml(_hover_reporter, [&] () {
_user_state.report_hovered_view_owner(xml, _motion_activity); });
}
/* report focus changes */
if (result.focus_changed || (old_button_activity != _button_activity)) {
Reporter::Xml_generator xml(_focus_reporter, [&] () {
_user_state.report_focused_view_owner(xml, _button_activity); });
}
/* update pointer position */
if (result.motion_activity)
_view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area()));
/* perform redraw and flush pixels to the framebuffer */
_view_stack.draw(_fb_screen->screen, _font).flush([&] (Rect const &rect) {
_framebuffer.refresh(rect.x1(), rect.y1(),
rect.w(), rect.h()); });
_view_stack.mark_all_views_as_clean();
/* deliver framebuffer synchronization events */
for (Session_component *s = _session_list.first(); s; s = s->next())
s->submit_sync();
2013-09-08 16:20:18 +02:00
}
2014-09-30 18:18:47 +02:00
/**
* Helper function for 'handle_config'
*/
static void configure_reporter(Genode::Xml_node config, Genode::Reporter &reporter)
2014-09-30 18:18:47 +02:00
{
try {
reporter.enabled(config.sub_node("report")
.attribute_value(reporter.name().string(), false));
2014-09-30 18:18:47 +02:00
}
catch (...) { reporter.enabled(false); }
2014-09-30 18:18:47 +02:00
}
void Nitpicker::Main::_handle_focus()
{
if (!_focus_rom.constructed())
return;
_focus_rom->update();
typedef Session::Label Label;
Label const label = _focus_rom->xml().attribute_value("label", Label());
/*
* Determine session that matches the label found in the focus ROM
*/
View_owner *next_focus = nullptr;
for (Session_component *s = _session_list.first(); s; s = s->next())
if (s->label() == label)
next_focus = s;
if (next_focus)
_user_state.focus(next_focus->forwarded_focus());
else
_user_state.reset_focus();
}
void Nitpicker::Main::_handle_config()
2013-09-08 16:20:18 +02:00
{
_config_rom.update();
Xml_node const config = _config_rom.xml();
/* update global keys policy */
_global_keys.apply_config(config, _session_list);
/* update background color */
_builtin_background.color = Background::default_color();
if (config.has_sub_node("background"))
_builtin_background.color =
config.sub_node("background")
.attribute_value("color", Background::default_color());
configure_reporter(config, _pointer_reporter);
configure_reporter(config, _hover_reporter);
configure_reporter(config, _focus_reporter);
configure_reporter(config, _keystate_reporter);
configure_reporter(config, _clicked_reporter);
configure_reporter(config, _displays_reporter);
2014-07-08 17:35:40 +02:00
/* update domain registry and session policies */
for (Session_component *s = _session_list.first(); s; s = s->next())
s->reset_domain();
try { _domain_registry.construct(_domain_registry_heap, config); }
catch (...) { }
for (Session_component *s = _session_list.first(); s; s = s->next()) {
s->apply_session_policy(config, *_domain_registry);
s->notify_mode_change();
}
_view_stack.apply_origin_policy(_pointer_origin);
/*
* Domains may have changed their layering, resort the view stack with the
* new constrains.
*/
_view_stack.sort_views_by_layer();
/*
* Respond to a configuration change of the input-focus mechanism
*/
bool const focus_rom = (config.attribute_value("focus", String<16>()) == "rom");
if (_focus_rom.constructed() && !focus_rom)
_focus_rom.destruct();
if (!_focus_rom.constructed() && focus_rom) {
_focus_rom.construct(_env, "focus");
_focus_rom->sigh(_focus_handler);
_handle_focus();
}
/* disable builtin focus handling when using an external focus policy */
_user_state.focus_via_click(!_focus_rom.constructed());
/* redraw */
_view_stack.update_all_views();
/* 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); });
}
void Nitpicker::Main::_report_displays()
{
if (!_displays_reporter.enabled())
return;
Reporter::Xml_generator xml(_displays_reporter, [&] () {
xml.node("display", [&] () {
xml.attribute("width", _fb_screen->size.w());
xml.attribute("height", _fb_screen->size.h());
});
});
}
void Nitpicker::Main::_handle_fb_mode()
{
/* reconstruct framebuffer screen and menu bar */
_fb_screen.construct(_env.rm(), _framebuffer);
/* let the view stack use the new size */
_view_stack.size(Area(_fb_screen->mode.width(), _fb_screen->mode.height()));
/* redraw */
_view_stack.update_all_views();
/* notify clients about the change screen mode */
for (Session_component *s = _session_list.first(); s; s = s->next())
s->notify_mode_change();
_report_displays();
2013-09-08 16:20:18 +02:00
}
void Component::construct(Genode::Env &env)
{
static Nitpicker::Main nitpicker(env);
}