From 8aa50dfdf1bd6daefe2a58f507a0d1353e47719f Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Tue, 3 Aug 2021 06:29:26 +0200 Subject: [PATCH 01/32] update IRC channel --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b3e4cb..3b3a72f 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ You can find a [list of Wayland applications on the sway wiki](https://github.co ## IRC channel -dwl's IRC channel is #dwl on irc.freenode.net. +dwl's IRC channel is #dwl on irc.libera.chat. ## Acknowledgements From 0c4740b27735199f2c194b47c85ab321250631b4 Mon Sep 17 00:00:00 2001 From: Humm Date: Wed, 5 Jan 2022 01:54:02 +0100 Subject: [PATCH 02/32] add dwl(1) Documentation is good. Man pages are documentation. A program without a man page is worthless. --- Makefile | 5 +- config.mk | 1 + dwl.1 | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 dwl.1 diff --git a/Makefile b/Makefile index 5ff69e9..536454f 100644 --- a/Makefile +++ b/Makefile @@ -15,10 +15,11 @@ clean: rm -f dwl *.o *-protocol.h *-protocol.c install: dwl - install -D dwl $(PREFIX)/bin/dwl + install -Dm755 dwl $(PREFIX)/bin/dwl + install -Dm644 dwl.1 $(MANDIR)/man1/dwl.1 uninstall: - rm -f $(PREFIX)/bin/dwl + rm -f $(PREFIX)/bin/dwl $(MANDIR)/man1/dwl.1 .PHONY: all clean install uninstall diff --git a/config.mk b/config.mk index cd4e821..e38a8e5 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,6 @@ # paths PREFIX = /usr/local +MANDIR = $(PREFIX)/share/man # Default compile flags (overridable by environment) CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wdeclaration-after-statement diff --git a/dwl.1 b/dwl.1 new file mode 100644 index 0000000..eea0f70 --- /dev/null +++ b/dwl.1 @@ -0,0 +1,144 @@ +.Dd January 8, 2021 +.Dt DWL 1 +.Os +.Sh NAME +.Nm dwl +.Nd dwm for Wayland +.Sh SYNOPSIS +.Nm +.Op Fl s Ar command +.Sh DESCRIPTION +.Nm +is a Wayland compositor based on wlroots. +It is intended to fill the same space in the Wayland world that +.Nm dwm +does for X11. +.Pp +When given the +.Fl s +option, +.Nm +starts a shell process running +.Ar command +when starting. +When stopping, it sends +.Dv SIGTERM +to the child process and waits for it to exit. +.Pp +Users are encouraged to customize +.Nm +by editing the sources, in particular +.Pa config.h . +The default key bindings are as follows: +.Bl -tag -width 20n -offset indent -compact +.It Mod-[1-9] +Show only all windows with a tag. +.It Mod-Ctrl-[1-9] +Show all windows with a tag. +.It Mod-Shift-[1-9] +Move window to a single tag. +.It Mod-Ctrl-Shift-[1-9] +Toggle tag for window. +.It Mod-p +Spawn +.Nm bemenu-run . +.It Mod-Shift-Return +Spawn +.Nm alacritty . +.It Mod-[jk] +Move focus down/up the stack. +.It Mod-[id] +Increase/decrease number of windows in master area. +.It Mod-[hl] +Decrease/increase master area. +.It Mod-Return +Move window on top of stack or switch top of stack with second window. +.It Mod-Tab +Show only all windows with previous tag. +.It Mod-Shift-c +Close window. +.It Mod-t +Switch to tabbed layout. +.It Mod-f +Switch to floating layout. +.It Mod-m +Switch to monocle layout. +.It Mod-Space +Switch to previous layout. +.It Mod-Shift-Space +Toggle floating state of window. +.It Mod-e +Toggle fullscreen state of window. +.It Mod-0 +Show all windows. +.It Mod-Shift-0 +Set all tags for window. +.It Mod-, +Move focus to previous monitor. +.It Mod-. +Move focus to next monitor. +.It Mod-Shift-, +Move window to previous monitor. +.It Mod-Shift-. +Move window to next monitor. +.It Mod-Shift-q +Quit +.Nm . +.El +These might differ depending on your keyboard layout. +.Sh ENVIRONMENT +These environment variables are used by +.Nm : +.Bl -tag -width XDG_RUNTIME_DIR +.It Ev XDG_RUNTIME_DIR +A directory where temporary user files, such as the Wayland socket, +are stored. +.It Ev XDG_CONFIG_DIR +A directory containung configuration of various programs and +libraries, including libxkbcommon. +.It Ev DISPLAY , WAYLAND_DISPLAY , WAYLAND_SOCKET +Tell how to connect to an underlying X11 or Wayland server. +.It Ev WLR_* +Various variables specific to wlroots. +.It Ev XKB_* , XLOCALEDIR , XCOMPOSEFILE +Various variables specific to libxkbcommon. +.It Ev XCURSOR_PATH +List of directories to search for XCursor themes in. +.It Ev HOME +A directory where there are always dear files there for you. +Waiting for you to clean them up. +.El +.Pp +These are set by +.Nm : +.Bl -tag -width WAYLAND_DISPLAY +.It Ev WAYLAND_DISPLAY +Tell how to connect to +.Nm . +.It Ev DISPLAY +If using +.Nm Xwayland , +tell how to connect to the +.Nm Xwayland +server. +.El +.Sh EXAMPLES +Start +.Nm +with s6 in the background: +.Dl dwl -s 's6-svscan <&-' +.Sh SEE ALSO +.Xr alacritty 1 , +.Xr bemenu 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. From 0dea553428c8c534ea8bbb914b1ec775cf36e4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 20 Mar 2022 19:09:28 -0600 Subject: [PATCH 03/32] destroy scene_output in cleanupmon() --- dwl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwl.c b/dwl.c index 01f51ad..74f8549 100644 --- a/dwl.c +++ b/dwl.c @@ -703,6 +703,7 @@ cleanupmon(struct wl_listener *listener, void *data) wl_list_remove(&m->frame.link); wl_list_remove(&m->link); wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); if ((nmons = wl_list_length(&mons))) do /* don't switch to disabled mons */ From c50f187c1f784c010b1261848fade72b9401b28f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 21 Mar 2022 13:52:33 -0600 Subject: [PATCH 04/32] improve floating detection mostly copied from sway --- client.h | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/client.h b/client.h index a5fc0d2..41c9b9a 100644 --- a/client.h +++ b/client.h @@ -91,16 +91,37 @@ client_get_title(Client *c) static inline int client_is_float_type(Client *c) { + struct wlr_xdg_toplevel *toplevel; + struct wlr_xdg_toplevel_state state; + #ifdef XWAYLAND - if (client_is_x11(c)) - for (size_t i = 0; i < c->surface.xwayland->window_type_len; i++) - if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] || - c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] || - c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] || - c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility]) + if (client_is_x11(c)) { + struct wlr_xwayland_surface *surface = c->surface.xwayland; + struct wlr_xwayland_surface_size_hints *size_hints; + if (surface->modal) + return 1; + + for (size_t i = 0; i < surface->window_type_len; i++) + if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] || + surface->window_type[i] == netatom[NetWMWindowTypeSplash] || + surface->window_type[i] == netatom[NetWMWindowTypeToolbar] || + surface->window_type[i] == netatom[NetWMWindowTypeUtility]) return 1; + + size_hints = surface->size_hints; + if (size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 + && (size_hints->max_width == size_hints->min_width || + size_hints->max_height == size_hints->min_height)) + return 1; + } #endif - return 0; + + toplevel = c->surface.xdg->toplevel; + state = toplevel->current; + return (state.min_width != 0 && state.min_height != 0 + && (state.min_width == state.max_width + || state.min_height == state.max_height)) + || toplevel->parent; } static inline int From 2bc01debdcf2c6cf13583c6a67f8a6a824446408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 21 Mar 2022 13:28:44 -0600 Subject: [PATCH 05/32] remove a useless resize in mapnotify() applyrules() calls setmon() which calls resize() --- dwl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dwl.c b/dwl.c index 74f8549..0b82e42 100644 --- a/dwl.c +++ b/dwl.c @@ -1359,7 +1359,6 @@ mapnotify(struct wl_listener *listener, void *data) /* Set initial monitor, tags, floating status, and focus */ applyrules(c); - resize(c, c->geom.x, c->geom.y, c->geom.width, c->geom.height, 0); printstatus(); if (c->isfullscreen) From ee1a72211d066de3766980d0452945df0a50334c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 21 Mar 2022 21:17:58 -0600 Subject: [PATCH 06/32] only skip frames if there are visible clients that have a resize --- dwl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index 0b82e42..cd9e8d5 100644 --- a/dwl.c +++ b/dwl.c @@ -1624,9 +1624,11 @@ rendermon(struct wl_listener *listener, void *data) int skip = 0; struct timespec now; - /* Render if no XDG clients have an outstanding resize. */ + /* Render if no XDG clients have an outstanding resize and are visible on + * this monitor. + */ wl_list_for_each(c, &clients, link) - skip = skip || c->resize; + skip = skip || (c->resize && VISIBLEON(c, m)); if (!skip && !wlr_scene_output_commit(m->scene_output)) return; From 86fe15f76c752cb848da580af8f7d897f932cae6 Mon Sep 17 00:00:00 2001 From: Sevz Date: Mon, 21 Mar 2022 22:34:30 -0600 Subject: [PATCH 07/32] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 9b9eef4..64e2054 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,4 +7,16 @@ assignees: '' --- +## Info +dwl's commit: +wlroots version: +## Description + From 330792b1fc37db86743d7c186577776e05295e00 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Mon, 21 Mar 2022 23:03:52 +0100 Subject: [PATCH 08/32] implement drag and drop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For brevity, only a single drag icon at a time is supported. Co-authored-by: Leonardo Hernández Hernández --- dwl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/dwl.c b/dwl.c index cd9e8d5..22287fb 100644 --- a/dwl.c +++ b/dwl.c @@ -227,6 +227,7 @@ static void cursorframe(struct wl_listener *listener, void *data); static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); +static void dragicondestroy(struct wl_listener *listener, void *data); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); @@ -254,6 +255,7 @@ static void printstatus(void); static void quit(const Arg *arg); static void quitsignal(int signo); static void rendermon(struct wl_listener *listener, void *data); +static void requeststartdrag(struct wl_listener *listener, void *data); static void resize(Client *c, int x, int y, int w, int h, int interact); static void run(char *startup_cmd); static Client *selclient(void); @@ -268,6 +270,7 @@ static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setup(void); static void sigchld(int unused); static void spawn(const Arg *arg); +static void startdrag(struct wl_listener *listener, void *data); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *m); @@ -340,6 +343,9 @@ static struct wl_listener request_activate = {.notify = urgent}; static struct wl_listener request_cursor = {.notify = setcursor}; static struct wl_listener request_set_psel = {.notify = setpsel}; static struct wl_listener request_set_sel = {.notify = setsel}; +static struct wl_listener request_start_drag = {.notify = requeststartdrag}; +static struct wl_listener start_drag = {.notify = startdrag}; +static struct wl_listener drag_icon_destroy = {.notify = dragicondestroy}; #ifdef XWAYLAND static void activatex11(struct wl_listener *listener, void *data); @@ -1023,6 +1029,16 @@ destroynotify(struct wl_listener *listener, void *data) free(c); } +void +dragicondestroy(struct wl_listener *listener, void *data) +{ + struct wlr_drag_icon *icon = data; + wlr_scene_node_destroy(icon->data); + // Focus enter isn't sent during drag, so refocus the focused node. + focusclient(selclient(), 1); + motionnotify(0); +} + void togglefullscreen(const Arg *arg) { @@ -1400,11 +1416,16 @@ motionnotify(uint32_t time) /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { + struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); + + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); } /* If we are currently grabbing the mouse, handle and return */ @@ -1665,6 +1686,18 @@ resize(Client *c, int x, int y, int w, int h, int interact) c->geom.height - 2 * c->bw); } +void +requeststartdrag(struct wl_listener *listener, void *data) +{ + struct wlr_seat_request_start_drag_event *event = data; + + if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, + event->serial)) + wlr_seat_start_pointer_drag(seat, event->drag, event->serial); + else + wlr_data_source_destroy(event->drag->source); +} + void run(char *startup_cmd) { @@ -1976,6 +2009,8 @@ setup(void) wl_signal_add(&seat->events.request_set_cursor, &request_cursor); wl_signal_add(&seat->events.request_set_selection, &request_set_sel); wl_signal_add(&seat->events.request_set_primary_selection, &request_set_psel); + wl_signal_add(&seat->events.request_start_drag, &request_start_drag); + wl_signal_add(&seat->events.start_drag, &start_drag); output_mgr = wlr_output_manager_v1_create(dpy); wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); @@ -2026,6 +2061,19 @@ spawn(const Arg *arg) } } +void +startdrag(struct wl_listener *listener, void *data) +{ + struct wlr_drag *drag = data; + + if (!drag->icon) + return; + + drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrTop], drag->icon->surface); + wlr_scene_node_raise_to_top(drag->icon->data); + wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); +} + void tag(const Arg *arg) { From 9aec6049ecbefe3618f34002d2239cc9462c07e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 22 Mar 2022 15:02:02 -0600 Subject: [PATCH 09/32] clients now works as expected in drag motion --- dwl.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dwl.c b/dwl.c index 22287fb..f8d01f2 100644 --- a/dwl.c +++ b/dwl.c @@ -1416,16 +1416,11 @@ motionnotify(uint32_t time) /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { - struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); - - if (seat->drag && (icon = seat->drag->icon)) - wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, - cursor->y + icon->surface->sy); } /* If we are currently grabbing the mouse, handle and return */ @@ -1564,6 +1559,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, { struct timespec now; int internal_call = !time; + struct wlr_drag_icon *icon; if (sloppyfocus && !internal_call && c && !client_is_unmanaged(c)) focusclient(c, 0); @@ -1585,6 +1581,13 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); + /* If there are is a drag icon, update its position */ + /* For anyone who wants to change this function: for some reason + * (maybe a wlroots bug?, or is it intended?) if we change the node position + * before telling the seat for a motion, the clients don't recognize the drag */ + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); } void From d8f430accfb66c2575de608bb1b4c71815e4379a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 22 Mar 2022 23:29:01 -0600 Subject: [PATCH 10/32] add sway LICENSE file part of the code in dwl is taken from sway, so credit it. dwm and sway are both licensed under the MIT license --- LICENSE | 2 +- LICENSE.sway | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 LICENSE.sway diff --git a/LICENSE b/LICENSE index e4bb015..658085a 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ dwl - dwm for Wayland Copyright © 2020 dwl team -See also the files LICENSE.tinywl and LICENSE.dwm. +See also the files LICENSE.tinywl, LICENSE.dwm and LICENSE.sway. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/LICENSE.sway b/LICENSE.sway new file mode 100644 index 0000000..3e0cacc --- /dev/null +++ b/LICENSE.sway @@ -0,0 +1,19 @@ +Copyright (c) 2016-2017 Drew DeVault + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 326eee14445f8a2c08e80c30778445630c75d3bb Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Mon, 12 Jul 2021 23:44:16 +0200 Subject: [PATCH 11/32] Add a configuration option for fullscreen locking Some people are annoyed to have this new behaviour forced for some application which use fake fullscreen. --- config.def.h | 1 + dwl.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 8408659..539dba6 100644 --- a/config.def.h +++ b/config.def.h @@ -1,6 +1,7 @@ /* appearance */ static const int sloppyfocus = 1; /* focus follows mouse */ static const unsigned int borderpx = 1; /* border pixel of windows */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ static const float rootcolor[] = {0.3, 0.3, 0.3, 1.0}; static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0}; static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0}; diff --git a/dwl.c b/dwl.c index f8d01f2..9ea44e2 100644 --- a/dwl.c +++ b/dwl.c @@ -1177,7 +1177,7 @@ focusstack(const Arg *arg) { /* Focus the next or previous client (in tiling order) on selmon */ Client *c, *sel = selclient(); - if (!sel) + if (!sel || (sel->isfullscreen && lockfullscreen)) return; if (arg->i > 0) { wl_list_for_each(c, &sel->link, link) { From 7d724dc7f34561e7a6d4ab97ff24b07805593f63 Mon Sep 17 00:00:00 2001 From: Palanix Date: Mon, 28 Feb 2022 23:46:24 +0100 Subject: [PATCH 12/32] Fix dwl freezing when resizing --- dwl.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/dwl.c b/dwl.c index 9ea44e2..3185062 100644 --- a/dwl.c +++ b/dwl.c @@ -178,6 +178,7 @@ struct Monitor { unsigned int tagset[2]; double mfact; int nmaster; + int un_map; /* If a map/unmap happened on this monitor, then this should be true */ }; typedef struct { @@ -1379,6 +1380,8 @@ mapnotify(struct wl_listener *listener, void *data) if (c->isfullscreen) setfullscreen(c, 1); + + c->mon->un_map = 1; } void @@ -1648,17 +1651,27 @@ rendermon(struct wl_listener *listener, void *data) int skip = 0; struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + /* Render if no XDG clients have an outstanding resize and are visible on - * this monitor. - */ - wl_list_for_each(c, &clients, link) - skip = skip || (c->resize && VISIBLEON(c, m)); + * this monitor. */ + /* Checking m->un_map for every client is not optimal but works */ + wl_list_for_each(c, &clients, link) { + if ((c->resize && m->un_map) || (c->type == XDGShell + && (c->surface.xdg->pending.geometry.width != + c->surface.xdg->current.geometry.width + || c->surface.xdg->pending.geometry.height != + c->surface.xdg->current.geometry.height))) { + /* Lie */ + wlr_surface_send_frame_done(client_surface(c), &now); + skip = 1; + } + } if (!skip && !wlr_scene_output_commit(m->scene_output)) return; - /* Let clients know a frame has been rendered */ - clock_gettime(CLOCK_MONOTONIC, &now); wlr_scene_output_send_frame_done(m->scene_output, &now); + m->un_map = 0; } void @@ -2196,6 +2209,9 @@ unmapnotify(struct wl_listener *listener, void *data) grabc = NULL; } + if (c->mon) + c->mon->un_map = 1; + if (client_is_unmanaged(c)) { wlr_scene_node_destroy(c->scene); return; From 4ef89996242c3b31a9957666f9f5b8cf7ef5cce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 23 Mar 2022 14:03:07 -0600 Subject: [PATCH 13/32] add note about how to change MODKEY for windows key --- config.def.h | 1 + 1 file changed, 1 insertion(+) diff --git a/config.def.h b/config.def.h index 539dba6..9bdf8b5 100644 --- a/config.def.h +++ b/config.def.h @@ -52,6 +52,7 @@ static const int repeat_delay = 600; static const int tap_to_click = 1; static const int natural_scrolling = 0; +/* If you want to use the windows key change this to WLR_MODIFIER_LOGO */ #define MODKEY WLR_MODIFIER_ALT #define TAGKEYS(KEY,SKEY,TAG) \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ From 3bace9ce6b9d5fa7c8871a414ed97976e44ecb9c Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Wed, 23 Mar 2022 22:01:04 +0100 Subject: [PATCH 14/32] inline the presentation variable This variable can be removed since with scene-graph wlr_presentation_surface_sampled_on_output no longer needs to be called. --- dwl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dwl.c b/dwl.c index 3185062..65d1381 100644 --- a/dwl.c +++ b/dwl.c @@ -309,7 +309,6 @@ static struct wl_list fstack; /* focus order */ static struct wlr_idle *idle; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; -static struct wlr_presentation *presentation; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; static struct wlr_cursor *cursor; @@ -2032,8 +2031,7 @@ setup(void) wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); wl_signal_add(&output_mgr->events.test, &output_mgr_test); - presentation = wlr_presentation_create(dpy, backend); - wlr_scene_set_presentation(scene, presentation); + wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); #ifdef XWAYLAND /* From 7a2e0eef746950f6ac0863dcbb5c957836a6d8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 23 Mar 2022 12:13:49 -0600 Subject: [PATCH 15/32] Revert "clients now works as expected in drag motion" This reverts commit 9aec6049ecbefe3618f34002d2239cc9462c07e9. this problem is caused because xytonode() returns the surface of the drag icon --- dwl.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/dwl.c b/dwl.c index 65d1381..ce53dfa 100644 --- a/dwl.c +++ b/dwl.c @@ -1418,11 +1418,16 @@ motionnotify(uint32_t time) /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { + struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); + + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); } /* If we are currently grabbing the mouse, handle and return */ @@ -1561,7 +1566,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, { struct timespec now; int internal_call = !time; - struct wlr_drag_icon *icon; if (sloppyfocus && !internal_call && c && !client_is_unmanaged(c)) focusclient(c, 0); @@ -1583,13 +1587,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); - /* If there are is a drag icon, update its position */ - /* For anyone who wants to change this function: for some reason - * (maybe a wlroots bug?, or is it intended?) if we change the node position - * before telling the seat for a motion, the clients don't recognize the drag */ - if (seat->drag && (icon = seat->drag->icon)) - wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, - cursor->y + icon->surface->sy); } void From bf8cc526deab39e269da219667ae24b6f8adecc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 23 Mar 2022 14:18:38 -0600 Subject: [PATCH 16/32] set position of the drag icon in startdrag() --- dwl.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dwl.c b/dwl.c index ce53dfa..536b4d6 100644 --- a/dwl.c +++ b/dwl.c @@ -1415,21 +1415,20 @@ motionnotify(uint32_t time) double sx = 0, sy = 0; Client *c = NULL; struct wlr_surface *surface = NULL; + struct wlr_drag_icon *icon; /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { - struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); - - if (seat->drag && (icon = seat->drag->icon)) - wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, - cursor->y + icon->surface->sy); } + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); /* If we are currently grabbing the mouse, handle and return */ if (cursor_mode == CurMove) { /* Move the grabbed client to the new position. */ @@ -2081,7 +2080,7 @@ startdrag(struct wl_listener *listener, void *data) return; drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrTop], drag->icon->surface); - wlr_scene_node_raise_to_top(drag->icon->data); + motionnotify(0); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); } From feb972acd0ea130bc3af0f0f7072a70fa3c786bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 23 Mar 2022 13:50:08 -0600 Subject: [PATCH 17/32] fix drag icon's surface returned by xytonode --- dwl.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/dwl.c b/dwl.c index 536b4d6..f8c2264 100644 --- a/dwl.c +++ b/dwl.c @@ -67,7 +67,7 @@ /* enums */ enum { CurNormal, CurMove, CurResize }; /* cursor */ enum { XDGShell, LayerShell, X11Managed, X11Unmanaged }; /* client types */ -enum { LyrBg, LyrBottom, LyrTop, LyrOverlay, LyrTile, LyrFloat, NUM_LAYERS }; /* scene layers */ +enum { LyrBg, LyrBottom, LyrTop, LyrOverlay, LyrTile, LyrFloat, LyrNoFocus, NUM_LAYERS }; /* scene layers */ #ifdef XWAYLAND enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ @@ -1911,6 +1911,7 @@ setup(void) layers[LyrFloat] = &wlr_scene_tree_create(&scene->node)->node; layers[LyrTop] = &wlr_scene_tree_create(&scene->node)->node; layers[LyrOverlay] = &wlr_scene_tree_create(&scene->node)->node; + layers[LyrNoFocus] = &wlr_scene_tree_create(&scene->node)->node; /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) @@ -2079,7 +2080,7 @@ startdrag(struct wl_listener *listener, void *data) if (!drag->icon) return; - drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrTop], drag->icon->surface); + drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrNoFocus], drag->icon->surface); motionnotify(0); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); } @@ -2308,17 +2309,23 @@ xytonode(double x, double y, struct wlr_surface **psurface, struct wlr_surface *surface = NULL; Client *c = NULL; LayerSurface *l = NULL; + int i; + int focus_order[] = { LyrOverlay, LyrTop, LyrFloat, LyrTile, LyrBottom, LyrBg }; - if ((node = wlr_scene_node_at(&scene->node, x, y, nx, ny))) { - if (node->type == WLR_SCENE_NODE_SURFACE) - surface = wlr_scene_surface_from_node(node)->surface; - /* Walk the tree to find a node that knows the client */ - for (pnode = node; pnode && !c; pnode = pnode->parent) - c = pnode->data; - if (c && c->type == LayerShell) { - c = NULL; - l = pnode->data; + for (i = 0; i < LENGTH(focus_order); i++) { + if ((node = wlr_scene_node_at(layers[focus_order[i]], x, y, nx, ny))) { + if (node->type == WLR_SCENE_NODE_SURFACE) + surface = wlr_scene_surface_from_node(node)->surface; + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = pnode->parent) + c = pnode->data; + if (c && c->type == LayerShell) { + c = NULL; + l = pnode->data; + } } + if (surface) + break; } if (psurface) *psurface = surface; From ae614ee5125891a4d75fac97c754207f97834a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 12 Jul 2021 19:58:55 -0500 Subject: [PATCH 18/32] implement idle-inhibitor protocol This allows clients to disable idle monitoring --- README.md | 2 +- dwl.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 13a0000..22172d5 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s - 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. - Configurable multi-monitor layout support, including position and rotation - Configurable HiDPI/multi-DPI support +- Idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Provide information to external status bars via stdout/stdin - Urgency hints via xdg-activate protocol - Various Wayland protocols @@ -26,7 +27,6 @@ Features under consideration (possibly as patches) are: - Protocols made trivial by wlroots - Implement the input-inhibitor protocol to support screen lockers (see https://github.com/djpohly/dwl/pull/132) -- Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring (see https://github.com/djpohly/dwl/pull/133) - Implement the text-input and input-method protocols to support IME once ibus implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and https://github.com/djpohly/dwl/pull/12) Feature *non-goals* for the main codebase include: diff --git a/dwl.c b/dwl.c index f8c2264..01d165b 100644 --- a/dwl.c +++ b/dwl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -219,12 +220,14 @@ static void cleanupmon(struct wl_listener *listener, void *data); static void closemon(Monitor *m); static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data); +static void createidleinhibitor(struct wl_listener *listener, void *data); static void createkeyboard(struct wlr_input_device *device); static void createmon(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); static void createlayersurface(struct wl_listener *listener, void *data); static void createpointer(struct wlr_input_device *device); static void cursorframe(struct wl_listener *listener, void *data); +static void destroyidleinhibitor(struct wl_listener *listener, void *data); static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); @@ -307,6 +310,7 @@ static struct wlr_xdg_activation_v1 *activation; static struct wl_list clients; /* tiling order */ static struct wl_list fstack; /* focus order */ static struct wlr_idle *idle; +static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; @@ -331,6 +335,8 @@ static struct wl_listener cursor_button = {.notify = buttonpress}; static struct wl_listener cursor_frame = {.notify = cursorframe}; static struct wl_listener cursor_motion = {.notify = motionrelative}; static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute}; +static struct wl_listener idle_inhibitor_create = {.notify = createidleinhibitor}; +static struct wl_listener idle_inhibitor_destroy = {.notify = destroyidleinhibitor}; static struct wl_listener layout_change = {.notify = updatemons}; static struct wl_listener new_input = {.notify = inputdevice}; static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; @@ -769,6 +775,15 @@ commitnotify(struct wl_listener *listener, void *data) c->resize = 0; } +void +createidleinhibitor(struct wl_listener *listener, void *data) +{ + struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; + wl_signal_add(&idle_inhibitor->events.destroy, &idle_inhibitor_destroy); + + wlr_idle_set_enabled(idle, seat, 0); +} + void createkeyboard(struct wlr_input_device *device) { @@ -988,6 +1003,14 @@ cursorframe(struct wl_listener *listener, void *data) wlr_seat_pointer_notify_frame(seat); } +void +destroyidleinhibitor(struct wl_listener *listener, void *data) +{ + /* I've been testing and at this point the inhibitor has not yet been + * removed from the list, checking if it has at least one item. */ + wlr_idle_set_enabled(idle, seat, wl_list_length(&idle_inhibit_mgr->inhibitors) <= 1); +} + void destroylayersurfacenotify(struct wl_listener *listener, void *data) { @@ -1147,6 +1170,7 @@ focusclient(Client *c, int lift) } printstatus(); + wlr_idle_set_enabled(idle, seat, wl_list_empty(&idle_inhibit_mgr->inhibitors)); if (!c) { /* With no client, all we have left is to clear focus */ @@ -1963,6 +1987,9 @@ setup(void) idle = wlr_idle_create(dpy); + idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); + wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &idle_inhibitor_create); + layer_shell = wlr_layer_shell_v1_create(dpy); wl_signal_add(&layer_shell->events.new_surface, &new_layer_shell_surface); From a95338ca43c7b979ef81fb9d6b0c561beda93be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 3 Jul 2021 15:48:40 -0500 Subject: [PATCH 19/32] implement input-inhibitor protocol --- README.md | 2 +- dwl.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 22172d5..72488e3 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s - Idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Provide information to external status bars via stdout/stdin - Urgency hints via xdg-activate protocol +- Support screen lockers via input-inhibitor protocol - Various Wayland protocols - XWayland support as provided by wlroots (can be enabled in `config.mk`) - Zero flickering - Wayland users naturally expect that "every frame is perfect" @@ -26,7 +27,6 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s Features under consideration (possibly as patches) are: - Protocols made trivial by wlroots -- Implement the input-inhibitor protocol to support screen lockers (see https://github.com/djpohly/dwl/pull/132) - Implement the text-input and input-method protocols to support IME once ibus implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and https://github.com/djpohly/dwl/pull/12) Feature *non-goals* for the main codebase include: diff --git a/dwl.c b/dwl.c index 01d165b..1bee09c 100644 --- a/dwl.c +++ b/dwl.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -311,6 +312,7 @@ static struct wl_list clients; /* tiling order */ static struct wl_list fstack; /* focus order */ static struct wlr_idle *idle; static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; +static struct wlr_input_inhibit_manager *input_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; @@ -1309,8 +1311,10 @@ keypress(struct wl_listener *listener, void *data) wlr_idle_notify_activity(idle, seat); - /* On _press_, attempt to process a compositor keybinding. */ - if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) + /* On _press_ if there is no active screen locker, + * attempt to process a compositor keybinding. */ + if (!input_inhibit_mgr->active_inhibitor + && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) for (i = 0; i < nsyms; i++) handled = keybinding(mods, syms[i]) || handled; @@ -1996,6 +2000,8 @@ setup(void) xdg_shell = wlr_xdg_shell_create(dpy); wl_signal_add(&xdg_shell->events.new_surface, &new_xdg_surface); + input_inhibit_mgr = wlr_input_inhibit_manager_create(dpy); + /* Use decoration protocols to negotiate server-side decorations */ wlr_server_decoration_manager_set_default_mode( wlr_server_decoration_manager_create(dpy), From cb4265ac8c48faeac385b038b59ac53a736d142d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 24 Mar 2022 14:19:08 -0600 Subject: [PATCH 20/32] check `m` in commitlayersurfacenotify() --- dwl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index 1bee09c..529dbf8 100644 --- a/dwl.c +++ b/dwl.c @@ -755,9 +755,8 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) wlr_scene_node_reparent(layersurface->scene, layers[wlr_layer_surface->current.layer]); - if (!wlr_output) + if (!wlr_output || !(m = wlr_output->data)) return; - m = wlr_output->data; if (layers[wlr_layer_surface->current.layer] != layersurface->scene) { wl_list_remove(&layersurface->link); From aab397c30b9b9e4223a4f408431eb3aa5521cb92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 15 Mar 2022 15:52:26 -0600 Subject: [PATCH 21/32] new functions ecalloc() and die() die() replaces EBARF and BARF and allow us to add `-pedantic` to CFLAGS --- Makefile | 4 ++-- config.mk | 2 +- dwl.c | 46 ++++++++++++++++++---------------------------- util.c | 35 +++++++++++++++++++++++++++++++++++ util.h | 4 ++++ 5 files changed, 60 insertions(+), 31 deletions(-) create mode 100644 util.c create mode 100644 util.h diff --git a/Makefile b/Makefile index 536454f..bba8c9f 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,6 @@ idle-protocol.o: idle-protocol.h config.h: | config.def.h cp config.def.h $@ -dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h +dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h util.h -dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o +dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o util.o diff --git a/config.mk b/config.mk index 960fc8a..ab61185 100644 --- a/config.mk +++ b/config.mk @@ -3,7 +3,7 @@ PREFIX = /usr/local MANDIR = $(PREFIX)/share/man # Default compile flags (overridable by environment) -CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement +CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement -pedantic # Uncomment to build XWayland support #CFLAGS += -DXWAYLAND diff --git a/dwl.c b/dwl.c index 529dbf8..a3b33aa 100644 --- a/dwl.c +++ b/dwl.c @@ -54,9 +54,9 @@ #include #endif +#include "util.h" + /* macros */ -#define BARF(fmt, ...) do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } while (0) -#define EBARF(fmt, ...) BARF(fmt ": %s", ##__VA_ARGS__, strerror(errno)) #define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) @@ -790,9 +790,7 @@ createkeyboard(struct wlr_input_device *device) { struct xkb_context *context; struct xkb_keymap *keymap; - Keyboard *kb = device->data = calloc(1, sizeof(*kb)); - if (!kb) - EBARF("createkeyboard: calloc"); + Keyboard *kb = device->data = ecalloc(1, sizeof(*kb)); kb->device = device; /* Prepare an XKB keymap and assign it to the keyboard. */ @@ -823,9 +821,7 @@ createmon(struct wl_listener *listener, void *data) * monitor) becomes available. */ struct wlr_output *wlr_output = data; const MonitorRule *r; - Monitor *m = wlr_output->data = calloc(1, sizeof(*m)); - if (!m) - EBARF("createmon: calloc"); + Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m)); m->wlr_output = wlr_output; wlr_output_init_render(wlr_output, alloc, drw); @@ -910,9 +906,7 @@ createnotify(struct wl_listener *listener, void *data) return; /* Allocate a Client for this surface */ - c = xdg_surface->data = calloc(1, sizeof(*c)); - if (!c) - EBARF("createnotify: calloc"); + c = xdg_surface->data = ecalloc(1, sizeof(*c)); c->surface.xdg = xdg_surface; c->bw = borderpx; @@ -938,9 +932,7 @@ createlayersurface(struct wl_listener *listener, void *data) wlr_layer_surface->output = selmon->wlr_output; } - layersurface = calloc(1, sizeof(LayerSurface)); - if (!layersurface) - EBARF("layersurface: calloc"); + layersurface = ecalloc(1, sizeof(LayerSurface)); layersurface->type = LayerShell; LISTEN(&wlr_layer_surface->surface->events.commit, &layersurface->surface_commit, commitlayersurfacenotify); @@ -1744,7 +1736,7 @@ run(char *startup_cmd) /* Add a Unix socket to the Wayland display. */ const char *socket = wl_display_add_socket_auto(dpy); if (!socket) - BARF("startup: display_add_socket_auto"); + die("startup: display_add_socket_auto"); setenv("WAYLAND_DISPLAY", socket, 1); /* Now that the socket exists, run the startup command */ @@ -1753,13 +1745,13 @@ run(char *startup_cmd) pipe(piperw); startup_pid = fork(); if (startup_pid < 0) - EBARF("startup: fork"); + die("startup: fork:"); if (startup_pid == 0) { dup2(piperw[0], STDIN_FILENO); close(piperw[0]); close(piperw[1]); execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); - EBARF("startup: execl"); + die("startup: execl:"); } dup2(piperw[1], STDOUT_FILENO); close(piperw[1]); @@ -1772,7 +1764,7 @@ run(char *startup_cmd) /* Start the backend. This will enumerate outputs and inputs, become the DRM * master, etc */ if (!wlr_backend_start(backend)) - BARF("startup: backend_start"); + die("startup: backend_start"); /* Now that outputs are initialized, choose initial selmon based on * cursor position, and set default cursor image */ @@ -1928,7 +1920,7 @@ setup(void) * if the backend does not support hardware cursors (some older GPUs * don't). */ if (!(backend = wlr_backend_autocreate(dpy))) - BARF("couldn't create backend"); + die("couldn't create backend"); /* Initialize the scene graph used to lay out windows */ scene = wlr_scene_create(); @@ -1942,12 +1934,12 @@ setup(void) /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) - BARF("couldn't create renderer"); + die("couldn't create renderer"); wlr_renderer_init_wl_display(drw, dpy); /* Create a default allocator */ if (!(alloc = wlr_allocator_autocreate(backend, drw))) - BARF("couldn't create allocator"); + die("couldn't create allocator"); /* This creates some hands-off wlroots interfaces. The compositor is * necessary for clients to allocate surfaces and the data device manager @@ -2088,7 +2080,7 @@ sigchld(int unused) * setting our own disposition for SIGCHLD. */ if (signal(SIGCHLD, sigchld) == SIG_ERR) - EBARF("can't install SIGCHLD handler"); + die("can't install SIGCHLD handler:"); while (0 < waitpid(-1, NULL, WNOHANG)) ; } @@ -2100,7 +2092,7 @@ spawn(const Arg *arg) dup2(STDERR_FILENO, STDOUT_FILENO); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); - EBARF("dwl: execvp %s failed", ((char **)arg->v)[0]); + die("dwl: execvp %s failed:", ((char **)arg->v)[0]); } } @@ -2435,9 +2427,7 @@ createnotifyx11(struct wl_listener *listener, void *data) setfullscreen(c, 0); /* Allocate a Client for this surface */ - c = xwayland_surface->data = calloc(1, sizeof(*c)); - if (!c) - EBARF("createnotifyx11: calloc"); + c = xwayland_surface->data = ecalloc(1, sizeof(*c)); c->surface.xwayland = xwayland_surface; c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed; c->bw = borderpx; @@ -2517,12 +2507,12 @@ main(int argc, char *argv[]) /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */ if (!getenv("XDG_RUNTIME_DIR")) - BARF("XDG_RUNTIME_DIR must be set"); + die("XDG_RUNTIME_DIR must be set"); setup(); run(startup_cmd); cleanup(); return EXIT_SUCCESS; usage: - BARF("Usage: %s [-s startup command]", argv[0]); + die("Usage: %s [-s startup command]", argv[0]); } diff --git a/util.c b/util.c new file mode 100644 index 0000000..932f89b --- /dev/null +++ b/util.c @@ -0,0 +1,35 @@ +/* See LICENSE.dwm file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} + +void +die(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..4c94117 --- /dev/null +++ b/util.h @@ -0,0 +1,4 @@ +/* See LICENSE.dwm file for copyright and license details. */ + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); From 2d6f932ecfc9580721cfa6a2f8dfa22d2af540c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 31 Mar 2022 09:21:27 -0600 Subject: [PATCH 22/32] don't let -pedantic be overridable by environment --- Makefile | 2 +- config.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index bba8c9f..70c31d3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ include config.mk -CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 +CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 -pedantic WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols) WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner) diff --git a/config.mk b/config.mk index ab61185..960fc8a 100644 --- a/config.mk +++ b/config.mk @@ -3,7 +3,7 @@ PREFIX = /usr/local MANDIR = $(PREFIX)/share/man # Default compile flags (overridable by environment) -CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement -pedantic +CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement # Uncomment to build XWayland support #CFLAGS += -DXWAYLAND From ae313911153b9c9ca8bef8ded97b95c0c2f49624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 31 Mar 2022 09:31:01 -0600 Subject: [PATCH 23/32] initialize rules and xkb_rules to fix compile errors with `-pedantic` --- config.def.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 9bdf8b5..00f6a85 100644 --- a/config.def.h +++ b/config.def.h @@ -13,8 +13,8 @@ static const Rule rules[] = { /* app_id title tags mask isfloating monitor */ /* examples: { "Gimp", NULL, 0, 1, -1 }, - { "firefox", NULL, 1 << 8, 0, -1 }, */ + { "firefox", NULL, 1 << 8, 0, -1 }, }; /* layout(s) */ @@ -43,6 +43,7 @@ static const struct xkb_rule_names xkb_rules = { /* example: .options = "ctrl:nocaps", */ + .options = "", }; static const int repeat_rate = 25; From b424602ebc2dc26a3c974ee2a87ab745821491b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 31 Mar 2022 09:39:34 -0600 Subject: [PATCH 24/32] add DESTDIR --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 70c31d3..48a0aa7 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,11 @@ clean: rm -f dwl *.o *-protocol.h *-protocol.c install: dwl - install -Dm755 dwl $(PREFIX)/bin/dwl - install -Dm644 dwl.1 $(MANDIR)/man1/dwl.1 + install -Dm755 dwl $(DESTDIR)$(PREFIX)/bin/dwl + install -Dm644 dwl.1 $(DESTDIR)$(MANDIR)/man1/dwl.1 uninstall: - rm -f $(PREFIX)/bin/dwl $(MANDIR)/man1/dwl.1 + rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 .PHONY: all clean install uninstall From 79b7e755b010fc1486a89a46251a404cb97a341a Mon Sep 17 00:00:00 2001 From: Raphael Robatsch Date: Sat, 6 Nov 2021 19:51:17 +0100 Subject: [PATCH 25/32] Layer shell: Prevent infinte configure/commit loop Check the wlr_layer_surface_v1_state.committed bitmask to see if we need to rearrange. This is also what sway does. Without this check, every commit request (even if only the attached buffer changed) will lead to another configure event, which will lead to another commit, etc. This loop results in swaybg consuming 100% CPU. Co-authored-by: Owen Rafferty --- dwl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dwl.c b/dwl.c index a3b33aa..bc74c96 100644 --- a/dwl.c +++ b/dwl.c @@ -140,6 +140,7 @@ typedef struct { typedef struct { /* Must be first */ unsigned int type; /* LayerShell */ + int mapped; struct wlr_scene_node *scene; struct wl_list link; struct wlr_layer_surface_v1 *layer_surface; @@ -758,6 +759,12 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) if (!wlr_output || !(m = wlr_output->data)) return; + if (wlr_layer_surface->current.committed == 0 + && layersurface->mapped == wlr_layer_surface->mapped) + return; + + layersurface->mapped = wlr_layer_surface->mapped; + if (layers[wlr_layer_surface->current.layer] != layersurface->scene) { wl_list_remove(&layersurface->link); wl_list_insert(&m->layers[wlr_layer_surface->current.layer], From 4d3adea68325b70eafbd56a31023f96b92532b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 31 Mar 2022 12:24:09 -0600 Subject: [PATCH 26/32] die on pipe failure --- dwl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwl.c b/dwl.c index bc74c96..ac62120 100644 --- a/dwl.c +++ b/dwl.c @@ -1749,9 +1749,9 @@ run(char *startup_cmd) /* Now that the socket exists, run the startup command */ if (startup_cmd) { int piperw[2]; - pipe(piperw); - startup_pid = fork(); - if (startup_pid < 0) + if (pipe(piperw) < 0) + die("startup: pipe:"); + if ((startup_pid = fork()) < 0) die("startup: fork:"); if (startup_pid == 0) { dup2(piperw[0], STDIN_FILENO); From 720f56161e5401afc1526d1ebfb977b191ca10f5 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 3 Apr 2022 00:01:52 -0500 Subject: [PATCH 27/32] Remove vestigial monitor configuration info The x/y fields in monitor rules are unused and were meant to be deleted. Also removes the outdated comment in config.h. --- config.def.h | 4 +--- dwl.c | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/config.def.h b/config.def.h index 00f6a85..7e61695 100644 --- a/config.def.h +++ b/config.def.h @@ -25,9 +25,7 @@ static const Layout layouts[] = { { "[M]", monocle }, }; -/* monitors - * The order in which monitors are defined determines their position. - * Non-configured monitors are always added to the left. */ +/* monitors */ static const MonitorRule monrules[] = { /* name mfact nmaster scale layout rotate/reflect x y */ /* example of a HiDPI laptop monitor: diff --git a/dwl.c b/dwl.c index ac62120..24d015f 100644 --- a/dwl.c +++ b/dwl.c @@ -191,8 +191,6 @@ typedef struct { float scale; const Layout *lt; enum wl_output_transform rr; - int x; - int y; } MonitorRule; typedef struct { From 6901743b0c334079ddc185af4f6844c336631d84 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 3 Apr 2022 00:13:11 -0500 Subject: [PATCH 28/32] Remove removed fields from struct instances --- config.def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index 7e61695..7eb80b5 100644 --- a/config.def.h +++ b/config.def.h @@ -29,10 +29,10 @@ static const Layout layouts[] = { static const MonitorRule monrules[] = { /* name mfact nmaster scale layout rotate/reflect x y */ /* example of a HiDPI laptop monitor: - { "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0 }, + { "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL }, */ /* defaults */ - { NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0 }, + { NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL }, }; /* keyboard */ From 437aea866268779e9599c584d5c5ab25ae682840 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 3 Apr 2022 00:14:08 -0500 Subject: [PATCH 29/32] It's past my bedtime. --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 7eb80b5..190b0da 100644 --- a/config.def.h +++ b/config.def.h @@ -27,7 +27,7 @@ static const Layout layouts[] = { /* monitors */ static const MonitorRule monrules[] = { - /* name mfact nmaster scale layout rotate/reflect x y */ + /* name mfact nmaster scale layout rotate/reflect */ /* example of a HiDPI laptop monitor: { "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL }, */ From 02ac9378c4fb40969db6e897605016bbaf422961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 5 Apr 2022 22:07:20 -0500 Subject: [PATCH 30/32] includes: abc --- dwl.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dwl.c b/dwl.c index 24d015f..816eaa5 100644 --- a/dwl.c +++ b/dwl.c @@ -3,6 +3,7 @@ */ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -10,9 +11,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -21,13 +22,12 @@ #include #include #include -#include -#include #include #include -#include +#include +#include #include -#include +#include #include #include #include @@ -35,10 +35,10 @@ #include #include #include -#include #include -#include +#include #include +#include #include #include #include @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #ifdef XWAYLAND From af741e586b80440b59b61e8fdc22c69fb7e8a457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 5 Apr 2022 22:15:46 -0500 Subject: [PATCH 31/32] typedefs: abc --- dwl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dwl.c b/dwl.c index 816eaa5..424485f 100644 --- a/dwl.c +++ b/dwl.c @@ -120,6 +120,14 @@ typedef struct { int isfullscreen; } Client; +typedef struct { + uint32_t singular_anchor; + uint32_t anchor_triplet; + int *positive_axis; + int *negative_axis; + int margin; +} Edge; + typedef struct { uint32_t mod; xkb_keysym_t keysym; @@ -152,14 +160,6 @@ typedef struct { struct wlr_box geo; } LayerSurface; -typedef struct { - uint32_t singular_anchor; - uint32_t anchor_triplet; - int *positive_axis; - int *negative_axis; - int margin; -} Edge; - typedef struct { const char *symbol; void (*arrange)(Monitor *); From c00697e6438164e08baacc309b3dcdb727053aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 5 Apr 2022 23:04:04 -0500 Subject: [PATCH 32/32] abc --- dwl.c | 238 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/dwl.c b/dwl.c index 424485f..b09fc6f 100644 --- a/dwl.c +++ b/dwl.c @@ -221,9 +221,9 @@ static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data); static void createidleinhibitor(struct wl_listener *listener, void *data); static void createkeyboard(struct wlr_input_device *device); +static void createlayersurface(struct wl_listener *listener, void *data); static void createmon(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); -static void createlayersurface(struct wl_listener *listener, void *data); static void createpointer(struct wlr_input_device *device); static void cursorframe(struct wl_listener *listener, void *data); static void destroyidleinhibitor(struct wl_listener *listener, void *data); @@ -234,8 +234,8 @@ static void dragicondestroy(struct wl_listener *listener, void *data); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static void fullscreennotify(struct wl_listener *listener, void *data); static Client *focustop(Monitor *m); +static void fullscreennotify(struct wl_listener *listener, void *data); static void incnmaster(const Arg *arg); static void inputdevice(struct wl_listener *listener, void *data); static int keybinding(uint32_t mods, xkb_keysym_t sym); @@ -263,13 +263,13 @@ static void resize(Client *c, int x, int y, int w, int h, int interact); static void run(char *startup_cmd); static Client *selclient(void); static void setcursor(struct wl_listener *listener, void *data); -static void setpsel(struct wl_listener *listener, void *data); -static void setsel(struct wl_listener *listener, void *data); static void setfloating(Client *c, int floating); static void setfullscreen(Client *c, int fullscreen); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setmon(Client *c, Monitor *m, unsigned int newtags); +static void setpsel(struct wl_listener *listener, void *data); +static void setsel(struct wl_listener *listener, void *data); static void setup(void); static void sigchld(int unused); static void spawn(const Arg *arg); @@ -289,9 +289,9 @@ static void updatetitle(struct wl_listener *listener, void *data); static void urgent(struct wl_listener *listener, void *data); static void view(const Arg *arg); static void virtualkeyboard(struct wl_listener *listener, void *data); +static Monitor *xytomon(double x, double y); static struct wlr_scene_node *xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny); -static Monitor *xytomon(double x, double y); static void zoom(const Arg *arg); /* variables */ @@ -818,6 +818,50 @@ createkeyboard(struct wlr_input_device *device) wl_list_insert(&keyboards, &kb->link); } +void +createlayersurface(struct wl_listener *listener, void *data) +{ + struct wlr_layer_surface_v1 *wlr_layer_surface = data; + LayerSurface *layersurface; + Monitor *m; + struct wlr_layer_surface_v1_state old_state; + + if (!wlr_layer_surface->output) { + wlr_layer_surface->output = selmon->wlr_output; + } + + layersurface = ecalloc(1, sizeof(LayerSurface)); + layersurface->type = LayerShell; + LISTEN(&wlr_layer_surface->surface->events.commit, + &layersurface->surface_commit, commitlayersurfacenotify); + LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy, + destroylayersurfacenotify); + LISTEN(&wlr_layer_surface->events.map, &layersurface->map, + maplayersurfacenotify); + LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap, + unmaplayersurfacenotify); + + layersurface->layer_surface = wlr_layer_surface; + wlr_layer_surface->data = layersurface; + m = wlr_layer_surface->output->data; + + layersurface->scene = wlr_layer_surface->surface->data = + wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer], + wlr_layer_surface->surface); + layersurface->scene->data = layersurface; + + wl_list_insert(&m->layers[wlr_layer_surface->pending.layer], + &layersurface->link); + + /* Temporarily set the layer's current state to pending + * so that we can easily arrange it + */ + old_state = wlr_layer_surface->current; + wlr_layer_surface->current = wlr_layer_surface->pending; + arrangelayers(m); + wlr_layer_surface->current = old_state; +} + void createmon(struct wl_listener *listener, void *data) { @@ -924,50 +968,6 @@ createnotify(struct wl_listener *listener, void *data) c->isfullscreen = 0; } -void -createlayersurface(struct wl_listener *listener, void *data) -{ - struct wlr_layer_surface_v1 *wlr_layer_surface = data; - LayerSurface *layersurface; - Monitor *m; - struct wlr_layer_surface_v1_state old_state; - - if (!wlr_layer_surface->output) { - wlr_layer_surface->output = selmon->wlr_output; - } - - layersurface = ecalloc(1, sizeof(LayerSurface)); - layersurface->type = LayerShell; - LISTEN(&wlr_layer_surface->surface->events.commit, - &layersurface->surface_commit, commitlayersurfacenotify); - LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy, - destroylayersurfacenotify); - LISTEN(&wlr_layer_surface->events.map, &layersurface->map, - maplayersurfacenotify); - LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap, - unmaplayersurfacenotify); - - layersurface->layer_surface = wlr_layer_surface; - wlr_layer_surface->data = layersurface; - m = wlr_layer_surface->output->data; - - layersurface->scene = wlr_layer_surface->surface->data = - wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer], - wlr_layer_surface->surface); - layersurface->scene->data = layersurface; - - wl_list_insert(&m->layers[wlr_layer_surface->pending.layer], - &layersurface->link); - - /* Temporarily set the layer's current state to pending - * so that we can easily arrange it - */ - old_state = wlr_layer_surface->current; - wlr_layer_surface->current = wlr_layer_surface->pending; - arrangelayers(m); - wlr_layer_surface->current = old_state; -} - void createpointer(struct wlr_input_device *device) { @@ -1049,57 +1049,6 @@ destroynotify(struct wl_listener *listener, void *data) free(c); } -void -dragicondestroy(struct wl_listener *listener, void *data) -{ - struct wlr_drag_icon *icon = data; - wlr_scene_node_destroy(icon->data); - // Focus enter isn't sent during drag, so refocus the focused node. - focusclient(selclient(), 1); - motionnotify(0); -} - -void -togglefullscreen(const Arg *arg) -{ - Client *sel = selclient(); - if (sel) - setfullscreen(sel, !sel->isfullscreen); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - c->isfullscreen = fullscreen; - c->bw = fullscreen ? 0 : borderpx; - client_set_fullscreen(c, fullscreen); - - if (fullscreen) { - c->prev = c->geom; - resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0); - } else { - /* restore previous size instead of arrange for floating windows since - * client positions are set by the user and cannot be recalculated */ - resize(c, c->prev.x, c->prev.y, c->prev.width, c->prev.height, 0); - } - arrange(c->mon); - printstatus(); -} - -void -fullscreennotify(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, fullscreen); - int fullscreen = client_wants_fullscreen(c); - - if (!c->mon) { - /* if the client is not mapped yet, let mapnotify() call setfullscreen() */ - c->isfullscreen = fullscreen; - return; - } - setfullscreen(c, fullscreen); -} - Monitor * dirtomon(enum wlr_direction dir) { @@ -1114,6 +1063,16 @@ dirtomon(enum wlr_direction dir) return selmon; } +void +dragicondestroy(struct wl_listener *listener, void *data) +{ + struct wlr_drag_icon *icon = data; + wlr_scene_node_destroy(icon->data); + // Focus enter isn't sent during drag, so refocus the focused node. + focusclient(selclient(), 1); + motionnotify(0); +} + void focusclient(Client *c, int lift) { @@ -1229,6 +1188,20 @@ focustop(Monitor *m) return NULL; } +void +fullscreennotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, fullscreen); + int fullscreen = client_wants_fullscreen(c); + + if (!c->mon) { + /* if the client is not mapped yet, let mapnotify() call setfullscreen() */ + c->isfullscreen = fullscreen; + return; + } + setfullscreen(c, fullscreen); +} + void incnmaster(const Arg *arg) { @@ -1692,6 +1665,18 @@ rendermon(struct wl_listener *listener, void *data) m->un_map = 0; } +void +requeststartdrag(struct wl_listener *listener, void *data) +{ + struct wlr_seat_request_start_drag_event *event = data; + + if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, + event->serial)) + wlr_seat_start_pointer_drag(seat, event->drag, event->serial); + else + wlr_data_source_destroy(event->drag->source); +} + void resize(Client *c, int x, int y, int w, int h, int interact) { @@ -1720,18 +1705,6 @@ resize(Client *c, int x, int y, int w, int h, int interact) c->geom.height - 2 * c->bw); } -void -requeststartdrag(struct wl_listener *listener, void *data) -{ - struct wlr_seat_request_start_drag_event *event = data; - - if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, - event->serial)) - wlr_seat_start_pointer_drag(seat, event->drag, event->serial); - else - wlr_data_source_destroy(event->drag->source); -} - void run(char *startup_cmd) { @@ -1830,6 +1803,25 @@ setfloating(Client *c, int floating) printstatus(); } +void +setfullscreen(Client *c, int fullscreen) +{ + c->isfullscreen = fullscreen; + c->bw = fullscreen ? 0 : borderpx; + client_set_fullscreen(c, fullscreen); + + if (fullscreen) { + c->prev = c->geom; + resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0); + } else { + /* restore previous size instead of arrange for floating windows since + * client positions are set by the user and cannot be recalculated */ + resize(c, c->prev.x, c->prev.y, c->prev.width, c->prev.height, 0); + } + arrange(c->mon); + printstatus(); +} + void setlayout(const Arg *arg) { @@ -2176,6 +2168,14 @@ togglefloating(const Arg *arg) setfloating(sel, !sel->isfloating); } +void +togglefullscreen(const Arg *arg) +{ + Client *sel = selclient(); + if (sel) + setfullscreen(sel, !sel->isfullscreen); +} + void toggletag(const Arg *arg) { @@ -2329,6 +2329,13 @@ virtualkeyboard(struct wl_listener *listener, void *data) createkeyboard(device); } +Monitor * +xytomon(double x, double y) +{ + struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); + return o ? o->data : NULL; +} + struct wlr_scene_node * xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny) @@ -2362,13 +2369,6 @@ xytonode(double x, double y, struct wlr_surface **psurface, return node; } -Monitor * -xytomon(double x, double y) -{ - struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); - return o ? o->data : NULL; -} - void zoom(const Arg *arg) {