mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +00:00
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:
parent
288f79270d
commit
4bcc75365c
@ -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
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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); }
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -1,6 +0,0 @@
|
|||||||
TARGET = launcher
|
|
||||||
SRC_CC = main.cc
|
|
||||||
LIBS = base
|
|
||||||
INC_DIR += $(PRG_DIR)
|
|
||||||
|
|
||||||
CC_CXX_WARN_STRICT =
|
|
@ -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_ */
|
|
Loading…
Reference in New Issue
Block a user