[dev] dwm + onscreen keyboard

From: Peter John Hartman <peterjohnhartman_AT_gmail.com>
Date: Mon, 20 Dec 2010 16:36:09 -0500

Hi folks,

Below is a diff of the modifications I made to make xvkbd play more nice
with dwm and to make dwm more friendly, in general, to touchscreens. Basic
mods:

1. Added ISPANEL (really should be ISKBD) definition which gets checked here
and there, notably in focus() (so it don't steal focus) and focusstack() (so
I can flip through my stack and pass over the xvkbd).

2. I added a couple tweaks to config.h to make the bar more friendly.
Notably, I have the title do a focusstack and the - close the bar. (I'm on a
8" touchscreen so I don't want the bar open too often.)

There's probably a better way to do this, but I wasn't clever enough to
figure it out

Any other tips and kind words of advice are welcome.

Here's the diff (off of hg tip):

diff -r 23b71491e149 config.mk
--- a/config.mk Thu Dec 02 10:16:47 2010 +0000
+++ b/config.mk Mon Dec 20 16:31:34 2010 -0500
@@ -11,8 +11,8 @@
 X11LIB = /usr/X11R6/lib
 
 # Xinerama
-XINERAMALIBS = -L${X11LIB} -lXinerama
-XINERAMAFLAGS = -DXINERAMA
+#XINERAMALIBS = -L${X11LIB} -lXinerama
+#XINERAMAFLAGS = -DXINERAMA
 
 # includes and libs
 INCS = -I. -I/usr/include -I${X11INC}
diff -r 23b71491e149 dwm.c
--- a/dwm.c Thu Dec 02 10:16:47 2010 +0000
+++ b/dwm.c Mon Dec 20 16:31:34 2010 -0500
@@ -53,6 +53,7 @@
 #define HEIGHT(X) ((X)->h + 2 * (X)->bw)
 #define TAGMASK ((1 << LENGTH(tags)) - 1)
 #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height)
+#define ISPANEL(x) (ISVISIBLE(x)&&(strcmp("xvkbd - Virtual Keyboard",x->name) == 0))
 
 /* enums */
 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -88,7 +89,7 @@
         int basew, baseh, incw, inch, maxw, maxh, minw, minh;
         int bw, oldbw;
         unsigned int tags;
- Bool isfixed, isfloating, isurgent, oldstate;
+ Bool isfixed, isfloating, isurgent, oldstate;
         Client *next;
         Client *snext;
         Monitor *mon;
@@ -810,7 +811,7 @@
         if(!c || !ISVISIBLE(c))
                 for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
         /* was if(selmon->sel) */
- if(selmon->sel && selmon->sel != c)
+ if(selmon->sel && selmon->sel != c && !ISPANEL(c))
                 unfocus(selmon->sel, False);
         if(c) {
                 if(c->mon != selmon)
@@ -820,13 +821,16 @@
                 detachstack(c);
                 attachstack(c);
                 grabbuttons(c, True);
- XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
- XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
+ if (!ISPANEL(c)) {
+ XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
+ XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
+ }
         }
         else
                 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
         selmon->sel = c;
- drawbars();
+ if (!ISPANEL(c))
+ drawbars();
 }
 
 void
@@ -857,17 +861,17 @@
         if(!selmon->sel)
                 return;
         if(arg->i > 0) {
- for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
+ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || ISPANEL(c)); c = c->next);
                 if(!c)
- for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
+ for(c = selmon->clients; c && (!ISVISIBLE(c) || ISPANEL(c)); c = c->next);
         }
         else {
                 for(i = selmon->clients; i != selmon->sel; i = i->next)
- if(ISVISIBLE(i))
+ if(ISVISIBLE(i) && !ISPANEL(i))
                                 c = i;
                 if(!c)
                         for(; i; i = i->next)
- if(ISVISIBLE(i))
+ if(ISVISIBLE(i) && !ISPANEL(i))
                                         c = i;
         }
         if(c) {

Here's my config.h:

/* See LICENSE file for copyright and license details. */

/* appearance */
static const char font[] = "-*-terminus-medium-r-*-*-20-*-*-*-*-*-*-*";
static const char normbordercolor[] = "#cccccc";
static const char normbgcolor[] = "#cccccc";
static const char normfgcolor[] = "#000000";
static const char selbordercolor[] = "#0066ff";
static const char selbgcolor[] = "#0066ff";
static const char selfgcolor[] = "#ffffff";
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const Bool showbar = False; /* False means no bar */
static const Bool topbar = True; /* False means bottom bar */

/* tagging */
// xprop | awk -F '"' '/^WM_CLASS/ { printf("%s:%s:",$4,$2) }; /^WM_NAME/ { printf("%s\n",$2) }'
static const char *tags[] = { "1", "2" };

static const Rule rules[] = {
        /* class instance title tags mask isfloating monitor */
        { "Gimp", NULL, NULL, 0, True, -1 },
        { NULL, NULL, "xvkbd - Virtual Keyboard", ~0, True, -1 },
// { "Firefox", NULL, NULL, 0, False, -1 }, // pjh
};

/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const Bool resizehints = False; /* True means respect size hints in tiled resizals */

static const Layout layouts[] = {
        /* symbol arrange function */
        { "[]=", tile }, /* first entry is default */
        { "><>", NULL }, /* no layout function means floating behavior */
        { "[M]", monocle },
};

/* key definitions */
#define MODKEY Mod2Mask // pjh was Mod1Mask
#define MODKEY1 Mod1Mask
#define TAGKEYS(KEY,TAG) \
        { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
        { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
        { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
        { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },

/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }

/* commands */
static const char *dmenucmd[] = { "dwm-dmenu", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; // pjh
static const char *termcmd[] = { "uxterm.sh", NULL };
static const char *vtcmd[] = { "chvt.sh", NULL }; // pjh
static const char *cutcmd[] = { "cut.sh", NULL }; // pjh
static const char *tmuxcmd[] = { "dwm-tmux.sh", NULL }; // pjh

static Key keys[] = {
        /* modifier key function argument */
        { MODKEY, XK_p, spawn, {.v = dmenucmd } },
        { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
        { MODKEY, XK_b, togglebar, {0} },
        { 0, XK_Super_L, togglebar, {0} },
        { 0, XK_Super_R, focusstack, {.i = +1 } },
        { MODKEY, XK_j, focusstack, {.i = +1 } },
        { MODKEY, XK_k, focusstack, {.i = -1 } },
        { MODKEY, XK_h, setmfact, {.f = -0.05} },
        { MODKEY, XK_l, setmfact, {.f = +0.05} },
        { MODKEY, XK_Return, zoom, {0} },
        { MODKEY, XK_Tab, view, {0} },
        { MODKEY|ShiftMask, XK_c, killclient, {0} },
        { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
        { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
        { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
        { MODKEY, XK_space, setlayout, {0} },
        { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
        { MODKEY, XK_0, view, {.ui = ~0 } },
        { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
        { MODKEY, XK_comma, focusmon, {.i = -1 } },
        { MODKEY, XK_period, focusmon, {.i = +1 } },
        { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
        { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
        TAGKEYS( XK_1, 0)
        TAGKEYS( XK_2, 1)
        TAGKEYS( XK_3, 2)
        TAGKEYS( XK_4, 3)
        TAGKEYS( XK_5, 4)
        TAGKEYS( XK_6, 5)
        TAGKEYS( XK_7, 6)
        TAGKEYS( XK_8, 7)
        TAGKEYS( XK_9, 8)
        { MODKEY|ShiftMask, XK_q, quit, {0} },
        { MODKEY, XK_q, killclient, {0} }, // pjh
        { MODKEY1, XK_Up, focusstack, {.i = +1 } },
        { MODKEY1, XK_Down, focusstack, {.i = -1 } },
        { MODKEY, XK_Up, focusstack, {.i = +1 } }, // pjh
        { MODKEY, XK_Down, focusstack, {.i = -1 } }, // pjh
        //{ 0, XK_x, spawn, {.v = dmenucmd } }, // pjh
        { 0, XK_Pause, spawn, {.v = vtcmd } }, // pjh
        { MODKEY, XK_c, spawn, {.v = cutcmd } }, // pjh
        { 0, XK_Shift_R,spawn, {.v = dmenucmd } }, // pjh
        { MODKEY, XK_Left, setmfact, {.f = -0.05} }, // pjh
        { MODKEY, XK_Right, setmfact, {.f = +0.05} }, // pjh
        { MODKEY, XK_a, spawn, {.v = tmuxcmd } }, // pjh

};

/* button definitions */
/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
        /* click event mask button function argument */
        { ClkLtSymbol, 0, Button1, setlayout, {0} },
        { ClkWinTitle, 0, Button1, focusstack, {.i = +1} },
        { ClkStatusText, 0, Button1, togglebar, {0} },
        { ClkClientWin, MODKEY, Button1, movemouse, {0} },
// { ClkClientWin, MODKEY1, Button1, focusstack, {.i = +1 } }, // pjh
        { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
        { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
        { ClkTagBar, 0, Button1, view, {0} },
        { ClkTagBar, 0, Button3, toggleview, {0} },
        { ClkTagBar, MODKEY, Button1, tag, {0} },
        { ClkTagBar, MODKEY, Button3, toggletag, {0} },
};

-- 
sic dicit magister P
PhD Candidate
Collaborative Programme in Ancient and Medieval Philosophy
University of Toronto
http://individual.utoronto.ca/peterjh
Received on Mon Dec 20 2010 - 22:36:09 CET

This archive was generated by hypermail 2.2.0 : Mon Dec 20 2010 - 22:48:01 CET