gui_session: distinguish view-stacking operations

This patch eliminates the use of invalid view handles as special
Session::Command arguments. The TO_FRONT and TO_BACK operations
interpreted as invalid neighbor as top-most or back-most position.
Those corner cases are now expressed via dedicated commands. The
new stacking commands are FRONT, BACK, FRONT_OF, and BEHIND_OF.

While changing the command interface, the patch removes the OP_
prefix from the opcode values.

Issue #5242
This commit is contained in:
Norman Feske 2024-08-06 15:05:10 +02:00 committed by Christian Helmuth
parent b0803eabdb
commit f274ed549e
29 changed files with 131 additions and 158 deletions

View File

@ -163,9 +163,7 @@ class Scout::Graphics_backend_impl : public Graphics_backend
void bring_to_front() override
{
using Command = Gui::Session::Command;
using View_handle = Gui::Session::View_handle;
_gui.enqueue<Command::To_front>(_view, View_handle());
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.execute();
}

View File

@ -375,7 +375,7 @@ class Log_view
void top()
{
_gui.enqueue<Command::To_front>(_handle, View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.execute();
}

View File

@ -279,11 +279,9 @@ class Nano3d::Scene
:
_env(env), _pos(pos), _size(size)
{
using View_handle = Gui::Session::View_handle;
Gui::Rect rect(_pos, _size);
_gui.enqueue<Command::Geometry>(_view_handle, rect);
_gui.enqueue<Command::To_front>(_view_handle, View_handle());
_gui.enqueue<Command::Front>(_view_handle);
_gui.execute();
_gui.input.sigh(_input_handler);

View File

@ -115,13 +115,12 @@ struct Backdrop::Main
void _update_view()
{
/* display view behind all others */
using Command = Gui::Session::Command;
using View_handle = Gui::Session::View_handle;
using Command = Gui::Session::Command;
_gui.enqueue<Command::Background>(_view_handle);
Gui::Rect rect(Gui::Point(), _buffer->size());
_gui.enqueue<Command::Geometry>(_view_handle, rect);
_gui.enqueue<Command::To_back>(_view_handle, View_handle());
_gui.enqueue<Command::Back>(_view_handle);
_gui.execute();
}

View File

@ -67,13 +67,12 @@ class Decorator::Window : public Window_base
void stack(View_handle neighbor)
{
_gui.enqueue<Command::To_front>(_handle, neighbor);
_gui.enqueue<Command::Front_of>(_handle, neighbor);
}
void stack_back_most()
{
_gui.enqueue<Command::To_back>(_handle, View_handle());
}
void stack_front_most() { _gui.enqueue<Command::Front>(_handle); }
void stack_back_most() { _gui.enqueue<Command::Back>(_handle); }
void place(Rect rect)
{
@ -445,7 +444,7 @@ class Decorator::Window : public Window_base
void stack_front_most() override
{
_content_view.stack(View_handle());
_content_view.stack_front_most();
_stack_decoration_views();
}

View File

@ -107,12 +107,11 @@ struct Menu_view::Dialog : List_model<Dialog>::Element
&& _view_geometry.area == geometry.area)
return;
using Command = Gui::Session::Command;
using View_handle = Gui::Session::View_handle;
using Command = Gui::Session::Command;
_view_geometry = geometry;
_gui.enqueue<Command::Geometry>(_view_handle, _view_geometry);
_gui.enqueue<Command::To_front>(_view_handle, View_handle());
_gui.enqueue<Command::Front>(_view_handle);
_gui.execute();
}

View File

@ -59,7 +59,7 @@ struct Osci::Main
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_handle, Rect(position, size));
_gui.enqueue<Command::To_front>(_handle, Gui::Session::View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.execute();
}

View File

@ -96,7 +96,7 @@ struct Osci::Main
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_handle, Rect(position, size));
_gui.enqueue<Command::To_front>(_handle, Gui::Session::View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.execute();
}

View File

@ -62,7 +62,7 @@ struct Screenshot_trigger::Main
{
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_handle, Rect(position, size));
_gui.enqueue<Command::To_front>(_handle, Gui::Session::View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.execute();
}

View File

@ -199,13 +199,12 @@ class Decorator::Window : public Window_base, public Animator::Item
void stack(View_handle neighbor)
{
_gui.enqueue<Command::To_front>(_handle, neighbor);
_gui.enqueue<Command::Front_of>(_handle, neighbor);
}
void stack_back_most()
{
_gui.enqueue<Command::To_back>(_handle, View_handle());
}
void stack_front_most() { _gui.enqueue<Command::Front>(_handle); }
void stack_back_most() { _gui.enqueue<Command::Back>(_handle); }
void place(Rect rect, Point offset)
{
@ -390,7 +389,7 @@ class Decorator::Window : public Window_base, public Animator::Item
}
void stack_front_most() override
{
_content_view.stack(View_handle());
_content_view.stack_front_most();
_stack_decoration_views();
}

View File

@ -393,7 +393,7 @@ class Gui_fader::Gui_session_component
bool forward_command = true;
if (command.opcode == Gui::Session::Command::OP_GEOMETRY) {
if (command.opcode == Gui::Session::Command::GEOMETRY) {
/* remember view geometry as defined by the client */
_view_geometry = command.geometry.rect;

View File

@ -163,7 +163,7 @@ struct Terminal::Main : Character_consumer
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_view, Rect(Point(0, 0), _fb_mode.area));
_gui.enqueue<Command::To_front>(_view, Gui::Session::View_handle());
_gui.enqueue<Command::Front>(_view);
_gui.execute();
_flushed_fb_mode = _fb_mode;

View File

@ -233,7 +233,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
{
switch (cmd.opcode) {
case Command::OP_TITLE:
case Command::TITLE:
{
unsigned id = 0;
Genode::ascii_to(cmd.title.title.string(), id);
@ -244,14 +244,15 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
return;
}
case Command::OP_TO_FRONT:
case Command::OP_TO_BACK:
case Command::FRONT:
case Command::BACK:
case Command::FRONT_OF:
case Command::BEHIND_OF:
try {
View_handle const view_handle = (cmd.opcode == Command::OP_TO_FRONT)
? cmd.to_front.view
: cmd.to_back.view;
/* the first argument is the same for all stacking operations */
View_handle const view_handle = cmd.front.view;
/*
* If the content view is re-stacked, replace it by the real
@ -287,7 +288,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
return;
case Command::OP_GEOMETRY:
case Command::GEOMETRY:
try {
@ -306,7 +307,7 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
_gui.enqueue(cmd);
return;
case Command::OP_OFFSET:
case Command::OFFSET:
try {
@ -321,8 +322,8 @@ struct Wm::Decorator_gui_session : Genode::Rpc_object<Gui::Session>,
}
return;
case Command::OP_BACKGROUND:
case Command::OP_NOP:
case Command::BACKGROUND:
case Command::NOP:
_gui.enqueue(cmd);
return;

View File

@ -158,10 +158,17 @@ class Wm::Gui::View : private Genode::Weak_object<View>,
[&] (auto) { warning("unable to obtain real_neighbor_handle"); }
);
if (_neighbor_behind)
_real_gui.enqueue<Command::To_front>(_real_handle, real_neighbor_handle);
else
_real_gui.enqueue<Command::To_back>(_real_handle, real_neighbor_handle);
if (real_neighbor_handle.valid()) {
if (_neighbor_behind)
_real_gui.enqueue<Command::Front_of>(_real_handle, real_neighbor_handle);
else
_real_gui.enqueue<Command::Behind_of>(_real_handle, real_neighbor_handle);
} else {
if (_neighbor_behind)
_real_gui.enqueue<Command::Front>(_real_handle);
else
_real_gui.enqueue<Command::Back>(_real_handle);
}
_real_gui.execute();
@ -730,7 +737,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
{
switch (command.opcode) {
case Command::OP_GEOMETRY:
case Command::GEOMETRY:
{
Locked_ptr<View> view(_view_handle_registry.lookup(command.geometry.view));
if (view.valid())
@ -738,7 +745,7 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
return;
}
case Command::OP_OFFSET:
case Command::OFFSET:
{
Locked_ptr<View> view(_view_handle_registry.lookup(command.offset.view));
if (view.valid())
@ -747,35 +754,30 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
return;
}
case Command::OP_TO_FRONT:
case Command::FRONT:
{
Locked_ptr<View> view(_view_handle_registry.lookup(command.to_front.view));
Locked_ptr<View> view(_view_handle_registry.lookup(command.front.view));
if (view.valid())
view->stack(Weak_ptr<View>(), true);
return;
}
case Command::FRONT_OF:
{
Locked_ptr<View> view(_view_handle_registry.lookup(command.front_of.view));
if (!view.valid())
return;
/* bring to front if no neighbor is specified */
if (!command.to_front.neighbor.valid()) {
view->stack(Weak_ptr<View>(), true);
if (!command.front_of.neighbor.valid())
return;
}
/* stack view relative to neighbor */
view->stack(_view_handle_registry.lookup(command.to_front.neighbor),
view->stack(_view_handle_registry.lookup(command.front_of.neighbor),
true);
return;
}
case Command::OP_TO_BACK:
{
return;
}
case Command::OP_BACKGROUND:
{
return;
}
case Command::OP_TITLE:
case Command::TITLE:
{
char sanitized_title[command.title.title.capacity()];
@ -793,7 +795,10 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
return;
}
case Command::OP_NOP:
case Command::BACK:
case Command::BEHIND_OF:
case Command::BACKGROUND:
case Command::NOP:
return;
}
}

View File

@ -142,7 +142,7 @@ class Pdf_view
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_view, Gui::Rect(Gui::Point(), _nit_mode.area));
_gui.enqueue<Command::To_front>(_view, Gui::Session::View_handle());
_gui.enqueue<Command::Front>(_view);
_gui.execute();
}

View File

@ -70,7 +70,7 @@ class Viewer
using namespace Gui;
_gui.enqueue<Command::Geometry>(_view, Gui::Rect(Gui::Point(0, 0), _mode.area));
_gui.enqueue<Command::To_front>(_view, Gui::Session::View_handle());
_gui.enqueue<Command::Front>(_view);
_gui.enqueue<Command::Title>(_view, "webcam");
_gui.execute();
}

View File

@ -224,7 +224,7 @@ void QGenodeViewWidget::paintEvent(QPaintEvent *event)
Gui::Session::View_handle const neighbor_handle =
gui->view_handle(platform_window->view_cap());
gui->enqueue<Command::To_front>(view_handle, neighbor_handle);
gui->enqueue<Command::Front_of>(view_handle, neighbor_handle);
gui->execute();
gui->release_view_handle(neighbor_handle);

View File

@ -69,7 +69,7 @@ struct Window : Genode_egl_window
mode_change();
gui.enqueue<Command::Title>(view, "eglut");
gui.enqueue<Command::To_front>(view, View_handle());
gui.enqueue<Command::Front>(view);
gui.execute();
}

View File

@ -63,52 +63,29 @@ struct Gui::Session : Genode::Session
struct Command
{
enum Opcode { OP_GEOMETRY, OP_OFFSET,
OP_TO_FRONT, OP_TO_BACK, OP_BACKGROUND,
OP_TITLE, OP_NOP };
enum Opcode { GEOMETRY, OFFSET, FRONT, BACK, FRONT_OF, BEHIND_OF,
BACKGROUND, TITLE, NOP };
struct Nop { static Opcode opcode() { return OP_NOP; } };
struct Nop { static constexpr Opcode opcode = NOP; };
struct Geometry
/**
* Operation that takes a view as first argument
*/
template <Opcode OPCODE>
struct View_op
{
static Opcode opcode() { return OP_GEOMETRY; }
View_handle view;
Rect rect;
};
struct Offset
{
static Opcode opcode() { return OP_OFFSET; }
View_handle view;
Point offset;
};
struct To_front
{
static Opcode opcode() { return OP_TO_FRONT; }
View_handle view;
View_handle neighbor;
};
struct To_back
{
static Opcode opcode() { return OP_TO_BACK; }
View_handle view;
View_handle neighbor;
};
struct Background
{
static Opcode opcode() { return OP_BACKGROUND; }
static constexpr Opcode opcode = OPCODE;
View_handle view;
};
struct Title
{
static Opcode opcode() { return OP_TITLE; }
View_handle view;
String<64> title;
};
struct Geometry : View_op<GEOMETRY> { Rect rect; };
struct Offset : View_op<OFFSET> { Point offset; };
struct Front : View_op<FRONT> { };
struct Back : View_op<BACK> { };
struct Front_of : View_op<FRONT_OF> { View_handle neighbor; };
struct Behind_of : View_op<BEHIND_OF> { View_handle neighbor; };
struct Background : View_op<BACKGROUND> { };
struct Title : View_op<TITLE> { String<64> title; };
Opcode opcode;
union
@ -116,16 +93,18 @@ struct Gui::Session : Genode::Session
Nop nop;
Geometry geometry;
Offset offset;
To_front to_front;
To_back to_back;
Front front;
Back back;
Front_of front_of;
Behind_of behind_of;
Background background;
Title title;
};
Command() : opcode(OP_NOP) { }
Command() : opcode(Opcode::NOP) { }
template <typename ARGS>
Command(ARGS args) : opcode(ARGS::opcode())
Command(ARGS args) : opcode(ARGS::opcode)
{
reinterpret_cast<ARGS &>(nop) = args;
}

View File

@ -357,8 +357,7 @@ Pointer::Main::Main(Genode::Env &env) : _env(env)
}
}
using View_handle = Gui::Session::View_handle;
_gui.enqueue<Gui::Session::Command::To_front>(_view, View_handle());
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.execute();
_update_pointer();

View File

@ -200,8 +200,7 @@ struct Status_bar::Main
_gui.mode_sigh(_mode_handler);
/* schedule initial view-stacking command, needed only once */
using View_handle = Gui::Session::View_handle;
_gui.enqueue<Gui::Session::Command::To_front>(_view, View_handle());
_gui.enqueue<Gui::Session::Command::Front>(_view);
/* import initial state */
_handle_mode();

View File

@ -304,7 +304,7 @@ struct Nit_fb::Main : View_updater
{
using Command = Gui::Session::Command;
gui.enqueue<Command::Geometry>(view, Rect(position, fb_session.size()));
gui.enqueue<Command::To_front>(view, View_handle());
gui.enqueue<Command::Front>(view);
gui.execute();
}

View File

@ -62,7 +62,7 @@ void Gui_session::_execute_command(Command const &command)
{
switch (command.opcode) {
case Command::OP_GEOMETRY:
case Command::GEOMETRY:
{
Command::Geometry const &cmd = command.geometry;
Locked_ptr<View> view(_view_handle_registry.lookup(cmd.view));
@ -81,7 +81,7 @@ void Gui_session::_execute_command(Command const &command)
return;
}
case Command::OP_OFFSET:
case Command::OFFSET:
{
Command::Offset const &cmd = command.offset;
Locked_ptr<View> view(_view_handle_registry.lookup(cmd.view));
@ -92,9 +92,29 @@ void Gui_session::_execute_command(Command const &command)
return;
}
case Command::OP_TO_FRONT:
case Command::FRONT:
{
Command::To_front const &cmd = command.to_front;
Command::Front const &cmd = command.front;
Locked_ptr<View> view(_view_handle_registry.lookup(cmd.view));
if (view.valid())
_view_stack.stack(*view, nullptr, true);
return;
}
case Command::BACK:
{
Command::Back const &cmd = command.back;
Locked_ptr<View> view(_view_handle_registry.lookup(cmd.view));
if (view.valid())
_view_stack.stack(*view, nullptr, false);
return;
}
case Command::FRONT_OF:
{
Command::Front_of const &cmd = command.front_of;
if (_views_are_equal(cmd.view, cmd.neighbor))
return;
@ -102,23 +122,16 @@ void Gui_session::_execute_command(Command const &command)
if (!view.valid())
return;
/* bring to front if no neighbor is specified */
if (!cmd.neighbor.valid()) {
_view_stack.stack(*view, nullptr, true);
return;
}
/* stack view relative to neighbor */
Locked_ptr<View> neighbor(_view_handle_registry.lookup(cmd.neighbor));
if (neighbor.valid())
_view_stack.stack(*view, &(*neighbor), false);
return;
}
case Command::OP_TO_BACK:
case Command::BEHIND_OF:
{
Command::To_back const &cmd = command.to_back;
Command::Behind_of const &cmd = command.behind_of;
if (_views_are_equal(cmd.view, cmd.neighbor))
return;
@ -126,21 +139,14 @@ void Gui_session::_execute_command(Command const &command)
if (!view.valid())
return;
/* bring to front if no neighbor is specified */
if (!cmd.neighbor.valid()) {
_view_stack.stack(*view, nullptr, false);
return;
}
/* stack view relative to neighbor */
Locked_ptr<View> neighbor(_view_handle_registry.lookup(cmd.neighbor));
if (neighbor.valid())
_view_stack.stack(*view, &(*neighbor), true);
return;
}
case Command::OP_BACKGROUND:
case Command::BACKGROUND:
{
Command::Background const &cmd = command.background;
if (_provides_default_bg) {
@ -171,7 +177,7 @@ void Gui_session::_execute_command(Command const &command)
return;
}
case Command::OP_TITLE:
case Command::TITLE:
{
Command::Title const &cmd = command.title;
Locked_ptr<View> view(_view_handle_registry.lookup(cmd.view));
@ -182,7 +188,7 @@ void Gui_session::_execute_command(Command const &command)
return;
}
case Command::OP_NOP:
case Command::NOP:
return;
}
}

View File

@ -466,7 +466,7 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_view, Rect(Point(0, 0), _fb_mode.area));
_gui.enqueue<Command::To_front>(_view, Gui::Session::View_handle());
_gui.enqueue<Command::Front>(_view);
_gui.execute();
return _gui.mode();
}

View File

@ -47,7 +47,7 @@ class Test::View
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_handle, rect);
_gui.enqueue<Command::To_front>(_handle, View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.execute();
}

View File

@ -65,7 +65,7 @@ class Test::View : private List<View>::Element, Interface
using namespace Gui;
_gui.enqueue<Command::Geometry>(_handle, Gui::Rect { _pos, _attr.size });
_gui.enqueue<Command::To_front>(_handle, View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.enqueue<Command::Title>(_handle, _attr.title);
_gui.execute();
}
@ -77,7 +77,7 @@ class Test::View : private List<View>::Element, Interface
void top()
{
_gui.enqueue<Command::To_front>(_handle, View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.execute();
}

View File

@ -49,7 +49,7 @@ class Test::View
using Command = Gui::Session::Command;
_gui.enqueue<Command::Geometry>(_handle, rect);
_gui.enqueue<Command::To_front>(_handle, View_handle());
_gui.enqueue<Command::Front>(_handle);
_gui.execute();
}

View File

@ -76,23 +76,19 @@ class Genodefb :
{
_gui.buffer(_fb_mode, false);
typedef Gui::Session::Command Command;
Gui::Rect rect(Gui::Point(0, 0), _fb_mode.area);
_gui.enqueue<Command::Geometry>(_view, rect);
_gui.enqueue<Gui::Session::Command::Geometry>(_view, rect);
_gui.execute();
}
Fb_Genode::Mode _initial_setup()
{
typedef Gui::Session::Command Command;
_view = _gui.create_view();
_adjust_buffer();
_gui.enqueue<Command::To_front>(_view, View_handle());
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.execute();
return _fb_mode;

View File

@ -74,23 +74,19 @@ class Genodefb :
{
_gui.buffer(_fb_mode, false);
using Command = Gui::Session::Command;
Gui::Rect rect(Gui::Point(0, 0), _fb_mode.area);
_gui.enqueue<Command::Geometry>(_view, rect);
_gui.enqueue<Gui::Session::Command::Geometry>(_view, rect);
_gui.execute();
}
Fb_Genode::Mode _initial_setup()
{
using Command = Gui::Session::Command;
_view = _gui.create_view();
_adjust_buffer();
_gui.enqueue<Command::To_front>(_view, View_handle());
_gui.enqueue<Gui::Session::Command::Front>(_view);
_gui.execute();
return _fb_mode;