aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Courtis <alex@courtis.org>2020-08-11 11:23:58 +1000
committerAlexander Courtis <alex@courtis.org>2020-08-11 11:23:58 +1000
commite7318f76239133cbbaf6e0b26416ed60e484b485 (patch)
tree05de3d1e89ac8b5097b4a37d4906188de4fff78d
parentf593820edee096dc62e296af9d7514cdf4268ce4 (diff)
parente3e9504fcd0b1b38037aa9dffd04ac0de1ce5e82 (diff)
Merge branch 'master' into 24-xwayland-cursor
-rw-r--r--Makefile7
-rw-r--r--config.mk5
-rw-r--r--dwl.c312
3 files changed, 191 insertions, 133 deletions
diff --git a/Makefile b/Makefile
index 7c90456..56ab751 100644
--- a/Makefile
+++ b/Makefile
@@ -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.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
diff --git a/dwl.c b/dwl.c
index fa59ede..767b9af 100644
--- a/dwl.c
+++ b/dwl.c
@@ -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,9 +230,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 +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 */
@@ -258,8 +266,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};
@@ -270,11 +276,22 @@ 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 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"
@@ -284,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 */
@@ -320,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)
@@ -340,7 +354,6 @@ applyrules(Client *c)
mon = m;
}
}
- updatewindowtype(c);
setmon(c, mon, newtags);
}
@@ -554,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 */
@@ -573,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
@@ -639,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);
}
@@ -690,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);
}
@@ -713,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);
}
@@ -764,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)
{
@@ -897,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);
}
@@ -909,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;
@@ -987,11 +974,13 @@ motionnotify(uint32_t time)
/* Otherwise, find the client under the pointer and send the event along. */
if ((c = xytoclient(cursor->x, cursor->y))) {
+#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);
@@ -1185,40 +1174,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;
@@ -1249,7 +1214,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
@@ -1282,11 +1249,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);
}
@@ -1581,6 +1550,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.
@@ -1608,6 +1578,7 @@ setup(void)
} else {
fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
}
+#endif
}
void
@@ -1719,50 +1690,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();
@@ -1826,6 +1763,119 @@ 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);
+}
+#endif
+
int
main(int argc, char *argv[])
{
@@ -1870,7 +1920,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);