A final tweak.  When you restart cwm the focus still automatically goes
to the window under the pointer.  In the update below I modified
screen_scan() to first check _NET_ACTIVE_WINDOW.


Index: calmwm.h
===================================================================
RCS file: /cvs/xenocara/app/cwm/calmwm.h,v
diff -u -p -u -p -r1.380 calmwm.h
--- calmwm.h    20 Aug 2025 23:44:06 -0000      1.380
+++ calmwm.h    30 Jun 2026 09:37:13 -0000
@@ -405,6 +405,7 @@ void                         client_config(struct 
client_ctx 
 struct client_ctx      *client_current(struct screen_ctx *);
 void                    client_draw_border(struct client_ctx *);
 struct client_ctx      *client_find(Window);
+void                    client_flush_enter_events(void);
 void                    client_get_sizehints(struct client_ctx *);
 void                    client_hide(struct client_ctx *);
 void                    client_htile(struct client_ctx *);
Index: client.c
===================================================================
RCS file: /cvs/xenocara/app/cwm/client.c,v
diff -u -p -u -p -r1.267 client.c
--- client.c    22 Mar 2023 08:27:36 -0000      1.267
+++ client.c    30 Jun 2026 09:37:13 -0000
@@ -210,6 +210,7 @@ client_remove(struct client_ctx *cc)
 {
        struct screen_ctx       *sc = cc->sc;
        struct winname          *wn;
+       struct client_ctx       *prevcc;
 
        TAILQ_REMOVE(&sc->clientq, cc, entry);
 
@@ -230,6 +231,19 @@ client_remove(struct client_ctx *cc)
        free(cc->res_class);
        free(cc->res_name);
        free(cc);
+
+       if (TAILQ_EMPTY(&sc->clientq))
+               return;
+
+       prevcc = TAILQ_FIRST(&sc->clientq);
+
+       /* Avoid windows with skip client flag or from other groups */
+       if ((prevcc->flags & (CLIENT_SKIP_CYCLE)) &&
+           ! (prevcc->flags & CWM_CYCLE_INGROUP))
+               return;
+
+       client_set_active(prevcc);
+       client_flush_enter_events();
 }
 
 void
@@ -336,7 +350,7 @@ client_toggle_fullscreen(struct client_c
 resize:
        client_resize(cc, 0);
        xu_ewmh_set_net_wm_state(cc);
-       client_ptr_inbound(cc, 1);
+       client_flush_enter_events();
 }
 
 void
@@ -377,7 +391,7 @@ client_toggle_maximize(struct client_ctx
 resize:
        client_resize(cc, 0);
        xu_ewmh_set_net_wm_state(cc);
-       client_ptr_inbound(cc, 1);
+       client_flush_enter_events();
 }
 
 void
@@ -410,7 +424,7 @@ client_toggle_vmaximize(struct client_ct
 resize:
        client_resize(cc, 0);
        xu_ewmh_set_net_wm_state(cc);
-       client_ptr_inbound(cc, 1);
+       client_flush_enter_events();
 }
 
 void
@@ -443,7 +457,7 @@ client_toggle_hmaximize(struct client_ct
 resize:
        client_resize(cc, 0);
        xu_ewmh_set_net_wm_state(cc);
-       client_ptr_inbound(cc, 1);
+       client_flush_enter_events();
 }
 
 void
@@ -516,8 +530,6 @@ client_ptr_inbound(struct client_ctx *cc
                cc->ptr.y = 0;
        else if (cc->ptr.y > cc->geom.h - 1)
                cc->ptr.y = cc->geom.h - 1;
-
-       client_ptr_warp(cc);
 }
 
 void
@@ -949,7 +961,6 @@ client_htile(struct client_ctx *cc)
        if (Conf.htile > 0)
                cc->geom.h = ((area.h - (cc->bwidth * 2)) * Conf.htile) / 100;
        client_resize(cc, 1);
-       client_ptr_warp(cc);
 
        mh = cc->geom.h + (cc->bwidth * 2);
        x = area.x;
@@ -1018,7 +1029,6 @@ client_vtile(struct client_ctx *cc)
                cc->geom.w = ((area.w - (cc->bwidth * 2)) * Conf.vtile) / 100;
        cc->geom.h = area.h - (cc->bwidth * 2);
        client_resize(cc, 1);
-       client_ptr_warp(cc);
 
        mw = cc->geom.w + (cc->bwidth * 2);
        y = area.y;
@@ -1046,4 +1056,14 @@ client_vtile(struct client_ctx *cc)
                i++;
                client_resize(ci, 1);
        }
+}
+
+void
+client_flush_enter_events(void)
+{
+       XEvent ev;
+
+       XSync(X_Dpy, False);
+       while (XCheckMaskEvent(X_Dpy, EnterWindowMask, &ev))
+               LOG_DEBUG3("Discarding stale EnterNotify event");
 }
Index: kbfunc.c
===================================================================
RCS file: /cvs/xenocara/app/cwm/kbfunc.c,v
diff -u -p -u -p -r1.176 kbfunc.c
--- kbfunc.c    20 Aug 2025 23:44:06 -0000      1.176
+++ kbfunc.c    30 Jun 2026 09:37:13 -0000
@@ -409,7 +409,7 @@ void
 kbfunc_client_cycle(void *ctx, struct cargs *cargs)
 {
        struct screen_ctx       *sc = ctx;
-       struct client_ctx       *newcc, *oldcc, *prevcc;
+       struct client_ctx       *newcc, *oldcc;
        int                      again = 1, flags = cargs->flag;
 
        /* For X apps that ignore/steal events. */
@@ -420,7 +420,6 @@ kbfunc_client_cycle(void *ctx, struct ca
        if (TAILQ_EMPTY(&sc->clientq))
                return;
 
-       prevcc = TAILQ_FIRST(&sc->clientq);
        oldcc = client_current(sc);
        if (oldcc == NULL)
                oldcc = (flags & CWM_CYCLE_REVERSE) ?
@@ -450,24 +449,17 @@ kbfunc_client_cycle(void *ctx, struct ca
                }
        }
 
-       /* Reset when cycling mod is released. XXX I hate this hack */
+       /* Reset when cycling mod is released */
        sc->cycling = 1;
-       client_ptr_save(oldcc);
-       client_raise(prevcc);
-       client_raise(newcc);
-       if (!client_inbound(newcc, newcc->ptr.x, newcc->ptr.y)) {
-               newcc->ptr.x = newcc->geom.w / 2;
-               newcc->ptr.y = newcc->geom.h / 2;
-       }
 
-       /* When no client is active, warp pointer to last active. */
-       if (oldcc->flags & (CLIENT_ACTIVE))
-               client_ptr_warp(newcc);
-       else if (oldcc->flags & (CLIENT_SKIP_CYCLE))
-               client_ptr_warp(newcc);
-       else {
+       /* When no client is active, activate last active. */
+       if (oldcc->flags & (CLIENT_ACTIVE) ||
+           oldcc->flags & (CLIENT_SKIP_CYCLE)) {
+               client_raise(newcc);
+               client_set_active(newcc);
+       } else {
                client_raise(oldcc);
-               client_ptr_warp(oldcc);
+               client_set_active(oldcc);
        }
 }
 
@@ -553,7 +545,7 @@ kbfunc_menu_client(void *ctx, struct car
                client_show(cc);
                if ((old_cc = client_current(sc)) != NULL)
                        client_ptr_save(old_cc);
-               client_ptr_warp(cc);
+               client_set_active(cc);
        }
 
        menuq_clear(&menuq);
Index: screen.c
===================================================================
RCS file: /cvs/xenocara/app/cwm/screen.c,v
diff -u -p -u -p -r1.98 screen.c
--- screen.c    27 Jan 2022 18:45:10 -0000      1.98
+++ screen.c    30 Jun 2026 09:37:13 -0000
@@ -87,22 +87,52 @@ screen_init(int which)
 static void
 screen_scan(struct screen_ctx *sc)
 {
-       struct client_ctx        *cc, *active = NULL;
-       Window                  *wins, w0, w1, rwin, cwin;
-       unsigned int             nwins, i, mask;
-       int                      rx, ry, wx, wy;
+       struct client_ctx       *active = NULL, *cc;
+       Atom                     actual_type;
+       Atom                     net_active_win;
+       int                      actual_format, rx, ry, wx, wy;
+       unsigned int             i, mask, nwins;
+       unsigned long            bytes_after, nitems;
+       unsigned char           *prop_return = NULL;
+       Window                  *wins, cwin, ewmh_active_win = None;
+       Window                   rwin, w0, w1;
 
+       /* Try to get the window active before the restart via EWMH */
+       net_active_win = XInternAtom(X_Dpy, "_NET_ACTIVE_WINDOW", False);
+
+       if (XGetWindowProperty(X_Dpy, sc->rootwin, net_active_win, 0, 1,
+           False, XA_WINDOW, &actual_type, &actual_format, &nitems,
+           &bytes_after, &prop_return) == Success && prop_return != NULL) {
+               if (nitems > 0)
+                       ewmh_active_win = *(Window *)prop_return;
+               XFree(prop_return);
+       }
+
+       /* Query the current pointer position as a fallback */
        XQueryPointer(X_Dpy, sc->rootwin, &rwin, &cwin,
            &rx, &ry, &wx, &wy, &mask);
 
+       /* Scan the window tree and initialize clients */
        if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) {
                for (i = 0; i < nwins; i++) {
-                       if ((cc = client_init(wins[i], sc)) != NULL)
-                               if (cc->win == cwin)
-                                       active = cc;
+                       if ((cc = client_init(wins[i], sc)) != NULL) {
+                               /*
+                                * If EWMH told us which window was active,
+                                * match against that.  Otherwise, fall back
+                                * to the window under the pointer.
+                                */
+                               if (ewmh_active_win != None) {
+                                       if (cc->win == ewmh_active_win)
+                                               active = cc;
+                               } else {
+                                       if (cc->win == cwin)
+                                               active = cc;
+                               }
+                       }
                }
                XFree(wins);
        }
+
        if (active)
                client_set_active(active);
 }
Index: xevents.c
===================================================================
RCS file: /cvs/xenocara/app/cwm/xevents.c,v
diff -u -p -u -p -r1.151 xevents.c
--- xevents.c   5 Jan 2026 14:46:59 -0000       1.151
+++ xevents.c   30 Jun 2026 09:37:13 -0000
@@ -93,7 +93,7 @@ xev_handle_maprequest(XEvent *ee)
                cc = client_init(e->window, NULL);
 
        if ((cc != NULL) && (!(cc->flags & CLIENT_IGNORE)))
-               client_ptr_warp(cc);
+               client_set_active(cc);
 }
 
 static void
@@ -330,8 +330,8 @@ xev_handle_keypress(XEvent *ee)
        kb->cargs->xev = CWM_XEV_KEY;
        switch (kb->context) {
        case CWM_CONTEXT_CC:
-               if (((cc = client_find(e->subwindow)) == NULL) &&
-                   ((cc = client_current(sc)) == NULL))
+               if (((cc = client_current(sc)) == NULL) &&
+                   ((cc = client_find(e->subwindow)) == NULL))
                        return;
                (*kb->callback)(cc, kb->cargs);
                break;
@@ -404,7 +404,6 @@ xev_handle_clientmessage(XEvent *ee)
                        if ((old_cc = client_current(NULL)) != NULL)
                                client_ptr_save(old_cc);
                        client_show(cc);
-                       client_ptr_warp(cc);
                }
        } else if (e->message_type == ewmh[_NET_WM_DESKTOP]) {
                if ((cc = client_find(e->window)) != NULL) {


-- 
Walter

Reply via email to