Compare commits

...

13 commits

Author SHA1 Message Date
Johan Malm
f0dbad27fc build: bump version to 0.9.7 2026-04-17 20:13:43 +01:00
Johan Malm
0cc98043ec NEWS.md: update notes for 0.9.7 2026-04-17 20:04:18 +01:00
yuiiio
40787a1147 osd-thumbnail: fix failed to get client texture
Use wlr_client_buffer->texture directly instead of wlr_texture_from_buffer.
All buffers in content_tree are wlr_client_buffer.

wlr_texture_from_buffer calls client_buffer_begin_data_ptr_access which
fails when client_buffer->source == NULL (client released buffer early,
e.g. wl_shm foot-terminal).
2026-04-15 21:02:21 +01:00
Jens Peters
49ab513047 input: fix tablet tool tilt motion
Tilt axis are not relative.
2026-04-10 20:50:30 +01:00
Consolatis
541cb1b15a osd-thumbnail: handle buffer allocation failure
Fixes: #3489
2026-04-02 22:32:42 +02:00
Johan Malm
12987307a5 build: bump version to 0.9.6 2026-03-15 13:21:39 +00:00
Johan Malm
795408edf8 NEWS.md: update notes for 0.9.6 2026-03-15 13:16:18 +00:00
Consolatis
b7412c6670 xwayland: make X11 always-on-top request opt-in
Fixes: #3441
2026-03-15 13:16:18 +00:00
tokyo4j
b3aabebac0 view: clear view->{title,app_id} later in view_destroy()
...as it *feels* unsafe to call functions like `undecorate()` after
clearing view->{title,app_id}, which are expected to be non-NULL.
2026-03-15 13:16:18 +00:00
Consolatis
47d42435ae src/output.c: handle outputs with all modes failing
- To reset the mode request we were using wlr_output_state_set_mode(NULL) which is not
  allowed in wlroots. Replace it with removing the mode from the commit manually.

- Before this patch, we would assume that we can't configure an output if it doesn't have
  any fixed mode. This is not true for wayland backed nested outputs. Replace the fixed
  return false with wlr_output_test_state().

- Prevent configuring the output if the test fails as the current behavior was a
  workaround for the hardcoded return false in case there were no fixed modes available.

Fixes: #3428
Reported-By: kode54
2026-03-15 13:16:18 +00:00
Consolatis
691c1fd0bd src/cycle: handle views without output
Fixes: #3425
Reported-By: kode54
2026-03-15 13:16:18 +00:00
Alexander Ziaee
c525d5f46a labwc-config.5: document mouse cursor variables
It was written that mouse cursor size can be set with XCURSOR_SIZE.
However, XCURSOR_THEME is also required, which exists in the context
of XCURSOR_PATH. Break them down in the ENVIRONMENT VARIABLES section.

Reported by: Consolatis (PATH)
Reported by: Jan Beich <jbeich@FreeBSD.org> (THEME)
Reported by: Thomas Dickey <dickey@invisible-island.net> (SIZE)
2026-03-15 13:16:18 +00:00
Tobias Bengfort
39851ca304 src/server.c: fix name of xdg-dialog-v1 global for sandbox permission 2026-03-15 13:16:18 +00:00
14 changed files with 149 additions and 28 deletions

80
NEWS.md
View file

@ -9,6 +9,8 @@ The format is based on [Keep a Changelog]
| Date | All Changes | wlroots version | lines-of-code | | Date | All Changes | wlroots version | lines-of-code |
|------------|---------------|-----------------|---------------| |------------|---------------|-----------------|---------------|
| 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 | | 2026-03-04 | [0.9.5] | 0.19.2 | 29251 |
| 2026-02-27 | [0.9.4] | 0.19.2 | 29225 | | 2026-02-27 | [0.9.4] | 0.19.2 | 29225 |
| 2025-12-19 | [0.9.3] | 0.19.2 | 28968 | | 2025-12-19 | [0.9.3] | 0.19.2 | 28968 |
@ -41,7 +43,8 @@ The format is based on [Keep a Changelog]
| 2021-04-15 | [0.2.0] | 0.13.0 | 5011 | | 2021-04-15 | [0.2.0] | 0.13.0 | 5011 |
| 2021-03-05 | [0.1.0] | 0.12.0 | 4627 | | 2021-03-05 | [0.1.0] | 0.12.0 | 4627 |
[unreleased]: NEWS.md#unreleased [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 [0.9.5]: NEWS.md#095---2026-03-04
[0.9.4]: NEWS.md#094---2026-02-27 [0.9.4]: NEWS.md#094---2026-02-27
[0.9.3]: NEWS.md#093---2025-12-19 [0.9.3]: NEWS.md#093---2025-12-19
@ -108,9 +111,64 @@ 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 [wlroots-5098]:https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5098
[gtk-8792]: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8792 [gtk-8792]: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8792
## unreleased ## 0.9.7 - 2026-04-17
[unreleased-commits] [0.9.7-commits]
This is a small bug fix release.
```
0.9.6--------0.9.7 <--- v0.9 branch with bug-fixes only
/
/
0.9.4--------0.9.5-------- <-- master (built with wlroots-0.20)
```
## Fixed
- Fix intermittent failed-to-get-texture issue with some clients (e.g. foot)
when using the window-switcher in the thumbnail mode. [#3511] @yuiiio
- Fix tablet tool tilt motion. [#3494] @jp7677
- Handle window-switcher buffer allocation failure when in 'thumbnail' mode.
This is believed to be very unlikely to happen, but has been reported by one
user and is believed to be GPU driver related. [#3490] @Consolatis
## 0.9.6 - 2026-03-15
[0.9.6-commits]
This is an earlier-than-usual release containing bug fixes only. It has been
done on a separate branch (v0.9) to avoid the inclusion of refactoring and new
features.
```
0.9.6 <--- bug-fixes only
/
/
0.9.4--------0.9.5-------- <-- master
```
### Fixed
- Disable outputs where all modes fail [#3428] [#3429] @Consolatis @kode54
- Fix regression in `0.9.4` that causes `NextWindow` action to segfault when
no outputs are connected. This fixes a window-switcher crash with some
Nvidia GPUs/drivers after suspend [#3425] [#3430] @Consolatis
- Fix typo to allow `xdg-dialog-v1` global [#3426] @xi
### Changed
- Disallow X11 window always-on-top requests by default to fix an issue whereby
Alt+Tab cannot be used to switch to other windows when using some XWayland
Wine games [#3441]. Add window-rule property `allowAlwaysOnTop` to optionally
allow this always-on-top requests. Add the snippet below to the `rc.xml` file
to restore the previous behaviour. [#3445] @Consolatis
```
<windowRules>
<windowRule identifier="*" allowAlwaysOnTop="yes" />
</windowRules>
```
## 0.9.5 - 2026-03-04 ## 0.9.5 - 2026-03-04
@ -2607,7 +2665,8 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
ShowMenu ShowMenu
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/ [Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
[unreleased-commits]: https://github.com/labwc/labwc/compare/0.9.5...HEAD [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 [0.9.5-commits]: https://github.com/labwc/labwc/compare/0.9.4...0.9.5
[0.9.4-commits]: https://github.com/labwc/labwc/compare/0.9.3...0.9.4 [0.9.4-commits]: https://github.com/labwc/labwc/compare/0.9.3...0.9.4
[0.9.3-commits]: https://github.com/labwc/labwc/compare/0.9.2...0.9.3 [0.9.3-commits]: https://github.com/labwc/labwc/compare/0.9.2...0.9.3
@ -3135,8 +3194,21 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
[#3365]: https://github.com/labwc/labwc/pull/3365 [#3365]: https://github.com/labwc/labwc/pull/3365
[#3372]: https://github.com/labwc/labwc/pull/3372 [#3372]: https://github.com/labwc/labwc/pull/3372
[#3373]: https://github.com/labwc/labwc/pull/3373 [#3373]: https://github.com/labwc/labwc/pull/3373
[#3387]: https://github.com/labwc/labwc/pull/3387
[#3400]: https://github.com/labwc/labwc/pull/3400 [#3400]: https://github.com/labwc/labwc/pull/3400
[#3406]: https://github.com/labwc/labwc/pull/3406 [#3406]: https://github.com/labwc/labwc/pull/3406
[#3410]: https://github.com/labwc/labwc/pull/3410 [#3410]: https://github.com/labwc/labwc/pull/3410
[#3411]: https://github.com/labwc/labwc/pull/3411 [#3411]: https://github.com/labwc/labwc/pull/3411
[#3412]: https://github.com/labwc/labwc/pull/3412 [#3412]: https://github.com/labwc/labwc/pull/3412
[#3425]: https://github.com/labwc/labwc/pull/3425
[#3426]: https://github.com/labwc/labwc/pull/3426
[#3428]: https://github.com/labwc/labwc/pull/3428
[#3429]: https://github.com/labwc/labwc/pull/3429
[#3430]: https://github.com/labwc/labwc/pull/3430
[#3440]: https://github.com/labwc/labwc/pull/3440
[#3441]: https://github.com/labwc/labwc/pull/3441
[#3443]: https://github.com/labwc/labwc/pull/3443
[#3445]: https://github.com/labwc/labwc/pull/3445
[#3490]: https://github.com/labwc/labwc/pull/3490
[#3494]: https://github.com/labwc/labwc/pull/3494
[#3511]: https://github.com/labwc/labwc/pull/3511

View file

@ -1354,6 +1354,13 @@ situation.
*ignoreConfigureRequest* prevents a X11 window to position and size *ignoreConfigureRequest* prevents a X11 window to position and size
itself. itself.
*<windowRules><windowRule allowAlwaysOnTop="">* [yes|no|default]
*allowAlwaysOnTop* allows a X11 window to control its always-on-top
state ('above' in X11 terms).
Note: X11 window always-on-top requests are disallowed by default.
This window rule offers a means of allowing it.
*<windowRules><windowRule fixedPosition="">* [yes|no|default] *<windowRules><windowRule fixedPosition="">* [yes|no|default]
*fixedPosition* disallows interactive move/resize and prevents *fixedPosition* disallows interactive move/resize and prevents
re-positioning in response to changes in reserved output space, which re-positioning in response to changes in reserved output space, which
@ -1429,9 +1436,25 @@ situation.
## ENVIRONMENT VARIABLES ## ENVIRONMENT VARIABLES
*XCURSOR_THEME* and *XCURSOR_SIZE* are supported to set cursor theme *XCURSOR_PATH*
and size respectively. The default size is 24. System cursor themes can Specify a colon-separated list of paths to look for mouse cursors in.
typically be found with a command such as: Default
~/.local/share/icons:
~/.icons:
/usr/share/icons:
/usr/share/pixmaps:
~/.cursors:
/usr/share/cursors/xorg-x11:
/usr/X11R6/lib/X11/icons:
*XCURSOR_SIZE*
Specify an alternative mouse cursor size in pixels. Requires
XCURSOR_THEME to be set also. Default 24.
*XCURSOR_THEME*
Specify a mouse cursor theme within XCURSOR_PATH.
System cursor themes can typically be found with a command such as:
``` ```
find /usr/share/icons/ -type d -name "cursors" find /usr/share/icons/ -type d -name "cursors"

View file

@ -141,7 +141,7 @@ example: *LABWC_DEBUG_FOO=1 labwc*.
*LABWC_DEBUG_KEY_STATE* *LABWC_DEBUG_KEY_STATE*
Enable logging of press and release events for bound keys (generally Enable logging of press and release events for bound keys (generally
key-combinations like *Ctrl-Alt-t*) key-combinations like *Ctrl-Alt-t*).
# SEE ALSO # SEE ALSO

View file

@ -40,6 +40,7 @@ struct window_rule {
enum property ignore_configure_request; enum property ignore_configure_request;
enum property fixed_position; enum property fixed_position;
enum property icon_prefer_client; enum property icon_prefer_client;
enum property allow_always_on_top;
struct wl_list link; /* struct rcxml.window_rules */ struct wl_list link; /* struct rcxml.window_rules */
}; };

View file

@ -1,7 +1,7 @@
project( project(
'labwc', 'labwc',
'c', 'c',
version: '0.9.5', version: '0.9.7',
license: 'GPL-2.0-only', license: 'GPL-2.0-only',
meson_version: '>=0.59.0', meson_version: '>=0.59.0',
default_options: [ default_options: [

View file

@ -300,6 +300,8 @@ fill_window_rule(xmlNode *node)
set_property(content, &window_rule->ignore_configure_request); set_property(content, &window_rule->ignore_configure_request);
} else if (!strcasecmp(key, "fixedPosition")) { } else if (!strcasecmp(key, "fixedPosition")) {
set_property(content, &window_rule->fixed_position); set_property(content, &window_rule->fixed_position);
} else if (!strcasecmp(key, "allowAlwaysOnTop")) {
set_property(content, &window_rule->allow_always_on_top);
} }
} }

View file

@ -346,9 +346,11 @@ init_cycle(struct server *server, struct cycle_filter filter)
struct view *view; struct view *view;
for_each_view(view, &server->views, criteria) { for_each_view(view, &server->views, criteria) {
if (!(cycle_outputs & view->output->id_bit)) { if (filter.output != CYCLE_OUTPUT_ALL) {
if (!view->output || !(cycle_outputs & view->output->id_bit)) {
continue; continue;
} }
}
if (cycle_app_id && strcmp(view->app_id, cycle_app_id) != 0) { if (cycle_app_id && strcmp(view->app_id, cycle_app_id) != 0) {
continue; continue;
} }

View file

@ -2,6 +2,7 @@
#include <assert.h> #include <assert.h>
#include <wlr/render/allocator.h> #include <wlr/render/allocator.h>
#include <wlr/render/swapchain.h> #include <wlr/render/swapchain.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h> #include <wlr/types/wlr_scene.h>
#include "config/rcxml.h" #include "config/rcxml.h"
@ -45,8 +46,12 @@ render_node(struct server *server, struct wlr_render_pass *pass,
if (!scene_buffer->buffer) { if (!scene_buffer->buffer) {
break; break;
} }
struct wlr_texture *texture = wlr_texture_from_buffer( struct wlr_texture *texture = NULL;
server->renderer, scene_buffer->buffer); struct wlr_client_buffer *client_buffer =
wlr_client_buffer_get(scene_buffer->buffer);
if (client_buffer) {
texture = client_buffer->texture;
}
if (!texture) { if (!texture) {
break; break;
} }
@ -61,7 +66,6 @@ render_node(struct server *server, struct wlr_render_pass *pass,
}, },
.transform = scene_buffer->transform, .transform = scene_buffer->transform,
}); });
wlr_texture_destroy(texture);
break; break;
} }
case WLR_SCENE_NODE_RECT: case WLR_SCENE_NODE_RECT:
@ -85,6 +89,10 @@ render_thumb(struct output *output, struct view *view)
struct wlr_buffer *buffer = wlr_allocator_create_buffer(server->allocator, struct wlr_buffer *buffer = wlr_allocator_create_buffer(server->allocator,
view->current.width, view->current.height, view->current.width, view->current.height,
&output->wlr_output->swapchain->format); &output->wlr_output->swapchain->format);
if (!buffer) {
wlr_log(WLR_ERROR, "failed to allocate buffer for thumbnail");
return NULL;
}
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass( struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(
server->renderer, buffer, NULL); server->renderer, buffer, NULL);
render_node(server, pass, &view->content_tree->node, 0, 0); render_node(server, pass, &view->content_tree->node, 0, 0);

View file

@ -402,8 +402,6 @@ handle_tablet_tool_axis(struct wl_listener *listener, void *data)
*/ */
tool->dx = 0; tool->dx = 0;
tool->dy = 0; tool->dy = 0;
tool->tilt_x = 0;
tool->tilt_y = 0;
if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_X) { if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_X) {
tool->x = ev->x; tool->x = ev->x;

View file

@ -362,8 +362,10 @@ output_test_auto(struct wlr_output *wlr_output, struct wlr_output_state *state,
} }
/* Reset mode if none worked (we may still try to commit) */ /* Reset mode if none worked (we may still try to commit) */
wlr_output_state_set_mode(state, NULL); wlr_log(WLR_DEBUG, "no working fixed mode found for output %s", wlr_output->name);
return false; state->committed &= ~WLR_OUTPUT_STATE_MODE;
return wlr_output_test_state(wlr_output, state);
} }
static void static void
@ -378,10 +380,8 @@ configure_new_output(struct server *server, struct output *output)
/* is_client_request */ false)) { /* is_client_request */ false)) {
wlr_log(WLR_INFO, "mode test failed for output %s", wlr_log(WLR_INFO, "mode test failed for output %s",
wlr_output->name); wlr_output->name);
/* wlr_output_state_set_enabled(&output->pending, false);
* Continue anyway. For some reason, the test fails when return;
* running nested, yet the following commit succeeds.
*/
} }
if (rc.adaptive_sync == LAB_ADAPTIVE_SYNC_ENABLED) { if (rc.adaptive_sync == LAB_ADAPTIVE_SYNC_ENABLED) {

View file

@ -277,7 +277,7 @@ allow_for_sandbox(const struct wlr_security_context_v1_state *security_state,
"zxdg_importer_v1", "zxdg_importer_v1",
"zxdg_importer_v2", "zxdg_importer_v2",
"xdg_toplevel_icon_manager_v1", "xdg_toplevel_icon_manager_v1",
"xdg_dialog_v1", "xdg_wm_dialog_v1",
/* plus */ /* plus */
"wp_alpha_modifier_v1", "wp_alpha_modifier_v1",
"wp_linux_drm_syncobj_manager_v1", "wp_linux_drm_syncobj_manager_v1",

View file

@ -1541,6 +1541,9 @@ void
view_set_layer(struct view *view, enum view_layer layer) view_set_layer(struct view *view, enum view_layer layer)
{ {
assert(view); assert(view);
if (view->layer == layer) {
return;
}
view->layer = layer; view->layer = layer;
wlr_scene_node_reparent(&view->scene_tree->node, wlr_scene_node_reparent(&view->scene_tree->node,
view->workspace->view_trees[layer]); view->workspace->view_trees[layer]);
@ -2499,9 +2502,6 @@ view_destroy(struct view *view)
wl_list_remove(&view->set_title.link); wl_list_remove(&view->set_title.link);
wl_list_remove(&view->destroy.link); wl_list_remove(&view->destroy.link);
zfree(view->title);
zfree(view->app_id);
if (view->foreign_toplevel) { if (view->foreign_toplevel) {
foreign_toplevel_destroy(view->foreign_toplevel); foreign_toplevel_destroy(view->foreign_toplevel);
view->foreign_toplevel = NULL; view->foreign_toplevel = NULL;
@ -2556,6 +2556,9 @@ view_destroy(struct view *view)
assert(wl_list_empty(&view->events.set_icon.listener_list)); assert(wl_list_empty(&view->events.set_icon.listener_list));
assert(wl_list_empty(&view->events.destroy.listener_list)); assert(wl_list_empty(&view->events.destroy.listener_list));
zfree(view->title);
zfree(view->app_id);
/* Remove view from server->views */ /* Remove view from server->views */
wl_list_remove(&view->link); wl_list_remove(&view->link);
free(view); free(view);

View file

@ -110,6 +110,10 @@ window_rules_get_property(struct view *view, const char *property)
&& !strcasecmp(property, "iconPreferClient")) { && !strcasecmp(property, "iconPreferClient")) {
return rule->icon_prefer_client; return rule->icon_prefer_client;
} }
if (rule->allow_always_on_top
&& !strcasecmp(property, "allowAlwaysOnTop")) {
return rule->allow_always_on_top;
}
} }
} }
return LAB_PROP_UNSPECIFIED; return LAB_PROP_UNSPECIFIED;

View file

@ -431,6 +431,11 @@ handle_request_above(struct wl_listener *listener, void *data)
wl_container_of(listener, xwayland_view, request_above); wl_container_of(listener, xwayland_view, request_above);
struct view *view = &xwayland_view->base; struct view *view = &xwayland_view->base;
if (window_rules_get_property(view, "allowAlwaysOnTop") != LAB_PROP_TRUE) {
wlr_log(WLR_INFO, "X11 client side always on top request rejected");
return;
}
view_set_layer(view, xwayland_view->xwayland_surface->above view_set_layer(view, xwayland_view->xwayland_surface->above
? VIEW_LAYER_ALWAYS_ON_TOP : VIEW_LAYER_NORMAL); ? VIEW_LAYER_ALWAYS_ON_TOP : VIEW_LAYER_NORMAL);
} }
@ -727,8 +732,11 @@ handle_map_request(struct wl_listener *listener, void *data)
axis |= VIEW_AXIS_VERTICAL; axis |= VIEW_AXIS_VERTICAL;
} }
view_maximize(view, axis); view_maximize(view, axis);
if (window_rules_get_property(view, "allowAlwaysOnTop") == LAB_PROP_TRUE) {
view_set_layer(view, xsurface->above view_set_layer(view, xsurface->above
? VIEW_LAYER_ALWAYS_ON_TOP : VIEW_LAYER_NORMAL); ? VIEW_LAYER_ALWAYS_ON_TOP : VIEW_LAYER_NORMAL);
}
/* /*
* We could also call set_initial_position() here, but it's not * We could also call set_initial_position() here, but it's not
* really necessary until the view is actually mapped (and at * really necessary until the view is actually mapped (and at