Remove gems/src/app/launcher

The graphical launcher remained unused for a few years now. It is not
suitable for systems as flexible as Sculpt OS.

Issue #3512
This commit is contained in:
Norman Feske 2019-10-07 15:19:13 +02:00 committed by Christian Helmuth
parent 288f79270d
commit 4bcc75365c
12 changed files with 0 additions and 2524 deletions

View File

@ -1,306 +0,0 @@
create_boot_directory
import_from_depot [depot_user]/src/[base_src] \
[depot_user]/pkg/[drivers_interactive_pkg] \
[depot_user]/pkg/motif_wm \
[depot_user]/raw/genode_bg \
[depot_user]/pkg/fonts_fs \
[depot_user]/pkg/backdrop \
[depot_user]/src/demo \
[depot_user]/src/init \
[depot_user]/src/nitpicker \
[depot_user]/src/nit_fb \
[depot_user]/src/nit_fader \
[depot_user]/src/rom_filter \
[depot_user]/src/menu_view
install_config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="RM"/>
<service name="LOG"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="drivers" caps="1000">
<resource name="RAM" quantum="32M" constrain_phys="yes"/>
<binary name="init"/>
<route>
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<any-service> <parent/> </any-service>
</route>
<provides>
<service name="Input"/> <service name="Framebuffer"/>
</provides>
</start>
<start name="nitpicker" caps="100">
<resource name="RAM" quantum="1M"/>
<provides><service name="Nitpicker"/></provides>
<config>
<report hover="yes" focus="yes" />
<domain name="pointer" layer="1" content="client" label="no" origin="pointer" />
<domain name="panel" layer="2" content="client" label="no" hover="always" focus="transient" />
<domain name="default" layer="3" color="#ff0000" hover="always" focus="click" />
<domain name="decorator" layer="3" content="client" label="no" hover="always" focus="transient" />
<policy label_prefix="pointer" domain="pointer"/>
<policy label_prefix="wm -> launcher -> menu" domain="panel"/>
<policy label_prefix="wm -> decorator" domain="decorator"/>
<policy label_prefix="status_bar" domain="panel"/>
<default-policy domain="default"/>
<global-key name="KEY_SCROLLLOCK" label="global_keys_handler -> input" />
<global-key name="KEY_F1" label="global_keys_handler -> input" />
<global-key name="KEY_F2" label="global_keys_handler -> input" />
<global-key name="KEY_LEFTMETA" label="wm -> launcher" />
<global-key name="KEY_F3" label="wm -> launcher" />
</config>
<route>
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="pointer">
<resource name="RAM" quantum="1M"/>
<route>
<service name="Nitpicker"> <child name="nitpicker" /> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="global_keys_handler">
<resource name="RAM" quantum="1M"/>
<config>
<bool name="xray" initial="no"/>
<press name="KEY_SCROLLLOCK" bool="xray" change="toggle"/>
<press name="KEY_F1" bool="xray" change="on"/>
<release name="KEY_F1" bool="xray" change="off"/>
<press name="KEY_F2" bool="xray" change="toggle"/>
<report name="xray" delay_ms="125">
<hovered domain="panel"/>
<hovered domain="decorator"/>
<bool name="xray"/>
</report>
</config>
<route>
<service name="ROM" label="hover"> <child name="report_rom"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="Nitpicker"> <child name="nitpicker"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="status_bar">
<resource name="RAM" quantum="1M"/>
<route>
<service name="ROM" label="focus"> <child name="report_rom"/> </service>
<service name="Nitpicker"> <child name="nitpicker"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="report_rom">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="no">
<policy label="decorator_config -> xray" report="global_keys_handler -> xray"/>
<policy label="layouter -> window_list" report="wm -> window_list"/>
<policy label="layouter -> focus_request" report="wm -> focus_request" />
<policy label="decorator -> window_layout" report="layouter -> window_layout"/>
<policy label="wm -> resize_request" report="layouter -> resize_request"/>
<policy label="decorator -> pointer" report="wm -> pointer"/>
<policy label="layouter -> hover" report="decorator -> hover"/>
<policy label="wm -> focus" report="layouter -> focus"/>
<policy label="status_bar -> focus" report="nitpicker -> focus"/>
<policy label="launcher -> focus" report="nitpicker -> focus"/>
<policy label="global_keys_handler -> hover" report="nitpicker -> hover"/>
<policy label="layouter -> decorator_margins" report="decorator -> decorator_margins"/>
<policy label="layouter -> rules" report="layouter -> rules"/>
</config>
</start>
<start name="wm" caps="200">
<resource name="RAM" quantum="6M"/>
<provides>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<config>
<policy label_prefix="decorator" role="decorator"/>
<policy label_prefix="layouter" role="layouter"/>
<policy label_prefix="launcher -> menu" role="direct"/>
<policy label_prefix="launcher -> testnit" role="direct"/>
<default-policy/>
</config>
<route>
<service name="ROM" label="focus"> <child name="report_rom"/> </service>
<service name="ROM" label="resize_request"> <child name="report_rom"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<any-service>
<child name="nitpicker"/> <parent/> <any-child/>
</any-service>
</route>
</start>
<start name="layouter">
<binary name="window_layouter"/>
<resource name="RAM" quantum="4M"/>
<config rules="rom">
<report rules="yes"/>
<rules>
<screen name="screen"/>
<assign label_prefix="" target="screen" xpos="any" ypos="any"/>
</rules>
</config>
<route>
<service name="ROM" label="window_list"> <child name="report_rom"/> </service>
<service name="ROM" label="focus_request"> <child name="report_rom"/> </service>
<service name="ROM" label="hover"> <child name="report_rom"/> </service>
<service name="ROM" label="decorator_margins"> <child name="report_rom"/> </service>
<service name="ROM" label="rules"> <child name="report_rom"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<any-service>
<child name="wm"/> <parent/> <any-child/>
</any-service>
</route>
</start>
<start name="decorator">
<binary name="decorator"/>
<resource name="RAM" quantum="8M"/>
<config>
<default-policy/>
</config>
<route>
<service name="ROM" label="config">
<child name="decorator_config"/> </service>
<service name="ROM" label="window_layout">
<child name="report_rom"/> </service>
<service name="ROM" label="pointer">
<child name="report_rom"/> </service>
<any-service>
<child name="wm"/> <parent/> <any-child/>
</any-service>
</route>
</start>
<start name="decorator_config">
<binary name="rom_filter"/>
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/></provides>
<config verbose="yes">
<input name="xray_enabled" rom="xray" node="xray">
<attribute name="enabled" />
</input>
<output node="config">
<inline>
<controls>
<title/> <minimizer/> <maximizer/> <closer/>
</controls>
</inline>
<if>
<has_value input="xray_enabled" value="yes" />
<then>
<inline>
<default-policy color="#ff0000" gradient="75" />
</inline>
</then>
</if>
</output>
</config>
<route>
<service name="ROM" label="xray"> <child name="report_rom"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
<start name="fonts_fs" caps="300">
<resource name="RAM" quantum="8M"/>
<binary name="vfs"/>
<route>
<service name="ROM" label="config"> <parent label="fonts_fs.config"/> </service>
<any-service> <parent/> </any-service>
</route>
<provides> <service name="File_system"/> </provides>
</start>
<start name="launcher" caps="10000">
<resource name="RAM" quantum="60M" />
<config focus_prefix="wm -> launcher -> ">
<subsystem name="scout" title="Scout" caps="200">
<resource name="RAM" quantum="20M" />
<binary name="scout" />
</subsystem>
<subsystem name="testnit1" title="Nitpicker Test" caps="100">
<resource name="RAM" quantum="2M" />
<binary name="testnit" />
</subsystem>
<subsystem name="testnit2" title="Nitpicker Test 2" caps="100">
<resource name="RAM" quantum="2M" />
<binary name="testnit" />
</subsystem>
<subsystem name="testnit3" title="Nitpicker Test 3" caps="100">
<resource name="RAM" quantum="2M" />
<binary name="testnit" />
</subsystem>
<subsystem name="scout2" title="Scoutx" caps="200">
<resource name="RAM" quantum="20M" />
<binary name="scout" />
</subsystem>
<subsystem name="testnit4" title="Nitpicker Testx" caps="100">
<resource name="RAM" quantum="2M" />
<binary name="testnit" />
</subsystem>
<subsystem name="testnit5" title="Nitpicker Test5" caps="100">
<resource name="RAM" quantum="2M" />
<binary name="testnit" />
</subsystem>
<subsystem name="backdrop" title="Backdrop" caps="100">
<resource name="RAM" quantum="8M"/>
<binary name="backdrop" />
<config>
<libc>
<vfs>
</vfs>
</libc>
<fill color="#224433" />
</config>
</subsystem>
</config>
<route>
<service name="ROM" label="focus"> <child name="report_rom" /> </service>
<service name="File_system" label="fonts"> <child name="fonts_fs"/> </service>
<any-service> <child name="wm"/> <parent/> <any-child/> </any-service>
</route>
</start>
</config>}
build { app/launcher test/nitpicker app/status_bar app/global_keys_handler }
build_boot_image { testnit launcher global_keys_handler status_bar }
run_genode_until forever

View File

@ -1,254 +0,0 @@
/*
* \brief Context dialog
* \author Norman Feske
* \date 2014-10-04
*/
/*
* Copyright (C) 2014-2017 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 _CONTEXT_DIALOG_H_
#define _CONTEXT_DIALOG_H_
/* local includes */
#include <fading_dialog.h>
namespace Launcher { struct Context_dialog; }
class Launcher::Context_dialog : Input_event_handler, Dialog_generator,
Hover_handler, Dialog_model
{
public:
struct Response_handler
{
virtual void handle_context_kill() = 0;
virtual void handle_context_hide() = 0;
};
private:
struct Element : List<Element>::Element
{
Label label;
bool hovered = false;
bool touched = false;
bool selected = false;
Element(char const *label) : label(label) { }
};
Label _hovered() const
{
for (Element const *e = _elements.first(); e; e = e->next())
if (e->hovered)
return e->label;
return Label("");
}
List<Element> _elements;
void _generate_dialog_elements(Xml_generator &xml)
{
for (Element const *e = _elements.first(); e; e = e->next()) {
xml.node("button", [&] () {
xml.attribute("name", e->label.string());
if ((e->hovered && !_click_in_progress)
|| (e->hovered && e->touched))
xml.attribute("hovered", "yes");
if (e->selected || e->touched)
xml.attribute("selected", "yes");
xml.node("label", [&] () {
xml.attribute("text", e->label.string());
});
});
}
}
void _touch(Label const &label)
{
for (Element *e = _elements.first(); e; e = e->next())
e->touched = (e->label == label);
}
void _reset_hover()
{
for (Element *e = _elements.first(); e; e = e->next())
e->hovered = false;
}
Element _hide_button { "Hide" };
Element _kill_button { "Kill" };
Fading_dialog _dialog;
bool _open = false;
unsigned _key_cnt = 0;
Label _clicked;
bool _click_in_progress = false;
Label _subsystem;
Response_handler &_response_handler;
public:
Context_dialog(Env &env,
Report_rom_slave &report_rom_slave,
Response_handler &response_handler)
:
_dialog(env, report_rom_slave,
"context_dialog", "context_hover",
*this, *this, *this, *this,
Fading_dialog::Position(364, 64)),
_response_handler(response_handler)
{
_elements.insert(&_hide_button);
_elements.insert(&_kill_button);
_dialog.update();
}
/**
* Dialog_generator interface
*/
void generate_dialog(Xml_generator &xml) override
{
xml.node("frame", [&] () {
xml.node("vbox", [&] () {
_generate_dialog_elements(xml);
});
});
}
/**
* Hover_handler interface
*/
void hover_changed(Xml_node hover) override
{
Label const old_hovered = _hovered();
_reset_hover();
try {
Xml_node button = hover.sub_node("dialog")
.sub_node("frame")
.sub_node("vbox")
.sub_node("button");
for (Element *e = _elements.first(); e; e = e->next()) {
Label const label = button.attribute_value("name", Label(""));
if (e->label == label)
e->hovered = true;
}
} catch (Xml_node::Nonexistent_sub_node) { }
Label const new_hovered = _hovered();
if (old_hovered != new_hovered)
dialog_changed();
}
/**
* Input_event_handler interface
*/
bool handle_input_event(Input::Event const &ev) override
{
if (ev.absolute_motion()) {
/*
* Re-enable the visibility of the menu if we detect motion
* events over the menu. This way, it reappears in situations
* where the pointer temporarily leaves the view and returns.
*/
if (_open)
visible(true);
return true;
}
if (ev.hover_leave()) {
visible(false);
return true;
}
if (ev.press()) _key_cnt++;
if (ev.release()) _key_cnt--;
if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) {
Label const hovered = _hovered();
_click_in_progress = true;
_clicked = hovered;
_touch(hovered);
dialog_changed();
}
if (ev.release() && _click_in_progress && _key_cnt == 0) {
Label const hovered = _hovered();
if (_clicked == hovered) {
if (_kill_button.hovered)
_response_handler.handle_context_kill();
if (_hide_button.hovered)
_response_handler.handle_context_hide();
} else {
_touch("");
}
_clicked = Label("");
_click_in_progress = false;
dialog_changed();
}
return false;
}
void visible(bool visible)
{
if (visible == _dialog.visible())
return;
/* reset touch state when (re-)opening the context dialog */
if (visible) {
_open = true;
_touch("");
_reset_hover();
dialog_changed();
_dialog.update();
}
_dialog.visible(visible);
}
void close()
{
_open = false;
visible(false);
}
void position(Fading_dialog::Position position)
{
_dialog.position(position);
}
};
#endif /* _CONTEXT_DIALOG_H_ */

View File

@ -1,134 +0,0 @@
/*
* \brief Local nitpicker service provided to dialog slaves
* \author Norman Feske
* \date 2014-10-01
*
* This implementation of the nitpicker interface intercepts the input events
* of a dialog slave to let the launcher respond to events (like mouse clicks)
* directly.
*/
/*
* Copyright (C) 2014-2017 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 _DIALOG_NITPICKER_H_
#define _DIALOG_NITPICKER_H_
/* Genode includes */
#include <util/string.h>
#include <base/entrypoint.h>
#include <base/attached_dataspace.h>
#include <nitpicker_session/nitpicker_session.h>
#include <input_session/client.h>
#include <input/event.h>
#include <input/component.h>
/* gems includes */
#include <gems/wrapped_nitpicker_session.h>
/* local includes */
#include <types.h>
namespace Launcher {
struct Dialog_nitpicker_session;
struct Dialog_nitpicker_service;
}
struct Launcher::Dialog_nitpicker_session : Wrapped_nitpicker_session
{
struct Input_event_handler
{
/**
* Handle input event
*
* \return true if the event should be propagated to the wrapped
* nitpicker session
*/
virtual bool handle_input_event(Input::Event const &ev) = 0;
};
Env &_env;
Input_event_handler &_input_event_handler;
Rpc_entrypoint &_session_ep;
Nitpicker::Session &_nitpicker_session;
Input::Session_client _nitpicker_input { _env.rm(), _nitpicker_session.input_session() };
Attached_dataspace _nitpicker_input_ds { _env.rm(), _nitpicker_input.dataspace() };
Signal_handler<Dialog_nitpicker_session> _input_handler;
Input::Session_component _input_session { _env, _env.ram() };
/**
* Constructor
*
* \param input_sigh_ep entrypoint where the input signal handler is
* installed ('env.ep')
* \param service_ep entrypoint providing the nitpicker session
* (slave-specific ep)
*/
Dialog_nitpicker_session(Env &env, Nitpicker::Session &nitpicker_session,
Entrypoint &input_sigh_ep,
Rpc_entrypoint &session_ep,
Input_event_handler &input_event_handler)
:
Wrapped_nitpicker_session(nitpicker_session),
_env(env),
_input_event_handler(input_event_handler),
_session_ep(session_ep),
_nitpicker_session(nitpicker_session),
_input_handler(input_sigh_ep, *this, &Dialog_nitpicker_session::_handle_input)
{
_session_ep.manage(this);
_session_ep.manage(&_input_session);
_nitpicker_input.sigh(_input_handler);
_input_session.event_queue().enabled(true);
}
~Dialog_nitpicker_session()
{
_session_ep.dissolve(&_input_session);
_session_ep.dissolve(this);
}
void _handle_input()
{
Input::Event const * const events =
_nitpicker_input_ds.local_addr<Input::Event>();
while (_nitpicker_input.pending()) {
size_t const num_events = _nitpicker_input.flush();
for (size_t i = 0; i < num_events; i++) {
Input::Event const &ev = events[i];
if (_input_event_handler.handle_input_event(ev))
_input_session.submit(ev);
}
}
}
/*********************************
** Nitpicker session interface **
*********************************/
Input::Session_capability input_session() override
{
return _input_session.cap();
}
};
#endif /* _DIALOG_NITPICKER_H_ */

View File

@ -1,227 +0,0 @@
/*
* \brief Dialog
* \author Norman Feske
* \date 2014-10-02
*/
/*
* Copyright (C) 2014-2017 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 _FADING_DIALOG_H_
#define _FADING_DIALOG_H_
/* gems includes */
#include <gems/report_rom_slave.h>
#include <gems/local_reporter.h>
/* local includes */
#include <nit_fader_slave.h>
#include <menu_view_slave.h>
#include <dialog_nitpicker.h>
#include <types.h>
namespace Launcher
{
struct Dialog_generator { virtual void generate_dialog(Xml_generator &) = 0; };
struct Hover_handler { virtual void hover_changed(Xml_node hover) = 0; };
typedef Dialog_nitpicker_session::Input_event_handler Input_event_handler;
class Fading_dialog;
class Dialog_model
{
private:
bool _up_to_date = true;
friend class Fading_dialog;
public:
void dialog_changed() { _up_to_date = false; }
};
}
class Launcher::Fading_dialog : private Input_event_handler
{
private:
Region_map &_rm;
Slave::Connection<Rom_connection> _dialog_rom;
/* dialog reported locally */
Slave::Connection<Report::Connection> _dialog_report;
Slave::Connection<Rom_connection> _hover_rom;
Constructible<Attached_dataspace> _hover_ds;
/* hovered element reported by menu view */
Slave::Connection<Report::Connection> _hover_report;
Local_reporter _dialog_reporter;
Input_event_handler &_dialog_input_event_handler;
Hover_handler &_hover_handler;
Dialog_generator &_dialog_generator;
Dialog_model &_dialog_model;
void _update_dialog()
{
bool const dialog_needs_update = !_dialog_model._up_to_date;
_dialog_model._up_to_date = false;
if (dialog_needs_update) {
Local_reporter::Xml_generator xml(_dialog_reporter, [&] ()
{
_dialog_generator.generate_dialog(xml);
});
}
}
/**
* Input_event_handler interface
*/
bool handle_input_event(Input::Event const &ev) override
{
bool const forward_event = _dialog_input_event_handler.handle_input_event(ev);
_update_dialog();
return forward_event;
}
void _handle_hover_update()
{
try {
if (!_hover_ds.constructed() || _hover_rom.update() == false) {
if (_hover_ds.constructed())
_hover_ds->invalidate();
_hover_ds.construct(_rm, _hover_rom.dataspace());
}
Xml_node hover(_hover_ds->local_addr<char>());
_hover_handler.hover_changed(hover);
bool const dialog_needs_update = !_dialog_model._up_to_date;
_dialog_model._up_to_date = true;
if (dialog_needs_update) {
Local_reporter::Xml_generator xml(_dialog_reporter, [&] ()
{
_dialog_generator.generate_dialog(xml);
});
}
} catch (...) {
Genode::warning("no menu hover model available");
}
}
Signal_handler<Fading_dialog> _hover_update_handler;
private:
/*
* Entrypoint for the fader slave
*
* This entrypoint is used for handling the parent interface for the
* fader slave and for providing the wrapped nitpicker service to the
* slave. The latter cannot be provided by the main entrypoint because
* during the construction of the 'nit_fader_slave' (executed in the
* context of the main entrypoint), the slave tries to create a
* nitpicker session (to be answered with the wrapped session).
*/
size_t const _fader_slave_ep_stack_size = 4*1024*sizeof(addr_t);
Rpc_entrypoint _fader_slave_ep;
/*
* Provide wrapped nitpicker connection as a service handed out to
* the menu-view slave
*/
typedef Genode::Local_service<Dialog_nitpicker_session> Nitpicker_service;
typedef Nitpicker_service::Single_session_factory Nitpicker_factory;
Nitpicker::Connection _nitpicker_connection;
Dialog_nitpicker_session _nitpicker_session;
Nitpicker_factory _nitpicker_factory { _nitpicker_session };
Nitpicker_service _nitpicker_service { _nitpicker_factory };
Nit_fader_slave _nit_fader_slave;
Slave::Connection<Nitpicker::Connection> _nit_fader_connection;
Menu_view_slave _menu_view_slave;
bool _visible = false;
public:
typedef Menu_view_slave::Position Position;
Fading_dialog(Env &env,
Report_rom_slave &report_rom_slave,
char const *dialog_name,
char const *hover_name,
Input_event_handler &input_event_handler,
Hover_handler &hover_handler,
Dialog_generator &dialog_generator,
Dialog_model &dialog_model,
Position initial_position)
:
_rm(env.rm()),
_dialog_rom(report_rom_slave.policy(), Slave::Args("label=", dialog_name)),
_dialog_report(report_rom_slave.policy(),
Slave::Args("label=", dialog_name, ", buffer_size=4096")),
_hover_rom(report_rom_slave.policy(), Slave::Args("label=", hover_name)),
_hover_report(report_rom_slave.policy(),
Slave::Args("label=", hover_name, ", buffer_size=4096")),
_dialog_reporter(env.rm(), "dialog", _dialog_report.rpc_cap()),
_dialog_input_event_handler(input_event_handler),
_hover_handler(hover_handler),
_dialog_generator(dialog_generator),
_dialog_model(dialog_model),
_hover_update_handler(env.ep(), *this, &Fading_dialog::_handle_hover_update),
_fader_slave_ep(&env.pd(), _fader_slave_ep_stack_size, "nit_fader"),
_nitpicker_connection(env, "menu"),
_nitpicker_session(env, _nitpicker_connection, env.ep(), _fader_slave_ep, *this),
_nit_fader_slave(env, _fader_slave_ep, _nitpicker_service),
_nit_fader_connection(env.rm(), _nit_fader_slave.policy(), Slave::Args("label=menu")),
_menu_view_slave(env, _nit_fader_connection.rpc_cap(),
_dialog_rom.rpc_cap(), _hover_report.rpc_cap(),
initial_position)
{
Rom_session_client(_hover_rom).sigh(_hover_update_handler);
}
void update()
{
Local_reporter::Xml_generator xml(_dialog_reporter, [&] ()
{
_dialog_generator.generate_dialog(xml);
});
}
void visible(bool visible)
{
_nit_fader_slave.visible(visible);
_visible = visible;
}
bool visible() const { return _visible; }
void position(Position position) { _menu_view_slave.position(position); }
};
#endif /* _FADING_DIALOG_H_ */

View File

@ -1,186 +0,0 @@
/*
* \brief Launcher
* \author Norman Feske
* \date 2014-09-30
*/
/*
* Copyright (C) 2014-2017 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.
*/
/* Genode includes */
#include <base/component.h>
#include <decorator/xml_utils.h>
#include <util/reconstructible.h>
#include <base/attached_rom_dataspace.h>
#include <nitpicker_session/connection.h>
/* local includes */
#include <panel_dialog.h>
namespace Launcher {
using namespace Genode;
struct Main;
}
struct Launcher::Main
{
Env &_env;
char const *_report_rom_config =
"<config>"
" <policy label=\"menu_dialog\" report=\"menu_dialog\"/>"
" <policy label=\"menu_hover\" report=\"menu_hover\"/>"
" <policy label=\"panel_dialog\" report=\"panel_dialog\"/>"
" <policy label=\"panel_hover\" report=\"panel_hover\"/>"
" <policy label=\"context_dialog\" report=\"context_dialog\"/>"
" <policy label=\"context_hover\" report=\"context_hover\"/>"
"</config>";
Report_rom_slave _report_rom_slave { _env, _report_rom_config };
/**
* Nitpicker session used to perform session-control operations on the
* subsystem's nitpicker sessions and to receive global keyboard
* shortcuts.
*/
Nitpicker::Connection _nitpicker { _env };
Signal_handler<Main> _input_handler =
{ _env.ep(), *this, &Main::_handle_input };
void _handle_input();
unsigned _key_cnt = 0;
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;
}
Subsystem_manager _subsystem_manager { _env,
_ram_preservation(_config.xml()),
_exited_child_handler };
Heap _heap { _env.ram(), _env.rm() };
Panel_dialog _panel_dialog { _env, _heap, _report_rom_slave,
_subsystem_manager, _nitpicker };
void _handle_config();
void _handle_exited_child()
{
auto kill_child_fn = [&] (Label const &label) { _panel_dialog.kill(label); };
_subsystem_manager.for_each_exited_child(kill_child_fn);
}
Label _focus_prefix;
Genode::Attached_rom_dataspace _focus_rom { _env, "focus" };
void _handle_focus_update();
Signal_handler<Main> _focus_update_handler =
{ _env.ep(), *this, &Main::_handle_focus_update };
/**
* Constructor
*/
Main(Env &env) : _env(env)
{
_nitpicker.input()->sigh(_input_handler);
_focus_rom.sigh(_focus_update_handler);
_handle_config();
_panel_dialog.visible(true);
}
};
void Launcher::Main::_handle_config()
{
_config.update();
_focus_prefix = _config.xml().attribute_value("focus_prefix", Label());
try {
_panel_dialog.update(_config.xml()); }
catch (Allocator::Out_of_memory) {
error("out of memory while applying configuration"); }
}
void Launcher::Main::_handle_input()
{
_nitpicker.input()->for_each_event([&] (Input::Event const &e) {
if (e.press()) _key_cnt++;
if (e.release()) _key_cnt--;
/*
* 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.key_press(Input::KEY_TAB) && _key_cnt == 2)
_panel_dialog.focus_next();
});
}
void Launcher::Main::_handle_focus_update()
{
try {
_focus_rom.update();
Xml_node focus_node(_focus_rom.local_addr<char>());
/*
* Propagate focus information to panel such that the focused
* subsystem gets highlighted.
*/
Label label = focus_node.attribute_value("label", Label());
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 (...) {
Genode::warning("no focus model available");
}
}
void Component::construct(Genode::Env &env) { static Launcher::Main main(env); }

View File

@ -1,264 +0,0 @@
/*
* \brief Menu dialog
* \author Norman Feske
* \date 2014-10-04
*/
/*
* Copyright (C) 2014-2017 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 _MENU_DIALOG_H_
#define _MENU_DIALOG_H_
/* Genode includes */
#include <timer_session/connection.h>
/* local includes */
#include <fading_dialog.h>
#include <subsystem_manager.h>
#include <context_dialog.h>
namespace Launcher { struct Menu_dialog; }
class Launcher::Menu_dialog : Input_event_handler, Dialog_generator,
Hover_handler, Dialog_model
{
public:
struct Response_handler
{
virtual void handle_selection(Label const &) = 0;
virtual void handle_menu_leave() = 0;
virtual void handle_menu_motion() = 0;
};
private:
Allocator &_alloc;
Response_handler &_response_handler;
typedef String<128> Title;
struct Element : List<Element>::Element
{
Label label;
Title title;
bool hovered = false;
bool touched = false;
bool running = false;
Element(Xml_node node)
:
label(node.attribute_value("name", Label(""))),
title(node.attribute_value("title", Title(label.string())))
{ }
};
List<Element> _elements;
void _generate_dialog_elements(Xml_generator &xml)
{
for (Element const *e = _elements.first(); e; e = e->next()) {
xml.node("button", [&] () {
xml.attribute("name", e->label.string());
if ((e->hovered)
|| (e->hovered && e->touched))
xml.attribute("hovered", "yes");
if (e->running || e->touched)
xml.attribute("selected", "yes");
xml.node("label", [&] () {
xml.attribute("text", e->title.string());
});
});
}
}
Fading_dialog::Position _position { 0 - 4, 28 - 4 };
Fading_dialog _dialog;
Rect _hovered_rect;
bool _open = false;
unsigned _key_cnt = 0;
Label _hovered() const
{
for (Element const *e = _elements.first(); e; e = e->next())
if (e->hovered)
return e->label;
return Label("");
}
public:
Menu_dialog(Env &env,
Allocator &alloc,
Report_rom_slave &report_rom_slave,
Response_handler &response_handler)
:
_alloc(alloc), _response_handler(response_handler),
_dialog(env, report_rom_slave, "menu_dialog", "menu_hover",
*this, *this, *this, *this, _position)
{ }
/**
* Dialog_generator interface
*/
void generate_dialog(Xml_generator &xml) override
{
xml.node("frame", [&] () {
xml.node("vbox", [&] () {
_generate_dialog_elements(xml);
});
});
}
Rect _hovered_button_rect(Xml_node hover) const
{
Point p(0, 0);
for (;; hover = hover.sub_node()) {
p = p + Point(point_attribute(hover));
if (hover.has_type("button"))
return Rect(p, area_attribute(hover));
if (!hover.num_sub_nodes())
break;
}
return Rect();
}
/**
* Hover_handler interface
*/
void hover_changed(Xml_node hover) override
{
Label const old_hovered = _hovered();
for (Element *e = _elements.first(); e; e = e->next())
e->hovered = false;
try {
Xml_node button = hover.sub_node("dialog")
.sub_node("frame")
.sub_node("vbox")
.sub_node("button");
for (Element *e = _elements.first(); e; e = e->next()) {
Label const label = button.attribute_value("name", Label(""));
if (e->label == label) {
e->hovered = true;
_hovered_rect = _hovered_button_rect(hover);
}
}
} catch (Xml_node::Nonexistent_sub_node) { }
Label const new_hovered = _hovered();
if (old_hovered != new_hovered)
dialog_changed();
}
/**
* Input_event_handler interface
*/
bool handle_input_event(Input::Event const &ev) override
{
if (ev.hover_leave()) {
_response_handler.handle_menu_leave();
return false;
}
if (ev.absolute_motion()) {
_response_handler.handle_menu_motion();
/*
* Re-enable the visibility of the menu if we detect motion
* events over the menu. This way, it reappears in situations
* where the pointer temporarily leaves the view and returns.
*/
if (_open)
visible(true);
return true;
}
if (ev.press()) _key_cnt++;
if (ev.release()) _key_cnt--;
if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1)
_response_handler.handle_selection(_hovered());
return false;
}
void visible(bool visible)
{
if (visible == _dialog.visible())
return;
_dialog.visible(visible);
if (visible)
_open = true;
}
void close()
{
_open = false;
visible(false);
}
void running(Label const &label, bool running)
{
for (Element *e = _elements.first(); e; e = e->next())
if (e->label == label)
e->running = running;
_dialog.update();
}
void update(Xml_node subsystems)
{
if (_elements.first()) {
Genode::error("subsequent updates are not supported");
return;
}
Element *last = nullptr;
subsystems.for_each_sub_node("subsystem",
[&] (Xml_node subsystem)
{
Element * const e = new (_alloc) Element(subsystem);
_elements.insert(e, last);
last = e;
});
_dialog.update();
}
};
#endif /* _MENU_DIALOG_H_ */

View File

@ -1,165 +0,0 @@
/*
* \brief Slave used for presenting the menu
* \author Norman Feske
* \date 2014-09-30
*/
/*
* Copyright (C) 2014-2017 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 _MENU_VIEW_SLAVE_H_
#define _MENU_VIEW_SLAVE_H_
/* Genode includes */
#include <os/static_parent_services.h>
#include <os/slave.h>
#include <nitpicker_session/nitpicker_session.h>
#include <file_system_session/file_system_session.h>
/* gems includes */
#include <os/single_session_service.h>
/* local includes */
#include <types.h>
namespace Launcher { class Menu_view_slave; }
class Launcher::Menu_view_slave
{
public:
typedef Surface_base::Point Position;
private:
struct Policy_base
{
Genode::Static_parent_services<Genode::Cpu_session,
Genode::Pd_session,
Genode::Rom_session,
Genode::Log_session,
File_system::Session,
Timer::Session>
_parent_services;
Policy_base(Env &env) : _parent_services(env) { }
};
class Policy : Policy_base, public Genode::Slave::Policy
{
private:
Genode::Single_session_service<Nitpicker::Session> _nitpicker;
Genode::Single_session_service<Genode::Rom_session> _dialog_rom;
Genode::Single_session_service<Report::Session> _hover_report;
Position _position;
private:
void _configure(Position pos)
{
char config[1024];
snprintf(config, sizeof(config),
"<config xpos=\"%d\" ypos=\"%d\">\n"
" <report hover=\"yes\"/>\n"
" <libc stderr=\"/dev/log\"/>\n"
" <vfs>\n"
" <tar name=\"menu_view_styles.tar\" />\n"
" <dir name=\"fonts\"> <fs label=\"fonts\"/> </dir>\n"
" </vfs>\n"
"</config>",
pos.x(), pos.y());
configure(config);
}
static Name _name() { return "menu_view"; }
static Genode::Ram_quota _quota() { return { 6*1024*1024 }; }
static Genode::Cap_quota _caps() { return { 100 }; }
Service &_matching_service(Genode::Service::Name const &service,
Genode::Session_label const &label)
{
if (service == "Nitpicker")
return _nitpicker.service();
if ((service == "ROM") && (label == "menu_view -> dialog"))
return _dialog_rom.service();
if ((service == "Report") && (label == "menu_view -> hover"))
return _hover_report.service();
throw Genode::Service_denied();
}
public:
Policy(Genode::Env &env,
Genode::Rpc_entrypoint &ep,
Capability<Nitpicker::Session> nitpicker_session,
Capability<Rom_session> dialog_rom_session,
Capability<Report::Session> hover_report_session,
Position position)
:
Policy_base(env),
Genode::Slave::Policy(env, _name(), _name(),
Policy_base::_parent_services,
ep, _caps(), _quota()),
_nitpicker(env.rm(), nitpicker_session),
_dialog_rom(dialog_rom_session),
_hover_report(hover_report_session),
_position(position)
{
_configure(position);
}
void position(Position pos) { _configure(pos); }
Route resolve_session_request(Genode::Service::Name const &name,
Genode::Session_label const &label) override
{
try {
return Route { .service = _matching_service(name, label),
.label = label,
.diag = Genode::Session::Diag() };
}
catch (Genode::Service_denied) { }
return Genode::Slave::Policy::resolve_session_request(name, label);
}
};
Genode::size_t const _ep_stack_size = 4*1024*sizeof(Genode::addr_t);
Genode::Rpc_entrypoint _ep;
Policy _policy;
Genode::Child _child;
public:
/**
* Constructor
*/
Menu_view_slave(Genode::Env &env,
Capability<Nitpicker::Session> nitpicker_session,
Capability<Rom_session> dialog_rom_session,
Capability<Report::Session> hover_report_session,
Position initial_position)
:
_ep(&env.pd(), _ep_stack_size, "nit_fader"),
_policy(env, _ep,
nitpicker_session, dialog_rom_session,
hover_report_session, initial_position),
_child(env.rm(), _ep, _policy)
{ }
void position(Position position) { _policy.position(position); }
};
#endif /* _NIT_FADER_SLAVE_H_ */

View File

@ -1,119 +0,0 @@
/*
* \brief Slave used for toggling the visibility of a nitpicker session
* \author Norman Feske
* \date 2014-09-30
*/
/*
* Copyright (C) 2014-2017 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 _NIT_FADER_SLAVE_H_
#define _NIT_FADER_SLAVE_H_
/* Genode includes */
#include <os/static_parent_services.h>
#include <os/slave.h>
#include <nitpicker_session/nitpicker_session.h>
/* local includes */
#include <types.h>
namespace Launcher { class Nit_fader_slave; }
class Launcher::Nit_fader_slave
{
private:
struct Policy_base
{
Genode::Static_parent_services<Genode::Cpu_session,
Genode::Pd_session,
Genode::Rom_session,
Genode::Log_session,
Timer::Session>
_parent_services;
Policy_base(Env &env) : _parent_services(env) { }
};
class Policy : Policy_base, public Slave::Policy
{
private:
Genode::Service &_nitpicker_service;
protected:
static Name _name() { return "nit_fader"; }
static Genode::Ram_quota _quota() { return { 2*1024*1024 }; }
static Genode::Cap_quota _caps() { return { 50 }; }
public:
Policy(Env &env,
Rpc_entrypoint &ep,
Genode::Service &nitpicker_service)
:
Policy_base(env),
Genode::Slave::Policy(env, _name(), _name(),
Policy_base::_parent_services,
ep, _caps(), _quota()),
_nitpicker_service(nitpicker_service)
{
visible(false);
}
void visible(bool visible)
{
char config[256];
snprintf(config, sizeof(config),
"<config alpha=\"%d\" />", visible ? 255 : 0);
configure(config, strlen(config) + 1);
}
Route resolve_session_request(Genode::Service::Name const &service,
Genode::Session_label const &label) override
{
if (service == Nitpicker::Session::service_name())
return Route { .service = _nitpicker_service,
.label = label,
.diag = Session::Diag() };
return Genode::Slave::Policy::resolve_session_request(service, label);
}
};
Policy _policy;
Child _child;
public:
/**
* Constructor
*
* \param ep entrypoint used for nitpicker child thread
*/
Nit_fader_slave(Env &env,
Rpc_entrypoint &ep,
Genode::Service &nitpicker_service)
:
_policy(env, ep, nitpicker_service),
_child(env.rm(), ep, _policy)
{
visible(false);
}
Genode::Slave::Policy &policy() { return _policy; }
void visible(bool visible)
{
_policy.visible(visible);
}
};
#endif /* _NIT_FADER_SLAVE_H_ */

View File

@ -1,559 +0,0 @@
/*
* \brief Panel dialog
* \author Norman Feske
* \date 2015-10-07
*/
/*
* Copyright (C) 2015-2017 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 _PANEL_DIALOG_H_
#define _PANEL_DIALOG_H_
/* Genode includes */
#include <timer_session/connection.h>
#include <os/buffered_xml.h>
/* local includes */
#include <fading_dialog.h>
#include <subsystem_manager.h>
#include <context_dialog.h>
#include <menu_dialog.h>
namespace Launcher { struct Panel_dialog; }
class Launcher::Panel_dialog : Input_event_handler, Dialog_generator,
Hover_handler, Dialog_model,
Context_dialog::Response_handler,
Menu_dialog::Response_handler
{
private:
typedef String<128> Title;
struct Element : List<Element>::Element
{
Label const label;
Title const title;
bool hovered = false;
bool touched = false;
bool selected = false;
Element(Label label, Title title) : label(label), title(title)
{ }
};
Genode::Allocator &_alloc;
Constructible<Buffered_xml> _config;
List<Element> _elements;
Label _focus;
static char const *_menu_button_label() { return "_menu"; }
Element _menu_button { _menu_button_label(), "Menu" };
bool _focused(Element const &e)
{
size_t const label_len = strlen(e.label.string());
if (strcmp(e.label.string(), _focus.string(), label_len))
return false;
/*
* Even when the strcmp suceeded, the element's label might
* not match the focus. E.g., if two subsystems "scout" and
* "scoutx" are present the focus of "scoutx" would match both
* subsystem labels because the strcmp is limited to the length
* of the subsystem label. Hence, we need to make sure that
* the focus matched at a separator boundary.
*/
char const *char_after_label = _focus.string() + label_len;
if (*char_after_label == 0 || !strcmp(" -> ", char_after_label, 4))
return true;
return false;
}
void _generate_dialog_element(Xml_generator &xml, Element const &e)
{
xml.node("button", [&] () {
xml.attribute("name", e.label.string());
if (&e != &_menu_button)
xml.attribute("style", "subdued");
if ((e.hovered && !_click_in_progress)
|| (e.hovered && e.touched))
xml.attribute("hovered", "yes");
if (e.selected || e.touched || _focused(e))
xml.attribute("selected", "yes");
xml.node("label", [&] () {
xml.attribute("text", e.title.string());
});
});
}
class Lookup_failed { };
Element const &_lookup_const(Label const &label) const
{
for (Element const *e = _elements.first(); e; e = e->next())
if (e->label == label)
return *e;
throw Lookup_failed();
}
Element &_lookup(Label const &label)
{
for (Element *e = _elements.first(); e; e = e->next())
if (e->label == label)
return *e;
throw Lookup_failed();
}
Fading_dialog::Position _position { 0, 0 };
Timer::Connection _timer;
Subsystem_manager &_subsystem_manager;
Nitpicker::Session &_nitpicker;
Fading_dialog _dialog;
Rect _hovered_rect;
unsigned _key_cnt = 0;
Element *_clicked = nullptr;
bool _click_in_progress = false;
Signal_handler<Panel_dialog> _timer_handler;
Label _context_subsystem;
Context_dialog _context_dialog;
Menu_dialog _menu_dialog;
Element *_hovered()
{
for (Element *e = _elements.first(); e; e = e->next())
if (e->hovered)
return e;
return nullptr;
}
/**
* Lookup subsystem in config
*/
static Xml_node _subsystem(Xml_node config, char const *name)
{
Xml_node node = config.sub_node("subsystem");
for (;; node = node.next("subsystem")) {
if (node.attribute("name").has_value(name))
return node;
}
}
void _start(Label const &label)
{
if (!_config.constructed()) {
warning("attempt to start subsystem without prior configuration");
return;
}
try {
Xml_node subsystem = _subsystem(_config->xml(), label.string());
_subsystem_manager.start(subsystem);
Title const title = subsystem.attribute_value("title", Title());
Element *e = new (_alloc) Element(label, title);
/* find last element of the list */
Element *at = _elements.first();
for (; at && at->next(); at = at->next());
_elements.insert(e, at);
dialog_changed();
} catch (Xml_node::Nonexistent_sub_node) {
Genode::error("no subsystem config found for \"", label, "\"");
} catch (Subsystem_manager::Invalid_config) {
Genode::error("invalid subsystem configuration for \"", label, "\"");
}
}
void _kill(Label const &label)
{
Element &e = _lookup(label);
_subsystem_manager.kill(label.string());
_elements.remove(&e);
if (_clicked == &e)
_clicked = nullptr;
Genode::destroy(_alloc, &e);
dialog_changed();
_dialog.update();
_context_dialog.close();
_menu_dialog.running(label, false);
}
void _hide(Label const &label)
{
_nitpicker.session_control(selector(label.string()),
Nitpicker::Session::SESSION_CONTROL_HIDE);
_context_dialog.close();
}
void _open_context_dialog(Label const &label)
{
/* reset touch state in each element */
for (Element *e = _elements.first(); e; e = e->next())
e->touched = false;
Fading_dialog::Position position(_hovered_rect.p1().x(),
_hovered_rect.p2().y());
_context_subsystem = label;
_context_dialog.position(_position + position);
_context_dialog.visible(true);
}
void _handle_timer()
{
if (_click_in_progress && _clicked && _hovered() == _clicked) {
_open_context_dialog(_clicked->label);
}
_click_in_progress = false;
}
void _to_front(Label const &label)
{
_nitpicker.session_control(selector(label.string()),
Nitpicker::Session::SESSION_CONTROL_TO_FRONT);
_nitpicker.session_control(selector(label.string()),
Nitpicker::Session::SESSION_CONTROL_SHOW);
}
public:
Panel_dialog(Env &env,
Genode::Allocator &alloc,
Report_rom_slave &report_rom_slave,
Subsystem_manager &subsystem_manager,
Nitpicker::Session &nitpicker)
:
_alloc(alloc),
_timer(env),
_subsystem_manager(subsystem_manager),
_nitpicker(nitpicker),
_dialog(env, report_rom_slave, "panel_dialog", "panel_hover",
*this, *this, *this, *this, _position),
_timer_handler(env.ep(), *this, &Panel_dialog::_handle_timer),
_context_dialog(env, report_rom_slave, *this),
_menu_dialog(env, alloc, report_rom_slave, *this)
{
_elements.insert(&_menu_button);
_timer.sigh(_timer_handler);
}
/**
* Dialog_generator interface
*/
void generate_dialog(Xml_generator &xml) override
{
xml.node("hbox", [&] () {
for (Element const *e = _elements.first(); e; e = e->next())
_generate_dialog_element(xml, *e);
});
}
Rect _hovered_button_rect(Xml_node hover) const
{
Point p(0, 0);
for (;; hover = hover.sub_node()) {
p = p + Point(point_attribute(hover));
if (hover.has_type("button"))
return Rect(p, area_attribute(hover));
if (!hover.num_sub_nodes())
break;
}
return Rect();
}
/**
* Hover_handler interface
*/
void hover_changed(Xml_node hover) override
{
Element *old_hovered = _hovered();
for (Element *e = _elements.first(); e; e = e->next())
e->hovered = false;
try {
Xml_node button = hover.sub_node("dialog")
.sub_node("hbox")
.sub_node("button");
for (Element *e = _elements.first(); e; e = e->next()) {
Label const label = button.attribute_value("name", Label(""));
if (e->label == label) {
e->hovered = true;
_hovered_rect = _hovered_button_rect(hover);
}
}
} catch (Xml_node::Nonexistent_sub_node) { }
Element *new_hovered = _hovered();
if (old_hovered != new_hovered)
dialog_changed();
}
/**
* Input_event_handler interface
*/
bool handle_input_event(Input::Event const &ev) override
{
if (ev.hover_leave()) {
/*
* Let menu dialog disappear when the panel is unhovered. One
* would expect that the user had no chance to select an item
* from the menu because when entering the menu, we will no
* longer hover the panel. However, the menu disappears slowly.
* If the pointer moves over to the menu in a reasonable time,
* the visiblity of the menu is re-enabled.
*/
_menu_dialog.visible(false);
_context_dialog.visible(false);
_menu_button.selected = false;
_dialog.update();
return true;
}
if (ev.absolute_motion())
return true;
if (ev.press()) _key_cnt++;
if (ev.release()) _key_cnt--;
if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) {
_context_dialog.visible(false);
Element *hovered = _hovered();
_click_in_progress = true;
_clicked = hovered;
if (!hovered)
return false;
hovered->touched = true;
if (hovered == &_menu_button) {
/* menu button presses */
if (_menu_button.selected)
_menu_dialog.close();
else
_menu_dialog.visible(true);
_menu_button.selected = !_menu_button.selected;
_dialog.update();
return false;
}
_menu_dialog.close();
_to_front(hovered->label);
/*
* Open the context dialog after the user keeps pressing the
* button for a while.
*/
enum { CONTEXT_DELAY = 500 };
_timer.trigger_once((Genode::uint64_t)CONTEXT_DELAY*1000);
}
/*
* Open context dialog on right click
*/
if (ev.key_press(Input::BTN_RIGHT) && _key_cnt == 1) {
Element *hovered = _hovered();
if (hovered && hovered != &_menu_button)
_open_context_dialog(hovered->label);
}
if (ev.release() && _click_in_progress && _key_cnt == 0) {
Element *hovered = _hovered();
if (hovered)
hovered->touched = false;
_clicked = nullptr;
_click_in_progress = false;
}
return false;
}
/**
* Context_dialog::Response_handler interface
*/
void handle_context_kill() override
{
_kill(_context_subsystem);
}
/**
* Context_dialog::Response_handler interface
*/
void handle_context_hide() override
{
_hide(_context_subsystem);
}
/**
* Menu_dialog::Response_handler interface
*/
void handle_menu_motion()
{
_menu_button.selected = true;
_dialog.update();
}
/**
* Menu_dialog::Response_handler interface
*/
void handle_menu_leave()
{
/* XXX eventually revert the state of the menu button */
_menu_button.selected = false;
_dialog.update();
_menu_dialog.visible(false);
}
/**
* Menu_dialog::Response_handler interface
*/
void handle_selection(Label const &label) override
{
/*
* If subsystem of the specified label is already running, ignore
* the click.
*/
bool already_running = false;
for (Element *e = _elements.first(); e; e = e->next())
if (e->label == label)
already_running = true;
if (already_running) {
_to_front(label);
} else {
_start(label);
_dialog.update();
/* propagate running state of subsystem to menu dialog */
_menu_dialog.running(label, true);
}
/* let menu disappear */
_menu_dialog.close();
}
void visible(bool visible)
{
_dialog.visible(visible);
if (!visible)
_context_dialog.visible(false);
}
void kill(Label const &label)
{
_kill(label);
}
/**
* \throw Allocator::Out_of_memory
*/
void update(Xml_node config)
{
_config.construct(_alloc, config);
/* populate menu dialog with one item per subsystem */
_menu_dialog.update(_config->xml());
/* evaluate configuration */
_dialog.update();
}
void focus_changed(Label const &label)
{
_focus = label;
_dialog.update();
}
void focus_next()
{
/* find focused element */
Element *e = _elements.first();
for (; e && !_focused(*e); e = e->next());
/* none of our subsystems is focused, start with the first one */
if (!e)
e = _elements.first();
/*
* Determine next session in the list, if we reach the end, start
* at the beginning (the element right after the menu button.
*/
Element *new_focused = e->next() ? e->next() : _menu_button.next();
if (new_focused)
_to_front(new_focused->label);
}
};
#endif /* _PANEL_DIALOG_H_ */

View File

@ -1,259 +0,0 @@
/*
* \brief Management of subsystems
* \author Norman Feske
* \date 2014-10-02
*/
/*
* Copyright (C) 2014-2017 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 _SUBSYSTEM_MANAGER_H_
#define _SUBSYSTEM_MANAGER_H_
/* Genode includes */
#include <base/component.h>
#include <decorator/xml_utils.h>
/* CLI-monitor includes */
#include <cli_monitor/child.h>
namespace Launcher {
class Subsystem_manager;
using Cli_monitor::Ram;
using namespace Genode;
}
class Launcher::Subsystem_manager
{
public:
/**
* Exception types
*/
class Invalid_config { };
private:
Env & _env;
Heap _heap { _env.ram(), _env.rm() };
size_t const _ram_preservation;
struct Child : Cli_monitor::Child_base, List<Child>::Element
{
template <typename... ARGS>
Child(ARGS &&... args) : Child_base(args...) { }
};
List<Child> _children;
void _try_response_to_resource_request()
{
for (Child *child = _children.first(); child; child = child->next())
child->try_response_to_resource_request();
}
Signal_handler<Subsystem_manager> _yield_broadcast_handler =
{ _env.ep(), *this, &Subsystem_manager::_handle_yield_broadcast };
void _handle_yield_broadcast()
{
_try_response_to_resource_request();
/*
* XXX copied from 'cli_monitor/main.cc'
*/
/*
* Compute argument of yield request to be broadcasted to all
* processes.
*/
size_t amount = 0;
/* amount needed to reach preservation limit */
Ram::Status ram_status = _ram.status();
if (ram_status.avail < ram_status.preserve)
amount += ram_status.preserve - ram_status.avail;
/* sum of pending resource requests */
for (Child *child = _children.first(); child; child = child->next())
amount += child->requested_ram_quota();
for (Child *child = _children.first(); child; child = child->next())
child->yield(amount, true);
}
Signal_handler<Subsystem_manager> _resource_avail_handler =
{ _env.ep(), *this, &Subsystem_manager::_handle_resource_avail };
void _handle_resource_avail()
{
_try_response_to_resource_request();
}
Signal_handler<Subsystem_manager> _yield_response_handler =
{ _env.ep(), *this, &Subsystem_manager::_handle_yield_response };
void _handle_yield_response()
{
_try_response_to_resource_request();
}
Genode::Signal_context_capability _exited_child_sig_cap;
Ram _ram { _env.pd(),
_env.pd_session_cap(),
_ram_preservation,
_yield_broadcast_handler,
_resource_avail_handler };
static Child::Binary_name _binary_name(Xml_node subsystem)
{
try {
return subsystem.sub_node("binary")
.attribute_value("name", Child::Binary_name());
} catch (Xml_node::Nonexistent_sub_node) {
Genode::error("missing <binary> definition");
throw Invalid_config();
}
}
struct Ram_config { Number_of_bytes quantum, limit; };
static Ram_config _ram_config(Xml_node subsystem)
{
Number_of_bytes quantum = 0, limit = 0;
try {
subsystem.for_each_sub_node("resource", [&] (Xml_node rsc) {
if (rsc.attribute("name").has_value("RAM")) {
rsc.attribute("quantum").value(quantum);
if (rsc.has_attribute("limit"))
rsc.attribute("limit").value(limit);
}
});
} catch (...) {
Genode::error("invalid RAM resource declaration");
throw Invalid_config();
}
return Ram_config { quantum, limit };
}
static Cap_quota _caps_config(Xml_node subsystem)
{
Cap_quota const caps { subsystem.attribute_value("caps", 0UL) };
if (caps.value)
return caps;
Genode::error("missing 'caps' attribute for ",
subsystem.attribute_value("name", Label()));
throw Invalid_config();
}
public:
Subsystem_manager(Genode::Env & env,
size_t ram_preservation,
Genode::Signal_context_capability exited_child_sig_cap)
:
_env(env), _ram_preservation(ram_preservation),
_exited_child_sig_cap(exited_child_sig_cap)
{ }
/**
* Start subsystem
*
* \throw Invalid_config
*/
void start(Xml_node subsystem)
{
Child::Binary_name const binary_name = _binary_name(subsystem);
Label const label = subsystem.attribute_value("name", Label(""));
Ram_config const ram_config = _ram_config(subsystem);
Genode::log("starting child '", label.string(), "'");
try {
Child *child = new (_heap)
Child(_env, _ram, _heap, label, binary_name.string(),
_env.pd(),
_env.pd_session_cap(),
_env.rm(),
_caps_config(subsystem),
ram_config.quantum, ram_config.limit,
_yield_broadcast_handler,
_exited_child_sig_cap);
auto configure_with_xml = [&] (Xml_node config)
{
config.with_raw_node([&] (char const *start, size_t length) {
child->configure(start, length); });
};
/* configure child */
try {
if (subsystem.has_sub_node("configfile")) {
Xml_node const node = subsystem.sub_node("configfile");
typedef Genode::String<96> Name;
Name const name = node.attribute_value("name", Name());
Attached_rom_dataspace rom(_env, name.string());
configure_with_xml(rom.xml());
} else if (subsystem.has_sub_node("config")) {
configure_with_xml(subsystem.sub_node("config"));
} else {
configure_with_xml(Xml_node("<config/>"));
}
} catch (...) { warning("failed to configure child ", label); }
_children.insert(child);
child->start();
}
catch (Service_denied) {
Genode::error("failed to start ", binary_name);
throw Invalid_config();
}
}
void kill(char const *label)
{
for (Child *c = _children.first(); c; c = c->next()) {
if (c->label() == Label(label)) {
_children.remove(c);
destroy(_heap, c);
return;
}
}
}
/**
* Call functor for each exited child
*
* The functor takes a 'Label' as argument.
*/
template <typename FUNC>
void for_each_exited_child(FUNC const &func)
{
Child *next = nullptr;
for (Child *child = _children.first(); child; child = next) {
next = child->next();
if (child->exited())
func(Label(child->label().string()));
}
}
};
#endif /* _SUBSYSTEM_MANAGER_H_ */

View File

@ -1,6 +0,0 @@
TARGET = launcher
SRC_CC = main.cc
LIBS = base
INC_DIR += $(PRG_DIR)
CC_CXX_WARN_STRICT =

View File

@ -1,45 +0,0 @@
/*
* \brief Common types for launcher
* \author Norman Feske
* \date 2014-09-30
*/
/*
* Copyright (C) 2014-2017 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 _TYPES_H_
#define _TYPES_H_
/* Genode includes */
#include <decorator/xml_utils.h>
#include <nitpicker_session/nitpicker_session.h>
namespace Launcher {
using namespace Genode;
typedef String<128> Label;
static Nitpicker::Session::Label selector(Label label)
{
/*
* Append label separator to uniquely identify the subsystem.
* Otherwise, the selector may be ambiguous if the label of one
* subsystem starts with the label of another subsystem.
*/
char selector[Nitpicker::Session::Label::size()];
snprintf(selector, sizeof(selector), "%s ->", label.string());
return Nitpicker::Session::Label(Cstring(selector));
}
using Decorator::area_attribute;
using Decorator::point_attribute;
typedef Nitpicker::Point Point;
typedef Nitpicker::Rect Rect;
}
#endif /* _TYPES_H_ */