summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md71
-rw-r--r--Makefile2
-rw-r--r--client.h12
-rw-r--r--config.def.h1
-rw-r--r--config.mk2
-rw-r--r--dwl.c70
-rw-r--r--util.c16
-rw-r--r--util.h1
8 files changed, 125 insertions, 50 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 366728d..6ef3d96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,18 +1,83 @@
# Changelog
-* [Unreleased](#unreleased)
+* [0.6](#0.6)
* [0.5](#0.5)
## Unreleased
+
### Added
+
+* Add `rootcolor` to change the default background color ([#544][544]).
+* Implement the wlr-virtual-pointer-unstable-v1 protocol ([#574][574]).
+* Implement the pointer-constraints and relative-pointer protocols ([#317][317])
+* Implement the wlr-output-power-management protocol ([#599][599])
+
+[544]: https://codeberg.org/dwl/dwl/pulls/544
+[574]: https://codeberg.org/dwl/dwl/pulls/574
+[317]: https://codeberg.org/dwl/dwl/issues/317
+[599]: https://codeberg.org/dwl/dwl/issues/559
+
+
### Changed
-### Deprecated
+
+* Keyboards are now managed through keyboard groups ([#549][549]).
+* Only the first matched keybinding is executed.
+* Allow toggling the layout before selecting a different one ([#570][570]).
+* Fullscreen clients are now rendered above wlr_layer_surfaces in the top layer
+ ([#609][609]).
+* The default menu was changed from `bemenu-run` to `wmenu-run` ([#553][553]).
+* The option `sloppyfocus` now replicates the dwm behavior ([#599][599]).
+* Allow configure position of monitors with negative values. (-1, -1) is
+ used to auto-configure them ([#635][635]).
+* dwl now kills the entire process group of `startup_cmd`
+* The O_NONBLOCK flag is set for stdout.
+
+[549]: https://codeberg.org/dwl/dwl/pulls/549
+[570]: https://codeberg.org/dwl/dwl/pulls/570
+[609]: https://codeberg.org/dwl/dwl/pulls/609
+[553]: https://codeberg.org/dwl/dwl/issues/553
+[599]: https://codeberg.org/dwl/dwl/pulls/599
+[635]: https://codeberg.org/dwl/dwl/pulls/635
+
+
### Removed
+
+* The SLOC limit is now removed ([#497][497]).
+
+[497]: https://codeberg.org/dwl/dwl/pulls/497
+
+
### Fixed
-### Security
+
+* Clients not having the correct border color when mapping.
+* Compliance with the xdg-decoration-unstable-v1 ([#546][546]).
+* dwl no longer sends negative values in xdg_toplevel.configure events.
+* Crashes with disabled monitors ([#472][472]).
+
+[546]: https://codeberg.org/dwl/dwl/pulls/546
+[472]: https://codeberg.org/dwl/dwl/issues/472
+
+
### Contributors
+Ben Jargowsky
+Benjamin Chausse
+David Donahue
+Devin J. Pohly
+Dima Krasner
+Emil Miler
+Forrest Bushstone
+Guido Cella
+Peter Hofmann
+Rutherther
+Squibid
+choc
+fictitiousexistence
+korei999
+sewn
+thanatos
+
## 0.5
diff --git a/Makefile b/Makefile
index aa3009f..3358bae 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \
# CFLAGS / LDFLAGS
PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS)
DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
-LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
+LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS)
all: dwl
dwl: dwl.o util.o
diff --git a/client.h b/client.h
index 42f225f..f0e5445 100644
--- a/client.h
+++ b/client.h
@@ -183,18 +183,6 @@ client_get_parent(Client *c)
return p;
}
-static inline int
-client_has_children(Client *c)
-{
-#ifdef XWAYLAND
- if (client_is_x11(c))
- return !wl_list_empty(&c->surface.xwayland->children);
-#endif
- /* surface.xdg->link is never empty because it always contains at least the
- * surface itself. */
- return wl_list_length(&c->surface.xdg->link) > 1;
-}
-
static inline const char *
client_get_title(Client *c)
{
diff --git a/config.def.h b/config.def.h
index 646a3d6..22d2171 100644
--- a/config.def.h
+++ b/config.def.h
@@ -20,6 +20,7 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
/* logging */
static int log_level = WLR_ERROR;
+/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
static const Rule rules[] = {
/* app_id title tags mask isfloating monitor */
/* examples: */
diff --git a/config.mk b/config.mk
index 259bd0f..6fb4fb3 100644
--- a/config.mk
+++ b/config.mk
@@ -1,4 +1,4 @@
-_VERSION = 0.5
+_VERSION = 0.6
VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config
diff --git a/dwl.c b/dwl.c
index 70d99ca..4a1267b 100644
--- a/dwl.c
+++ b/dwl.c
@@ -4,6 +4,7 @@
#include <getopt.h>
#include <libinput.h>
#include <linux/input-event-codes.h>
+#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -71,8 +72,6 @@
/* macros */
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
-#define ROUND(X) ((int)((X < 0) ? (X - 0.5) : (X + 0.5)))
-#define CEIL(X) ((int)((X < 0) ? (X) : ((int)X == X) ? (X) : ((int)X + 1)))
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
#define LENGTH(X) (sizeof X / sizeof X[0])
@@ -178,7 +177,6 @@ typedef struct {
struct wlr_layer_surface_v1 *layer_surface;
struct wl_listener destroy;
- struct wl_listener map;
struct wl_listener unmap;
struct wl_listener surface_commit;
} LayerSurface;
@@ -302,7 +300,6 @@ static void keypressmod(struct wl_listener *listener, void *data);
static int keyrepeat(void *data);
static void killclient(const Arg *arg);
static void locksession(struct wl_listener *listener, void *data);
-static void maplayersurfacenotify(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
static void maximizenotify(struct wl_listener *listener, void *data);
static void monocle(Monitor *m);
@@ -447,9 +444,9 @@ applybounds(Client *c, struct wlr_box *bbox)
c->geom.x = bbox->x + bbox->width - c->geom.width;
if (c->geom.y >= bbox->y + bbox->height)
c->geom.y = bbox->y + bbox->height - c->geom.height;
- if (c->geom.x + c->geom.width + 2 * (int)c->bw <= bbox->x)
+ if (c->geom.x + c->geom.width <= bbox->x)
c->geom.x = bbox->x;
- if (c->geom.y + c->geom.height + 2 * (int)c->bw <= bbox->y)
+ if (c->geom.y + c->geom.height <= bbox->y)
c->geom.y = bbox->y;
}
@@ -612,6 +609,7 @@ buttonpress(struct wl_listener *listener, void *data)
switch (event->state) {
case WL_POINTER_BUTTON_STATE_PRESSED:
cursor_mode = CurPressed;
+ selmon = xytomon(cursor->x, cursor->y);
if (locked)
break;
@@ -795,6 +793,17 @@ commitnotify(struct wl_listener *listener, void *data)
Client *c = wl_container_of(listener, c, commit);
if (c->surface.xdg->initial_commit) {
+ /*
+ * 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 wrong monitor.
+ */
+ applyrules(c);
+ wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale));
+ wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale);
+ setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */
+
wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
if (c->decoration)
@@ -923,7 +932,6 @@ createlayersurface(struct wl_listener *listener, void *data)
l = layer_surface->data = ecalloc(1, sizeof(*l));
l->type = LayerShell;
LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify);
- LISTEN(&surface->events.map, &l->map, maplayersurfacenotify);
LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify);
LISTEN(&layer_surface->events.destroy, &l->destroy, destroylayersurfacenotify);
@@ -938,7 +946,7 @@ createlayersurface(struct wl_listener *listener, void *data)
wl_list_insert(&l->mon->layers[layer_surface->pending.layer],&l->link);
wlr_surface_send_enter(surface, layer_surface->output);
wlr_fractional_scale_v1_notify_scale(surface, l->mon->wlr_output->scale);
- wlr_surface_set_preferred_buffer_scale(surface, CEIL(l->mon->wlr_output->scale));
+ wlr_surface_set_preferred_buffer_scale(surface, (int32_t)ceilf(l->mon->wlr_output->scale));
}
void
@@ -1195,7 +1203,6 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data)
wl_list_remove(&l->link);
wl_list_remove(&l->destroy.link);
- wl_list_remove(&l->map.link);
wl_list_remove(&l->unmap.link);
wl_list_remove(&l->surface_commit.link);
wlr_scene_node_destroy(&l->scene->node);
@@ -1420,7 +1427,7 @@ focusstack(const Arg *arg)
{
/* Focus the next or previous client (in tiling order) on selmon */
Client *c, *sel = focustop(selmon);
- if (!sel || (sel->isfullscreen && !client_has_children(sel)))
+ if (!sel || sel->isfullscreen)
return;
if (arg->i > 0) {
wl_list_for_each(c, &sel->link, link) {
@@ -1675,17 +1682,10 @@ locksession(struct wl_listener *listener, void *data)
}
void
-maplayersurfacenotify(struct wl_listener *listener, void *data)
-{
- motionnotify(0, NULL, 0, 0, 0, 0);
-}
-
-void
mapnotify(struct wl_listener *listener, void *data)
{
/* Called when the surface is mapped, or ready to display on-screen. */
- Client *p = NULL;
- Client *w, *c = wl_container_of(listener, c, map);
+ Client *p, *w, *c = wl_container_of(listener, c, map);
Monitor *m;
int i;
@@ -1741,7 +1741,7 @@ mapnotify(struct wl_listener *listener, void *data)
unset_fullscreen:
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
wl_list_for_each(w, &clients, link) {
- if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags))
+ if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags))
setfullscreen(w, 0);
}
}
@@ -1859,17 +1859,17 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
}
/* Update drag icon's position */
- wlr_scene_node_set_position(&drag_icon->node, ROUND(cursor->x), ROUND(cursor->y));
+ wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
/* If we are currently grabbing the mouse, handle and return */
if (cursor_mode == CurMove) {
/* Move the grabbed client to the new position. */
- resize(grabc, (struct wlr_box){.x = ROUND(cursor->x) - grabcx, .y = ROUND(cursor->y) - grabcy,
+ resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy,
.width = grabc->geom.width, .height = grabc->geom.height}, 1);
return;
} else if (cursor_mode == CurResize) {
resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
- .width = ROUND(cursor->x) - grabc->geom.x, .height = ROUND(cursor->y) - grabc->geom.y}, 1);
+ .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
return;
}
@@ -1910,8 +1910,8 @@ moveresize(const Arg *arg)
setfloating(grabc, 1);
switch (cursor_mode = arg->ui) {
case CurMove:
- grabcx = ROUND(cursor->x) - grabc->geom.x;
- grabcy = ROUND(cursor->y) - grabc->geom.y;
+ grabcx = (int)round(cursor->x) - grabc->geom.x;
+ grabcy = (int)round(cursor->y) - grabc->geom.y;
wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
break;
case CurResize:
@@ -1991,7 +1991,7 @@ apply_or_test:
wlr_output_configuration_v1_send_failed(config);
wlr_output_configuration_v1_destroy(config);
- /* TODO: use a wrapper function? */
+ /* https://codeberg.org/dwl/dwl/issues/577 */
updatemons(NULL, NULL);
}
@@ -2181,7 +2181,7 @@ resize(Client *c, struct wlr_box geo, int interact)
struct wlr_box *bbox;
struct wlr_box clip;
- if (!c->mon)
+ if (!c->mon || !c->scene)
return;
bbox = interact ? &sgeom : &c->mon->w;
@@ -2241,6 +2241,12 @@ run(char *startup_cmd)
close(piperw[1]);
close(piperw[0]);
}
+
+ /* Mark stdout as non-blocking to avoid people who does not close stdin
+ * nor consumes it in their startup script getting dwl frozen */
+ if (fd_set_nonblock(STDOUT_FILENO) < 0)
+ close(STDOUT_FILENO);
+
printstatus();
/* At this point the outputs are initialized, choose initial selmon based on
@@ -2298,14 +2304,12 @@ setcursorshape(struct wl_listener *listener, void *data)
void
setfloating(Client *c, int floating)
{
- Client *p = client_get_parent(c);
c->isfloating = floating;
/* If in floating layout do not change the client's layer */
- if (!c->mon || !c->mon->lt[c->mon->sellt]->arrange)
+ if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
return;
- wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
- (p && p->isfullscreen) ? LyrFS
- : c->isfloating ? LyrFloat : LyrTile]);
+ wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen
+ ? LyrFS : c->isfloating ? LyrFloat : LyrTile]);
arrange(c->mon);
printstatus();
}
@@ -2314,7 +2318,7 @@ void
setfullscreen(Client *c, int fullscreen)
{
c->isfullscreen = fullscreen;
- if (!c->mon)
+ if (!c->mon || !client_surface(c)->mapped)
return;
c->bw = fullscreen ? 0 : borderpx;
client_set_fullscreen(c, fullscreen);
@@ -2694,7 +2698,7 @@ tile(Monitor *m)
return;
if (n > m->nmaster)
- mw = m->nmaster ? ROUND(m->w.width * m->mfact) : 0;
+ mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
else
mw = m->w.width;
i = my = ty = 0;
diff --git a/util.c b/util.c
index cca7c19..51130af 100644
--- a/util.c
+++ b/util.c
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
#include "util.h"
@@ -33,3 +34,18 @@ ecalloc(size_t nmemb, size_t size)
die("calloc:");
return p;
}
+
+int
+fd_set_nonblock(int fd) {
+ int flags = fcntl(fd, F_GETFL);
+ if (flags < 0) {
+ perror("fcntl(F_GETFL):");
+ return -1;
+ }
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ perror("fcntl(F_SETFL):");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/util.h b/util.h
index 4c94117..226980d 100644
--- a/util.h
+++ b/util.h
@@ -2,3 +2,4 @@
void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size);
+int fd_set_nonblock(int fd);