KWin/Shadow

From KDE Community Wiki

KWin Shadows

The ideas for a new shadow system originated from the disadvantages of the old system. The old code shows serious bugs in conjunction with blur effect, slows down the system, is mostly obsoleted by the decoration shadows and not consistent with the overall look'n'feel. The widget style has no influence in the shadow.

Giving control to the Widget Style

The new system should give the control to the widget style. A shadow is part of the overall light model. The compositor does not know about the light model or about things like the Oxygen glow.

Nevertheless the decoration shadows should be kept and the new shadow system should only be used if the decoration does not provide shadows. The new system is therefore mostly meant for unmanaged windows such as menus, tooltips, dropdown menus, etc. but can also be used for "normal" windows with a legacy decoration. In future we could think about allowing an ARGB deco to not use the decoration shadows any more, but the new system. For decorations like Aurorae we will still need the decoration shadows.

The shadow elements

The shadow elements are inspired by Plasma's FrameSvg borders. There will be eight pixmaps defining the shadow:

* top
* top-right
* right
* bottom-right
* bottom
* bottom-left
* left
* top-left

The center element is not required as we do not want to have shadows behind the window. The shadow pixmaps are specified on the root window in the same way as _NET_WM_ICON starting with the top pixmap in clockwise order.

The compositor announces support for the shadows through adding _KDE_NET_WM_SHADOW to _NET_SUPPORTED

Different Shadows

Three different styles for shadows are required:

1. One shadow for all kind of "undecorated" windows such as menus, dropdown lists, tooltips. In general for override redirect windows.
1. One shadow for a focused and decorated window
1. One shadow for an unfocused and decorated window

These shadows should be specified on the root window through the following properties in the formate described above:

1. _KDE_NET_WM_SHADOW
1. _KDE_NET_WM_SHADOW_FOCUSED
1. _KDE_NET_WM_SHADOW_UNFOCUSED

It is the task of the compositor to choose between focused and unfocused automatically. Focused and unfocused shadows do not have to be set by the toolkit. If not present the generic shadow will be used for all windows.

Requesting Shadow for a Window

To set a shadow for a window the toolkit/widget style should set the property _KDE_NET_WM_SHADOW. The structure of the property is the padding in the various directions starting from top in clockwise direction. For border elements only one element is required, for corner elements x and y padding is required, that is 12 elements:

* padding in y-pixels for TOP
* padding in x-pixels for TOP-RIGHT
* padding in y-pixels for TOP-RIGHT
* padding in x-pixels for RIGHT
* ...
* padding in x-pixels for TOP-LEFT
* padding in y-pixels for TOP-LEFT

Two additional values are required: the first to specify if borders need to be stretched or tiled: zero represents stretched, any non-zero represents tiled. The second value specifies whether the generic of (un)focused shadow should be used: zero represents generic, any non-zero value represents the (un)focused shadow. An additional third parameter for the (un)focused shadow can be specified to provide the duration of a transition animation from focused to unfocused state (and vice versa) in msec. If not specified or 0 no transition animation is used.

An example for a shadow of 10 pixels in all directions and 20 pixels on the bottom, tiled with (un)focused shadow and a 200 msec transition animation would look like the following: _KDE_NET_WM_SHADOW=10, 10, 10, 10, 10, 20, 20, 10, 20, 10, 10, 10, 1, 1, 200

The pixmaps start from the offset and are painted in there complete size. For the borders the pixmaps are either tiled or stretched in the respective direction, the other size is fixed.

Implementation in KWin

Shadows are moved directly into the compositor following the approach of the decoration shadows. Window quads for each of the shadow areas are added and rendered before the window (if it is RGB) or rendered together with the window in case of RGBA (for Oxygen the latter case will always be the case).

Moving the shadows directly into the compositor and not in an effect should provide the required performance and should not show the visual bugs seen before with e.g. blur effect. The shadow belongs to the window, so even wobbly shadows should work better ;-)

Ideas for Future Improvements

It should be possible to set shadow pixmaps on a per-window level (though global shadows on the root window should be preferred for performance reasons).