]> git.mdlowis.com Git - projs/tide.git/commitdiff
Implemented a fix for window managers being able to kill the editor with no warning
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 22 Dec 2016 18:19:37 +0000 (13:19 -0500)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 22 Dec 2016 18:19:37 +0000 (13:19 -0500)
TODO.md
inc/x11.h
libx/x11.c
tests/xedit.c
xedit.c

diff --git a/TODO.md b/TODO.md
index 7a7c9a71f549bc4aabeca8001d1465cc8db2baab..37149b6227bb55c6d5be47c6846b3ab3db929964 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -14,7 +14,6 @@ Up Next:
 The Rest: 
 
 * Auto-save on focus change or quit
-* Implement EWMH hooks to prevent window manager killing client with modifications
 * Implement X Selection protocol for handling clipboard and primary selections
 * add a distinct state for pointer move versus drag
 * Add a SaveAs tag that takes an argument for the filename to save as
index b5fda7e7bd6ee1976c566cac11f9313f2bcf4465..7563f541e66c536b81deccfe436562b2b45307ed 100644 (file)
--- a/inc/x11.h
+++ b/inc/x11.h
@@ -18,6 +18,7 @@ typedef struct {
     void (*redraw)(int width, int height);
     void (*handle_key)(int mods, uint32_t rune);
     void (*handle_mouse)(MouseAct act, MouseBtn btn, int x, int y);
+    void (*shutdown)(void);
     uint32_t palette[16];
 } XConfig;
 
index 1232adbb25870aa9848ea05830d6c67224d314d8..26d25a10cd1ba21e84110850a237688e983559c5 100644 (file)
@@ -99,6 +99,12 @@ void x11_window(char* name, int width, int height) {
         X.height,
         0, X.depth,
         Config->palette[0]);
+    
+    /* register interest in the delete window message */
+    Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
+    XSetWMProtocols(X.display, X.window, &wmDeleteMessage, 1);
+    
+    /* setup window attributes and events */
     XSetWindowAttributes swa;
     swa.backing_store = WhenMapped;
     swa.bit_gravity = NorthWestGravity;
@@ -113,12 +119,15 @@ void x11_window(char* name, int width, int height) {
         | KeyPressMask
         | ExposureMask
         | FocusChangeMask);
+    
     /* set input methods */
     if ((X.xim = XOpenIM(X.display, 0, 0, 0)))
         X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.window, XNFocusWindow, X.window, NULL);
+    
     /* initialize pixmap and drawing context */
     X.pixmap = XCreatePixmap(X.display, X.window, width, height, X.depth);
     X.xft    = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap);
+    
     /* initialize the graphics context */
     XGCValues gcv;
     gcv.foreground = WhitePixel(X.display, X.screen);
@@ -262,7 +271,7 @@ void x11_loop(void) {
         XPeekEvent(X.display,&e);
         while (XPending(X.display)) {
             XNextEvent(X.display, &e);
-            if (!XFilterEvent(&e, None))
+            if (!XFilterEvent(&e, None)) {
                 switch (e.type) {
                     case FocusIn:       if (X.xic) XSetICFocus(X.xic);   break;
                     case FocusOut:      if (X.xic) XUnsetICFocus(X.xic); break;
@@ -270,6 +279,12 @@ void x11_loop(void) {
                     case ButtonRelease: handle_mouse(&e);                break;
                     case ButtonPress:   handle_mouse(&e);                break;
                     case MotionNotify:  handle_mouse(&e);                break;
+                    case ClientMessage: {
+                            Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
+                            if (e.xclient.data.l[0] == wmDeleteMessage)
+                                Config->shutdown();
+                        }
+                        break;
                     case ConfigureNotify: // Resize the window
                         if (e.xconfigure.width != X.width || e.xconfigure.height != X.height) {
                             X.width  = e.xconfigure.width;
@@ -279,6 +294,7 @@ void x11_loop(void) {
                         }
                         break;
                 }
+            }
         }
         if (Running) {
             /* redraw the window */
index 5c203cf5df880f0fc30e18945981a93f52120acc..c4d76d32c46aafbe07693449c198dde5dfa8f388 100644 (file)
@@ -66,6 +66,10 @@ static void redraw(int width, int height) {
     /* do nothing for unit testing */
 }
 
+void x11_deinit(void) {
+    mockexit(0);
+}
+
 /* Unit Tests
  *****************************************************************************/
 TEST_SUITE(XeditTests) {
diff --git a/xedit.c b/xedit.c
index 3eea77563c8414eaa51ccc22c91df2c537270488..3cda95ac1734f7bcc45f2c5fef5f77a32d5186b0 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -98,6 +98,7 @@ static XConfig Config = {
     .redraw       = redraw,
     .handle_key   = key_handler,
     .handle_mouse = mouse_handler,
+    .shutdown     = quit,
     .palette      = COLOR_PALETTE
 };
 
@@ -485,7 +486,7 @@ static void quit(void) {
     static uint64_t before = 0;
     uint64_t now = getmillis();
     if (!getbuf(EDIT)->modified || (now-before) <= 250) {
-        exit(0);
+        x11_deinit();
     } else {
         view_append(getview(TAGS),
             "File is modified. Repeat action twice in < 250ms to quit.");