mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-18 23:28:29 +00:00
Move repositories to 'repos/' subdirectory
This patch changes the top-level directory layout as a preparatory step for improving the tools for managing 3rd-party source codes. The rationale is described in the issue referenced below. Issue #1082
This commit is contained in:
39
repos/demo/src/server/liquid_framebuffer/README
Normal file
39
repos/demo/src/server/liquid_framebuffer/README
Normal file
@ -0,0 +1,39 @@
|
||||
Liquid frame buffer is an implementation of the frame buffer interface
|
||||
running as a client of the Nitpicker GUI server. It supports the
|
||||
following configuration options. The example shows the default
|
||||
values.
|
||||
|
||||
! <config
|
||||
!
|
||||
! <!-- enable the animated background,
|
||||
! valid values are 'on' and 'off' -->
|
||||
! animate="on"
|
||||
!
|
||||
! <!-- the initial window position and
|
||||
! size of the virtual frame buffer -->
|
||||
! xpos="400"
|
||||
! ypos="270"
|
||||
! width="500"
|
||||
! height="400"
|
||||
!
|
||||
! <!-- set the window title -->
|
||||
! title="Liquid Framebuffer"
|
||||
!
|
||||
! <!-- show a resize handle,
|
||||
! valid values are 'on' and 'off' -->
|
||||
! resize_handle="off"
|
||||
!
|
||||
! <!-- show window decoration (title bar and borders),
|
||||
! valid values are 'on' and 'off' -->
|
||||
! decoration="on"
|
||||
!
|
||||
! />
|
||||
|
||||
Because Liquid frame buffer creates the virtual frame-buffer window at
|
||||
start time, not at session-creation time, sufficient memory resources must
|
||||
be provided when starting the program. Consequently, the client does not
|
||||
need to donate memory for the frame buffer backing store.
|
||||
|
||||
Liquid frame buffer supports only one client. If multiple
|
||||
virtual frame buffers are needed, multiple instances of the
|
||||
program should be used.
|
231
repos/demo/src/server/liquid_framebuffer/framebuffer_window.h
Normal file
231
repos/demo/src/server/liquid_framebuffer/framebuffer_window.h
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* \brief Window with holding a fixed-size content element
|
||||
* \author Norman Feske
|
||||
* \date 2006-09-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _FRAMEBUFFER_WINDOW_H_
|
||||
#define _FRAMEBUFFER_WINDOW_H_
|
||||
|
||||
#include <scout/window.h>
|
||||
|
||||
#include "titlebar.h"
|
||||
#include "sky_texture.h"
|
||||
#include "fade_icon.h"
|
||||
|
||||
#define TITLEBAR_RGBA _binary_titlebar_rgba_start
|
||||
#define SIZER_RGBA _binary_sizer_rgba_start
|
||||
|
||||
extern unsigned char TITLEBAR_RGBA[];
|
||||
extern unsigned char SIZER_RGBA[];
|
||||
|
||||
|
||||
template <typename PT>
|
||||
class Framebuffer_window : public Scout::Window
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
enum { _TH = 32 }; /* height of title bar */
|
||||
|
||||
/**
|
||||
* Widgets
|
||||
*/
|
||||
Scout::Titlebar<PT> _titlebar;
|
||||
Scout::Sky_texture<PT, 512, 512> _bg_texture;
|
||||
int _bg_offset;
|
||||
Scout::Fade_icon<PT, 32, 32> _sizer;
|
||||
Scout::Element *_content;
|
||||
bool _config_alpha;
|
||||
bool _config_resize_handle;
|
||||
bool _config_decoration;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Framebuffer_window(Scout::Graphics_backend &gfx_backend,
|
||||
Scout::Element *content,
|
||||
Scout::Point position,
|
||||
Scout::Area size,
|
||||
Scout::Area max_size,
|
||||
char const *name,
|
||||
bool config_alpha,
|
||||
bool config_resize_handle,
|
||||
bool config_decoration)
|
||||
:
|
||||
Scout::Window(gfx_backend, position,
|
||||
Scout::Area(content->min_size().w() + 2,
|
||||
content->min_size().h() + 1 + _TH),
|
||||
max_size, false),
|
||||
_bg_offset(0), _content(content), _config_alpha(config_alpha),
|
||||
_config_resize_handle(config_resize_handle),
|
||||
_config_decoration(config_decoration)
|
||||
{
|
||||
/* titlebar */
|
||||
_titlebar.rgba(TITLEBAR_RGBA);
|
||||
_titlebar.text(name);
|
||||
_titlebar.event_handler(new Scout::Mover_event_handler(this));
|
||||
|
||||
/* resize handle */
|
||||
_sizer.rgba(SIZER_RGBA);
|
||||
_sizer.event_handler(new Scout::Sizer_event_handler(this));
|
||||
_sizer.alpha(100);
|
||||
|
||||
if (config_decoration)
|
||||
append(&_titlebar);
|
||||
|
||||
append(_content);
|
||||
|
||||
if (config_resize_handle)
|
||||
append(&_sizer);
|
||||
|
||||
unsigned const BORDER = 1, TITLE = _TH, RESIZER = 32;
|
||||
_min_size = Scout::Area(BORDER + RESIZER + BORDER,
|
||||
BORDER + TITLE + RESIZER + BORDER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the window title
|
||||
*/
|
||||
void name(const char *name)
|
||||
{
|
||||
_titlebar.text(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha config option
|
||||
*/
|
||||
void config_alpha(bool alpha)
|
||||
{
|
||||
_config_alpha = alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resize_handle config option
|
||||
*/
|
||||
void config_resize_handle(bool resize_handle)
|
||||
{
|
||||
if (!_config_resize_handle && resize_handle)
|
||||
append(&_sizer);
|
||||
else if (_config_resize_handle && !resize_handle)
|
||||
remove(&_sizer);
|
||||
|
||||
_config_resize_handle = resize_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the decoration config option
|
||||
*/
|
||||
void config_decoration(bool decoration)
|
||||
{
|
||||
_config_decoration = decoration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move window to new position
|
||||
*/
|
||||
void vpos(int x, int y)
|
||||
{
|
||||
Window::vpos(x, y);
|
||||
format(_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the window according to the new content size
|
||||
*/
|
||||
void content_geometry(int x, int y, int w, int h)
|
||||
{
|
||||
if (_config_decoration) {
|
||||
x -= 1; /* border */
|
||||
y -= _TH; /* title bar */
|
||||
}
|
||||
Window::vpos(x, y);
|
||||
format(Scout::Area(w + 2, h + 1 + _TH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Window interface
|
||||
*/
|
||||
void format(Scout::Area size)
|
||||
{
|
||||
using namespace Scout;
|
||||
|
||||
unsigned w = size.w();
|
||||
unsigned h = size.h();
|
||||
|
||||
/* limit window size to valid values */
|
||||
w = max(w, min_size().w());
|
||||
h = max(h, min_size().h());
|
||||
w = min(w, max_size().w());
|
||||
h = min(h, max_size().h());
|
||||
|
||||
_size = Scout::Area(w, h);
|
||||
|
||||
int y = 0;
|
||||
|
||||
if (_config_decoration) {
|
||||
_titlebar.format_fixed_width(w);
|
||||
_titlebar.geometry(Rect(Point(1, y),
|
||||
Area(_titlebar.min_size().w(),
|
||||
_titlebar.min_size().h())));
|
||||
y += _titlebar.min_size().h();
|
||||
}
|
||||
|
||||
int const content_h = ((int)h > y + 1) ? (h - y - 1) : 0;
|
||||
int const content_x = _config_decoration ? 1 : 0;
|
||||
int const content_w = w - 2;
|
||||
|
||||
_content->format_fixed_size(Area(content_w, content_h));
|
||||
_content->geometry(Rect(Point(content_x, y),
|
||||
Area(content_w, content_h)));
|
||||
|
||||
_sizer.geometry(Rect(Point(_size.w() - 32, _size.h() - 32), Area(32, 32)));
|
||||
|
||||
if (_config_decoration)
|
||||
Window::format(_size);
|
||||
else
|
||||
Window::format(Area(_size.w() - 2, _size.h() - 1 - _TH));
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure background texture offset (for background animation)
|
||||
*/
|
||||
void bg_offset(int bg_offset) { _bg_offset = bg_offset; }
|
||||
|
||||
/**
|
||||
* Element interface
|
||||
*/
|
||||
void draw(Scout::Canvas_base &canvas, Scout::Point abs_position)
|
||||
{
|
||||
using namespace Scout;
|
||||
|
||||
if (_config_alpha)
|
||||
_bg_texture.draw(canvas, Point(0, - _bg_offset));
|
||||
|
||||
Parent_element::draw(canvas, abs_position);
|
||||
|
||||
/* border */
|
||||
Color color(0, 0, 0);
|
||||
canvas.draw_box(0, 0, _size.w(), 1, color);
|
||||
if (_config_decoration)
|
||||
canvas.draw_box(0, _TH, _size.w(), 1, color);
|
||||
canvas.draw_box(0, _size.h() - 1, _size.w(), 1, color);
|
||||
canvas.draw_box(0, 1, 1, _size.h() - 2, color);
|
||||
canvas.draw_box(_size.w() - 1, 1, 1, _size.h() - 2, color);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
327
repos/demo/src/server/liquid_framebuffer/main.cc
Normal file
327
repos/demo/src/server/liquid_framebuffer/main.cc
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* \brief Nitpicker-based virtual framebuffer
|
||||
* \author Norman Feske
|
||||
* \date 2006-09-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/signal.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <os/config.h>
|
||||
#include <scout/user_state.h>
|
||||
#include <scout/nitpicker_graphics_backend.h>
|
||||
|
||||
#include "framebuffer_window.h"
|
||||
#include "services.h"
|
||||
|
||||
|
||||
/**
|
||||
* Runtime configuration
|
||||
*/
|
||||
namespace Scout { namespace Config
|
||||
{
|
||||
int iconbar_detail = 1;
|
||||
int background_detail = 1;
|
||||
int mouse_cursor = 1;
|
||||
int browser_attr = 0;
|
||||
} }
|
||||
|
||||
|
||||
void Scout::Launcher::launch() { }
|
||||
|
||||
|
||||
class Background_animator : public Scout::Tick
|
||||
{
|
||||
private:
|
||||
|
||||
Framebuffer_window<Scout::Pixel_rgb565> *_fb_win;
|
||||
|
||||
int _bg_offset;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Background_animator(Framebuffer_window<Scout::Pixel_rgb565> *fb_win):
|
||||
_fb_win(fb_win), _bg_offset(0) {
|
||||
schedule(20); }
|
||||
|
||||
/**
|
||||
* Tick interface
|
||||
*/
|
||||
int on_tick()
|
||||
{
|
||||
_fb_win->bg_offset(_bg_offset);
|
||||
_bg_offset += 2;
|
||||
_fb_win->refresh();
|
||||
|
||||
/* schedule next tick */
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Animated background
|
||||
*/
|
||||
static bool config_animate = true;
|
||||
static bool config_alpha = true;
|
||||
|
||||
/**
|
||||
* Size and position of virtual frame buffer
|
||||
*/
|
||||
static long config_fb_width = 500;
|
||||
static long config_fb_height = 400;
|
||||
static long config_fb_x = 400;
|
||||
static long config_fb_y = 260;
|
||||
|
||||
/**
|
||||
* Window title
|
||||
*/
|
||||
static const char *config_title = "Liquid Framebuffer";
|
||||
|
||||
/**
|
||||
* Resize handle
|
||||
*/
|
||||
static bool config_resize_handle = false;
|
||||
|
||||
/**
|
||||
* Window decoration
|
||||
*/
|
||||
static bool config_decoration = true;
|
||||
|
||||
/**
|
||||
* Parse configuration
|
||||
*/
|
||||
static void read_config()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Xml_node config_node = config()->xml_node();
|
||||
|
||||
try {
|
||||
char buf[16];
|
||||
config_node.attribute("animate").value(buf, sizeof(buf));
|
||||
|
||||
if (!strcmp("off", buf)) config_animate = false;
|
||||
else if (!strcmp("on", buf)) config_animate = true;
|
||||
else
|
||||
Genode::printf("Warning: invalid value for animate declaration,\n"
|
||||
" valid values are 'on', 'off.\n'");
|
||||
} catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
config_alpha = config_animate;
|
||||
|
||||
try { config_node.attribute("xpos").value(&config_fb_x); }
|
||||
catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
try { config_node.attribute("ypos").value(&config_fb_y); }
|
||||
catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
try { config_node.attribute("width").value(&config_fb_width); }
|
||||
catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
try { config_node.attribute("height").value(&config_fb_height); }
|
||||
catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
try {
|
||||
static char buf[64];
|
||||
config_node.attribute("title").value(buf, sizeof(buf));
|
||||
config_title = buf;
|
||||
} catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
try {
|
||||
char buf[16];
|
||||
config_node.attribute("decoration").value(buf, sizeof(buf));
|
||||
|
||||
if (!strcmp("off", buf)) config_decoration = false;
|
||||
else if (!strcmp("on", buf)) config_decoration = true;
|
||||
else
|
||||
Genode::printf("Warning: invalid value for decoration declaration,\n"
|
||||
" valid values are 'on', 'off.\n'");
|
||||
} catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
try {
|
||||
char buf[16];
|
||||
config_node.attribute("resize_handle").value(buf, sizeof(buf));
|
||||
|
||||
if (!strcmp("off", buf)) config_resize_handle = false;
|
||||
else if (!strcmp("on", buf)) config_resize_handle = true;
|
||||
else
|
||||
Genode::printf("Warning: invalid value for resize_handle declaration,\n"
|
||||
" valid values are 'on', 'off.\n'");
|
||||
} catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** Input handler **
|
||||
*******************/
|
||||
|
||||
struct Input_handler
|
||||
{
|
||||
GENODE_RPC(Rpc_handle_input, void, handle, Scout::Event&);
|
||||
GENODE_RPC_INTERFACE(Rpc_handle_input);
|
||||
};
|
||||
|
||||
|
||||
class Input_handler_component : public Genode::Rpc_object<Input_handler,
|
||||
Input_handler_component>
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
Scout::Platform &_pf;
|
||||
Scout::User_state &_user_state;
|
||||
Framebuffer_window<Genode::Pixel_rgb565> &_fb_win;
|
||||
Genode::Signal_receiver &_sig_rec;
|
||||
unsigned long _curr_time, _old_time;
|
||||
|
||||
public:
|
||||
|
||||
Input_handler_component(Scout::Platform &pf,
|
||||
Scout::User_state &user_state,
|
||||
Framebuffer_window<Genode::Pixel_rgb565> &fb_win,
|
||||
Genode::Signal_receiver &sig_rec)
|
||||
:
|
||||
_pf(pf),
|
||||
_user_state(user_state),
|
||||
_fb_win(fb_win),
|
||||
_sig_rec(sig_rec)
|
||||
{
|
||||
_curr_time = _old_time = _pf.timer_ticks();
|
||||
}
|
||||
|
||||
void handle(Scout::Event &ev)
|
||||
{
|
||||
using Scout::Event;
|
||||
|
||||
if (ev.type != Event::WHEEL)
|
||||
ev.mouse_position = ev.mouse_position - _user_state.view_position();
|
||||
|
||||
/* direct all keyboard events to the window content */
|
||||
if ((ev.type == Event::PRESS || ev.type == Event::RELEASE)
|
||||
&& (ev.code != Event::BTN_LEFT))
|
||||
window_content()->handle_event(ev);
|
||||
else
|
||||
_user_state.handle_event(ev);
|
||||
|
||||
if (ev.type == Event::TIMER) {
|
||||
Scout::Tick::handle(_pf.timer_ticks());
|
||||
/* check for configuration changes */
|
||||
if (_sig_rec.pending()) {
|
||||
_sig_rec.wait_for_signal();
|
||||
Genode::config()->reload();
|
||||
/* keep the current values by default */
|
||||
config_fb_x = _fb_win.view_x();
|
||||
config_fb_y = _fb_win.view_y();
|
||||
config_fb_width = _fb_win.view_w();
|
||||
config_fb_height = _fb_win.view_h();
|
||||
try { read_config(); } catch (...) { }
|
||||
_fb_win.name(config_title);
|
||||
_fb_win.config_alpha(config_alpha);
|
||||
_fb_win.config_resize_handle(config_resize_handle);
|
||||
_fb_win.config_decoration(config_decoration);
|
||||
/* must get called after 'config_decoration()' */
|
||||
_fb_win.content_geometry(config_fb_x, config_fb_y,
|
||||
config_fb_width, config_fb_height);
|
||||
_user_state.update_view_offset();
|
||||
}
|
||||
}
|
||||
|
||||
/* perform periodic redraw */
|
||||
_curr_time = _pf.timer_ticks();
|
||||
if (!_pf.event_pending() && ((_curr_time - _old_time > 20) || (_curr_time < _old_time))) {
|
||||
_old_time = _curr_time;
|
||||
_fb_win.process_redraw();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Main program
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
using namespace Scout;
|
||||
|
||||
try { read_config(); } catch (...) { }
|
||||
|
||||
/*
|
||||
* Register signal handler for config changes
|
||||
*/
|
||||
static Genode::Signal_receiver sig_rec;
|
||||
static Genode::Signal_context sig_ctx;
|
||||
|
||||
try { Genode::config()->sigh(sig_rec.manage(&sig_ctx)); } catch (...) { }
|
||||
|
||||
/* heuristic for allocating the double-buffer backing store */
|
||||
enum { WINBORDER_WIDTH = 10, WINBORDER_HEIGHT = 40 };
|
||||
|
||||
/* init platform */
|
||||
static Nitpicker::Connection nitpicker;
|
||||
static Platform pf(*nitpicker.input());
|
||||
|
||||
Area const max_size(config_fb_width + WINBORDER_WIDTH,
|
||||
config_fb_height + WINBORDER_HEIGHT);
|
||||
Point const initial_position(config_fb_x, config_fb_y);
|
||||
Area const initial_size = max_size;
|
||||
|
||||
static Nitpicker_graphics_backend
|
||||
graphics_backend(nitpicker, max_size, initial_position, initial_size);
|
||||
|
||||
/* initialize our window content */
|
||||
init_window_content(config_fb_width, config_fb_height, config_alpha);
|
||||
|
||||
/* create instance of browser window */
|
||||
static Framebuffer_window<Pixel_rgb565>
|
||||
fb_win(graphics_backend, window_content(),
|
||||
initial_position, initial_size, max_size,
|
||||
config_title, config_alpha,
|
||||
config_resize_handle, config_decoration);
|
||||
|
||||
if (config_animate) {
|
||||
static Background_animator fb_win_bg_anim(&fb_win);
|
||||
}
|
||||
|
||||
/* create user state manager */
|
||||
static User_state user_state(&fb_win, &fb_win,
|
||||
initial_position.x(), initial_position.y());
|
||||
fb_win.parent(&user_state);
|
||||
fb_win.content_geometry(config_fb_x, config_fb_y,
|
||||
config_fb_width, config_fb_height);
|
||||
|
||||
/* initialize server entry point */
|
||||
enum { STACK_SIZE = 2*1024*sizeof(Genode::addr_t) };
|
||||
static Genode::Cap_connection cap;
|
||||
static Genode::Rpc_entrypoint ep(&cap, STACK_SIZE, "liquid_fb_ep");
|
||||
|
||||
/* initialize public services */
|
||||
init_services(ep);
|
||||
|
||||
/* create local input handler service */
|
||||
static Input_handler_component input_handler(pf, user_state, fb_win,
|
||||
sig_rec);
|
||||
Genode::Capability<Input_handler> input_handler_cap = ep.manage(&input_handler);
|
||||
|
||||
/* enter main loop */
|
||||
for (;;) {
|
||||
Event ev = pf.get_event();
|
||||
input_handler_cap.call<Input_handler::Rpc_handle_input>(ev);
|
||||
|
||||
if (ev.type == Event::QUIT)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
361
repos/demo/src/server/liquid_framebuffer/services.cc
Normal file
361
repos/demo/src/server/liquid_framebuffer/services.cc
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* \brief Implementation of Framebuffer and Input services
|
||||
* \author Norman Feske
|
||||
* \date 2006-09-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.
|
||||
*/
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/semaphore.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <framebuffer_session/framebuffer_session.h>
|
||||
#include <input/component.h>
|
||||
#include <nitpicker_gfx/texture_painter.h>
|
||||
#include <os/pixel_rgb565.h>
|
||||
|
||||
#include "services.h"
|
||||
|
||||
|
||||
typedef Genode::Texture<Genode::Pixel_rgb565> Texture_rgb565;
|
||||
|
||||
|
||||
/*****************
|
||||
** Event queue **
|
||||
*****************/
|
||||
|
||||
class Event_queue
|
||||
{
|
||||
private:
|
||||
|
||||
enum { QUEUE_SIZE = 1024 };
|
||||
|
||||
Input::Event _queue[QUEUE_SIZE];
|
||||
int _head;
|
||||
int _tail;
|
||||
Genode::Semaphore _sem;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Event_queue(): _head(0), _tail(0)
|
||||
{
|
||||
Scout::memset(_queue, 0, sizeof(_queue));
|
||||
}
|
||||
|
||||
void post(Input::Event ev)
|
||||
{
|
||||
if ((_head + 1)%QUEUE_SIZE != _tail) {
|
||||
_queue[_head] = ev;
|
||||
_head = (_head + 1)%QUEUE_SIZE;
|
||||
_sem.up();
|
||||
}
|
||||
}
|
||||
|
||||
Input::Event get()
|
||||
{
|
||||
_sem.down();
|
||||
Input::Event dst_ev = _queue[_tail];
|
||||
_tail = (_tail + 1)%QUEUE_SIZE;
|
||||
return dst_ev;
|
||||
}
|
||||
|
||||
int pending() { return _head != _tail; }
|
||||
|
||||
} _ev_queue;
|
||||
|
||||
|
||||
/***************************
|
||||
** Input service backend **
|
||||
***************************/
|
||||
|
||||
namespace Input {
|
||||
|
||||
void event_handling(bool enable) { }
|
||||
bool event_pending() { return _ev_queue.pending(); }
|
||||
Event get_event() { return _ev_queue.get(); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Window_content : public Scout::Element
|
||||
{
|
||||
private:
|
||||
|
||||
class Content_event_handler : public Scout::Event_handler
|
||||
{
|
||||
private:
|
||||
|
||||
Event_queue *_ev_queue;
|
||||
Scout::Point _old_mouse_position;
|
||||
Element *_element;
|
||||
|
||||
public:
|
||||
|
||||
Content_event_handler(Event_queue *ev_queue,
|
||||
Scout::Element *element)
|
||||
:
|
||||
_ev_queue(ev_queue), _element(element) { }
|
||||
|
||||
void handle(Scout::Event &ev)
|
||||
{
|
||||
using namespace Scout;
|
||||
|
||||
Point mouse_position = ev.mouse_position - _element->abs_position();
|
||||
|
||||
int code = 0;
|
||||
|
||||
if (ev.type == Event::PRESS || ev.type == Event::RELEASE)
|
||||
code = ev.code;
|
||||
|
||||
Input::Event::Type type;
|
||||
|
||||
type = (ev.type == Event::MOTION) ? Input::Event::MOTION
|
||||
: (ev.type == Event::PRESS) ? Input::Event::PRESS
|
||||
: (ev.type == Event::RELEASE) ? Input::Event::RELEASE
|
||||
: Input::Event::INVALID;
|
||||
|
||||
if (type != Input::Event::INVALID)
|
||||
_ev_queue->post(Input::Event(type, code, mouse_position.x(),
|
||||
mouse_position.y(),
|
||||
mouse_position.x() - _old_mouse_position.x(),
|
||||
mouse_position.y() - _old_mouse_position.y()));
|
||||
|
||||
_old_mouse_position = mouse_position;
|
||||
}
|
||||
};
|
||||
|
||||
struct Fb_texture
|
||||
{
|
||||
unsigned w, h;
|
||||
Genode::Attached_ram_dataspace ds;
|
||||
Genode::Pixel_rgb565 *pixel;
|
||||
unsigned char *alpha;
|
||||
Genode::Texture<Genode::Pixel_rgb565> texture;
|
||||
|
||||
Fb_texture(unsigned w, unsigned h, bool config_alpha)
|
||||
:
|
||||
w(w), h(h),
|
||||
ds(Genode::env()->ram_session(), w*h*sizeof(Genode::Pixel_rgb565)),
|
||||
pixel(ds.local_addr<Genode::Pixel_rgb565>()),
|
||||
alpha((unsigned char *)Genode::env()->heap()->alloc(w*h)),
|
||||
texture(pixel, alpha, Scout::Area(w, h))
|
||||
{
|
||||
int alpha_min = config_alpha ? 0 : 255;
|
||||
|
||||
/* init alpha channel */
|
||||
for (unsigned y = 0; y < h; y++)
|
||||
for (unsigned x = 0; x < w; x++) {
|
||||
|
||||
int v = (x * y + (w*h)/4) / w;
|
||||
v = v + (x + y)/2;
|
||||
int a = v & 0xff;
|
||||
if (v & 0x100)
|
||||
a = 255 - a;
|
||||
|
||||
a += (Genode::Dither_matrix::value(x, y) - 127) >> 4;
|
||||
|
||||
alpha[y*w + x] = Genode::max(alpha_min, Genode::min(a, 255));
|
||||
}
|
||||
}
|
||||
|
||||
~Fb_texture()
|
||||
{
|
||||
Genode::env()->heap()->free(alpha, w*h);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool _config_alpha;
|
||||
Content_event_handler _ev_handler;
|
||||
Fb_texture *_fb;
|
||||
|
||||
/**
|
||||
* Size of the framebuffer handed out by the next call of 'dataspace'
|
||||
*/
|
||||
Scout::Area _next_size;
|
||||
|
||||
/**
|
||||
* Most current designated size of the framebuffer as defined by the
|
||||
* user.
|
||||
*
|
||||
* The '_designated_size' may be updated any time when the user drags
|
||||
* the resize handle of the window. It is propagated to '_next_size'
|
||||
* not before the framebuffer client requests the current mode. Once
|
||||
* the mode information is passed to the client, it is locked until
|
||||
* the client requests the mode again.
|
||||
*/
|
||||
Scout::Area _designated_size;
|
||||
|
||||
Genode::Signal_context_capability _mode_sigh;
|
||||
|
||||
public:
|
||||
|
||||
Window_content(unsigned fb_w, unsigned fb_h, Event_queue *ev_queue,
|
||||
bool config_alpha)
|
||||
:
|
||||
_config_alpha(config_alpha),
|
||||
_ev_handler(ev_queue, this),
|
||||
_fb(new (Genode::env()->heap()) Fb_texture(fb_w, fb_h, _config_alpha)),
|
||||
_next_size(fb_w, fb_h),
|
||||
_designated_size(_next_size)
|
||||
{
|
||||
_min_size = Scout::Area(_fb->w, _fb->h);
|
||||
|
||||
event_handler(&_ev_handler);
|
||||
}
|
||||
|
||||
Genode::Dataspace_capability fb_ds_cap() { return _fb->ds.cap(); }
|
||||
|
||||
unsigned fb_w() { return _fb->w; }
|
||||
unsigned fb_h() { return _fb->h; }
|
||||
|
||||
Scout::Area mode_size()
|
||||
{
|
||||
_next_size = _designated_size;
|
||||
return _next_size;
|
||||
}
|
||||
|
||||
void mode_sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
_mode_sigh = sigh;
|
||||
}
|
||||
|
||||
void realloc_framebuffer()
|
||||
{
|
||||
/* skip reallocation if size has not changed */
|
||||
if (_next_size.w() == _fb->w && _next_size.h() == _fb->h)
|
||||
return;
|
||||
|
||||
Genode::destroy(Genode::env()->heap(), _fb);
|
||||
|
||||
_fb = new (Genode::env()->heap())
|
||||
Fb_texture(_next_size.w(), _next_size.h(), _config_alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Element interface
|
||||
*/
|
||||
void draw(Scout::Canvas_base &canvas, Scout::Point abs_position)
|
||||
{
|
||||
canvas.draw_texture(abs_position + _position, _fb->texture);
|
||||
}
|
||||
|
||||
void format_fixed_size(Scout::Area size)
|
||||
{
|
||||
_designated_size = size;
|
||||
|
||||
/* notify framebuffer client about mode change */
|
||||
if (_mode_sigh.valid())
|
||||
Genode::Signal_transmitter(_mode_sigh).submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Window_content *_window_content;
|
||||
|
||||
Scout::Element *window_content() { return _window_content; }
|
||||
|
||||
|
||||
/***********************************************
|
||||
** Implementation of the framebuffer service **
|
||||
***********************************************/
|
||||
|
||||
namespace Framebuffer
|
||||
{
|
||||
class Session_component : public Genode::Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Window_content &_window_content;
|
||||
|
||||
Genode::Signal_context_capability _sync_sigh;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Window_content &window_content)
|
||||
: _window_content(window_content) { }
|
||||
|
||||
Genode::Dataspace_capability dataspace() override
|
||||
{
|
||||
_window_content.realloc_framebuffer();
|
||||
return _window_content.fb_ds_cap();
|
||||
}
|
||||
|
||||
Mode mode() const override
|
||||
{
|
||||
return Mode(_window_content.mode_size().w(),
|
||||
_window_content.mode_size().h(), Mode::RGB565);
|
||||
}
|
||||
|
||||
void mode_sigh(Genode::Signal_context_capability sigh) override {
|
||||
_window_content.mode_sigh(sigh); }
|
||||
|
||||
void sync_sigh(Genode::Signal_context_capability sigh) override {
|
||||
_sync_sigh = sigh; }
|
||||
|
||||
void refresh(int x, int y, int w, int h) override
|
||||
{
|
||||
_window_content.redraw_area(x, y, w, h);
|
||||
|
||||
if (_sync_sigh.valid())
|
||||
Genode::Signal_transmitter(_sync_sigh).submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Window_content &_window_content;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) override {
|
||||
return new (md_alloc()) Session_component(_window_content); }
|
||||
|
||||
public:
|
||||
|
||||
Root(Genode::Rpc_entrypoint *session_ep,
|
||||
Genode::Allocator *md_alloc,
|
||||
Window_content &window_content)
|
||||
:
|
||||
Genode::Root_component<Session_component>(session_ep, md_alloc),
|
||||
_window_content(window_content)
|
||||
{ }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void init_window_content(unsigned fb_w, unsigned fb_h, bool config_alpha)
|
||||
{
|
||||
static Window_content content(fb_w, fb_h, &_ev_queue, config_alpha);
|
||||
_window_content = &content;
|
||||
}
|
||||
|
||||
|
||||
void init_services(Genode::Rpc_entrypoint &ep)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/*
|
||||
* Let the entry point serve the framebuffer and input root interfaces
|
||||
*/
|
||||
static Framebuffer::Root fb_root(&ep, env()->heap(), *_window_content);
|
||||
static Input::Root input_root(&ep, env()->heap());
|
||||
|
||||
/*
|
||||
* Now, the root interfaces are ready to accept requests.
|
||||
* This is the right time to tell mummy about our services.
|
||||
*/
|
||||
env()->parent()->announce(ep.manage(&fb_root));
|
||||
env()->parent()->announce(ep.manage(&input_root));
|
||||
}
|
28
repos/demo/src/server/liquid_framebuffer/services.h
Normal file
28
repos/demo/src/server/liquid_framebuffer/services.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* \brief Fb_nit-internal service interface
|
||||
* \author Norman Feske
|
||||
* \date 2006-09-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 _SERVICES_H_
|
||||
#define _SERVICES_H_
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
#include <scout/canvas.h>
|
||||
|
||||
#include "elements.h"
|
||||
|
||||
extern Scout::Element *window_content();
|
||||
extern void init_window_content(unsigned fb_w, unsigned fb_h, bool config_alpha);
|
||||
extern void init_services(Genode::Rpc_entrypoint &ep);
|
||||
extern void lock_window_content();
|
||||
extern void unlock_window_content();
|
||||
|
||||
#endif
|
5
repos/demo/src/server/liquid_framebuffer/target.mk
Normal file
5
repos/demo/src/server/liquid_framebuffer/target.mk
Normal file
@ -0,0 +1,5 @@
|
||||
TARGET = liquid_fb
|
||||
LIBS = scout_widgets config
|
||||
SRC_CC = main.cc services.cc
|
||||
INC_DIR += $(REP_DIR)/src/app/scout \
|
||||
$(REP_DIR)/src/server/framebuffer/sdl
|
466
repos/demo/src/server/nitlog/main.cc
Normal file
466
repos/demo/src/server/nitlog/main.cc
Normal file
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* \brief Nitpicker-based logging service
|
||||
* \author Norman Feske
|
||||
* \date 2006-09-18
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <util/arg_string.h>
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <root/component.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <log_session/log_session.h>
|
||||
#include <nitpicker_session/connection.h>
|
||||
#include <nitpicker_view/client.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <input/event.h>
|
||||
#include <os/pixel_rgb565.h>
|
||||
|
||||
/*
|
||||
* Nitpicker's graphics backend
|
||||
*/
|
||||
#include <nitpicker_gfx/text_painter.h>
|
||||
#include <nitpicker_gfx/box_painter.h>
|
||||
|
||||
|
||||
enum { LOG_W = 80 }; /* number of visible characters per line */
|
||||
enum { LOG_H = 25 }; /* number of lines of log window */
|
||||
|
||||
typedef Text_painter::Font Font;
|
||||
typedef Genode::Surface_base::Point Point;
|
||||
typedef Genode::Surface_base::Area Area;
|
||||
typedef Genode::Surface_base::Rect Rect;
|
||||
typedef Genode::Color Color;
|
||||
|
||||
|
||||
/*
|
||||
* Font initialization
|
||||
*/
|
||||
extern char _binary_mono_tff_start;
|
||||
Font default_font(&_binary_mono_tff_start);
|
||||
|
||||
|
||||
/**
|
||||
* Pixel-type-independent interface to graphics backend
|
||||
*/
|
||||
struct Canvas_base
|
||||
{
|
||||
virtual void draw_string(Point, Font const &, Color, char const *) = 0;
|
||||
|
||||
virtual void draw_box(Rect, Color) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pixel-type-specific graphics backend
|
||||
*/
|
||||
template <typename PT>
|
||||
class Canvas : public Canvas_base
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Surface<PT> _surface;
|
||||
|
||||
public:
|
||||
|
||||
Canvas(PT *base, Area size) : _surface(base, size) { }
|
||||
|
||||
void clip(Rect rect) { _surface.clip(rect); }
|
||||
|
||||
void draw_string(Point p, Font const &font, Color color,
|
||||
char const *sstr)
|
||||
{
|
||||
Text_painter::paint(_surface, p, font, color, sstr);
|
||||
}
|
||||
|
||||
void draw_box(Rect rect, Color color)
|
||||
{
|
||||
Box_painter::paint(_surface, rect, color);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Log_entry
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Genode::Color Color;
|
||||
|
||||
char _label[64];
|
||||
char _text[LOG_W];
|
||||
char _attr[LOG_W];
|
||||
Color _color;
|
||||
int _label_len;
|
||||
int _text_len;
|
||||
int _id;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructors
|
||||
*
|
||||
* The default constructor is used to build an array of log entries.
|
||||
*/
|
||||
Log_entry() { }
|
||||
|
||||
Log_entry(Genode::Color color, const char *label, const char *log_text, const char *log_attr, int id):
|
||||
_color(color), _id(id)
|
||||
{
|
||||
Genode::strncpy(_label, label, sizeof(_label));
|
||||
Genode::strncpy(_text, log_text, sizeof(_text));
|
||||
|
||||
_label_len = Genode::strlen(_label);
|
||||
_text_len = Genode::strlen(_text);
|
||||
|
||||
/* replace line feed at the end of the text with a blank */
|
||||
if (_text_len > 0 && _text[_text_len - 1] == '\n')
|
||||
_text[_text_len - 1] = ' ';
|
||||
|
||||
Genode::memcpy(_attr, log_attr, _text_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw entry
|
||||
*
|
||||
* An entry consists of a label and text. The argument 'new_section'
|
||||
* marks a transition of output from one session to another. This
|
||||
* information is used to separate sessions visually.
|
||||
*/
|
||||
void draw(Canvas_base &canvas, int y, int new_section = false)
|
||||
{
|
||||
Color label_fgcol = Color(Genode::min(255, _color.r + 200),
|
||||
Genode::min(255, _color.g + 200),
|
||||
Genode::min(255, _color.b + 200));
|
||||
Color label_bgcol = Color(_color.r, _color.g, _color.b);
|
||||
Color text_fgcol = Color(180, 180, 180);
|
||||
Color text_bgcol = Color(_color.r / 2, _color.g / 2, _color.b / 2);
|
||||
|
||||
/* calculate label dimensions */
|
||||
int label_w = default_font.str_w(_label);
|
||||
int label_h = default_font.str_h(_label);
|
||||
|
||||
if (new_section) {
|
||||
canvas.draw_box(Rect(Point(1, y), Area(label_w + 2, label_h - 1)), label_bgcol);
|
||||
canvas.draw_string(Point(1, y - 1), default_font, label_fgcol, _label);
|
||||
canvas.draw_box(Rect(Point(1, y + label_h - 1), Area(label_w + 2, 1)), Color(0, 0, 0));
|
||||
canvas.draw_box(Rect(Point(label_w + 2, y), Area(1, label_h - 1)), _color);
|
||||
canvas.draw_box(Rect(Point(label_w + 3, y), Area(1, label_h - 1)), Color(0, 0, 0));
|
||||
canvas.draw_box(Rect(Point(label_w + 4, y), Area(1000, label_h)), text_bgcol);
|
||||
canvas.draw_box(Rect(Point(label_w + 4, y), Area(1000, 1)), Color(0, 0, 0));
|
||||
} else
|
||||
canvas.draw_box(Rect(Point(1, y), Area(1000, label_h)), text_bgcol);
|
||||
|
||||
/* draw log text */
|
||||
canvas.draw_string(Point(label_w + 6, y), default_font, text_fgcol, _text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessors
|
||||
*/
|
||||
int label_len() { return _label_len; }
|
||||
int id() { return _id; }
|
||||
};
|
||||
|
||||
|
||||
class Log_window
|
||||
{
|
||||
private:
|
||||
|
||||
Canvas_base &_canvas;
|
||||
Log_entry _entries[LOG_H]; /* log entries */
|
||||
int _dst_entry; /* destination entry for next write */
|
||||
int _view_pos; /* current view port on the entry array */
|
||||
bool _scroll; /* scroll mode (when text hits bottom) */
|
||||
char _attr[LOG_W]; /* character attribute buffer */
|
||||
bool _dirty; /* schedules the log window for a redraw */
|
||||
Genode::Lock _dirty_lock;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Log_window(Canvas_base &canvas)
|
||||
: _canvas(canvas), _dst_entry(0), _view_pos(0), _dirty(true)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Write log entry
|
||||
*
|
||||
* \param color base color for highlighting the session.
|
||||
* \param sid unique ID of the log session. This ID is used to
|
||||
* determine section transitions in the log output.
|
||||
*/
|
||||
void write(Genode::Color color, const char *label,
|
||||
const char *log_text, int sid)
|
||||
{
|
||||
_entries[_dst_entry] = Log_entry(color, label, log_text, _attr, sid);
|
||||
|
||||
if (_scroll)
|
||||
_view_pos++;
|
||||
|
||||
/* cycle through log entries */
|
||||
_dst_entry = (_dst_entry + 1) % LOG_H;
|
||||
|
||||
/* start scrolling when the dst entry wraps for the first time */
|
||||
if (_dst_entry == 0)
|
||||
_scroll = true;
|
||||
|
||||
/* schedule log window for redraw */
|
||||
Genode::Lock::Guard lock_guard(_dirty_lock);
|
||||
_dirty |= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw log window
|
||||
*
|
||||
* \retval true drawing operations had been performed
|
||||
*/
|
||||
bool draw()
|
||||
{
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_dirty_lock);
|
||||
if (!_dirty) return false;
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
int line_h = default_font.str_h(" ");
|
||||
int curr_session_id = -1;
|
||||
|
||||
for (int i = 0, y = 0; i < LOG_H; i++, y += line_h) {
|
||||
Log_entry *le = &_entries[(i + _view_pos) % LOG_H];
|
||||
le->draw(_canvas, y, curr_session_id != le->id());
|
||||
curr_session_id = le->id();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Log_session_component : public Genode::Rpc_object<Genode::Log_session>
|
||||
{
|
||||
public:
|
||||
|
||||
enum { LABEL_LEN = 64 };
|
||||
|
||||
private:
|
||||
|
||||
Genode::Color _color;
|
||||
Log_window *_log_window;
|
||||
char _label[LABEL_LEN];
|
||||
int _id;
|
||||
|
||||
static int _bit(int v, int bit_num) { return (v >> bit_num) & 1; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Log_session_component(const char *label, Log_window *log_window)
|
||||
: _color(0, 0, 0), _log_window(log_window)
|
||||
{
|
||||
static int cnt;
|
||||
|
||||
_id = cnt++;
|
||||
|
||||
const int scale = 32;
|
||||
const int offset = 64;
|
||||
|
||||
/* compute session color */
|
||||
int r = (_bit(_id, 3) + 2*_bit(_id, 0))*scale + offset;
|
||||
int g = (_bit(_id, 4) + 2*_bit(_id, 1))*scale + offset;
|
||||
int b = (_bit(_id, 5) + 2*_bit(_id, 2))*scale + offset;
|
||||
|
||||
_color = Genode::Color(r, g, b);
|
||||
|
||||
Genode::strncpy(_label, label, sizeof(_label));
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
** Log session interface **
|
||||
***************************/
|
||||
|
||||
Genode::size_t write(String const &log_text)
|
||||
{
|
||||
if (!log_text.is_valid_string()) {
|
||||
PERR("corrupted string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_log_window->write(_color, _label, log_text.string(), _id);
|
||||
return Genode::strlen(log_text.string());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Log_root_component : public Genode::Root_component<Log_session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Log_window *_log_window;
|
||||
|
||||
protected:
|
||||
|
||||
Log_session_component *_create_session(const char *args)
|
||||
{
|
||||
PINF("create log session (%s)", args);
|
||||
char label_buf[Log_session_component::LABEL_LEN];
|
||||
|
||||
Genode::Arg label_arg = Genode::Arg_string::find_arg(args, "label");
|
||||
label_arg.string(label_buf, sizeof(label_buf), "");
|
||||
|
||||
return new (md_alloc()) Log_session_component(label_buf, _log_window);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Log_root_component(Genode::Rpc_entrypoint *ep,
|
||||
Genode::Allocator *md_alloc,
|
||||
Log_window *log_window)
|
||||
:
|
||||
Genode::Root_component<Log_session_component>(ep, md_alloc),
|
||||
_log_window(log_window) { }
|
||||
};
|
||||
|
||||
|
||||
class Log_view
|
||||
{
|
||||
private:
|
||||
|
||||
Nitpicker::View_capability _cap;
|
||||
|
||||
int _x, _y, _w, _h;
|
||||
|
||||
public:
|
||||
|
||||
Log_view(Nitpicker::Session *nitpicker,
|
||||
int x, int y, int w, int h)
|
||||
:
|
||||
_x(x), _y(y), _w(w), _h(h)
|
||||
{
|
||||
using namespace Nitpicker;
|
||||
|
||||
_cap = nitpicker->create_view();
|
||||
View_client(_cap).viewport(_x, _y, _w, _h, 0, 0, true);
|
||||
View_client(_cap).stack(Nitpicker::View_capability(), true, true);
|
||||
}
|
||||
|
||||
void top()
|
||||
{
|
||||
Nitpicker::View_client(_cap).stack(Nitpicker::View_capability(), true, true);
|
||||
}
|
||||
|
||||
void move(int x, int y)
|
||||
{
|
||||
_x = x, _y = y;
|
||||
Nitpicker::View_client(_cap).viewport(_x, _y, _w, _h, 0, 0, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessors
|
||||
*/
|
||||
int x() { return _x; }
|
||||
int y() { return _y; }
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* make sure that we connect to LOG before providing this service by ourself */
|
||||
printf("--- nitlog ---\n");
|
||||
|
||||
/* calculate size of log view in pixels */
|
||||
int log_win_w = default_font.str_w(" ") * LOG_W + 2;
|
||||
int log_win_h = default_font.str_h(" ") * LOG_H + 2;
|
||||
|
||||
/* init sessions to the required external services */
|
||||
static Nitpicker::Connection nitpicker;
|
||||
static Timer::Connection timer;
|
||||
|
||||
nitpicker.buffer(Framebuffer::Mode(log_win_w, log_win_h,
|
||||
Framebuffer::Mode::RGB565), false);
|
||||
|
||||
/* initialize entry point that serves the root interface */
|
||||
enum { STACK_SIZE = 4096 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "nitlog_ep");
|
||||
|
||||
/*
|
||||
* Use sliced heap to allocate each session component at a separate
|
||||
* dataspace.
|
||||
*/
|
||||
static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
|
||||
|
||||
/* create log window */
|
||||
void *addr = env()->rm_session()->attach(nitpicker.framebuffer()->dataspace());
|
||||
|
||||
static Canvas<Pixel_rgb565> canvas((Pixel_rgb565 *)addr,
|
||||
::Area(log_win_w, log_win_h));
|
||||
static Log_window log_window(canvas);
|
||||
|
||||
/*
|
||||
* We clip a border of one pixel off the canvas. This way, the
|
||||
* border remains unaffected by the drawing operations and
|
||||
* acts as an outline for the log window.
|
||||
*/
|
||||
canvas.clip(::Rect(::Point(1, 1), ::Area(log_win_w - 2, log_win_h - 2)));
|
||||
|
||||
/* create view for log window */
|
||||
Log_view log_view(&nitpicker, 20, 20, log_win_w, log_win_h);
|
||||
|
||||
/* create root interface for service */
|
||||
static Log_root_component log_root(&ep, &sliced_heap, &log_window);
|
||||
|
||||
/* announce service at our parent */
|
||||
env()->parent()->announce(ep.manage(&log_root));
|
||||
|
||||
/* handle input events */
|
||||
Input::Event *ev_buf = env()->rm_session()->attach(nitpicker.input()->dataspace());
|
||||
int omx = 0, omy = 0, key_cnt = 0;
|
||||
while (1) {
|
||||
|
||||
while (!nitpicker.input()->is_pending()) {
|
||||
if (log_window.draw())
|
||||
nitpicker.framebuffer()->refresh(0, 0, log_win_w, log_win_h);
|
||||
timer.msleep(20);
|
||||
}
|
||||
|
||||
for (int i = 0, num_ev = nitpicker.input()->flush(); i < num_ev; i++) {
|
||||
|
||||
Input::Event *ev = &ev_buf[i];
|
||||
|
||||
if (ev->type() == Input::Event::PRESS) key_cnt++;
|
||||
if (ev->type() == Input::Event::RELEASE) key_cnt--;
|
||||
|
||||
/* move view */
|
||||
if (ev->type() == Input::Event::MOTION && key_cnt > 0)
|
||||
log_view.move(log_view.x() + ev->ax() - omx,
|
||||
log_view.y() + ev->ay() - omy);
|
||||
|
||||
/* find selected view and bring it to front */
|
||||
if (ev->type() == Input::Event::PRESS && key_cnt == 1)
|
||||
log_view.top();
|
||||
|
||||
omx = ev->ax(); omy = ev->ay();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
repos/demo/src/server/nitlog/mono.tff
Normal file
BIN
repos/demo/src/server/nitlog/mono.tff
Normal file
Binary file not shown.
5
repos/demo/src/server/nitlog/target.mk
Normal file
5
repos/demo/src/server/nitlog/target.mk
Normal file
@ -0,0 +1,5 @@
|
||||
TARGET = nitlog
|
||||
LIBS = base blit
|
||||
SRC_CC = main.cc
|
||||
SRC_BIN = mono.tff
|
||||
INC_DIR = $(REP_DIR)/src/server/nitpicker/include
|
Reference in New Issue
Block a user