genode/repos/gems/src/app/window_layouter
Ehmry - 196c340aa9 Tup: build more of gems 2020-01-29 16:26:29 +01:00
..
README gems: flexible window layouter 2018-11-16 14:53:20 +01:00
Tupfile Tup: build more of gems 2020-01-29 16:26:29 +01:00
action.h gems: flexible window layouter 2018-11-16 14:53:20 +01:00
assign.h window layouter: control maximize by editing rules 2019-07-09 08:55:24 +02:00
assign_list.h window layouter: bring unknown windows to front 2018-11-29 11:54:30 +01:00
decorator_margins.h gems: flexible window layouter 2018-11-16 14:53:20 +01:00
focus_history.h gems: flexible window layouter 2018-11-16 14:53:20 +01:00
key_sequence_tracker.h gems: flexible window layouter 2018-11-16 14:53:20 +01:00
layout_rules.h gems: flexible window layouter 2018-11-16 14:53:20 +01:00
main.cc window layouter: reduce snap-back artifact 2019-07-09 08:58:38 +02:00
operations.h gems: flexible window layouter 2018-11-16 14:53:20 +01:00
target.h gems: flexible window layouter 2018-11-16 14:53:20 +01:00
target.mk gems: flexible window layouter 2018-11-16 14:53:20 +01:00
target_list.h gems: remove the use of deprecated APIs 2019-01-30 13:49:54 +01:00
types.h gems: remove the use of deprecated APIs 2019-01-30 13:49:54 +01:00
user_state.h window layouter: avoid superfluous layout updates 2019-01-07 12:38:45 +01:00
window.h window layouter: reduce snap-back artifact 2019-07-09 08:58:38 +02:00
window_list.h gems: remove the use of deprecated APIs 2019-01-30 13:49:54 +01:00

README

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.