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: private:
Gui::Session_client &_gui; Gui::Connection &_gui;
Gui::Point _pos; Gui::Point _pos;
Gui::Area _size; Gui::Area _size;
Gui::Session::View_handle _handle; Gui::Session::View_handle _handle;
@ -362,7 +362,7 @@ class Log_view
public: public:
Log_view(Gui::Session_client &gui, Gui::Rect geometry) Log_view(Gui::Connection &gui, Gui::Rect geometry)
: :
_gui(gui), _gui(gui),
_pos(geometry.at), _pos(geometry.at),

View File

@ -183,23 +183,10 @@ struct Decorator::Main : Window_factory_base
*/ */
Window_base *create(Xml_node window_node) override Window_base *create(Xml_node window_node) override
{ {
for (;;) {
try {
return new (_heap) return new (_heap)
Window(window_node.attribute_value("id", 0U), Window(window_node.attribute_value("id", 0U),
_gui, _animator, _decorator_config); _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;
}
/** /**
* Window_factory_base interface * Window_factory_base interface

View File

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

View File

@ -57,7 +57,11 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
Input::Seq_number &_global_input_seq_number; 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() }; Input::Session_component _input_component { _env, _env.ram() };
@ -68,7 +72,7 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
void _handle_input() 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 * 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), _env(env), _event_handler(event_handler),
_global_input_seq_number(global_input_seq_number), _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); _env.ep().manage(_input_component);
_input_component.event_queue().enabled(true); _input_component.event_queue().enabled(true);
} }
@ -112,52 +116,46 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
} }
Framebuffer::Session_capability framebuffer_session() override { Framebuffer::Session_capability framebuffer_session() override {
return _connection.framebuffer_session(); } return _gui_session.framebuffer_session(); }
Input::Session_capability input_session() override { Input::Session_capability input_session() override {
return _input_component.cap(); } return _input_component.cap(); }
View_handle create_view() override { Create_view_result create_view() override {
return _connection.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 _connection.create_child_view(parent); } return _gui_session.create_child_view(parent); }
void destroy_view(View_handle view) override { 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 { View_handle_result view_handle(View_capability view_cap, View_handle handle) override {
return _connection.view_handle(view_cap, handle); } return _gui_session.view_handle(view_cap, handle); }
View_capability view_capability(View_handle view) override { 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 { void release_view_handle(View_handle view) override {
_connection.release_view_handle(view); } _gui_session.release_view_handle(view); }
Dataspace_capability command_dataspace() override { Dataspace_capability command_dataspace() override {
return _connection.command_dataspace(); } return _gui_session.command_dataspace(); }
void execute() override { void execute() override {
_connection.execute(); } _gui_session.execute(); }
Framebuffer::Mode mode() override { Framebuffer::Mode mode() override {
return _connection.mode(); } return _gui_session.mode(); }
void mode_sigh(Signal_context_capability sigh) override { 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 Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override {
{ return _gui_session.buffer(mode, use_alpha); }
/*
* Do not call 'Connection::buffer' to avoid paying session quota
* from our own budget.
*/
_connection.Session_client::buffer(mode, use_alpha);
}
void focus(Capability<Gui::Session> session) override { void focus(Capability<Gui::Session> session) override {
_connection.focus(session); } _gui_session.focus(session); }
}; };

View File

@ -170,22 +170,10 @@ struct Decorator::Main : Window_factory_base
*/ */
Window_base *create(Xml_node window_node) override Window_base *create(Xml_node window_node) override
{ {
for (;;) {
try {
return new (_heap) return new (_heap)
Window(_env, window_node.attribute_value("id", 0U), Window(_env, window_node.attribute_value("id", 0U),
_gui, _animator, _theme, _decorator_config); _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);
}
}
}
/** /**
* Window_factory_base interface * Window_factory_base interface

View File

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

View File

@ -336,7 +336,7 @@ struct Window_layouter::Main : Operations,
_env.ep(), *this, &Main::_handle_mode_change }; _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() }; 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; 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() }; Input::Session_component _input_component { _env, _env.ram() };
@ -70,7 +74,7 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
void _handle_input() 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 * 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...), Session_object(args...),
_env(env), _view(view), _env(env), _view(view),
_element(_view._gui_sessions, *this), _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); _env.ep().manage(_input_component);
_input_component.event_queue().enabled(true); _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 { Framebuffer::Session_capability framebuffer_session() override {
return _connection.framebuffer_session(); } return _gui_session.framebuffer_session(); }
Input::Session_capability input_session() override { Input::Session_capability input_session() override {
return _input_component.cap(); } return _input_component.cap(); }
View_handle create_view() override { Create_view_result create_view() override {
return _connection.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 _connection.create_child_view(parent); } return _gui_session.create_child_view(parent); }
void destroy_view(View_handle view) override { 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 { View_handle_result view_handle(View_capability view_cap, View_handle handle) override {
return _connection.view_handle(view_cap, handle); } return _gui_session.view_handle(view_cap, handle); }
View_capability view_capability(View_handle view) override { 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 { void release_view_handle(View_handle view) override {
_connection.release_view_handle(view); } _gui_session.release_view_handle(view); }
Dataspace_capability command_dataspace() override { Dataspace_capability command_dataspace() override {
return _connection.command_dataspace(); } return _gui_session.command_dataspace(); }
void execute() override { void execute() override {
_connection.execute(); } _gui_session.execute(); }
Framebuffer::Mode mode() override { Framebuffer::Mode mode() override {
return _connection.mode(); } return _gui_session.mode(); }
void mode_sigh(Signal_context_capability sigh) override { 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 Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override {
{ return _gui_session.buffer(mode, use_alpha); }
/*
* Do not call 'Connection::buffer' to avoid paying session quota
* from our own budget.
*/
_connection.Session_client::buffer(mode, use_alpha);
}
void focus(Capability<Gui::Session> session) override { 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 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(); _view_handle = _gui.create_view();
_update_view_visibility(); _update_view_visibility();
return _view_handle; 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); _view_handle = _gui.create_child_view(parent);
_update_view_visibility(); _update_view_visibility();
@ -364,7 +364,7 @@ class Gui_fader::Gui_session_component
return _gui.destroy_view(handle); return _gui.destroy_view(handle);
} }
View_handle view_handle(View_capability view_cap, View_handle_result view_handle(View_capability view_cap,
View_handle handle) override View_handle handle) override
{ {
return _gui.view_handle(view_cap, handle); return _gui.view_handle(view_cap, handle);
@ -420,7 +420,7 @@ class Gui_fader::Gui_session_component
_gui.mode_sigh(sigh); _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; Area const size = mode.area;
@ -429,6 +429,7 @@ class Gui_fader::Gui_session_component
_gui.buffer(mode, true); _gui.buffer(mode, true);
_fb_session.dst_buffer(_gui.framebuffer()->dataspace(), size); _fb_session.dst_buffer(_gui.framebuffer()->dataspace(), size);
return Buffer_result::OK;
} }
void focus(Genode::Capability<Session> focused) override void focus(Genode::Capability<Session> focused) override

View File

@ -16,8 +16,6 @@
/* Genode includes */ /* Genode includes */
#include <util/string.h> #include <util/string.h>
#include <base/attached_dataspace.h>
#include <gui_session/connection.h>
#include <input_session/client.h> #include <input_session/client.h>
#include <input/event.h> #include <input/event.h>
#include <input/component.h> #include <input/component.h>
@ -25,6 +23,7 @@
/* local includes */ /* local includes */
#include <window_registry.h> #include <window_registry.h>
#include <pointer.h> #include <pointer.h>
#include <real_gui.h>
namespace Wm { class Main; namespace Wm { class Main;
using Genode::size_t; using Genode::size_t;
@ -166,13 +165,15 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
Genode::Ram_allocator &_ram; 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 { }; 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; Pointer::State _pointer_state;
@ -212,7 +213,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
_content_callback(content_callback), _content_callback(content_callback),
_md_alloc(md_alloc) _md_alloc(md_alloc)
{ {
_gui_session.input()->sigh(_input_handler); _input_session.sigh(_input_handler);
} }
~Decorator_gui_session() ~Decorator_gui_session()
@ -222,8 +223,8 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
void _handle_input() void _handle_input()
{ {
while (_gui_session.input()->pending()) while (_input_session.pending())
_gui_session.input()->for_each_event([&] (Input::Event const &ev) { _input_session.for_each_event([&] (Input::Event const &ev) {
_pointer_state.apply_event(ev); _pointer_state.apply_event(ev);
_window_layouter_input.submit(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); View_capability view_cap = _content_callback.content_view(win_id);
_gui_session.destroy_view(view_handle); _gui.session.destroy_view(view_handle);
_gui_session.view_handle(view_cap, view_handle); _gui.session.view_handle(view_cap, view_handle);
_gui_session.enqueue(cmd); _gui.enqueue(cmd);
_gui_session.execute(); _gui.execute();
/* /*
* Now that the physical content view exists, it is time * 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) { } catch (Decorator_content_registry::Lookup_failed) {
_gui_session.enqueue(cmd); _gui.enqueue(cmd);
} }
return; return;
@ -302,7 +303,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
catch (Decorator_content_registry::Lookup_failed) { } catch (Decorator_content_registry::Lookup_failed) { }
/* forward command */ /* forward command */
_gui_session.enqueue(cmd); _gui.enqueue(cmd);
return; return;
case Command::OP_OFFSET: case Command::OP_OFFSET:
@ -316,21 +317,21 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
_content_registry.lookup(cmd.geometry.view); _content_registry.lookup(cmd.geometry.view);
} }
catch (Decorator_content_registry::Lookup_failed) { catch (Decorator_content_registry::Lookup_failed) {
_gui_session.enqueue(cmd); _gui.enqueue(cmd);
} }
return; return;
case Command::OP_BACKGROUND: case Command::OP_BACKGROUND:
case Command::OP_NOP: case Command::OP_NOP:
_gui_session.enqueue(cmd); _gui.enqueue(cmd);
return; return;
} }
} }
void upgrade(const char *args) 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 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 Framebuffer::Session_capability framebuffer_session() override
{ {
return _gui_session.framebuffer_session(); return _gui.session.framebuffer_session();
} }
Input::Session_capability input_session() override 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; 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 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)) { if (_content_registry.registered(view)) {
Gui::Rect rect(Gui::Point(0, 0), Gui::Area(0, 0)); Gui::Rect rect(Gui::Point(0, 0), Gui::Area(0, 0));
_gui_session.enqueue<Gui::Session::Command::Geometry>(view, rect); _gui.enqueue<Gui::Session::Command::Geometry>(view, rect);
_gui_session.execute(); _gui.execute();
Window_registry::Id win_id = _content_registry.lookup(view); Window_registry::Id win_id = _content_registry.lookup(view);
_content_callback.hide_content_child_views(win_id); _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 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 void release_view_handle(View_handle view) override
{ {
/* XXX dealloc View_ptr */ /* XXX dealloc View_ptr */
_gui_session.release_view_handle(view); _gui.session.release_view_handle(view);
} }
Genode::Dataspace_capability command_dataspace() override Genode::Dataspace_capability command_dataspace() override
{ {
return _command_ds.cap(); return _client_command_ds.cap();
} }
void execute() override void execute() override
{ {
for (unsigned i = 0; i < _command_buffer.num(); i++) { for (unsigned i = 0; i < _client_command_buffer.num(); i++) {
try { try {
_execute_command(_command_buffer.get(i)); _execute_command(_client_command_buffer.get(i));
} }
catch (...) { catch (...) {
Genode::warning("unhandled exception while processing command from decorator"); Genode::warning("unhandled exception while processing command from decorator");
} }
} }
_gui_session.execute(); _gui.execute();
} }
Framebuffer::Mode mode() override Framebuffer::Mode mode() override
{ {
return _gui_session.mode(); return _gui.session.mode();
} }
void mode_sigh(Genode::Signal_context_capability sigh) override 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. * transitive delegations of the capability.
*/ */
_mode_sigh = sigh; _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
{ {
/* return _gui.session.buffer(mode, use_alpha);
* See comment in 'Wm::Gui::Session_component::buffer'.
*/
Gui::Session_client(_env.rm(), _gui_session.cap()).buffer(mode, use_alpha);
} }
void focus(Genode::Capability<Gui::Session>) override { } 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: private:
Genode::Session_label _session_label; Genode::Env &_env;
Gui::Connection _session;
Genode::Session_label _label;
Genode::Connection<Gui::Session> _connection {
_env, _label, Genode::Ram_quota { 36*1024 }, /* Args */ { } };
Gui::Session_client _session { _connection.cap() };
public: public:
/** /**
* Constructor * 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), _env(env), _label(label)
_session(env, _session_label.string())
{ } { }
void upgrade(char const *args) void upgrade(char const *args)
{ {
size_t const ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0); 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(); return _session.input_session();
} }
View_handle create_view() override Create_view_result create_view() override
{ {
return _session.create_view(); 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); 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); _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); 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); _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 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; using View_handle = Gui::Session::View_handle;
Session_label _session_label; Session_label _session_label;
Gui::Session_client &_real_gui; Real_gui &_real_gui;
View_handle _real_handle { }; View_handle _real_handle { };
Title _title { }; Title _title { };
Rect _geometry { }; Rect _geometry { };
@ -125,7 +125,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
bool _neighbor_behind { }; bool _neighbor_behind { };
bool _has_alpha; bool _has_alpha;
View(Gui::Session_client &real_gui, View(Real_gui &real_gui,
Session_label const &session_label, Session_label const &session_label,
bool has_alpha) bool has_alpha)
: :
@ -153,7 +153,10 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
View_handle real_neighbor_handle; View_handle real_neighbor_handle;
if (neighbor.valid()) 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) if (_neighbor_behind)
_real_gui.enqueue<Command::To_front>(_real_handle, real_neighbor_handle); _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(); _real_gui.execute();
if (real_neighbor_handle.valid()) 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() void _apply_view_config()
@ -177,7 +180,7 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
~View() ~View()
{ {
if (_real_handle.valid()) if (_real_handle.valid())
_real_gui.destroy_view(_real_handle); _real_gui.session.destroy_view(_real_handle);
} }
using Genode::Weak_object<View>::weak_ptr; 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() 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) void buffer_offset(Point buffer_offset)
@ -256,22 +259,22 @@ class Wm::Gui::Top_level_view : public View, private List<Top_level_view>::Eleme
bool _resizeable = false; bool _resizeable = false;
Title _window_title { }; Title _window_title { };
Session_label _session_label;
Session_label const _session_label;
using Command = Gui::Session::Command; using Command = Gui::Session::Command;
public: public:
Top_level_view(Gui::Session_client &real_gui, Top_level_view(Real_gui &real_gui,
Session_label const &session_label,
bool has_alpha, bool has_alpha,
Window_registry &window_registry, Window_registry &window_registry,
Input_origin_changed_handler &input_origin_changed_handler) 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), _window_registry(window_registry),
_input_origin_changed_handler(input_origin_changed_handler), _input_origin_changed_handler(input_origin_changed_handler),
_session_label(session_label) _session_label(real_gui.label)
{ } { }
~Top_level_view() ~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. * 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::Offset>(_real_handle, _buffer_offset);
_real_gui.enqueue<Command::Title> (_real_handle, _title.string()); _real_gui.enqueue<Command::Title> (_real_handle, _title.string());
_real_gui.execute(); _real_gui.execute();
} },
[&] (Gui::Session::Create_view_error) { }
);
return _real_gui.view_capability(_real_handle); if (!_real_handle.valid()) {
warning("failed to created content view for ", _title);
return { };
}
}
return _real_gui.session.view_capability(_real_handle);
} }
void hidden(bool hidden) { _window_registry.hidden(_win_id, hidden); } 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: public:
Child_view(Gui::Session_client &real_gui, Child_view(Real_gui &real_gui,
Session_label const &session_label,
bool has_alpha, bool has_alpha,
Weak_ptr<View> parent) 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(); try_to_init_real_view();
} }
@ -433,13 +443,26 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
if (!parent.valid()) if (!parent.valid())
return; return;
View_handle parent_handle = _real_gui.view_handle(parent->real_view_cap()); View_handle parent_handle { };
if (!parent_handle.valid()) _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; 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) if (_neighbor_ptr == _parent)
_unsynchronized_apply_view_config(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()) if (!_real_handle.valid())
return; return;
_real_gui.destroy_view(_real_handle); _real_gui.session.destroy_view(_real_handle);
_real_handle = { }; _real_handle = { };
} }
}; };
@ -477,8 +500,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
Session_label _session_label; Session_label _session_label;
Genode::Ram_allocator &_ram; Genode::Ram_allocator &_ram;
Gui::Connection _session { _env, _session_label.string() }; Real_gui _real_gui { _env, _session_label };
Window_registry &_window_registry; Window_registry &_window_registry;
Tslab<Top_level_view, 8000> _top_level_view_alloc; Tslab<Top_level_view, 8000> _top_level_view_alloc;
Tslab<Child_view, 6000> _child_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
*/ */
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() }; Attached_dataspace _gui_input_ds { _env.rm(), _gui_input.dataspace() };
Signal_handler<Session_component> _input_handler { Signal_handler<Session_component> _input_handler {
@ -661,7 +683,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
View &_create_view_object() View &_create_view_object()
{ {
Top_level_view *view = new (_top_level_view_alloc) 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); _window_registry, *this);
view->resizeable(_mode_sigh.valid()); 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); Weak_ptr<View> parent_ptr = _view_handle_registry.lookup(parent_handle);
Child_view *view = new (_child_view_alloc) 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); _child_views.insert(view);
return *view; return *view;
@ -803,7 +825,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
_view_handle_registry(session_alloc) _view_handle_registry(session_alloc)
{ {
_gui_input.sigh(_input_handler); _gui_input.sigh(_input_handler);
_session.mode_sigh(_mode_handler); _real_gui.session.mode_sigh(_mode_handler);
_input_session.event_queue().enabled(true); _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) 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() 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 * 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 Framebuffer::Session_capability framebuffer_session() override
{ {
return _session.framebuffer_session(); return _real_gui.session.framebuffer_session();
} }
Input::Session_capability input_session() override Input::Session_capability input_session() override
@ -931,20 +953,26 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
return _input_session_cap; return _input_session_cap;
} }
View_handle create_view() override Create_view_result create_view() override
{ {
try {
View &view = _create_view_object(); View &view = _create_view_object();
_env.ep().manage(view); _env.ep().manage(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; }
}
View_handle create_child_view(View_handle parent) override Create_child_view_result create_child_view(View_handle parent) override
{ {
try { try {
View &view = _create_child_view_object(parent); View &view = _create_child_view_object(parent);
_env.ep().manage(view); _env.ep().manage(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; }
catch (View_handle_registry::Lookup_failed) { catch (View_handle_registry::Lookup_failed) {
return View_handle(); } return View_handle(); }
} }
@ -972,12 +1000,16 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
} catch (View_handle_registry::Lookup_failed) { } } 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
{ {
try {
return _env.ep().rpc_ep().apply(view_cap, [&] (View *view) { return _env.ep().rpc_ep().apply(view_cap, [&] (View *view) {
return (view) ? _view_handle_registry.alloc(*view, handle) return (view) ? _view_handle_registry.alloc(*view, handle)
: 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 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 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 * 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); 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 * 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 * wrapped GUI session. Otherwise, we would perform session
* upgrades initiated by the wm client's buffer operation twice. * 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; _has_alpha = has_alpha;
return _real_gui.session.buffer(mode, has_alpha);
} }
void focus(Genode::Capability<Gui::Session>) override { } 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 used to perform session-control operations
*/ */
Gui::Session &_focus_gui_session; Gui::Connection &_focus_gui_session;
public: 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, Window_registry &window_registry, Allocator &md_alloc,
Genode::Ram_allocator &ram, Genode::Ram_allocator &ram,
Pointer::Tracker &pointer_tracker, Reporter &focus_request_reporter, Pointer::Tracker &pointer_tracker, Reporter &focus_request_reporter,
Gui::Session &focus_gui_session) Gui::Connection &focus_gui_session)
: :
_env(env), _env(env),
_md_alloc(md_alloc), _ram(ram), _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; 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 { } 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(); return View_handle();
} }
@ -100,7 +100,7 @@ struct Wm::Layouter_gui_session : Genode::Rpc_object<Gui::Session>
_mode_sigh_gui.mode_sigh(sigh); _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 { } 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 <QtWidgets>
#include <gui_session/client.h> #include <gui_session/connection.h>
class QEmbeddedViewWidget : public QWidget class QEmbeddedViewWidget : public QWidget
@ -66,7 +66,7 @@ class QGenodeViewWidget : public QEmbeddedViewWidget
protected: protected:
Gui::Session_client *gui; Gui::Connection *gui;
Gui::Session::View_handle view_handle; Gui::Session::View_handle view_handle;
virtual void showEvent(QShowEvent *event); virtual void showEvent(QShowEvent *event);
@ -78,7 +78,7 @@ public:
QGenodeViewWidget(QWidget *parent =0); QGenodeViewWidget(QWidget *parent =0);
~QGenodeViewWidget(); ~QGenodeViewWidget();
void setGenodeView(Gui::Session_client *gui, void setGenodeView(Gui::Connection *gui,
Gui::Session::View_handle view_handle, Gui::Session::View_handle view_handle,
int buf_x, int buf_y, int w, int h); int buf_x, int buf_y, int w, int h);
}; };

View File

@ -2,7 +2,7 @@ _ZN17QGenodeViewWidget10paintEventEP11QPaintEvent T
_ZN17QGenodeViewWidget11qt_metacallEN11QMetaObject4CallEiPPv T _ZN17QGenodeViewWidget11qt_metacallEN11QMetaObject4CallEiPPv T
_ZN17QGenodeViewWidget11qt_metacastEPKc T _ZN17QGenodeViewWidget11qt_metacastEPKc T
_ZN17QGenodeViewWidget12focusInEventEP11QFocusEvent T _ZN17QGenodeViewWidget12focusInEventEP11QFocusEvent T
_ZN17QGenodeViewWidget13setGenodeViewEPN3Gui14Session_clientEN6Genode6HandleINS0_4ViewEEEiiii T _ZN17QGenodeViewWidget13setGenodeViewEPN3Gui10ConnectionEN6Genode6HandleINS0_4ViewEEEiiii T
_ZN17QGenodeViewWidget16staticMetaObjectE D 48 _ZN17QGenodeViewWidget16staticMetaObjectE D 48
_ZN17QGenodeViewWidget9hideEventEP10QHideEvent T _ZN17QGenodeViewWidget9hideEventEP10QHideEvent T
_ZN17QGenodeViewWidget9showEventEP10QShowEvent 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, Gui::Session::View_handle new_view_handle,
int buf_x, int buf_y, int w, int h) int buf_x, int buf_y, int w, int h)
{ {
@ -236,5 +236,5 @@ void QGenodeViewWidget::focusInEvent(QFocusEvent *)
QGenodePlatformWindow *platform_window = QGenodePlatformWindow *platform_window =
dynamic_cast<QGenodePlatformWindow*>(window()->windowHandle()->handle()); 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; } 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 * Constructor
*/ */
Session_client(Region_map &rm, Session_capability session) Session_client(Session_capability session) : Rpc_client<Session>(session) { }
:
Rpc_client<Session>(session),
_command_ds(rm, command_dataspace()),
_command_buffer(*_command_ds.local_addr<Command_buffer>())
{ }
Framebuffer::Session_capability framebuffer_session() override { Framebuffer::Session_capability framebuffer_session() override {
return call<Rpc_framebuffer_session>(); } return call<Rpc_framebuffer_session>(); }
@ -47,16 +34,16 @@ class Gui::Session_client : public Rpc_client<Session>
Input::Session_capability input_session() override { Input::Session_capability input_session() override {
return call<Rpc_input_session>(); } return call<Rpc_input_session>(); }
View_handle create_view() override { Create_view_result create_view() override {
return call<Rpc_create_view>(); } 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); } return call<Rpc_create_child_view>(parent); }
void destroy_view(View_handle view) override { void destroy_view(View_handle view) override {
call<Rpc_destroy_view>(view); } call<Rpc_destroy_view>(view); }
View_handle view_handle(View_capability view, View_handle_result view_handle(View_capability view,
View_handle handle = View_handle()) override View_handle handle = View_handle()) override
{ {
return call<Rpc_view_handle>(view, handle); return call<Rpc_view_handle>(view, handle);
@ -71,11 +58,7 @@ class Gui::Session_client : public Rpc_client<Session>
Dataspace_capability command_dataspace() override { Dataspace_capability command_dataspace() override {
return call<Rpc_command_dataspace>(); } return call<Rpc_command_dataspace>(); }
void execute() override void execute() override { call<Rpc_execute>(); }
{
call<Rpc_execute>();
_command_buffer.reset();
}
Framebuffer::Mode mode() override { Framebuffer::Mode mode() override {
return call<Rpc_mode>(); } return call<Rpc_mode>(); }
@ -83,30 +66,12 @@ class Gui::Session_client : public Rpc_client<Session>
void mode_sigh(Signal_context_capability sigh) override { void mode_sigh(Signal_context_capability sigh) override {
call<Rpc_mode_sigh>(sigh); } call<Rpc_mode_sigh>(sigh); }
void buffer(Framebuffer::Mode mode, bool alpha) override { Buffer_result buffer(Framebuffer::Mode mode, bool alpha) override {
call<Rpc_buffer>(mode, alpha); } return call<Rpc_buffer>(mode, alpha); }
void focus(Gui::Session_capability session) override { void focus(Gui::Session_capability session) override {
call<Rpc_focus>(session); } 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_ */ #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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -22,45 +22,43 @@
namespace Gui { class Connection; } namespace Gui { class Connection; }
class Gui::Connection : public Genode::Connection<Session>, class Gui::Connection : private Genode::Connection<Session>
public Session_client
{ {
private: private:
Framebuffer::Session_client _framebuffer; Env &_env;
Input::Session_client _input;
size_t _session_quota = 0; 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: 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 * 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()), Genode::Connection<Session>(env, label, Ram_quota { 36*1024 }, Args()),
Session_client(env.rm(), cap()), _env(env)
/* request frame-buffer and input sub sessions */
_framebuffer(framebuffer_session()),
_input(env.rm(), input_session())
{ } { }
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 * 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 * Return sub session for session's frame buffer
*/ */
Framebuffer::Session *framebuffer() { return &_framebuffer; } 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_ */ #endif /* _INCLUDE__GUI_SESSION__CONNECTION_H_ */

View File

@ -195,32 +195,36 @@ struct Gui::Session : Genode::Session
*/ */
virtual Input::Session_capability input_session() = 0; 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 * 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 * Create a new child view at the buffer
* *
* \param parent parent view * \param parent parent view
*
* \throw Invalid_handle
* \return handle for new view * \return handle for new view
* *
* The 'parent' argument allows the client to use the location of an * The 'parent' argument allows the client to use the location of an
* existing view as the coordinate origin for the to-be-created view. * 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 * Destroy view
*/ */
virtual void destroy_view(View_handle) = 0; 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 * Return session-local handle for the specified view
* *
@ -229,11 +233,8 @@ struct Gui::Session : Genode::Session
* *
* \param handle designated view handle to be assigned to the imported * \param handle designated view handle to be assigned to the imported
* view. By default, a new handle will be allocated. * view. By default, a new handle will be allocated.
*
* \throw Out_of_ram
* \throw Out_of_caps
*/ */
virtual View_handle view_handle(View_capability, virtual View_handle_result view_handle(View_capability,
View_handle handle = View_handle()) = 0; View_handle handle = View_handle()) = 0;
/** /**
@ -269,14 +270,12 @@ struct Gui::Session : Genode::Session
*/ */
virtual void mode_sigh(Signal_context_capability) = 0; virtual void mode_sigh(Signal_context_capability) = 0;
enum class Buffer_result { OK, OUT_OF_RAM, OUT_OF_CAPS };
/** /**
* Define dimensions of virtual framebuffer * 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 * 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_framebuffer_session, Framebuffer::Session_capability, framebuffer_session);
GENODE_RPC(Rpc_input_session, Input::Session_capability, input_session); GENODE_RPC(Rpc_input_session, Input::Session_capability, input_session);
GENODE_RPC_THROW(Rpc_create_view, View_handle, create_view, GENODE_RPC(Rpc_create_view, Create_view_result, create_view);
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps)); GENODE_RPC(Rpc_create_child_view, Create_child_view_result, create_child_view, View_handle);
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_destroy_view, void, destroy_view, View_handle); GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_handle);
GENODE_RPC_THROW(Rpc_view_handle, View_handle, view_handle, GENODE_RPC(Rpc_view_handle, View_handle_result, view_handle, View_capability, View_handle);
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), View_capability, View_handle);
GENODE_RPC(Rpc_view_capability, View_capability, 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_release_view_handle, void, release_view_handle, View_handle);
GENODE_RPC(Rpc_command_dataspace, Dataspace_capability, command_dataspace); 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, Framebuffer::Mode, mode);
GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Signal_context_capability); GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Signal_context_capability);
GENODE_RPC(Rpc_focus, void, focus, Capability<Session>); GENODE_RPC(Rpc_focus, void, focus, Capability<Session>);
GENODE_RPC_THROW(Rpc_buffer, void, buffer, GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), GENODE_RPC(Rpc_buffer, Buffer_result, buffer, Framebuffer::Mode, bool);
Framebuffer::Mode, bool);
GENODE_RPC_INTERFACE(Rpc_framebuffer_session, Rpc_input_session, GENODE_RPC_INTERFACE(Rpc_framebuffer_session, Rpc_input_session,
Rpc_create_view, Rpc_create_child_view, Rpc_destroy_view, Rpc_create_view, Rpc_create_child_view, Rpc_destroy_view,

View File

@ -241,8 +241,9 @@ 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()
{ {
try {
View &view = *new (_view_alloc) View &view = *new (_view_alloc)
View(*this, _texture, { .transparent = false, .background = false }, nullptr); View(*this, _texture, { .transparent = false, .background = false }, nullptr);
@ -250,9 +251,12 @@ Gui_session::View_handle Gui_session::create_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; View *parent_view_ptr = nullptr;
@ -264,8 +268,9 @@ Gui_session::View_handle Gui_session::create_child_view(View_handle const parent
catch (View_handle_registry::Lookup_failed) { } catch (View_handle_registry::Lookup_failed) { }
if (!parent_view_ptr) if (!parent_view_ptr)
return View_handle(); return Create_child_view_error::INVALID;
try {
View &view = *new (_view_alloc) View &view = *new (_view_alloc)
View(*this, _texture, { .transparent = false, .background = false }, parent_view_ptr); View(*this, _texture, { .transparent = false, .background = false }, parent_view_ptr);
@ -275,6 +280,9 @@ Gui_session::View_handle Gui_session::create_child_view(View_handle const parent
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; }
}
void Gui_session::apply_session_policy(Xml_node config, void Gui_session::apply_session_policy(Xml_node config,
@ -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) 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 { 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 */ /* check if the session quota suffices for the specified mode */
if (_buffer_size + _ram_quota_guard().avail().value < ram_quota(mode, use_alpha)) 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 */ /* buffer re-allocation may consume new dataspace capability if buffer is new */
if (_cap_quota_guard().avail().value < 1) 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); _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 { Input::Session_capability input_session() override {
return _input_session_cap; } 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; 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; 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 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; void focus(Capability<Gui::Session> session_cap) override;