Merge branch 'master' into config-nag

This commit is contained in:
elviosak 2026-05-26 16:23:38 -03:00
commit 591fdf40c4
31 changed files with 343 additions and 163 deletions

180
NEWS.md
View file

@ -9,7 +9,7 @@ The format is based on [Keep a Changelog]
| Date | All Changes | wlroots version | lines-of-code |
|------------|---------------|-----------------|---------------|
| 2026-04-29 | [unreleased] | 0.20.0 | 27849 |
| 2026-05-25 | [0.20.0] | 0.20.1 | 28313 |
| 2026-04-17 | [0.9.7] | 0.19.2 | 29277 |
| 2026-03-15 | [0.9.6] | 0.19.2 | 29271 |
| 2026-03-04 | [0.9.5] | 0.19.2 | 29251 |
@ -45,6 +45,7 @@ The format is based on [Keep a Changelog]
| 2021-03-05 | [0.1.0] | 0.12.0 | 4627 |
[unreleased]: NEWS.md#unreleased
[0.20.0]: NEWS.md#0200---2026-05-25
[0.9.7]: NEWS.md#097---2026-04-17
[0.9.6]: NEWS.md#096---2026-03-15
[0.9.5]: NEWS.md#095---2026-03-04
@ -79,6 +80,109 @@ The format is based on [Keep a Changelog]
[0.2.0]: NEWS.md#020---2021-04-15
[0.1.0]: NEWS.md#010---2021-03-05
## unreleased
[unreleased-commits]
## 0.20.0 - 2026-05-25
[0.20.0-commits]
This is the first release using wlroots-0.20 and therefore has an increased risk
of teething issues. Many thanks to @Consolatis for leading the effort to port
across [#2956].
In terms of new features, the most noteworthy ones include: (i) the frequently
requested show-desktop action; (ii) initial toplevel capture support to
screenshot specific windows; (iii) menu accelerators/shortcuts; and (iv) HDR10
support when running with the Vulkan renderer option.
The eagle-eyed amongst you will have noticed the sudden jump from labwc `0.9.7`
to `0.20.0`. The reason for this is to align the minor number to that of the
wlroots version against which the compositor is linked.
The 0.9.x series has turned into a maintenance branch named v0.9 with bug fixes
only, for anyone preferring to build with wlroots-0.19.
Note to maintainers:
- libinput >=1.26 is required in support of tablet tool pressure range
configuration.
- wlroots >=0.20.1 is required to avoid some bugs that we do not want labwc to
ship with. For details, see:
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5325
### Added
- Partially support toplevel-capture. Note that the following are not yet
implemented: (i) XWayland child windows; (ii) XWayland unmanaged windows
(e.g. popups); (iii) xdg child window positioning; (iv) xdg subsurfaces;
and (v) xdg popup positioning. [#2968] @Consolatis
- Add command line option -t|--title to set the labwc window title when running
nested [#3577] @mdsib
- Add support for HDR10 output @kode54 @Consolatis [#3424]
- Include wlroots version in --version string @Consolatis [#3567] [#3581]
- Implement menu accelerators (one-letter mnemonics to quickly select/exec
items from the current menu) @ch3rn1ka [#3505]
- Add Next/PreviousWindowImmediate actions @elviosak @johanmalm [#3547]
- Add labnag options `--details-border-color` and `--details-margin`
@st0rm-shad0w [#3527]
- Add config option `<focus><raiseOnFocusDelay>` to defer raise-on-focus by a
small amount when `raiseOnFocus` is enabled @joske [#3513]
- Install `labwc-session.target` systemd user unit when the systemd dependency
is available @joske [#3534]
- Add `onbutton` to config option `<libinput><device><scrollMethod>`. Also add
associated option `<libinput><device><scrollButton>`. @diniamo [#3540]
- Add `overrideInhibition` option to `<keybind>` [#3507] @drougas
- Add action `ToggleShowDesktop` to hide/unhide windows, and default keybind
`Super-d` to trigger this action [#3500] [#3595] @johanmalm
- Add `<privilegedInterfaces>` config option so that privileged protocols can be
restricted [#3493] @xi
- Add action `DebugToggleKeyStateIndicator` to show a key-state on-screen
display (OSD) for debugging. [#3499] @johanmalm @tokyo4j
- Add support for `color-management-v1` and `color-representation-manager-v1`
protocols [#3469] @ManuLinares
- Add configuration option `<tabletTool minPressure="0.0" maxPressure="1.0" />`
to enable tablet tool pressure range libinput settings [#2916] @jp7677
- Add `wl_fixes` interface [#2956] @kode54
### Fixed
- Enable labnag long option --exclusive-zone [#3576] @st0rm-shad0w
- Position chromium popup correctly when a window is maximized on a multi-
output setup @elviosak [#3547]
- Run session activation environment update synchronously to avoid a race
condition with the autostart script [#3543] @joske
- Allow interactive resize on fully maximized windows so that a resize
initiated by modifier plus right-mouse-button-drag is not ignored [#3525]
@bjorn
- Gracefully handle missing XWayland packages, so that a labwc compositor which
has been built with XWayland support (which is optional) can be run even if
XWayland is not installed. [#3401] @quite
- Rework how XWayland window initial geometry is set to ensure that the natural
geometry does not exceed the usable output area when handling initial
maximize/fullscreen requests. [#3439] @jlindgren90.
- For XWayland windows, sync always-on-top state back to X.Org Server. This
makes `wmctrl -b toggle,above` work. [#3446] @jlindgren90
- Fix missing title and icon with XWayland client override-redirect toggle.
There are no known issues with clients, so this is purely for preventative
purposes. [#3450] @jlindgren90
- Update titlebar title when set to empty and fix an associated issue causing
the title to be misplaced outside of the titlebar when the window is resized.
[#3443] @tokyo4j
- When running nested, exit compositor when last output is destroyed because
in this situation, each output corresponds to a window in the parent
compositor and, unlike DRM outputs, these cannot be reconnected after being
destroyed. [#3440] @marler8997
- Allow policy-based placement to apply when an initially-maximized/fullscreen
view is restored to floating geometry. [#3387] [#3502] @jlindgren90
### Changed
- Change the default keybinds for XF86Audio{LowerVolume,RaiseVolume,Mute} to use
pactl instead of amixer [#3484] @danielrrrr
- Drop cosmic-workspace protocol [#3031] @tokyo4j
## Notes on wlroots-0.19
There are some regression warnings worth noting for the switch to wlroots 0.19:
@ -113,72 +217,6 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
[wlroots-5098]:https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5098
[gtk-8792]: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8792
## unreleased
[unreleased-commits]
The codebase has been ported to wlroots 0.20 [#2956] @Consolatis
Note to maintainers:
- libinput >=1.26 is required in support of tablet tool pressure range
configuration.
### Added
- Add labnag options `--details-border-color` and `--details-margin`
@st0rm-shad0w [#3527]
- Add config option `<focus><raiseOnFocusDelay>` to defer raise-on-focus by a
small amount when `raiseOnFocus` is enabled @joske [#3513]
- Install `labwc-session.target` systemd user unit when the systemd dependency
is available @joske [#3534]
- Add `onbutton` to config option `<libinput><device><scrollMethod>`. Also add
associated option `<libinput><device><scrollButton>`. @diniamo [#3540]
- Add `overrideInhibition` option to `<keybind>` [#3507] @drougas
- Add action `ToggleShowDesktop` to hide/unhide windows [#3500] @johanmalm
- Add `<privilegedInterfaces>` config option so that privileged protocols can be
restricted [#3493] @xi
- Add action `DebugToggleKeyStateIndicator` to show a key-state on-screen
display (OSD) for debugging. [#3499] @johanmalm @tokyo4j
- Add support for `color-management-v1` and `color-representation-manager-v1`
protocols [#3469] @ManuLinares
- Add configuration option `<tabletTool minPressure="0.0" maxPressure="1.0" />`
to enable tablet tool pressure range libinput settings [#2916] @jp7677
- Add `wl_fixes` interface [#2956] @kode54
### Fixed
- Run session activation environment update synchronously to avoid a race
condition with the autostart script [#3543] @joske
- Allow interactive resize on fully maximized windows so that a resize
initiated by modifier plus right-mouse-button-drag is not ignored [#3525]
@bjorn
- Gracefully handle missing XWayland packages, so that a labwc compositor which
has been built with XWayland support (which is optional) can be run even if
XWayland is not installed. [#3401] @quite
- Rework how XWayland window initial geometry is set to ensure that the natural
geometry does not exceed the usable output area when handling initial
maximize/fullscreen requests. [#3439] @jlindgren90.
- For XWayland windows, sync always-on-top state back to X.Org Server. This
makes `wmctrl -b toggle,above` work. [#3446] @jlindgren90
- Fix missing title and icon with XWayland client override-redirect toggle.
There are no known issues with clients, so this is purely for preventative
purposes. [#3450] @jlindgren90
- Update titlebar title when set to empty and fix an associated issue causing
the title to be misplaced outside of the titlebar when the window is resized.
[#3443] @tokyo4j
- When running nested, exit compositor when last output is destroyed because
in this situation, each output corresponds to a window in the parent
compositor and, unlike DRM outputs, these cannot be reconnected after being
destroyed. [#3440] @marler8997
- Allow policy-based placement to apply when an initially-maximized/fullscreen
view is restored to floating geometry. [#3387] [#3502] @jlindgren90
### Changed
- Change the default keybinds for XF86Audio{LowerVolume,RaiseVolume,Mute} to use
pactl instead of amixer [#3484] @danielrrrr
- Drop cosmic-workspace protocol [#3031] @tokyo4j
## 0.9.7 - 2026-04-17
[0.9.7-commits]
@ -2732,7 +2770,8 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
ShowMenu
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
[unreleased-commits]: https://github.com/labwc/labwc/compare/0.9.5...HEAD
[unreleased-commits]: https://github.com/labwc/labwc/compare/0.20.0...HEAD
[0.20.0-commits]: https://github.com/labwc/labwc/compare/0.9.5..0.20.0
[0.9.7-commits]: https://github.com/labwc/labwc/compare/0.9.6...0.9.7
[0.9.6-commits]: https://github.com/labwc/labwc/compare/0.9.5...0.9.6
[0.9.5-commits]: https://github.com/labwc/labwc/compare/0.9.4...0.9.5
@ -3272,6 +3311,7 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
[#3410]: https://github.com/labwc/labwc/pull/3410
[#3411]: https://github.com/labwc/labwc/pull/3411
[#3412]: https://github.com/labwc/labwc/pull/3412
[#3424]: https://github.com/labwc/labwc/pull/3424
[#3425]: https://github.com/labwc/labwc/pull/3425
[#3426]: https://github.com/labwc/labwc/pull/3426
[#3428]: https://github.com/labwc/labwc/pull/3428
@ -3292,6 +3332,7 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
[#3499]: https://github.com/labwc/labwc/pull/3499
[#3500]: https://github.com/labwc/labwc/pull/3500
[#3502]: https://github.com/labwc/labwc/pull/3502
[#3505]: https://github.com/labwc/labwc/pull/3505
[#3507]: https://github.com/labwc/labwc/pull/3507
[#3511]: https://github.com/labwc/labwc/pull/3511
[#3513]: https://github.com/labwc/labwc/pull/3513
@ -3300,3 +3341,6 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
[#3534]: https://github.com/labwc/labwc/pull/3534
[#3540]: https://github.com/labwc/labwc/pull/3540
[#3543]: https://github.com/labwc/labwc/pull/3543
[#3547]: https://github.com/labwc/labwc/pull/3547
[#3567]: https://github.com/labwc/labwc/pull/3567
[#3595]: https://github.com/labwc/labwc/pull/3595

View file

@ -213,6 +213,7 @@ If you have not created an rc.xml config file, default bindings will be:
| `super`-`return` | lab-sensible-terminal
| `alt`-`F4` | close window
| `super`-`a` | toggle maximize
| `super`-`d` | toggle show-desktop
| `super`-`mouse-left` | move window
| `super`-`mouse-right` | resize window
| `super`-`arrow` | resize window to fill half the output

View file

@ -1592,6 +1592,7 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
{"message", required_argument, NULL, 'm'},
{"output", required_argument, NULL, 'o'},
{"timeout", required_argument, NULL, 't'},
{"exclusive-zone", no_argument, NULL, 'x'},
{"version", no_argument, NULL, 'v'},
{"background-color", required_argument, NULL, TO_COLOR_BACKGROUND},

View file

@ -12,7 +12,7 @@
swaybg -c '#113344' >/dev/null 2>&1 &
# Configure output directives such as mode, position, scale and transform.
# Use wlr-randr to get your output names
# Use wlr-randr to get your output names.
# Example ~/.config/kanshi/config below:
# profile {
# output HDMI-A-1 position 1366,0

View file

@ -139,22 +139,21 @@ Actions are used in menus and keyboard/mouse bindings.
and OSD, useful for binding to keys without modifiers.
*workspace* [all|current]
This determines whether to cycle through windows on all workspaces or the
current workspace. Default is "current".
This determines whether to cycle through windows on all workspaces or
the current workspace. Default is "current".
*output* [all|focused|cursor]
This determines whether to cycle through windows on all outputs, the focused
output, or the output under the cursor. Default is "all".
This determines whether to cycle through windows on all outputs, the
focused output, or the output under the cursor. Default is "all".
*identifier* [all|current]
This determines whether to cycle through all windows or only windows of the
same application as the currently focused window. Default is "all".
This determines whether to cycle through all windows or only windows of
the same application as the currently focused window. Default is "all".
*<action name="Reconfigure" />*
Re-load configuration and theme files.
*<action name="ShowMenu" menu="root-menu"/>*
*<action name="ShowMenu" menu="root-menu" />*
Show a menu.
```
@ -300,7 +299,7 @@ Actions are used in menus and keyboard/mouse bindings.
(if one exists).
*wrap* [yes|no] When using the direction attribute, wrap around from
right-to-left or top-to-bottom, and vice versa. Default no.
right-to-left or top-to-bottom, and vice versa. Default is no.
*<action name="FitToOutput" />*
Resizes active window size to width and height of the output when the
@ -314,10 +313,10 @@ Actions are used in menus and keyboard/mouse bindings.
workspace or its index (starting at 1) as configured in rc.xml.
*wrap* [yes|no] Wrap around from last desktop to first, and vice
versa. Default yes.
versa. Default is yes.
*toggle* [yes|no] Toggle to “last” if already on the workspace that
would be the actual destination. Default no.
would be the actual destination. Default is no.
*<action name="SendToDesktop" to="value" follow="yes" wrap="yes" />*
Send active window to workspace.
@ -325,10 +324,11 @@ Actions are used in menus and keyboard/mouse bindings.
*to* The workspace to send the window to. Supported values are the same
as for GoToDesktop.
*follow* [yes|no] Also switch to the specified workspace. Default yes.
*follow* [yes|no] Also switch to the specified workspace.
Default is yes.
*wrap* [yes|no] Wrap around from last desktop to first, and vice
versa. Default yes.
versa. Default is yes.
*<action name="VirtualOutputAdd" output_name="value" />*
Add virtual output (headless backend).
@ -346,11 +346,11 @@ Actions are used in menus and keyboard/mouse bindings.
```
<keybind key="W-v">
<action name="VirtualOutputAdd" output_name="ScreenCasting"/>
<action name="Execute" command='sh -c "wlr-randr --output ScreenCasting --pos 0,0 --scale 2 --custom-mode 3840x2110; wlr-randr --output eDP-1 --pos 0,0 --scale 2 --mode 3840x2160"'/>
<action name="VirtualOutputAdd" output_name="ScreenCasting" />
<action name="Execute" command='sh -c "wlr-randr --output ScreenCasting --pos 0,0 --scale 2 --custom-mode 3840x2110; wlr-randr --output eDP-1 --pos 0,0 --scale 2 --mode 3840x2160"' />
</keybind>
<keybind key="W-c">
<action name="VirtualOutputRemove"/>
<action name="VirtualOutputRemove" />
</keybind>
```
@ -371,7 +371,7 @@ Actions are used in menus and keyboard/mouse bindings.
*output_name* The name of virtual output. If not supplied, will remove
the last virtual output added.
*<action name="AutoPlace" policy="value"/>*
*<action name="AutoPlace" policy="value" />*
Reposition the window according to the desired placement policy.
*policy* [automatic|cursor|center|cascade] Use the specified policy,
@ -430,11 +430,11 @@ Actions are used in menus and keyboard/mouse bindings.
used.
*<action name="ToggleShowDesktop" />*
Minimize all windows in the current workspace so that the desktop becomes
visible. On calling the action again the hidden windows are unminimized,
provided that - since the initial `ShowDesktop` - (a) no windows have been
unminimized; (b) workspaces have not been switched; and (c) no new
applications have been started.
Minimize all windows in the current workspace so that the desktop
becomes visible. On calling the action again the hidden windows are
unminimized, provided that - since the initial `ShowDesktop` - (a) no
windows have been unminimized; (b) workspaces have not been switched;
and (c) no new applications have been started.
*<action name="ZoomIn">*++
*<action name="ZoomOut">*
@ -449,8 +449,8 @@ Actions are used in menus and keyboard/mouse bindings.
binding.
*<action name="DebugToggleKeyStateIndicator" />*
Toggle visibility of key-state on-screen display (OSD). Note: This is for
debugging purposes only.
Toggle visibility of key-state on-screen display (OSD). Note: This is
for debugging purposes only.
# CONDITIONAL ACTIONS
@ -464,10 +464,10 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
```
<action name="If">
<query/>
<prompt message=""/>
<then><action/></then>
<else><action/></else>
<query />
<prompt message="" />
<then><action /></then>
<else><action /></else>
</action>
```
@ -549,9 +549,9 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
```
<keybind key="W-q">
<action name="If">
<prompt message="Quit?"/>
<prompt message="Quit?" />
<then>
<action name="Exit"/>
<action name="Exit" />
</then>
</action>
</keybind>

View file

@ -550,7 +550,8 @@ extending outward from the snapped edge.
*<range><inner>* and *<range><outer>*, and 50 for *<cornerRange>*.
*<snapping><overlay><enabled>* [yes|no]
Show an overlay when snapping a window to an output edge. Default is yes.
Show an overlay when snapping a window to an output edge.
Default is yes.
*<snapping><overlay><delay><inner>*++
*<snapping><overlay><delay><outer>*
@ -619,7 +620,7 @@ extending outward from the snapped edge.
A setting of 0 disables the OSD. Default is 1000 ms.
*<desktops><prefix>*
Set the prefix to use when using "number" above. Default is "Workspace"
Set the prefix to use when using "number" above. Default is "Workspace".
## THEME
@ -848,9 +849,10 @@ overrideInhibition="">*
Make this keybind work even if the screen is locked. Default is no.
*overrideInhibition* [yes|no]
Make this keybind work even if the view inhibits keybinds. Default is no.
Make this keybind work even if the view inhibits keybinds.
This can be used to prevent W-Tab and similar keybinds from being
delivered to Virtual Machines, VNC clients or nested compositors.
Default is no.
*onRelease* [yes|no]
When yes, fires the keybind action when the key or key
@ -864,7 +866,7 @@ overrideInhibition="">*
```
<keybind key="Super_L" onRelease="yes">
<action name="Execute" command="rofi -show drun"/>
<action name="Execute" command="rofi -show drun" />
</keybind>
```
@ -885,6 +887,7 @@ overrideInhibition="">*
W-Return - lab-sensible-terminal
A-F4 - close window
W-a - toggle maximize
W-d - toggle show-desktop
W-<arrow> - resize window to fill half or quarter of the output
A-Space - show window menu
```
@ -924,7 +927,7 @@ input-devices by the Wayland protocol.
- Shade: A button that, by default, toggles window shading.
- AllDesktops: A button that, by default, toggles omnipresence of a
window.
- Close: A button that, by default, closses a window.
- Close: A button that, by default, closes a window.
- Border: The window's border including Top...BRCorner below.
- Top: The top edge of the window's border.
- Bottom: The bottom edge of the window's border.
@ -998,10 +1001,10 @@ input-devices by the Wayland protocol.
```
<mouse>
<default/>
<default />
<context name="Frame">
<mousebind button="W-Left" action="Press"/>
<mousebind button="W-Left" action="Drag"/>
<mousebind button="W-Left" action="Press" />
<mousebind button="W-Left" action="Drag" />
</context>
</mouse>
```
@ -1021,7 +1024,7 @@ Note: To rotate touch events with output rotation, use the libinput
*calibrationMatrix* setting.
```
<touch deviceName="" mapToOutput="" mouseEmulation="no"/>
<touch deviceName="" mapToOutput="" mouseEmulation="no" />
```
*<touch deviceName="" />*
@ -1284,7 +1287,8 @@ Note: To rotate touch events with output rotation, use the libinput
The default method depends on the touchpad hardware.
*<libinput><device><scrollMethod>* [none|twofinger|edge|onbutton]
Configure the method by which physical movements are mapped to scroll events.
Configure the method by which physical movements are mapped to scroll
events.
The scroll methods available are:
- *twofinger* - Scroll by two fingers being placed on the surface of the
@ -1299,7 +1303,8 @@ Note: To rotate touch events with output rotation, use the libinput
*<libinput><device><scrollButton>* [button]
Set the button used for the *onbutton* scroll method.
*button* is the decimal form of a value from `linux/input-event-codes.h`.
*button* is the decimal form of a value
from `linux/input-event-codes.h`.
*<libinput><device><sendEventsMode>* [yes|no|disabledOnExternalMouse]
Optionally enable or disable sending any device events.
@ -1348,7 +1353,7 @@ defined as shown below.
<!-- Action -->
<windowRule identifier="" title="" type="">
<action name=""/>
<action name="" />
</windowRule>
<!-- Property -->
@ -1545,7 +1550,7 @@ This is the full list of interfaces that can be controlled with this mechanism:
*XCURSOR_PATH*
Specify a colon-separated list of paths to look for mouse cursors in.
Default
Default is
~/.local/share/icons:
~/.icons:
/usr/share/icons:
@ -1556,7 +1561,7 @@ This is the full list of interfaces that can be controlled with this mechanism:
*XCURSOR_SIZE*
Specify an alternative mouse cursor size in pixels. Requires
XCURSOR_THEME to be set also. Default 24.
XCURSOR_THEME to be set also. Default is 24.
*XCURSOR_THEME*
Specify a mouse cursor theme within XCURSOR_PATH.

View file

@ -111,7 +111,7 @@ Pipe menus are menus generated dynamically based on output of scripts or
binaries. They are so-called because the output of the executable is piped to
the labwc menu.
For any *<menu id="" label="" execute="COMMAND"/>* entry in menu.xml, the
For any *<menu id="" label="" execute="COMMAND" />* entry in menu.xml, the
COMMAND will be executed the first time the item is selected (for example by
cursor or keyboard input). The XML output of the command will be parsed and
shown as a submenu. The content of pipemenus is cached until the whole menu
@ -124,7 +124,7 @@ menus, for example:
```
<openbox_pipe_menu>
<item label="Terminal">
<action name="Execute" command="xterm"/>
<action name="Execute" command="xterm" />
</item>
</openbox_pipe_menu>
```
@ -144,7 +144,7 @@ obmenu-generator with the menu generator of your choice):
```
<?xml version="1.0"?>
<openbox_menu>
<menu id="root-menu" label="" execute="obmenu-generator"/>
<menu id="root-menu" label="" execute="obmenu-generator" />
</openbox_menu>
```

View file

@ -135,7 +135,7 @@ window.*.title.bg.colorTo.splitTo: #557485
*window.active.title.bg*
Texture for the focused window's titlebar. See texture section above.
Default is *Solid*
Default is *Solid*.
*window.active.title.bg.color*
Background color for the focused window's titlebar. See texture section
@ -144,7 +144,7 @@ window.*.title.bg.colorTo.splitTo: #557485
*window.inactive.title.bg*
Texture for non-focused windows' titlebars. See texture section above.
Default is *Solid*
Default is *Solid*.
*window.inactive.title.bg.color*
Background color for non-focused windows' titlebars. See texture section
@ -470,7 +470,7 @@ all are supported.
Width of magnifier window border in pixels. Default is 1.
*magnifier.border.color*
Color of the magnfier window border. Default is #ff0000 (red).
Color of the magnifier window border. Default is #ff0000 (red).
# BUTTONS

View file

@ -70,6 +70,14 @@ the `--exit` and `--reconfigure` options use.
session clients support both X11 and Wayland, this command line option
avoids re-writes and fragmentation.
*-t, --title* <fmtstr>
Set the window title for labwc to use when it is running in a window
(i.e. nested in a compositor). <fmtstr> is a format string to be used as
the window title, replacing `%o` with the name of the output
region. This is useful when simulating multiple screens, such as with
running labwc with the environment variable `WLR_WL_OUTPUTS=2`. In this
case, `%o` will be unique per simulated screen.
*-v, --version*
Show the version number and quit

View file

@ -23,7 +23,7 @@
Any menu with the id "workspaces" will be hidden
if there is only a single workspace available.
-->
<menu id="client-send-to-menu"/>
<menu id="client-send-to-menu" />
<!--
openbox default workspace selector
to use replace above workspace menu with the example below
@ -56,9 +56,9 @@
# A prompt can be used as follows:
<item label="Exit">
<action name="If">
<prompt message="Do you really want to exit the compositor?"/>
<prompt message="Do you really want to exit the compositor?" />
<then>
<action name="Exit"/>
<action name="Exit" />
</then>
</action>
</item>

View file

@ -279,6 +279,9 @@
<keybind key="W-a">
<action name="ToggleMaximize" />
</keybind>
<keybind key="W-d">
<action name="ToggleShowDesktop" />
</keybind>
<keybind key="W-Left">
<action name="SnapToEdge" direction="left" combine="yes" />
</keybind>
@ -642,10 +645,10 @@
# string and '?' matches any single character.
<windowRules>
<windowRule identifier="*"><action name="Maximize"/></windowRule>
<windowRule identifier="foo" serverDecoration="yes"/>
<windowRule title="bar" serverDecoration="yes"/>
<windowRule identifier="baz" title="quax" serverDecoration="yes"/>
<windowRule identifier="*"><action name="Maximize" /></windowRule>
<windowRule identifier="foo" serverDecoration="yes" />
<windowRule title="bar" serverDecoration="yes" />
<windowRule identifier="baz" title="quax" serverDecoration="yes" />
</windowRules>
# Example below for `lxqt-panel` and `pcmanfm-qt \-\-desktop`
@ -656,18 +659,18 @@
<windowRule identifier="lxqt-panel" matchOnce="true">
<skipTaskbar>yes</skipTaskbar>
<action name="MoveTo" x="0" y="0" />
<action name="ToggleAlwaysOnTop"/>
<action name="ToggleAlwaysOnTop" />
</windowRule>
<windowRule title="pcmanfm-desktop*">
<skipTaskbar>yes</skipTaskbar>
<skipWindowSwitcher>yes</skipWindowSwitcher>
<fixedPosition>yes</fixedPosition>
<action name="MoveTo" x="0" y="0" />
<action name="ToggleAlwaysOnBottom"/>
<action name="ToggleAlwaysOnBottom" />
</windowRule>
<windowRule identifier="org.qutebrowser.qutebrowser">
<action name="ResizeTo" width="1024" height="800" />
<action name="AutoPlace"/>
<action name="AutoPlace" />
</windowRule>
</windowRules>
-->

View file

@ -28,6 +28,9 @@ static struct key_combos {
}, {
.binding = "W-a",
.action = "ToggleMaximize",
}, {
.binding = "W-d",
.action = "ToggleShowDesktop",
}, {
.binding = "W-Left",
.action = "SnapToEdge",
@ -141,14 +144,14 @@ static struct key_combos {
* <mouse>
* <context name="Maximize">
* <mousebind button="Left" action="Click">
* <action name="Focus"/>
* <action name="Raise"/>
* <action name="ToggleMaximize"/>
* <action name="Focus" />
* <action name="Raise" />
* <action name="ToggleMaximize" />
* </mousebind>
* </context>
* <context name="Root">
* <mousebind direction="Up" action="Scroll">
* <action name="GoToDesktop" to="left" wrap="yes"/>
* <action name="GoToDesktop" to="left" wrap="yes" />
* </mousebind>
* </context>
* </mouse>

View file

@ -194,6 +194,13 @@ struct server {
struct wlr_xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager;
struct wl_listener xdg_toplevel_icon_set_icon;
struct {
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *manager;
struct {
struct wl_listener new_request;
} on;
} toplevel_capture;
/* front to back order */
struct wl_list views;
uint64_t next_view_creation_id;
@ -315,6 +322,8 @@ struct server {
struct sfdo *sfdo;
pid_t primary_client_pid;
char *title_fmt;
};
/* defined in main.c */

View file

@ -130,7 +130,7 @@ void scaled_buffer_request_update(struct scaled_buffer *self,
/**
* scaled_buffer_invalidate_sharing - clear the list of entire cached
* scaled_buffers used to share visually dupliated buffers. This should
* scaled_buffers used to share visually duplicated buffers. This should
* be called on Reconfigure to force updates of newly created
* scaled_buffers rather than reusing ones created before Reconfigure.
*/

View file

@ -177,6 +177,12 @@ struct view {
char *title;
char *app_id; /* WM_CLASS for xwayland windows */
struct {
struct wlr_scene *scene;
struct wlr_ext_image_capture_source_v1 *source;
struct wl_listener on_capture_source_destroy;
} capture;
bool mapped;
bool been_mapped;
uint64_t creation_id;
@ -319,6 +325,7 @@ struct xdg_toplevel_view {
/* Events unique to xdg-toplevel views */
struct wl_listener set_app_id;
struct wl_listener request_show_window_menu;
struct wl_listener set_parent;
struct wl_listener new_popup;
};

View file

@ -1,7 +1,7 @@
project(
'labwc',
'c',
version: '0.9.5',
version: '0.20.0',
license: 'GPL-2.0-only',
meson_version: '>=0.59.0',
default_options: [
@ -53,7 +53,7 @@ add_project_arguments('-DLABWC_VERSION=@0@'.format(version), language: 'c')
wlroots = dependency(
'wlroots-0.20',
default_options: ['default_library=static', 'examples=false'],
version: ['>=0.20.0', '<0.21.0'],
version: ['>=0.20.1', '<0.21.0'],
)
wlroots_has_xwayland = wlroots.get_variable('have_xwayland') == 'true'

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2025-08-15 20:01+0000\n"
"Last-Translator: Ettore Atalan <atalanttore@googlemail.com>\n"
"PO-Revision-Date: 2026-05-18 18:28+0000\n"
"Last-Translator: Demian <Demian@gmx.co.uk>\n"
"Language-Team: German <https://translate.lxqt-project.org/projects/labwc/"
"labwc/de/>\n"
"Language: de\n"
@ -21,7 +21,7 @@ msgstr ""
#: src/menu/menu.c:1016
msgid "Go there..."
msgstr "Dorthin gehen..."
msgstr "Dorthin wechseln ..."
#: src/menu/menu.c:1034
msgid "Terminal"
@ -61,11 +61,11 @@ msgstr "Immer im Vordergrund"
#: src/menu/menu.c:1071
msgid "Move Left"
msgstr "nach links"
msgstr "Nach links"
#: src/menu/menu.c:1078
msgid "Move Right"
msgstr "nach rechts"
msgstr "Nach rechts"
#: src/menu/menu.c:1083
msgid "Always on Visible Workspace"

View file

@ -146,7 +146,7 @@ struct action_arg_list {
* Will expand to:
*
* enum action_type {
* ACTION_TYPE_INVALID,
* ACTION_TYPE_INVALID = 0,
* ACTION_TYPE_NONE,
* ACTION_TYPE_CLOSE,
* ACTION_TYPE_KILL,
@ -1313,7 +1313,7 @@ run_action(struct view *view, struct action *action,
/*
* To support only setting one of width/height
* in <action name="ResizeTo" width="" height=""/>
* in <action name="ResizeTo" width="" height="" />
* we fall back to current dimension when unset.
*/
struct wlr_box box = {

View file

@ -614,9 +614,9 @@ fill_mousebind(xmlNode *node, const char *context)
/*
* Example of what we are parsing:
* <mousebind button="Left" action="DoubleClick">
* <action name="Focus"/>
* <action name="Raise"/>
* <action name="ToggleMaximize"/>
* <action name="Focus" />
* <action name="Raise" />
* <action name="ToggleMaximize" />
* </mousebind>
*/

View file

@ -75,6 +75,9 @@ ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
return;
}
/* In support for ext-toplevel-capture */
ext_toplevel->handle->data = view;
/* Client side requests */
ext_toplevel->on.handle_destroy.notify = handle_handle_destroy;
wl_signal_add(&ext_toplevel->handle->events.destroy, &ext_toplevel->on.handle_destroy);

View file

@ -226,7 +226,7 @@ out:
/*
* Openbox built-in icons are not bigger than 8x8, so have only written this
* function to cope wit that max size
* function to cope with that max size
*/
#define LABWC_BUILTIN_ICON_MAX_SIZE (8)

View file

@ -9,6 +9,7 @@
#include "common/font.h"
#include "common/macros.h"
#include "common/spawn.h"
#include "common/string-helpers.h"
#include "config/rcxml.h"
#include "config/session.h"
#include "labwc.h"
@ -37,6 +38,7 @@ static const struct option long_options[] = {
{"reconfigure", no_argument, NULL, 'r'},
{"startup", required_argument, NULL, 's'},
{"session", required_argument, NULL, 'S'},
{"title", required_argument, NULL, 't'},
{"version", no_argument, NULL, 'v'},
{"verbose", no_argument, NULL, 'V'},
{0, 0, 0, 0}
@ -53,6 +55,7 @@ static const char labwc_usage[] =
" -r, --reconfigure Reload the compositor configuration\n"
" -s, --startup <command> Run command on startup\n"
" -S, --session <command> Run command on startup and terminate on exit\n"
" -t, --title <fmtstr> Specify title to use when running in a window\n"
" -v, --version Show version number and quit\n"
" -V, --verbose Enable more verbose logging\n";
@ -67,7 +70,7 @@ static void
print_version(void)
{
#define FEATURE_ENABLED(feature) (HAVE_##feature ? "+" : "-")
printf("labwc %s (%sxwayland %snls %srsvg %slibsfdo) running on wlroots %d.%d.%d\n",
printf("labwc %s (%sxwayland %snls %srsvg %slibsfdo) wlroots-%d.%d.%d\n",
LABWC_VERSION,
FEATURE_ENABLED(XWAYLAND),
FEATURE_ENABLED(NLS),
@ -178,7 +181,7 @@ main(int argc, char *argv[])
int c;
while (1) {
int index = 0;
c = getopt_long(argc, argv, "c:C:dehmrs:S:vV", long_options, &index);
c = getopt_long(argc, argv, "c:C:dehmrs:S:t:vV", long_options, &index);
if (c == -1) {
break;
}
@ -207,6 +210,9 @@ main(int argc, char *argv[])
case 'S':
primary_client = optarg;
break;
case 't':
server.title_fmt = optarg;
break;
case 'v':
print_version();
exit(0);
@ -265,6 +271,10 @@ main(int argc, char *argv[])
increase_nofile_limit();
if (string_null_or_empty(server.title_fmt)) {
server.title_fmt = "labwc - %o";
}
server_init();
server_start();

View file

@ -172,7 +172,7 @@ item_parse_accelerator(struct menuitem *item, const char *text)
accel_ptr = underscore + 1;
break;
} else {
/* Ignore empty accelertor */
/* Ignore empty accelerator */
break;
}
}
@ -627,7 +627,7 @@ fill_menu(struct menu *parent, xmlNode *n)
*
* <?xml version="1.0" encoding="UTF-8"?>
* <openbox_menu>
* <menu id="root-menu" label="foo" execute="bar"/>
* <menu id="root-menu" label="foo" execute="bar" />
* </openbox_menu>
*/
} else {

View file

@ -10,6 +10,7 @@
#include "output.h"
#include <assert.h>
#include <drm_fourcc.h>
#include <glib.h>
#include <strings.h>
#include <wlr/backend/wayland.h>
#include <wlr/config.h>
@ -26,6 +27,7 @@
#include "common/macros.h"
#include "common/mem.h"
#include "common/scene-helpers.h"
#include "common/string-helpers.h"
#include "config/rcxml.h"
#include "labwc.h"
#include "layers.h"
@ -605,9 +607,10 @@ handle_new_output(struct wl_listener *listener, void *data)
}
if (wlr_output_is_wl(wlr_output)) {
char title[64];
snprintf(title, sizeof(title), "%s - %s", "labwc", wlr_output->name);
wlr_wl_output_set_title(wlr_output, title);
GString *title = g_string_new(server.title_fmt);
g_string_replace(title, "%o", wlr_output->name, 0);
wlr_wl_output_set_title(wlr_output, title->str);
g_string_free(title, TRUE);
wlr_wl_output_set_app_id(wlr_output, "labwc");
}

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#define _POSIX_C_SOURCE 200809L
#include "config.h"
#include <assert.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
@ -414,6 +415,39 @@ handle_renderer_lost(struct wl_listener *listener, void *data)
wlr_renderer_destroy(old_renderer);
}
static void
handle_toplevel_capture_source_destroy(struct wl_listener *listener, void *data)
{
struct view *view = wl_container_of(listener, view, capture.on_capture_source_destroy);
assert(view->capture.source);
view->capture.source = NULL;
wl_list_remove(&listener->link);
wl_list_init(&listener->link);
}
static void
handle_toplevel_capture_request(struct wl_listener *listener, void *data)
{
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data;
struct view *view = request->toplevel_handle->data;
assert(view);
wlr_log(WLR_INFO, "Capturing toplevel %s", view->app_id);
if (!view->capture.source) {
view->capture.source = wlr_ext_image_capture_source_v1_create_with_scene_node(
&view->capture.scene->tree.node, server.wl_event_loop,
server.allocator, server.renderer);
assert(view->capture.source);
view->capture.on_capture_source_destroy.notify =
handle_toplevel_capture_source_destroy;
wl_signal_add(&view->capture.source->events.destroy,
&view->capture.on_capture_source_destroy);
}
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
request, view->capture.source);
}
void
server_init(void)
{
@ -693,6 +727,19 @@ server_init(void)
wlr_screencopy_manager_v1_create(server.wl_display);
wlr_ext_image_copy_capture_manager_v1_create(server.wl_display, 1);
wlr_ext_output_image_capture_source_manager_v1_create(server.wl_display, 1);
server.toplevel_capture.manager =
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(
server.wl_display, 1);
if (server.toplevel_capture.manager) {
server.toplevel_capture.on.new_request.notify = handle_toplevel_capture_request;
wl_signal_add(&server.toplevel_capture.manager->events.new_request,
&server.toplevel_capture.on.new_request);
} else {
/* Allow safe removal on shutdown */
wl_list_init(&server.toplevel_capture.on.new_request.link);
}
wlr_data_control_manager_v1_create(server.wl_display);
wlr_ext_data_control_manager_v1_create(server.wl_display,
LAB_EXT_DATA_CONTROL_VERSION);
@ -828,6 +875,8 @@ server_finish(void)
server.drm_lease_request.notify = NULL;
}
wl_list_remove(&server.toplevel_capture.on.new_request.link);
wlr_backend_destroy(server.backend);
wlr_allocator_destroy(server.allocator);

View file

@ -788,7 +788,7 @@ entry(struct theme *theme, const char *key, const char *value)
value, "window.button.spacing");
}
/* botton hover overlay */
/* button hover overlay */
if (match_glob(key, "window.button.hover.bg.color")) {
parse_color(value, theme->window_button_hover_bg_color);
}

View file

@ -2482,6 +2482,10 @@ view_init(struct view *view)
view->title = xstrdup("");
view->app_id = xstrdup("");
view->capture.scene = wlr_scene_create();
view->capture.scene->restack_xwayland_surfaces = false;
wl_list_init(&view->capture.on_capture_source_destroy.link);
}
void
@ -2503,6 +2507,9 @@ view_destroy(struct view *view)
wl_list_remove(&view->request_fullscreen.link);
wl_list_remove(&view->set_title.link);
wl_list_remove(&view->destroy.link);
wl_list_remove(&view->capture.on_capture_source_destroy.link);
wlr_scene_node_destroy(&view->capture.scene->tree.node);
if (view->foreign_toplevel) {
foreign_toplevel_destroy(view->foreign_toplevel);

View file

@ -69,8 +69,8 @@ window_rules_get_property(struct view *view, const char *property)
* for foot's "serverDecoration" property to be "default".
*
* <windowRules>
* <windowRule identifier="*" serverDecoration="no"/>
* <windowRule identifier="foot" serverDecoration="default"/>
* <windowRule identifier="*" serverDecoration="no" />
* <windowRule identifier="foot" serverDecoration="default" />
* </windowRules>
*/
struct window_rule *rule;

View file

@ -169,4 +169,6 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
node_descriptor_create(wlr_popup->base->surface->data,
LAB_NODE_XDG_POPUP, view, /*data*/ NULL);
wlr_scene_xdg_surface_create(&view->capture.scene->tree, wlr_popup->base);
}

View file

@ -30,6 +30,8 @@
#define LAB_XDG_SHELL_VERSION 6
#define CONFIGURE_TIMEOUT_MS 100
static struct view *xdg_toplevel_view_get_root(struct view *view);
static struct xdg_toplevel_view *
xdg_toplevel_view_from_view(struct view *view)
{
@ -462,6 +464,7 @@ handle_destroy(struct wl_listener *listener, void *data)
/* Remove xdg-shell view specific listeners */
wl_list_remove(&xdg_toplevel_view->set_app_id.link);
wl_list_remove(&xdg_toplevel_view->request_show_window_menu.link);
wl_list_remove(&xdg_toplevel_view->set_parent.link);
wl_list_remove(&xdg_toplevel_view->new_popup.link);
wl_list_remove(&view->commit.link);
@ -565,6 +568,23 @@ handle_request_show_window_menu(struct wl_listener *listener, void *data)
menu_open_root(menu, cursor->x, cursor->y);
}
static void
handle_set_parent(struct wl_listener *listener, void *data)
{
struct xdg_toplevel_view *xdg_toplevel_view = wl_container_of(
listener, xdg_toplevel_view, set_parent);
struct view *view = &xdg_toplevel_view->base;
struct view *view_root = xdg_toplevel_view_get_root(view);
if (view_root == view) {
return;
}
struct wlr_scene_node *node, *tmp;
wl_list_for_each_safe(node, tmp, &view->capture.scene->tree.children, link) {
wlr_log(WLR_DEBUG, "moving capture scene node to view_root");
wlr_scene_node_reparent(node, &view_root->capture.scene->tree);
}
}
static void
handle_set_title(struct wl_listener *listener, void *data)
{
@ -1046,6 +1066,9 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
mappable_connect(&view->mappable, xdg_surface->surface,
handle_map, handle_unmap);
struct view *root_view = xdg_toplevel_view_get_root(view);
wlr_scene_xdg_surface_create(&root_view->capture.scene->tree, xdg_surface);
struct wlr_xdg_toplevel *toplevel = xdg_surface->toplevel;
CONNECT_SIGNAL(toplevel, view, destroy);
CONNECT_SIGNAL(toplevel, view, request_move);
@ -1059,6 +1082,7 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
/* Events specific to XDG toplevel views */
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, set_app_id);
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, request_show_window_menu);
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, set_parent);
CONNECT_SIGNAL(xdg_surface, xdg_toplevel_view, new_popup);
wl_list_insert(&server.views, &view->link);

View file

@ -783,6 +783,7 @@ handle_map(struct wl_listener *listener, void *data)
view->content_tree = wlr_scene_subsurface_tree_create(
view->scene_tree, view->surface);
die_if_null(view->content_tree);
wlr_scene_subsurface_tree_create(&view->capture.scene->tree, view->surface);
}
wlr_scene_node_set_enabled(&view->content_tree->node, !view->shaded);