2014-09-30 16:46:55 +02:00
|
|
|
/*
|
|
|
|
* \brief Launcher
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2014-09-30
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Genode Labs GmbH
|
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
2016-11-23 17:07:49 +01:00
|
|
|
#include <base/component.h>
|
2014-09-30 16:46:55 +02:00
|
|
|
#include <decorator/xml_utils.h>
|
2016-12-01 17:37:08 +01:00
|
|
|
#include <util/reconstructible.h>
|
2017-01-30 11:35:12 +01:00
|
|
|
#include <base/attached_rom_dataspace.h>
|
2014-09-30 16:46:55 +02:00
|
|
|
#include <nitpicker_session/connection.h>
|
|
|
|
|
|
|
|
/* local includes */
|
2015-09-29 17:17:08 +02:00
|
|
|
#include <panel_dialog.h>
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
namespace Launcher {
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
struct Main;
|
|
|
|
}
|
2014-09-30 16:46:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
struct Launcher::Main
|
|
|
|
{
|
2016-11-23 17:07:49 +01:00
|
|
|
Env &_env;
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
char const *_report_rom_config =
|
2016-11-02 11:38:20 +01:00
|
|
|
"<config>"
|
2014-09-30 16:46:55 +02:00
|
|
|
" <policy label=\"menu_dialog\" report=\"menu_dialog\"/>"
|
|
|
|
" <policy label=\"menu_hover\" report=\"menu_hover\"/>"
|
2015-09-29 17:17:08 +02:00
|
|
|
" <policy label=\"panel_dialog\" report=\"panel_dialog\"/>"
|
|
|
|
" <policy label=\"panel_hover\" report=\"panel_hover\"/>"
|
2014-09-30 16:46:55 +02:00
|
|
|
" <policy label=\"context_dialog\" report=\"context_dialog\"/>"
|
|
|
|
" <policy label=\"context_hover\" report=\"context_hover\"/>"
|
2016-11-02 11:38:20 +01:00
|
|
|
"</config>";
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
Report_rom_slave _report_rom_slave {
|
|
|
|
_env.pd(), _env.rm(), _env.ram_session_cap(), _report_rom_config };
|
2014-09-30 16:46:55 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Nitpicker session used to perform session-control operations on the
|
2015-09-29 17:17:08 +02:00
|
|
|
* subsystem's nitpicker sessions and to receive global keyboard
|
|
|
|
* shortcuts.
|
2014-09-30 16:46:55 +02:00
|
|
|
*/
|
2016-11-23 17:07:49 +01:00
|
|
|
Nitpicker::Connection _nitpicker { _env };
|
2015-09-15 15:37:42 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
Signal_handler<Main> _input_handler =
|
|
|
|
{ _env.ep(), *this, &Main::_handle_input };
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
void _handle_input();
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
unsigned _key_cnt = 0;
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
Signal_handler<Main> _exited_child_handler =
|
|
|
|
{ _env.ep(), *this, &Main::_handle_exited_child };
|
|
|
|
|
|
|
|
Attached_rom_dataspace _config { _env, "config" };
|
|
|
|
|
|
|
|
static size_t _ram_preservation(Xml_node config)
|
|
|
|
{
|
|
|
|
char const * const node_name = "preservation";
|
|
|
|
|
|
|
|
if (config.has_sub_node(node_name)) {
|
|
|
|
|
|
|
|
Xml_node const node = config.sub_node(node_name);
|
|
|
|
if (node.attribute_value("name", Genode::String<16>()) == "RAM")
|
|
|
|
return node.attribute_value("quantum", Genode::Number_of_bytes());
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2017-01-03 12:52:42 +01:00
|
|
|
Subsystem_manager _subsystem_manager { _env,
|
2016-11-23 17:07:49 +01:00
|
|
|
_ram_preservation(_config.xml()),
|
|
|
|
_exited_child_handler };
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
Heap _heap { _env.ram(), _env.rm() };
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
Panel_dialog _panel_dialog { _env, _heap, _report_rom_slave,
|
|
|
|
_subsystem_manager, _nitpicker };
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
void _handle_config();
|
|
|
|
|
|
|
|
void _handle_exited_child()
|
2015-09-15 15:37:42 +02:00
|
|
|
{
|
2016-01-12 14:11:58 +01:00
|
|
|
auto kill_child_fn = [&] (Label const &label) { _panel_dialog.kill(label); };
|
2015-09-15 15:37:42 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
_subsystem_manager.for_each_exited_child(kill_child_fn);
|
2015-09-15 15:37:42 +02:00
|
|
|
}
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
Label _focus_prefix;
|
|
|
|
|
|
|
|
Genode::Attached_rom_dataspace _focus_rom { "focus" };
|
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
void _handle_focus_update();
|
2015-09-29 17:17:08 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
Signal_handler<Main> _focus_update_handler =
|
|
|
|
{ _env.ep(), *this, &Main::_handle_focus_update };
|
2015-09-29 17:17:08 +02:00
|
|
|
|
2014-09-30 16:46:55 +02:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
2016-11-23 17:07:49 +01:00
|
|
|
Main(Env &env) : _env(env)
|
2014-09-30 16:46:55 +02:00
|
|
|
{
|
2016-11-23 17:07:49 +01:00
|
|
|
_nitpicker.input()->sigh(_input_handler);
|
|
|
|
_focus_rom.sigh(_focus_update_handler);
|
2015-09-29 17:17:08 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
_handle_config();
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
_panel_dialog.visible(true);
|
2014-09-30 16:46:55 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
void Launcher::Main::_handle_config()
|
2014-09-30 16:46:55 +02:00
|
|
|
{
|
2016-11-23 17:07:49 +01:00
|
|
|
_config.update();
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
_focus_prefix = _config.xml().attribute_value("focus_prefix", Label());
|
2015-09-29 17:17:08 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
try {
|
|
|
|
_panel_dialog.update(_config.xml()); }
|
|
|
|
catch (Allocator::Out_of_memory) {
|
|
|
|
error("out of memory while applying configuration"); }
|
2015-09-29 17:17:08 +02:00
|
|
|
}
|
|
|
|
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
void Launcher::Main::_handle_input()
|
2015-09-29 17:17:08 +02:00
|
|
|
{
|
2016-09-12 18:41:37 +02:00
|
|
|
_nitpicker.input()->for_each_event([&] (Input::Event const &e) {
|
2015-09-29 17:17:08 +02:00
|
|
|
if (e.type() == Input::Event::PRESS) _key_cnt++;
|
|
|
|
if (e.type() == Input::Event::RELEASE) _key_cnt--;
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
/*
|
|
|
|
* The _key_cnt can become 2 only when the global key (as configured
|
|
|
|
* in the nitpicker config) is pressed together with another key.
|
|
|
|
* Hence, the following condition triggers on key combinations with
|
|
|
|
* the global modifier key, whatever the global modifier key is.
|
|
|
|
*/
|
|
|
|
if (e.type() == Input::Event::PRESS && _key_cnt == 2) {
|
|
|
|
|
|
|
|
if (e.keycode() == Input::KEY_TAB)
|
|
|
|
_panel_dialog.focus_next();
|
2014-09-30 16:46:55 +02:00
|
|
|
}
|
2016-09-12 18:41:37 +02:00
|
|
|
});
|
2014-09-30 16:46:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
void Launcher::Main::_handle_focus_update()
|
2014-09-30 16:46:55 +02:00
|
|
|
{
|
2015-09-29 17:17:08 +02:00
|
|
|
try {
|
|
|
|
_focus_rom.update();
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
Xml_node focus_node(_focus_rom.local_addr<char>());
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
/*
|
|
|
|
* Propagate focus information to panel such that the focused
|
|
|
|
* subsystem gets highlighted.
|
|
|
|
*/
|
|
|
|
Label label = focus_node.attribute_value("label", Label());
|
2014-09-30 16:46:55 +02:00
|
|
|
|
2015-09-29 17:17:08 +02:00
|
|
|
size_t const prefix_len = Genode::strlen(_focus_prefix.string());
|
|
|
|
if (!Genode::strcmp(_focus_prefix.string(), label.string(), prefix_len)) {
|
|
|
|
label = Label(label.string() + prefix_len);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A foreign nitpicker client not started by ourself has the focus.
|
|
|
|
*/
|
|
|
|
label = Label();
|
|
|
|
}
|
|
|
|
|
|
|
|
_panel_dialog.focus_changed(label);
|
|
|
|
|
|
|
|
} catch (...) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::warning("no focus model available");
|
2015-09-29 17:17:08 +02:00
|
|
|
}
|
2014-09-30 16:46:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
void Component::construct(Genode::Env &env) { static Launcher::Main main(env); }
|