]> Pileus Git - wmpus/blobdiff - sys-x11.c
Add wm_handle_state functiton
[wmpus] / sys-x11.c
index 4d88cf09bde123a129357f68b07642c8ab44fe5f..2120ee07931b427dc4be43c6486655f3c0f73197 100644 (file)
--- a/sys-x11.c
+++ b/sys-x11.c
@@ -40,7 +40,6 @@ struct win_sys {
        struct {
                int left, right, top, bottom;
        } strut;
-       state_t  state;
 };
 
 typedef struct {
@@ -49,7 +48,7 @@ typedef struct {
 } event_map_t;
 
 typedef enum {
-       WM_PROTO, WM_FOCUS,
+       WM_PROTO, WM_FOCUS, WM_DELETE,
        NET_STATE, NET_FULL, NET_STRUT,
        NATOMS
 } atom_t;
@@ -400,12 +399,12 @@ static void process_event(int type, XEvent *xe, win_t *root)
        }
        else if (type == UnmapNotify) {
                if ((win = win_find(dpy,xe->xunmap.window,0)) &&
-                    win->sys->state != ST_HIDE) {
+                    win->state != ST_HIDE) {
                        if (!strut_del(root, win))
                                wm_remove(win);
                        else
                                wm_update();
-                       win->sys->state = ST_HIDE;
+                       win->state = ST_HIDE;
                }
        }
        else if (type == DestroyNotify) {
@@ -418,7 +417,7 @@ static void process_event(int type, XEvent *xe, win_t *root)
                printf("configure_req: %d - %x, (0x%lx) %dx%d @ %d,%d\n",
                                type, (int)cre->window, cre->value_mask,
                                cre->height, cre->width, cre->x, cre->y);
-               if ((win = win_find(dpy,xe->xmaprequest.window,1))) {
+               if ((win = win_find(dpy,xe->xconfigurerequest.window,1))) {
                        XSendEvent(dpy, cre->window, False, StructureNotifyMask, &(XEvent){
                                .xconfigure.type              = ConfigureNotify,
                                .xconfigure.display           = win->sys->dpy,
@@ -435,14 +434,15 @@ static void process_event(int type, XEvent *xe, win_t *root)
        }
        else if (type == MapRequest) {
                printf("map_req: %d\n", type);
-               if ((win = win_find(dpy,xe->xmaprequest.window,1))) {
+               if ((win = win_find(dpy,xe->xmaprequest.window,1)) &&
+                    win->state == ST_HIDE) {
                        XSelectInput(win->sys->dpy, win->sys->xid, PropertyChangeMask);
                        if (!strut_add(root, win))
                                wm_insert(win);
                        else
                                wm_update();
                }
-               XMapWindow(dpy, xe->xmaprequest.window);
+               sys_show(win, ST_SHOW);
        }
        else if (type == ClientMessage) {
                XClientMessageEvent *cme = &xe->xclient;
@@ -454,12 +454,11 @@ static void process_event(int type, XEvent *xe, win_t *root)
                    (cme->message_type == atoms[NET_STATE]) &&
                    (cme->data.l[1] == atoms[NET_FULL] ||
                     cme->data.l[2] == atoms[NET_FULL])) {
-                       if (cme->data.l[0] == 1 || /* _NET_WM_STATE_ADD    */
-                          (cme->data.l[0] == 2 && /* _NET_WM_STATE_TOGGLE */
-                           win->sys->state != ST_FULL))
-                               sys_show(win, ST_FULL);
-                       else
-                               sys_show(win, ST_SHOW);
+                       state_t next = (cme->data.l[0] == 1 || /* _NET_WM_STATE_ADD    */
+                                      (cme->data.l[0] == 2 && /* _NET_WM_STATE_TOGGLE */
+                                       win->state != ST_FULL)) ? ST_FULL : ST_SHOW;
+                       wm_handle_state(win, win->state, next);
+                       sys_show(win, next);
                }
        }
        else if (type == PropertyNotify) {
@@ -487,6 +486,12 @@ static int xerror(Display *dpy, XErrorEvent *err)
        return xerrorxlib(dpy, err);
 }
 
+static int xnoerror(Display *dpy, XErrorEvent *err)
+{
+       return 0;
+}
+
+
 /********************
  * System functions *
  ********************/
@@ -536,18 +541,25 @@ void sys_focus(win_t *win)
 
 void sys_show(win_t *win, state_t state)
 {
-       /* Restore from fullscreen */
        switch (state) {
+       case ST_HIDE:
+               printf("sys_show: hide %p\n", win);
+               XUnmapWindow(win->sys->dpy, win->sys->xid);
+               break;
        case ST_SHOW:
-               printf("sys_show: show\n");
-               if (win->sys->state == ST_FULL)
+               printf("sys_show: show %p\n", win);
+               if (win->state == ST_FULL)
                        sys_move(win, win->x, win->y, win->w, win->h);
                XSetWindowBorderWidth(win->sys->dpy, win->sys->xid, border);
                XMapWindow(win->sys->dpy, win->sys->xid);
                XSync(win->sys->dpy, False);
                break;
+       case ST_MAX:
+               printf("sys_show: max %p\n", win);
+               XMapWindow(win->sys->dpy, win->sys->xid);
+               break;
        case ST_FULL:
-               printf("sys_show: full\n");
+               printf("sys_show: full %p\n", win);
                win_t *screen = NULL;
                for (list_t *cur = screens; cur; cur = cur->next) {
                        screen = cur->data;
@@ -565,22 +577,27 @@ void sys_show(win_t *win, state_t state)
                XRaiseWindow(win->sys->dpy, win->sys->xid);
                break;
        case ST_SHADE:
-               printf("sys_show: shade\n");
+               printf("sys_show: shade %p\n", win);
                XMapWindow(win->sys->dpy, win->sys->xid);
                break;
        case ST_ICON:
-               printf("sys_show: icon\n");
-               break;
-       case ST_HIDE:
-               printf("sys_show: hide\n");
-               XUnmapWindow(win->sys->dpy, win->sys->xid);
+               printf("sys_show: icon %p\n", win);
                break;
        case ST_CLOSE:
-               printf("sys_show: close\n");
+               printf("sys_show: close %p\n", win);
+               if (!win_msg(win, WM_DELETE)) {
+                       XGrabServer(win->sys->dpy);
+                       XSetErrorHandler(xnoerror);
+                       XSetCloseDownMode(win->sys->dpy, DestroyAll);
+                       XKillClient(win->sys->dpy, win->sys->xid);
+                       XSync(win->sys->dpy, False);
+                       XSetErrorHandler(xerror);
+                       XUngrabServer(win->sys->dpy);
+               }
                XDestroyWindow(win->sys->dpy, win->sys->xid);
                break;
        }
-       win->sys->state = state;
+       win->state = state;
 }
 
 void sys_watch(win_t *win, event_t ev, mod_t mod)
@@ -654,11 +671,12 @@ win_t *sys_init(void)
                error("Unable to get root window");
 
        /* Setup X11 data */
-       atoms[WM_PROTO]  = XInternAtom(dpy, "WM_PROTOCOLS",  False);
-       atoms[WM_FOCUS]  = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
-       atoms[NET_STATE] = XInternAtom(dpy, "_NET_WM_STATE", False);
-       atoms[NET_FULL]  = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
-       atoms[NET_STRUT] = XInternAtom(dpy, "_NET_WM_STRUT", False);
+       atoms[WM_PROTO]    = XInternAtom(dpy, "WM_PROTOCOLS",             False);
+       atoms[WM_FOCUS]    = XInternAtom(dpy, "WM_TAKE_FOCUS",            False);
+       atoms[WM_DELETE]   = XInternAtom(dpy, "WM_DELETE_WINDOW",         False);
+       atoms[NET_STATE]   = XInternAtom(dpy, "_NET_WM_STATE",            False);
+       atoms[NET_FULL]    = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
+       atoms[NET_STRUT]   = XInternAtom(dpy, "_NET_WM_STRUT",            False);
 
        colors[CLR_FOCUS]   = get_color(dpy, "#a0a0ff");
        colors[CLR_UNFOCUS] = get_color(dpy, "#101066");