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
This commit is contained in:
Stefan Kalkowski 2020-01-09 12:59:05 +01:00 committed by Christian Helmuth
parent 2afc218767
commit b76bd57ed1
8 changed files with 99 additions and 15 deletions

View File

@ -2,8 +2,17 @@
<report rules="yes"/> <report rules="yes"/>
<rules> <rules>
<screen name="screen"/> <screen name="screen_1"/>
<assign label_prefix="" target="screen" xpos="any" ypos="any"/> <screen name="screen_2"/>
<screen name="screen_3"/>
<screen name="screen_4"/>
<screen name="screen_5"/>
<screen name="screen_6"/>
<screen name="screen_7"/>
<screen name="screen_8"/>
<screen name="screen_9"/>
<screen name="screen_0"/>
<assign label_prefix="" target="screen_1" xpos="any" ypos="any"/>
</rules> </rules>
<press key="KEY_SCREEN"> <press key="KEY_SCREEN">
@ -21,5 +30,15 @@
</press> </press>
</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_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> </config>

View File

@ -2,8 +2,17 @@
<report rules="yes"/> <report rules="yes"/>
<rules> <rules>
<screen name="screen"/> <screen name="screen_1"/>
<assign label_prefix="" target="screen" xpos="any" ypos="any"/> <screen name="screen_2"/>
<screen name="screen_3"/>
<screen name="screen_4"/>
<screen name="screen_5"/>
<screen name="screen_6"/>
<screen name="screen_7"/>
<screen name="screen_8"/>
<screen name="screen_9"/>
<screen name="screen_0"/>
<assign label_prefix="" target="screen_1" xpos="any" ypos="any"/>
</rules> </rules>
<press key="KEY_SCREEN"> <press key="KEY_SCREEN">
@ -21,5 +30,15 @@
</press> </press>
</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_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> </config>

View File

@ -14,6 +14,8 @@
#ifndef _ACTION_H_ #ifndef _ACTION_H_
#define _ACTION_H_ #define _ACTION_H_
#include <target.h>
namespace Window_layouter { class Action; } namespace Window_layouter { class Action; }
@ -46,11 +48,13 @@ class Window_layouter::Action
NEXT_TAB, NEXT_TAB,
PREV_TAB, PREV_TAB,
TOOGLE_OVERLAY, TOOGLE_OVERLAY,
SCREEN,
}; };
private: private:
Type _type; Type _type;
Target::Name _target;
template <Genode::size_t N> template <Genode::size_t N>
static Type _type_by_string(String<N> const &string) static Type _type_by_string(String<N> const &string)
@ -59,6 +63,7 @@ class Window_layouter::Action
if (string == "prev_window") return PREV_WINDOW; if (string == "prev_window") return PREV_WINDOW;
if (string == "raise_window") return RAISE_WINDOW; if (string == "raise_window") return RAISE_WINDOW;
if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN; if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN;
if (string == "screen") return SCREEN;
Genode::warning("cannot convert \"", string, "\" to action type"); Genode::warning("cannot convert \"", string, "\" to action type");
return NONE; return NONE;
@ -66,12 +71,14 @@ class Window_layouter::Action
public: public:
Action(Type type) : _type(type) { } Action(Type type) : _type(type), _target() { }
template <Genode::size_t N> template <Genode::size_t N>
Action(String<N> const &string) : _type(_type_by_string(string)) { } Action(String<N> const &string, Target::Name const &arg)
: _type(_type_by_string(string)), _target(arg) { }
Type type() const { return _type; } Type type() const { return _type; }
Target::Name target_name() const { return _target; }
}; };
#endif /* _ACTION_H_ */ #endif /* _ACTION_H_ */

View File

@ -179,7 +179,10 @@ class Window_layouter::Key_sequence_tracker
typedef String<32> Action; typedef String<32> Action;
Action action = node.attribute_value("action", 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: public:

View File

@ -105,9 +105,6 @@ struct Window_layouter::Main : Operations,
_assign_list.for_each([&] (Assign &assign) { _assign_list.for_each([&] (Assign &assign) {
_target_list.for_each([&] (Target const &target) { _target_list.for_each([&] (Target const &target) {
if (target.name() != assign.target_name())
return;
assign.for_each_member([&] (Assign::Member &member) { assign.for_each_member([&] (Assign::Member &member) {
member.window.floating(assign.floating()); member.window.floating(assign.floating());
@ -208,6 +205,11 @@ struct Window_layouter::Main : Operations,
_gen_resize_request(); _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 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)
@ -356,7 +358,13 @@ struct Window_layouter::Main : Operations,
void _gen_window_layout(); void _gen_window_layout();
void _gen_resize_request(); void _gen_resize_request();
void _gen_focus(); 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 <typename FN> template <typename FN>
void _gen_rules_assignments(Xml_generator &, FN const &); 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()) if (!_rules_reporter.constructed())
return; return;
_rules_reporter->generate([&] (Xml_generator &xml) { _rules_reporter->generate([&] (Xml_generator &xml) {
_target_list.gen_screens(xml); _target_list.gen_screens(xml, screen);
/* /*
* Generate exact <assign> nodes for present windows. * Generate exact <assign> nodes for present windows.

View File

@ -31,6 +31,7 @@ struct Window_layouter::Operations : Interface
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 screen(Target::Name const &) = 0;
}; };
#endif /* _OPERATIONS_H_ */ #endif /* _OPERATIONS_H_ */

View File

@ -219,13 +219,36 @@ class Window_layouter::Target_list
/** /**
* Generate screen-layout definitions for the 'rules' report * 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()) if (!_rules.constructed())
return; return;
_rules->xml().for_each_sub_node("screen", [&] (Xml_node screen) { _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) { screen.with_raw_node([&] (char const *start, size_t length) {
xml.append(start, length); }); xml.append(start, length); });
xml.append("\n"); xml.append("\n");

View File

@ -327,6 +327,10 @@ void Window_layouter::User_state::_handle_event(Input::Event const &e,
_operations.focus(_focused_window_id); _operations.focus(_focused_window_id);
return; return;
case Action::SCREEN:
_operations.screen(action.target_name());
return;
default: default:
warning("action ", (int)action.type(), " unhanded"); warning("action ", (int)action.type(), " unhanded");
} }