JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
replace large enternotify hammer with pliers instead.
[spectrwm.git] / scrotwm.c
index aab81c0..0aa4860 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -933,8 +933,9 @@ dumpwins(struct swm_region *r, union arg *args)
                if (!XGetWindowAttributes(display, win->id, &wa))
                        fprintf(stderr, "window: %lu failed "
                            "XGetWindowAttributes\n", win->id);
-               fprintf(stderr, "window: %lu map_state: %d state: %d\n",
-                   win->id, wa.map_state, state);
+               fprintf(stderr, "window: %lu map_state: %d state: %d "
+                   "transient: %lu\n",
+                   win->id, wa.map_state, state, win->transient);
        }
 
        fprintf(stderr, "===== unmanaged window list =====\n");
@@ -943,8 +944,9 @@ dumpwins(struct swm_region *r, union arg *args)
                if (!XGetWindowAttributes(display, win->id, &wa))
                        fprintf(stderr, "window: %lu failed "
                            "XGetWindowAttributes\n", win->id);
-               fprintf(stderr, "window: %lu map_state: %d state: %d\n",
-                   win->id, wa.map_state, state);
+               fprintf(stderr, "window: %lu map_state: %d state: %d "
+                   "transient: %lu\n",
+                   win->id, wa.map_state, state, win->transient);
        }
 
        fprintf(stderr, "=================================\n");
@@ -1379,6 +1381,18 @@ bar_setup(struct swm_region *r)
 }
 
 void
+drain_enter_notify(void)
+{
+       int                     i = 0;
+       XEvent                  cne;
+
+       while (XCheckMaskEvent(display, EnterWindowMask, &cne))
+               i++;
+
+       DNPRINTF(SWM_D_MISC, "drain_enter_notify: drained %d\n", i);
+}
+
+void
 set_win_state(struct ws_win *win, long state)
 {
        long                    data[] = {state, None};
@@ -1957,12 +1971,16 @@ switchws(struct swm_region *r, union arg *args)
        stack();
        a.id = SWM_ARG_ID_FOCUSCUR;
        focus(new_ws->r, &a);
+
        bar_update();
 
        /* unmap old windows */
        if (unmap_old)
                TAILQ_FOREACH(win, &old_ws->winlist, entry)
                        unmap_window(win);
+
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
 }
 
 void
@@ -2065,6 +2083,29 @@ cyclescr(struct swm_region *r, union arg *args)
 }
 
 void
+sort_windows(struct ws_win_list *wl)
+{
+       struct ws_win           *win, *parent, *nxt;
+
+       if (wl == NULL)
+               return;
+
+       for (win = TAILQ_FIRST(wl); win != TAILQ_END(wl); win = nxt) {
+               nxt = TAILQ_NEXT(win, entry);
+               if (win->transient) {
+                       parent = find_window(win->transient);
+                       if (parent == NULL) {
+                               fprintf(stderr, "not possible bug\n");
+                               continue;
+                       }
+                       TAILQ_REMOVE(wl, win, entry);
+                       TAILQ_INSERT_AFTER(wl, parent, win, entry);
+               }
+       }
+
+}
+
+void
 swapwin(struct swm_region *r, union arg *args)
 {
        struct ws_win           *target, *source;
@@ -2085,8 +2126,12 @@ swapwin(struct swm_region *r, union arg *args)
 
        switch (args->id) {
        case SWM_ARG_ID_SWAPPREV:
+               if (source->transient)
+                       source = find_window(source->transient);
                target = TAILQ_PREV(source, ws_win_list, entry);
-               TAILQ_REMOVE(wl, cur_focus, entry);
+               if (target && target->transient)
+                       target = find_window(target->transient);
+               TAILQ_REMOVE(wl, source, entry);
                if (target == NULL)
                        TAILQ_INSERT_TAIL(wl, source, entry);
                else
@@ -2094,6 +2139,9 @@ swapwin(struct swm_region *r, union arg *args)
                break;
        case SWM_ARG_ID_SWAPNEXT:
                target = TAILQ_NEXT(source, entry);
+               /* move the parent and let the sort handle the move */
+               if (source->transient)
+                       source = find_window(source->transient);
                TAILQ_REMOVE(wl, source, entry);
                if (target == NULL)
                        TAILQ_INSERT_HEAD(wl, source, entry);
@@ -2127,6 +2175,8 @@ swapwin(struct swm_region *r, union arg *args)
                return;
        }
 
+       sort_windows(wl);
+
        stack();
 }
 
@@ -2269,7 +2319,6 @@ focus(struct swm_region *r, union arg *args)
        default:
                return;
        }
-
        if (winfocus == winlostfocus || winfocus == NULL)
                return;
 
@@ -2342,6 +2391,9 @@ stack(void) {
        }
        if (font_adjusted)
                font_adjusted--;
+
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
 }
 
 void
@@ -2842,7 +2894,7 @@ void
 send_to_ws(struct swm_region *r, union arg *args)
 {
        int                     wsid = args->id;
-       struct ws_win           *win = win;
+       struct ws_win           *win = NULL, *parent;
        struct workspace        *ws, *nws;
        Atom                    ws_idx_atom = 0;
        unsigned char           ws_idx_str[SWM_PROPLEN];
@@ -2864,6 +2916,15 @@ send_to_ws(struct swm_region *r, union arg *args)
 
        a.id = SWM_ARG_ID_FOCUSPREV;
        focus(r, &a);
+       if (win->transient) {
+               parent = find_window(win->transient);
+               if (parent) {
+                       unmap_window(parent);
+                       TAILQ_REMOVE(&ws->winlist, parent, entry);
+                       TAILQ_INSERT_TAIL(&nws->winlist, parent, entry);
+                       parent->ws = nws;
+               }
+       }
        unmap_window(win);
        TAILQ_REMOVE(&ws->winlist, win, entry);
        TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
@@ -3215,7 +3276,7 @@ resize(struct ws_win *win, union arg *args)
        XUngrabPointer(display, CurrentTime);
 
        /* drain events */
-       while (XCheckMaskEvent(display, EnterWindowMask, &ev));
+       drain_enter_notify();
 }
 
 void
@@ -3309,7 +3370,7 @@ move(struct ws_win *win, union arg *args)
        XUngrabPointer(display, CurrentTime);
 
        /* drain events */
-       while (XCheckMaskEvent(display, EnterWindowMask, &ev));
+       drain_enter_notify();
 }
 
 /* user/key callable function IDs */
@@ -4735,10 +4796,6 @@ manage_window(Window id)
 
        XSelectInput(display, id, EnterWindowMask | FocusChangeMask |
            PropertyChangeMask | StructureNotifyMask);
-       if (win->iconic)
-               set_win_state(win, IconicState);
-       else
-               set_win_state(win, NormalState);
 
        /* floaters need to be mapped if they are in the current workspace */
        if ((win->floating || win->transient) && (ws->idx == r->ws->idx))
@@ -4982,11 +5039,6 @@ enternotify(XEvent *e)
 
        switch (focus_mode) {
        case SWM_FOCUS_DEFAULT:
-               if (QLength(display)) {
-                       DNPRINTF(SWM_D_EVENT, "ignore enternotify %d\n",
-                           QLength(display));
-                       return;
-               }
                break;
        case SWM_FOCUS_FOLLOW:
                break;
@@ -5236,6 +5288,21 @@ unmapnotify(XEvent *e)
        if (getstate(e->xunmap.window) == NormalState) {
                unmanage_window(win);
                stack();
+
+               /* giant hack for apps that don't destroy transient windows */
+               /* eat a bunch of events to prevent remanaging the window */
+               XEvent                  cne;
+               while (XCheckWindowEvent(display, e->xunmap.window,
+                   EnterWindowMask, &cne))
+                       ;
+               while (XCheckWindowEvent(display, e->xunmap.window,
+                   StructureNotifyMask, &cne))
+                       ;
+               while (XCheckWindowEvent(display, e->xunmap.window,
+                   SubstructureNotifyMask, &cne))
+                       ;
+               /* resend unmap because we ated it */
+               XUnmapWindow(display, e->xunmap.window);
        }
 }