]> git.mdlowis.com Git - proto/anvil.git/commitdiff
added handling of WM_DELETE_WINDOW for orderly shutdown of windows
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 14 Mar 2020 20:07:58 +0000 (16:07 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 14 Mar 2020 20:07:58 +0000 (16:07 -0400)
anvil.c
anvil.h
client.c
util.c

diff --git a/anvil.c b/anvil.c
index dcd041a6c6dd4ebe4b106dfdfb6fe0dfbb8d62fc..aac42347538a86780b6bc92843b5202666343e0f 100644 (file)
--- 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 54ddd6ed84ed504ba06e47c2088d7385d4ee2219..7adc09a838d0c053ae53480206f3ee424cbbaa54 100644 (file)
--- 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);
index 0e622b7fa9e90c22ac148c82295c490b8d128c7b..89dc016dbbe309620413846b4e2d83665706ba76 100644 (file)
--- 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 6396ea451348cddb38d352ea0d9d78f2d5c8c46a..d442726a681d7a88a277de4b12cb61abd552134f 100644 (file)
--- 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);
+}
+