nitpicker: Move status bar to separate program

This commit is contained in:
Norman Feske 2014-07-08 22:53:41 +02:00
parent 7fef141b96
commit b5b1dd03bd
8 changed files with 354 additions and 235 deletions

View File

@ -5,10 +5,11 @@
set build_components {
core init
drivers/timer
server/nitpicker app/pointer
server/nitpicker app/pointer app/status_bar
server/liquid_framebuffer app/launchpad app/scout
test/nitpicker server/nitlog
drivers/framebuffer drivers/pci drivers/input
server/report_rom
}
lappend_if [have_spec usb] build_components drivers/usb
@ -116,15 +117,27 @@ append config {
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="report_rom">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config>
<rom>
<policy label="status_bar -> focus" report="nitpicker -> focus"/>
</rom>
</config>
</start>
<start name="nitpicker">
<resource name="RAM" quantum="1M"/>
<provides><service name="Nitpicker"/></provides>
<config>
<report focus="yes" />
<domain name="pointer" layer="1" xray="no" origin="pointer" />
<domain name="default" layer="2" />
<domain name="panel" layer="2" xray="no" />
<domain name="" layer="3" ypos="18" height="-18" />
<policy label="pointer" domain="pointer"/>
<policy label="" domain="default"/>
<policy label="pointer" domain="pointer"/>
<policy label="status_bar" domain="panel"/>
<policy label="" domain=""/>
<global-key name="KEY_SCROLLLOCK" operation="xray" />
<global-key name="KEY_SYSRQ" operation="kill" />
@ -136,6 +149,13 @@ append config {
<start name="pointer">
<resource name="RAM" quantum="1M"/>
</start>
<start name="status_bar">
<resource name="RAM" quantum="1M"/>
<route>
<service name="ROM"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="launchpad">
<resource name="RAM" quantum="64M" />
<configfile name="launchpad.config" />
@ -170,7 +190,7 @@ close $launchpad_config_fd
set boot_modules {
core init
timer
nitpicker pointer liquid_fb launchpad scout
nitpicker pointer status_bar report_rom liquid_fb launchpad scout
testnit nitlog
launchpad.config
}

View File

@ -0,0 +1,282 @@
/*
* \brief Minimalistic status bar for nitpicker
* \author Norman Feske
* \date 2014-07-08
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <util/volatile_object.h>
#include <util/xml_node.h>
#include <util/color.h>
#include <os/attached_rom_dataspace.h>
#include <os/pixel_rgb565.h>
#include <nitpicker_session/connection.h>
#include <nitpicker_gfx/box_painter.h>
#include <nitpicker_gfx/text_painter.h>
typedef Genode::Color Color;
typedef Genode::String<128> Domain_name;
typedef Genode::String<128> Label;
typedef Genode::Surface_base::Area Area;
typedef Genode::Surface_base::Point Point;
typedef Genode::Surface_base::Rect Rect;
typedef Genode::size_t size_t;
/***************
** Utilities **
***************/
template <size_t N>
static Genode::String<N> read_string_attribute(Genode::Xml_node node, char const *attr,
Genode::String<N> default_value)
{
try {
char buf[N];
node.attribute(attr).value(buf, sizeof(buf));
return Genode::String<N>(buf);
}
catch (...) {
return default_value; }
}
extern char _binary_default_tff_start;
/******************
** Main program **
******************/
struct Status_bar_buffer
{
enum { HEIGHT = 18, LABEL_GAP = 15 };
Nitpicker::Connection &nitpicker;
Framebuffer::Mode const nit_mode { nitpicker.mode() };
/*
* Dimension nitpicker buffer depending on nitpicker's screen size.
* The status bar is as wide as nitpicker's screen and has a fixed
* height.
*/
Framebuffer::Mode const mode { nit_mode.width(), HEIGHT, nit_mode.format() };
Genode::Dataspace_capability init_buffer()
{
nitpicker.buffer(mode, false);
return nitpicker.framebuffer()->dataspace();
}
Genode::Attached_dataspace fb_ds { init_buffer() };
Text_painter::Font const font { &_binary_default_tff_start };
Status_bar_buffer(Nitpicker::Connection &nitpicker)
:
nitpicker(nitpicker)
{ }
template <typename PT>
void _draw_outline(Genode::Surface<PT> &surface, Point pos, char const *s)
{
for (int j = -1; j <= 1; j++)
for (int i = -1; i <= 1; i++)
if (i || j)
Text_painter::paint(surface, pos + Point(i, j), font,
Color(0, 0, 0), s);
}
template <typename PT>
void _draw_label(Genode::Surface<PT> &surface, Point pos,
Domain_name const &domain_name, Label const &label,
Color color)
{
Color const label_text_color((color.r + 255)/2,
(color.g + 255)/2,
(color.b + 255)/2);
Color const domain_text_color(255, 255, 255);
pos = pos + Point(1, 1);
_draw_outline(surface, pos, domain_name.string());
Text_painter::paint(surface, pos, font, domain_text_color,
domain_name.string());
pos = pos + Point(font.str_w(domain_name.string()) + LABEL_GAP, 0);
_draw_outline(surface, pos, label.string());
Text_painter::paint(surface, pos, font, label_text_color, label.string());
}
Area _label_size(Domain_name const &domain_name, Label const &label) const
{
return Area(font.str_w(domain_name.string()) + LABEL_GAP
+ font.str_w(label.string()) + 2,
font.str_h(domain_name.string()) + 2);
}
void draw(Domain_name const &, Label const &, Color);
};
void Status_bar_buffer::draw(Domain_name const &domain_name,
Label const &label,
Color color)
{
if (mode.format() != Framebuffer::Mode::RGB565) {
PERR("pixel format not supported");
return;
}
typedef Genode::Pixel_rgb565 PT;
Area const area(mode.width(), mode.height());
Genode::Surface<PT> surface(fb_ds.local_addr<PT>(), area);
Rect const view_rect(Point(0, 0), area);
int r = color.r, g = color.g, b = color.b;
/* dim session color a bit to improve the contrast of the label */
r = (r + 100)/2, g = (g + 100)/2, b = (b + 100)/2;
/* highlight first line with slightly brighter color */
Box_painter::paint(surface,
Rect(Point(0, 0), Area(view_rect.w(), 1)),
Color(r + (r / 2), g + (g / 2), b + (b / 2)));
/* draw slightly shaded background */
for (unsigned i = 1; i < area.h() - 1; i++) {
r -= r > 3 ? 4 : 0;
g -= g > 3 ? 4 : 0;
b -= b > 4 ? 4 : 0;
Box_painter::paint(surface,
Rect(Point(0, i), Area(view_rect.w(), 1)),
Color(r, g, b));
}
/* draw last line darker */
Box_painter::paint(surface,
Rect(Point(0, view_rect.h() - 1), Area(view_rect.w(), 1)),
Color(r / 4, g / 4, b / 4));
_draw_label(surface, view_rect.center(_label_size(domain_name, label)),
domain_name, label, color);
nitpicker.framebuffer()->refresh(0, 0, area.w(), area.h());
}
struct Main
{
Genode::Attached_rom_dataspace focus_ds { "focus" };
Genode::Signal_receiver sig_rec;
void handle_focus(unsigned);
Genode::Signal_dispatcher<Main> focus_signal_dispatcher {
sig_rec, *this, &Main::handle_focus };
void handle_mode(unsigned);
Genode::Signal_dispatcher<Main> mode_signal_dispatcher {
sig_rec, *this, &Main::handle_mode };
Nitpicker::Connection nitpicker;
/* status-bar attributes */
Domain_name domain_name;
Label label;
Color color;
Genode::Volatile_object<Status_bar_buffer> status_bar_buffer { nitpicker };
Nitpicker::Session::View_handle const view { nitpicker.create_view() };
void draw_status_bar()
{
status_bar_buffer->draw(domain_name, label, color);
}
Main()
{
/* register signal handlers */
focus_ds.sigh(focus_signal_dispatcher);
nitpicker.mode_sigh(mode_signal_dispatcher);
/* schedule initial view-stacking command, needed only once */
nitpicker.enqueue<Nitpicker::Session::Command::To_front>(view);
/* import initial state */
handle_mode(0);
handle_focus(0);
}
};
void Main::handle_focus(unsigned)
{
/* fetch new content of the focus ROM module */
focus_ds.update();
/* reset status-bar properties */
label = Label();
domain_name = Domain_name();
color = Color(0, 0, 0);
/* read new focus information from nitpicker's focus report */
try {
Genode::Xml_node node(focus_ds.local_addr<char>());
label = read_string_attribute(node, "label", Label());
domain_name = read_string_attribute(node, "domain", Domain_name());
color = node.attribute_value("color", Color(0, 0, 0));
}
catch (...) {
PWRN("could not parse focus report"); }
draw_status_bar();
}
void Main::handle_mode(unsigned)
{
status_bar_buffer.construct(nitpicker);
draw_status_bar();
Rect const geometry(Point(0, 0), Area(status_bar_buffer->mode.width(),
status_bar_buffer->mode.height()));
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(view, geometry);
nitpicker.execute();
}
int main(int, char **)
{
static Main main;
/* dispatch signals */
for (;;) {
Genode::Signal sig = main.sig_rec.wait_for_signal();
Genode::Signal_dispatcher_base *dispatcher =
dynamic_cast<Genode::Signal_dispatcher_base *>(sig.context());
if (dispatcher)
dispatcher->dispatch(sig.num());
}
return 0;
}

View File

@ -0,0 +1,6 @@
TARGET = status_bar
SRC_CC = main.cc
LIBS += base
SRC_BIN = default.tff
vpath %.tff $(REP_DIR)/src/server/nitpicker

View File

@ -1,111 +0,0 @@
/*
* \brief Chunky-pixel-based menubar
* \author Norman Feske
* \date 2006-08-22
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CHUNKY_MENUBAR_
#define _CHUNKY_MENUBAR_
#include <nitpicker_gfx/box_painter.h>
#include <nitpicker_gfx/texture_painter.h>
#include "menubar.h"
template <typename PT>
class Chunky_menubar : public Texture<PT>,
public Session,
public Menubar,
public View
{
private:
Canvas<PT> _canvas;
public:
Chunky_menubar(PT *pixels, Area size)
:
Texture<PT>(pixels, 0, size),
Session(Genode::Session_label("")),
View(*this, View::NOT_TRANSPARENT, View::NOT_BACKGROUND, 0),
_canvas(pixels, size)
{
View::geometry(Rect(Point(0, 0), size));
Session::texture(this, false);
}
/***********************
** Session interface **
***********************/
void submit_input_event(Input::Event) override { }
void submit_sync() override { }
/********************
** View interface **
********************/
int frame_size(Mode const &mode) const override { return 0; }
void frame(Canvas_base &canvas, Mode const &mode) const override { }
void draw(Canvas_base &canvas, Mode const &mode) const override
{
Clip_guard clip_guard(canvas, geometry());
/* draw menubar content */
canvas.draw_texture(abs_position(), *this, Texture_painter::SOLID, BLACK, false);
}
/***********************
** Menubar interface **
***********************/
void state(Menubar_state const state) override
{
*static_cast<Menubar_state *>(this) = state;
/* choose base color dependent on the Nitpicker state */
int r = (mode.kill()) ? 200 : (mode.xray()) ? session_color.r : (session_color.r + 100) >> 1;
int g = (mode.kill()) ? 70 : (mode.xray()) ? session_color.g : (session_color.g + 100) >> 1;
int b = (mode.kill()) ? 70 : (mode.xray()) ? session_color.b : (session_color.b + 100) >> 1;
Rect const view_rect = abs_geometry();
/* highlight first line with slightly brighter color */
_canvas.draw_box(Rect(Point(0, 0), Area(view_rect.w(), 1)),
Color(r + (r / 2), g + (g / 2), b + (b / 2)));
/* draw slightly shaded background */
for (unsigned i = 1; i < view_rect.h() - 1; i++) {
r -= r > 3 ? 4 : 0;
g -= g > 3 ? 4 : 0;
b -= b > 4 ? 4 : 0;
_canvas.draw_box(Rect(Point(0, i), Area(view_rect.w(), 1)), Color(r, g, b));
}
/* draw last line darker */
_canvas.draw_box(Rect(Point(0, view_rect.h() - 1), Area(view_rect.w(), 1)),
Color(r / 4, g / 4, b / 4));
/* draw label */
draw_label(_canvas, view_rect.center(label_size(session_label.string(), "")),
session_label.string(), WHITE, "", session_color);
}
View &view() override { return *this; }
using Menubar::state;
};
#endif

View File

@ -37,7 +37,6 @@
#include "background.h"
#include "clip_guard.h"
#include "pointer_origin.h"
#include "chunky_menubar.h"
#include "domain_registry.h"
namespace Input { class Session_component; }
@ -98,6 +97,20 @@ static void report_focus(Genode::Reporter &reporter, Session *focused_session)
}
static void report_kill_focus(Genode::Reporter &reporter)
{
if (!reporter.is_enabled())
return;
Genode::Reporter::Xml_generator xml(reporter, [&] ()
{
xml.attribute("label", "");
xml.attribute("domain", "");
xml.attribute("color", "#ff4444");
});
}
/*
* Font initialization
*/
@ -1043,11 +1056,10 @@ struct Nitpicker::Main
typedef Pixel_rgb565 PT; /* physical pixel type */
/*
* Initialize framebuffer and menu bar
* Initialize framebuffer
*
* The framebuffer and menubar are encapsulated in a volatile object to
* allow their reconstruction at runtime as a response to resolution
* changes.
* The framebuffer is encapsulated in a volatile object to allow its
* reconstruction at runtime as a response to resolution changes.
*/
struct Framebuffer_screen
{
@ -1059,28 +1071,10 @@ struct Nitpicker::Main
Screen<PT> screen = { fb_ds.local_addr<PT>(), Area(mode.width(), mode.height()) };
enum { MENUBAR_HEIGHT = 16 };
/**
* Size of menubar pixel buffer in bytes
*/
size_t const menubar_size = sizeof(PT)*mode.width()*MENUBAR_HEIGHT;
PT *menubar_pixels =
(PT *)env()->heap()->alloc(menubar_size);
Chunky_menubar<PT> menubar =
{ menubar_pixels, Area(mode.width(), MENUBAR_HEIGHT) };
/**
* Constructor
*/
Framebuffer_screen(Framebuffer::Session &fb) : framebuffer(fb) { }
/**
* Destructor
*/
~Framebuffer_screen() { env()->heap()->free(menubar_pixels, menubar_size); }
};
Genode::Volatile_object<Framebuffer_screen> fb_screen = { framebuffer };
@ -1103,7 +1097,7 @@ struct Nitpicker::Main
Genode::Volatile_object<Domain_registry> domain_registry {
*env()->heap(), Genode::Xml_node("<config/>") };
User_state user_state = { global_keys, fb_screen->screen.size(), fb_screen->menubar };
User_state user_state = { global_keys, fb_screen->screen.size() };
/*
* Create view stack with default elements
@ -1151,12 +1145,9 @@ struct Nitpicker::Main
{
// tmp_fb = &framebuffer;
fb_screen->menubar.state(Menubar_state(user_state, "", BLACK));
user_state.default_background(background);
user_state.stack(pointer_origin);
user_state.stack(background);
user_state.stack(fb_screen->menubar);
config()->sigh(config_dispatcher);
Signal_transmitter(config_dispatcher).submit();
@ -1185,6 +1176,7 @@ void Nitpicker::Main::handle_input(unsigned)
do {
Point const old_pointer_pos = user_state.pointer_pos();
::Session * const old_focused_session = user_state.Mode::focused_session();
bool const old_kill_mode = user_state.kill();
/* handle batch of pending events */
if (input.is_pending())
@ -1192,6 +1184,7 @@ void Nitpicker::Main::handle_input(unsigned)
Point const new_pointer_pos = user_state.pointer_pos();
::Session * const new_focused_session = user_state.Mode::focused_session();
bool const new_kill_mode = user_state.kill();
/* report mouse-position updates */
if (pointer_reporter.is_enabled() && old_pointer_pos != new_pointer_pos) {
@ -1207,6 +1200,24 @@ void Nitpicker::Main::handle_input(unsigned)
if (old_focused_session != new_focused_session)
report_focus(focus_reporter, new_focused_session);
/* report kill mode */
if (old_kill_mode != new_kill_mode) {
if (new_kill_mode)
report_kill_focus(focus_reporter);
if (!new_kill_mode)
report_focus(focus_reporter, new_focused_session);
}
/*
* Continuously redraw the whole screen when kill mode is active.
* Otherwise client updates (e.g., the status bar) would stay invisible
* because we do not dispatch the RPC interface during kill mode.
*/
if (new_kill_mode)
user_state.update_all_views();
/* update mouse cursor */
if (old_pointer_pos != new_pointer_pos)
user_state.geometry(pointer_origin, Rect(new_pointer_pos, Area()));
@ -1290,24 +1301,12 @@ void Nitpicker::Main::handle_config(unsigned)
void Nitpicker::Main::handle_fb_mode(unsigned)
{
/* save state of menu bar */
Menubar_state menubar_state = fb_screen->menubar.state();
/* remove old version of menu bar from view stack */
user_state.remove_view(fb_screen->menubar, false);
/* reconstruct framebuffer screen and menu bar */
fb_screen.construct(framebuffer);
/* let the view stack use the new size */
user_state.size(Area(fb_screen->mode.width(), fb_screen->mode.height()));
/* load original state into new menu bar */
fb_screen->menubar.state(menubar_state);
/* re-insert menu bar behind mouse cursor */
user_state.stack(fb_screen->menubar, &pointer_origin);
/* redraw */
user_state.update_all_views();

View File

@ -1,50 +0,0 @@
/*
* \brief Nitpicker menubar interface
* \author Norman Feske
* \date 2006-08-22
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _MENUBAR_H_
#define _MENUBAR_H_
#include "view.h"
#include "draw_label.h"
#include "mode.h"
struct Menubar_state
{
Genode::String<128> session_label;
Mode mode;
Color session_color;
Menubar_state(Mode mode, char const *session_label, Color session_color)
:
session_label(session_label), mode(mode), session_color(session_color)
{ }
Menubar_state() : session_color(BLACK) { }
};
struct Menubar : Menubar_state
{
virtual ~Menubar() { }
/**
* Set state that is displayed in the trusted menubar
*/
virtual void state(Menubar_state) = 0;
Menubar_state state() const { return *this; }
virtual View &view() = 0;
};
#endif

View File

@ -35,30 +35,14 @@ static inline bool _mouse_button(Keycode keycode) {
** User state interface **
**************************/
User_state::User_state(Global_keys &global_keys, Area view_stack_size, Menubar &menubar)
User_state::User_state(Global_keys &global_keys, Area view_stack_size)
:
View_stack(view_stack_size, *this), _global_keys(global_keys), _menubar(menubar)
View_stack(view_stack_size, *this), _global_keys(global_keys)
{ }
void User_state::_update_menubar()
{
Menubar_state state(*this, "", BLACK);
if (_input_receiver)
state = Menubar_state(*this,
_input_receiver->label().string(),
_input_receiver->color());
_menubar.state(state);
refresh_view(_menubar.view(), _menubar.view().abs_geometry());
}
void User_state::_update_all()
{
_update_menubar();
update_all_views();
}
@ -283,6 +267,4 @@ void User_state::focused_session(::Session *session)
if (!_global_key_sequence)
_input_receiver = session;
_update_menubar();
}

View File

@ -19,7 +19,6 @@
#define _USER_STATE_H_
#include "mode.h"
#include "menubar.h"
#include "view_stack.h"
#include "global_keys.h"
@ -32,13 +31,6 @@ class User_state : public Mode, public View_stack
*/
Global_keys &_global_keys;
/*
* Menubar to display trusted labeling information
* according to the current Mitpicker mode and the
* focused session.
*/
Menubar &_menubar;
/*
* Current pointer position
*/
@ -59,7 +51,6 @@ class User_state : public Mode, public View_stack
*/
bool _global_key_sequence = false;
void _update_menubar();
void _update_all();
public:
@ -67,7 +58,7 @@ class User_state : public Mode, public View_stack
/**
* Constructor
*/
User_state(Global_keys &, Area view_stack_size, Menubar &);
User_state(Global_keys &, Area view_stack_size);
/**
* Handle input event