summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author0undefined <oscar@nelin.dk>2025-10-17 15:45:28 +0000
committer0undefined <oscar@nelin.dk>2025-10-17 15:45:28 +0000
commit2d924afa8e41fe92c29724d1c36b99a4242f4f18 (patch)
tree7fc8710bdcfc1f80ee72fb4d27fab2a0f09a78b2
parent964b3f9ce49bb5d5de229ecb29d970b6bb2155a7 (diff)
parent6cd26568d5b8be2252ac0def36cd194b4fb2d7c3 (diff)
Merge remote-tracking branch 'upstream/main'
-rw-r--r--README.md42
-rw-r--r--client.h4
-rw-r--r--config.def.h2
-rw-r--r--config.mk2
-rw-r--r--dwl.1124
-rw-r--r--dwl.c47
6 files changed, 167 insertions, 54 deletions
diff --git a/README.md b/README.md
index 1bcc36e..390788d 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,9 @@ Join us on our IRC channel: [#dwl on Libera Chat]
Or on the community-maintained [Discord server].
dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is
-intended to fill the same space in the Wayland world that dwm does in X11,
+intended to fill the same space in the Wayland world that [dwm] does in X11,
primarily in terms of functionality, and secondarily in terms of
-philosophy. Like dwm, dwl is:
+philosophy. Like [dwm], dwl is:
- Easy to understand, hack on, and extend with patches
- One C source file (or a very small number) configurable via `config.h`
@@ -15,10 +15,11 @@ philosophy. Like dwm, dwl is:
## Getting Started:
### Latest semi-stable [release]
-This is probably where you want to start. This builds against the dependent
-packages' versions currently shipping in major distributions. If your
-distribution's wlroots version is older, use an earlier dwl [release] or [0.x
-branch].
+This is probably where you want to start. This builds against the [wlroots]
+versions currently shipping in major distributions. If your
+distribution's `wlroots` version is older, use an earlier dwl [release].
+The `wlroots` version against which a given `dwl` release builds is specified
+with each release on the [release] page
### Development branch [main]
Active development progresses on the `main` branch. The `main` branch is built
@@ -54,11 +55,11 @@ To enable XWayland, you should uncomment its flags in `config.mk`.
## Configuration
All configuration is done by editing `config.h` and recompiling, in the same
-manner as dwm. There is no way to separately restart the window manager in
+manner as [dwm]. There is no way to separately restart the window manager in
Wayland without restarting the entire display server, so any changes will take
effect the next time dwl is executed.
-As in the dwm community, we encourage users to share patches they have
+As in the [dwm] community, we encourage users to share patches they have
created. Check out the [dwl-patches] repository!
## Running dwl
@@ -74,7 +75,7 @@ seatd daemon.
When dwl is run with no arguments, it will launch the server and begin handling
any shortcuts configured in `config.h`. There is no status bar or other
decoration initially; these are instead clients that can be run within the
-Wayland session. Do note that the default background color is black. This can be
+Wayland session. Do note that the default background color is grey. This can be
modified in `config.h`.
If you would like to run a script or command automatically at startup, you can
@@ -102,7 +103,7 @@ automatically, you will need to configure it prior to launching `dwl`, e.g.:
Information about selected layouts, current window title, app-id, and
selected/occupied/urgent tags is written to the stdin of the `-s` command (see
-the `printstatus()` function for details). This information can be used to
+the `STATUS INFORMATION` section in `_dwl_(1)`). This information can be used to
populate an external status bar with a script that parses the
information. Failing to read this information will cause dwl to block, so if you
do want to run a startup command that does not consume the status information,
@@ -117,17 +118,26 @@ script with the line
To get a list of status bars that work with dwl consult our [wiki].
+### (Known) Java nonreparenting WM issue
+Certain IDEs don't display correctly unless an environmental variable for Java AWT
+indicates that the WM is nonreparenting.
+
+For some Java AWT-based IDEs, such as Xilinx Vivado and Microchip MPLAB X, the
+following environment variable needs to be set before running the IDE or dwl:
+
+ export _JAVA_AWT_WM_NONREPARENTING=1
+
## Replacements for X applications
You can find a [list of useful resources on our wiki].
## Background
-dwl is not meant to provide every feature under the sun. Instead, like dwm, it
+dwl is not meant to provide every feature under the sun. Instead, like [dwm], it
sticks to features which are necessary, simple, and straightforward to implement
given the base on which it is built. Implemented default features are:
-- Any features provided by dwm/Xlib: simple window borders, tags, keybindings,
+- Any features provided by [dwm]/Xlib: simple window borders, tags, keybindings,
client rules, mouse move/resize. Providing a built-in status bar is an
exception to this goal, to avoid dependencies on font rendering and/or drawing
libraries when an external bar could work well.
@@ -144,10 +154,10 @@ given the base on which it is built. Implemented default features are:
- Layer shell popups (used by Waybar)
- Damage tracking provided by scenegraph API
-Given the Wayland architecture, dwl has to implement features from dwm **and**
+Given the Wayland architecture, dwl has to implement features from [dwm] **and**
the xorg-server. Because of this, it is impossible to maintain the original
project goal of 2000 SLOC and have a reasonably complete compositor with
-features comparable to dwm. However, this does not mean that the code will grow
+features comparable to [dwm]. However, this does not mean that the code will grow
indiscriminately. We will try to keep the code as small as possible.
Features under consideration (possibly as patches) are:
@@ -171,7 +181,7 @@ developers. This was made possible in many cases by looking at how sway
accomplished something, then trying to do the same in as suckless a way as
possible.
-Many thanks to suckless.org and the dwm developers and community for the
+Many thanks to suckless.org and the [dwm] developers and community for the
inspiration, and to the various contributors to the project, including:
- **Devin J. Pohly for creating and nurturing the fledgling project**
@@ -181,6 +191,8 @@ inspiration, and to the various contributors to the project, including:
- Stivvo for output management and fullscreen support, and patch maintenance
+[wlroots]: https://gitlab.freedesktop.org/wlroots
+[dwm]: https://dwm.suckless.org/
[`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User
[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl
[0.7-rc1]: https://codeberg.org/dwl/dwl/releases/tag/v0.7-rc1
diff --git a/client.h b/client.h
index 18000b0..83e1c57 100644
--- a/client.h
+++ b/client.h
@@ -276,8 +276,8 @@ client_is_stopped(Client *c)
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) {
- /* This process is not our child process, while is very unluckely that
- * it is stopped, in order to do not skip frames assume that it is. */
+ /* This process is not our child process, while is very unlikely that
+ * it is stopped, in order to do not skip frames, assume that it is. */
if (errno == ECHILD)
return 1;
} else if (in.si_pid) {
diff --git a/config.def.h b/config.def.h
index d366ac8..7806271 100644
--- a/config.def.h
+++ b/config.def.h
@@ -18,7 +18,7 @@ static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = {"monospace:size=10"};
static const float rootcolor[] = COLOR(0x000000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
-static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
+static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */
static const uint32_t col_border = 0x4f5b58ff;
diff --git a/config.mk b/config.mk
index e2f1816..eb08a05 100644
--- a/config.mk
+++ b/config.mk
@@ -11,7 +11,7 @@ DATADIR = $(PREFIX)/share
WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19`
WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
-# Allow using an alternative wlroots installations
+# Allow using an alternative wlroots installation
# This has to have all the includes required by wlroots, e.g:
# Assuming wlroots git repo is "${PWD}/wlroots" and you only ran "meson setup build && ninja -C build"
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
diff --git a/dwl.1 b/dwl.1
index 780c78f..7fee870 100644
--- a/dwl.1
+++ b/dwl.1
@@ -37,7 +37,7 @@ starts a shell process running
when starting.
When stopping, it sends
.Dv SIGTERM
-to the child process and waits for it to exit.
+to the child process group and waits for it to exit.
.Pp
Users are encouraged to customize
.Nm
@@ -55,10 +55,10 @@ Move window to a single tag.
Toggle tag for window.
.It Mod-p
Spawn
-.Nm wmenu-run .
+.Xr wmenu-run 1 .
.It Mod-Shift-Return
Spawn
-.Nm foot .
+.Xr foot 1 .
.It Mod-[jk]
Move focus down/up the stack.
.It Mod-[id]
@@ -100,6 +100,114 @@ Quit
.Nm .
.El
These might differ depending on your keyboard layout.
+.Ss Mouse commands
+.Bl -tag -width 20n -offset indent -compact
+.It Mod-Button1
+Move focused window while dragging.
+Tiled windows will be toggled to the floating state.
+.It Mod-Button2
+Toggle focused window between floating and tiled state.
+.It Mod-Button3
+Resize focused window while dragging.
+Tiled windows will be toggled to the floating state.
+.El
+.Sh STATUS INFORMATION
+.Nm
+writes its status information to standard output.
+If the
+.Fl s
+option is given, the status information is written to the standard input of the
+child process instead.
+.Pp
+Said information has the following format:
+.Bd -ragged -offset indent
+.Ar <monitor>
+.Ar <component>
+.Ar <data>
+.Ed
+.Pp
+.Bl -tag -width 11n -offset 0 -compact
+.It Ar <monitor>
+is the name given to the output.
+.It Ar <component>
+is one of (in order)
+.Em title ,
+.Em appid ,
+.Em fullscreen ,
+.Em floating ,
+.Em selmon ,
+.Em tags ,
+.Em layout .
+.It Ar <data>
+changes depending on
+.Ar <component> .
+.Bl -tag -width 10n -compact
+.It Em title
+The title of the focused window on
+.Ar <monitor>
+or nothing if there is no focused window.
+.It Em appid
+The app_id of the focused window on
+.Ar <monitor>
+or nothing if there is no focused window.
+.It Em fullscreen
+Prints 1 if the focused window on
+.Ar <monitor>
+is in fullscreen state, otherwise prints 0. If there is no focused
+window it prints nothing.
+.It Em floating
+Prints 1 if the focused window on
+.Ar <monitor>
+is in floating state, otherwise prints 0. If there is no focused
+window it prints nothing.
+.It Em selmon
+Prints 1 if
+.Ar <monitor>
+is the selected monitor, otherwise prints 0.
+.It Em tags
+Prints four bitmasks in the following order:
+.Bl -bullet -width 2n -compact
+.It
+Occupied tags of
+.Ar <monitor> .
+.It
+Selected tags of
+.Ar <monitor> .
+.It
+Tags of the focused window on
+.Ar <monitor> .
+.It
+Tags where a window on
+.Ar <monitor>
+requested activation or has urgency hints.
+.El
+The bitmasks are 32-bit unsigned decimal integers.
+.It Em layout
+Prints the symbol of the current layout.
+.El
+.El
+.Ss Examples
+When there is a selected window:
+.Bd -literal -offset indent
+HDMI\-A\-1 title \(ti/source/repos/dwl > man \-l dwl.1
+HDMI\-A\-1 appid footclient
+HDMI\-A\-1 fullscreen 0
+HDMI\-A\-1 floating 0
+HDMI\-A\-1 selmon 1
+HDMI\-A\-1 tags 271 4 4 0
+HDMI\-A\-1 layout [T]
+.Ed
+.Pp
+When there is no selected window:
+.Bd -literal -offset indent
+HDMI\-A\-1 title
+HDMI\-A\-1 appid
+HDMI\-A\-1 fullscreen
+HDMI\-A\-1 floating
+HDMI\-A\-1 selmon 1
+HDMI\-A\-1 tags 271 512 0 0
+HDMI\-A\-1 layout [T]
+.Ed
.Sh ENVIRONMENT
These environment variables are used by
.Nm :
@@ -142,17 +250,9 @@ Start
with s6 in the background:
.Dl dwl \-s \(aqs6\-svscan <&\-\(aq
.Sh SEE ALSO
+.Xr dwm 1 ,
.Xr foot 1 ,
.Xr wmenu 1 ,
-.Xr dwm 1 ,
.Xr xkeyboard-config 7
-.Sh CAVEATS
-The child process's standard input is connected with a pipe to
-.Nm .
-If the child process neither reads from the pipe nor closes its
-standard input,
-.Nm
-will freeze after a while due to it blocking when writing to the full
-pipe buffer.
.Sh BUGS
All of them.
diff --git a/dwl.c b/dwl.c
index cbe9b1b..d129406 100644
--- a/dwl.c
+++ b/dwl.c
@@ -760,8 +760,8 @@ axisnotify(struct wl_listener *listener, void *data)
* for example when you move the scroll wheel. */
struct wlr_pointer_axis_event *event = data;
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
- /* TODO: allow usage of scroll whell for mousebindings, it can be implemented
- * checking the event's orientation and the delta of the event */
+ /* TODO: allow usage of scroll wheel for mousebindings, it can be implemented
+ * by checking the event's orientation and the delta of the event */
/* Notify the client with pointer focus of the axis event. */
wlr_seat_pointer_notify_axis(seat,
event->time_msec, event->orientation, event->delta,
@@ -989,8 +989,8 @@ cleanup(void)
destroykeyboardgroup(&kb_group->destroy, NULL);
- /* If it's not destroyed manually it will cause a use-after-free of wlr_seat.
- * Destroy it until it's fixed in the wlroots side */
+ /* If it's not destroyed manually, it will cause a use-after-free of wlr_seat.
+ * Destroy it until it's fixed on the wlroots side */
wlr_backend_destroy(backend);
wl_display_destroy(dpy);
@@ -1028,6 +1028,8 @@ cleanupmon(struct wl_listener *listener, void *data)
wl_list_remove(&m->frame.link);
wl_list_remove(&m->link);
wl_list_remove(&m->request_state.link);
+ if (m->lock_surface)
+ destroylocksurface(&m->destroy_lock_surface, NULL);
m->wlr_output->data = NULL;
wlr_output_layout_remove(output_layout, m->wlr_output);
wlr_scene_output_destroy(m->scene_output);
@@ -1148,7 +1150,7 @@ commitnotify(struct wl_listener *listener, void *data)
/*
* Get the monitor this client will be rendered on
* Note that if the user set a rule in which the client is placed on
- * a different monitor based on its title this will likely select
+ * a different monitor based on its title, this will likely select
* a wrong monitor.
*/
applyrules(c);
@@ -1516,7 +1518,7 @@ cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
void
cursorframe(struct wl_listener *listener, void *data)
{
- /* This event is forwarded by the cursor when a pointer emits an frame
+ /* This event is forwarded by the cursor when a pointer emits a frame
* event. Frame events are sent after regular pointer events to group
* multiple events together. For instance, two axis events may happen at the
* same time, in which case a frame event won't be sent in between. */
@@ -2174,7 +2176,7 @@ focusstack(const Arg *arg)
if (mousefollowsfocus) warpcursortoclient(c);
}
-/* We probably should change the name of this, it sounds like
+/* We probably should change the name of this: it sounds like it
* will focus the topmost client of this mon, when actually will
* only return that client */
Client *
@@ -2526,8 +2528,8 @@ mapnotify(struct wl_listener *listener, void *data)
/* Set initial monitor, tags, floating status, and focus:
* we always consider floating, clients that have parent and thus
- * we set the same tags and monitor than its parent, if not
- * try to apply rules for them */
+ * we set the same tags and monitor as its parent.
+ * If there is no parent, apply rules */
if ((p = client_get_parent(c))) {
c->isfloating = 1;
setmon(c, p->mon, p->tags);
@@ -2630,8 +2632,7 @@ motionabsolute(struct wl_listener *listener, void *data)
* motion event, from 0..1 on each axis. This happens, for example, when
* wlroots is running under a Wayland window rather than KMS+DRM, and you
* move the mouse over the window. You could enter the window from any edge,
- * so we have to warp the mouse there. There is also some hardware which
- * emits these events. */
+ * so we have to warp the mouse there. Also, some hardware emits these events. */
struct wlr_pointer_motion_absolute_event *event = data;
double lx, ly, dx, dy;
@@ -2753,7 +2754,7 @@ moveresize(const Arg *arg)
case CurMove:
grabcx = (int)round(cursor->x) - grabc->geom.x;
grabcy = (int)round(cursor->y) - grabc->geom.y;
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "all-scroll");
break;
case CurResize:
/* Doesn't work for X11 output - the next absolute motion event
@@ -2816,9 +2817,9 @@ apply_or_test:
ok &= test ? wlr_output_test_state(wlr_output, &state)
: wlr_output_commit_state(wlr_output, &state);
- /* Don't move monitors if position wouldn't change, this to avoid
- * wlroots marking the output as manually configured.
- * wlr_output_layout_add does not like disabled outputs */
+ /* Don't move monitors if position wouldn't change. This avoids
+ * wlroots marking the output as manually configured.
+ * wlr_output_layout_add does not like disabled outputs */
if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y))
wlr_output_layout_add(output_layout, wlr_output,
config_head->state.x, config_head->state.y);
@@ -3032,7 +3033,7 @@ run(char *startup_cmd, uid_t uid)
selmon = xytomon(cursor->x, cursor->y);
/* TODO hack to get cursor to display in its initial location (100, 100)
- * instead of (0, 0) and then jumping. still may not be fully
+ * instead of (0, 0) and then jumping. Still may not be fully
* initialized, as the image/coordinates are not transformed for the
* monitor when displayed here */
wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y);
@@ -3055,7 +3056,7 @@ setcursor(struct wl_listener *listener, void *data)
* event, which will result in the client requesting set the cursor surface */
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
return;
- /* This can be sent by any client, so we check to make sure this one is
+ /* This can be sent by any client, so we check to make sure this one
* actually has pointer focus first. If so, we can tell the cursor to
* use the provided surface as the cursor image. It will set the
* hardware cursor on the output that it's currently on and continue to
@@ -3071,7 +3072,7 @@ setcursorshape(struct wl_listener *listener, void *data)
struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
return;
- /* This can be sent by any client, so we check to make sure this one is
+ /* This can be sent by any client, so we check to make sure this one
* actually has pointer focus first. If so, we can tell the cursor to
* use the provided cursor shape. */
if (event->seat_client == seat->pointer_state.focused_client)
@@ -3204,7 +3205,7 @@ setpsel(struct wl_listener *listener, void *data)
{
/* This event is raised by the seat when a client wants to set the selection,
* usually when the user copies something. wlroots allows compositors to
- * ignore such requests if they so choose, but in dwl we always honor
+ * ignore such requests if they so choose, but in dwl we always honor them
*/
struct wlr_seat_request_set_primary_selection_event *event = data;
wlr_seat_set_primary_selection(seat, event->source, event->serial);
@@ -3215,7 +3216,7 @@ setsel(struct wl_listener *listener, void *data)
{
/* This event is raised by the seat when a client wants to set the selection,
* usually when the user copies something. wlroots allows compositors to
- * ignore such requests if they so choose, but in dwl we always honor
+ * ignore such requests if they so choose, but in dwl we always honor them
*/
struct wlr_seat_request_set_selection_event *event = data;
wlr_seat_set_selection(seat, event->source, event->serial);
@@ -3263,9 +3264,9 @@ setup(void)
wl_signal_add(&drw->events.lost, &gpu_reset);
/* Create shm, drm and linux_dmabuf interfaces by ourselves.
- * The simplest way is call:
+ * The simplest way is to call:
* wlr_renderer_init_wl_display(drw);
- * but we need to create manually the linux_dmabuf interface to integrate it
+ * but we need to create the linux_dmabuf interface manually to integrate it
* with wlr_scene. */
wlr_renderer_init_wl_shm(drw, dpy);
@@ -3314,7 +3315,7 @@ setup(void)
power_mgr = wlr_output_power_manager_v1_create(dpy);
wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode);
- /* Creates an output layout, which a wlroots utility for working with an
+ /* Creates an output layout, which is a wlroots utility for working with an
* arrangement of screens in a physical layout. */
output_layout = wlr_output_layout_create(dpy);
wl_signal_add(&output_layout->events.change, &layout_change);