diff --git a/repos/gems/run/decorator.run b/repos/gems/run/decorator.run
index 0366a904d7..6f3025733e 100644
--- a/repos/gems/run/decorator.run
+++ b/repos/gems/run/decorator.run
@@ -77,79 +77,93 @@ install_config {
-
+
+
+
-
-
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
@@ -160,7 +174,7 @@ install_config {
-
+
diff --git a/repos/gems/sculpt/leitzentrale/default b/repos/gems/sculpt/leitzentrale/default
index 39d841370c..e4be530b53 100644
--- a/repos/gems/sculpt/leitzentrale/default
+++ b/repos/gems/sculpt/leitzentrale/default
@@ -114,7 +114,7 @@
-
+
diff --git a/repos/gems/src/app/decorator/main.cc b/repos/gems/src/app/decorator/main.cc
index 7ec8beca58..84fe8a3a16 100644
--- a/repos/gems/src/app/decorator/main.cc
+++ b/repos/gems/src/app/decorator/main.cc
@@ -40,6 +40,8 @@ struct Decorator::Main : Window_factory_base
{
Env &_env;
+ Heap _heap { _env.ram(), _env.rm() };
+
Timer::Connection _timer { _env };
/*
@@ -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
@@ -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();
@@ -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
{
- return new (_heap)
- Window(window_node.attribute_value("id", 0U),
- _gui, _animator, _decorator_config);
+ Windows::Id const id { window_node.attribute_value("id", 0U) };
+
+ Window_base *window_ptr = nullptr;
+ _windows.apply(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(Window_base *window) override
+ void destroy_ref(Window_base::Ref &ref) override
{
- Genode::destroy(_heap, static_cast(window));
+ destroy(_heap, &ref);
+ }
+
+ /**
+ * Window_factory_base interface
+ */
+ void destroy_window(Window_base &window) override
+ {
+ destroy(_heap, &window);
}
};
@@ -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");
diff --git a/repos/gems/src/app/decorator/window.cc b/repos/gems/src/app/decorator/window.cc
index c133b8b7d3..d2b1e8db3b 100644
--- a/repos/gems/src/app/decorator/window.cc
+++ b/repos/gems/src/app/decorator/window.cc
@@ -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);
@@ -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));
diff --git a/repos/gems/src/app/decorator/window.h b/repos/gems/src/app/decorator/window.h
index 393489d565..5fd2753779 100644
--- a/repos/gems/src/app/decorator/window.h
+++ b/repos/gems/src/app/decorator/window.h
@@ -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;
@@ -74,11 +76,18 @@ class Decorator::Window : public Window_base
void stack_back_most() { _gui.enqueue(id()); }
- void place(Rect rect)
+ void place_as_decor(Clip const &clip, Rect rect)
{
- _gui.enqueue(id(), rect);
- Point offset = Point(0, 0) - rect.at;
- _gui.enqueue(id(), offset);
+ Rect const intersection = Rect::intersect(clip, rect);
+ _gui.enqueue(id(), intersection);
+ _gui.enqueue(id(), Point() - intersection.at);
+ }
+
+ void place_as_content(Clip const &clip, Rect rect)
+ {
+ Rect const intersection = Rect::intersect(clip, rect);
+ _gui.enqueue(id(), intersection);
+ _gui.enqueue(id(), rect.at - intersection.at);
}
};
@@ -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,
@@ -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)
{ }
@@ -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;
}
@@ -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;
diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc
index 3d2f0d25b5..c0ff8b8154 100644
--- a/repos/gems/src/app/sculpt_manager/main.cc
+++ b/repos/gems/src/app/sculpt_manager/main.cc
@@ -1621,8 +1621,9 @@ struct Sculpt::Main : Input_event_handler,
Rom_handler _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
void _with_window(Xml_node window_list, String const &match, auto const &fn)
@@ -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());
@@ -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 */
@@ -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()) {
@@ -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
diff --git a/repos/gems/src/app/themed_decorator/main.cc b/repos/gems/src/app/themed_decorator/main.cc
index edf44d3bca..57c84d650c 100644
--- a/repos/gems/src/app/themed_decorator/main.cc
+++ b/repos/gems/src/app/themed_decorator/main.cc
@@ -37,6 +37,8 @@ struct Decorator::Main : Window_factory_base
{
Env &_env;
+ Heap _heap { _env.ram(), _env.rm() };
+
Timer::Connection _timer { _env };
/*
@@ -49,7 +51,9 @@ 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 };
+
+ Windows _windows { };
/**
* Handler for responding to window-layout changes
@@ -84,8 +88,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" };
@@ -177,19 +179,35 @@ 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
{
- return new (_heap)
- Window(_env, window_node.attribute_value("id", 0U),
- _gui, _animator, _theme, _decorator_config);
+ Windows::Id const id { window_node.attribute_value("id", 0U) };
+
+ Window_base *window_ptr = nullptr;
+ _windows.apply(id,
+ [&] (Window_base &window) { window_ptr = &window; },
+ [&] /* missing */ {
+ window_ptr = new (_heap)
+ Window(_env, _windows, id, _gui, _animator, _theme,
+ _decorator_config); });
+
+ return *new (_heap) Window_base::Ref(*window_ptr);
}
/**
* Window_factory_base interface
*/
- void destroy(Window_base *window) override
+ void destroy_ref(Window_base::Ref &ref) override
{
- Genode::destroy(_heap, static_cast(window));
+ destroy(_heap, &ref);
+ }
+
+ /**
+ * Window_factory_base interface
+ */
+ void destroy_window(Window_base &window) override
+ {
+ destroy(_heap, &window);
}
};
@@ -233,11 +251,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");
diff --git a/repos/gems/src/app/themed_decorator/theme.cc b/repos/gems/src/app/themed_decorator/theme.cc
index 3570c4efbd..807e1940cc 100644
--- a/repos/gems/src/app/themed_decorator/theme.cc
+++ b/repos/gems/src/app/themed_decorator/theme.cc
@@ -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);
diff --git a/repos/gems/src/app/themed_decorator/theme.h b/repos/gems/src/app/themed_decorator/theme.h
index 32988982f6..600ea1c0cc 100644
--- a/repos/gems/src/app/themed_decorator/theme.h
+++ b/repos/gems/src/app/themed_decorator/theme.h
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
namespace Decorator {
@@ -29,10 +30,6 @@ namespace Decorator {
using Pixel_surface = Genode::Surface;
using Alpha_surface = Genode::Surface;
-
- using Area = Genode::Surface_base::Area;
- using Point = Genode::Surface_base::Point;
- using Rect = Genode::Surface_base::Rect;
}
diff --git a/repos/gems/src/app/themed_decorator/window.h b/repos/gems/src/app/themed_decorator/window.h
index 7abdf8fb02..b82cb70e40 100644
--- a/repos/gems/src/app/themed_decorator/window.h
+++ b/repos/gems/src/app/themed_decorator/window.h
@@ -52,6 +52,8 @@ class Decorator::Window : public Window_base, public Animator::Item
*/
bool _gui_views_up_to_date = false;
+ Rect _clip { }; /* most recently used clipping rectangle */
+
unsigned _topped_cnt = 0;
Window_title _title { };
@@ -162,10 +164,11 @@ class Decorator::Window : public Window_base, public Animator::Item
void stack_back_most() { _gui.enqueue(id()); }
- void place(Rect rect, Point offset)
+ void place(Clip const &clip, Rect rect, Point offset)
{
- _gui.enqueue(id(), rect);
- _gui.enqueue(id(), offset);
+ Rect const intersection = Rect::intersect(clip, rect);
+ _gui.enqueue(id(), intersection);
+ _gui.enqueue(id(), offset + rect.at - intersection.at);
}
};
@@ -263,7 +266,7 @@ class Decorator::Window : public Window_base, public Animator::Item
_left_view { _gui, _gui_left_right },
_top_view { _gui, _gui_top_bottom };
- Content_view _content_view { _gui, (unsigned)id() };
+ Content_view _content_view { _gui, unsigned(id().value) };
void _repaint_decorations(Gui_buffer &buffer, Area area)
{
@@ -352,10 +355,11 @@ class Decorator::Window : public Window_base, public Animator::Item
public:
- Window(Genode::Env &env, unsigned id, Gui::Connection &gui,
- Animator &animator, Theme const &theme, Config const &config)
+ Window(Genode::Env &env, Windows &windows, Windows::Id id,
+ Gui::Connection &gui, Animator &animator, Theme const &theme,
+ Config const &config)
:
- Window_base(id),
+ Window_base(windows, id),
Animator::Item(animator),
_env(env), _theme(theme), _animator(animator),
_gui(gui), _config(config)
@@ -433,11 +437,10 @@ class Decorator::Window : public Window_base, public Animator::Item
return _outer_from_inner_geometry(geometry());
}
- void update_gui_views() override
+ void update_gui_views(Clip const &clip) override
{
- bool const gui_view_rect_up_to_date =
- _gui_view_rect.p1() == geometry().p1() &&
- _gui_view_rect.p2() == geometry().p2();
+ bool const gui_view_rect_up_to_date = (_gui_view_rect == geometry())
+ && (_clip == clip);
if (!_gui_views_up_to_date || !gui_view_rect_up_to_date) {
@@ -448,20 +451,21 @@ class Decorator::Window : public Window_base, public Animator::Item
/* update view positions */
Rect::Cut_remainder const r = outer.cut(inner);
- _content_view.place(inner, Point(0, 0));
- _top_view .place(r.top, Point(0, 0));
- _left_view .place(r.left, Point(0, -r.top.h()));
- _right_view .place(r.right, Point(-r.right.w(), -r.top.h()));
- _bottom_view .place(r.bottom, Point(0, -theme_size.h + r.bottom.h()));
+ _content_view.place(clip, inner, Point(0, 0));
+ _top_view .place(clip, r.top, Point(0, 0));
+ _left_view .place(clip, r.left, Point(0, -r.top.h()));
+ _right_view .place(clip, r.right, Point(-r.right.w(), -r.top.h()));
+ _bottom_view .place(clip, r.bottom, Point(0, -theme_size.h + r.bottom.h()));
_gui.execute();
_gui_view_rect = inner;
_gui_views_up_to_date = true;
+ _clip = clip;
}
}
- void draw(Canvas_base &, Rect, Draw_behind_fn const &) const override { }
+ void draw(Canvas_base &, Ref const &, Rect, Draw_behind_fn const &) const override { }
void adapt_to_changed_config()
{
diff --git a/repos/gems/src/app/window_layouter/assign_list.h b/repos/gems/src/app/window_layouter/assign_list.h
index 8d4ed67dbb..7ad88647f0 100644
--- a/repos/gems/src/app/window_layouter/assign_list.h
+++ b/repos/gems/src/app/window_layouter/assign_list.h
@@ -90,11 +90,24 @@ class Window_layouter::Assign_list : Noncopyable
return result;
}
- template
- void for_each(FN const &fn) { _assignments.for_each(fn); }
+ void for_each(auto const &fn) { _assignments.for_each(fn); }
+ void for_each(auto const &fn) const { _assignments.for_each(fn); }
- template
- void for_each(FN const &fn) const { _assignments.for_each(fn); }
+ void for_each_visible(auto const &target_name, auto const &fn) const
+ {
+ for_each([&] (Assign const &assign) {
+ if (assign.visible() && target_name == assign.target_name())
+ fn(assign); });
+ }
+
+ bool target_empty(auto const &target_name) const
+ {
+ bool result = true;
+ for_each_visible(target_name, [&] (Assign const &assign) {
+ assign.for_each_member([&] (Assign::Member const &) {
+ result = false; }); });
+ return result;
+ }
};
#endif /* _ASSIGN_LIST_H_ */
diff --git a/repos/gems/src/app/window_layouter/target_list.h b/repos/gems/src/app/window_layouter/target_list.h
index 69a5b72893..b65fa2d476 100644
--- a/repos/gems/src/app/window_layouter/target_list.h
+++ b/repos/gems/src/app/window_layouter/target_list.h
@@ -146,29 +146,28 @@ class Window_layouter::Target_list
if (target.layer() >= min_layer && target.layer() <= layer)
layer = target.layer(); });
- /* visit all windows on the layer */
- assignments.for_each([&] (Assign const &assign) {
+ /* search target by name */
+ _targets.for_each([&] (Target const &target) {
- if (!assign.visible())
+ if (target.layer() != layer)
return;
- Target::Name const target_name = assign.target_name();
+ if (!target.visible())
+ return;
- /* search target by name */
- _targets.for_each([&] (Target const &target) {
+ if (assignments.target_empty(target.name()))
+ return;
- if (target.name() != target_name)
- return;
+ Rect const boundary = target.geometry();
+ xml.node("boundary", [&] {
+ xml.attribute("name", target.name());
+ generate(xml, boundary);
- if (target.layer() != layer)
- return;
-
- if (!target.visible())
- return;
-
- /* found target area, iterate though all assigned windows */
- assign.for_each_member([&] (Assign::Member const &member) {
- member.window.generate(xml, target.geometry()); });
+ /* visit all windows on the layer */
+ assignments.for_each_visible(target.name(), [&] (Assign const &assign) {
+ assign.for_each_member([&] (Assign::Member const &member) {
+ member.window.generate(xml, boundary); });
+ });
});
});
diff --git a/repos/gems/src/app/window_layouter/types.h b/repos/gems/src/app/window_layouter/types.h
index 43728ac1e0..d647949928 100644
--- a/repos/gems/src/app/window_layouter/types.h
+++ b/repos/gems/src/app/window_layouter/types.h
@@ -78,6 +78,14 @@ namespace Window_layouter {
from.for_each_sub_node([&] (Xml_node const &sub_node) {
copy_node(xml, sub_node, { max_depth.value - 1 }); }); });
}
+
+ static void generate(Xml_generator &xml, Rect const &rect)
+ {
+ xml.attribute("xpos", rect.x1());
+ xml.attribute("ypos", rect.y1());
+ xml.attribute("width", rect.w());
+ xml.attribute("height", rect.h());
+ }
}
#endif /* _TYPES_H_ */
diff --git a/repos/gems/src/server/wm/decorator_gui.h b/repos/gems/src/server/wm/decorator_gui.h
index 067606c2dc..e59ef3688f 100644
--- a/repos/gems/src/server/wm/decorator_gui.h
+++ b/repos/gems/src/server/wm/decorator_gui.h
@@ -64,6 +64,11 @@ struct Wm::Decorator_gui_session : Session_object,
Window_registry::Id win_id;
+ Rect geometry { };
+ Point offset { };
+
+ Rect content_geometry() const { return { geometry.p1() + offset, geometry.area }; }
+
Content_view_ref(Window_registry::Id win_id, Gui::View_ids &ids, View_id id)
: id(*this, ids, id), win_id(win_id) { }
};
@@ -152,35 +157,33 @@ struct Wm::Decorator_gui_session : Session_object,
void _execute_command(Command const &cmd)
{
+ /*
+ * If the content view changes position, propagate the new position to
+ * the GUI service to properly transform absolute input coordinates.
+ */
+ auto with_content_view_ref = [&] (View_id id, auto const &fn)
+ {
+ _content_view_ids.apply(id,
+ [&] (Content_view_ref &ref) {
+ Rect const orig = ref.content_geometry();
+ fn(ref);
+ if (orig != ref.content_geometry())
+ _content_callback.content_geometry(ref.win_id,
+ ref.content_geometry()); },
+ [&] { });
+ };
+
switch (cmd.opcode) {
case Command::GEOMETRY:
- /*
- * If the content view changes position, propagate the new position
- * to the GUI service to properly transform absolute input
- * coordinates.
- */
- _content_view_ids.apply(cmd.geometry.view,
- [&] (Content_view_ref const &view_ref) {
- _content_callback.content_geometry(view_ref.win_id, cmd.geometry.rect); },
- [&] { });
+ with_content_view_ref(cmd.geometry.view, [&] (Content_view_ref &view_ref) {
+ view_ref.geometry = cmd.geometry.rect; });
/* forward command */
_real_gui.enqueue(cmd);
return;
- case Command::OFFSET:
-
- /*
- * If non-content views change their offset (if the lookup
- * fails), propagate the event
- */
- _content_view_ids.apply(cmd.geometry.view,
- [&] (Content_view_ref const &) { },
- [&] { _real_gui.enqueue(cmd); });
- return;
-
case Command::FRONT:
case Command::BACK:
case Command::FRONT_OF:
@@ -192,7 +195,14 @@ struct Wm::Decorator_gui_session : Session_object,
_real_gui.execute();
_content_callback.update_content_child_views(view_ref.win_id); },
[&] { });
+ return;
+ case Command::OFFSET:
+
+ with_content_view_ref(cmd.offset.view, [&] (Content_view_ref &view_ref) {
+ view_ref.offset = cmd.offset.offset; });
+
+ _real_gui.enqueue(cmd);
return;
case Command::TITLE:
diff --git a/repos/gems/src/test/decorator_stress/main.cc b/repos/gems/src/test/decorator_stress/main.cc
index 3f129d0b0a..289a0a70c3 100644
--- a/repos/gems/src/test/decorator_stress/main.cc
+++ b/repos/gems/src/test/decorator_stress/main.cc
@@ -45,30 +45,34 @@ struct Param
};
-void report_window_layout(Param param, Genode::Reporter &reporter)
+void report_window_layout(Param param, Genode::Expanding_reporter &reporter)
{
float w = 1024;
float h = 768;
- Genode::Reporter::Xml_generator xml(reporter, [&] ()
- {
- for (unsigned i = 1; i <= 10; i++) {
+ reporter.generate([&] (Genode::Xml_generator &xml) {
- xml.node("window", [&] ()
- {
- xml.attribute("id", i);
- xml.attribute("xpos", (long)(w * (0.25 + sin(param.angle[0])/5)));
- xml.attribute("ypos", (long)(h * (0.25 + sin(param.angle[1])/5)));
- xml.attribute("width", (long)(w * (0.25 + sin(param.angle[2])/5)));
- xml.attribute("height", (long)(h * (0.25 + sin(param.angle[3])/5)));
+ xml.node("boundary", [&] {
+ xml.attribute("width", unsigned(w));
+ xml.attribute("height", unsigned(h));
- if (i == 2)
- xml.attribute("focused", "yes");
- });
+ for (unsigned i = 1; i <= 10; i++) {
- param = param + Param(2.2, 3.3, 4.4, 5.5);
- }
+ xml.node("window", [&] {
+ xml.attribute("id", i);
+ xml.attribute("xpos", (long)(w * (0.25 + sin(param.angle[0])/5)));
+ xml.attribute("ypos", (long)(h * (0.25 + sin(param.angle[1])/5)));
+ xml.attribute("width", (long)(w * (0.25 + sin(param.angle[2])/5)));
+ xml.attribute("height", (long)(h * (0.25 + sin(param.angle[3])/5)));
+
+ if (i == 2)
+ xml.attribute("focused", "yes");
+ });
+
+ param = param + Param(2.2, 3.3, 4.4, 5.5);
+ }
+ });
});
}
@@ -79,7 +83,8 @@ struct Main
Param _param { 0, 1, 2, 3 };
- Genode::Reporter _window_layout_reporter { _env, "window_layout", "window_layout", 10*4096 };
+ Genode::Expanding_reporter _window_layout_reporter {
+ _env, "window_layout", "window_layout" };
Timer::Connection _timer { _env };
@@ -95,7 +100,6 @@ struct Main
Main(Genode::Env &env) : _env(env)
{
- _window_layout_reporter.enabled(true);
_timer.sigh(_timer_handler);
_timer.trigger_periodic(10*1000);
}
diff --git a/repos/os/include/decorator/types.h b/repos/os/include/decorator/types.h
index cd5c0c6a34..ad9df150fc 100644
--- a/repos/os/include/decorator/types.h
+++ b/repos/os/include/decorator/types.h
@@ -27,16 +27,12 @@
namespace Decorator {
- using Point = Genode::Surface_base::Point;
- using Area = Genode::Surface_base::Area;
- using Rect = Genode::Surface_base::Rect;
- using Dirty_rect = Genode::Dirty_rect;
+ using namespace Genode;
- using Genode::size_t;
- using Genode::Color;
- using Genode::Xml_node;
- using Genode::List_model;
- using Genode::Interface;
+ using Point = Surface_base::Point;
+ using Area = Surface_base::Area;
+ using Rect = Surface_base::Rect;
+ using Dirty_rect = Genode::Dirty_rect;
}
#endif /* _INCLUDE__DECORATOR__TYPES_H_ */
diff --git a/repos/os/include/decorator/window.h b/repos/os/include/decorator/window.h
index bc097c9de8..9746163574 100644
--- a/repos/os/include/decorator/window.h
+++ b/repos/os/include/decorator/window.h
@@ -20,6 +20,8 @@
#include
#include
#include
+#include
+#include
/* decorator includes */
#include
@@ -30,15 +32,49 @@ namespace Decorator {
class Canvas_base;
class Window_base;
- using Abandoned_windows = Genode::List >;
+ using Windows = Id_space;
+ using Abandoned_windows = Registry;
using Reversed_windows = Genode::List >;
}
-class Decorator::Window_base : private Genode::List_model::Element
+class Decorator::Window_base : private Windows::Element
{
public:
+ using Windows::Element::id;
+
+ struct Ref;
+
+ using Refs = List_model[;
+
+ /**
+ * Reference to a window
+ *
+ * The 'Ref' type decouples the lifetime of window objects from
+ * the lifetimes of their surrounding boundaries. If a window
+ * moves from one boundary to another, the old 'Ref' vanishes and
+ * a new 'Ref' is created but the window object stays intact.
+ */
+ struct Ref : Refs::Element
+ {
+ Window_base &window;
+
+ Registry][::Element _registered;
+
+ inline Ref(Window_base &);
+
+ /**
+ * List_model::Element
+ */
+ inline bool matches(Xml_node const &) const;
+
+ /**
+ * List_model::Element
+ */
+ static bool type_matches(Xml_node const &) { return true; }
+ };
+
struct Border
{
unsigned top, left, right, bottom;
@@ -59,7 +95,7 @@ class Decorator::Window_base : private Genode::List_model::Element
maximizer = false,
unmaximizer = false;
- unsigned window_id = 0;
+ Windows::Id window_id { };
bool operator != (Hover const &other) const
{
@@ -84,7 +120,7 @@ class Decorator::Window_base : private Genode::List_model::Element
*/
struct Draw_behind_fn : Interface
{
- virtual void draw_behind(Canvas_base &, Window_base const &, Rect) const = 0;
+ virtual void draw_behind(Canvas_base &, Ref const &, Rect) const = 0;
};
private:
@@ -93,16 +129,13 @@ class Decorator::Window_base : private Genode::List_model::Element
friend class Genode::List_model;
friend class Genode::List;
+ Registry][ _refs { };
+
/*
* Geometry of content
*/
Rect _geometry { };
- /*
- * Unique window ID
- */
- unsigned const _id;
-
bool _stacked = false;
/*
@@ -110,30 +143,42 @@ class Decorator::Window_base : private Genode::List_model::Element
*/
Genode::Constructible _neighbor { };
- Genode::List_element _abandoned { this };
+ Constructible _abandoned { };
Genode::List_element _reversed { this };
public:
- Window_base(unsigned id) : _id(id) { }
+ Window_base(Windows &windows, Windows::Id id)
+ :
+ Windows::Element(*this, windows, id)
+ { }
virtual ~Window_base() { }
- void abandon(Abandoned_windows &abandoned_windows)
+ bool referenced() const
{
- abandoned_windows.insert(&_abandoned);
+ bool result = false;
+ _refs.for_each([&] (Ref const &) { result = true; });
+ return result;
}
+ void consider_as_abandoned(Abandoned_windows ®istry)
+ {
+ _abandoned.construct(registry, *this);
+ }
+
+ /**
+ * Revert 'consider_as_abandoned' after window was temporarily not referenced
+ */
+ void dont_abandon() { _abandoned.destruct(); }
+
void prepend_to_reverse_list(Reversed_windows &window_list)
{
window_list.insert(&_reversed);
}
- using List_model::Element::next;
-
- unsigned id() const { return _id; }
- Rect geometry() const { return _geometry; }
+ Rect geometry() const { return _geometry; }
void stacking_neighbor(Gui::View_id neighbor)
{
@@ -169,11 +214,8 @@ class Decorator::Window_base : private Genode::List_model::Element
/**
* Draw window elements
- *
- * \param canvas graphics back end
- * \param clip clipping area to apply
*/
- virtual void draw(Canvas_base &canvas, Rect clip, Draw_behind_fn const &) const = 0;
+ virtual void draw(Canvas_base &, Ref const &, Rect clip, Draw_behind_fn const &) const = 0;
/**
* Update internal window representation from XML model
@@ -187,7 +229,9 @@ class Decorator::Window_base : private Genode::List_model::Element
*/
virtual bool update(Xml_node window_node) = 0;
- virtual void update_gui_views() { }
+ struct Clip : Rect { };
+
+ virtual void update_gui_views(Clip const &) { }
/**
* Report information about element at specified position
@@ -207,7 +251,7 @@ class Decorator::Window_base : private Genode::List_model::Element
*/
bool matches(Xml_node const &node) const
{
- return _id == node.attribute_value("id", ~0UL);
+ return id() == Windows::Id { node.attribute_value("id", ~0UL) };
}
/**
@@ -216,4 +260,16 @@ class Decorator::Window_base : private Genode::List_model::Element
static bool type_matches(Xml_node const &) { return true; }
};
+
+Decorator::Window_base::Ref::Ref(Window_base &window)
+:
+ window(window), _registered(window._refs, *this)
+{ }
+
+
+bool Decorator::Window_base::Ref::matches(Xml_node const &node) const
+{
+ return window.id() == Windows::Id { node.attribute_value("id", ~0UL) };
+}
+
#endif /* _INCLUDE__DECORATOR__WINDOW_H_ */
diff --git a/repos/os/include/decorator/window_factory.h b/repos/os/include/decorator/window_factory.h
index 967bba4003..a64ef45672 100644
--- a/repos/os/include/decorator/window_factory.h
+++ b/repos/os/include/decorator/window_factory.h
@@ -24,8 +24,13 @@ namespace Decorator {
struct Decorator::Window_factory_base : Interface
{
- virtual Window_base *create (Xml_node) = 0;
- virtual void destroy (Window_base *) = 0;
+ using Win_ref = Window_base::Ref;
+
+ virtual Win_ref &create_ref(Xml_node const &) = 0;
+
+ virtual void destroy_ref(Win_ref &) = 0;
+
+ virtual void destroy_window(Window_base &) = 0;
};
#endif /* _INCLUDE__DECORATOR__WINDOW_FACTORY_H_ */
diff --git a/repos/os/include/decorator/window_stack.h b/repos/os/include/decorator/window_stack.h
index e305a84d49..99c0a68301 100644
--- a/repos/os/include/decorator/window_stack.h
+++ b/repos/os/include/decorator/window_stack.h
@@ -17,6 +17,7 @@
/* Genode includes */
#include
#include
+#include
/* local includes */
#include
@@ -31,13 +32,102 @@ class Decorator::Window_stack : public Window_base::Draw_behind_fn
{
private:
- List_model _windows { };
- Window_factory_base &_window_factory;
- Dirty_rect mutable _dirty_rect { };
+ struct Boundary;
+ using Boundaries = List_model;
- unsigned long _front_most_id = ~0UL;
+ using Abandoned_boundaries = Registry;
- inline void _draw_rec(Canvas_base &canvas, Window_base const *win,
+ using Win_ref = Window_base::Ref;
+
+ struct Boundary : Boundaries::Element
+ {
+ using Name = Genode::String<64>;
+
+ Name const _name;
+
+ Constructible::Element> _abandoned { };
+
+ Rect rect { };
+
+ List_model win_refs { };
+
+ Boundary(Name const &name) : _name(name) { }
+
+ void update(Window_factory_base &factory,
+ Abandoned_windows &abandoned_windows,
+ Dirty_rect &dirty_rect,
+ Xml_node const &boundary)
+ {
+ rect = Rect::from_xml(boundary);
+
+ win_refs.update_from_xml(boundary,
+
+ [&] (Xml_node const &node) -> Win_ref & {
+ return factory.create_ref(node); },
+
+ [&] (Win_ref &ref) {
+ Window_base &window = ref.window;
+ factory.destroy_ref(ref);
+ if (!window.referenced())
+ window.consider_as_abandoned(abandoned_windows);
+ },
+
+ [&] (Win_ref &ref, Xml_node const &node) {
+ Rect const orig_geometry = ref.window.outer_geometry();
+ if (ref.window.update(node)) {
+ dirty_rect.mark_as_dirty(orig_geometry);
+ dirty_rect.mark_as_dirty(ref.window.outer_geometry());
+ }
+ }
+ );
+ }
+
+ void abandon(Registry ®istry)
+ {
+ _abandoned.construct(registry, *this);
+ }
+
+ static Name name(Xml_node const &node)
+ {
+ return node.attribute_value("name", Name());
+ }
+
+ /**
+ * List_model::Element
+ */
+ bool matches(Xml_node const &node) const
+ {
+ return _name == name(node);
+ }
+
+ /**
+ * List_model::Element
+ */
+ static bool type_matches(Xml_node const &node)
+ {
+ return node.has_type("boundary");
+ }
+
+ /**
+ * Generate window list in reverse order
+ */
+ Reversed_windows reversed_window_list()
+ {
+ Reversed_windows reversed { };
+ win_refs.for_each([&] (Win_ref &ref) {
+ ref.window.prepend_to_reverse_list(reversed); });
+ return reversed;
+ }
+ };
+
+ Boundaries _boundaries { };
+ Window_factory_base &_window_factory;
+ Allocator &_alloc;
+ Dirty_rect mutable _dirty_rect { };
+
+ Windows::Id _front_most_id { ~0UL };
+
+ inline void _draw_rec(Canvas_base &canvas, Win_ref const *,
Rect rect) const;
static inline
@@ -54,33 +144,38 @@ class Decorator::Window_stack : public Window_base::Draw_behind_fn
throw Xml_node::Nonexistent_sub_node();
}
- /**
- * Generate window list in reverse order
- */
- Reversed_windows _reversed_window_list()
+ void _for_each_window_const(auto const &fn) const
{
- Reversed_windows reversed { };
- _windows.for_each([&] (Window_base &window) {
- window.prepend_to_reverse_list(reversed); });
- return reversed;
+ _boundaries.for_each([&] (Boundary const &boundary) {
+ boundary.win_refs.for_each([&] (Win_ref const &ref) {
+ fn(ref.window); }); });
}
public:
- Window_stack(Window_factory_base &window_factory)
+ Window_stack(Window_factory_base &window_factory, Allocator &alloc)
:
- _window_factory(window_factory)
+ _window_factory(window_factory), _alloc(alloc)
{ }
void mark_as_dirty(Rect rect) { _dirty_rect.mark_as_dirty(rect); }
+ void for_each_window(auto const &fn)
+ {
+ _boundaries.for_each([&] (Boundary &boundary) {
+ boundary.win_refs.for_each([&] (Win_ref &ref) {
+ fn(ref.window); }); });
+ }
+
Dirty_rect draw(Canvas_base &canvas) const
{
Dirty_rect result = _dirty_rect;
_dirty_rect.flush([&] (Rect const &rect) {
- _windows.with_first([&] (Window_base const &first) {
- _draw_rec(canvas, &first, rect); }); });
+ _boundaries.for_each([&] (Boundary const &boundary) {
+ Rect const clipped = Rect::intersect(rect, boundary.rect);
+ boundary.win_refs.with_first([&] (Win_ref const &first) {
+ _draw_rec(canvas, &first, clipped); }); }); });
return result;
}
@@ -91,8 +186,7 @@ class Decorator::Window_stack : public Window_base::Draw_behind_fn
{
bool redraw_needed = false;
- _windows.for_each([&] (Window_base const &win) {
-
+ _for_each_window_const([&] (Window_base const &win) {
if (win.animated()) {
_dirty_rect.mark_as_dirty(win.outer_geometry());
redraw_needed = true;
@@ -101,41 +195,37 @@ class Decorator::Window_stack : public Window_base::Draw_behind_fn
return redraw_needed;
}
- /**
- * Apply functor to each window
- *
- * The functor is called with 'Window_base &' as argument.
- */
- void for_each_window(auto const &fn) { _windows.for_each(fn); }
-
void update_gui_views()
{
- /*
- * Update GUI views in reverse order (back-most first). The
- * reverse order is important because the stacking position of a
- * view is propagated by referring to the neighbor the view is in
- * front of. By starting with the back-most view, we make sure that
- * each view is always at its final stacking position when
- * specified as neighbor of another view.
- */
- Reversed_windows reversed = _reversed_window_list();
+ _boundaries.for_each([&] (Boundary &boundary) {
- while (Genode::List_element *win = reversed.first()) {
- win->object()->update_gui_views();
- reversed.remove(win);
- }
+ /*
+ * Update GUI views in reverse order (back-most first). The
+ * reverse order is important because the stacking position of
+ * a view is propagated by referring to the neighbor the view
+ * is in front of. By starting with the back-most view, we make
+ * sure that each view is always at its final stacking position
+ * when specified as neighbor of another view.
+ */
+ Reversed_windows reversed = boundary.reversed_window_list();
+
+ while (Genode::List_element *win = reversed.first()) {
+ win->object()->update_gui_views({ boundary.rect });
+ reversed.remove(win);
+ }
+ });
}
Window_base::Hover hover(Point pos) const
{
Window_base::Hover result { };
- _windows.for_each([&] (Window_base const &win) {
+ _for_each_window_const([&] (Window_base const &win) {
- if (!result.window_id && win.outer_geometry().contains(pos)) {
+ if (!result.window_id.value && win.outer_geometry().contains(pos)) {
Window_base::Hover const hover = win.hover(pos);
- if (hover.window_id != 0)
+ if (hover.window_id.value != 0)
result = hover;
}
});
@@ -148,28 +238,27 @@ class Decorator::Window_stack : public Window_base::Draw_behind_fn
** Window::Draw_behind_fn interface **
**************************************/
- void draw_behind(Canvas_base &canvas, Window_base const &window, Rect clip) const override
+ void draw_behind(Canvas_base &canvas, Win_ref const &ref, Rect clip) const override
{
- _draw_rec(canvas, window.next(), clip);
+ _draw_rec(canvas, ref.next(), clip);
}
};
-void Decorator::Window_stack::_draw_rec(Decorator::Canvas_base &canvas,
- Decorator::Window_base const *win,
- Decorator::Rect rect) const
+void Decorator::Window_stack::_draw_rec(Canvas_base &canvas,
+ Win_ref const *ref, Rect rect) const
{
Rect clipped;
/* find next window that intersects with the rectangle */
- for ( ; win && !(clipped = Rect::intersect(win->outer_geometry(), rect)).valid(); )
- win = win->next();
+ for ( ; ref && !(clipped = Rect::intersect(ref->window.outer_geometry(), rect)).valid(); )
+ ref = ref->next();
/* check if we hit the bottom of the window stack */
- if (!win) return;
+ if (!ref) return;
/* draw areas around the current window */
- if (Window_base const * const next = win->next()) {
+ if (Window_base::Ref const * const next = ref->next()) {
Rect::Cut_remainder const r = rect.cut(clipped);
@@ -180,50 +269,41 @@ void Decorator::Window_stack::_draw_rec(Decorator::Canvas_base &canvas,
}
/* draw current window */
- win->draw(canvas, clipped, *this);
+ ref->window.draw(canvas, *ref, clipped, *this);
}
void Decorator::Window_stack::update_model(Genode::Xml_node root_node,
auto const &flush_window_stack_changes_fn)
{
- Abandoned_windows _abandoned_windows { };
+ Abandoned_boundaries abandoned_boundaries { };
+ Abandoned_windows abandoned_windows { };
- _windows.update_from_xml(root_node,
+ _boundaries.update_from_xml(root_node,
- [&] (Xml_node const &node) -> Window_base & {
- return *_window_factory.create(node); },
+ [&] (Xml_node const &node) -> Boundary & {
+ return *new (_alloc) Boundary(Boundary::name(node)); },
- [&] (Window_base &window) { window.abandon(_abandoned_windows); },
+ [&] (Boundary &boundary) {
+ boundary.update(_window_factory, abandoned_windows, _dirty_rect,
+ Xml_node(""));
+ boundary.abandon(abandoned_boundaries);
+ },
- [&] (Window_base &window, Xml_node const &node)
- {
- Rect const orig_geometry = window.outer_geometry();
-
- if (window.update(node)) {
- _dirty_rect.mark_as_dirty(orig_geometry);
- _dirty_rect.mark_as_dirty(window.outer_geometry());
- }
- }
+ [&] (Boundary &boundary, Xml_node const &node) {
+ boundary.update(_window_factory, abandoned_windows, _dirty_rect, node); }
);
- unsigned long new_front_most_id = ~0UL;
- if (root_node.has_sub_node("window"))
- new_front_most_id = root_node.sub_node("window").attribute_value("id", ~0UL);
+ Windows::Id new_front_most_id { ~0UL };
- /*
- * Propagate changed stacking order to the GUI server
- *
- * First, we reverse the window list. The 'reversed' list starts with
- * the back-most window. We then go throuh each window back to front
- * and check if its neighbor is consistent with its position in the
- * window list.
- */
- Reversed_windows reversed = _reversed_window_list();
+ _boundaries.with_first([&] (Boundary const &boundary) {
+ boundary.win_refs.with_first([&] (Window_base::Ref const &ref) {
+ new_front_most_id = ref.window.id(); }); });
/* return true if window just came to front */
auto new_front_most_window = [&] (Window_base const &win) {
- return (new_front_most_id != _front_most_id) && (win.id() == new_front_most_id); };
+ return (new_front_most_id.value != _front_most_id.value)
+ && (win.id() == new_front_most_id); };
auto stack_back_most_window = [&] (Window_base &window) {
@@ -251,27 +331,40 @@ void Decorator::Window_stack::update_model(Genode::Xml_node root_node,
_dirty_rect.mark_as_dirty(window.outer_geometry());
};
- if (Genode::List_element *back_most = reversed.first()) {
+ _boundaries.for_each([&] (Boundary &boundary) {
- /* handle back-most window */
- reversed.remove(back_most);
- Window_base &window = *back_most->object();
- stack_back_most_window(window);
- window.forget_neighbor();
+ /*
+ * Propagate changed stacking order to the GUI server
+ *
+ * First, we reverse the window list. The 'reversed' list starts with
+ * the back-most window. We then go throuh each window back to front
+ * and check if its neighbor is consistent with its position in the
+ * window list.
+ */
+ Reversed_windows reversed = boundary.reversed_window_list();
- Window_base *neighbor = &window;
+ if (Genode::List_element *back_most = reversed.first()) {
- /* check consistency between window list order and view stacking */
- while (Genode::List_element *elem = reversed.first()) {
+ /* handle back-most window */
+ reversed.remove(back_most);
+ Window_base &window = *back_most->object();
+ stack_back_most_window(window);
+ window.forget_neighbor();
- reversed.remove(elem);
+ Window_base *neighbor = &window;
- Window_base &window = *elem->object();
- stack_window(window, *neighbor);
- window.stacking_neighbor(neighbor->frontmost_view());
- neighbor = &window;
+ /* check consistency between window list order and view stacking */
+ while (Genode::List_element *elem = reversed.first()) {
+
+ reversed.remove(elem);
+
+ Window_base &window = *elem->object();
+ stack_window(window, *neighbor);
+ window.stacking_neighbor(neighbor->frontmost_view());
+ neighbor = &window;
+ }
}
- }
+ });
/*
* Apply window-creation operations before destroying windows to prevent
@@ -280,7 +373,7 @@ void Decorator::Window_stack::update_model(Genode::Xml_node root_node,
flush_window_stack_changes_fn();
/*
- * Destroy abandoned window objects
+ * Destroy abandoned window and boundary objects
*
* This is done after all other operations to avoid flickering whenever one
* window is replaced by another one. If we first destroyed the original
@@ -289,12 +382,19 @@ void Decorator::Window_stack::update_model(Genode::Xml_node root_node,
* point when the new one already exists, one of both windows is visible at
* all times.
*/
- Genode::List_element *elem = _abandoned_windows.first(), *next = nullptr;
- for (; elem; elem = next) {
- next = elem->next();
- _dirty_rect.mark_as_dirty(elem->object()->outer_geometry());
- _window_factory.destroy(elem->object());
- }
+
+ abandoned_boundaries.for_each([&] (Boundary &boundary) {
+ destroy(_alloc, &boundary); });
+
+ abandoned_windows.for_each([&] (Window_base &window) {
+ if (window.referenced()) {
+ window.dont_abandon();
+ } else {
+ Rect const rect = window.outer_geometry();
+ _window_factory.destroy_window(window);
+ mark_as_dirty(rect);
+ }
+ });
_front_most_id = new_front_most_id;
}
]