13 Commits
Author SHA1 Message Date
A Frederick Christensen 21be76ac80 Formally not lead developers in README
User @guidocella joins dwl as a lead developer
2026-09-08 11:33:59 -05:00
julmajustus 70c33c015a Remove rendermon pending resize frame skip
This is no longer needed as wlroots => 0.19 handles this internally via scene-level surface state tracking and
linux-drm-syncobj explicit sync.

The manual commit skip now causes the c->resize to be stuck on non-zero
state which leads to choppy resizing experience.
2026-09-08 17:28:19 +02:00
Guido Cella ee788f0149 update wlroots version in commented variables 2026-09-08 11:44:44 +02:00
A Frederick Christensen 132606e133 add support for ext-image-copy-capture-v1 and ext-image-capture-source-v1 (wlroots!4545) 2026-09-08 11:44:44 +02:00
Thanatos 49ca434514 Bumped to 0.9 for wlroots-0.20.0. Updated cursor image buffer handling for xwayland 2026-09-08 11:44:44 +02:00
save196 babccfe6dc Preserve asleep disabled outputs in output config 2026-09-08 11:39:37 +02:00
klim 4847f97678 Clear surface->data on unmap to fix idle-inhibitor use-after-free
mapnotify() stores the client's scene tree in client_surface(c)->data;
checkidleinhibitor() later reads it back as a wlr_scene_tree and calls
wlr_scene_node_coords() on it. unmapnotify() frees the scene tree with
wlr_scene_node_destroy() but leaves surface->data dangling, so the next
arrange() -> checkidleinhibitor() dereferences freed memory and crashes
(SIGSEGV) whenever an idle inhibitor outlives the unmap.

Reset the pointer to NULL on unmap so the existing !tree guard handles it.
2026-09-08 09:30:56 +02:00
Alex Denes 04279f28e0 Remove decoration event listeners on destroynotify
When destroynotify doesn't clean up these listeners it causes a crash once the cleanup of the decoration is triggered

Thanks to kennylevinsen - https://codeberg.org/dwl/dwl/issues/1205#issuecomment-22424401
2026-09-06 13:52:31 +00:00
Alex Denes f4dfdabd0b NULL out decoration on destroy 2026-09-06 13:52:31 +00:00
Diego Viola a2d03cf618 Remove trailing whitespace from README 2026-03-02 02:13:43 +01:00
Diego Viola cb4cc3ae8f Fix typos 2026-02-25 02:38:09 -03:00
thanatos 9b76ee8e90 Updated README to clarify branch roles
This change effectively reverts DWL to the prior development model, where development of DWL itself happens against the current wlroots release, and changes in anticipation of the next wlroots release are made on a separate branch.
2026-02-21 19:50:17 +01:00
thanatos 908a73da82 Corrected README 2026-02-21 16:53:19 +01:00
4 changed files with 48 additions and 34 deletions
+4
View File
@@ -20,6 +20,7 @@ all: dwl
dwl: dwl.o util.o
$(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
ext-image-copy-capture-v1-protocol.h \
pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
util.o: util.c util.h
@@ -33,6 +34,9 @@ WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols`
cursor-shape-v1-protocol.h:
$(WAYLAND_SCANNER) enum-header \
$(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@
ext-image-copy-capture-v1-protocol.h:
$(WAYLAND_SCANNER) enum-header \
$(WAYLAND_PROTOCOLS)/staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml $@
pointer-constraints-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) enum-header \
$(WAYLAND_PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@
+16 -9
View File
@@ -1,7 +1,7 @@
# dwl - dwm for Wayland
Join us on our [Discord server]
Or Matrix: [#dwl-official:matrix.org]
Join us on our [Discord server]
Or Matrix: [#dwl-official:matrix.org]
Or on our IRC channel: [#dwl on Libera Chat]
dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is
@@ -24,12 +24,14 @@ with each release on the [release] page
### Development branch [main]
Active development progresses on the `main` branch. The `main` branch is built
against a late (and often changing) git commit of wlroots. While the adventurous
are welcome to use `main`, it is a rocky road. Using `main` requires that the
user be willing to chase git commits of wlroots. Testing development pull
requests may involve merging unmerged pull requests in [wlroots]' git repository
and/or git commits of wayland.
against the latest release of [wlroots]. PRs should target this branch unless they
depend on functionality that is not in the current release of `wlroots`.
### Preview branch [wlroots-next]
The `wlroots-next` branch is built against the git version of [wlroots], which
is unstable and changes frequently. PRs requiring functionality from the git
version of `wlroots` should target this branch.
### Building dwl
dwl has the following dependencies:
- libinput
@@ -191,6 +193,10 @@ inspiration, and to the various contributors to the project, including:
and for helping to keep the project running
- Stivvo for output management and fullscreen support, and patch maintenance
Also, thanks to our current lead developers:
- @thanatos
- @guidocella
[wlroots]: https://gitlab.freedesktop.org/wlroots
[dwm]: https://dwm.suckless.org/
@@ -203,6 +209,7 @@ inspiration, and to the various contributors to the project, including:
[dwl-patches]: https://codeberg.org/dwl/dwl-patches
[list of useful resources on our wiki]: https://codeberg.org/dwl/dwl/wiki/Home#migrating-from-x
[main]: https://codeberg.org/dwl/dwl/src/branch/main
[wlroots-next]: https://codeberg.org/dwl/dwl/src/branch/wlroots-next
[release]: https://codeberg.org/dwl/dwl/releases
[runit]: http://smarden.org/runit/faq.html#userservices
[s6]: https://skarnet.org/software/s6/
@@ -210,4 +217,4 @@ inspiration, and to the various contributors to the project, including:
[wiki]: https://codeberg.org/dwl/dwl/wiki/Home#compatible-status-bars
[Discord server]: https://discord.gg/jJxZnrGPWN
[Wayland]: https://wayland.freedesktop.org/
[#dwl-official:matrix.org]: https://matrix.to/#/#dwl-official:matrix.org
[#dwl-official:matrix.org]: https://matrix.to/#/#dwl-official:matrix.org
+7 -7
View File
@@ -1,4 +1,4 @@
_VERSION = 0.8-dev
_VERSION = 0.9-dev
VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config
@@ -8,8 +8,8 @@ PREFIX = /usr/local
MANDIR = $(PREFIX)/share/man
DATADIR = $(PREFIX)/share
WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19`
WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.20`
WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.20`
# Allow using an alternative wlroots installation
# This has to have all the includes required by wlroots, e.g:
@@ -17,12 +17,12 @@ WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/include
# Set -rpath to avoid using the wrong library.
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.19
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.20
# Assuming you ran "meson setup --prefix ${PWD}/0.19 build && ninja -C build install"
# Assuming you ran "meson setup --prefix ${PWD}/0.20 build && ninja -C build install"
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/0.19/include/wlroots-0.19
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.19/lib64 -L$(PWD)/wlroots/0.19/lib64 -lwlroots-0.19
# -I$(PWD)/wlroots/0.20/include/wlroots-0.20
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.20/lib64 -L$(PWD)/wlroots/0.20/lib64 -lwlroots-0.20
XWAYLAND =
XLIBS =
+21 -18
View File
@@ -25,6 +25,8 @@
#include <wlr/types/wlr_drm.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_ext_data_control_v1.h>
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
#include <wlr/types/wlr_fractional_scale_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
@@ -69,6 +71,7 @@
#include <xcb/xcb_icccm.h>
#endif
#include "xdg-shell-protocol.h"
#include "util.h"
/* macros */
@@ -586,7 +589,7 @@ arrangelayers(Monitor *m)
arrange(m);
}
/* Arrange non-exlusive surfaces from top->bottom */
/* Arrange non-exclusive surfaces from top->bottom */
for (i = 3; i >= 0; i--)
arrangelayer(m, &m->layers[i], &usable_area, 0);
@@ -1242,6 +1245,7 @@ void
destroydecoration(struct wl_listener *listener, void *data)
{
Client *c = wl_container_of(listener, c, destroy_decoration);
c->decoration = NULL;
wl_list_remove(&c->destroy_decoration.link);
wl_list_remove(&c->set_decoration_mode.link);
@@ -1347,6 +1351,10 @@ destroynotify(struct wl_listener *listener, void *data)
wl_list_remove(&c->map.link);
wl_list_remove(&c->unmap.link);
wl_list_remove(&c->maximize.link);
if (c->decoration) {
wl_list_remove(&c->set_decoration_mode.link);
wl_list_remove(&c->destroy_decoration.link);
}
}
free(c);
}
@@ -2134,7 +2142,7 @@ powermgrsetmode(struct wl_listener *listener, void *data)
if (!m)
return;
m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the ouput */
m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the output */
wlr_output_state_set_enabled(&state, event->mode);
wlr_output_commit_state(m->wlr_output, &state);
@@ -2154,24 +2162,15 @@ rendermon(struct wl_listener *listener, void *data)
/* This function is called every time an output is ready to display a frame,
* generally at the output's refresh rate (e.g. 60Hz). */
Monitor *m = wl_container_of(listener, m, frame);
Client *c;
struct wlr_output_state pending = {0};
struct timespec now;
/* Render if no XDG clients have an outstanding resize and are visible on
* this monitor. */
wl_list_for_each(c, &clients, link) {
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
goto skip;
if (!wlr_scene_output_needs_frame(m->scene_output)) {
return;
}
wlr_scene_output_commit(m->scene_output, NULL);
skip:
/* Let clients know a frame has been rendered */
clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_output_send_frame_done(m->scene_output, &now);
wlr_output_state_finish(&pending);
}
void
@@ -2456,7 +2455,7 @@ setup(void)
wlr_log_init(log_level, NULL);
/* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */
* clients from the Unix socket, managing Wayland globals, and so on. */
dpy = wl_display_create();
event_loop = wl_display_get_event_loop(dpy);
@@ -2518,6 +2517,8 @@ setup(void)
wlr_data_device_manager_create(dpy);
wlr_export_dmabuf_manager_v1_create(dpy);
wlr_screencopy_manager_v1_create(dpy);
wlr_ext_image_copy_capture_manager_v1_create(dpy, 1);
wlr_ext_output_image_capture_source_manager_v1_create(dpy, 1);
wlr_data_control_manager_v1_create(dpy);
wlr_ext_data_control_manager_v1_create(dpy, 1);
wlr_primary_selection_v1_device_manager_create(dpy);
@@ -2834,6 +2835,7 @@ unmapnotify(struct wl_listener *listener, void *data)
}
wlr_scene_node_destroy(&c->scene->node);
client_surface(c)->data = NULL;
printstatus();
motionnotify(0, NULL, 0, 0, 0, 0);
}
@@ -2856,10 +2858,13 @@ updatemons(struct wl_listener *listener, void *data)
/* First remove from the layout the disabled monitors */
wl_list_for_each(m, &mons, link) {
if (m->wlr_output->enabled || m->asleep)
if (m->wlr_output->enabled)
continue;
config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
config_head->state.enabled = 0;
if (m->asleep)
continue;
/* Remove this output from the layout to avoid cursor enter inside it */
wlr_output_layout_remove(output_layout, m->wlr_output);
closemon(m);
@@ -3178,9 +3183,7 @@ xwaylandready(struct wl_listener *listener, void *data)
/* Set the default XWayland cursor to match the rest of dwl. */
if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1)))
wlr_xwayland_set_cursor(xwayland,
xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
xcursor->images[0]->width, xcursor->images[0]->height,
wlr_xwayland_set_cursor(xwayland, wlr_xcursor_image_get_buffer(xcursor->images[0]),
xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
}
#endif