~ruther/dwl

5dfd7cf180ce2a8e9333bb385cd17484675f8467 — Devin J. Pohly 3 years ago 77e75cf + 06ca860
Merge branch 'main' into wlroots-next
4 files changed, 52 insertions(+), 19 deletions(-)

M Makefile
M README.md
M client.h
M dwl.c
M Makefile => Makefile +12 -10
@@ 11,6 11,17 @@ 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

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
# to your build system yourself and provide them in the include path.


@@ 47,15 58,6 @@ 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

clean:
	rm -f dwl *.o *-protocol.h *-protocol.c

install: dwl
	install -D dwl $(PREFIX)/bin/dwl

.DEFAULT_GOAL=dwl
.PHONY: clean

M README.md => README.md +5 -4
@@ 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


M client.h => client.h +11 -0
@@ 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)
{

M dwl.c => dwl.c +24 -5
@@ 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);


@@ 883,14 885,11 @@ 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);
	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 993,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)


@@ 1304,6 1304,9 @@ 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 */
	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);
}


@@ 1805,15 1808,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


@@ 2292,6 2302,14 @@ updatemons(struct wl_listener *listener, void *data)
}

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)
{
	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])


@@ 2427,6 2445,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);

Do not follow this link