From 744f20790cae868ee435dcceefdfa4c40fd21925 Mon Sep 17 00:00:00 2001 From: Alvar Penning Date: Mon, 27 Jul 2020 22:03:13 +0200 Subject: [PATCH 1/9] getatom: fix potential uninitialized atom variable The getatom function returns the atom variable, which is only initialized in case of a success. This results in a maybe-uninitialized warning/error. After this commit, now a zero value is returned in case of error. --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index f7f88f1..30a45f1 100644 --- a/dwl.c +++ b/dwl.c @@ -762,7 +762,7 @@ focusstack(const Arg *arg) Atom getatom(xcb_connection_t *xc, const char *name) { - Atom atom; + Atom atom = 0; xcb_generic_error_t *error; xcb_intern_atom_cookie_t cookie; xcb_intern_atom_reply_t *reply; From d89cf6b7206faa480b5e780fb59062794a876941 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Aug 2020 11:20:12 -0500 Subject: [PATCH 2/9] add some more hands-off protocols --- README.md | 1 - dwl.c | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8206a37..3251ccf 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,6 @@ dwl is a work in progress, and it has not yet reached its feature goals in a num - Urgent/attention/focus-request ([not yet supported](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/9) by xdg-shell protocol) - Statusbar support (built-in or external) - layer-shell -- export-dmabuf - Damage tracking - Fullscreen/fixed windows (or whatever the Wayland analogues are) diff --git a/dwl.c b/dwl.c index 433c4b1..4261fd6 100644 --- a/dwl.c +++ b/dwl.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1485,9 +1487,11 @@ setup(void) * the clients cannot set the selection directly without compositor approval, * see the setsel() function. */ compositor = wlr_compositor_create(dpy, drw); + wlr_export_dmabuf_manager_v1_create(dpy); wlr_screencopy_manager_v1_create(dpy); wlr_data_device_manager_create(dpy); wlr_primary_selection_v1_device_manager_create(dpy); + wlr_viewporter_create(dpy); /* Creates an output layout, which a wlroots utility for working with an * arrangement of screens in a physical layout. */ From 27bbf9c14f81c5b09bfe2a0378c8e1f96ab89160 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Aug 2020 12:22:02 -0500 Subject: [PATCH 3/9] condense getatom and add note about error return --- dwl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index c700776..804adae 100644 --- a/dwl.c +++ b/dwl.c @@ -765,13 +765,11 @@ Atom getatom(xcb_connection_t *xc, const char *name) { Atom atom = 0; - xcb_generic_error_t *error; xcb_intern_atom_cookie_t cookie; xcb_intern_atom_reply_t *reply; cookie = xcb_intern_atom(xc, 0, strlen(name), name); - reply = xcb_intern_atom_reply(xc, cookie, &error); - if (reply != NULL && error == NULL) + if ((reply = xcb_intern_atom_reply(xc, cookie, NULL))) atom = reply->atom; free(reply); @@ -1722,7 +1720,8 @@ xwaylandready(struct wl_listener *listener, void *data) { return; } - /* collect atoms we are interested in */ + /* 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"); From 5a2d87fa6cd33bd170b6e98534fe966ffa17576b Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Aug 2020 12:44:47 -0500 Subject: [PATCH 4/9] add monocle layout --- config.def.h | 2 ++ dwl.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/config.def.h b/config.def.h index 681cfba..8c10165 100644 --- a/config.def.h +++ b/config.def.h @@ -19,6 +19,7 @@ static const Layout layouts[] = { /* symbol arrange function */ { "[]=", tile }, { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, }; /* monitors */ @@ -65,6 +66,7 @@ static const Key keys[] = { { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, killclient, {0} }, { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, { MODKEY, XKB_KEY_space, setlayout, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, diff --git a/dwl.c b/dwl.c index 804adae..fbdfbe0 100644 --- a/dwl.c +++ b/dwl.c @@ -189,6 +189,7 @@ static void keypress(struct wl_listener *listener, void *data); static void keypressmod(struct wl_listener *listener, void *data); static void killclient(const Arg *arg); static void maprequest(struct wl_listener *listener, void *data); +static void monocle(Monitor *m); static void motionabsolute(struct wl_listener *listener, void *data); static void motionnotify(uint32_t time); static void motionrelative(struct wl_listener *listener, void *data); @@ -932,6 +933,18 @@ maprequest(struct wl_listener *listener, void *data) applyrules(c); } +void +monocle(Monitor *m) +{ + Client *c; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating) + continue; + resize(c, m->w.x, m->w.y, m->w.width, m->w.height, 0); + } +} + void motionabsolute(struct wl_listener *listener, void *data) { From 541ecea796d2ac99e08a7e1185585cf0d1531799 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Aug 2020 12:54:20 -0500 Subject: [PATCH 5/9] fix killclient binding, add helpful comment --- config.def.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 8c10165..309c2fa 100644 --- a/config.def.h +++ b/config.def.h @@ -53,6 +53,7 @@ static const int repeat_delay = 600; static const char *termcmd[] = { "alacritty", NULL }; static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ /* modifier key function argument */ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, @@ -63,7 +64,7 @@ static const Key keys[] = { { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05} }, { MODKEY, XKB_KEY_Return, zoom, {0} }, { MODKEY, XKB_KEY_Tab, view, {0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, killclient, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, From e3e9504fcd0b1b38037aa9dffd04ac0de1ce5e82 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 10 Aug 2020 12:50:56 -0500 Subject: [PATCH 6/9] make XWayland support optional --- Makefile | 7 +- config.mk | 5 + dwl.c | 312 +++++++++++++++++++++++++++++++----------------------- 3 files changed, 191 insertions(+), 133 deletions(-) create mode 100644 config.mk diff --git a/Makefile b/Makefile index 7c90456..56ab751 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ +include config.mk + +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) -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 - 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 fbdfbe0..d5559e6 100644 --- a/dwl.c +++ b/dwl.c @@ -33,9 +33,11 @@ #include #include #include -#include -#include #include +#ifdef XWAYLAND +#include +#include +#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 */ @@ -256,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}; @@ -268,11 +274,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" @@ -281,16 +298,6 @@ static struct wl_listener xwayland_ready = {.notify = xwaylandready}; 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) { @@ -318,10 +325,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 +352,6 @@ applyrules(Client *c) mon = m; } } - updatewindowtype(c); setmon(c, mon, newtags); } @@ -552,7 +565,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 */ @@ -570,29 +582,6 @@ createnotify(struct wl_listener *listener, void *data) wl_signal_add(&xdg_surface->events.destroy, &c->destroy); } -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) { @@ -637,10 +626,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 +679,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 +704,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 +757,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 +875,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 +889,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; @@ -985,11 +972,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); @@ -1183,39 +1172,15 @@ 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) { @@ -1247,7 +1212,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 +1247,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 +1548,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 +1562,7 @@ setup(void) } else { fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); } +#endif } void @@ -1703,49 +1674,15 @@ 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) { @@ -1810,6 +1747,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[]) { @@ -1854,7 +1904,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); From 82b2a948b69691bde5f2d08b132d26c128d5537c Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Fri, 14 Aug 2020 10:06:04 +0200 Subject: [PATCH 7/9] Fix Firefox class --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 309c2fa..f605d7b 100644 --- a/config.def.h +++ b/config.def.h @@ -11,7 +11,7 @@ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const Rule rules[] = { /* app_id title tags mask isfloating monitor */ { "Gimp", NULL, 0, 1, -1 }, - { "Firefox", NULL, 1 << 8, 0, -1 }, + { "firefox", NULL, 1 << 8, 0, -1 }, }; /* layout(s) */ From f7fae6447b9f92a960cffa36e35e39b00a716cb7 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Fri, 14 Aug 2020 10:20:18 -0500 Subject: [PATCH 8/9] make rule examples a comment --- config.def.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.def.h b/config.def.h index f605d7b..5f26c3e 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 }, + */ }; /* layout(s) */ From c0608aa017120d674e77468073703a0ae266d337 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sat, 15 Aug 2020 16:47:22 +0200 Subject: [PATCH 9/9] Declare commitnotify --- dwl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwl.c b/dwl.c index d5559e6..3260d87 100644 --- a/dwl.c +++ b/dwl.c @@ -179,6 +179,7 @@ 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);