gui_session: manage view ID at the client side

This patch moves the management of view IDs from the server to the
client side. The former 'create_view' and 'create_child_view'
operations do no longer return a view ID but take a view ID as
argument. While changing those operations, this patch takes the
opportunity to allow for initial view attributes. Combined, those
changes simplify the window manager while accommodating typical
client use cases with less code.

To ease the client-side ID management, the Gui::Connection hosts
a 'view_ids' ID space for optional use. E.g., the new 'Top_level_view'
class uses this ID space for ID allocation. This class accommodates the
most typical use case of opening a single window.

The 'alloc_view_id' RPC function is no longer needed.

Issue #5242
This commit is contained in:
Norman Feske 2024-08-09 14:27:26 +02:00 committed by Christian Helmuth
parent 805e3552fd
commit f98c356efd
37 changed files with 583 additions and 944 deletions

View File

@ -58,19 +58,20 @@ class Scout::Graphics_backend_impl : public Graphics_backend
Point _position;
Area _view_size;
Gui::View_id _view { _gui.create_view() };
Canvas_base *_canvas[2];
bool _flip_state = { false };
Gui::Top_level_view _view { _gui, { _position, _view_size } };
void _update_viewport()
{
using Command = Gui::Session::Command;
Gui::Rect rect(_position, _view_size);
_gui.enqueue<Command::Geometry>(_view, rect);
_gui.enqueue<Command::Geometry>(_view.id(), rect);
Gui::Point offset(0, _flip_state ? -_max_size.h : 0);
_gui.enqueue<Command::Offset>(_view, offset);
_gui.enqueue<Command::Offset>(_view.id(), offset);
_gui.execute();
}
@ -109,8 +110,6 @@ class Scout::Graphics_backend_impl : public Graphics_backend
_position(position),
_view_size(view_size)
{
bring_to_front();
using PT = Genode::Pixel_rgb888;
static Canvas<PT> canvas_0(_base<PT>(0), max_size, alloc);
static Canvas<PT> canvas_1(_base<PT>(1), max_size, alloc);
@ -161,8 +160,7 @@ class Scout::Graphics_backend_impl : public Graphics_backend
void bring_to_front() override
{
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.execute();
_view.front();
}
void view_area(Area area) override

View File

@ -348,48 +348,6 @@ class Nitlog::Root : public Root_component<Session_component>
};
class Log_view
{
private:
Gui::Connection &_gui;
Gui::Point _pos;
Gui::Area _size;
Gui::View_id const _view = _gui.create_view();
using Command = Gui::Session::Command;
public:
Log_view(Gui::Connection &gui, Gui::Rect geometry)
:
_gui(gui),
_pos(geometry.at),
_size(geometry.area)
{
move(_pos);
top();
}
void top()
{
_gui.enqueue<Command::Front>(_view);
_gui.execute();
}
void move(Gui::Point pos)
{
_pos = pos;
Gui::Rect rect(_pos, _size);
_gui.enqueue<Command::Geometry>(_view, rect);
_gui.execute();
}
Gui::Point pos() const { return _pos; }
};
struct Nitlog::Main
{
Env &_env;
@ -435,10 +393,7 @@ struct Nitlog::Main
bool const _canvas_initialized = (_init_canvas(), true);
/* create view for log window */
Gui::Rect const _view_geometry { Gui::Point(20, 20),
Gui::Area(_win_w, _win_h) };
Log_view _view { _gui, _view_geometry };
Gui::Top_level_view _view { _gui, { { 20, 20 }, { _win_w, _win_h } } };
/* create root interface for service */
Root _root { _env.ep(), _sliced_heap, _log_window };
@ -471,14 +426,14 @@ struct Nitlog::Main
Gui::Point const mouse_pos(x, y);
if (_key_cnt && _old_mouse_pos != _initial_mouse_pos)
_view.move(_view.pos() + mouse_pos - _old_mouse_pos);
_view.at(_view.at() + mouse_pos - _old_mouse_pos);
_old_mouse_pos = mouse_pos;
});
/* find selected view and bring it to front */
if (ev.press() && _key_cnt == 1)
_view.top();
_view.front();
}
}

View File

@ -144,7 +144,7 @@ class Nano3d::Scene
} _framebuffer { _gui, _size, _env.rm() };
Gui::View_id _view_id = _gui.create_view();
Gui::Top_level_view _view { _gui, { _pos, _size } };
using Pixel_surface = Genode::Surface<PT>;
using Alpha_surface = Genode::Surface<Genode::Pixel_alpha8>;
@ -261,7 +261,7 @@ class Nano3d::Scene
: -2*h;
Gui::Point const offset(0, buf_y);
_gui.enqueue<Command::Offset>(_view_id, offset);
_gui.enqueue<Command::Offset>(_view.id(), offset);
_gui.execute();
_do_sync = false;
@ -279,11 +279,6 @@ class Nano3d::Scene
:
_env(env), _pos(pos), _size(size)
{
Gui::Rect rect(_pos, _size);
_gui.enqueue<Command::Geometry>(_view_id, rect);
_gui.enqueue<Command::Front>(_view_id);
_gui.execute();
_gui.input.sigh(_input_handler);
_timer.sigh(_periodic_handler);

View File

@ -110,7 +110,7 @@ struct Backdrop::Main
Constructible<Buffer> _buffer { };
Gui::View_id _view_id = _gui.create_view();
Gui::View_id const _view_id { 1 };
void _update_view()
{
@ -148,6 +148,8 @@ struct Backdrop::Main
Main(Genode::Env &env) : _env(env)
{
_gui.view(_view_id, { });
_gui.mode_sigh(_config_handler);
_config.sigh(_config_handler);

View File

@ -38,46 +38,47 @@ class Decorator::Window : public Window_base
*/
bool _gui_views_up_to_date = false;
struct Gui_view
struct Gui_view : Genode::Noncopyable
{
Gui::Connection &_gui;
Gui::View_id _id { _gui.create_view() };
Gui::View_ref _view_ref { };
Gui::View_ids::Element _id { _view_ref, _gui.view_ids };
using Command = Gui::Session::Command;
Gui_view(Gui::Connection &gui, unsigned id = 0)
:
_gui(gui)
Gui_view(Gui::Connection &gui, unsigned win_id = 0) : _gui(gui)
{
/*
* We supply the window ID as label for the anchor view.
*/
if (id)
_gui.enqueue<Command::Title>(_id, Gui::Title { id });
_gui.view(_id.id(), { .title = { win_id },
.rect = { },
.front = false });
}
~Gui_view()
{
_gui.destroy_view(_id);
_gui.destroy_view(id());
}
Gui::View_id id() const { return _id; }
Gui::View_id id() const { return _id.id(); }
void stack(Gui::View_id neighbor)
{
_gui.enqueue<Command::Front_of>(_id, neighbor);
_gui.enqueue<Command::Front_of>(id(), neighbor);
}
void stack_front_most() { _gui.enqueue<Command::Front>(_id); }
void stack_front_most() { _gui.enqueue<Command::Front>(id()); }
void stack_back_most() { _gui.enqueue<Command::Back>(_id); }
void stack_back_most() { _gui.enqueue<Command::Back>(id()); }
void place(Rect rect)
{
_gui.enqueue<Command::Geometry>(_id, rect);
_gui.enqueue<Command::Geometry>(id(), rect);
Point offset = Point(0, 0) - rect.at;
_gui.enqueue<Command::Offset>(_id, offset);
_gui.enqueue<Command::Offset>(id(), offset);
}
};

View File

@ -74,7 +74,8 @@ struct Menu_view::Dialog : List_model<Dialog>::Element
Constructible<Gui_buffer> _buffer { };
Gui::View_id const _view_id = _gui.create_view();
Gui::View_ref _view_ref { };
Gui::View_ids::Element const _view { _view_ref, _gui.view_ids };
Point _position { };
@ -110,8 +111,8 @@ struct Menu_view::Dialog : List_model<Dialog>::Element
using Command = Gui::Session::Command;
_view_geometry = geometry;
_gui.enqueue<Command::Geometry>(_view_id, _view_geometry);
_gui.enqueue<Command::Front>(_view_id);
_gui.enqueue<Command::Geometry>(_view.id(), _view_geometry);
_gui.enqueue<Command::Front>(_view.id());
_gui.execute();
}
@ -130,11 +131,15 @@ struct Menu_view::Dialog : List_model<Dialog>::Element
_env(env), _global_widget_factory(widget_factory), _action(action),
_name(_name_from_attr(node))
{
_gui.view(_view.id(), { });
_dialog_rom.sigh(_dialog_handler);
_dialog_handler.local_submit();
_gui.input.sigh(_input_handler);
}
~Dialog() { _gui.destroy_view(_view.id()); }
Widget::Hovered hovered_widget() const
{
return _root_widget.hovered(_hovered_position);

View File

@ -49,24 +49,7 @@ struct Osci::Main
Constructible<Gui_buffer> _gui_buffer { };
struct View
{
Gui::Connection &_gui;
Gui::View_id _id { _gui.create_view() };
View(Gui::Connection &gui, Point position, Area size) : _gui(gui)
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_id, Rect(position, size));
_gui.enqueue<Command::Front>(_id);
_gui.execute();
}
~View() { _gui.destroy_view(_id); }
};
Constructible<View> _view { };
Constructible<Gui::Top_level_view> _view { };
Signal_handler<Main> _timer_handler { _env.ep(), *this, &Main::_handle_timer };
@ -130,7 +113,7 @@ struct Osci::Main
_gui_buffer.construct(_gui, _size, _env.ram(), _env.rm(),
Gui_buffer::Alpha::OPAQUE, _background);
_view.construct(_gui, Point::from_xml(config), _size);
_view.construct(_gui, Rect { Point::from_xml(config), _size });
_timer.trigger_periodic(1000*config.attribute_value("period_ms", 20));
}

View File

@ -86,24 +86,7 @@ struct Osci::Main
Constructible<Gui_buffer> _gui_buffer { };
struct View
{
Gui::Connection &_gui;
Gui::View_id _id { _gui.create_view() };
View(Gui::Connection &gui, Point position, Area size) : _gui(gui)
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_id, Rect(position, size));
_gui.enqueue<Command::Front>(_id);
_gui.execute();
}
~View() { _gui.destroy_view(_id); }
};
Constructible<View> _view { };
Constructible<Gui::Top_level_view> _view { };
Attached_rom_dataspace _config { _env, "config" };
Attached_rom_dataspace _recording { _env, "recording" };
@ -286,7 +269,7 @@ struct Osci::Main
_gui_buffer.construct(_gui, _size, _env.ram(), _env.rm(),
Gui_buffer::Alpha::OPAQUE, _background);
_view.construct(_gui, Point::from_xml(config), _size);
_view.construct(_gui, Rect { Point::from_xml(config), _size });
_channels.update_from_xml(config,
[&] (Xml_node const &node) -> Registered<Channel> & {

View File

@ -52,24 +52,7 @@ struct Screenshot_trigger::Main
Constructible<Gui_buffer> _gui_buffer { };
struct View
{
Gui::Connection &_gui;
Gui::View_id _id { _gui.create_view() };
View(Gui::Connection &gui, Point position, Area size) : _gui(gui)
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_id, Rect(position, size));
_gui.enqueue<Command::Front>(_id);
_gui.execute();
}
~View() { _gui.destroy_view(_id); }
};
Constructible<View> _view { };
Constructible<Gui::Top_level_view> _view { };
Signal_handler<Main> _timer_handler { _env.ep(), *this, &Main::_handle_timer };
Signal_handler<Main> _input_handler { _env.ep(), *this, &Main::_handle_input };
@ -80,7 +63,7 @@ struct Screenshot_trigger::Main
void visible(bool visible)
{
_visible = visible;
_view.conditional(visible, _gui, _position, _area);
_view.conditional(visible, _gui, Rect { _position, _area });
}
void _handle_input()

View File

@ -121,18 +121,15 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
Input::Session_capability input() override {
return _input_component.cap(); }
Create_view_result create_view() override {
return _gui_session.create_view(); }
View_result view(View_id id, View_attr const &attr) override {
return _gui_session.view(id, attr); }
Create_child_view_result create_child_view(View_id parent) override {
return _gui_session.create_child_view(parent); }
Child_view_result child_view(View_id id, View_id parent, View_attr const &attr) override {
return _gui_session.child_view(id, parent, attr); }
void destroy_view(View_id view) override {
_gui_session.destroy_view(view); }
Alloc_view_id_result alloc_view_id(View_capability view_cap) override {
return _gui_session.alloc_view_id(view_cap); }
View_id_result view_id(View_capability view_cap, View_id id) override {
return _gui_session.view_id(view_cap, id); }

View File

@ -141,74 +141,63 @@ class Decorator::Window : public Window_base, public Animator::Item
func(_maximizer);
}
struct Gui_view
struct Gui_view : Genode::Noncopyable
{
using Command = Gui::Session::Command;
bool const _view_is_remote;
Gui::Connection &_gui;
Gui::View_ref _view_ref { };
Gui::View_ids::Element _id { _view_ref, _gui.view_ids };
Gui::Connection &_gui;
Gui_view(Gui::Connection &gui) : _gui(gui) { }
Gui::View_id _id;
Gui_view(Gui::Connection &gui, unsigned win_id = 0)
:
_view_is_remote(false),
_gui(gui),
_id(_gui.create_view())
{
/*
* We supply the window ID as label for the anchor view.
*/
if (win_id)
_gui.enqueue<Command::Title>(_id, Gui::Title { win_id });
}
Gui::View_id _create_remote_view(Gui::Connection &remote_gui)
{
/* create view at the remote GUI session */
Gui::View_id id = remote_gui.create_view();
Gui::View_capability view_cap = remote_gui.view_capability(id);
/* import remote view into local GUI session */
return _gui.alloc_view_id(view_cap);
}
/**
* Constructor called for creating a view that refers to a buffer
* of another GUI session
*/
Gui_view(Gui::Connection &gui,
Gui::Connection &remote_gui)
:
_view_is_remote(true),
_gui(gui),
_id(_create_remote_view(remote_gui))
{ }
~Gui_view()
{
if (_view_is_remote)
_gui.release_view_id(_id);
else
_gui.destroy_view(_id);
}
Gui::View_id id() const { return _id; }
Gui::View_id id() const { return _id.id(); }
void stack(Gui::View_id neighbor)
{
_gui.enqueue<Command::Front_of>(_id, neighbor);
_gui.enqueue<Command::Front_of>(id(), neighbor);
}
void stack_front_most() { _gui.enqueue<Command::Front>(_id); }
void stack_front_most() { _gui.enqueue<Command::Front>(id()); }
void stack_back_most() { _gui.enqueue<Command::Back>(_id); }
void stack_back_most() { _gui.enqueue<Command::Back>(id()); }
void place(Rect rect, Point offset)
{
_gui.enqueue<Command::Geometry>(_id, rect);
_gui.enqueue<Command::Offset>(_id, offset);
_gui.enqueue<Command::Geometry>(id(), rect);
_gui.enqueue<Command::Offset>(id(), offset);
}
};
struct Content_view : Gui_view
{
Content_view(Gui::Connection &gui, unsigned win_id = 0) : Gui_view(gui)
{
/* supply the window ID as label for the anchor view */
_gui.view(id(), { .title = { win_id },
.rect = { },
.front = false });
}
~Content_view() { _gui.destroy_view(id()); }
};
struct Remote_view : Gui_view
{
Gui::Connection &_remote_gui;
Remote_view(Gui::Connection &gui, Gui::Connection &remote_gui)
:
Gui_view(gui), _remote_gui(remote_gui)
{
remote_gui.view(id(), { });
gui.view_id(remote_gui.view_capability(id()), id());
}
~Remote_view()
{
_gui.release_view_id(id());
_remote_gui.destroy_view(id());
}
};
@ -269,12 +258,12 @@ class Decorator::Window : public Window_base, public Animator::Item
return Area(outer_size.w - inner_size.w, outer_size.h);
}
Gui_view _bottom_view { _gui, _gui_top_bottom },
_right_view { _gui, _gui_left_right },
_left_view { _gui, _gui_left_right },
_top_view { _gui, _gui_top_bottom };
Remote_view _bottom_view { _gui, _gui_top_bottom },
_right_view { _gui, _gui_left_right },
_left_view { _gui, _gui_left_right },
_top_view { _gui, _gui_top_bottom };
Gui_view _content_view { _gui, (unsigned)id() };
Content_view _content_view { _gui, (unsigned)id() };
void _repaint_decorations(Gui_buffer &buffer, Area area)
{

View File

@ -58,6 +58,7 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
Registry<Gui_session>::Element _element;
using View_capability = Gui::View_capability;
using View_id = Gui::View_id;
Genode::Connection<Gui::Session> _connection;
@ -125,25 +126,22 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
Input::Session_capability input() override {
return _input_component.cap(); }
Create_view_result create_view() override {
return _gui_session.create_view(); }
View_result view(View_id id, View_attr const &attr) override {
return _gui_session.view(id, attr); }
Create_child_view_result create_child_view(Gui::View_id parent) override {
return _gui_session.create_child_view(parent); }
Child_view_result child_view(View_id id, View_id parent, View_attr const &attr) override {
return _gui_session.child_view(id, parent, attr); }
void destroy_view(Gui::View_id view) override {
void destroy_view(View_id view) override {
_gui_session.destroy_view(view); }
Alloc_view_id_result alloc_view_id(View_capability view_cap) override {
return _gui_session.alloc_view_id(view_cap); }
View_id_result view_id(View_capability view_cap, Gui::View_id id) override {
View_id_result view_id(View_capability view_cap, View_id id) override {
return _gui_session.view_id(view_cap, id); }
View_capability view_capability(Gui::View_id view) override {
View_capability view_capability(View_id view) override {
return _gui_session.view_capability(view); }
void release_view_id(Gui::View_id view) override {
void release_view_id(View_id view) override {
_gui_session.release_view_id(view); }
Dataspace_capability command_dataspace() override {

View File

@ -345,18 +345,20 @@ class Gui_fader::Gui_session_component
return _gui.input.rpc_cap();
}
Create_view_result create_view() override
View_result view(View_id id, View_attr const &attr) override
{
_view_id.construct(_gui.create_view());
_view_id.construct(id);
_gui.view(id, attr);
_update_view_visibility();
return *_view_id;
return View_result::OK;
}
Create_child_view_result create_child_view(View_id parent) override
Child_view_result child_view(View_id id, View_id parent, View_attr const &attr) override
{
_view_id.construct(_gui.create_child_view(parent));
_view_id.construct(id);
_gui.child_view(id, parent, attr);
_update_view_visibility();
return *_view_id;
return Child_view_result::OK;
}
void destroy_view(View_id id) override
@ -364,11 +366,6 @@ class Gui_fader::Gui_session_component
return _gui.destroy_view(id);
}
Alloc_view_id_result alloc_view_id(View_capability view_cap) override
{
return _gui.alloc_view_id(view_cap);
}
View_id_result view_id(View_capability view_cap, View_id id) override
{
_gui.view_id(view_cap, id);

View File

@ -116,7 +116,7 @@ struct Terminal::Main : Character_consumer
Framebuffer::Mode _fb_mode { };
Gui::View_id _view = _gui.create_view();
Gui::View_id _view { };
Point _pointer { }; /* pointer positon in pixels */
@ -209,6 +209,8 @@ struct Terminal::Main : Character_consumer
Main(Env &env) : _env(env)
{
_gui.view(_view, { });
_timer .sigh(_flush_handler);
_config.sigh(_config_handler);

View File

@ -58,97 +58,6 @@ struct Wm::Decorator_content_callback : Interface
};
class Wm::Decorator_content_registry
{
public:
/**
* Exception type
*/
struct Lookup_failed { };
private:
using View_id = Gui::View_id;
struct Entry : List<Entry>::Element
{
View_id const decorator_view_id;
Window_registry::Id const win_id;
Entry(View_id decorator_view_id, Window_registry::Id win_id)
:
decorator_view_id(decorator_view_id),
win_id(win_id)
{ }
};
List<Entry> _list { };
Allocator &_entry_alloc;
Entry const &_lookup(View_id view_id) const
{
for (Entry const *e = _list.first(); e; e = e->next()) {
if (e->decorator_view_id == view_id)
return *e;
}
throw Lookup_failed();
}
void _remove(Entry const &e)
{
_list.remove(&e);
destroy(_entry_alloc, const_cast<Entry *>(&e));
}
public:
Decorator_content_registry(Allocator &entry_alloc)
:
_entry_alloc(entry_alloc)
{ }
~Decorator_content_registry()
{
while (Entry *e = _list.first())
_remove(*e);
}
void insert(View_id decorator_view_id, Window_registry::Id win_id)
{
Entry *e = new (_entry_alloc) Entry(decorator_view_id, win_id);
_list.insert(e);
}
/**
* Lookup window ID for a given decorator content view
*
* \throw Lookup_failed
*/
Window_registry::Id lookup(View_id view_id) const
{
return _lookup(view_id).win_id;
}
bool registered(View_id view_id) const
{
try { lookup(view_id); return true; } catch (...) { }
return false;
}
/**
* Remove entry
*
* \throw Lookup_failed
*/
void remove(View_id view_id)
{
_remove(_lookup(view_id));
}
};
struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
private List<Decorator_gui_session>::Element
{
@ -159,6 +68,18 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
using View_id = Gui::View_id;
using Command_buffer = Gui::Session::Command_buffer;
struct Content_view_ref : Gui::View_ref
{
Gui::View_ids::Element id;
Window_registry::Id win_id;
Content_view_ref(Window_registry::Id win_id, Gui::View_ids &ids, View_id id)
: id(*this, ids, id), win_id(win_id) { }
};
Gui::View_ids _content_view_ids { };
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
@ -181,9 +102,6 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
Decorator_content_callback &_content_callback;
/* XXX don't allocate content-registry entries from heap */
Decorator_content_registry _content_registry { _heap };
Allocator &_md_alloc;
/* Gui::Connection requires a valid input session */
@ -194,6 +112,13 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
Signal_handler<Decorator_gui_session>
_input_handler { _env.ep(), *this, &Decorator_gui_session::_handle_input };
Window_registry::Id _win_id_from_title(Gui::Title const &title)
{
unsigned value = 0;
Genode::ascii_to(title.string(), value);
return { value };
}
/**
* Constructor
*
@ -233,75 +158,17 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
{
switch (cmd.opcode) {
case Command::TITLE:
{
unsigned id = 0;
Genode::ascii_to(cmd.title.title.string(), id);
if (id > 0)
_content_registry.insert(cmd.title.view,
Window_registry::Id(id));
return;
}
case Command::FRONT:
case Command::BACK:
case Command::FRONT_OF:
case Command::BEHIND_OF:
try {
/* the first argument is the same for all stacking operations */
View_id const view_id = cmd.front.view;
/*
* If the content view is re-stacked, replace it by the real
* window content.
*
* The lookup fails with an exception for non-content views.
* In this case, forward the command.
*/
Window_registry::Id win_id = _content_registry.lookup(view_id);
/*
* Replace content view originally created by the decorator
* by view that shows the real window content.
*/
View_capability view_cap = _content_callback.content_view(win_id);
_gui.session.destroy_view(view_id);
_gui.session.view_id(view_cap, view_id);
_gui.enqueue(cmd);
_gui.execute();
/*
* Now that the physical content view exists, it is time
* to revisit the child views.
*/
_content_callback.update_content_child_views(win_id);
} catch (Decorator_content_registry::Lookup_failed) {
_gui.enqueue(cmd);
}
return;
case Command::GEOMETRY:
try {
/*
* If the content view changes position, propagate the new
* position to the GUI service to properly transform absolute
* input coordinates.
*/
Window_registry::Id win_id = _content_registry.lookup(cmd.geometry.view);
_content_callback.content_geometry(win_id, cmd.geometry.rect);
}
catch (Decorator_content_registry::Lookup_failed) { }
/*
* If the content view changes position, propagate the new position
* to the GUI service to properly transform absolute input
* coordinates.
*/
_content_view_ids.apply<Content_view_ref const>(cmd.geometry.view,
[&] (Content_view_ref const &view_ref) {
_content_callback.content_geometry(view_ref.win_id, cmd.geometry.rect); },
[&] { });
/* forward command */
_gui.enqueue(cmd);
@ -309,19 +176,29 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
case Command::OFFSET:
try {
/*
* If non-content views change their offset (if the lookup
* fails), propagate the event
*/
_content_registry.lookup(cmd.geometry.view);
}
catch (Decorator_content_registry::Lookup_failed) {
_gui.enqueue(cmd);
}
/*
* If non-content views change their offset (if the lookup
* fails), propagate the event
*/
_content_view_ids.apply<Content_view_ref const>(cmd.geometry.view,
[&] (Content_view_ref const &) { },
[&] { _gui.enqueue(cmd); });
return;
case Command::FRONT:
case Command::BACK:
case Command::FRONT_OF:
case Command::BEHIND_OF:
_content_view_ids.apply<Content_view_ref const>(cmd.front.view,
[&] (Content_view_ref const &view_ref) {
_content_callback.update_content_child_views(view_ref.win_id); },
[&] { });
_gui.enqueue(cmd);
return;
case Command::TITLE:
case Command::BACKGROUND:
case Command::NOP:
@ -359,14 +236,40 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
return _dummy_input_component_cap;
}
Create_view_result create_view() override
View_result view(View_id id, View_attr const &attr) override
{
return _gui.session.create_view();
/*
* The decorator marks a content view by specifying the window ID
* as view title. For such views, we import the view from the
* corresponding GUI cient instead of creating a new view.
*/
Window_registry::Id const win_id = _win_id_from_title(attr.title);
if (win_id.valid()) {
try {
Content_view_ref &view_ref_ptr = *new (_heap)
Content_view_ref(Window_registry::Id(win_id), _content_view_ids, id);
View_capability view_cap = _content_callback.content_view(win_id);
View_id_result result = _gui.session.view_id(view_cap, id);
if (result != View_id_result::OK)
destroy(_heap, &view_ref_ptr);
switch (result) {
case View_id_result::OUT_OF_RAM: return View_result::OUT_OF_RAM;
case View_id_result::OUT_OF_CAPS: return View_result::OUT_OF_CAPS;
case View_id_result::OK: return View_result::OK;
case View_id_result::INVALID: break; /* fall back to regular view */
};
}
catch (Genode::Out_of_ram) { return View_result::OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return View_result::OUT_OF_CAPS; }
}
return _gui.session.view(id, attr);
}
Create_child_view_result create_child_view(View_id parent) override
Child_view_result child_view(View_id id, View_id parent, View_attr const &attr) override
{
return _gui.session.create_child_view(parent);
return _gui.session.child_view(id, parent, attr);
}
void destroy_view(View_id view) override
@ -374,23 +277,22 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
/*
* Reset view geometry when destroying a content view
*/
if (_content_registry.registered(view)) {
Gui::Rect rect(Gui::Point(0, 0), Gui::Area(0, 0));
_gui.enqueue<Gui::Session::Command::Geometry>(view, rect);
_gui.execute();
_content_view_ids.apply<Content_view_ref>(view,
[&] (Content_view_ref &view_ref) {
Window_registry::Id win_id = _content_registry.lookup(view);
_content_callback.hide_content_child_views(win_id);
}
_content_callback.hide_content_child_views(view_ref.win_id);
Gui::Rect rect(Gui::Point(0, 0), Gui::Area(0, 0));
_gui.enqueue<Gui::Session::Command::Geometry>(view, rect);
_gui.execute();
destroy(_heap, &view_ref);
},
[&] { });
_gui.session.destroy_view(view);
}
Alloc_view_id_result alloc_view_id(View_capability view_cap) override
{
return _gui.session.alloc_view_id(view_cap);
}
View_id_result view_id(View_capability view_cap, View_id id) override
{
return _gui.session.view_id(view_cap, id);
@ -403,7 +305,10 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
void release_view_id(View_id view) override
{
/* XXX dealloc View_ptr */
_content_view_ids.apply<Content_view_ref>(view,
[&] (Content_view_ref &view_ref) { destroy(_heap, &view_ref); },
[&] { });
_gui.session.release_view_id(view);
}
@ -414,14 +319,9 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
void execute() override
{
for (unsigned i = 0; i < _client_command_buffer.num(); i++) {
try {
_execute_command(_client_command_buffer.get(i));
}
catch (...) {
Genode::warning("unhandled exception while processing command from decorator");
}
}
for (unsigned i = 0; i < _client_command_buffer.num(); i++)
_execute_command(_client_command_buffer.get(i));
_gui.execute();
}

View File

@ -68,14 +68,14 @@ class Wm::Direct_gui_session : public Genode::Rpc_object<Gui::Session>
return _session.input();
}
Create_view_result create_view() override
View_result view(View_id id, View_attr const &attr) override
{
return _session.create_view();
return _session.view(id, attr);
}
Create_child_view_result create_child_view(View_id parent) override
Child_view_result child_view(View_id id, View_id parent, View_attr const &attr) override
{
return _session.create_child_view(parent);
return _session.child_view(id, parent, attr);
}
void destroy_view(View_id view) override
@ -83,11 +83,6 @@ class Wm::Direct_gui_session : public Genode::Rpc_object<Gui::Session>
_session.destroy_view(view);
}
Alloc_view_id_result alloc_view_id(View_capability view_cap) override
{
return _session.alloc_view_id(view_cap);
}
View_id_result view_id(View_capability view_cap, View_id id) override
{
return _session.view_id(view_cap, id);

View File

@ -111,21 +111,42 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
using Command = Gui::Session::Command;
using View_id = Gui::View_id;
Session_label _session_label;
Real_gui &_real_gui;
Constructible<View_id> _real_view { };
Title _title { };
Rect _geometry { };
Point _buffer_offset { };
Weak_ptr<View> _neighbor_ptr { };
bool _neighbor_behind { };
bool _has_alpha;
Session_label _session_label;
Real_gui &_real_gui;
Gui::View_ref _real_view_ref { };
View_ids::Element const _real_view;
Title _title { };
Rect _geometry { };
Point _buffer_offset { };
Weak_ptr<View> _neighbor_ptr { };
bool _neighbor_behind { };
bool _has_alpha;
void _with_temporary_view_id(View_capability cap, auto const &fn)
{
Gui::View_ref ref { };
Gui::View_ids::Element tmp { ref, _real_gui.view_ids };
switch (_real_gui.session.view_id(cap, tmp.id())) {
case Gui::Session::View_id_result::OUT_OF_RAM:
case Gui::Session::View_id_result::OUT_OF_CAPS:
case Gui::Session::View_id_result::INVALID:
warning("unable to obtain view ID for given view capability");
return;
case Gui::Session::View_id_result::OK:
break;
}
fn(tmp.id());
_real_gui.session.release_view_id(tmp.id());
};
View(Real_gui &real_gui,
View_id const &real_view_id,
Session_label const &session_label,
bool has_alpha)
:
_session_label(session_label), _real_gui(real_gui),
_real_view(_real_view_ref, _real_gui.view_ids, real_view_id),
_has_alpha(has_alpha)
{ }
@ -139,37 +160,28 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
*/
void _unsynchronized_apply_view_config(Locked_ptr<View> &neighbor)
{
if (!_real_view.constructed())
return;
_propagate_view_geometry();
_real_gui.enqueue<Command::Offset>(*_real_view, _buffer_offset);
_real_gui.enqueue<Command::Title> (*_real_view, _title);
_real_gui.enqueue<Command::Offset>(_real_view.id(), _buffer_offset);
_real_gui.enqueue<Command::Title> (_real_view.id(), _title);
Constructible<View_id> real_neighbor_id { };
if (neighbor.valid()) {
_with_temporary_view_id(neighbor->real_view_cap(), [&] (View_id id) {
if (_neighbor_behind)
_real_gui.enqueue<Command::Front_of>(_real_view.id(), id);
else
_real_gui.enqueue<Command::Behind_of>(_real_view.id(), id);
if (neighbor.valid())
_real_gui.session.alloc_view_id(neighbor->real_view_cap()).with_result(
[&] (View_id id) { real_neighbor_id.construct(id); },
[&] (auto) { warning("unable to obtain real_neighbor_id"); }
);
_real_gui.execute();
});
if (real_neighbor_id.constructed()) {
if (_neighbor_behind)
_real_gui.enqueue<Command::Front_of>(*_real_view, *real_neighbor_id);
else
_real_gui.enqueue<Command::Behind_of>(*_real_view, *real_neighbor_id);
} else {
if (_neighbor_behind)
_real_gui.enqueue<Command::Front>(*_real_view);
_real_gui.enqueue<Command::Front>(_real_view.id());
else
_real_gui.enqueue<Command::Back>(*_real_view);
_real_gui.enqueue<Command::Back>(_real_view.id());
_real_gui.execute();
}
_real_gui.execute();
if (real_neighbor_id.constructed())
_real_gui.session.release_view_id(*real_neighbor_id);
}
void _apply_view_config()
@ -182,8 +194,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
~View()
{
if (_real_view.constructed())
_real_gui.session.destroy_view(*_real_view);
_real_gui.session.destroy_view(_real_view.id());
}
using Genode::Weak_object<View>::weak_ptr;
@ -196,24 +207,16 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
virtual void geometry(Rect geometry)
{
_geometry = geometry;
/*
* Propagate new size to real GUI view but
*/
if (_real_view.constructed()) {
_propagate_view_geometry();
_real_gui.execute();
}
_propagate_view_geometry();
_real_gui.execute();
}
virtual void title(Title const &title)
{
_title = title;
if (_real_view.constructed()) {
_real_gui.enqueue<Command::Title>(*_real_view, title);
_real_gui.execute();
}
_real_gui.enqueue<Command::Title>(_real_view.id(), title);
_real_gui.execute();
}
virtual Point input_anchor_position() const = 0;
@ -222,19 +225,15 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
View_capability real_view_cap()
{
return _real_view.constructed()
? _real_gui.session.view_capability(*_real_view)
: View_capability();
return _real_gui.session.view_capability(_real_view.id());
}
void buffer_offset(Point buffer_offset)
{
_buffer_offset = buffer_offset;
if (_real_view.constructed()) {
_real_gui.enqueue<Command::Offset>(*_real_view, _buffer_offset);
_real_gui.execute();
}
_real_gui.enqueue<Command::Offset>(_real_view.id(), _buffer_offset);
_real_gui.execute();
}
bool has_alpha() const { return _has_alpha; }
@ -270,15 +269,23 @@ class Wm::Gui::Top_level_view : public View, private List<Top_level_view>::Eleme
public:
Top_level_view(Real_gui &real_gui,
View_id view_id,
bool has_alpha,
Window_registry &window_registry,
Input_origin_changed_handler &input_origin_changed_handler)
:
View(real_gui, real_gui.label, has_alpha),
View(real_gui, view_id, real_gui.label, has_alpha),
_window_registry(window_registry),
_input_origin_changed_handler(input_origin_changed_handler),
_session_label(real_gui.label)
{ }
{
/*
* Create and configure physical GUI view.
*/
_real_gui.session.view(_real_view.id(), { .title = _title,
.rect = { },
.front = false });
}
~Top_level_view()
{
@ -290,31 +297,6 @@ class Wm::Gui::Top_level_view : public View, private List<Top_level_view>::Eleme
using List<Top_level_view>::Element::next;
void init_real_gui_view()
{
if (_real_view.constructed())
return;
/*
* Create and configure physical GUI view.
*/
_real_gui.session.create_view().with_result(
[&] (View_id id) {
_real_view.construct(id);
_real_gui.enqueue<Command::Offset>(id, _buffer_offset);
_real_gui.enqueue<Command::Title> (id, _title.string());
_real_gui.execute();
},
[&] (Gui::Session::Create_view_error) {
warning("init_real_view failed");
}
);
if (!_real_view.constructed()) {
warning("failed to created content view for ", _title);
}
}
void _propagate_view_geometry() override { }
void geometry(Rect geometry) override
@ -373,13 +355,7 @@ class Wm::Gui::Top_level_view : public View, private List<Top_level_view>::Eleme
View_capability content_view()
{
init_real_gui_view();
if (_real_view.constructed())
return _real_gui.session.view_capability(*_real_view);
error("content_view was unable to obtain real view");
return { };
return _real_gui.session.view_capability(_real_view.id());
}
void hidden(bool hidden) { _window_registry.hidden(_win_id, hidden); }
@ -402,13 +378,16 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
Weak_ptr<View> mutable _parent;
bool _visible = false;
public:
Child_view(Real_gui &real_gui,
View_id real_gui_id,
bool has_alpha,
Weak_ptr<View> parent)
:
View(real_gui, real_gui.label, has_alpha), _parent(parent)
View(real_gui, real_gui_id, real_gui.label, has_alpha), _parent(parent)
{
try_to_init_real_view();
}
@ -422,8 +401,7 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
void _propagate_view_geometry() override
{
if (_real_view.constructed())
_real_gui.enqueue<Command::Geometry>(*_real_view, _geometry);
_real_gui.enqueue<Command::Geometry>(_real_view.id(), _geometry);
}
void stack(Weak_ptr<View> neighbor_ptr, bool behind) override
@ -451,35 +429,30 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
void try_to_init_real_view()
{
if (_real_view.constructed())
return;
Locked_ptr<View> parent(_parent);
if (!parent.valid())
return;
Constructible<View_id> parent_id { };
_real_gui.session.alloc_view_id(parent->real_view_cap()).with_result(
[&] (View_id id) { parent_id.construct(id); },
[&] (Gui::Session::Alloc_view_id_error e) {
warning("try_to_init_real_view could not alloc parent ID e=", (int)e);
}
);
if (!parent_id.constructed()) {
warning("try_to_init_real_view failed to obtain parent ID");
return;
}
_with_temporary_view_id(parent->real_view_cap(), [&] (View_id parent_id) {
_real_gui.session.create_child_view(*parent_id).with_result(
[&] (View_id id) { _real_view.construct(id); },
[&] (Gui::Session::Create_child_view_error) { }
);
if (!_real_view.constructed()) {
warning("try_to_init_real_view failed to create child view");
return;
}
if (_visible)
return;
_real_gui.session.release_view_id(*parent_id);
Gui::Session::View_attr const attr { .title = _title,
.rect = _geometry,
.front = false };
switch (_real_gui.session.child_view(_real_view.id(), parent_id, attr)) {
case Gui::Session::Child_view_result::OUT_OF_RAM:
case Gui::Session::Child_view_result::OUT_OF_CAPS:
case Gui::Session::Child_view_result::INVALID:
warning("unable to create child view");
return;
case Gui::Session::Child_view_result::OK:
break;
};
_visible = true;
});
if (_neighbor_ptr == _parent)
_unsynchronized_apply_view_config(parent);
@ -494,11 +467,8 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
void hide()
{
if (!_real_view.constructed())
return;
_real_gui.session.destroy_view(*_real_view);
_real_view.destruct();
_real_gui.session.destroy_view(_real_view.id());
_visible = false;
}
};
@ -511,8 +481,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
friend class List<Session_component>;
using View_id = Gui::View_id;
using View_ids = Id_space<Gui::View_ref>;
using View_id = Gui::View_id;
struct View_ref : Gui::View_ref
{
@ -550,7 +519,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
Real_gui _real_gui { _env, _session_label };
Window_registry &_window_registry;
Tslab<Top_level_view, 8000> _top_level_view_alloc;
Tslab<Child_view, 6000> _child_view_alloc;
Tslab<Child_view, 7000> _child_view_alloc;
Tslab<View_ref, 4000> _view_ref_alloc;
List<Top_level_view> _top_level_views { };
List<Child_view> _child_views { };
@ -972,26 +941,28 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
}
template <typename VIEW>
Create_view_result _create_view_with_id(auto &dealloc, auto const &create_fn)
View_result _create_view_with_id(auto &dealloc, View_id id, View_attr const &attr, auto const &create_fn)
{
Create_view_error error { };
release_view_id(id);
View_result error { };
VIEW *view_ptr = nullptr;
try {
view_ptr = create_fn();
view_ptr = &create_fn();
}
catch (Out_of_ram) { error = Create_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { error = Create_view_error::OUT_OF_CAPS; }
catch (Out_of_ram) { error = View_result::OUT_OF_RAM; }
catch (Out_of_caps) { error = View_result::OUT_OF_CAPS; }
if (!view_ptr)
return error;
View_ref *view_ref_ptr = nullptr;
try {
view_ref_ptr =
new (_view_ref_alloc) View_ref(view_ptr->weak_ptr(), _view_ids);
new (_view_ref_alloc) View_ref(view_ptr->weak_ptr(), _view_ids, id);
}
catch (Out_of_ram) { error = Create_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { error = Create_view_error::OUT_OF_CAPS; }
catch (Out_of_ram) { error = View_result::OUT_OF_RAM; }
catch (Out_of_caps) { error = View_result::OUT_OF_CAPS; }
if (!view_ref_ptr) {
destroy(dealloc, view_ptr);
return error;
@ -999,64 +970,64 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
_env.ep().manage(*view_ptr);
return view_ref_ptr->id.id();
/* apply initial view attributes */
_execute_command(Command::Title { id, attr.title });
_execute_command(Command::Geometry { id, attr.rect });
if (attr.front) {
_execute_command(Command::Front { id });
_window_registry.flush();
}
return View_result::OK;
}
Create_view_result create_view() override
View_result view(View_id id, View_attr const &attr) override
{
Top_level_view *view_ptr = nullptr;
Create_view_result const result =
_create_view_with_id<Top_level_view>(_top_level_view_alloc,
[&] {
View_result const result =
_create_view_with_id<Top_level_view>(_top_level_view_alloc, id, attr,
[&] () -> Top_level_view & {
view_ptr = new (_top_level_view_alloc)
Top_level_view(_real_gui, _has_alpha,
Top_level_view(_real_gui, id, _has_alpha,
_window_registry, *this);
return view_ptr;
return *view_ptr;
});
if (result.ok() && view_ptr) {
view_ptr->init_real_gui_view();
if (result == View_result::OK && view_ptr) {
view_ptr->resizeable(_mode_sigh.valid());
_top_level_views.insert(view_ptr);
}
return result;
}
Create_child_view_result create_child_view(View_id const parent) override
Child_view_result child_view(View_id const id, View_id const parent, View_attr const &attr) override
{
using Error = Create_child_view_error;
return _with_view(parent,
[&] (View &parent) -> Create_child_view_result {
[&] (View &parent) -> Child_view_result {
Child_view *view_ptr = nullptr;
Create_view_result const result =
_create_view_with_id<Child_view>(_child_view_alloc,
[&] {
View_result const result =
_create_view_with_id<Child_view>(_child_view_alloc, id, attr,
[&] () -> Child_view & {
view_ptr = new (_child_view_alloc)
Child_view(_real_gui, _has_alpha, parent.weak_ptr());
return view_ptr;
Child_view(_real_gui, id, _has_alpha, parent.weak_ptr());
return *view_ptr;
});
return result.convert<Create_child_view_result>(
[&] (View_id id) {
if (view_ptr)
_child_views.insert(view_ptr);
return id;
},
[&] (Create_view_error e) {
switch (e) {
case Create_view_error::OUT_OF_RAM: return Error::OUT_OF_RAM;
case Create_view_error::OUT_OF_CAPS: return Error::OUT_OF_CAPS;
};
return Error::INVALID;
}
);
switch (result) {
case View_result::OUT_OF_RAM: return Child_view_result::OUT_OF_RAM;
case View_result::OUT_OF_CAPS: return Child_view_result::OUT_OF_CAPS;
case View_result::OK: break;
}
if (view_ptr)
_child_views.insert(view_ptr);
return Child_view_result::OK;
},
[&] () -> Create_child_view_result { return Error::INVALID; });
[&] () -> Child_view_result { return Child_view_result::INVALID; });
}
void destroy_view(View_id id) override
@ -1079,22 +1050,6 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
release_view_id(id);
}
Alloc_view_id_result alloc_view_id(View_capability view_cap) override
{
return _env.ep().rpc_ep().apply(view_cap,
[&] (View *view_ptr) -> Alloc_view_id_result {
if (!view_ptr)
return Alloc_view_id_error::INVALID;
try {
View_ref &view_ref = *new (_view_ref_alloc)
View_ref(view_ptr->weak_ptr(), _view_ids);
return view_ref.id.id();
}
catch (Out_of_ram) { return Alloc_view_id_error::OUT_OF_RAM; }
catch (Out_of_caps) { return Alloc_view_id_error::OUT_OF_CAPS; }
});
}
View_id_result view_id(View_capability view_cap, View_id id) override
{
/* prevent ID conflict in 'View_ids::Element' constructor */
@ -1192,7 +1147,11 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
* upgrades initiated by the wm client's buffer operation twice.
*/
_has_alpha = has_alpha;
return _real_gui.session.buffer(mode, has_alpha);
Buffer_result const result = _real_gui.session.buffer(mode, has_alpha);
_window_registry.flush();
return result;
}
void focus(Genode::Capability<Gui::Session>) override { }

View File

@ -62,17 +62,18 @@ struct Wm::Layouter_gui_session : Genode::Rpc_object<Gui::Session>
return _input_session_cap;
}
Create_view_result create_view() override { return View_id(); }
View_result view(View_id, View_attr const &) override
{
return View_result::OK;
}
Create_child_view_result create_child_view(View_id) override { return View_id(); }
Child_view_result child_view(View_id, View_id, View_attr const &) override
{
return Child_view_result::OK;
}
void destroy_view(View_id) override { }
Alloc_view_id_result alloc_view_id(View_capability) override
{
return View_id();
}
View_id_result view_id(View_capability, View_id) override
{
return View_id_result::OK;

View File

@ -54,6 +54,8 @@ struct Wm::Real_gui
public:
Gui::View_ids view_ids { };
template <typename CMD>
void enqueue(auto &&... args) { enqueue(Gui::Session::Command( CMD { args... } )); }

View File

@ -107,7 +107,7 @@ class Pdf_view
Genode::Signal_handler<Pdf_view> _input_handler {
_env.ep(), *this, &Pdf_view::_handle_input_events };
Gui::View_id _view = _gui.create_view();
Gui::Top_level_view _view { _gui };
pixel_t *_fb_base() { return _fb_ds->local_addr<pixel_t>(); }
@ -140,10 +140,8 @@ class Pdf_view
_pdfapp.resolution = Genode::min(_nit_mode.area.w/5,
_nit_mode.area.h/4);
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_view, Gui::Rect(Gui::Point(), _nit_mode.area));
_gui.enqueue<Command::Front>(_view);
_gui.execute();
_view.area(_nit_mode.area);
_view.front();
}
void _handle_nit_mode()
@ -272,7 +270,7 @@ class Pdf_view
void title(Gui::Title const &msg)
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Title>(_view, msg);
_gui.enqueue<Command::Title>(_view.id(), msg);
_gui.execute();
}

View File

@ -48,8 +48,8 @@ class Viewer
Genode::Env &_env;
Gui::Connection _gui { _env, "webcam" };
Gui::View_id _view { _gui.create_view() };
Framebuffer::Mode const _mode;
Gui::Top_level_view _view { _gui, { { }, _mode.area } };
Constructible<Genode::Attached_dataspace> _fb_ds { };
uint8_t *_framebuffer { nullptr };
@ -65,14 +65,6 @@ class Viewer
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());
_framebuffer = _fb_ds->local_addr<uint8_t>();
using Command = Gui::Session::Command;
using namespace Gui;
_gui.enqueue<Command::Geometry>(_view, Gui::Rect(Gui::Point(0, 0), _mode.area));
_gui.enqueue<Command::Front>(_view);
_gui.enqueue<Command::Title>(_view, "webcam");
_gui.execute();
}
uint8_t *framebuffer() { return _framebuffer; }

View File

@ -221,13 +221,15 @@ void QGenodeViewWidget::paintEvent(QPaintEvent *event)
QGenodePlatformWindow *platform_window =
dynamic_cast<QGenodePlatformWindow*>(window()->windowHandle()->handle());
Gui::View_id const neighbor_id =
gui->alloc_view_id(platform_window->view_cap());
Gui::View_ref tmp_view_ref { };
Gui::View_ids::Element neighbor_id { tmp_view_ref, gui->view_ids };
gui->enqueue<Command::Front_of>(view_id, neighbor_id);
gui->view_id(platform_window->view_cap(), neighbor_id.id());
gui->enqueue<Command::Front_of>(view_id, neighbor_id.id());
gui->execute();
gui->release_view_id(neighbor_id);
gui->release_view_id(neighbor_id.id());
}

View File

@ -48,7 +48,8 @@ struct Window : Genode_egl_window
Framebuffer::Mode mode;
Gui::Connection gui { env };
Genode::Constructible<Genode::Attached_dataspace> ds { };
Gui::View_id view { };
Gui::Top_level_view view { gui };
Genode::addr_t fb_addr { 0 };
Genode::addr_t fb_size { 0 };
@ -63,13 +64,8 @@ struct Window : Genode_egl_window
type = WINDOW;
gui.buffer(mode, false);
view = gui.create_view();
mode_change();
gui.enqueue<Command::Title>(view, "eglut");
gui.enqueue<Command::Front>(view);
gui.execute();
}
void mode_change()
@ -81,9 +77,7 @@ struct Window : Genode_egl_window
addr = ds->local_addr<unsigned char>();
Gui::Rect rect { Gui::Point { 0, 0 }, mode.area };
gui.enqueue<Command::Geometry>(view, rect);
gui.execute();
view.area(mode.area);
}
void refresh()

View File

@ -30,18 +30,15 @@ struct Gui::Session_client : Rpc_client<Session>
Input::Session_capability input() override {
return call<Rpc_input>(); }
Create_view_result create_view() override {
return call<Rpc_create_view>(); }
View_result view(View_id id, View_attr const &attr) override {
return call<Rpc_view>(id, attr); }
Create_child_view_result create_child_view(View_id parent) override {
return call<Rpc_create_child_view>(parent); }
Child_view_result child_view(View_id id, View_id parent, View_attr const &attr) override {
return call<Rpc_child_view>(id, parent, attr); }
void destroy_view(View_id view) override {
call<Rpc_destroy_view>(view); }
Alloc_view_id_result alloc_view_id(View_capability view) override {
return call<Rpc_alloc_view_id>(view); }
View_id_result view_id(View_capability view, View_id id) override {
return call<Rpc_view_id>(view, id); }

View File

@ -19,7 +19,10 @@
#include <input_session/client.h>
#include <base/connection.h>
namespace Gui { class Connection; }
namespace Gui {
class Connection;
struct Top_level_view;
}
class Gui::Connection : private Genode::Connection<Session>
@ -40,6 +43,8 @@ class Gui::Connection : private Genode::Connection<Session>
public:
View_ids view_ids { };
/**
* Framebuffer access
*/
@ -64,44 +69,33 @@ class Gui::Connection : private Genode::Connection<Session>
_env(env)
{ }
View_id create_view()
void view(View_id id, Session::View_attr const &attr)
{
View_id result { };
for (bool retry = false; ; ) {
using Error = Session_client::Create_view_error;
_client.create_view().with_result(
[&] (View_id id) { result = id; },
[&] (Error e) {
switch (e) {
case Error::OUT_OF_RAM: upgrade_ram(8*1024); retry = true; return;
case Error::OUT_OF_CAPS: upgrade_caps(2); retry = true; return;
}
});
if (!retry)
break;
for (;;) {
using Result = Session::View_result;
switch (_client.view(id, attr)) {
case Result::OUT_OF_RAM: upgrade_ram(8*1024); break;
case Result::OUT_OF_CAPS: upgrade_caps(2); break;
case Result::OK:
return;
}
}
return result;
}
View_id create_child_view(View_id parent)
void child_view(View_id id, View_id parent, Session::View_attr const &attr)
{
View_id result { };
for (bool retry = false; ; ) {
using Error = Session_client::Create_child_view_error;
_client.create_child_view(parent).with_result(
[&] (View_id id) { result = id; },
[&] (Error e) {
switch (e) {
case Error::OUT_OF_RAM: upgrade_ram(8*1024); retry = true; return;
case Error::OUT_OF_CAPS: upgrade_caps(2); retry = true; return;
case Error::INVALID: break;
}
error("failed to create child view for invalid parent view");
});
if (!retry)
break;
for (;;) {
using Result = Session::Child_view_result;
switch (_client.child_view(id, parent, attr)) {
case Result::OUT_OF_RAM: upgrade_ram(8*1024); break;
case Result::OUT_OF_CAPS: upgrade_caps(2); break;
case Result::OK:
return;
case Result::INVALID:
error("failed to create child view for invalid parent view");
return;
}
}
return result;
}
void destroy_view(View_id view)
@ -119,27 +113,6 @@ class Gui::Connection : private Genode::Connection<Session>
return _client.view_capability(id);
}
View_id alloc_view_id(View_capability view)
{
View_id result { };
for (bool retry = false; ; ) {
using Error = Session_client::Alloc_view_id_error;
_client.alloc_view_id(view).with_result(
[&] (View_id id) { result = id; },
[&] (Error e) {
switch (e) {
case Error::OUT_OF_RAM: upgrade_ram(8*1024); retry = true; return;
case Error::OUT_OF_CAPS: upgrade_caps(2); retry = true; return;
case Error::INVALID: break;
}
warning("attempt to alloc ID for invalid view");
});
if (!retry)
break;
}
return result;
}
void view_id(View_capability view, View_id id)
{
using Result = Session::View_id_result;
@ -200,17 +173,62 @@ class Gui::Connection : private Genode::Connection<Session>
_command_buffer.reset();
}
/**
* Return physical screen mode
*/
Framebuffer::Mode mode() { return _client.mode(); }
/**
* Return physical screen mode
*/
Framebuffer::Mode mode() { return _client.mode(); }
/**
* Register signal handler to be notified about mode changes
*/
void mode_sigh(Signal_context_capability sigh) { _client.mode_sigh(sigh); }
/**
* Register signal handler to be notified about mode changes
*/
void mode_sigh(Signal_context_capability sigh) { _client.mode_sigh(sigh); }
void focus(Capability<Session> focused) { _client.focus(focused); }
void focus(Capability<Session> focused) { _client.focus(focused); }
};
/**
* Helper for the common case of creating a top-level view
*/
class Gui::Top_level_view : View_ref, View_ids::Element
{
private:
Connection &_gui;
Rect _rect;
public:
using View_ids::Element::id;
Top_level_view(Connection &gui, Rect rect = { })
:
View_ids::Element(*this, gui.view_ids), _gui(gui), _rect(rect)
{
_gui.view(id(), { .title = { }, .rect = rect, .front = true });
}
~Top_level_view() { _gui.destroy_view(id()); }
void front()
{
_gui.enqueue<Session::Command::Front>(id());
_gui.execute();
}
void geometry(Rect rect)
{
_rect = rect;
_gui.enqueue<Session::Command::Geometry>(id(), _rect);
_gui.execute();
}
void area(Area area) { geometry(Rect { _rect.at, area } ); }
void at (Point at) { geometry(Rect { at, _rect.area } ); }
Area area() const { return _rect.area; }
Point at() const { return _rect.at; }
};
#endif /* _INCLUDE__GUI_SESSION__CONNECTION_H_ */

View File

@ -37,6 +37,7 @@ namespace Gui {
struct View_ref : Interface { };
using View_capability = Capability<View>;
using View_ids = Id_space<View_ref>;
using View_id = Id_space<View_ref>::Id;
using Title = String<64>;
@ -170,16 +171,21 @@ struct Gui::Session : Genode::Session
*/
virtual Input::Session_capability input() = 0;
enum class Create_view_error { OUT_OF_RAM, OUT_OF_CAPS };
using Create_view_result = Attempt<View_id, Create_view_error>;
struct View_attr
{
Title title;
Rect rect;
bool front;
};
enum class View_result { OK, OUT_OF_RAM, OUT_OF_CAPS };
/**
* Create a new top-level view at the buffer
*/
virtual Create_view_result create_view() = 0;
virtual View_result view(View_id, View_attr const &) = 0;
enum class Create_child_view_error { OUT_OF_RAM, OUT_OF_CAPS, INVALID };
using Create_child_view_result = Attempt<View_id, Create_child_view_error>;
enum class Child_view_result { OK, OUT_OF_RAM, OUT_OF_CAPS, INVALID };
/**
* Create a new child view at the buffer
@ -187,24 +193,13 @@ struct Gui::Session : Genode::Session
* The 'parent' argument allows the client to use the location of an
* existing view as the coordinate origin for the to-be-created view.
*/
virtual Create_child_view_result create_child_view(View_id parent) = 0;
virtual Child_view_result child_view(View_id, View_id parent, View_attr const &) = 0;
/**
* Destroy view
*/
virtual void destroy_view(View_id) = 0;
enum class Alloc_view_id_error { OUT_OF_RAM, OUT_OF_CAPS, INVALID };
using Alloc_view_id_result = Attempt<View_id, Alloc_view_id_error>;
/**
* Return session-local ID for the specified view
*
* The ID returned by this method can be used to issue commands via the
* 'execute' method.
*/
virtual Alloc_view_id_result alloc_view_id(View_capability) = 0;
enum class View_id_result { OK, OUT_OF_RAM, OUT_OF_CAPS, INVALID };
/**
@ -286,10 +281,9 @@ struct Gui::Session : Genode::Session
GENODE_RPC(Rpc_framebuffer, Framebuffer::Session_capability, framebuffer);
GENODE_RPC(Rpc_input, Input::Session_capability, input);
GENODE_RPC(Rpc_create_view, Create_view_result, create_view);
GENODE_RPC(Rpc_create_child_view, Create_child_view_result, create_child_view, View_id);
GENODE_RPC(Rpc_view, View_result, view, View_id, View_attr const &);
GENODE_RPC(Rpc_child_view, Child_view_result, child_view, View_id, View_id, View_attr const &);
GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_id);
GENODE_RPC(Rpc_alloc_view_id, Alloc_view_id_result, alloc_view_id, View_capability);
GENODE_RPC(Rpc_view_id, View_id_result, view_id, View_capability, View_id);
GENODE_RPC(Rpc_view_capability, View_capability, view_capability, View_id);
GENODE_RPC(Rpc_release_view_id, void, release_view_id, View_id);
@ -302,8 +296,7 @@ struct Gui::Session : Genode::Session
GENODE_RPC(Rpc_buffer, Buffer_result, buffer, Framebuffer::Mode, bool);
GENODE_RPC_INTERFACE(Rpc_framebuffer, Rpc_input,
Rpc_create_view, Rpc_create_child_view, Rpc_destroy_view,
Rpc_alloc_view_id, Rpc_view_id,
Rpc_view, Rpc_child_view, Rpc_destroy_view, Rpc_view_id,
Rpc_view_capability, Rpc_release_view_id,
Rpc_command_dataspace, Rpc_execute, Rpc_mode,
Rpc_mode_sigh, Rpc_buffer, Rpc_focus);

View File

@ -68,7 +68,7 @@ class Pointer::Main : public Rom::Reader
Gui::Connection _gui { _env };
Gui::View_id _view = _gui.create_view();
Gui::Top_level_view _view { _gui };
bool _default_pointer_visible = false;
@ -166,7 +166,7 @@ void Pointer::Main::_show_default_pointer()
_gui.framebuffer.refresh(0, 0, pointer_size.w, pointer_size.h);
Gui::Rect geometry(Gui::Point(0, 0), pointer_size);
_gui.enqueue<Gui::Session::Command::Geometry>(_view, geometry);
_gui.enqueue<Gui::Session::Command::Geometry>(_view.id(), geometry);
_gui.execute();
_default_pointer_visible = true;
@ -227,7 +227,7 @@ void Pointer::Main::_show_shape_pointer(Shape_report &shape_report)
_gui.framebuffer.refresh(0, 0, shape_size.w, shape_size.h);
Gui::Rect geometry(shape_hot, shape_size);
_gui.enqueue<Gui::Session::Command::Geometry>(_view, geometry);
_gui.enqueue<Gui::Session::Command::Geometry>(_view.id(), geometry);
_gui.execute();
_default_pointer_visible = false;
@ -357,7 +357,7 @@ Pointer::Main::Main(Genode::Env &env) : _env(env)
}
}
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.enqueue<Gui::Session::Command::Front>(_view.id());
_gui.execute();
_update_pointer();

View File

@ -186,7 +186,7 @@ struct Status_bar::Main
Reconstructible<Buffer> _buffer { _env.rm(), _gui };
Gui::View_id const _view { _gui.create_view() };
Gui::Top_level_view const _view { _gui };
void _draw_status_bar()
{
@ -199,9 +199,6 @@ struct Status_bar::Main
_focus_ds.sigh(_focus_handler);
_gui.mode_sigh(_mode_handler);
/* schedule initial view-stacking command, needed only once */
_gui.enqueue<Gui::Session::Command::Front>(_view);
/* import initial state */
_handle_mode();
_handle_focus();
@ -244,7 +241,7 @@ void Status_bar::Main::_handle_mode()
Rect const geometry(Point(0, 0), _buffer->mode().area);
_gui.enqueue<Gui::Session::Command::Geometry>(_view, geometry);
_gui.enqueue<Gui::Session::Command::Geometry>(_view.id(), geometry);
_gui.execute();
}

View File

@ -242,7 +242,7 @@ struct Nit_fb::Main : View_updater
unsigned refresh_rate = 0;
Gui::View_id view = gui.create_view();
Gui::Top_level_view const view { gui };
Genode::Attached_dataspace input_ds { env.rm(), gui.input.dataspace() };
@ -301,8 +301,8 @@ struct Nit_fb::Main : View_updater
void update_view() override
{
using Command = Gui::Session::Command;
gui.enqueue<Command::Geometry>(view, Rect(position, fb_session.size()));
gui.enqueue<Command::Front>(view);
gui.enqueue<Command::Geometry>(view.id(), Rect(position, fb_session.size()));
gui.enqueue<Command::Front>(view.id());
gui.execute();
}

View File

@ -198,30 +198,39 @@ void Gui_session::_adopt_new_view(View &view)
}
Gui_session::Create_view_result Gui_session::_create_view_with_id(auto const &create_fn)
Gui_session::View_result
Gui_session::_create_view_and_ref(View_id const id, View_attr const &attr, auto const &create_fn)
{
Create_view_error error { };
release_view_id(id);
View_result error { }; /* assigned only in the error case */
try {
View &view = create_fn();
try {
View_ref &view_ref =
*new (_view_ref_alloc) View_ref(view.weak_ptr(), _view_ids);
new (_view_ref_alloc) View_ref(view.weak_ptr(), _view_ids, id);
_adopt_new_view(view);
return view_ref.id.id();
/* apply initial view attributes */
_execute_command(Command::Title { id, attr.title });
_execute_command(Command::Geometry { id, attr.rect });
if (attr.front)
_execute_command(Command::Front { id });
return View_result::OK;
}
catch (Out_of_ram) { error = Create_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { error = Create_view_error::OUT_OF_CAPS; }
catch (Out_of_ram) { error = View_result::OUT_OF_RAM; }
catch (Out_of_caps) { error = View_result::OUT_OF_CAPS; }
destroy(_view_alloc, &view);
}
catch (Out_of_ram) { error = Create_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { error = Create_view_error::OUT_OF_CAPS; }
catch (Out_of_ram) { error = View_result::OUT_OF_RAM; }
catch (Out_of_caps) { error = View_result::OUT_OF_CAPS; }
return error;
}
Gui_session::Create_view_result Gui_session::create_view()
Gui_session::View_result Gui_session::view(View_id const id, View_attr const &attr)
{
return _create_view_with_id([&] () -> View & {
return _create_view_and_ref(id, attr, [&] () -> View & {
return *new (_view_alloc)
View(*this, _texture,
{ .transparent = false, .background = false },
@ -230,39 +239,32 @@ Gui_session::Create_view_result Gui_session::create_view()
}
Gui_session::Create_child_view_result Gui_session::create_child_view(View_id const parent)
Gui_session::Child_view_result
Gui_session::child_view(View_id const id, View_id const parent, View_attr const &attr)
{
using Error = Create_child_view_error;
return _with_view(parent,
[&] (View &parent) -> Create_child_view_result {
[&] (View &parent) -> Child_view_result {
View *view_ptr = nullptr;
Create_view_result const result = _create_view_with_id(
[&] () -> View & {
view_ptr = new (_view_alloc)
View(*this, _texture,
{ .transparent = false, .background = false },
&parent);
return *view_ptr;
});
View_result const result = _create_view_and_ref(id, attr, [&] () -> View & {
view_ptr = new (_view_alloc)
View(*this, _texture,
{ .transparent = false, .background = false },
&parent);
return *view_ptr;
});
return result.convert<Create_child_view_result>(
[&] (View_id id) {
if (view_ptr)
parent.add_child(*view_ptr);
return id;
},
[&] (Create_view_error e) {
switch (e) {
case Create_view_error::OUT_OF_RAM: return Error::OUT_OF_RAM;
case Create_view_error::OUT_OF_CAPS: return Error::OUT_OF_CAPS;
};
return Error::INVALID;
});
switch (result) {
case View_result::OUT_OF_RAM: return Child_view_result::OUT_OF_RAM;
case View_result::OUT_OF_CAPS: return Child_view_result::OUT_OF_CAPS;
case View_result::OK: break;
}
if (view_ptr)
parent.add_child(*view_ptr);
return Child_view_result::OK;
},
[&] /* parent view does not exist */ () -> Create_child_view_result {
return Error::INVALID; }
[&] /* parent view does not exist */ () -> Child_view_result {
return Child_view_result::INVALID; }
);
}
@ -317,24 +319,6 @@ void Gui_session::destroy_view(View_id const id)
}
Gui_session::Alloc_view_id_result
Gui_session::alloc_view_id(View_capability view_cap)
{
return _env.ep().rpc_ep().apply(view_cap,
[&] (View *view_ptr) -> Alloc_view_id_result {
if (!view_ptr)
return Alloc_view_id_error::INVALID;
try {
View_ref &view_ref = *new (_view_ref_alloc)
View_ref(view_ptr->weak_ptr(), _view_ids);
return view_ref.id.id();
}
catch (Out_of_ram) { return Alloc_view_id_error::OUT_OF_RAM; }
catch (Out_of_caps) { return Alloc_view_id_error::OUT_OF_CAPS; }
});
}
Gui_session::View_id_result
Gui_session::view_id(View_capability view_cap, View_id id)
{

View File

@ -48,8 +48,6 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
{
private:
using View_ids = Id_space<Gui::View_ref>;
struct View_ref : Gui::View_ref
{
Weak_ptr<View> _weak_ptr;
@ -178,7 +176,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
void _adopt_new_view(View &);
Create_view_result _create_view_with_id(auto const &);
View_result _create_view_and_ref(View_id, View_attr const &attr, auto const &);
auto _with_view(View_id id, auto const &fn, auto const &missing_fn)
-> decltype(missing_fn())
@ -386,14 +384,12 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
Input::Session_capability input() override {
return _input_session_cap; }
Create_view_result create_view() override;
View_result view(View_id, View_attr const &attr) override;
Create_child_view_result create_child_view(View_id) override;
Child_view_result child_view(View_id, View_id, View_attr const &attr) override;
void destroy_view(View_id) override;
Alloc_view_id_result alloc_view_id(View_capability) override;
View_id_result view_id(View_capability, View_id) override;
View_capability view_capability(View_id) override;

View File

@ -297,7 +297,7 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
Cpu::Signal_handler<Virtio_gpu_device> _handler;
Constructible<Attached_dataspace> _fb_ds { };
Framebuffer::Mode _fb_mode { _gui.mode() };
Gui::View_id _view = _gui.create_view();
Gui::Top_level_view _view { _gui, { { }, _fb_mode.area } };
using Area = Genode::Area<>;
using Rect = Genode::Rect<>;
@ -465,8 +465,8 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_view, Rect(Point(0, 0), _fb_mode.area));
_gui.enqueue<Command::Front>(_view);
_gui.enqueue<Command::Geometry>(_view.id(), Rect(Point(0, 0), _fb_mode.area));
_gui.enqueue<Command::Front>(_view.id());
_gui.execute();
return _gui.mode();
}

View File

@ -25,34 +25,10 @@ namespace Test {
using namespace Genode;
struct View;
struct Main;
}
class Test::View
{
private:
Gui::Connection &_gui;
Gui::View_id const _id = _gui.create_view();
Gui::Rect const _rect;
public:
View(Gui::Connection &gui, Gui::Rect rect) : _gui(gui), _rect(rect)
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_id, rect);
_gui.enqueue<Command::Front>(_id);
_gui.execute();
}
virtual ~View() { }
};
struct Test::Main
{
Env &_env;
@ -94,7 +70,7 @@ struct Test::Main
Attached_dataspace _fb_ds { _env.rm(), _gui.framebuffer.dataspace() };
Registry<Registered<View>> _views { };
Registry<Registered<Gui::Top_level_view>> _views { };
Output(Env &env, Allocator &alloc, Xml_node const &config)
:
@ -109,12 +85,12 @@ struct Test::Main
config.for_each_sub_node("view", [&] (Xml_node node) {
new (_alloc)
Registered<View>(_views, _gui, view_rect(node)); });
Registered<Gui::Top_level_view>(_views, _gui, view_rect(node)); });
}
~Output()
{
_views.for_each([&] (Registered<View> &view) {
_views.for_each([&] (Registered<Gui::Top_level_view> &view) {
destroy(_alloc, &view); });
}

View File

@ -34,12 +34,7 @@ class Test::View : private List<View>::Element, Interface
{
public:
struct Attr
{
Gui::Point pos;
Gui::Area size;
Gui::Title title;
};
using Attr = Gui::Session::View_attr;
private:
@ -48,24 +43,18 @@ class Test::View : private List<View>::Element, Interface
using Command = Gui::Session::Command;
Gui::Connection &_gui;
Gui::Connection &_gui;
Gui::View_id const _id;
Attr const _attr;
Gui::Point _pos = _attr.pos;
Gui::Area const _size;
Gui::Point _pos;
public:
View(Gui::Connection &gui, Attr const attr, auto const &create_fn)
View(Gui::Connection &gui, Gui::View_id const id, Attr const attr)
:
_gui(gui), _id(create_fn()), _attr(attr)
{
using namespace Gui;
_gui.enqueue<Command::Geometry>(_id, Gui::Rect { _pos, _attr.size });
_gui.enqueue<Command::Front>(_id);
_gui.enqueue<Command::Title>(_id, _attr.title);
_gui.execute();
}
_gui(gui), _id(id), _size(attr.rect.area), _pos(attr.rect.at)
{ }
Gui::View_capability view_cap()
{
@ -81,13 +70,13 @@ class Test::View : private List<View>::Element, Interface
virtual void move(Gui::Point const pos)
{
_pos = pos;
_gui.enqueue<Command::Geometry>(_id, Gui::Rect { _pos, _attr.size });
_gui.enqueue<Command::Geometry>(_id, Gui::Rect { _pos, _size });
_gui.execute();
}
virtual Gui::Point pos() const { return _pos; }
Gui::Rect rect() const { return { pos(), _attr.size }; }
Gui::Rect rect() const { return { pos(), _size }; }
bool contains(Gui::Point pos) { return rect().contains(pos); }
};
@ -95,10 +84,12 @@ class Test::View : private List<View>::Element, Interface
struct Test::Top_level_view : View
{
Top_level_view(Gui::Connection &gui, Attr const &attr)
Top_level_view(Gui::Connection &gui, Gui::View_id const id, Attr const &attr)
:
View(gui, attr, [&] { return gui.create_view(); })
{ }
View(gui, id, attr)
{
gui.view(id, attr);
}
};
@ -106,17 +97,15 @@ struct Test::Child_view : View
{
View &_parent;
Child_view(Gui::Connection &gui, View &parent, Attr const &attr)
Child_view(Gui::Connection &gui, Gui::View_id const id, View &parent, Attr const &attr)
:
View(gui, attr,
[&] /* create_fn */ {
Gui::View_id const parent_id = gui.alloc_view_id(parent.view_cap());
Gui::View_id const id = gui.create_child_view(parent_id);
gui.release_view_id(parent_id);
return id;
}
), _parent(parent)
{ }
View(gui, id, attr), _parent(parent)
{
Gui::View_id const parent_id { 0 }; /* temporary */
gui.view_id(parent.view_cap(), parent_id);
gui.child_view(id, parent_id, attr);
gui.release_view_id(parent_id);
}
void move(Gui::Point const pos) override
{
@ -219,17 +208,17 @@ struct Test::Main
/*
* View '_v1' is used as coordinate origin of '_v2' and '_v3'.
*/
Top_level_view _v1 { _gui, { .pos = { 150, 100 },
.size = { 230, 200 },
.title = "Eins" } };
Top_level_view _v1 { _gui, { 1 }, { .title = "Eins",
.rect = { { 150, 100 }, { 230, 200 } },
.front = true } };
Child_view _v2 { _gui, _v1, { .pos = { 20, 20 },
.size = { 230, 210 },
.title = "Zwei" } };
Child_view _v2 { _gui, { 2 }, _v1, { .title = "Zwei",
.rect = { { 20, 20 }, { 230, 210 } },
.front = true } };
Child_view _v3 { _gui, _v1, { .pos = { 40, 40 },
.size = { 230, 220 },
.title = "Drei" } };
Child_view _v3 { _gui, { 3 }, _v1, { .title = "Drei",
.rect = { { 40, 40 }, { 230, 220 } },
.front = true } };
Signal_handler<Main> _input_handler { _env.ep(), *this, &Main::_handle_input };

View File

@ -27,34 +27,10 @@ namespace Test {
using namespace Genode;
struct View;
struct Main;
}
class Test::View
{
private:
Gui::Connection &_gui;
Gui::View_id const _id = _gui.create_view();
Gui::Rect const _rect;
public:
View(Gui::Connection &gui, Gui::Rect rect) : _gui(gui), _rect(rect)
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_id, rect);
_gui.enqueue<Command::Front>(_id);
_gui.execute();
}
virtual ~View() { }
};
struct Test::Main
{
Env &_env;
@ -98,7 +74,7 @@ struct Test::Main
Attached_dataspace _fb_ds { _env.rm(), _gui.framebuffer.dataspace() };
Registry<Registered<View>> _views { };
Registry<Registered<Gui::Top_level_view>> _views { };
Output(Env &env, Allocator &alloc, Xml_node const &config)
:
@ -113,12 +89,12 @@ struct Test::Main
config.for_each_sub_node("view", [&] (Xml_node node) {
new (_alloc)
Registered<View>(_views, _gui, view_rect(node)); });
Registered<Gui::Top_level_view>(_views, _gui, view_rect(node)); });
}
~Output()
{
_views.for_each([&] (Registered<View> &view) {
_views.for_each([&] (Registered<Gui::Top_level_view> &view) {
destroy(_alloc, &view); });
}

View File

@ -31,10 +31,10 @@ class Genodefb :
{
private:
Genode::Env &_env;
Gui::Connection &_gui;
Gui::View_id _view;
Fb_Genode::Mode _fb_mode { .area = { 1024, 768 } };
Genode::Env &_env;
Gui::Connection &_gui;
Gui::Top_level_view _view { _gui };
Fb_Genode::Mode _fb_mode { .area = { 1024, 768 } };
/*
* The mode currently used by the VM. Can be smaller than the
@ -73,22 +73,13 @@ class Genodefb :
void _adjust_buffer()
{
_gui.buffer(_fb_mode, false);
Gui::Rect rect(Gui::Point(0, 0), _fb_mode.area);
_gui.enqueue<Gui::Session::Command::Geometry>(_view, rect);
_gui.execute();
_view.area(_fb_mode.area);
}
Fb_Genode::Mode _initial_setup()
{
_view = _gui.create_view();
_adjust_buffer();
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.execute();
_view.front();
return _fb_mode;
}

View File

@ -30,10 +30,10 @@ class Genodefb :
{
private:
Genode::Env &_env;
Gui::Connection &_gui;
Gui::View_id _view;
Fb_Genode::Mode _fb_mode { .area = { 1024, 768 } };
Genode::Env &_env;
Gui::Connection &_gui;
Gui::Top_level_view _view { _gui };
Fb_Genode::Mode _fb_mode { .area = { 1024, 768 } };
/*
* The mode currently used by the VM. Can be smaller than the
@ -71,22 +71,13 @@ class Genodefb :
void _adjust_buffer()
{
_gui.buffer(_fb_mode, false);
Gui::Rect rect(Gui::Point(0, 0), _fb_mode.area);
_gui.enqueue<Gui::Session::Command::Geometry>(_view, rect);
_gui.execute();
_view.area(_fb_mode.area);
}
Fb_Genode::Mode _initial_setup()
{
_view = _gui.create_view();
_adjust_buffer();
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.execute();
_view.front();
return _fb_mode;
}