From b372d4b55e256b96fe926c512499ed90c460d66f Mon Sep 17 00:00:00 2001
From: "Devin J. Pohly" <djpohly@gmail.com>
Date: Wed, 14 Apr 2021 11:15:26 -0500
Subject: [PATCH 1/9] pipe status info into -s command

Unlike with X window managers, the display socket in Wayland isn't set
up prior to starting the compositor.  Because of this, you can't pipe
the compositor's output directly into a program which needs access to
$WAYLAND_DISPLAY, which is a typical setup for this purpose.  Existing
scripts have been forced to create a pipe/FIFO or a temporary file as an
intermediary.

Instead, send the status info directly to stdin of the -s command, which
*does* have access to $WAYLAND_DISPLAY.

Fixes #103.
---
 dwl.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/dwl.c b/dwl.c
index d463985..f4b9b3a 100644
--- a/dwl.c
+++ b/dwl.c
@@ -1805,15 +1805,22 @@ run(char *startup_cmd)
 	setenv("WAYLAND_DISPLAY", socket, 1);
 
 	if (startup_cmd) {
+		int piperw[2];
+		pipe(piperw);
 		startup_pid = fork();
 		if (startup_pid < 0)
 			EBARF("startup: fork");
 		if (startup_pid == 0) {
-			dup2(STDERR_FILENO, STDOUT_FILENO);
+			dup2(piperw[0], STDIN_FILENO);
+			close(piperw[1]);
 			execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL);
 			EBARF("startup: execl");
 		}
+		dup2(piperw[1], STDOUT_FILENO);
+		close(piperw[0]);
 	}
+	/* If nobody is reading the status output, don't terminate */
+	signal(SIGPIPE, SIG_IGN);
 
 	/* Run the Wayland event loop. This does not return until you exit the
 	 * compositor. Starting the backend rigged up all of the necessary event

From 6a0dec69ec47ed8143f13016e629e5502d6339a2 Mon Sep 17 00:00:00 2001
From: "Devin J. Pohly" <djpohly@gmail.com>
Date: Thu, 15 Apr 2021 13:03:21 -0500
Subject: [PATCH 2/9] re-compile if config.mk changes

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index a0d1cc3..1362db8 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ idle-protocol.o: idle-protocol.h
 config.h: | config.def.h
 	cp config.def.h $@
 
-dwl.o: 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
 
 dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o
 

From 4170a90fbccb5823f536d7b77c2ba40e5358002b Mon Sep 17 00:00:00 2001
From: "Devin J. Pohly" <djpohly@gmail.com>
Date: Thu, 15 Apr 2021 13:04:31 -0500
Subject: [PATCH 3/9] group phony targets together in Makefile

---
 Makefile | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/Makefile b/Makefile
index 1362db8..fe6ff04 100644
--- a/Makefile
+++ b/Makefile
@@ -11,6 +11,14 @@ LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p)))
 
 all: dwl
 
+clean:
+	rm -f dwl *.o *-protocol.h *-protocol.c
+
+install: dwl
+	install -D dwl $(PREFIX)/bin/dwl
+
+.PHONY: all clean install
+
 # wayland-scanner is a tool which generates C headers and rigging for Wayland
 # protocols, which are specified in XML. wlroots requires you to rig these up
 # to your build system yourself and provide them in the include path.
@@ -50,12 +58,3 @@ config.h: | 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: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o
-
-clean:
-	rm -f dwl *.o *-protocol.h *-protocol.c
-
-install: dwl
-	install -D dwl $(PREFIX)/bin/dwl
-
-.DEFAULT_GOAL=dwl
-.PHONY: clean

From 3727f4a7b3d230226f0082581444344d563e0f9c Mon Sep 17 00:00:00 2001
From: "Devin J. Pohly" <djpohly@gmail.com>
Date: Thu, 15 Apr 2021 13:05:05 -0500
Subject: [PATCH 4/9] update status info if focused client changes title

Fixes #108.
---
 dwl.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/dwl.c b/dwl.c
index d463985..c5308f5 100644
--- a/dwl.c
+++ b/dwl.c
@@ -96,6 +96,7 @@ typedef struct {
 	struct wl_listener map;
 	struct wl_listener unmap;
 	struct wl_listener destroy;
+	struct wl_listener set_title;
 	struct wl_listener fullscreen;
 	struct wlr_box geom;  /* layout-relative, includes border */
 	Monitor *mon;
@@ -288,6 +289,7 @@ static void unmaplayersurface(LayerSurface *layersurface);
 static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
 static void unmapnotify(struct wl_listener *listener, void *data);
 static void updatemons(struct wl_listener *listener, void *data);
+static void updatetitle(struct wl_listener *listener, void *data);
 static void view(const Arg *arg);
 static void virtualkeyboard(struct wl_listener *listener, void *data);
 static Client *xytoclient(double x, double y);
@@ -891,6 +893,7 @@ createnotify(struct wl_listener *listener, void *data)
 	LISTEN(&xdg_surface->events.map, &c->map, mapnotify);
 	LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify);
 	LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify);
+	LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle);
 	LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen,
 			fullscreennotify);
 	c->isfullscreen = 0;
@@ -994,6 +997,7 @@ destroynotify(struct wl_listener *listener, void *data)
 	wl_list_remove(&c->map.link);
 	wl_list_remove(&c->unmap.link);
 	wl_list_remove(&c->destroy.link);
+	wl_list_remove(&c->set_title.link);
 	wl_list_remove(&c->fullscreen.link);
 #ifdef XWAYLAND
 	if (c->type == X11Managed)
@@ -2291,6 +2295,14 @@ updatemons(struct wl_listener *listener, void *data)
 	wlr_output_manager_v1_set_configuration(output_mgr, config);
 }
 
+void
+updatetitle(struct wl_listener *listener, void *data)
+{
+	Client *c = wl_container_of(listener, c, set_title);
+	if (c == focustop(c->mon))
+		printstatus();
+}
+
 void
 view(const Arg *arg)
 {
@@ -2427,6 +2439,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
 			activatex11);
 	LISTEN(&xwayland_surface->events.request_configure, &c->configure,
 			configurex11);
+	LISTEN(&xwayland_surface->events.set_title, &c->set_title, updatetitle);
 	LISTEN(&xwayland_surface->events.destroy, &c->destroy, destroynotify);
 	LISTEN(&xwayland_surface->events.request_fullscreen, &c->fullscreen,
 			fullscreennotify);

From d57db4cac927126d1d006becf5f2ed743ac21474 Mon Sep 17 00:00:00 2001
From: Jason Goulet-Lipman <jason.gouletlipman@gmail.com>
Date: Mon, 19 Apr 2021 09:05:35 -0400
Subject: [PATCH 5/9] added uninstall target

---
 Makefile | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index fe6ff04..5ff69e9 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,10 @@ clean:
 install: dwl
 	install -D dwl $(PREFIX)/bin/dwl
 
-.PHONY: all clean install
+uninstall:
+	rm -f $(PREFIX)/bin/dwl
+
+.PHONY: all clean install uninstall
 
 # wayland-scanner is a tool which generates C headers and rigging for Wayland
 # protocols, which are specified in XML. wlroots requires you to rig these up

From 1b139a860dacbca8c4b3f8d24930b3f829534206 Mon Sep 17 00:00:00 2001
From: "Devin J. Pohly" <djpohly@gmail.com>
Date: Tue, 18 May 2021 11:33:12 -0500
Subject: [PATCH 6/9] update README

---
 README.md | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 22dfa07..51aecf8 100644
--- a/README.md
+++ b/README.md
@@ -14,26 +14,27 @@ 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
+- Provide information to external status bars via stdout/stdin
 - Various Wayland protocols
-- XWayland support as provided by wlroots
+- XWayland support as provided by wlroots (can be enabled in `config.mk`)
 - Zero flickering - Wayland users naturally expect that "every frame is perfect"
 
 Features under consideration (possibly as patches) are:
 
 - Protocols made trivial by wlroots
-- Provide information to external status bars via stdout or another file descriptor
+- Implement urgent/focus-request once the xdg-activation protocol [hits wlroots](https://github.com/swaywm/wlroots/pull/2718)
 - Implement the input-inhibitor protocol to support screen lockers
 - Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring
 - Layer shell popups (used by Waybar)
 - Basic yes/no damage tracking to avoid needless redraws
 - More in-depth damage region tracking ([which may improve power usage](https://mozillagfx.wordpress.com/2019/10/22/dramatically-reduced-power-usage-in-firefox-70-on-macos-with-core-animation/))
 - 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)
-- Implement urgent/attention/focus-request once it's part of the xdg-shell protocol (https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/9)
 
-Feature *non-goals* include:
+Feature *non-goals* for the main codebase include:
 
 - Client-side decoration (any more than is necessary to tell the clients not to)
 - Client-initiated window management, such as move, resize, and close, which can be done through the compositor
+- Animations and visual effects
 
 ## Building dwl
 

From 93a58abf2955aa01b7c148b85490d443ab017fb7 Mon Sep 17 00:00:00 2001
From: "Devin J. Pohly" <djpohly@gmail.com>
Date: Sat, 22 May 2021 14:22:37 -0500
Subject: [PATCH 7/9] Wait until map to set window's tiled state

Workaround for a bug in Chromium where it fails to attach a buffer to
the surface.  Fixes #119.
---
 dwl.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/dwl.c b/dwl.c
index d7e798b..30a64f8 100644
--- a/dwl.c
+++ b/dwl.c
@@ -885,10 +885,6 @@ createnotify(struct wl_listener *listener, void *data)
 	c->surface.xdg = xdg_surface;
 	c->bw = borderpx;
 
-	/* Tell the client not to try anything fancy */
-	wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
-			WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
-
 	LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify);
 	LISTEN(&xdg_surface->events.map, &c->map, mapnotify);
 	LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify);
@@ -1308,6 +1304,10 @@ mapnotify(struct wl_listener *listener, void *data)
 	c->geom.width += 2 * c->bw;
 	c->geom.height += 2 * c->bw;
 
+	/* Tell the client not to try anything fancy */
+	wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
+			WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
+
 	/* Set initial monitor, tags, floating status, and focus */
 	applyrules(c);
 }

From 9ab5e01d5b3864f151c222d001a8a2152f29b518 Mon Sep 17 00:00:00 2001
From: Sevz17 <leohdz172@outlook.com>
Date: Sun, 23 May 2021 11:24:32 -0500
Subject: [PATCH 8/9] before set tiled verify if client is xdg-shell, then set
 tile

---
 dwl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/dwl.c b/dwl.c
index 30a64f8..3a562b9 100644
--- a/dwl.c
+++ b/dwl.c
@@ -1304,9 +1304,17 @@ mapnotify(struct wl_listener *listener, void *data)
 	c->geom.width += 2 * c->bw;
 	c->geom.height += 2 * c->bw;
 
+#ifdef XWAYLAND
+	if (c->type == XDGShell) {
+		/* Tell the client not to try anything fancy */
+		wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
+				WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
+	}
+#else
 	/* Tell the client not to try anything fancy */
 	wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
 			WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
+#endif
 
 	/* Set initial monitor, tags, floating status, and focus */
 	applyrules(c);

From 06ca86009296c1b8753cba259fd797703a281bbd Mon Sep 17 00:00:00 2001
From: "Devin J. Pohly" <djpohly@gmail.com>
Date: Sun, 23 May 2021 18:28:13 -0500
Subject: [PATCH 9/9] factor xwayland hackiness out into client.h

---
 client.h | 11 +++++++++++
 dwl.c    | 11 +----------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/client.h b/client.h
index f4735c2..56e3089 100644
--- a/client.h
+++ b/client.h
@@ -141,6 +141,17 @@ client_set_size(Client *c, uint32_t width, uint32_t height)
 	return wlr_xdg_toplevel_set_size(c->surface.xdg, width, height);
 }
 
+static inline void
+client_set_tiled(Client *c, uint32_t edges)
+{
+#ifdef XWAYLAND
+	if (client_is_x11(c))
+		return;
+#endif
+	wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
+			WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
+}
+
 static inline struct wlr_surface *
 client_surface(Client *c)
 {
diff --git a/dwl.c b/dwl.c
index 3a562b9..9188f06 100644
--- a/dwl.c
+++ b/dwl.c
@@ -1304,17 +1304,8 @@ mapnotify(struct wl_listener *listener, void *data)
 	c->geom.width += 2 * c->bw;
 	c->geom.height += 2 * c->bw;
 
-#ifdef XWAYLAND
-	if (c->type == XDGShell) {
-		/* Tell the client not to try anything fancy */
-		wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
-				WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
-	}
-#else
 	/* Tell the client not to try anything fancy */
-	wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
-			WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
-#endif
+	client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
 
 	/* Set initial monitor, tags, floating status, and focus */
 	applyrules(c);