Hi Anselm,

> It appears to me that both the onscreen keyboard and the client with
> the input focus should have a selfg border -- at least that makes most
> sense in my opinion.

But you need to be able to distinguish between dwm's _selected_ (for
tagging, closing etc.) client and X's _focused_ client. Killing your
terminal window on accident could be awful.

> Introducing another couple just for that sounds quite over-engineered
> to me.

Agreed.

What I would propose is the attached series of patches for hg import:
The first renames focus() to selclient() and focusstack() to selstack().
The second adds a new focus() function calling XSetInputFocus() and
saving the client in a global foc (analogue to sel) variable; it then
implements isfocusable based on the Gottox port + selfgcolor border
for focused, but unselected windows.

By the way, your last commits have "a...@null" as the author?

Regards,
Peter
>From 21a07081c462ba83851d4bc120fd02be3692fe7a Mon Sep 17 00:00:00 2001
From: Peter Hartlich <[email protected]>
Date: Mon, 9 Feb 2009 01:13:29 +0059
Subject: [PATCH 1/2] rename focus to selclient, focusstack to selstack

---
 config.def.h |    4 +-
 dwm.c        |  114 +++++++++++++++++++++++++++++-----------------------------
 2 files changed, 59 insertions(+), 59 deletions(-)

diff --git a/config.def.h b/config.def.h
index bb60471..03dc235 100644
--- a/config.def.h
+++ b/config.def.h
@@ -56,8 +56,8 @@ static Key keys[] = {
        { MODKEY,                       XK_p,      spawn,          {.v = 
dmenucmd } },
        { MODKEY|ShiftMask,             XK_Return, spawn,          {.v = 
termcmd } },
        { MODKEY,                       XK_b,      togglebar,      {0} },
-       { MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
-       { MODKEY,                       XK_k,      focusstack,     {.i = -1 } },
+       { MODKEY,                       XK_j,      selstack,       {.i = +1 } },
+       { MODKEY,                       XK_k,      selstack,       {.i = -1 } },
        { MODKEY,                       XK_h,      setmfact,       {.f = -0.05} 
},
        { MODKEY,                       XK_l,      setmfact,       {.f = +0.05} 
},
        { MODKEY,                       XK_Return, zoom,           {0} },
diff --git a/dwm.c b/dwm.c
index db9e9c0..489fe0e 100644
--- a/dwm.c
+++ b/dwm.c
@@ -149,9 +149,7 @@ static void drawsquare(Bool filled, Bool empty, Bool 
invert, unsigned long col[C
 static void drawtext(const char *text, unsigned long col[ColLast], Bool 
invert);
 static void enternotify(XEvent *e);
 static void expose(XEvent *e);
-static void focus(Client *c);
 static void focusin(XEvent *e);
-static void focusstack(const Arg *arg);
 static Client *getclient(Window w);
 static unsigned long getcolor(const char *colstr);
 static long getstate(Window w);
@@ -175,6 +173,8 @@ static void resizemouse(const Arg *arg);
 static void restack(void);
 static void run(void);
 static void scan(void);
+static void selclient(Client *c);
+static void selstack(const Arg *arg);
 static void setclientstate(Client *c, long state);
 static void setlayout(const Arg *arg);
 static void setmfact(const Arg *arg);
@@ -288,7 +288,7 @@ arrange(void) {
 
        for(nt = 0, c = nexttiled(clients); c; c = nexttiled(c->next), nt++);
        showhide(stack, nt);
-       focus(NULL);
+       selclient(NULL);
        if(lt[sellt]->arrange)
                lt[sellt]->arrange();
        restack();
@@ -329,7 +329,7 @@ buttonpress(XEvent *e) {
                        click = ClkWinTitle;
        }
        else if((c = getclient(ev->window))) {
-               focus(c);
+               selclient(c);
                click = ClkClientWin;
        }
 
@@ -603,9 +603,9 @@ enternotify(XEvent *e) {
        if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && 
ev->window != root)
                return;
        if((c = getclient(ev->window)))
-               focus(c);
+               selclient(c);
        else
-               focus(NULL);
+               selclient(NULL);
 }
 
 void
@@ -617,29 +617,6 @@ expose(XEvent *e) {
 }
 
 void
-focus(Client *c) {
-       if(!c || !ISVISIBLE(c))
-               for(c = stack; c && !ISVISIBLE(c); c = c->snext);
-       if(sel && sel != c) {
-               grabbuttons(sel, False);
-               XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
-       }
-       if(c) {
-               if(c->isurgent)
-                       clearurgent(c);
-               detachstack(c);
-               attachstack(c);
-               grabbuttons(c, True);
-               XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
-               XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
-       }
-       else
-               XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
-       sel = c;
-       drawbar();
-}
-
-void
 focusin(XEvent *e) { /* there are some broken focus acquiring clients */
        XFocusChangeEvent *ev = &e->xfocus;
 
@@ -647,32 +624,6 @@ focusin(XEvent *e) { /* there are some broken focus 
acquiring clients */
                XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
 }
 
-void
-focusstack(const Arg *arg) {
-       Client *c = NULL, *i;
-
-       if(!sel)
-               return;
-       if (arg->i > 0) {
-               for(c = sel->next; c && !ISVISIBLE(c); c = c->next);
-               if(!c)
-                       for(c = clients; c && !ISVISIBLE(c); c = c->next);
-       }
-       else {
-               for(i = clients; i != sel; i = i->next)
-                       if(ISVISIBLE(i))
-                               c = i;
-               if(!c)
-                       for(; i; i = i->next)
-                               if(ISVISIBLE(i))
-                                       c = i;
-       }
-       if(c) {
-               focus(c);
-               restack();
-       }
-}
-
 Client *
 getclient(Window w) {
        Client *c;
@@ -1236,6 +1187,55 @@ scan(void) {
 }
 
 void
+selclient(Client *c) {
+       if(!c || !ISVISIBLE(c))
+               for(c = stack; c && !ISVISIBLE(c); c = c->snext);
+       if(sel && sel != c) {
+               grabbuttons(sel, False);
+               XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
+       }
+       if(c) {
+               if(c->isurgent)
+                       clearurgent(c);
+               detachstack(c);
+               attachstack(c);
+               grabbuttons(c, True);
+               XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
+               XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
+       }
+       else
+               XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
+       sel = c;
+       drawbar();
+}
+
+void
+selstack(const Arg *arg) {
+       Client *c = NULL, *i;
+
+       if(!sel)
+               return;
+       if (arg->i > 0) {
+               for(c = sel->next; c && !ISVISIBLE(c); c = c->next);
+               if(!c)
+                       for(c = clients; c && !ISVISIBLE(c); c = c->next);
+       }
+       else {
+               for(i = clients; i != sel; i = i->next)
+                       if(ISVISIBLE(i))
+                               c = i;
+               if(!c)
+                       for(; i; i = i->next)
+                               if(ISVISIBLE(i))
+                                       c = i;
+       }
+       if(c) {
+               selclient(c);
+               restack();
+       }
+}
+
+void
 setclientstate(Client *c, long state) {
        long data[] = {state, None};
 
@@ -1491,7 +1491,7 @@ unmanage(Client *c) {
        detach(c);
        detachstack(c);
        if(sel == c)
-               focus(NULL);
+               selclient(NULL);
        XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
        setclientstate(c, WithdrawnState);
        free(c);
@@ -1701,7 +1701,7 @@ zoom(const Arg *arg) {
                        return;
        detach(c);
        attach(c);
-       focus(c);
+       selclient(c);
        arrange();
 }
 
-- 
1.6.1.2

>From 4b76309f2ecbc95ab032d0b13dad8a898d9a9721 Mon Sep 17 00:00:00 2001
From: Peter Hartlich <[email protected]>
Date: Mon, 9 Feb 2009 01:22:08 +0059
Subject: [PATCH 2/2] implement isfocusable

---
 dwm.c |   23 ++++++++++++++++++++---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/dwm.c b/dwm.c
index 489fe0e..0557143 100644
--- a/dwm.c
+++ b/dwm.c
@@ -86,7 +86,7 @@ struct Client {
        int basew, baseh, incw, inch, maxw, maxh, minw, minh;
        int bw, oldbw;
        unsigned int tags;
-       Bool isfixed, isfloating, isurgent;
+       Bool isfixed, isfloating, isurgent, isfocusable;
        Client *next;
        Client *snext;
        Window win;
@@ -149,6 +149,7 @@ static void drawsquare(Bool filled, Bool empty, Bool 
invert, unsigned long col[C
 static void drawtext(const char *text, unsigned long col[ColLast], Bool 
invert);
 static void enternotify(XEvent *e);
 static void expose(XEvent *e);
+static void focus(Client *c);
 static void focusin(XEvent *e);
 static Client *getclient(Window w);
 static unsigned long getcolor(const char *colstr);
@@ -232,6 +233,7 @@ static Bool otherwm;
 static Bool running = True;
 static Client *clients = NULL;
 static Client *sel = NULL;
+static Client *foc = NULL;
 static Client *stack = NULL;
 static Cursor cursor[CurLast];
 static Display *dpy;
@@ -617,11 +619,17 @@ expose(XEvent *e) {
 }
 
 void
+focus(Client *c) {
+       XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
+       foc = c;
+}
+
+void
 focusin(XEvent *e) { /* there are some broken focus acquiring clients */
        XFocusChangeEvent *ev = &e->xfocus;
 
        if(sel && ev->window != sel->win)
-               XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
+               focus(sel);
 }
 
 Client *
@@ -824,6 +832,7 @@ manage(Window w, XWindowAttributes *wa) {
        c->w = wa->width;
        c->h = wa->height;
        c->oldbw = wa->border_width;
+       c->isfocusable = True;
        if(c->w == sw && c->h == sh) {
                c->x = sx;
                c->y = sy;
@@ -845,6 +854,7 @@ manage(Window w, XWindowAttributes *wa) {
        XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
        configure(c); /* propagates border_width, if size doesn't change */
        updatesizehints(c);
+       updatewmhints(c);
        XSelectInput(dpy, w, 
EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
        grabbuttons(c, False);
        updatetitle(c);
@@ -1201,7 +1211,13 @@ selclient(Client *c) {
                attachstack(c);
                grabbuttons(c, True);
                XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
-               XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
+               if(c->isfocusable) {
+                       if(foc && foc != c)
+                               XSetWindowBorder(dpy, foc->win, 
dc.norm[ColBorder]);
+                       focus(c);
+               }
+               else if(foc)
+                       XSetWindowBorder(dpy, foc->win, dc.sel[ColFG]);
        }
        else
                XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
@@ -1642,6 +1658,7 @@ updatewmhints(Client *c) {
                }
                else
                        c->isurgent = (wmh->flags & XUrgencyHint) ? True : 
False;
+               c->isfocusable = !(wmh->flags & InputHint) || wmh->input;
 
                XFree(wmh);
        }
-- 
1.6.1.2

Reply via email to