From b76bd57ed11f283dafe8b88dcbfe0c339eaf63fa Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 9 Jan 2020 12:59:05 +0100 Subject: [PATCH] window_layouter: add dynamic screen handling This commit adds dynamic switching in between different defined screens via keyboard shortcuts, or by editing the rules file. In the window_layouter package it defines per default ten screens, reachable by pressing the screen key along with numbers 0-9. Fix #3646 --- .../gems/recipes/raw/motif_wm/layouter.config | 23 +++++++++++++++-- .../window_layouter/window_layouter.config | 23 +++++++++++++++-- repos/gems/src/app/window_layouter/action.h | 13 +++++++--- .../window_layouter/key_sequence_tracker.h | 5 +++- repos/gems/src/app/window_layouter/main.cc | 20 ++++++++++----- .../gems/src/app/window_layouter/operations.h | 1 + .../src/app/window_layouter/target_list.h | 25 ++++++++++++++++++- .../gems/src/app/window_layouter/user_state.h | 4 +++ 8 files changed, 99 insertions(+), 15 deletions(-) diff --git a/repos/gems/recipes/raw/motif_wm/layouter.config b/repos/gems/recipes/raw/motif_wm/layouter.config index 06aaf9ae3..4611a48a5 100644 --- a/repos/gems/recipes/raw/motif_wm/layouter.config +++ b/repos/gems/recipes/raw/motif_wm/layouter.config @@ -2,8 +2,17 @@ - - + + + + + + + + + + + @@ -21,5 +30,15 @@ + + + + + + + + + + diff --git a/repos/gems/recipes/raw/window_layouter/window_layouter.config b/repos/gems/recipes/raw/window_layouter/window_layouter.config index 06aaf9ae3..4611a48a5 100644 --- a/repos/gems/recipes/raw/window_layouter/window_layouter.config +++ b/repos/gems/recipes/raw/window_layouter/window_layouter.config @@ -2,8 +2,17 @@ - - + + + + + + + + + + + @@ -21,5 +30,15 @@ + + + + + + + + + + diff --git a/repos/gems/src/app/window_layouter/action.h b/repos/gems/src/app/window_layouter/action.h index 2ef592482..45890aa42 100644 --- a/repos/gems/src/app/window_layouter/action.h +++ b/repos/gems/src/app/window_layouter/action.h @@ -14,6 +14,8 @@ #ifndef _ACTION_H_ #define _ACTION_H_ +#include + namespace Window_layouter { class Action; } @@ -46,11 +48,13 @@ class Window_layouter::Action NEXT_TAB, PREV_TAB, TOOGLE_OVERLAY, + SCREEN, }; private: - Type _type; + Type _type; + Target::Name _target; template static Type _type_by_string(String const &string) @@ -59,6 +63,7 @@ class Window_layouter::Action if (string == "prev_window") return PREV_WINDOW; if (string == "raise_window") return RAISE_WINDOW; if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN; + if (string == "screen") return SCREEN; Genode::warning("cannot convert \"", string, "\" to action type"); return NONE; @@ -66,12 +71,14 @@ class Window_layouter::Action public: - Action(Type type) : _type(type) { } + Action(Type type) : _type(type), _target() { } template - Action(String const &string) : _type(_type_by_string(string)) { } + Action(String const &string, Target::Name const &arg) + : _type(_type_by_string(string)), _target(arg) { } Type type() const { return _type; } + Target::Name target_name() const { return _target; } }; #endif /* _ACTION_H_ */ diff --git a/repos/gems/src/app/window_layouter/key_sequence_tracker.h b/repos/gems/src/app/window_layouter/key_sequence_tracker.h index a2601d922..770690730 100644 --- a/repos/gems/src/app/window_layouter/key_sequence_tracker.h +++ b/repos/gems/src/app/window_layouter/key_sequence_tracker.h @@ -179,7 +179,10 @@ class Window_layouter::Key_sequence_tracker typedef String<32> Action; Action action = node.attribute_value("action", Action()); - func(Window_layouter::Action(action)); + using Name = Window_layouter::Target::Name; + Name const target = node.attribute_value("target", Name()); + + func(Window_layouter::Action(action, target)); } public: diff --git a/repos/gems/src/app/window_layouter/main.cc b/repos/gems/src/app/window_layouter/main.cc index c92d6e355..65990bde3 100644 --- a/repos/gems/src/app/window_layouter/main.cc +++ b/repos/gems/src/app/window_layouter/main.cc @@ -105,9 +105,6 @@ struct Window_layouter::Main : Operations, _assign_list.for_each([&] (Assign &assign) { _target_list.for_each([&] (Target const &target) { - if (target.name() != assign.target_name()) - return; - assign.for_each_member([&] (Assign::Member &member) { member.window.floating(assign.floating()); @@ -208,6 +205,11 @@ struct Window_layouter::Main : Operations, _gen_resize_request(); } + void screen(Target::Name const & name) override + { + _gen_rules_with_frontmost_screen(name); + } + void drag(Window_id id, Window::Element element, Point clicked, Point curr) override { if (_drag_state == Drag_state::SETTLING) @@ -356,7 +358,13 @@ struct Window_layouter::Main : Operations, void _gen_window_layout(); void _gen_resize_request(); void _gen_focus(); - void _gen_rules(); + void _gen_rules_with_frontmost_screen(Target::Name const &); + + void _gen_rules() + { + /* keep order of screens unmodified */ + _gen_rules_with_frontmost_screen(Target::Name()); + } template void _gen_rules_assignments(Xml_generator &, FN const &); @@ -492,14 +500,14 @@ void Window_layouter::Main::_gen_rules_assignments(Xml_generator &xml, FN const } -void Window_layouter::Main::_gen_rules() +void Window_layouter::Main::_gen_rules_with_frontmost_screen(Target::Name const &screen) { if (!_rules_reporter.constructed()) return; _rules_reporter->generate([&] (Xml_generator &xml) { - _target_list.gen_screens(xml); + _target_list.gen_screens(xml, screen); /* * Generate exact nodes for present windows. diff --git a/repos/gems/src/app/window_layouter/operations.h b/repos/gems/src/app/window_layouter/operations.h index 883267fdb..4ed9922d1 100644 --- a/repos/gems/src/app/window_layouter/operations.h +++ b/repos/gems/src/app/window_layouter/operations.h @@ -31,6 +31,7 @@ struct Window_layouter::Operations : Interface 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 screen(Target::Name const &) = 0; }; #endif /* _OPERATIONS_H_ */ diff --git a/repos/gems/src/app/window_layouter/target_list.h b/repos/gems/src/app/window_layouter/target_list.h index 4ade236fb..6cb02def7 100644 --- a/repos/gems/src/app/window_layouter/target_list.h +++ b/repos/gems/src/app/window_layouter/target_list.h @@ -219,13 +219,36 @@ class Window_layouter::Target_list /** * Generate screen-layout definitions for the 'rules' report + * + * If a valid 'screen_name' is specified, move the referred screen in + * front of all others. */ - void gen_screens(Xml_generator &xml) const + void gen_screens(Xml_generator &xml, Target::Name const &screen_name) const { if (!_rules.constructed()) return; _rules->xml().for_each_sub_node("screen", [&] (Xml_node screen) { + if (screen_name.valid()) { + Target::Name const name = + screen.attribute_value("name", Target::Name()); + + if (screen_name != name) + return; + } + screen.with_raw_node([&] (char const *start, size_t length) { + xml.append(start, length); }); + xml.append("\n"); + }); + + if (!screen_name.valid()) + return; + + _rules->xml().for_each_sub_node("screen", [&] (Xml_node screen) { + Target::Name const name = screen.attribute_value("name", Target::Name()); + if (screen_name == name) + return; + screen.with_raw_node([&] (char const *start, size_t length) { xml.append(start, length); }); xml.append("\n"); diff --git a/repos/gems/src/app/window_layouter/user_state.h b/repos/gems/src/app/window_layouter/user_state.h index a28edde4e..e2967c5a4 100644 --- a/repos/gems/src/app/window_layouter/user_state.h +++ b/repos/gems/src/app/window_layouter/user_state.h @@ -327,6 +327,10 @@ void Window_layouter::User_state::_handle_event(Input::Event const &e, _operations.focus(_focused_window_id); return; + case Action::SCREEN: + _operations.screen(action.target_name()); + return; + default: warning("action ", (int)action.type(), " unhanded"); }