gui_session: remove C++ exceptions

To maintain ease of use at the client side, the OUT_OF_RAM and
OUT_OF_CAPS results are handled at the 'Gui::Connection' now.

Gui::Connection does not inherit the Gui::Session interface any longer,
which allows for the use of different result types.

Issue #5242
Issue #5245
This commit is contained in:
Norman Feske 2024-08-05 13:47:22 +02:00 committed by Christian Helmuth
parent 1c148c7984
commit 9823b7dbd0
22 changed files with 523 additions and 344 deletions

View File

@ -352,7 +352,7 @@ class Log_view
{
private:
Gui::Session_client &_gui;
Gui::Connection &_gui;
Gui::Point _pos;
Gui::Area _size;
Gui::Session::View_handle _handle;
@ -362,7 +362,7 @@ class Log_view
public:
Log_view(Gui::Session_client &gui, Gui::Rect geometry)
Log_view(Gui::Connection &gui, Gui::Rect geometry)
:
_gui(gui),
_pos(geometry.at),

View File

@ -183,22 +183,9 @@ struct Decorator::Main : Window_factory_base
*/
Window_base *create(Xml_node window_node) override
{
for (;;) {
try {
return new (_heap)
Window(window_node.attribute_value("id", 0U),
_gui, _animator, _decorator_config);
}
catch (Genode::Out_of_ram) {
Genode::log("Handle Out_of_ram of GUI session - upgrade by 8K");
_gui.upgrade_ram(8192);
}
catch (Genode::Out_of_caps) {
Genode::log("Handle Out_of_caps of GUI session - upgrade by 2");
_gui.upgrade_caps(2);
}
}
return nullptr;
return new (_heap)
Window(window_node.attribute_value("id", 0U),
_gui, _animator, _decorator_config);
}
/**

View File

@ -16,6 +16,7 @@
/* Genode includes */
#include <decorator/window.h>
#include <gui_session/connection.h>
/* local includes */
#include "config.h"
@ -29,7 +30,7 @@ class Decorator::Window : public Window_base
{
private:
Gui::Session_client &_gui;
Gui::Connection &_gui;
/*
* Flag indicating that the current window position has been propagated
@ -39,13 +40,13 @@ class Decorator::Window : public Window_base
struct Gui_view
{
Gui::Session_client &_gui;
Gui::Connection &_gui;
View_handle _handle { _gui.create_view() };
using Command = Gui::Session::Command;
Gui_view(Gui::Session_client &gui, unsigned id = 0)
Gui_view(Gui::Connection &gui, unsigned id = 0)
:
_gui(gui)
{
@ -419,7 +420,7 @@ class Decorator::Window : public Window_base
public:
Window(unsigned id, Gui::Session_client &gui,
Window(unsigned id, Gui::Connection &gui,
Animator &animator, Config const &config)
:
Window_base(id),

View File

@ -57,7 +57,11 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
Input::Seq_number &_global_input_seq_number;
Gui::Connection _connection;
Genode::Connection<Gui::Session> _connection;
Gui::Session_client _gui_session { _connection.cap() };
Input::Session_client _gui_input { _env.rm(), _gui_session.input_session() };
Input::Session_component _input_component { _env, _env.ram() };
@ -68,7 +72,7 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
void _handle_input()
{
_connection.input()->for_each_event([&] (Input::Event ev) {
_gui_input.for_each_event([&] (Input::Event ev) {
/*
* Assign new event sequence number, pass seq event to menu view
@ -97,9 +101,9 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
:
_env(env), _event_handler(event_handler),
_global_input_seq_number(global_input_seq_number),
_connection(env, session_label_from_args(args).string())
_connection(env, session_label_from_args(args), Ram_quota { 36*1024 }, { })
{
_connection.input()->sigh(_input_handler);
_gui_input.sigh(_input_handler);
_env.ep().manage(_input_component);
_input_component.event_queue().enabled(true);
}
@ -112,52 +116,46 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
}
Framebuffer::Session_capability framebuffer_session() override {
return _connection.framebuffer_session(); }
return _gui_session.framebuffer_session(); }
Input::Session_capability input_session() override {
return _input_component.cap(); }
View_handle create_view() override {
return _connection.create_view(); }
Create_view_result create_view() override {
return _gui_session.create_view(); }
View_handle create_child_view(View_handle parent) override {
return _connection.create_child_view(parent); }
Create_child_view_result create_child_view(View_handle parent) override {
return _gui_session.create_child_view(parent); }
void destroy_view(View_handle view) override {
_connection.destroy_view(view); }
_gui_session.destroy_view(view); }
View_handle view_handle(View_capability view_cap, View_handle handle) override {
return _connection.view_handle(view_cap, handle); }
View_handle_result view_handle(View_capability view_cap, View_handle handle) override {
return _gui_session.view_handle(view_cap, handle); }
View_capability view_capability(View_handle view) override {
return _connection.view_capability(view); }
return _gui_session.view_capability(view); }
void release_view_handle(View_handle view) override {
_connection.release_view_handle(view); }
_gui_session.release_view_handle(view); }
Dataspace_capability command_dataspace() override {
return _connection.command_dataspace(); }
return _gui_session.command_dataspace(); }
void execute() override {
_connection.execute(); }
_gui_session.execute(); }
Framebuffer::Mode mode() override {
return _connection.mode(); }
return _gui_session.mode(); }
void mode_sigh(Signal_context_capability sigh) override {
_connection.mode_sigh(sigh); }
_gui_session.mode_sigh(sigh); }
void buffer(Framebuffer::Mode mode, bool use_alpha) override
{
/*
* Do not call 'Connection::buffer' to avoid paying session quota
* from our own budget.
*/
_connection.Session_client::buffer(mode, use_alpha);
}
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override {
return _gui_session.buffer(mode, use_alpha); }
void focus(Capability<Gui::Session> session) override {
_connection.focus(session); }
_gui_session.focus(session); }
};

View File

@ -170,21 +170,9 @@ struct Decorator::Main : Window_factory_base
*/
Window_base *create(Xml_node window_node) override
{
for (;;) {
try {
return new (_heap)
Window(_env, window_node.attribute_value("id", 0U),
_gui, _animator, _theme, _decorator_config);
}
catch (Out_of_ram) {
log("Handle Out_of_ram of GUI session - upgrade by 8K");
_gui.upgrade_ram(8192);
}
catch (Out_of_caps) {
log("Handle Out_of_caps of GUI session - upgrade by 2");
_gui.upgrade_caps(2);
}
}
return new (_heap)
Window(_env, window_node.attribute_value("id", 0U),
_gui, _animator, _theme, _decorator_config);
}
/**

View File

@ -147,11 +147,11 @@ class Decorator::Window : public Window_base, public Animator::Item
bool const _view_is_remote;
Gui::Session_client &_gui;
Gui::Connection &_gui;
View_handle _handle;
Gui_view(Gui::Session_client &gui, unsigned id = 0)
Gui_view(Gui::Connection &gui, unsigned id = 0)
:
_view_is_remote(false),
_gui(gui),
@ -165,7 +165,7 @@ class Decorator::Window : public Window_base, public Animator::Item
Genode::String<128>(id).string());
}
View_handle _create_remote_view(Gui::Session_client &remote_gui)
View_handle _create_remote_view(Gui::Connection &remote_gui)
{
/* create view at the remote GUI session */
View_handle handle = remote_gui.create_view();
@ -179,8 +179,8 @@ class Decorator::Window : public Window_base, public Animator::Item
* Constructor called for creating a view that refers to a buffer
* of another GUI session
*/
Gui_view(Gui::Session_client &gui,
Gui::Session_client &remote_gui)
Gui_view(Gui::Connection &gui,
Gui::Connection &remote_gui)
:
_view_is_remote(true),
_gui(gui),
@ -217,7 +217,7 @@ class Decorator::Window : public Window_base, public Animator::Item
/**
* GUI session used as a global namespace of view handles
*/
Gui::Session_client &_gui;
Gui::Connection &_gui;
Config const &_config;
@ -369,7 +369,7 @@ class Decorator::Window : public Window_base, public Animator::Item
public:
Window(Genode::Env &env, unsigned id, Gui::Session_client &gui,
Window(Genode::Env &env, unsigned id, Gui::Connection &gui,
Animator &animator, Theme const &theme, Config const &config)
:
Window_base(id),

View File

@ -336,7 +336,7 @@ struct Window_layouter::Main : Operations,
_env.ep(), *this, &Main::_handle_mode_change };
Input::Session_client _input { _env.rm(), _gui.input_session() };
Input::Session_client &_input = *_gui.input();
Attached_dataspace _input_ds { _env.rm(), _input.dataspace() };

View File

@ -59,7 +59,11 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
using View_capability = Gui::View_capability;
Gui::Connection _connection;
Genode::Connection<Gui::Session> _connection;
Gui::Session_client _gui_session { _connection.cap() };
Input::Session_client _gui_input { _env.rm(), _gui_session.input_session() };
Input::Session_component _input_component { _env, _env.ram() };
@ -70,7 +74,7 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
void _handle_input()
{
_connection.input()->for_each_event([&] (Input::Event const &ev) {
_gui_input.for_each_event([&] (Input::Event const &ev) {
/*
* Assign new event sequence number, pass seq event to menu view
@ -101,9 +105,9 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
Session_object(args...),
_env(env), _view(view),
_element(_view._gui_sessions, *this),
_connection(env, _label.string())
_connection(env, _label, Ram_quota { 36*1024 }, { })
{
_connection.input()->sigh(_input_handler);
_gui_input.sigh(_input_handler);
_env.ep().manage(_input_component);
_input_component.event_queue().enabled(true);
}
@ -116,52 +120,46 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
}
Framebuffer::Session_capability framebuffer_session() override {
return _connection.framebuffer_session(); }
return _gui_session.framebuffer_session(); }
Input::Session_capability input_session() override {
return _input_component.cap(); }
View_handle create_view() override {
return _connection.create_view(); }
Create_view_result create_view() override {
return _gui_session.create_view(); }
View_handle create_child_view(View_handle parent) override {
return _connection.create_child_view(parent); }
Create_child_view_result create_child_view(View_handle parent) override {
return _gui_session.create_child_view(parent); }
void destroy_view(View_handle view) override {
_connection.destroy_view(view); }
_gui_session.destroy_view(view); }
View_handle view_handle(View_capability view_cap, View_handle handle) override {
return _connection.view_handle(view_cap, handle); }
View_handle_result view_handle(View_capability view_cap, View_handle handle) override {
return _gui_session.view_handle(view_cap, handle); }
View_capability view_capability(View_handle view) override {
return _connection.view_capability(view); }
return _gui_session.view_capability(view); }
void release_view_handle(View_handle view) override {
_connection.release_view_handle(view); }
_gui_session.release_view_handle(view); }
Dataspace_capability command_dataspace() override {
return _connection.command_dataspace(); }
return _gui_session.command_dataspace(); }
void execute() override {
_connection.execute(); }
_gui_session.execute(); }
Framebuffer::Mode mode() override {
return _connection.mode(); }
return _gui_session.mode(); }
void mode_sigh(Signal_context_capability sigh) override {
_connection.mode_sigh(sigh); }
_gui_session.mode_sigh(sigh); }
void buffer(Framebuffer::Mode mode, bool use_alpha) override
{
/*
* Do not call 'Connection::buffer' to avoid paying session quota
* from our own budget.
*/
_connection.Session_client::buffer(mode, use_alpha);
}
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override {
return _gui_session.buffer(mode, use_alpha); }
void focus(Capability<Gui::Session> session) override {
_connection.focus(session); }
_gui_session.focus(session); }
};

View File

@ -342,17 +342,17 @@ class Gui_fader::Gui_session_component
Input::Session_capability input_session() override
{
return _gui.input_session();
return _gui.cap().call<Gui::Session::Rpc_input_session>();
}
View_handle create_view() override
Create_view_result create_view() override
{
_view_handle = _gui.create_view();
_update_view_visibility();
return _view_handle;
}
View_handle create_child_view(View_handle parent) override
Create_child_view_result create_child_view(View_handle parent) override
{
_view_handle = _gui.create_child_view(parent);
_update_view_visibility();
@ -364,8 +364,8 @@ class Gui_fader::Gui_session_component
return _gui.destroy_view(handle);
}
View_handle view_handle(View_capability view_cap,
View_handle handle) override
View_handle_result view_handle(View_capability view_cap,
View_handle handle) override
{
return _gui.view_handle(view_cap, handle);
}
@ -420,7 +420,7 @@ class Gui_fader::Gui_session_component
_gui.mode_sigh(sigh);
}
void buffer(Framebuffer::Mode mode, bool use_alpha) override
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override
{
Area const size = mode.area;
@ -429,6 +429,7 @@ class Gui_fader::Gui_session_component
_gui.buffer(mode, true);
_fb_session.dst_buffer(_gui.framebuffer()->dataspace(), size);
return Buffer_result::OK;
}
void focus(Genode::Capability<Session> focused) override

View File

@ -16,8 +16,6 @@
/* Genode includes */
#include <util/string.h>
#include <base/attached_dataspace.h>
#include <gui_session/connection.h>
#include <input_session/client.h>
#include <input/event.h>
#include <input/component.h>
@ -25,6 +23,7 @@
/* local includes */
#include <window_registry.h>
#include <pointer.h>
#include <real_gui.h>
namespace Wm { class Main;
using Genode::size_t;
@ -166,13 +165,15 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
Genode::Ram_allocator &_ram;
Gui::Connection _gui_session { _env, "decorator" };
Real_gui _gui { _env, "decorator" };
Input::Session_client _input_session { _env.rm(), _gui.session.input_session() };
Genode::Signal_context_capability _mode_sigh { };
Attached_ram_dataspace _command_ds { _ram, _env.rm(), sizeof(Command_buffer) };
Attached_ram_dataspace _client_command_ds { _ram, _env.rm(), sizeof(Command_buffer) };
Command_buffer &_command_buffer = *_command_ds.local_addr<Command_buffer>();
Command_buffer &_client_command_buffer = *_client_command_ds.local_addr<Command_buffer>();
Pointer::State _pointer_state;
@ -212,7 +213,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
_content_callback(content_callback),
_md_alloc(md_alloc)
{
_gui_session.input()->sigh(_input_handler);
_input_session.sigh(_input_handler);
}
~Decorator_gui_session()
@ -222,8 +223,8 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
void _handle_input()
{
while (_gui_session.input()->pending())
_gui_session.input()->for_each_event([&] (Input::Event const &ev) {
while (_input_session.pending())
_input_session.for_each_event([&] (Input::Event const &ev) {
_pointer_state.apply_event(ev);
_window_layouter_input.submit(ev); });
}
@ -267,11 +268,11 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
*/
View_capability view_cap = _content_callback.content_view(win_id);
_gui_session.destroy_view(view_handle);
_gui_session.view_handle(view_cap, view_handle);
_gui.session.destroy_view(view_handle);
_gui.session.view_handle(view_cap, view_handle);
_gui_session.enqueue(cmd);
_gui_session.execute();
_gui.enqueue(cmd);
_gui.execute();
/*
* Now that the physical content view exists, it is time
@ -281,7 +282,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
} catch (Decorator_content_registry::Lookup_failed) {
_gui_session.enqueue(cmd);
_gui.enqueue(cmd);
}
return;
@ -302,7 +303,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
catch (Decorator_content_registry::Lookup_failed) { }
/* forward command */
_gui_session.enqueue(cmd);
_gui.enqueue(cmd);
return;
case Command::OP_OFFSET:
@ -316,21 +317,21 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
_content_registry.lookup(cmd.geometry.view);
}
catch (Decorator_content_registry::Lookup_failed) {
_gui_session.enqueue(cmd);
_gui.enqueue(cmd);
}
return;
case Command::OP_BACKGROUND:
case Command::OP_NOP:
_gui_session.enqueue(cmd);
_gui.enqueue(cmd);
return;
}
}
void upgrade(const char *args)
{
_gui_session.upgrade(Genode::session_resources_from_args(args));
_gui.connection.upgrade(Genode::session_resources_from_args(args));
}
Pointer::Position last_observed_pointer_pos() const
@ -345,7 +346,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
Framebuffer::Session_capability framebuffer_session() override
{
return _gui_session.framebuffer_session();
return _gui.session.framebuffer_session();
}
Input::Session_capability input_session() override
@ -357,14 +358,14 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
return _dummy_input_component_cap;
}
View_handle create_view() override
Create_view_result create_view() override
{
return _gui_session.create_view();
return _gui.session.create_view();
}
View_handle create_child_view(View_handle parent) override
Create_child_view_result create_child_view(View_handle parent) override
{
return _gui_session.create_child_view(parent);
return _gui.session.create_child_view(parent);
}
void destroy_view(View_handle view) override
@ -374,53 +375,53 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
*/
if (_content_registry.registered(view)) {
Gui::Rect rect(Gui::Point(0, 0), Gui::Area(0, 0));
_gui_session.enqueue<Gui::Session::Command::Geometry>(view, rect);
_gui_session.execute();
_gui.enqueue<Gui::Session::Command::Geometry>(view, rect);
_gui.execute();
Window_registry::Id win_id = _content_registry.lookup(view);
_content_callback.hide_content_child_views(win_id);
}
_gui_session.destroy_view(view);
_gui.session.destroy_view(view);
}
View_handle view_handle(View_capability view_cap, View_handle handle) override
View_handle_result view_handle(View_capability view_cap, View_handle handle) override
{
return _gui_session.view_handle(view_cap, handle);
return _gui.session.view_handle(view_cap, handle);
}
View_capability view_capability(View_handle view) override
{
return _gui_session.view_capability(view);
return _gui.session.view_capability(view);
}
void release_view_handle(View_handle view) override
{
/* XXX dealloc View_ptr */
_gui_session.release_view_handle(view);
_gui.session.release_view_handle(view);
}
Genode::Dataspace_capability command_dataspace() override
{
return _command_ds.cap();
return _client_command_ds.cap();
}
void execute() override
{
for (unsigned i = 0; i < _command_buffer.num(); i++) {
for (unsigned i = 0; i < _client_command_buffer.num(); i++) {
try {
_execute_command(_command_buffer.get(i));
_execute_command(_client_command_buffer.get(i));
}
catch (...) {
Genode::warning("unhandled exception while processing command from decorator");
}
}
_gui_session.execute();
_gui.execute();
}
Framebuffer::Mode mode() override
{
return _gui_session.mode();
return _gui.session.mode();
}
void mode_sigh(Genode::Signal_context_capability sigh) override
@ -430,15 +431,12 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
* transitive delegations of the capability.
*/
_mode_sigh = sigh;
_gui_session.mode_sigh(sigh);
_gui.session.mode_sigh(sigh);
}
void buffer(Framebuffer::Mode mode, bool use_alpha) override
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override
{
/*
* See comment in 'Wm::Gui::Session_component::buffer'.
*/
Gui::Session_client(_env.rm(), _gui_session.cap()).buffer(mode, use_alpha);
return _gui.session.buffer(mode, use_alpha);
}
void focus(Genode::Capability<Gui::Session>) override { }

View File

@ -25,24 +25,29 @@ class Wm::Direct_gui_session : public Genode::Rpc_object<Gui::Session>
{
private:
Genode::Session_label _session_label;
Gui::Connection _session;
Genode::Env &_env;
Genode::Session_label _label;
Genode::Connection<Gui::Session> _connection {
_env, _label, Genode::Ram_quota { 36*1024 }, /* Args */ { } };
Gui::Session_client _session { _connection.cap() };
public:
/**
* Constructor
*/
Direct_gui_session(Genode::Env &env, Genode::Session_label const &session_label)
Direct_gui_session(Genode::Env &env, Genode::Session_label const &label)
:
_session_label(session_label),
_session(env, _session_label.string())
_env(env), _label(label)
{ }
void upgrade(char const *args)
{
size_t const ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
_session.upgrade_ram(ram_quota);
_connection.upgrade_ram(ram_quota);
}
@ -60,12 +65,12 @@ class Wm::Direct_gui_session : public Genode::Rpc_object<Gui::Session>
return _session.input_session();
}
View_handle create_view() override
Create_view_result create_view() override
{
return _session.create_view();
}
View_handle create_child_view(View_handle parent) override
Create_child_view_result create_child_view(View_handle parent) override
{
return _session.create_child_view(parent);
}
@ -75,7 +80,7 @@ class Wm::Direct_gui_session : public Genode::Rpc_object<Gui::Session>
_session.destroy_view(view);
}
View_handle view_handle(Gui::View_capability view_cap, View_handle handle) override
View_handle_result view_handle(Gui::View_capability view_cap, View_handle handle) override
{
return _session.view_handle(view_cap, handle);
}
@ -110,9 +115,9 @@ class Wm::Direct_gui_session : public Genode::Rpc_object<Gui::Session>
_session.mode_sigh(sigh);
}
void buffer(Framebuffer::Mode mode, bool use_alpha) override
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override
{
_session.buffer(mode, use_alpha);
return _session.buffer(mode, use_alpha);
}
void focus(Genode::Capability<Gui::Session> session) override

View File

@ -116,7 +116,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
using View_handle = Gui::Session::View_handle;
Session_label _session_label;
Gui::Session_client &_real_gui;
Real_gui &_real_gui;
View_handle _real_handle { };
Title _title { };
Rect _geometry { };
@ -125,7 +125,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
bool _neighbor_behind { };
bool _has_alpha;
View(Gui::Session_client &real_gui,
View(Real_gui &real_gui,
Session_label const &session_label,
bool has_alpha)
:
@ -153,7 +153,10 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
View_handle real_neighbor_handle;
if (neighbor.valid())
real_neighbor_handle = _real_gui.view_handle(neighbor->real_view_cap());
_real_gui.session.view_handle(neighbor->real_view_cap()).with_result(
[&] (View_handle handle) { real_neighbor_handle = handle; },
[&] (auto) { warning("unable to obtain real_neighbor_handle"); }
);
if (_neighbor_behind)
_real_gui.enqueue<Command::To_front>(_real_handle, real_neighbor_handle);
@ -163,7 +166,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
_real_gui.execute();
if (real_neighbor_handle.valid())
_real_gui.release_view_handle(real_neighbor_handle);
_real_gui.session.release_view_handle(real_neighbor_handle);
}
void _apply_view_config()
@ -177,7 +180,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
~View()
{
if (_real_handle.valid())
_real_gui.destroy_view(_real_handle);
_real_gui.session.destroy_view(_real_handle);
}
using Genode::Weak_object<View>::weak_ptr;
@ -218,7 +221,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
View_capability real_view_cap()
{
return _real_gui.view_capability(_real_handle);
return _real_gui.session.view_capability(_real_handle);
}
void buffer_offset(Point buffer_offset)
@ -255,23 +258,23 @@ class Wm::Gui::Top_level_view : public View, private List<Top_level_view>::Eleme
bool _resizeable = false;
Title _window_title { };
Session_label _session_label;
Title _window_title { };
Session_label const _session_label;
using Command = Gui::Session::Command;
public:
Top_level_view(Gui::Session_client &real_gui,
Session_label const &session_label,
Top_level_view(Real_gui &real_gui,
bool has_alpha,
Window_registry &window_registry,
Input_origin_changed_handler &input_origin_changed_handler)
:
View(real_gui, session_label, has_alpha),
View(real_gui, real_gui.label, has_alpha),
_window_registry(window_registry),
_input_origin_changed_handler(input_origin_changed_handler),
_session_label(session_label)
_session_label(real_gui.label)
{ }
~Top_level_view()
@ -347,14 +350,22 @@ class Wm::Gui::Top_level_view : public View, private List<Top_level_view>::Eleme
/*
* Create and configure physical GUI view.
*/
_real_handle = _real_gui.create_view();
_real_gui.session.create_view().with_result(
[&] (View_handle handle) {
_real_handle = handle;
_real_gui.enqueue<Command::Offset>(_real_handle, _buffer_offset);
_real_gui.enqueue<Command::Title> (_real_handle, _title.string());
_real_gui.execute();
},
[&] (Gui::Session::Create_view_error) { }
);
_real_gui.enqueue<Command::Offset>(_real_handle, _buffer_offset);
_real_gui.enqueue<Command::Title> (_real_handle, _title.string());
_real_gui.execute();
if (!_real_handle.valid()) {
warning("failed to created content view for ", _title);
return { };
}
}
return _real_gui.view_capability(_real_handle);
return _real_gui.session.view_capability(_real_handle);
}
void hidden(bool hidden) { _window_registry.hidden(_win_id, hidden); }
@ -379,12 +390,11 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
public:
Child_view(Gui::Session_client &real_gui,
Session_label const &session_label,
bool has_alpha,
Weak_ptr<View> parent)
Child_view(Real_gui &real_gui,
bool has_alpha,
Weak_ptr<View> parent)
:
View(real_gui, session_label, has_alpha), _parent(parent)
View(real_gui, real_gui.label, has_alpha), _parent(parent)
{
try_to_init_real_view();
}
@ -433,13 +443,26 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
if (!parent.valid())
return;
View_handle parent_handle = _real_gui.view_handle(parent->real_view_cap());
if (!parent_handle.valid())
View_handle parent_handle { };
_real_gui.session.view_handle(parent->real_view_cap()).with_result(
[&] (View_handle handle) { parent_handle = handle; },
[&] (Gui::Session::View_handle_error) { }
);
if (!parent_handle.valid()) {
warning("try_to_init_real_view failed to obtain parent handle");
return;
}
_real_handle = _real_gui.create_child_view(parent_handle);
_real_gui.session.create_child_view(parent_handle).with_result(
[&] (View_handle handle) { _real_handle = handle; },
[&] (Gui::Session::Create_child_view_error) { }
);
if (!_real_handle.valid()) {
warning("try_to_init_real_view failed to create child view");
return;
}
_real_gui.release_view_handle(parent_handle);
_real_gui.session.release_view_handle(parent_handle);
if (_neighbor_ptr == _parent)
_unsynchronized_apply_view_config(parent);
@ -457,7 +480,7 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
if (!_real_handle.valid())
return;
_real_gui.destroy_view(_real_handle);
_real_gui.session.destroy_view(_real_handle);
_real_handle = { };
}
};
@ -475,10 +498,9 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
Genode::Env &_env;
Session_label _session_label;
Genode::Ram_allocator &_ram;
Gui::Connection _session { _env, _session_label.string() };
Session_label _session_label;
Genode::Ram_allocator &_ram;
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;
@ -516,7 +538,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
/*
* Input
*/
Input::Session_client _gui_input { _env.rm(), _session.input_session() };
Input::Session_client _gui_input { _env.rm(), _real_gui.session.input_session() };
Attached_dataspace _gui_input_ds { _env.rm(), _gui_input.dataspace() };
Signal_handler<Session_component> _input_handler {
@ -661,7 +683,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
View &_create_view_object()
{
Top_level_view *view = new (_top_level_view_alloc)
Top_level_view(_session, _session_label, _has_alpha,
Top_level_view(_real_gui, _has_alpha,
_window_registry, *this);
view->resizeable(_mode_sigh.valid());
@ -675,7 +697,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
Weak_ptr<View> parent_ptr = _view_handle_registry.lookup(parent_handle);
Child_view *view = new (_child_view_alloc)
Child_view(_session, _session_label, _has_alpha, parent_ptr);
Child_view(_real_gui, _has_alpha, parent_ptr);
_child_views.insert(view);
return *view;
@ -803,7 +825,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
_view_handle_registry(session_alloc)
{
_gui_input.sigh(_input_handler);
_session.mode_sigh(_mode_handler);
_real_gui.session.mode_sigh(_mode_handler);
_input_session.event_queue().enabled(true);
}
@ -822,7 +844,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
void upgrade(char const *args)
{
_session.upgrade(Genode::session_resources_from_args(args));
_real_gui.connection.upgrade(Genode::session_resources_from_args(args));
}
void try_to_init_real_child_views()
@ -914,7 +936,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
/**
* Return session capability to real GUI session
*/
Capability<Session> session() { return _session.rpc_cap(); }
Capability<Session> session() { return _real_gui.connection.cap(); }
/***************************
@ -923,7 +945,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
Framebuffer::Session_capability framebuffer_session() override
{
return _session.framebuffer_session();
return _real_gui.session.framebuffer_session();
}
Input::Session_capability input_session() override
@ -931,20 +953,26 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
return _input_session_cap;
}
View_handle create_view() override
Create_view_result create_view() override
{
View &view = _create_view_object();
_env.ep().manage(view);
return _view_handle_registry.alloc(view);
try {
View &view = _create_view_object();
_env.ep().manage(view);
return _view_handle_registry.alloc(view);
}
catch (Out_of_ram) { return Create_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { return Create_view_error::OUT_OF_CAPS; }
}
View_handle create_child_view(View_handle parent) override
Create_child_view_result create_child_view(View_handle parent) override
{
try {
View &view = _create_child_view_object(parent);
_env.ep().manage(view);
return _view_handle_registry.alloc(view);
}
catch (Out_of_ram) { return Create_child_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { return Create_child_view_error::OUT_OF_CAPS; }
catch (View_handle_registry::Lookup_failed) {
return View_handle(); }
}
@ -972,11 +1000,15 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
} catch (View_handle_registry::Lookup_failed) { }
}
View_handle view_handle(View_capability view_cap, View_handle handle) override
View_handle_result view_handle(View_capability view_cap, View_handle handle) override
{
return _env.ep().rpc_ep().apply(view_cap, [&] (View *view) {
return (view) ? _view_handle_registry.alloc(*view, handle)
: View_handle(); });
try {
return _env.ep().rpc_ep().apply(view_cap, [&] (View *view) {
return (view) ? _view_handle_registry.alloc(*view, handle)
: View_handle(); });
}
catch (Out_of_ram) { return View_handle_error::OUT_OF_RAM; }
catch (Out_of_caps) { return View_handle_error::OUT_OF_CAPS; }
}
View_capability view_capability(View_handle handle) override
@ -1017,7 +1049,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
Framebuffer::Mode mode() override
{
Framebuffer::Mode const real_mode = _session.mode();
Framebuffer::Mode const real_mode = _real_gui.session.mode();
/*
* While resizing the window, return requested window size as
@ -1054,7 +1086,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
v->resizeable(resizeable);
}
void buffer(Framebuffer::Mode mode, bool has_alpha) override
Buffer_result buffer(Framebuffer::Mode mode, bool has_alpha) override
{
/*
* We must not perform the 'buffer' operation on the connection
@ -1065,8 +1097,8 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
* wrapped GUI session. Otherwise, we would perform session
* upgrades initiated by the wm client's buffer operation twice.
*/
Gui::Session_client(_env.rm(), _session.cap()).buffer(mode, has_alpha);
_has_alpha = has_alpha;
return _real_gui.session.buffer(mode, has_alpha);
}
void focus(Genode::Capability<Gui::Session>) override { }
@ -1139,7 +1171,7 @@ class Wm::Gui::Root : public Genode::Rpc_object<Genode::Typed_root<Gui::Session>
/**
* GUI session used to perform session-control operations
*/
Gui::Session &_focus_gui_session;
Gui::Connection &_focus_gui_session;
public:
@ -1150,7 +1182,7 @@ class Wm::Gui::Root : public Genode::Rpc_object<Genode::Typed_root<Gui::Session>
Window_registry &window_registry, Allocator &md_alloc,
Genode::Ram_allocator &ram,
Pointer::Tracker &pointer_tracker, Reporter &focus_request_reporter,
Gui::Session &focus_gui_session)
Gui::Connection &focus_gui_session)
:
_env(env),
_md_alloc(md_alloc), _ram(ram),

View File

@ -62,13 +62,13 @@ struct Wm::Layouter_gui_session : Genode::Rpc_object<Gui::Session>
return _input_session_cap;
}
View_handle create_view() override { return View_handle(); }
Create_view_result create_view() override { return View_handle(); }
View_handle create_child_view(View_handle) override { return View_handle(); }
Create_child_view_result create_child_view(View_handle) override { return View_handle(); }
void destroy_view(View_handle) override { }
View_handle view_handle(View_capability, View_handle) override
View_handle_result view_handle(View_capability, View_handle) override
{
return View_handle();
}
@ -100,7 +100,7 @@ struct Wm::Layouter_gui_session : Genode::Rpc_object<Gui::Session>
_mode_sigh_gui.mode_sigh(sigh);
}
void buffer(Framebuffer::Mode, bool) override { }
Buffer_result buffer(Framebuffer::Mode, bool) override { return Buffer_result::OK; }
void focus(Genode::Capability<Gui::Session>) override { }
};

View File

@ -0,0 +1,75 @@
/*
* \brief Wrapped GUI session
* \author Norman Feske
* \date 2024-08-05
*/
/*
* Copyright (C) 2024 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _REAL_GUI_H_
#define _REAL_GUI_H_
/* Genode includes */
#include <base/connection.h>
#include <base/attached_dataspace.h>
#include <gui_session/client.h>
namespace Wm { struct Real_gui; }
struct Wm::Real_gui
{
private:
Genode::Env &_env;
public:
Genode::Session_label const &label;
using Command_buffer = Gui::Session::Command_buffer;
public:
Real_gui(Genode::Env &env, Genode::Session_label const &label)
:
_env(env), label(label)
{ }
Genode::Connection<Gui::Session> connection {
_env, label, Genode::Ram_quota { 36*1024 }, /* Args */ { } };
Gui::Session_client session { connection.cap() };
private:
Genode::Attached_dataspace _command_ds { _env.rm(), session.command_dataspace() };
Command_buffer &_command_buffer { *_command_ds.local_addr<Command_buffer>() };
public:
template <typename CMD>
void enqueue(auto &&... args) { enqueue(Gui::Session::Command( CMD { args... } )); }
void enqueue(Gui::Session::Command const &command)
{
if (_command_buffer.full())
execute();
_command_buffer.enqueue(command);
}
void execute()
{
session.execute();
_command_buffer.reset();
}
};
#endif /* _REAL_GUI_H_ */

View File

@ -16,7 +16,7 @@
#include <QtWidgets>
#include <gui_session/client.h>
#include <gui_session/connection.h>
class QEmbeddedViewWidget : public QWidget
@ -66,7 +66,7 @@ class QGenodeViewWidget : public QEmbeddedViewWidget
protected:
Gui::Session_client *gui;
Gui::Connection *gui;
Gui::Session::View_handle view_handle;
virtual void showEvent(QShowEvent *event);
@ -78,7 +78,7 @@ public:
QGenodeViewWidget(QWidget *parent =0);
~QGenodeViewWidget();
void setGenodeView(Gui::Session_client *gui,
void setGenodeView(Gui::Connection *gui,
Gui::Session::View_handle view_handle,
int buf_x, int buf_y, int w, int h);
};

View File

@ -2,7 +2,7 @@ _ZN17QGenodeViewWidget10paintEventEP11QPaintEvent T
_ZN17QGenodeViewWidget11qt_metacallEN11QMetaObject4CallEiPPv T
_ZN17QGenodeViewWidget11qt_metacastEPKc T
_ZN17QGenodeViewWidget12focusInEventEP11QFocusEvent T
_ZN17QGenodeViewWidget13setGenodeViewEPN3Gui14Session_clientEN6Genode6HandleINS0_4ViewEEEiiii T
_ZN17QGenodeViewWidget13setGenodeViewEPN3Gui10ConnectionEN6Genode6HandleINS0_4ViewEEEiiii T
_ZN17QGenodeViewWidget16staticMetaObjectE D 48
_ZN17QGenodeViewWidget9hideEventEP10QHideEvent T
_ZN17QGenodeViewWidget9showEventEP10QShowEvent T

View File

@ -137,7 +137,7 @@ QGenodeViewWidget::QGenodeViewWidget(QWidget *parent)
{ }
void QGenodeViewWidget::setGenodeView(Gui::Session_client *new_gui,
void QGenodeViewWidget::setGenodeView(Gui::Connection *new_gui,
Gui::Session::View_handle new_view_handle,
int buf_x, int buf_y, int w, int h)
{
@ -236,5 +236,5 @@ void QGenodeViewWidget::focusInEvent(QFocusEvent *)
QGenodePlatformWindow *platform_window =
dynamic_cast<QGenodePlatformWindow*>(window()->windowHandle()->handle());
platform_window->gui_session().focus(gui->rpc_cap());
platform_window->gui_session().focus(gui->cap());
}

View File

@ -21,25 +21,12 @@
namespace Gui { struct Session_client; }
class Gui::Session_client : public Rpc_client<Session>
struct Gui::Session_client : Rpc_client<Session>
{
private:
Attached_dataspace _command_ds;
Command_buffer &_command_buffer;
public:
/**
* Constructor
*/
Session_client(Region_map &rm, Session_capability session)
:
Rpc_client<Session>(session),
_command_ds(rm, command_dataspace()),
_command_buffer(*_command_ds.local_addr<Command_buffer>())
{ }
Session_client(Session_capability session) : Rpc_client<Session>(session) { }
Framebuffer::Session_capability framebuffer_session() override {
return call<Rpc_framebuffer_session>(); }
@ -47,17 +34,17 @@ class Gui::Session_client : public Rpc_client<Session>
Input::Session_capability input_session() override {
return call<Rpc_input_session>(); }
View_handle create_view() override {
Create_view_result create_view() override {
return call<Rpc_create_view>(); }
View_handle create_child_view(View_handle parent) override {
Create_child_view_result create_child_view(View_handle parent) override {
return call<Rpc_create_child_view>(parent); }
void destroy_view(View_handle view) override {
call<Rpc_destroy_view>(view); }
View_handle view_handle(View_capability view,
View_handle handle = View_handle()) override
View_handle_result view_handle(View_capability view,
View_handle handle = View_handle()) override
{
return call<Rpc_view_handle>(view, handle);
}
@ -71,11 +58,7 @@ class Gui::Session_client : public Rpc_client<Session>
Dataspace_capability command_dataspace() override {
return call<Rpc_command_dataspace>(); }
void execute() override
{
call<Rpc_execute>();
_command_buffer.reset();
}
void execute() override { call<Rpc_execute>(); }
Framebuffer::Mode mode() override {
return call<Rpc_mode>(); }
@ -83,30 +66,12 @@ class Gui::Session_client : public Rpc_client<Session>
void mode_sigh(Signal_context_capability sigh) override {
call<Rpc_mode_sigh>(sigh); }
void buffer(Framebuffer::Mode mode, bool alpha) override {
call<Rpc_buffer>(mode, alpha); }
Buffer_result buffer(Framebuffer::Mode mode, bool alpha) override {
return call<Rpc_buffer>(mode, alpha); }
void focus(Gui::Session_capability session) override {
call<Rpc_focus>(session); }
/**
* Enqueue command to command buffer
*
* The submitted command is not executed immediately. To execute a
* batch of enqueued commands, the 'execute' method must be called.
* Only in the corner case when there is not space left in the command
* buffer, the 'execute' is called to make room in the buffer.
*/
template <typename CMD>
void enqueue(auto &&... args) { enqueue(Command( CMD { args... } )); }
void enqueue(Command const &command)
{
if (_command_buffer.full())
execute();
_command_buffer.enqueue(command);
}
};
#endif /* _INCLUDE__GUI_SESSION__CLIENT_H_ */

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2008-2017 Genode Labs GmbH
* Copyright (C) 2008-2024 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -22,45 +22,43 @@
namespace Gui { class Connection; }
class Gui::Connection : public Genode::Connection<Session>,
public Session_client
class Gui::Connection : private Genode::Connection<Session>
{
private:
Framebuffer::Session_client _framebuffer;
Input::Session_client _input;
size_t _session_quota = 0;
Env &_env;
Session_client _client { cap() };
Attached_dataspace _command_ds { _env.rm(), _client.command_dataspace() };
using Command_buffer = Gui::Session::Command_buffer;
Command_buffer &_command_buffer { *_command_ds.local_addr<Command_buffer>() };
Framebuffer::Session_client _framebuffer { _client.framebuffer_session() };
Input::Session_client _input { _env.rm(), _client.input_session() };
Ram_quota _ram_quota { }; /* session quota donated for virtual frame buffer */
public:
using View_handle = Session::View_handle;
using Genode::Connection<Session>::cap;
using Genode::Connection<Session>::upgrade;
using Genode::Connection<Session>::upgrade_ram;
using Genode::Connection<Session>::upgrade_caps;
/**
* Constructor
*/
Connection(Env &env, Label const &label = Label())
Connection(Env &env, Session_label const &label = { })
:
/* establish nitpicker session */
Genode::Connection<Session>(env, label, Ram_quota { 36*1024 }, Args()),
Session_client(env.rm(), cap()),
/* request frame-buffer and input sub sessions */
_framebuffer(framebuffer_session()),
_input(env.rm(), input_session())
_env(env)
{ }
void buffer(Framebuffer::Mode mode, bool use_alpha) override
{
size_t const needed = ram_quota(mode, use_alpha);
size_t const upgrade = needed > _session_quota
? needed - _session_quota
: 0;
if (upgrade > 0) {
this->upgrade_ram(upgrade);
_session_quota += upgrade;
}
Session_client::buffer(mode, use_alpha);
}
/**
* Return sub session for GUI's input service
*/
@ -70,6 +68,137 @@ class Gui::Connection : public Genode::Connection<Session>,
* Return sub session for session's frame buffer
*/
Framebuffer::Session *framebuffer() { return &_framebuffer; }
View_handle create_view()
{
View_handle result { };
for (bool retry = false; ; ) {
using Error = Session_client::Create_view_error;
_client.create_view().with_result(
[&] (View_handle handle) { result = handle; },
[&] (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;
}
return result;
}
View_handle create_child_view(View_handle parent)
{
View_handle result { };
for (bool retry = false; ; ) {
using Error = Session_client::Create_child_view_error;
_client.create_child_view(parent).with_result(
[&] (View_handle handle) { result = handle; },
[&] (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;
}
return result;
}
void destroy_view(View_handle view)
{
_client.destroy_view(view);
}
void release_view_handle(View_handle handle)
{
_client.release_view_handle(handle);
}
View_capability view_capability(View_handle handle)
{
return _client.view_capability(handle);
}
View_handle view_handle(View_capability view, View_handle handle = { })
{
View_handle result { };
for (bool retry = false; ; ) {
using Error = Session_client::View_handle_error;
_client.view_handle(view, handle).with_result(
[&] (View_handle handle) { result = handle; },
[&] (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;
}
return result;
}
void buffer(Framebuffer::Mode mode, bool use_alpha)
{
size_t const needed = Session_client::ram_quota(mode, use_alpha);
size_t const upgrade = needed > _ram_quota.value
? needed - _ram_quota.value : 0u;
if (upgrade > 0) {
this->upgrade_ram(upgrade);
_ram_quota.value += upgrade;
}
for (bool retry = false; ; ) {
using Result = Session_client::Buffer_result;
auto const result = _client.buffer(mode, use_alpha);
if (result == Result::OUT_OF_RAM) { upgrade_ram(8*1024); retry = true; }
if (result == Result::OUT_OF_CAPS) { upgrade_caps(2); retry = true; }
if (!retry)
break;
}
}
/**
* Enqueue command to command buffer
*
* The submitted command is not executed immediately. To execute a
* batch of enqueued commands, the 'execute' method must be called.
* Only in the corner case when there is not space left in the command
* buffer, the 'execute' is called to make room in the buffer.
*/
template <typename CMD>
void enqueue(auto &&... args) { enqueue(Session::Command( CMD { args... } )); }
void enqueue(Session::Command const &command)
{
if (_command_buffer.full())
execute();
_command_buffer.enqueue(command);
}
void execute()
{
_client.execute();
_command_buffer.reset();
}
/**
* 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); }
void focus(Capability<Session> focused) { _client.focus(focused); }
};
#endif /* _INCLUDE__GUI_SESSION__CONNECTION_H_ */

View File

@ -195,32 +195,36 @@ struct Gui::Session : Genode::Session
*/
virtual Input::Session_capability input_session() = 0;
enum class Create_view_error { OUT_OF_RAM, OUT_OF_CAPS };
using Create_view_result = Attempt<View_handle, Create_view_error>;
/**
* Create a new top-level view at the buffer
*
* \throw Invalid_handle
* \return handle for new view
*/
virtual View_handle create_view() = 0;
virtual Create_view_result create_view() = 0;
enum class Create_child_view_error { OUT_OF_RAM, OUT_OF_CAPS, INVALID };
using Create_child_view_result = Attempt<View_handle, Create_child_view_error>;
/**
* Create a new child view at the buffer
*
* \param parent parent view
*
* \throw Invalid_handle
* \param parent parent view
* \return handle for new view
*
* 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 View_handle create_child_view(View_handle parent) = 0;
virtual Create_child_view_result create_child_view(View_handle parent) = 0;
/**
* Destroy view
*/
virtual void destroy_view(View_handle) = 0;
enum class View_handle_error { OUT_OF_RAM, OUT_OF_CAPS };
using View_handle_result = Attempt<View_handle, View_handle_error>;
/**
* Return session-local handle for the specified view
*
@ -229,12 +233,9 @@ struct Gui::Session : Genode::Session
*
* \param handle designated view handle to be assigned to the imported
* view. By default, a new handle will be allocated.
*
* \throw Out_of_ram
* \throw Out_of_caps
*/
virtual View_handle view_handle(View_capability,
View_handle handle = View_handle()) = 0;
virtual View_handle_result view_handle(View_capability,
View_handle handle = View_handle()) = 0;
/**
* Request view capability for a given handle
@ -269,14 +270,12 @@ struct Gui::Session : Genode::Session
*/
virtual void mode_sigh(Signal_context_capability) = 0;
enum class Buffer_result { OK, OUT_OF_RAM, OUT_OF_CAPS };
/**
* Define dimensions of virtual framebuffer
*
* \throw Out_of_ram session quota does not suffice for specified
* buffer dimensions
* \throw Out_of_caps
*/
virtual void buffer(Framebuffer::Mode mode, bool use_alpha) = 0;
virtual Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) = 0;
/**
* Set focused session
@ -312,13 +311,10 @@ struct Gui::Session : Genode::Session
GENODE_RPC(Rpc_framebuffer_session, Framebuffer::Session_capability, framebuffer_session);
GENODE_RPC(Rpc_input_session, Input::Session_capability, input_session);
GENODE_RPC_THROW(Rpc_create_view, View_handle, create_view,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps));
GENODE_RPC_THROW(Rpc_create_child_view, View_handle, create_child_view,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps, Invalid_handle), View_handle);
GENODE_RPC(Rpc_create_view, Create_view_result, create_view);
GENODE_RPC(Rpc_create_child_view, Create_child_view_result, create_child_view, View_handle);
GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_handle);
GENODE_RPC_THROW(Rpc_view_handle, View_handle, view_handle,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), View_capability, View_handle);
GENODE_RPC(Rpc_view_handle, View_handle_result, view_handle, View_capability, View_handle);
GENODE_RPC(Rpc_view_capability, View_capability, view_capability, View_handle);
GENODE_RPC(Rpc_release_view_handle, void, release_view_handle, View_handle);
GENODE_RPC(Rpc_command_dataspace, Dataspace_capability, command_dataspace);
@ -327,8 +323,7 @@ struct Gui::Session : Genode::Session
GENODE_RPC(Rpc_mode, Framebuffer::Mode, mode);
GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Signal_context_capability);
GENODE_RPC(Rpc_focus, void, focus, Capability<Session>);
GENODE_RPC_THROW(Rpc_buffer, void, buffer, GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
Framebuffer::Mode, bool);
GENODE_RPC(Rpc_buffer, Buffer_result, buffer, Framebuffer::Mode, bool);
GENODE_RPC_INTERFACE(Rpc_framebuffer_session, Rpc_input_session,
Rpc_create_view, Rpc_create_child_view, Rpc_destroy_view,

View File

@ -241,18 +241,22 @@ void Gui_session::_adopt_new_view(View &view)
}
Gui_session::View_handle Gui_session::create_view()
Gui_session::Create_view_result Gui_session::create_view()
{
View &view = *new (_view_alloc)
View(*this, _texture, { .transparent = false, .background = false }, nullptr);
try {
View &view = *new (_view_alloc)
View(*this, _texture, { .transparent = false, .background = false }, nullptr);
_adopt_new_view(view);
_adopt_new_view(view);
return _view_handle_registry.alloc(view);
return _view_handle_registry.alloc(view);
}
catch (Out_of_ram) { return Create_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { return Create_view_error::OUT_OF_CAPS; }
}
Gui_session::View_handle Gui_session::create_child_view(View_handle const parent_handle)
Gui_session::Create_child_view_result Gui_session::create_child_view(View_handle const parent_handle)
{
View *parent_view_ptr = nullptr;
@ -264,16 +268,20 @@ Gui_session::View_handle Gui_session::create_child_view(View_handle const parent
catch (View_handle_registry::Lookup_failed) { }
if (!parent_view_ptr)
return View_handle();
return Create_child_view_error::INVALID;
View &view = *new (_view_alloc)
View(*this, _texture, { .transparent = false, .background = false }, parent_view_ptr);
try {
View &view = *new (_view_alloc)
View(*this, _texture, { .transparent = false, .background = false }, parent_view_ptr);
parent_view_ptr->add_child(view);
parent_view_ptr->add_child(view);
_adopt_new_view(view);
_adopt_new_view(view);
return _view_handle_registry.alloc(view);
return _view_handle_registry.alloc(view);
}
catch (Out_of_ram) { return Create_child_view_error::OUT_OF_RAM; }
catch (Out_of_caps) { return Create_child_view_error::OUT_OF_CAPS; }
}
@ -341,19 +349,17 @@ void Gui_session::destroy_view(View_handle handle)
}
Gui_session::View_handle
Gui_session::View_handle_result
Gui_session::view_handle(View_capability view_cap, View_handle handle)
{
auto lambda = [&] (View *view)
{
return (view) ? _view_handle_registry.alloc(*view, handle)
: View_handle();
};
try {
return _env.ep().rpc_ep().apply(view_cap, lambda);
return _env.ep().rpc_ep().apply(view_cap, [&] (View *view) {
return (view) ? _view_handle_registry.alloc(*view, handle)
: View_handle(); });
}
catch (View_handle_registry::Out_of_memory) { throw Out_of_ram(); }
catch (View_handle_registry::Out_of_memory) { return View_handle_error::OUT_OF_RAM; }
catch (Out_of_ram) { return View_handle_error::OUT_OF_RAM; }
catch (Out_of_caps) { return View_handle_error::OUT_OF_RAM; }
}
@ -404,17 +410,18 @@ Framebuffer::Mode Gui_session::mode()
}
void Gui_session::buffer(Framebuffer::Mode mode, bool use_alpha)
Gui_session::Buffer_result Gui_session::buffer(Framebuffer::Mode mode, bool use_alpha)
{
/* check if the session quota suffices for the specified mode */
if (_buffer_size + _ram_quota_guard().avail().value < ram_quota(mode, use_alpha))
throw Out_of_ram();
return Buffer_result::OUT_OF_RAM;
/* buffer re-allocation may consume new dataspace capability if buffer is new */
if (_cap_quota_guard().avail().value < 1)
throw Out_of_caps();
throw Buffer_result::OUT_OF_CAPS;
_framebuffer_session_component.notify_mode_change(mode, use_alpha);
return Buffer_result::OK;
}

View File

@ -348,13 +348,13 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
Input::Session_capability input_session() override {
return _input_session_cap; }
View_handle create_view() override;
Create_view_result create_view() override;
View_handle create_child_view(View_handle parent_handle) override;
Create_child_view_result create_child_view(View_handle parent_handle) override;
void destroy_view(View_handle handle) override;
View_handle view_handle(View_capability view_cap, View_handle handle) override;
View_handle_result view_handle(View_capability view_cap, View_handle handle) override;
View_capability view_capability(View_handle handle) override;
@ -368,7 +368,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
void mode_sigh(Signal_context_capability sigh) override { _mode_sigh = sigh; }
void buffer(Framebuffer::Mode mode, bool use_alpha) override;
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override;
void focus(Capability<Gui::Session> session_cap) override;