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; } /**