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"/>
<rules>
<screen name="screen"/>
<assign label_prefix="" target="screen" xpos="any" ypos="any"/>
<screen name="screen_1"/>
<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>
<press key="KEY_SCREEN">
@ -21,5 +30,15 @@
</press>
</press>
<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>
</config>

View File

@ -2,8 +2,17 @@
<report rules="yes"/>
<rules>
<screen name="screen"/>
<assign label_prefix="" target="screen" xpos="any" ypos="any"/>
<screen name="screen_1"/>
<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>
<press key="KEY_SCREEN">
@ -21,5 +30,15 @@
</press>
</press>
<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>
</config>

View File

@ -14,6 +14,8 @@
#ifndef _ACTION_H_
#define _ACTION_H_
#include <target.h>
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 <Genode::size_t N>
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 == "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 <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; }
Target::Name target_name() const { return _target; }
};
#endif /* _ACTION_H_ */

View File

@ -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:

View File

@ -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 <typename FN>
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 <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 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_ */

View File

@ -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");

View File

@ -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");
}