~ruther/dwl

29a2b647b27e5314fa1b9cb6158eb95cfb0bc405 — Leonardo Hernández Hernández 3 years ago dd0b8e4 + c00697e
Merge remote-tracking branch 'djpohly/main' into HEAD
6 files changed, 230 insertions(+), 165 deletions(-)

M Makefile
M README.md
M config.def.h
M dwl.c
A util.c
A util.h
M Makefile => Makefile +6 -6
@@ 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)


@@ 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



@@ 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

M README.md => README.md +2 -2
@@ 14,8 14,10 @@ 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
- 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"


@@ 25,8 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 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:

M config.def.h => config.def.h +6 -7
@@ 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) */


@@ 25,16 25,14 @@ 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 */
	/* 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, 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 */


@@ 43,6 41,7 @@ static const struct xkb_rule_names xkb_rules = {
	/* example:
	.options = "ctrl:nocaps",
	*/
	.options = "",
};

static const int repeat_rate = 25;

M dwl.c => dwl.c +177 -150
@@ 3,6 3,7 @@
 */
#define _POSIX_C_SOURCE 200809L
#include <getopt.h>
#include <libinput.h>
#include <linux/input-event-codes.h>
#include <signal.h>
#include <stdio.h>


@@ 10,9 11,9 @@
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <libinput.h>
#include <wayland-server-core.h>
#include <wlr/backend.h>
#include <wlr/backend/libinput.h>
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_compositor.h>


@@ 21,11 22,12 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output_management_v1.h>


@@ 33,10 35,10 @@
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_primary_selection_v1.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>


@@ 45,7 47,6 @@
#include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/backend/libinput.h>
#include <wlr/util/log.h>
#include <xkbcommon/xkbcommon.h>
#ifdef XWAYLAND


@@ 53,9 54,9 @@
#include <wlr/xwayland.h>
#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)


@@ 139,6 140,7 @@ typedef struct {
typedef struct {
	/* Must be first */
	unsigned int type; /* LayerShell */
	int mapped;
	struct wlr_scene_node *scene;
	struct wlr_scene_layer_surface_v1 *scene_layer;
	struct wl_list link;


@@ 180,8 182,6 @@ typedef struct {
	float scale;
	const Layout *lt;
	enum wl_output_transform rr;
	int x;
	int y;
} MonitorRule;

typedef struct {


@@ 208,12 208,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_keyboard *keyboard);
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_pointer *pointer);
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);


@@ 221,8 223,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);


@@ 250,13 252,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 spawn(const Arg *arg);
static void startdrag(struct wl_listener *listener, void *data);


@@ 275,9 277,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 */


@@ 295,6 297,8 @@ 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_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;


@@ 319,6 323,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};


@@ 620,9 626,14 @@ 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 (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);


@@ 643,13 654,20 @@ commitnotify(struct wl_listener *listener, void *data)
}

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_keyboard *keyboard)
{
	struct xkb_context *context;
	struct xkb_keymap *keymap;
	Keyboard *kb = keyboard->data = calloc(1, sizeof(*kb));
	if (!kb)
		EBARF("createkeyboard: calloc");
	Keyboard *kb = keyboard->data = ecalloc(1, sizeof(*kb));
	kb->wlr_keyboard = keyboard;

	/* Prepare an XKB keymap and assign it to the keyboard. */


@@ 674,15 692,59 @@ createkeyboard(struct wlr_keyboard *keyboard)
}

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_layer = wlr_scene_layer_surface_v1_create(
			layers[wlr_layer_surface->pending.layer], wlr_layer_surface);
	layersurface->scene = wlr_layer_surface->surface->data =
			layersurface->scene_layer->node;

	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)
{
	/* This event is raised by the backend when a new output (aka a display or
	 * 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);


@@ 767,9 829,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;



@@ 784,53 844,6 @@ createnotify(struct wl_listener *listener, void *data)
}

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 = calloc(1, sizeof(LayerSurface));
	if (!layersurface)
		EBARF("layersurface: calloc");
	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_layer = wlr_scene_layer_surface_v1_create(
			layers[wlr_layer_surface->pending.layer], wlr_layer_surface);
	layersurface->scene = wlr_layer_surface->surface->data =
			layersurface->scene_layer->node;
	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_pointer *pointer)
{
	if (wlr_input_device_is_libinput(&pointer->base)) {


@@ 863,6 876,14 @@ cursorframe(struct wl_listener *listener, void *data)
}

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)
{
	LayerSurface *layersurface = wl_container_of(listener, layersurface, destroy);


@@ 903,57 924,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)
{


@@ 969,6 939,16 @@ dirtomon(enum wlr_direction dir)
}

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)
{
	struct wlr_surface *old = seat->keyboard_state.focused_surface;


@@ 1021,6 1001,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 */


@@ 1083,6 1064,20 @@ focustop(Monitor *m)
}

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)
{
	selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);


@@ 1159,8 1154,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;



@@ 1591,22 1588,22 @@ 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 */
	if (startup_cmd) {
		int piperw[2];
		pipe(piperw);
		startup_pid = fork();
		if (startup_pid < 0)
			EBARF("startup: fork");
		if (pipe(piperw) < 0)
			die("startup: pipe:");
		if ((startup_pid = fork()) < 0)
			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]);


@@ 1619,7 1616,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 */


@@ 1682,6 1679,25 @@ setfloating(Client *c, int floating)
}

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)
{
	if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])


@@ 1779,7 1795,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();


@@ 1793,12 1809,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


@@ 1842,12 1858,17 @@ 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);

	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),


@@ 1933,7 1954,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]);
	}
}



@@ 2014,6 2035,14 @@ togglefloating(const Arg *arg)
}

void
togglefullscreen(const Arg *arg)
{
	Client *sel = selclient();
	if (sel)
		setfullscreen(sel, !sel->isfullscreen);
}

void
toggletag(const Arg *arg)
{
	unsigned int newtags;


@@ 2167,6 2196,13 @@ virtualkeyboard(struct wl_listener *listener, void *data)
	createkeyboard(device->keyboard);
}

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)


@@ 2200,13 2236,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)
{


@@ 2269,9 2298,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;


@@ 2370,12 2397,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]);
}

A util.c => util.c +35 -0
@@ 0,0 1,35 @@
/* See LICENSE.dwm file for copyright and license details. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#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);
}

A util.h => util.h +4 -0
@@ 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);

Do not follow this link