diff options
-rw-r--r-- | CHANGELOG.md | 71 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | client.h | 12 | ||||
-rw-r--r-- | config.def.h | 1 | ||||
-rw-r--r-- | config.mk | 2 | ||||
-rw-r--r-- | dwl.c | 70 | ||||
-rw-r--r-- | util.c | 16 | ||||
-rw-r--r-- | util.h | 1 |
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 @@ -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 @@ -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: */ @@ -1,4 +1,4 @@ -_VERSION = 0.5 +_VERSION = 0.6 VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)` PKG_CONFIG = pkg-config @@ -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; @@ -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; +} @@ -2,3 +2,4 @@ void die(const char *fmt, ...); void *ecalloc(size_t nmemb, size_t size); +int fd_set_nonblock(int fd); |