a973d9902b
This commit replaces the former floating_window_layouter with a new window_layouter component that supports the subdivision of screen space into columns and rows, the concept of layers, and the principle ability to store window layout information across reboots. The latter is accomplished by reflecting the component's internal state as a 'rules' report to the outside. Fixes #3031
165 lines
6.7 KiB
Plaintext
165 lines
6.7 KiB
Plaintext
The window-layouter component complements the window manager (wm) with the
|
|
policy of how windows are positioned on screen and how windows behave when the
|
|
user interacts with window elements like the maximize button or the window
|
|
title. Whereas the decorator defines how windows look, the layouter defines how
|
|
they behave.
|
|
|
|
|
|
Layout rules
|
|
------------
|
|
|
|
The window layouter positions windows according to rules defined by the
|
|
component's configuration. The rules consist of two parts, the definition
|
|
of the screen's layout and the assignment of client windows to the defined
|
|
parts of the screen's layout.
|
|
|
|
! <config>
|
|
! <rules>
|
|
! <screen>
|
|
! ...definition of screen layout...
|
|
! </screen>
|
|
! <assign label_prefix="..." target="..."/>
|
|
! ,,,
|
|
! </rules>
|
|
! ...
|
|
! </config>
|
|
|
|
The '<screen>' node can host any number of '<column>' nodes, which partition
|
|
the screen horizontally into columns. By default, each column has the same
|
|
size. By specifying an optional 'weight' attribute, column sizes can be
|
|
weighted relative to one another. The default weight is '1'. Alternatively,
|
|
the 'width' of a column can be explicitly specified in pixels.
|
|
Each column can host any number of '<row>' nodes, which subdivide the column
|
|
vertically. Analogously to columns, rows can be dimensioned via an optional
|
|
'weight' attribute or an explicit 'height' in pixels. A '<row>' can, in turn,
|
|
contain '<column>' nodes, thereby further subdividing the screen.
|
|
Each '<column>' or '<row>' can be used as window-placement target when
|
|
equipped with a 'name' attribute. Each name must occur only once within
|
|
the '<screen>'. In the following, a named column or row is referred to as
|
|
_target_. Each target can host an optional 'layer' attribute. If not
|
|
specified, the layer 9999 is assumed. A target with a lower layer overlaps
|
|
targets with higher layers.
|
|
|
|
The assignment of windows to targets is defined via '<assign>' nodes. Each
|
|
'<assign>' node must be equipped with a 'label', 'label_prefix', or
|
|
'label_suffix' attribute, which is used to match window labels. For a given
|
|
window, the first matching '<assign>' node takes effect.
|
|
|
|
Each '<assign>' node must have a 'target' attribute that refers to the name
|
|
of a column or row. By default, the window is sized to fit the target area.
|
|
However, it is possible to position the window relative to the target area by
|
|
specifying the 'xpos', 'ypos', 'width', and 'height' attributes together with
|
|
the 'maximized="no"' attribute.
|
|
|
|
If multiple windows are assigned to the same target area, the order of their
|
|
'<assign>' rules defines their stacking order. The window with earliest
|
|
'<assign>' rule is displayed in front.
|
|
|
|
|
|
Dynamic layouts
|
|
---------------
|
|
|
|
The window layouter is able to respond to rule changes at runtime.
|
|
|
|
By specifying the '<config>' attribute 'rules="rom"', the window layouter
|
|
tries to obtain the layout rules from a distinct ROM module. Should the ROM
|
|
module not contain valid rules, the '<rules>' sub node of the '<config>' comes
|
|
into effect.
|
|
|
|
Any window-layout change such as the movement of a floating window is
|
|
realized as a change of the window-layout rules. To support interactive
|
|
adjustments of the window layout, the layouter responds to certain user
|
|
interactions by generating new rules by itself in the form of a "rules"
|
|
report. The generation of such rules can be enabled via the '<report>' sub
|
|
node of the configuration:
|
|
|
|
! <config>
|
|
! <report rules="yes"/>
|
|
! ...
|
|
! </config>
|
|
|
|
By feeding back the rules generated by the window layouter into the window
|
|
layouter itself via a 'report_rom' service, the window layout becomes
|
|
adjustable interactively. As the rules entail the complete state of the
|
|
present window layout, it is possible to save/restore the layout state.
|
|
|
|
|
|
Dynamic rule-generation mechanism
|
|
---------------------------------
|
|
|
|
Whenever a new window appears that solely matches a wildcard '<assign>' rule
|
|
(one that uses a 'label_prefix' or 'label_suffix'), the layouter generates a
|
|
new '<assign>' rule with the window's label as 'label' attribute. The
|
|
explicitly labeled '<assign>' rules appear before any wildcard '<assign>'
|
|
rules.
|
|
|
|
If the user brings a window to front, the window layouter will change the order
|
|
of the explicit '<assign>' rules such that the window's '<assign>' rule comes
|
|
first. When moving or resizing a window, the 'xpos', 'ypos', 'width', and
|
|
'height' attribute of the window's assign rule are updated. When maximizing
|
|
or unmaximizing a window, the 'maximized' attribute of its '<assign>' rule is
|
|
toggled.
|
|
|
|
|
|
Keyboard shortcuts
|
|
------------------
|
|
|
|
The window layouter is able to respond to key sequences. However, normally,
|
|
the layouter is not a regular nitpicker client but receives only those
|
|
input events that refer to the window decorations. It never owns the keyboard
|
|
focus. In order to propagate global key sequences to the layouter, nitpicker
|
|
must be explicitly configured to direct key sequences initiated with certain
|
|
keys to the decorator. For example, the following nitpicker configuration
|
|
routes key sequences starting with the left windows key to the decorator. The
|
|
window manager, in turn, forwards those events to the layouter.
|
|
|
|
! <start name="nitpicker">
|
|
! ...
|
|
! <config>
|
|
! ...
|
|
! <global-key name="KEY_LEFTMETA" label="wm -> decorator" />
|
|
! ...
|
|
! </config>
|
|
! ...
|
|
! </start>
|
|
|
|
The response of the window layouter to key sequences can be expressed in the
|
|
layouter configuration as follows:
|
|
|
|
! <config>
|
|
! ...
|
|
! <press key="KEY_LEFTMETA">
|
|
! <press key="KEY_TAB" action="next_window">
|
|
! <release key="KEY_TAB">
|
|
! <release key="KEY_LEFTMETA" action="raise_window"/>
|
|
! </release>
|
|
! </press>
|
|
! <press key="KEY_LEFTSHIFT">
|
|
! <press key="KEY_TAB" action="prev_window">
|
|
! <release key="KEY_TAB">
|
|
! <release key="KEY_LEFTMETA" action="raise_window"/>
|
|
! </release>
|
|
! </press>
|
|
! </press>
|
|
! <press key="KEY_ENTER" action="toggle_fullscreen"/>
|
|
! </press>
|
|
! </config>
|
|
|
|
Each '<press>' node defines the policy when the specified 'key' is pressed.
|
|
It can be equipped with an 'action' attribute that triggers a window action.
|
|
The supported window actions are:
|
|
|
|
:next_window: Focus the next window in the focus history.
|
|
:prev_window: Focus the previous window in the focus history.
|
|
:raise_window: Bring the focused window to the front.
|
|
:toggle_fullscreen: Maximize/unmaximize the focused window.
|
|
|
|
By nesting '<press>' nodes, actions can be tied to key sequences. In the
|
|
example above, the 'next_window' action is executed only if TAB is pressed
|
|
while the left windows-key is kept pressed. Furthermore, key sequences can
|
|
contain specific release events. In the example above, the release of the left
|
|
windows key brings the focused window to front, but only if TAB was pressed
|
|
before.
|
|
|
|
|