mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-04 05:21:19 +00:00
window_layouter: "pick_up" and "place_down" action
The new 'action' attribute values can be used to realize the keyboard-based assignement of windows to screens. The "pick_up" action (on a key press) selects the focused window to be held at the current position until the "place_down" action is issued (by a key release). While the focused window is held, "screen" actions can be executed taking the picked up window to the selected screen. Issue #5390
This commit is contained in:
parent
d9e49a5c03
commit
248c37784b
@ -26,12 +26,23 @@
|
|||||||
</release>
|
</release>
|
||||||
<release key="KEY_SCREEN" action="raise_window"/>
|
<release key="KEY_SCREEN" action="raise_window"/>
|
||||||
</press>
|
</press>
|
||||||
<press key="KEY_LEFTSHIFT">
|
<press key="KEY_LEFTSHIFT" action="pick_up">
|
||||||
<press key="KEY_TAB" action="prev_window">
|
<press key="KEY_TAB" action="prev_window">
|
||||||
<release key="KEY_TAB">
|
<release key="KEY_TAB">
|
||||||
<release key="KEY_SCREEN" action="raise_window"/>
|
<release key="KEY_SCREEN" action="raise_window"/>
|
||||||
</release>
|
</release>
|
||||||
</press>
|
</press>
|
||||||
|
<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"/>
|
||||||
|
<release key="KEY_LEFTSHIFT" action="place_down"/>
|
||||||
</press>
|
</press>
|
||||||
<press key="KEY_ENTER" action="toggle_fullscreen"/>
|
<press key="KEY_ENTER" action="toggle_fullscreen"/>
|
||||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||||
|
@ -26,12 +26,23 @@
|
|||||||
</release>
|
</release>
|
||||||
<release key="KEY_SCREEN" action="raise_window"/>
|
<release key="KEY_SCREEN" action="raise_window"/>
|
||||||
</press>
|
</press>
|
||||||
<press key="KEY_LEFTSHIFT">
|
<press key="KEY_LEFTSHIFT" action="pick_up">
|
||||||
<press key="KEY_TAB" action="prev_window">
|
<press key="KEY_TAB" action="prev_window">
|
||||||
<release key="KEY_TAB">
|
<release key="KEY_TAB">
|
||||||
<release key="KEY_SCREEN" action="raise_window"/>
|
<release key="KEY_SCREEN" action="raise_window"/>
|
||||||
</release>
|
</release>
|
||||||
</press>
|
</press>
|
||||||
|
<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"/>
|
||||||
|
<release key="KEY_LEFTSHIFT" action="place_down"/>
|
||||||
</press>
|
</press>
|
||||||
<press key="KEY_ENTER" action="toggle_fullscreen"/>
|
<press key="KEY_ENTER" action="toggle_fullscreen"/>
|
||||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||||
|
@ -22,7 +22,7 @@ namespace Window_layouter { class Command; }
|
|||||||
struct Window_layouter::Command
|
struct Window_layouter::Command
|
||||||
{
|
{
|
||||||
enum Type { NONE, NEXT_WINDOW, PREV_WINDOW, RAISE_WINDOW, TOGGLE_FULLSCREEN,
|
enum Type { NONE, NEXT_WINDOW, PREV_WINDOW, RAISE_WINDOW, TOGGLE_FULLSCREEN,
|
||||||
NEXT_TAB, PREV_TAB, SCREEN, RELEASE_GRAB, };
|
NEXT_TAB, PREV_TAB, SCREEN, RELEASE_GRAB, PICK_UP, PLACE_DOWN };
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
Target::Name target;
|
Target::Name target;
|
||||||
@ -37,6 +37,8 @@ struct Window_layouter::Command
|
|||||||
if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN;
|
if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN;
|
||||||
if (string == "screen") return SCREEN;
|
if (string == "screen") return SCREEN;
|
||||||
if (string == "release_grab") return RELEASE_GRAB;
|
if (string == "release_grab") return RELEASE_GRAB;
|
||||||
|
if (string == "pick_up") return PICK_UP;
|
||||||
|
if (string == "place_down") return PLACE_DOWN;
|
||||||
|
|
||||||
warning("cannot convert \"", string, "\" to action type");
|
warning("cannot convert \"", string, "\" to action type");
|
||||||
return NONE;
|
return NONE;
|
||||||
|
@ -48,6 +48,7 @@ struct Window_layouter::Main : User_state::Action,
|
|||||||
Timer::Connection _drop_timer { _env };
|
Timer::Connection _drop_timer { _env };
|
||||||
|
|
||||||
Drag _drag { };
|
Drag _drag { };
|
||||||
|
Pick _pick { };
|
||||||
|
|
||||||
Signal_handler<Main> _drop_timer_handler {
|
Signal_handler<Main> _drop_timer_handler {
|
||||||
_env.ep(), *this, &Main::_handle_drop_timer };
|
_env.ep(), *this, &Main::_handle_drop_timer };
|
||||||
@ -247,7 +248,7 @@ struct Window_layouter::Main : User_state::Action,
|
|||||||
fn(from, to); }); });
|
fn(from, to); }); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void _retarget_window(Window_id id, Target const &from, Target const &to)
|
void _with_retargeted_window(Window_id id, Target const &to, auto const &fn)
|
||||||
{
|
{
|
||||||
_assign_list.for_each([&] (Assign &assign) {
|
_assign_list.for_each([&] (Assign &assign) {
|
||||||
Window *window_ptr = nullptr;
|
Window *window_ptr = nullptr;
|
||||||
@ -256,18 +257,44 @@ struct Window_layouter::Main : User_state::Action,
|
|||||||
window_ptr = &member.window; });
|
window_ptr = &member.window; });
|
||||||
if (window_ptr) {
|
if (window_ptr) {
|
||||||
assign.target_name = to.name;
|
assign.target_name = to.name;
|
||||||
window_ptr->warp(from.rect.at - to.rect.at);
|
fn(*window_ptr);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _retarget_window(Window_id id, Target const &to)
|
||||||
|
{
|
||||||
|
_with_retargeted_window(id, to, [&] (Window &) { });
|
||||||
|
}
|
||||||
|
|
||||||
|
void _retarget_and_warp_window(Window_id id, Target const &from, Target const &to)
|
||||||
|
{
|
||||||
|
_with_retargeted_window(id, to, [&] (Window &window) {
|
||||||
|
window.warp(from.rect.at - to.rect.at); });
|
||||||
|
}
|
||||||
|
|
||||||
void screen(Target::Name const &name) override
|
void screen(Target::Name const &name) override
|
||||||
{
|
{
|
||||||
|
auto with_visible_geometry = [&] (Rect orig, Area target_area, auto const &fn)
|
||||||
|
{
|
||||||
|
Area const overlap = Rect::intersect(orig, { { }, target_area }).area;
|
||||||
|
bool const visible = (overlap.w > 50) && (overlap.h > 50);
|
||||||
|
|
||||||
|
fn(visible ? orig : Rect { { }, orig.area });
|
||||||
|
};
|
||||||
|
|
||||||
|
/* change screen under picked window */
|
||||||
|
if (_pick.picked)
|
||||||
|
_with_target_change(_pick.window_id, name, [&] (Target const &, Target const &to) {
|
||||||
|
_with_retargeted_window(_pick.window_id, to, [&] (Window &window) {
|
||||||
|
with_visible_geometry(_pick.orig_geometry, to.rect.area, [&] (Rect rect) {
|
||||||
|
window.outer_geometry(rect); }); }); });
|
||||||
|
|
||||||
/* change of screen under the dragged window */
|
/* change of screen under the dragged window */
|
||||||
if (_drag.dragging())
|
if (_drag.dragging())
|
||||||
_with_target_change(_drag.window_id, name, [&] (Target const &from, Target const &to) {
|
_with_target_change(_drag.window_id, name, [&] (Target const &from, Target const &to) {
|
||||||
if (from.rect == to.rect)
|
if (from.rect == to.rect)
|
||||||
_retarget_window(_drag.window_id, from, to); });
|
_retarget_window(_drag.window_id, to); });
|
||||||
|
|
||||||
/* repeated activation of screen moves focus to the screen */
|
/* repeated activation of screen moves focus to the screen */
|
||||||
bool already_visible = false;
|
bool already_visible = false;
|
||||||
@ -287,6 +314,18 @@ struct Window_layouter::Main : User_state::Action,
|
|||||||
_gen_rules_with_frontmost_screen(name);
|
_gen_rules_with_frontmost_screen(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pick_up(Window_id id) override
|
||||||
|
{
|
||||||
|
_window_list.with_window(id, [&] (Window const &window) {
|
||||||
|
_pick = { .picked = true,
|
||||||
|
.window_id = id,
|
||||||
|
.orig_geometry = window.outer_geometry() };
|
||||||
|
to_front(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void place_down() override { _pick = { }; }
|
||||||
|
|
||||||
void drag(Window_id id, Window::Element element, Point clicked, Point curr) override
|
void drag(Window_id id, Window::Element element, Point clicked, Point curr) override
|
||||||
{
|
{
|
||||||
if (_drag.state == Drag::State::SETTLING)
|
if (_drag.state == Drag::State::SETTLING)
|
||||||
@ -362,7 +401,7 @@ struct Window_layouter::Main : User_state::Action,
|
|||||||
_target_list.with_target_at(curr, [&] (Target const &pointed) {
|
_target_list.with_target_at(curr, [&] (Target const &pointed) {
|
||||||
_drag = { Drag::State::SETTLING, moving, id, curr, pointed.rect };
|
_drag = { Drag::State::SETTLING, moving, id, curr, pointed.rect };
|
||||||
_with_target_change(id, pointed.name, [&] (Target const &from, Target const &to) {
|
_with_target_change(id, pointed.name, [&] (Target const &from, Target const &to) {
|
||||||
_retarget_window(id, from, to); });
|
_retarget_and_warp_window(id, from, to); });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,13 @@ namespace Window_layouter {
|
|||||||
return dragging() && id == window_id && moving;
|
return dragging() && id == window_id && moving;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Pick
|
||||||
|
{
|
||||||
|
bool picked;
|
||||||
|
Window_id window_id;
|
||||||
|
Rect orig_geometry;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _TYPES_H_ */
|
#endif /* _TYPES_H_ */
|
||||||
|
@ -34,6 +34,8 @@ class Window_layouter::User_state
|
|||||||
virtual void to_front(Window_id) = 0;
|
virtual void to_front(Window_id) = 0;
|
||||||
virtual void drag(Window_id, Window::Element, Point clicked, Point curr) = 0;
|
virtual void drag(Window_id, Window::Element, Point clicked, Point curr) = 0;
|
||||||
virtual void finalize_drag(Window_id, Window::Element, Point clicked, Point final) = 0;
|
virtual void finalize_drag(Window_id, Window::Element, Point clicked, Point final) = 0;
|
||||||
|
virtual void pick_up(Window_id) = 0;
|
||||||
|
virtual void place_down() = 0;
|
||||||
virtual void screen(Target::Name const &) = 0;
|
virtual void screen(Target::Name const &) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,6 +78,8 @@ class Window_layouter::User_state
|
|||||||
*/
|
*/
|
||||||
bool _drag_init_done = false;
|
bool _drag_init_done = false;
|
||||||
|
|
||||||
|
bool _picked_up = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer position at the beginning of a drag operation
|
* Pointer position at the beginning of a drag operation
|
||||||
*/
|
*/
|
||||||
@ -168,7 +172,7 @@ class Window_layouter::User_state
|
|||||||
|
|
||||||
void hover(Window_id window_id, Window::Element element)
|
void hover(Window_id window_id, Window::Element element)
|
||||||
{
|
{
|
||||||
Window_id const last_hovered_window_id = _hovered_window_id;
|
Window_id const orig_hovered_window_id = _hovered_window_id;
|
||||||
|
|
||||||
_hovered_window_id = window_id;
|
_hovered_window_id = window_id;
|
||||||
_hovered_element = element;
|
_hovered_element = element;
|
||||||
@ -192,10 +196,11 @@ class Window_layouter::User_state
|
|||||||
_initiate_drag(_hovered_window_id, _hovered_element);
|
_initiate_drag(_hovered_window_id, _hovered_element);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let focus follows the pointer
|
* Let focus follows the pointer, except while dragging or when
|
||||||
|
* the focused window is currently picked up.
|
||||||
*/
|
*/
|
||||||
if (!_drag_state && _hovered_window_id.valid()
|
if (!_drag_state && !_picked_up && _hovered_window_id.valid()
|
||||||
&& _hovered_window_id != last_hovered_window_id) {
|
&& _hovered_window_id != orig_hovered_window_id) {
|
||||||
|
|
||||||
_focused_window_id = _hovered_window_id;
|
_focused_window_id = _hovered_window_id;
|
||||||
_focus_history.focus(_focused_window_id);
|
_focus_history.focus(_focused_window_id);
|
||||||
@ -329,6 +334,20 @@ void Window_layouter::User_state::_handle_event(Input::Event const &e,
|
|||||||
_action.release_grab();
|
_action.release_grab();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case Command::PICK_UP:
|
||||||
|
if (_focused_window_id.value) {
|
||||||
|
_picked_up = true;
|
||||||
|
_action.pick_up(_focused_window_id);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Command::PLACE_DOWN:
|
||||||
|
if (_picked_up) {
|
||||||
|
_action.place_down();
|
||||||
|
_picked_up = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
warning("command ", (int)command.type, " unhanded");
|
warning("command ", (int)command.type, " unhanded");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user