From 5cb0ac3cf6d32b4e5a2b1533e7b08880326b9ac7 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Sat, 14 Mar 2020 16:07:58 -0400 Subject: [PATCH] added handling of WM_DELETE_WINDOW for orderly shutdown of windows --- anvil.c | 1 - anvil.h | 8 +++++++- client.c | 30 +++++++++++++++++++++++++----- util.c | 20 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/anvil.c b/anvil.c index dcd041a..aac4234 100644 --- a/anvil.c +++ b/anvil.c @@ -139,7 +139,6 @@ static void xdestroynotify(XEvent* e) static void xclientmsg(XEvent* e) { (void)e; - /* TODO: handle client messages per ICCCM */ } static void xpropnotify(XEvent* e) diff --git a/anvil.h b/anvil.h index 54ddd6e..7adc09a 100644 --- a/anvil.h +++ b/anvil.h @@ -38,11 +38,15 @@ typedef struct { void (*eventfns[LASTEvent])(XEvent*); } XConf; +enum { + F_WM_DELETE = (1 << 0) +}; + typedef struct Client { struct Client* next; char* name; Window frame, win; - int x, y, w, h; + int flags, x, y, w, h; } Client; enum { @@ -132,3 +136,5 @@ void check(intptr_t stat, char* msg); void die(char* str); void* ecalloc(size_t n, size_t sz); void xfree(void* p); +Atom atom(char* str); +void sendmsg(Window win, Atom proto, Atom type); diff --git a/client.c b/client.c index 0e622b7..89dc016 100644 --- a/client.c +++ b/client.c @@ -34,11 +34,25 @@ Client* client_add(Window win, XWindowAttributes* attr) client_readprops(c); /* get normal hints ? */ - /* get registered protocols */ /* get transient_for property ? */ /* set client flags appropriately */ - /* get size and position */ - /* Find monitor, add to that monitors cspace */ + + + /* get registered protocols */ + Atom* protos; + int nprotos; + if (XGetWMProtocols(X.disp, c->win, &protos, &nprotos) != 0) + { + for (int i = 0; i < nprotos; i++) + { + if (protos[i] == atom("WM_DELETE_WINDOW")) + { + c->flags |= F_WM_DELETE; + } + } + xfree(protos); + } + /* Reparent the window if applicable */ c->frame = XCreateSimpleWindow(X.disp, X.root, @@ -136,8 +150,14 @@ void client_resize(Client* c, int xdiff, int ydiff) void client_close(Client* c) { - /* TODO: handle wm_delete client message here */ - XKillClient(X.disp, c->win); + if (c->flags & F_WM_DELETE) + { + sendmsg(c->win, atom("WM_PROTOCOLS"), atom("WM_DELETE_WINDOW")); + } + else + { + XKillClient(X.disp, c->win); + } } void client_focus(Client* c) diff --git a/util.c b/util.c index 6396ea4..d442726 100644 --- a/util.c +++ b/util.c @@ -31,3 +31,23 @@ void xfree(void* p) XFree(p); } } + +Atom atom(char* str) +{ + return XInternAtom(X.disp, str, False); +} + +void sendmsg(Window win, Atom proto, Atom type) +{ + XEvent ev; + memset(&ev, 0, sizeof(ev)); + ev.xclient.type = ClientMessage; + ev.xclient.window = win; + ev.xclient.message_type = proto; + ev.xclient.format = 32; + ev.xclient.data.l[0] = type; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(X.disp, win, False, 0, &ev); + XSync(X.disp, False); +} + -- 2.51.0