diff --git a/repos/os/run/demo.run b/repos/os/run/demo.run
index bfc6922dc..cbed7e6f3 100644
--- a/repos/os/run/demo.run
+++ b/repos/os/run/demo.run
@@ -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 {
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
+
+
+
@@ -136,6 +149,13 @@ append 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
}
diff --git a/repos/os/src/app/status_bar/main.cc b/repos/os/src/app/status_bar/main.cc
new file mode 100644
index 000000000..761dc50ff
--- /dev/null
+++ b/repos/os/src/app/status_bar/main.cc
@@ -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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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
+static Genode::String read_string_attribute(Genode::Xml_node node, char const *attr,
+ Genode::String default_value)
+{
+ try {
+ char buf[N];
+ node.attribute(attr).value(buf, sizeof(buf));
+ return Genode::String(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
+ void _draw_outline(Genode::Surface &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
+ void _draw_label(Genode::Surface &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 surface(fb_ds.local_addr(), 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 focus_signal_dispatcher {
+ sig_rec, *this, &Main::handle_focus };
+
+ void handle_mode(unsigned);
+
+ Genode::Signal_dispatcher 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 { 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(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());
+
+ 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(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(sig.context());
+
+ if (dispatcher)
+ dispatcher->dispatch(sig.num());
+ }
+
+ return 0;
+}
diff --git a/repos/os/src/app/status_bar/target.mk b/repos/os/src/app/status_bar/target.mk
new file mode 100644
index 000000000..f66e445d6
--- /dev/null
+++ b/repos/os/src/app/status_bar/target.mk
@@ -0,0 +1,6 @@
+TARGET = status_bar
+SRC_CC = main.cc
+LIBS += base
+SRC_BIN = default.tff
+
+vpath %.tff $(REP_DIR)/src/server/nitpicker
diff --git a/repos/os/src/server/nitpicker/chunky_menubar.h b/repos/os/src/server/nitpicker/chunky_menubar.h
deleted file mode 100644
index a3e2cc0ec..000000000
--- a/repos/os/src/server/nitpicker/chunky_menubar.h
+++ /dev/null
@@ -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
-#include
-
-#include "menubar.h"
-
-
-template
-class Chunky_menubar : public Texture,
- public Session,
- public Menubar,
- public View
-{
- private:
-
- Canvas _canvas;
-
- public:
-
- Chunky_menubar(PT *pixels, Area size)
- :
- Texture(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(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
diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc
index 2f0fd9aae..afb753c67 100644
--- a/repos/os/src/server/nitpicker/main.cc
+++ b/repos/os/src/server/nitpicker/main.cc
@@ -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 screen = { fb_ds.local_addr(), 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 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 fb_screen = { framebuffer };
@@ -1103,7 +1097,7 @@ struct Nitpicker::Main
Genode::Volatile_object domain_registry {
*env()->heap(), Genode::Xml_node("") };
- 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();
diff --git a/repos/os/src/server/nitpicker/menubar.h b/repos/os/src/server/nitpicker/menubar.h
deleted file mode 100644
index eeaaf9d0c..000000000
--- a/repos/os/src/server/nitpicker/menubar.h
+++ /dev/null
@@ -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
diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc
index ec80c395d..ebc68518e 100644
--- a/repos/os/src/server/nitpicker/user_state.cc
+++ b/repos/os/src/server/nitpicker/user_state.cc
@@ -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();
}
diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h
index d59ac8b8f..642b481f4 100644
--- a/repos/os/src/server/nitpicker/user_state.h
+++ b/repos/os/src/server/nitpicker/user_state.h
@@ -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