mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-03 13:14:45 +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 key="KEY_SCREEN" action="raise_window"/>
|
||||
</press>
|
||||
<press key="KEY_LEFTSHIFT">
|
||||
<press key="KEY_LEFTSHIFT" action="pick_up">
|
||||
<press key="KEY_TAB" action="prev_window">
|
||||
<release key="KEY_TAB">
|
||||
<release key="KEY_SCREEN" action="raise_window"/>
|
||||
</release>
|
||||
</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 key="KEY_ENTER" action="toggle_fullscreen"/>
|
||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||
|
@ -26,12 +26,23 @@
|
||||
</release>
|
||||
<release key="KEY_SCREEN" action="raise_window"/>
|
||||
</press>
|
||||
<press key="KEY_LEFTSHIFT">
|
||||
<press key="KEY_LEFTSHIFT" action="pick_up">
|
||||
<press key="KEY_TAB" action="prev_window">
|
||||
<release key="KEY_TAB">
|
||||
<release key="KEY_SCREEN" action="raise_window"/>
|
||||
</release>
|
||||
</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 key="KEY_ENTER" action="toggle_fullscreen"/>
|
||||
<press key="KEY_1" action="screen" target="screen_1"/>
|
||||
|
@ -22,7 +22,7 @@ namespace Window_layouter { class Command; }
|
||||
struct Window_layouter::Command
|
||||
{
|
||||
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;
|
||||
Target::Name target;
|
||||
@ -37,6 +37,8 @@ struct Window_layouter::Command
|
||||
if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN;
|
||||
if (string == "screen") return SCREEN;
|
||||
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");
|
||||
return NONE;
|
||||
|
@ -48,6 +48,7 @@ struct Window_layouter::Main : User_state::Action,
|
||||
Timer::Connection _drop_timer { _env };
|
||||
|
||||
Drag _drag { };
|
||||
Pick _pick { };
|
||||
|
||||
Signal_handler<Main> _drop_timer_handler {
|
||||
_env.ep(), *this, &Main::_handle_drop_timer };
|
||||
@ -247,7 +248,7 @@ struct Window_layouter::Main : User_state::Action,
|
||||
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) {
|
||||
Window *window_ptr = nullptr;
|
||||
@ -256,18 +257,44 @@ struct Window_layouter::Main : User_state::Action,
|
||||
window_ptr = &member.window; });
|
||||
if (window_ptr) {
|
||||
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
|
||||
{
|
||||
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 */
|
||||
if (_drag.dragging())
|
||||
_with_target_change(_drag.window_id, name, [&] (Target const &from, Target const &to) {
|
||||
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 */
|
||||
bool already_visible = false;
|
||||
@ -287,6 +314,18 @@ struct Window_layouter::Main : User_state::Action,
|
||||
_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
|
||||
{
|
||||
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) {
|
||||
_drag = { Drag::State::SETTLING, moving, id, curr, pointed.rect };
|
||||
_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;
|
||||
}
|
||||
};
|
||||
|
||||
struct Pick
|
||||
{
|
||||
bool picked;
|
||||
Window_id window_id;
|
||||
Rect orig_geometry;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _TYPES_H_ */
|
||||
|
@ -34,6 +34,8 @@ class Window_layouter::User_state
|
||||
virtual void to_front(Window_id) = 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 pick_up(Window_id) = 0;
|
||||
virtual void place_down() = 0;
|
||||
virtual void screen(Target::Name const &) = 0;
|
||||
};
|
||||
|
||||
@ -76,6 +78,8 @@ class Window_layouter::User_state
|
||||
*/
|
||||
bool _drag_init_done = false;
|
||||
|
||||
bool _picked_up = false;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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_element = element;
|
||||
@ -192,10 +196,11 @@ class Window_layouter::User_state
|
||||
_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()
|
||||
&& _hovered_window_id != last_hovered_window_id) {
|
||||
if (!_drag_state && !_picked_up && _hovered_window_id.valid()
|
||||
&& _hovered_window_id != orig_hovered_window_id) {
|
||||
|
||||
_focused_window_id = _hovered_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();
|
||||
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:
|
||||
warning("command ", (int)command.type, " unhanded");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user