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 Dec 18, 2024
1 parent c533765 commit 761bfd5
Show file tree
Hide file tree
Showing 19 changed files with 591 additions and 314 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
39 changes: 28 additions & 11 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,9 @@ struct Decorator::Main : Window_factory_base
_back_to_front(dirty);
}

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

Windows _windows { };

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

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

Attached_rom_dataspace _config { _env, "config" };

void _handle_config();
Expand Down Expand Up @@ -222,19 +224,34 @@ struct Decorator::Main : Window_factory_base
/**
* Window_factory_base interface
*/
Window_base *create(Xml_node window_node) override
Window_base::Ref &create_ref(Xml_node const &window_node) override
{
Windows::Id const id { window_node.attribute_value("id", 0U) };

Window_base *window_ptr = nullptr;
_windows.apply<Window_base>(id,
[&] (Window_base &window) { window_ptr = &window; },
[&] /* missing */ {
window_ptr = new (_heap)
Window(_windows, id, _gui, _animator, _decorator_config); });

return *new (_heap) Window_base::Ref(*window_ptr);
}

/**
* Window_factory_base interface
*/
void destroy_ref(Window_base::Ref &ref) override
{
return new (_heap)
Window(window_node.attribute_value("id", 0U),
_gui, _animator, _decorator_config);
destroy(_heap, &ref);
}

/**
* Window_factory_base interface
*/
void destroy(Window_base *window) override
void destroy_window(Window_base &window) override
{
Genode::destroy(_heap, static_cast<Window *>(window));
destroy(_heap, &window);
}
};

Expand Down Expand Up @@ -280,11 +297,11 @@ static void update_hover_report(Genode::Xml_node pointer_node,

Genode::Reporter::Xml_generator xml(hover_reporter, [&] ()
{
if (hover.window_id > 0) {
if (hover.window_id.value > 0) {

xml.node("window", [&] () {

xml.attribute("id", hover.window_id);
xml.attribute("id", hover.window_id.value);

if (hover.left_sizer) xml.node("left_sizer");
if (hover.right_sizer) xml.node("right_sizer");
Expand Down
7 changes: 3 additions & 4 deletions repos/gems/src/app/decorator/window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
#include "window.h"


void Decorator::Window::draw(Decorator::Canvas_base &canvas,
Decorator::Rect clip,
Draw_behind_fn const &draw_behind_fn) const
void Decorator::Window::draw(Decorator::Canvas_base &canvas, Ref const &win_ref,
Decorator::Rect clip, Draw_behind_fn const &draw_behind_fn) const
{
Clip_guard clip_guard(canvas, clip);

Expand All @@ -28,7 +27,7 @@ void Decorator::Window::draw(Decorator::Canvas_base &canvas,
Point p2 = rect.p2();

if (_has_alpha)
draw_behind_fn.draw_behind(canvas, *this, canvas.clip());
draw_behind_fn.draw_behind(canvas, win_ref, canvas.clip());

_draw_corner(canvas, Rect(p1, corner), _border_size, true, true,
_window_elem_attr(Element::TOP_LEFT));
Expand Down
39 changes: 24 additions & 15 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 All @@ -87,7 +96,7 @@ class Decorator::Window : public Window_base
_left_view { _gui },
_top_view { _gui };

Gui_view _content_view { _gui, (unsigned)id() };
Gui_view _content_view { _gui, unsigned(id().value) };

static Border _init_border() {
return Border(_border_size + _title_height,
Expand Down Expand Up @@ -419,10 +428,10 @@ class Decorator::Window : public Window_base

public:

Window(unsigned id, Gui::Connection &gui,
Window(Windows &windows, Windows::Id id, Gui::Connection &gui,
Animator &animator, Config const &config)
:
Window_base(id),
Window_base(windows, id),
_gui(gui),
_animator(animator), _config(config)
{ }
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 All @@ -487,7 +496,7 @@ class Decorator::Window : public Window_base
_base_color = _config.base_color(_title);
}

void draw(Canvas_base &canvas, Rect clip, Draw_behind_fn const &) const override;
void draw(Canvas_base &canvas, Ref const &, Rect clip, Draw_behind_fn const &) const override;

bool update(Xml_node) override;

Expand Down
Loading

0 comments on commit 761bfd5

Please sign in to comment.