mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-15 15:07:16 +00:00
window_layouter: allow screen-change during drag
This patch enables the user to interactively change the assignment of windows to screens. For screens visible side by side in a multi-monitor setup, one can now move a window from one screen to another by dragging the window title. When using screens as virtual desktops on one display, a window can be moved to another screen by switching the screen (by pressing a key matching a desired screen) while the window is dragged with the mouse. So the user can drag the window between virtual desktops. Issue #5390
This commit is contained in:
parent
8496d5b02a
commit
ca1b22b0aa
@ -45,4 +45,31 @@
|
||||
<press key="KEY_9" action="screen" target="screen_9"/>
|
||||
<press key="KEY_0" action="screen" target="screen_0"/>
|
||||
</press>
|
||||
|
||||
<!-- support switching screens while dragging a window -->
|
||||
<press key="BTN_LEFT">
|
||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||
<press key="KEY_2" action="screen" target="screen_2"/>
|
||||
<press key="KEY_3" action="screen" target="screen_3"/>
|
||||
<press key="KEY_4" action="screen" target="screen_4"/>
|
||||
<press key="KEY_5" action="screen" target="screen_5"/>
|
||||
<press key="KEY_6" action="screen" target="screen_6"/>
|
||||
<press key="KEY_7" action="screen" target="screen_7"/>
|
||||
<press key="KEY_8" action="screen" target="screen_8"/>
|
||||
<press key="KEY_9" action="screen" target="screen_9"/>
|
||||
<press key="KEY_0" action="screen" target="screen_0"/>
|
||||
<press key="KEY_SCREEN">
|
||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||
<press key="KEY_2" action="screen" target="screen_2"/>
|
||||
<press key="KEY_3" action="screen" target="screen_3"/>
|
||||
<press key="KEY_4" action="screen" target="screen_4"/>
|
||||
<press key="KEY_5" action="screen" target="screen_5"/>
|
||||
<press key="KEY_6" action="screen" target="screen_6"/>
|
||||
<press key="KEY_7" action="screen" target="screen_7"/>
|
||||
<press key="KEY_8" action="screen" target="screen_8"/>
|
||||
<press key="KEY_9" action="screen" target="screen_9"/>
|
||||
<press key="KEY_0" action="screen" target="screen_0"/>
|
||||
</press>
|
||||
</press>
|
||||
|
||||
</config>
|
||||
|
@ -45,4 +45,31 @@
|
||||
<press key="KEY_9" action="screen" target="screen_9"/>
|
||||
<press key="KEY_0" action="screen" target="screen_0"/>
|
||||
</press>
|
||||
|
||||
<!-- support switching screens while dragging a window -->
|
||||
<press key="BTN_LEFT">
|
||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||
<press key="KEY_2" action="screen" target="screen_2"/>
|
||||
<press key="KEY_3" action="screen" target="screen_3"/>
|
||||
<press key="KEY_4" action="screen" target="screen_4"/>
|
||||
<press key="KEY_5" action="screen" target="screen_5"/>
|
||||
<press key="KEY_6" action="screen" target="screen_6"/>
|
||||
<press key="KEY_7" action="screen" target="screen_7"/>
|
||||
<press key="KEY_8" action="screen" target="screen_8"/>
|
||||
<press key="KEY_9" action="screen" target="screen_9"/>
|
||||
<press key="KEY_0" action="screen" target="screen_0"/>
|
||||
<press key="KEY_SCREEN">
|
||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||
<press key="KEY_2" action="screen" target="screen_2"/>
|
||||
<press key="KEY_3" action="screen" target="screen_3"/>
|
||||
<press key="KEY_4" action="screen" target="screen_4"/>
|
||||
<press key="KEY_5" action="screen" target="screen_5"/>
|
||||
<press key="KEY_6" action="screen" target="screen_6"/>
|
||||
<press key="KEY_7" action="screen" target="screen_7"/>
|
||||
<press key="KEY_8" action="screen" target="screen_8"/>
|
||||
<press key="KEY_9" action="screen" target="screen_9"/>
|
||||
<press key="KEY_0" action="screen" target="screen_0"/>
|
||||
</press>
|
||||
</press>
|
||||
|
||||
</config>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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()))
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -333,6 +333,8 @@ class Window_layouter::Window : public List_model<Window>::Element
|
||||
|
||||
void resizeable(bool resizeable) { _resizeable = resizeable; }
|
||||
|
||||
bool resizeable() const { return _resizeable; }
|
||||
|
||||
bool label_matches(Label const &label) const { return label == _label; }
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user