diff options
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | config.def.h | 4 | ||||
| -rw-r--r-- | config.mk | 5 | ||||
| -rw-r--r-- | dwl.c | 351 | 
4 files changed, 233 insertions, 134 deletions
| @@ -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))) diff --git a/config.def.h b/config.def.h index 17b1489..eff8f59 100644 --- a/config.def.h +++ b/config.def.h @@ -10,8 +10,10 @@ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };  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) */ diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..a101f23 --- /dev/null +++ b/config.mk @@ -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 @@ -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); @@ -166,10 +179,10 @@ static void buttonpress(struct wl_listener *listener, void *data);  static void chvt(const Arg *arg);  static void cleanupkeyboard(struct wl_listener *listener, void *data);  static void cleanupmon(struct wl_listener *listener, void *data); +static void commitnotify(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 +193,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,9 +231,7 @@ 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 Monitor *xytomon(double x, double y); @@ -233,7 +243,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 */ @@ -256,8 +265,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}; @@ -268,11 +275,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" @@ -282,16 +301,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 */ @@ -318,10 +327,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) @@ -338,7 +354,6 @@ applyrules(Client *c)  					mon = m;  		}  	} -	updatewindowtype(c);  	setmon(c, mon, newtags);  } @@ -552,7 +567,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 */ @@ -571,29 +585,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 @@ -637,10 +628,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);  } @@ -688,9 +681,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);  	} @@ -711,9 +706,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);  } @@ -762,21 +759,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)  { @@ -895,9 +877,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);  } @@ -907,23 +891,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; @@ -983,13 +972,25 @@ 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, +				cursor->x - c->surface.xwayland->x - c->bw, +				cursor->y - c->surface.xwayland->y - c->bw, &sx, &sy); +  	/* 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); @@ -1070,6 +1071,12 @@ 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 XWAYLAND +	if (c->type == X11Unmanaged) +		return; +#endif +  	if (sloppyfocus)  		focusclient(selclient(), c, 0);  } @@ -1183,40 +1190,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; @@ -1247,7 +1230,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 @@ -1280,11 +1265,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);  } @@ -1579,6 +1566,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. @@ -1592,6 +1580,7 @@ setup(void)  	} else {  		fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");  	} +#endif  }  void @@ -1703,50 +1692,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(); @@ -1810,6 +1765,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[])  { @@ -1854,7 +1943,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); | 
