~ruther/dwl

4788baee8db25c797648ca7440a6c821f3f62a9c — Alexander Courtis 4 years ago 5b464ed + e3e9504
Merge branch 'master' into 31-independents-mouse-focus
3 files changed, 224 insertions(+), 156 deletions(-)

M Makefile
A config.mk
M dwl.c
M Makefile => Makefile +4 -3
@@ 1,9 1,10 @@
WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)
include config.mk

CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-error=unused-function
CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 -Werror=declaration-after-statement

WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)

PKGS = wlroots wayland-server xcb xkbcommon
CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p)))
LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p)))

A config.mk => config.mk +5 -0
@@ 0,0 1,5 @@
# Default compile flags (overridable by environment)
CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-error=unused-function

# Uncomment to build XWayland support
#CFLAGS += -DXWAYLAND

M dwl.c => dwl.c +215 -153
@@ 33,9 33,11 @@
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
#include <wlr/xwayland.h>
#include <X11/Xlib.h>
#include <xkbcommon/xkbcommon.h>
#ifdef XWAYLAND
#include <X11/Xlib.h>
#include <wlr/xwayland.h>
#endif

/* macros */
#define MAX(A, B)               ((A) > (B) ? (A) : (B))


@@ 45,13 47,19 @@
#define LENGTH(X)               (sizeof X / sizeof X[0])
#define END(A)                  ((A) + LENGTH(A))
#define TAGMASK                 ((1 << LENGTH(tags)) - 1)
#ifdef XWAYLAND
#define WLR_SURFACE(C)          ((C)->type != XDGShell ? (C)->surface.xwayland->surface : (C)->surface.xdg->surface)
#else
#define WLR_SURFACE(C)          ((C)->surface.xdg->surface)
#endif

/* enums */
enum { CurNormal, CurMove, CurResize }; /* cursor */
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
	NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
#ifdef XWAYLAND
enum { XDGShell, X11Managed, X11Unmanaged }; /* client types */
#endif

typedef union {
	int i;


@@ 74,16 82,22 @@ typedef struct {
	struct wl_list slink;
	union {
		struct wlr_xdg_surface *xdg;
#ifdef XWAYLAND
		struct wlr_xwayland_surface *xwayland;
#endif
	} surface;
#ifdef XWAYLAND
	struct wl_listener activate;
#endif
	struct wl_listener commit;
	struct wl_listener map;
	struct wl_listener unmap;
	struct wl_listener destroy;
	struct wlr_box geom;  /* layout-relative, includes border */
	Monitor *mon;
#ifdef XWAYLAND
	unsigned int type;
#endif
	int bw;
	unsigned int tags;
	int isfloating;


@@ 157,7 171,6 @@ struct render_data {
};

/* function declarations */
static void activatex11(struct wl_listener *listener, void *data);
static void applybounds(Client *c, struct wlr_box *bbox);
static void applyrules(Client *c);
static void arrange(Monitor *m);


@@ 169,7 182,6 @@ static void cleanupmon(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 createnotifyx11(struct wl_listener *listener, void *data);
static void createpointer(struct wlr_input_device *device);
static void createxdeco(struct wl_listener *listener, void *data);
static void cursorframe(struct wl_listener *listener, void *data);


@@ 180,7 192,6 @@ static void focusclient(Client *old, Client *c, int lift);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static Client *focustop(Monitor *m);
static Atom getatom(xcb_connection_t *xc, const char *name);
static void getxdecomode(struct wl_listener *listener, void *data);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);


@@ 219,12 230,9 @@ static void tile(Monitor *m);
static void togglefloating(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void updatewindowtype(Client *c);
static void unmapnotify(struct wl_listener *listener, void *data);
static void xwaylandready(struct wl_listener *listener, void *data);
static void view(const Arg *arg);
static Client *xytoclient(double x, double y);
static Client *xytoindependent(double x, double y);
static Monitor *xytomon(double x, double y);
static void zoom(const Arg *arg);



@@ 234,7 242,6 @@ static struct wl_display *dpy;
static struct wlr_backend *backend;
static struct wlr_renderer *drw;
static struct wlr_compositor *compositor;
static struct wlr_xwayland *xwayland;

static struct wlr_xdg_shell *xdg_shell;
static struct wl_list clients; /* tiling order */


@@ 257,8 264,6 @@ static struct wlr_box sgeom;
static struct wl_list mons;
static Monitor *selmon;

static Atom netatom[NetLast];

/* global event handlers */
static struct wl_listener cursor_axis = {.notify = axisnotify};
static struct wl_listener cursor_button = {.notify = buttonpress};


@@ 269,11 274,23 @@ static struct wl_listener new_input = {.notify = inputdevice};
static struct wl_listener new_output = {.notify = createmon};
static struct wl_listener new_xdeco = {.notify = createxdeco};
static struct wl_listener new_xdg_surface = {.notify = createnotify};
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
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};

#ifdef XWAYLAND
static void activatex11(struct wl_listener *listener, void *data);
static void createnotifyx11(struct wl_listener *listener, void *data);
static Atom getatom(xcb_connection_t *xc, const char *name);
static void renderindependents(struct wlr_output *output, struct timespec *now);
static void updatewindowtype(Client *c);
static void xwaylandready(struct wl_listener *listener, void *data);
static Client *xytoindependent(double x, double y);
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
static struct wlr_xwayland *xwayland;
static Atom netatom[NetLast];
#endif

/* configuration, allows nested code to access above variables */
#include "config.h"


@@ 283,16 300,6 @@ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };

/* function implementations */
void
activatex11(struct wl_listener *listener, void *data)
{
       Client *c = wl_container_of(listener, c, activate);

       /* Only "managed" windows can be activated */
       if (c->type == X11Managed)
               wlr_xwayland_surface_activate(c->surface.xwayland, 1);
}

void
applybounds(Client *c, struct wlr_box *bbox)
{
	/* set minimum possible */


@@ 319,10 326,17 @@ applyrules(Client *c)

	/* rule matching */
	c->isfloating = 0;
	appid = c->type != XDGShell ? c->surface.xwayland->class :
		c->surface.xdg->toplevel->app_id;
	title = c->type != XDGShell ? c->surface.xwayland->title :
		c->surface.xdg->toplevel->title;
#ifdef XWAYLAND
	updatewindowtype(c);
	if (c->type != XDGShell) {
		appid = c->surface.xwayland->class;
		title = c->surface.xwayland->title;
	} else
#endif
	{
		appid = c->surface.xdg->toplevel->app_id;
		title = c->surface.xdg->toplevel->title;
	}
	if (!appid)
		appid = broken;
	if (!title)


@@ 339,7 353,6 @@ applyrules(Client *c)
					mon = m;
		}
	}
	updatewindowtype(c);
	setmon(c, mon, newtags);
}



@@ 553,7 566,6 @@ createnotify(struct wl_listener *listener, void *data)
	/* Allocate a Client for this surface */
	c = xdg_surface->data = calloc(1, sizeof(*c));
	c->surface.xdg = xdg_surface;
	c->type = XDGShell;
	c->bw = borderpx;

	/* Tell the client not to try anything fancy */


@@ 572,29 584,6 @@ createnotify(struct wl_listener *listener, void *data)
}

void
createnotifyx11(struct wl_listener *listener, void *data)
{
	struct wlr_xwayland_surface *xwayland_surface = data;
	Client *c;

	/* Allocate a Client for this surface */
	c = xwayland_surface->data = calloc(1, sizeof(*c));
	c->surface.xwayland = xwayland_surface;
	c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
	c->bw = borderpx;

	/* Listen to the various events it can emit */
	c->map.notify = maprequest;
	wl_signal_add(&xwayland_surface->events.map, &c->map);
	c->unmap.notify = unmapnotify;
	wl_signal_add(&xwayland_surface->events.unmap, &c->unmap);
	c->activate.notify = activatex11;
	wl_signal_add(&xwayland_surface->events.request_activate, &c->activate);
	c->destroy.notify = destroynotify;
	wl_signal_add(&xwayland_surface->events.destroy, &c->destroy);
}

void
createpointer(struct wlr_input_device *device)
{
	/* We don't do anything special with pointers. All of our pointer handling


@@ 638,10 627,12 @@ 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);
	if (c->type == XDGShell)
		wl_list_remove(&c->commit.link);
#ifdef XWAYLAND
	if (c->type == X11Managed)
		wl_list_remove(&c->activate.link);
	else if (c->type == XDGShell)
#endif
		wl_list_remove(&c->commit.link);
	free(c);
}



@@ 689,9 680,11 @@ focusclient(Client *old, Client *c, int lift)

	/* Deactivate old client if focus is changing */
	if (c != old && old) {
#ifdef XWAYLAND
		if (old->type != XDGShell)
			wlr_xwayland_surface_activate(old->surface.xwayland, 0);
		else
#endif
			wlr_xdg_toplevel_set_activated(old->surface.xdg, 0);
	}



@@ 712,9 705,11 @@ focusclient(Client *old, Client *c, int lift)
	selmon = c->mon;

	/* Activate the new client */
#ifdef XWAYLAND
	if (c->type != XDGShell)
		wlr_xwayland_surface_activate(c->surface.xwayland, 1);
	else
#endif
		wlr_xdg_toplevel_set_activated(c->surface.xdg, 1);
}



@@ 763,21 758,6 @@ focustop(Monitor *m)
	return NULL;
}

Atom
getatom(xcb_connection_t *xc, const char *name)
{
	Atom atom = 0;
	xcb_intern_atom_cookie_t cookie;
	xcb_intern_atom_reply_t *reply;

	cookie = xcb_intern_atom(xc, 0, strlen(name), name);
	if ((reply = xcb_intern_atom_reply(xc, cookie, NULL)))
		atom = reply->atom;
	free(reply);

	return atom;
}

void
getxdecomode(struct wl_listener *listener, void *data)
{


@@ 896,9 876,11 @@ killclient(const Arg *arg)
	if (!sel)
		return;

#ifdef XWAYLAND
	if (sel->type != XDGShell)
		wlr_xwayland_surface_close(sel->surface.xwayland);
	else
#endif
		wlr_xdg_toplevel_send_close(sel->surface.xdg);
}



@@ 908,23 890,28 @@ maprequest(struct wl_listener *listener, void *data)
	/* Called when the surface is mapped, or ready to display on-screen. */
	Client *c = wl_container_of(listener, c, map);

#ifdef XWAYLAND
	if (c->type == X11Unmanaged) {
		/* Insert this independent into independents lists. */
		wl_list_insert(&independents, &c->link);
		return;
	}
#endif

	/* Insert this client into client lists. */
	wl_list_insert(&clients, &c->link);
	wl_list_insert(&fstack, &c->flink);
	wl_list_insert(&stack, &c->slink);

#ifdef XWAYLAND
	if (c->type != XDGShell) {
		c->geom.x = c->surface.xwayland->x;
		c->geom.y = c->surface.xwayland->y;
		c->geom.width = c->surface.xwayland->width + 2 * c->bw;
		c->geom.height = c->surface.xwayland->height + 2 * c->bw;
	} else {
	} else
#endif
	{
		wlr_xdg_surface_get_geometry(c->surface.xdg, &c->geom);
		c->geom.width += 2 * c->bw;
		c->geom.height += 2 * c->bw;


@@ 984,6 971,7 @@ motionnotify(uint32_t time)
		return;
	}

#ifdef XWAYLAND
	/* Find an independent under the pointer and send the event along. */
	if ((c = xytoindependent(cursor->x, cursor->y))) {
		surface = wlr_surface_surface_at(c->surface.xwayland->surface,


@@ 992,11 980,16 @@ motionnotify(uint32_t time)

	/* Otherwise, find the client under the pointer and send the event along. */
	} else if ((c = xytoclient(cursor->x, cursor->y))) {
#else
	if ((c = xytoclient(cursor->x, cursor->y))) {
#endif
#ifdef XWAYLAND
		if (c->type != XDGShell)
			surface = wlr_surface_surface_at(c->surface.xwayland->surface,
					cursor->x - c->geom.x - c->bw,
					cursor->y - c->geom.y - c->bw, &sx, &sy);
		else
#endif
			surface = wlr_xdg_surface_surface_at(c->surface.xdg,
					cursor->x - c->geom.x - c->bw,
					cursor->y - c->geom.y - c->bw, &sx, &sy);


@@ 1077,7 1070,13 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
	/* Otherwise, let the client know that the mouse cursor has entered one
	 * of its surfaces, and make keyboard focus follow if desired. */
	wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
	if (sloppyfocus && c->type != X11Unmanaged)

#if XWAYLAND
	if (c->type == X11Unmanaged)
		return;
#endif

	if (sloppyfocus)
		focusclient(selclient(), c, 0);
}



@@ 1190,40 1189,16 @@ renderclients(Monitor *m, struct timespec *now)
		rdata.when = now;
		rdata.x = c->geom.x + c->bw;
		rdata.y = c->geom.y + c->bw;
#ifdef XWAYLAND
		if (c->type != XDGShell)
			wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
		else
#endif
			wlr_xdg_surface_for_each_surface(c->surface.xdg, render, &rdata);
	}
}

void
renderindependents(struct wlr_output *output, struct timespec *now)
{
	Client *c;
	struct render_data rdata;
	struct wlr_box geom;

	wl_list_for_each_reverse(c, &independents, link) {
		geom.x = c->surface.xwayland->x;
		geom.y = c->surface.xwayland->y;
		geom.width = c->surface.xwayland->width;
		geom.height = c->surface.xwayland->height;

		/* Only render visible clients which show on this output */
		if (!wlr_output_layout_intersects(output_layout, output, &geom))
			continue;

		rdata.output = output;
		rdata.when = now;
		rdata.x = c->surface.xwayland->x;
		rdata.y = c->surface.xwayland->y;

		wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
	}
}

void
rendermon(struct wl_listener *listener, void *data)
{
	Client *c;


@@ 1254,7 1229,9 @@ rendermon(struct wl_listener *listener, void *data)
		wlr_renderer_clear(drw, rootcolor);

		renderclients(m, &now);
#ifdef XWAYLAND
		renderindependents(m->wlr_output, &now);
#endif

		/* Hardware cursors are rendered by the GPU on a separate plane, and can be
		 * moved around without re-rendering what's beneath them - which is more


@@ 1287,11 1264,13 @@ resize(Client *c, int x, int y, int w, int h, int interact)
	c->geom.height = h;
	applybounds(c, bbox);
	/* wlroots makes this a no-op if size hasn't changed */
#ifdef XWAYLAND
	if (c->type != XDGShell)
		wlr_xwayland_surface_configure(c->surface.xwayland,
				c->geom.x, c->geom.y,
				c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
	else
#endif
		c->resize = wlr_xdg_toplevel_set_size(c->surface.xdg,
				c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
}


@@ 1586,6 1565,7 @@ setup(void)
	wl_signal_add(&seat->events.request_set_primary_selection,
			&request_set_psel);

#ifdef XWAYLAND
	/*
	 * Initialise the XWayland X server.
	 * It will be started when the first X client is started.


@@ 1599,6 1579,7 @@ setup(void)
	} else {
		fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
	}
#endif
}

void


@@ 1710,50 1691,16 @@ unmapnotify(struct wl_listener *listener, void *data)
	/* Called when the surface is unmapped, and should no longer be shown. */
	Client *c = wl_container_of(listener, c, unmap);
	wl_list_remove(&c->link);
#ifdef XWAYLAND
	if (c->type == X11Unmanaged)
		return;
#endif
	setmon(c, NULL, 0);
	wl_list_remove(&c->flink);
	wl_list_remove(&c->slink);
}

void
updatewindowtype(Client *c)
{
	size_t i;

	if (c->type != XDGShell)
		for (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])
				c->isfloating = 1;
}

void
xwaylandready(struct wl_listener *listener, void *data) {
	xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL);
	int err = xcb_connection_has_error(xc);
	if (err) {
		fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err);
		return;
	}

	/* Collect atoms we are interested in.  If getatom returns 0, we will
	 * not detect that window type. */
	netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
	netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
	netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR");
	netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY");

	/* assign the one and only seat */
	wlr_xwayland_set_seat(xwayland, seat);

	xcb_disconnect(xc);
}

void
view(const Arg *arg)
{
	Client *sel = selclient();


@@ 1778,27 1725,6 @@ xytoclient(double x, double y)
	return NULL;
}

Client *
xytoindependent(double x, double y)
{
	/* Find the topmost visible independent at point (x, y).
	 * For independents, the most recently created can be used as the "top".
	 * We rely on the X11 convention of unmapping unmanaged when the "owning"
	 * client loses focus, which ensures that unmanaged are only visible on
	 * the current tag. */
	Client *c;
	struct wlr_box geom;
	wl_list_for_each_reverse(c, &independents, link) {
		geom.x = c->surface.xwayland->x;
		geom.y = c->surface.xwayland->y;
		geom.width = c->surface.xwayland->width;
		geom.height = c->surface.xwayland->height;
		if (wlr_box_contains_point(&geom, x, y))
			return c;
	}
	return NULL;
}

Monitor *
xytomon(double x, double y)
{


@@ 1838,6 1764,140 @@ zoom(const Arg *arg)
	arrange(selmon);
}

#ifdef XWAYLAND
void
activatex11(struct wl_listener *listener, void *data)
{
       Client *c = wl_container_of(listener, c, activate);

       /* Only "managed" windows can be activated */
       if (c->type == X11Managed)
               wlr_xwayland_surface_activate(c->surface.xwayland, 1);
}

void
createnotifyx11(struct wl_listener *listener, void *data)
{
	struct wlr_xwayland_surface *xwayland_surface = data;
	Client *c;

	/* Allocate a Client for this surface */
	c = xwayland_surface->data = calloc(1, sizeof(*c));
	c->surface.xwayland = xwayland_surface;
	c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
	c->bw = borderpx;

	/* Listen to the various events it can emit */
	c->map.notify = maprequest;
	wl_signal_add(&xwayland_surface->events.map, &c->map);
	c->unmap.notify = unmapnotify;
	wl_signal_add(&xwayland_surface->events.unmap, &c->unmap);
	c->activate.notify = activatex11;
	wl_signal_add(&xwayland_surface->events.request_activate, &c->activate);
	c->destroy.notify = destroynotify;
	wl_signal_add(&xwayland_surface->events.destroy, &c->destroy);
}

Atom
getatom(xcb_connection_t *xc, const char *name)
{
	Atom atom = 0;
	xcb_intern_atom_cookie_t cookie;
	xcb_intern_atom_reply_t *reply;

	cookie = xcb_intern_atom(xc, 0, strlen(name), name);
	if ((reply = xcb_intern_atom_reply(xc, cookie, NULL)))
		atom = reply->atom;
	free(reply);

	return atom;
}

void
renderindependents(struct wlr_output *output, struct timespec *now)
{
	Client *c;
	struct render_data rdata;
	struct wlr_box geom;

	wl_list_for_each_reverse(c, &independents, link) {
		geom.x = c->surface.xwayland->x;
		geom.y = c->surface.xwayland->y;
		geom.width = c->surface.xwayland->width;
		geom.height = c->surface.xwayland->height;

		/* Only render visible clients which show on this output */
		if (!wlr_output_layout_intersects(output_layout, output, &geom))
			continue;

		rdata.output = output;
		rdata.when = now;
		rdata.x = c->surface.xwayland->x;
		rdata.y = c->surface.xwayland->y;

		wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
	}
}

void
updatewindowtype(Client *c)
{
	size_t i;

	if (c->type != XDGShell)
		for (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])
				c->isfloating = 1;
}

void
xwaylandready(struct wl_listener *listener, void *data)
{
	xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL);
	int err = xcb_connection_has_error(xc);
	if (err) {
		fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err);
		return;
	}

	/* Collect atoms we are interested in.  If getatom returns 0, we will
	 * not detect that window type. */
	netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
	netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
	netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR");
	netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY");

	/* assign the one and only seat */
	wlr_xwayland_set_seat(xwayland, seat);

	xcb_disconnect(xc);
}

Client *
xytoindependent(double x, double y)
{
	/* Find the topmost visible independent at point (x, y).
	 * For independents, the most recently created can be used as the "top".
	 * We rely on the X11 convention of unmapping unmanaged when the "owning"
	 * client loses focus, which ensures that unmanaged are only visible on
	 * the current tag. */
	Client *c;
	struct wlr_box geom;
	wl_list_for_each_reverse(c, &independents, link) {
		geom.x = c->surface.xwayland->x;
		geom.y = c->surface.xwayland->y;
		geom.width = c->surface.xwayland->width;
		geom.height = c->surface.xwayland->height;
		if (wlr_box_contains_point(&geom, x, y))
			return c;
	}
	return NULL;
}
#endif

int
main(int argc, char *argv[])
{


@@ 1882,7 1942,9 @@ main(int argc, char *argv[])
	run(startup_cmd);

	/* Once wl_display_run returns, we shut down the server. */
#ifdef XWAYLAND
	wlr_xwayland_destroy(xwayland);
#endif
	wl_display_destroy_clients(dpy);
	wl_display_destroy(dpy);


Do not follow this link