diff --git a/repos/gems/recipes/raw/motif_wm/layouter.config b/repos/gems/recipes/raw/motif_wm/layouter.config
index 76a71de991..1631c5ccc9 100644
--- a/repos/gems/recipes/raw/motif_wm/layouter.config
+++ b/repos/gems/recipes/raw/motif_wm/layouter.config
@@ -45,4 +45,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/repos/gems/recipes/raw/window_layouter/window_layouter.config b/repos/gems/recipes/raw/window_layouter/window_layouter.config
index 76a71de991..1631c5ccc9 100644
--- a/repos/gems/recipes/raw/window_layouter/window_layouter.config
+++ b/repos/gems/recipes/raw/window_layouter/window_layouter.config
@@ -45,4 +45,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/repos/gems/src/app/window_layouter/main.cc b/repos/gems/src/app/window_layouter/main.cc
index c524b7d640..167b66f854 100644
--- a/repos/gems/src/app/window_layouter/main.cc
+++ b/repos/gems/src/app/window_layouter/main.cc
@@ -213,8 +213,36 @@ struct Window_layouter::Main : Operations,
_gen_resize_request();
}
- void screen(Target::Name const & name) override
+ void _with_target_change(Window_id id, Target::Name to_name, auto const &fn) const
{
+ _target_list.with_target(_assign_list, id, [&] (Target const &from) {
+ _target_list.with_target(to_name, [&] (Target const &to) {
+ if (&from != &to)
+ fn(from, to); }); });
+ }
+
+ void _retarget_window(Window_id id, Target const &from, Target const &to)
+ {
+ _assign_list.for_each([&] (Assign &assign) {
+ Window *window_ptr = nullptr;
+ assign.for_each_member([&] (Assign::Member &member) {
+ if (member.window.id() == id)
+ window_ptr = &member.window; });
+ if (window_ptr) {
+ assign.target_name = to.name();
+ window_ptr->warp(from.geometry().at - to.geometry().at);
+ }
+ });
+ }
+
+ void screen(Target::Name const &name) override
+ {
+ /* change of screen under the dragged window */
+ if (_drag.dragging())
+ _with_target_change(_drag.window_id, name, [&] (Target const &from, Target const &to) {
+ if (from.geometry() == to.geometry())
+ _retarget_window(_drag.window_id, from, to); });
+
_gen_rules_with_frontmost_screen(name);
}
@@ -223,9 +251,9 @@ struct Window_layouter::Main : Operations,
if (_drag.state == Drag::State::SETTLING)
return;
- _target_list.with_target_at(curr, [&] (Target const &pointed_target) {
- bool const moving = (element.type == Window::Element::TITLE);
- _drag = { Drag::State::DRAGGING, moving, id, curr, pointed_target.name() }; });
+ bool const moving = _moving(id, element);
+ _target_list.with_target_at(curr, [&] (Target const &pointed) {
+ _drag = { Drag::State::DRAGGING, moving, id, curr, pointed.geometry() }; });
to_front(id);
@@ -260,6 +288,18 @@ struct Window_layouter::Main : Operations,
window.finalize_drag_operation(); });
}
+ bool _moving(Window_id id, Window::Element element)
+ {
+ if (element.type == Window::Element::TITLE)
+ return true;
+
+ /* a non-resizeable window can be moved by dragging its border */
+ bool resizeable = false;
+ _window_list.with_window(id, [&] (Window const &window) {
+ resizeable = window.resizeable(); });
+ return !resizeable && element.resize_handle();
+ }
+
void finalize_drag(Window_id id, Window::Element element, Point, Point curr) override
{
/*
@@ -272,34 +312,19 @@ struct Window_layouter::Main : Operations,
_handle_hover();
_drag = { };
- _target_list.with_target_at(curr, [&] (Target const &pointed_target) {
- bool const moving = (element.type == Window::Element::TITLE);
- _drag = { Drag::State::SETTLING, moving, id, curr, pointed_target.name() }; });
/*
* Update the target of the assign rule of the dragged window
*/
- auto with_target_change = [&] (auto const fn)
- {
- _target_list.with_target(_assign_list, id, [&] (Target const &from) {
- _target_list.with_target(_drag.target, [&] (Target const &to) {
- if (&from != &to)
- fn(from, to); }); });
- };
- if (_drag.moving) {
- with_target_change([&] (Target const &from, Target const &to) {
- _assign_list.for_each([&] (Assign &assign) {
- Window *window_ptr = nullptr;
- assign.for_each_member([&] (Assign::Member &member) {
- if (member.window.id() == id)
- window_ptr = &member.window; });
- if (window_ptr) {
- assign.target_name = to.name();
- window_ptr->warp(from.geometry().at - to.geometry().at);
- }
- });
+ bool const moving = _moving(id, element);
+ if (moving) {
+ _target_list.with_target_at(curr, [&] (Target const &pointed) {
+ _drag = { Drag::State::SETTLING, moving, id, curr, pointed.geometry() };
+ _with_target_change(id, pointed.name(), [&] (Target const &from, Target const &to) {
+ _retarget_window(id, from, to); });
});
}
+
_drop_timer.trigger_once(250*1000);
}
diff --git a/repos/gems/src/app/window_layouter/target_list.h b/repos/gems/src/app/window_layouter/target_list.h
index d7f20806fc..9ec68f180f 100644
--- a/repos/gems/src/app/window_layouter/target_list.h
+++ b/repos/gems/src/app/window_layouter/target_list.h
@@ -147,7 +147,7 @@ class Window_layouter::Target_list
if (target.layer() >= min_layer && target.layer() <= layer)
layer = target.layer(); });
- Rect const drag_origin_boundary = drag.dragging()
+ Rect const drag_origin_boundary = drag.dragging() && drag.moving
? target_boundary(assignments, drag.window_id)
: Rect { };
/* search target by name */
@@ -159,7 +159,7 @@ class Window_layouter::Target_list
if (!target.visible())
return;
- if (assignments.target_empty(target.name()) && !drag.moving_at_target(target.name()))
+ if (assignments.target_empty(target.name()) && !drag.moving_at_target_rect(target.geometry()))
return;
Rect const boundary = target.geometry();
@@ -168,7 +168,7 @@ class Window_layouter::Target_list
generate(xml, boundary);
/* in-flux window node for the currently dragged window */
- if (drag.moving_at_target(target.name()))
+ if (drag.moving_at_target_rect(target.geometry()))
assignments.for_each([&] (Assign const &assign) {
assign.for_each_member([&] (Assign::Member const &member) {
if (drag.moving_window(member.window.id()))
diff --git a/repos/gems/src/app/window_layouter/types.h b/repos/gems/src/app/window_layouter/types.h
index 0383aeb1f0..205c336b0d 100644
--- a/repos/gems/src/app/window_layouter/types.h
+++ b/repos/gems/src/app/window_layouter/types.h
@@ -92,13 +92,13 @@ namespace Window_layouter {
bool moving; /* distiguish moving from resizing */
Window_id window_id;
Point curr_pos;
- Name target;
+ Rect target_rect;
bool dragging() const { return state == State::DRAGGING; }
- bool moving_at_target(Name const &name) const
+ bool moving_at_target_rect(Rect const &rect) const
{
- return dragging() && name == target && moving;
+ return dragging() && rect == target_rect && moving;
}
bool moving_window(Window_id id) const
diff --git a/repos/gems/src/app/window_layouter/user_state.h b/repos/gems/src/app/window_layouter/user_state.h
index 1d826390d3..95f03995bc 100644
--- a/repos/gems/src/app/window_layouter/user_state.h
+++ b/repos/gems/src/app/window_layouter/user_state.h
@@ -82,22 +82,9 @@ class Window_layouter::User_state
Focus_history &_focus_history;
/*
- * Return true if key is potentially part of a key sequence
+ * Return true if event is potentially part of a key sequence
*/
- static bool _key(Input::Keycode key) { return key != Input::BTN_LEFT; }
-
- bool _key(Input::Event const &ev) const
- {
- bool relevant = false;
-
- ev.handle_press([&] (Input::Keycode key, Codepoint) {
- relevant |= _key(key); });
-
- ev.handle_release([&] (Input::Keycode key) {
- relevant |= _key(key); });
-
- return relevant;
- }
+ bool _key(Input::Event const &ev) const { return ev.press() || ev.release(); }
inline void _handle_event(Input::Event const &, Xml_node);
diff --git a/repos/gems/src/app/window_layouter/window.h b/repos/gems/src/app/window_layouter/window.h
index d421f924e4..27622b93f6 100644
--- a/repos/gems/src/app/window_layouter/window.h
+++ b/repos/gems/src/app/window_layouter/window.h
@@ -333,6 +333,8 @@ class Window_layouter::Window : public List_model::Element
void resizeable(bool resizeable) { _resizeable = resizeable; }
+ bool resizeable() const { return _resizeable; }
+
bool label_matches(Label const &label) const { return label == _label; }
/**