Skip to content

Commit

Permalink
wm/decorator/layouter: window clipping
Browse files Browse the repository at this point in the history
This patch changes the window-layout format to support the rectangular
clipping of windows at screen boundaries. The new <boundary> node defines
the clipping boundary for the windows listed within the node. Boundaries
are expected to be disjoint. In the example below, the "vbox" window is
placed partially outside the screen area of "screen_2".

<window_layout>
  <boundary name="screen_1" xpos="0" ypos="0" width="640" height="480">
    <window id="1" title="launchpad" xpos="10" ypos="140" width="400" height=">
  </boundary>
  <boundary name="screen_2" xpos="640" ypos="0" width="800" height="600">
    <window id="2" title="vbox"     xpos="520" ypos="52" width="800" height="600">
    <window id="3" title="terminal" xpos="650" ypos="72" width="500" height="400">
  </boundary>
</window_layout>

The layouter uses boundaries to restrict the visiblilty of windows to
their respective target areas.

Until now, Sculpt relied on the fact that the window-layout ROM had the
same structure as the resize-request ROM. With the addition of the
<boundary> nodes, this is no longer the case. Therefore, the Sculpt
manager generates a dedicated resize-request ROM now.

Issue genodelabs#5390
  • Loading branch information
nfeske committed Nov 29, 2024
1 parent f6351c7 commit d850861
Show file tree
Hide file tree
Showing 17 changed files with 389 additions and 240 deletions.
102 changes: 58 additions & 44 deletions repos/gems/run/decorator.run
Original file line number Diff line number Diff line change
Expand Up @@ -77,79 +77,93 @@ install_config {
<sleep milliseconds="500" />
<inline description="open window 1">
<window_layout>
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<boundary width="1024" height="768">
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
</boundary>
</window_layout>
</inline>
<sleep milliseconds="1000" />
<inline description="open window 2 behind window 1">
<window_layout>
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
<boundary width="1024" height="768">
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
</boundary>
</window_layout>
</inline>
<sleep milliseconds="1000" />
<inline description="open window 3 in front">
<window_layout>
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200" />
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
<boundary width="1024" height="768">
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200" />
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
</boundary>
</window_layout>
</inline>
<sleep milliseconds="1000" />
<inline description="bring window 1 to front">
<window_layout>
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
<boundary width="1024" height="768">
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
</boundary>
</window_layout>
</inline>
<sleep milliseconds="1000" />
<inline description="change title of window 1">
<window_layout>
<window id="1" title="Genode Toolchain (running)"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
<boundary width="1024" height="768">
<window id="1" title="Genode Toolchain (running)"
xpos="100" ypos="50" width="200" height="200"
focused="yes" />
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
</boundary>
</window_layout>
</inline>
<sleep milliseconds="1000" />
<inline description="change focus to window 3">
<window_layout>
<window id="1" title="Genode Toolchain (running)"
xpos="100" ypos="50" width="200" height="200" />
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
<boundary width="1024" height="768">
<window id="1" title="Genode Toolchain (running)"
xpos="100" ypos="50" width="200" height="200" />
<window id="3" title="Launchpad"
xpos="210" ypos="250" width="400" height="200"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
</boundary>
</window_layout>
</inline>
<sleep milliseconds="1000" />
<inline description="move window 3">
<window_layout>
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200" />
<window id="3" title="Launchpad"
xpos="310" ypos="300" width="500" height="300"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
<boundary width="1024" height="768">
<window id="1" title="Genode Toolchain"
xpos="100" ypos="50" width="200" height="200" />
<window id="3" title="Launchpad"
xpos="310" ypos="300" width="500" height="300"
focused="yes" />
<window id="2" title="Arora (2)"
xpos="170" ypos="150" width="300" height="200" />
</boundary>
</window_layout>
</inline>
<sleep milliseconds="1000" />
Expand All @@ -160,7 +174,7 @@ install_config {
</start>

<start name="decorator">
<resource name="RAM" quantum="4M"/>
<resource name="RAM" quantum="8M"/>
<route>
<service name="ROM" label="pointer">
<child name="report_rom" />
Expand Down
2 changes: 1 addition & 1 deletion repos/gems/sculpt/leitzentrale/default
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
</provides>
<config verbose="no">
<policy label="decorator -> window_layout" report="manager -> window_layout"/>
<policy label="wm -> resize_request" report="manager -> window_layout"/>
<policy label="wm -> resize_request" report="manager -> resize_request"/>
<policy label="wm -> focus" report="manager -> wm_focus"/>
<policy label="decorator -> pointer" report="wm -> pointer"/>
<policy label="manager -> window_list" report="wm -> window_list"/>
Expand Down
6 changes: 3 additions & 3 deletions repos/gems/src/app/decorator/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct Decorator::Main : Window_factory_base
{
Env &_env;

Heap _heap { _env.ram(), _env.rm() };

Timer::Connection _timer { _env };

/*
Expand Down Expand Up @@ -120,7 +122,7 @@ struct Decorator::Main : Window_factory_base
_back_to_front(dirty);
}

Window_stack _window_stack = { *this };
Window_stack _window_stack { *this, _heap };

/**
* Handler for responding to window-layout changes
Expand Down Expand Up @@ -177,8 +179,6 @@ struct Decorator::Main : Window_factory_base
}
}

Heap _heap { _env.ram(), _env.rm() };

Attached_rom_dataspace _config { _env, "config" };

void _handle_config();
Expand Down
31 changes: 20 additions & 11 deletions repos/gems/src/app/decorator/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class Decorator::Window : public Window_base
*/
bool _gui_views_up_to_date = false;

Rect _clip { }; /* most recently used clipping rectangle */

struct Gui_view : Genode::Noncopyable
{
Gui::Connection &_gui;
Expand Down Expand Up @@ -74,11 +76,18 @@ class Decorator::Window : public Window_base

void stack_back_most() { _gui.enqueue<Command::Back>(id()); }

void place(Rect rect)
void place_as_decor(Clip const &clip, Rect rect)
{
Rect const intersection = Rect::intersect(clip, rect);
_gui.enqueue<Command::Geometry>(id(), intersection);
_gui.enqueue<Command::Offset>(id(), Point() - intersection.at);
}

void place_as_content(Clip const &clip, Rect rect)
{
_gui.enqueue<Command::Geometry>(id(), rect);
Point offset = Point(0, 0) - rect.at;
_gui.enqueue<Command::Offset>(id(), offset);
Rect const intersection = Rect::intersect(clip, rect);
_gui.enqueue<Command::Geometry>(id(), intersection);
_gui.enqueue<Command::Offset>(id(), rect.at - intersection.at);
}
};

Expand Down Expand Up @@ -465,18 +474,18 @@ class Decorator::Window : public Window_base
geometry().p2() + Point(_border.right, _border.bottom));
}

void update_gui_views() override
void update_gui_views(Clip const &clip) override
{
if (!_gui_views_up_to_date) {
if (!_gui_views_up_to_date || (clip != _clip)) {

/* update view positions */
auto const border = outer_geometry().cut(geometry());

_content_view.place(geometry());
_top_view .place(border.top);
_left_view .place(border.left);
_right_view .place(border.right);
_bottom_view .place(border.bottom);
_content_view.place_as_content(clip, geometry());
_top_view .place_as_decor (clip, border.top);
_left_view .place_as_decor (clip, border.left);
_right_view .place_as_decor (clip, border.right);
_bottom_view .place_as_decor (clip, border.bottom);

_gui_views_up_to_date = true;
}
Expand Down
42 changes: 34 additions & 8 deletions repos/gems/src/app/sculpt_manager/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1621,8 +1621,9 @@ struct Sculpt::Main : Input_event_handler,
Rom_handler<Main> _decorator_margins {
_env, "decorator_margins", *this, &Main::_handle_window_layout_or_decorator_margins };

Expanding_reporter _wm_focus { _env, "focus", "wm_focus" };
Expanding_reporter _window_layout { _env, "window_layout", "window_layout" };
Expanding_reporter _wm_focus { _env, "focus", "wm_focus" };
Expanding_reporter _window_layout { _env, "window_layout", "window_layout" };
Expanding_reporter _resize_request { _env, "resize_request", "resize_request" };

template <size_t N>
void _with_window(Xml_node window_list, String<N> const &match, auto const &fn)
Expand Down Expand Up @@ -1906,10 +1907,20 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins,
Point const inspect_p2(avail.x2() - margins.right - 1,
avail.y2() - margins.bottom - 1);

_window_layout.generate([&] (Xml_generator &xml) {
auto generate_within_screen_boundary = [&] (auto const &fn)
{
_resize_request.generate([&] (Xml_generator &resize_xml) {
_window_layout.generate([&] (Xml_generator &xml) {
xml.node("boundary", [&] {
xml.attribute("width", _screen_size.w);
xml.attribute("height", _screen_size.h);
fn(xml, resize_xml); }); }); });
};

generate_within_screen_boundary([&] (Xml_generator &xml, Xml_generator &resize_xml) {

auto gen_window = [&] (Xml_node const &win, Rect rect) {
if (rect.valid()) {
if (rect.valid())
xml.node("window", [&] {
xml.attribute("id", win.attribute_value("id", 0UL));
xml.attribute("xpos", rect.x1());
Expand All @@ -1918,7 +1929,15 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins,
xml.attribute("height", rect.h());
xml.attribute("title", win.attribute_value("label", Label()));
});
}
};

auto gen_resize = [&] (Xml_node const &win, Area area) {
if (area.valid())
resize_xml.node("window", [&] {
resize_xml.attribute("id", win.attribute_value("id", 0UL));
resize_xml.attribute("width", area.w);
resize_xml.attribute("height", area.h);
});
};

/* window size limited to space unobstructed by the menu and log */
Expand All @@ -1935,7 +1954,10 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins,
gen_window(win, panel); });

_with_window(window_list, Label("log"), [&] (Xml_node const &win) {
gen_window(win, Rect::compound(log_p1, log_p2)); });
Rect const rect = Rect::compound(log_p1, log_p2);
gen_window(win, rect);
gen_resize(win, rect.area);
});

int system_right_xpos = 0;
if (system_available()) {
Expand Down Expand Up @@ -2058,8 +2080,12 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins,
}

_with_window(window_list, inspect_label, [&] (Xml_node const &win) {
if (_selected_tab == Panel_dialog::Tab::INSPECT)
gen_window(win, Rect::compound(inspect_p1, inspect_p2)); });
if (_selected_tab == Panel_dialog::Tab::INSPECT) {
Rect const rect = Rect::compound(inspect_p1, inspect_p2);
gen_window(win, rect);
gen_resize(win, rect.area);
}
});

/*
* Position runtime view centered within the inspect area, but allow
Expand Down
6 changes: 3 additions & 3 deletions repos/gems/src/app/themed_decorator/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct Decorator::Main : Window_factory_base
{
Env &_env;

Heap _heap { _env.ram(), _env.rm() };

Timer::Connection _timer { _env };

/*
Expand All @@ -49,7 +51,7 @@ struct Decorator::Main : Window_factory_base
return { .cs = _timer.curr_time().trunc_to_plain_ms().value / 10 };
}

Window_stack _window_stack = { *this };
Window_stack _window_stack = { *this, _heap };

/**
* Handler for responding to window-layout changes
Expand Down Expand Up @@ -84,8 +86,6 @@ struct Decorator::Main : Window_factory_base

Animator _animator { };

Heap _heap { _env.ram(), _env.rm() };

Theme _theme { _env.ram(), _env.rm(), _heap };

Reporter _decorator_margins_reporter = { _env, "decorator_margins" };
Expand Down
4 changes: 3 additions & 1 deletion repos/gems/src/app/themed_decorator/theme.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,9 @@ element_geometry(Genode::Ram_allocator &ram, Genode::Region_map &rm,
Genode::Allocator &alloc, char const *sub_node_type,
Texture_id texture_id)
{
using namespace Decorator;
using Rect = Decorator::Rect;
using Point = Decorator::Point;
using Area = Decorator::Area;

static Genode::Xml_node const node = metadata(alloc);

Expand Down
5 changes: 1 addition & 4 deletions repos/gems/src/app/themed_decorator/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <os/texture.h>
#include <os/pixel_alpha8.h>
#include <os/pixel_rgb888.h>
#include <decorator/types.h>

namespace Decorator {

Expand All @@ -29,10 +30,6 @@ namespace Decorator {

using Pixel_surface = Genode::Surface<Pixel_rgb888>;
using Alpha_surface = Genode::Surface<Pixel_alpha8>;

using Area = Genode::Surface_base::Area;
using Point = Genode::Surface_base::Point;
using Rect = Genode::Surface_base::Rect;
}


Expand Down
Loading

0 comments on commit d850861

Please sign in to comment.