From 88ac2898373c1535260eaaf4f74ca2de73ff970a Mon Sep 17 00:00:00 2001 From: Jonathan Hodgson Date: Wed, 3 Feb 2021 22:33:24 +0000 Subject: [PATCH] Adds the ability to have an on screen keyboard I'm going to be using dwm on my new pinephone and need the ability to type. Almost all the code for this has come from minego: https://github.com/minego/dwm-customized --- config.def.h | 14 +-- dwm.c | 249 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 168 insertions(+), 95 deletions(-) diff --git a/config.def.h b/config.def.h index 5366cca..3c730da 100644 --- a/config.def.h +++ b/config.def.h @@ -31,12 +31,14 @@ static const Rule rules[] = { * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* class instance title tags mask isfloating isterminal noswallow nofakefullscreen monitor */ - //{ "Gimp", NULL, NULL, 0, 0, 0, 0, 0, -1 }, - //{ "Firefox", NULL, NULL, 1 << 8, 0, 0, 0, 0, -1 }, - { "xterm-256color", NULL, NULL, 0, 0, 1, 1, 0, -1 }, - { "Thunderbird", NULL, NULL, 1 << 8 , 0, 0, 0, 0, -1 }, - { NULL, NULL, "noswallow", 0, 0, 0, 1, 0, -1 } + /* class instance title tags mask isfloating isterminal noswallow nofakefullscreen iskeyboard monitor */ + //{ "Gimp", NULL, NULL, 0, 0, 0, 0, 0, 0, -1 }, + //{ "Firefox", NULL, NULL, 1 << 8, 0, 0, 0, 0, 0, -1 }, + { "xterm-256color", NULL, NULL, 0, 0, 1, 1, 0, 0, -1 }, + { "Thunderbird", NULL, NULL, 1 << 8 , 0, 0, 0, 0, 0, -1 }, + { NULL, NULL, "noswallow", 0, 0, 0, 1, 0, 0, -1 }, + { "Onboard", NULL, NULL, 0, 1, 0, 1, 0, 1, -1 }, + { "Onboard-settings", NULL, NULL, 0, 0, 0, 0, 0, 0, -1 } }; diff --git a/dwm.c b/dwm.c index 673f284..14a1be2 100644 --- a/dwm.c +++ b/dwm.c @@ -51,7 +51,7 @@ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define ISVISIBLE(C) (((C->tags & C->mon->tagset[C->mon->seltags])) || (C->iskeyboard)) #define LENGTH(X) (sizeof X / sizeof X[0]) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) @@ -94,7 +94,7 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow, nofakefullscreen; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow, nofakefullscreen, iskeyboard; pid_t pid; Client *next; Client *snext; @@ -145,6 +145,7 @@ typedef struct { int isterminal; int noswallow; int nofakefullscreen; + int iskeyboard; int monitor; } Rule; @@ -244,6 +245,7 @@ static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void zoom(const Arg *arg); +static void adjustborders(Monitor *m); static pid_t getparentprocess(pid_t p); static int isdescprocess(pid_t p, pid_t c); @@ -321,6 +323,7 @@ applyrules(Client *c) c->noswallow = r->noswallow; c->isfloating = r->isfloating; c->nofakefullscreen = r->nofakefullscreen; + c->iskeyboard = r->iskeyboard; c->tags |= r->tags; for (m = mons; m && m->num != r->monitor; m = m->next); if (m) @@ -340,6 +343,10 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) int baseismin; Monitor *m = c->mon; + if (c->iskeyboard){ + return(False); + } + /* set minimum possible */ *w = MAX(1, *w); *h = MAX(1, *h); @@ -401,12 +408,14 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) } void -arrange(Monitor *m) -{ - if (m) +arrange(Monitor *m) { + if (m){ + adjustborders(m); showhide(m->stack); - else for (m = mons; m; m = m->next) + } else for (m = mons; m; m = m->next){ + adjustborders(m); showhide(m->stack); + } if (m) { arrangemon(m); restack(m); @@ -459,7 +468,7 @@ attachstack(Client *c) void swallow(Client *p, Client *c) { - if (c->noswallow || c->isterminal) + if (c->noswallow || c->isterminal || c->isfloating) return; detach(c); @@ -498,8 +507,7 @@ unswallow(Client *c) } void -buttonpress(XEvent *e) -{ +buttonpress(XEvent *e) { unsigned int i, x, click; Arg arg = {0}; Client *c; @@ -540,8 +548,7 @@ buttonpress(XEvent *e) } void -checkotherwm(void) -{ +checkotherwm(void) { xerrorxlib = XSetErrorHandler(xerrorstart); /* this causes an error if some other window manager is running */ XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); @@ -551,8 +558,7 @@ checkotherwm(void) } void -cleanup(void) -{ +cleanup(void) { Arg a = {.ui = ~0}; Layout foo = { "", NULL }; Monitor *m; @@ -578,8 +584,7 @@ cleanup(void) } void -cleanupmon(Monitor *mon) -{ +cleanupmon(Monitor *mon) { Monitor *m; if (mon == mons) @@ -613,8 +618,7 @@ clientmessage(XEvent *e) } void -configure(Client *c) -{ +configure(Client *c) { XConfigureEvent ce; ce.type = ConfigureNotify; @@ -632,8 +636,7 @@ configure(Client *c) } void -configurenotify(XEvent *e) -{ +configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; int dirty; @@ -656,14 +659,13 @@ configurenotify(XEvent *e) } void -configurerequest(XEvent *e) -{ +configurerequest(XEvent *e) { Client *c; Monitor *m; XConfigureRequestEvent *ev = &e->xconfigurerequest; XWindowChanges wc; - if ((c = wintoclient(ev->window))) { + if ((c = wintoclient(ev->window)) && !c->iskeyboard) { if (ev->value_mask & CWBorderWidth) c->bw = ev->border_width; else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { @@ -708,8 +710,7 @@ configurerequest(XEvent *e) } Monitor * -createmon(void) -{ +createmon(void) { Monitor *m; m = ecalloc(1, sizeof(Monitor)); @@ -725,8 +726,7 @@ createmon(void) } void -destroynotify(XEvent *e) -{ +destroynotify(XEvent *e) { Client *c; XDestroyWindowEvent *ev = &e->xdestroywindow; @@ -738,8 +738,7 @@ destroynotify(XEvent *e) } void -detach(Client *c) -{ +detach(Client *c) { Client **tc; for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); @@ -747,8 +746,7 @@ detach(Client *c) } void -detachstack(Client *c) -{ +detachstack(Client *c) { Client **tc, *t; for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); @@ -761,8 +759,7 @@ detachstack(Client *c) } Monitor * -dirtomon(int dir) -{ +dirtomon(int dir) { Monitor *m = NULL; if (dir > 0) { @@ -775,8 +772,7 @@ dirtomon(int dir) return m; } -void -drawbar(Monitor *m) +void drawbar(Monitor *m) { int x, w, tw = 0; int boxs = drw->fonts->h / 9; @@ -844,6 +840,11 @@ enternotify(XEvent *e) if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) return; c = wintoclient(ev->window); + + if ( c && c->iskeyboard ){ + return; + } + m = c ? c->mon : wintomon(ev->window); if (m != selmon) { unfocus(selmon->sel, 1); @@ -854,8 +855,7 @@ enternotify(XEvent *e) } void -expose(XEvent *e) -{ +expose(XEvent *e) { Monitor *m; XExposeEvent *ev = &e->xexpose; @@ -864,8 +864,10 @@ expose(XEvent *e) } void -focus(Client *c) -{ +focus(Client *c) { + if ( c && c->iskeyboard ) { + return; + } if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); if (selmon->sel && selmon->sel != c) @@ -899,8 +901,7 @@ focusin(XEvent *e) } void -focusmon(const Arg *arg) -{ +focusmon(const Arg *arg) { Monitor *m; if (!mons->next) @@ -914,23 +915,23 @@ focusmon(const Arg *arg) } void -focusstack(const Arg *arg) -{ +focusstack(const Arg *arg) { Client *c = NULL, *i; 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) || c->iskeyboard); c = c->next); if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { + for(c = selmon->clients; c && (!ISVISIBLE(c) || c->iskeyboard); c = c->next); + } + else { for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) + if(ISVISIBLE(i) && !i->iskeyboard) c = i; if (!c) for (; i; i = i->next) - if (ISVISIBLE(i)) + if(ISVISIBLE(i) && !i->iskeyboard) c = i; } if (c) { @@ -940,8 +941,7 @@ focusstack(const Arg *arg) } Atom -getatomprop(Client *c, Atom prop) -{ +getatomprop(Client *c, Atom prop) { int di; unsigned long dl; unsigned char *p = NULL; @@ -956,8 +956,7 @@ getatomprop(Client *c, Atom prop) } int -getrootptr(int *x, int *y) -{ +getrootptr(int *x, int *y) { int di; unsigned int dui; Window dummy; @@ -966,8 +965,7 @@ getrootptr(int *x, int *y) } long -getstate(Window w) -{ +getstate(Window w) { int format; long result = -1; unsigned char *p = NULL; @@ -1030,8 +1028,7 @@ grabbuttons(Client *c, int focused) } void -grabkeys(void) -{ +grabkeys(void) { updatenumlockmask(); { unsigned int i, j; @@ -1048,8 +1045,7 @@ grabkeys(void) } void -incnmaster(const Arg *arg) -{ +incnmaster(const Arg *arg) { selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } @@ -1067,8 +1063,7 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) #endif /* XINERAMA */ void -keypress(XEvent *e) -{ +keypress(XEvent *e) { unsigned int i; KeySym keysym; XKeyEvent *ev; @@ -1099,8 +1094,7 @@ killclient(const Arg *arg) } void -manage(Window w, XWindowAttributes *wa) -{ +manage(Window w, XWindowAttributes *wa) { Client *c, *t = NULL, *term = NULL; Window trans = None; XWindowChanges wc; @@ -1108,13 +1102,6 @@ manage(Window w, XWindowAttributes *wa) c = ecalloc(1, sizeof(Client)); c->win = w; c->pid = winpid(w); - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - updatetitle(c); if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; @@ -1125,15 +1112,43 @@ manage(Window w, XWindowAttributes *wa) term = termforwin(c); } - if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) - c->x = c->mon->mx + c->mon->mw - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) - c->y = c->mon->my + c->mon->mh - HEIGHT(c); - c->x = MAX(c->x, c->mon->mx); - /* only fix client y-offset, if the client center might cover the bar */ - c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + + + /* If Keyboard */ + + if (c->iskeyboard) { + c->y = c->mon->my + c->mon->mh - c->h; + c->mon->mh -= HEIGHT(c); + } else { + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + c->x = c->mon->mx + c->mon->mw - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) + c->y = c->mon->my + c->mon->mh - HEIGHT(c); + c->x = MAX(c->x, c->mon->mx); + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + } + + updatewindowtype(c); + if (c->isfloating) { + c->bw = (c->isfullscreen || c->iskeyboard) ? 0 : borderpx; + } else { + c->bw = 0; + for(t = c->mon->clients; t; t = c->next) { + if (!t->isfloating && c != t && c->tags & t->tags) { + c->bw = borderpx; + break; + } + } + adjustborders(c->mon); + } wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); @@ -1224,8 +1239,7 @@ motionnotify(XEvent *e) } void -movemouse(const Arg *arg) -{ +movemouse(const Arg *arg) { int x, y, ocx, ocy, nx, ny; Client *c; Monitor *m; @@ -1282,15 +1296,13 @@ movemouse(const Arg *arg) } Client * -nexttiled(Client *c) -{ +nexttiled(Client *c) { for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); return c; } void -pop(Client *c) -{ +pop(Client *c) { detach(c); attach(c); focus(c); @@ -1298,8 +1310,7 @@ pop(Client *c) } void -propertynotify(XEvent *e) -{ +propertynotify(XEvent *e) { Client *c; Window trans; XPropertyEvent *ev = &e->xproperty; @@ -1355,15 +1366,67 @@ recttomon(int x, int y, int w, int h) } void -resize(Client *c, int x, int y, int w, int h, int interact) -{ +adjustborders(Monitor *m) { + Client *c, *l = NULL; + int visible = 0; + + for(c = m->clients; c; c = c->next) { + if (ISVISIBLE(c) && !c->isfloating && m->lt[m->sellt]->arrange) { + if (m->lt[m->sellt]->arrange == monocle) { + visible = 1; + c->oldbw = c->bw; + c->bw = 0; + } else { + visible++; + c->oldbw = c->bw; + c->bw = borderpx; + } + + l = c; + } + } + + if (l && visible == 1 && l->bw) { + l->oldbw = l->bw; + l->bw = 0; + resizeclient(l, l->x, l->y, l->w, l->h); + } +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) { + int n; + + if (c && c->iskeyboard) { + return; + } + + n = c->mon->mx + c->mon->mw; + if (x + w + 1 + (2 * c->bw) >= n) { + w = n - x - c->bw; + } + + n = c->mon->my + c->mon->mh; + if (y + h + 1 + (2 * c->bw) >= n) { + h = n - y - c->bw; + } + + if (x <= c->mon->mx) { + x -= c->bw; + w += c->bw; + } + + if (y <= c->mon->my) { + y -= c->bw; + y += c->bw; + } + if (applysizehints(c, &x, &y, &w, &h, interact)) resizeclient(c, x, y, w, h); } void -resizeclient(Client *c, int x, int y, int w, int h) -{ +resizeclient(Client *c, int x, int y, int w, int h) { XWindowChanges wc; unsigned int n; unsigned int gapoffset; @@ -1372,6 +1435,10 @@ resizeclient(Client *c, int x, int y, int w, int h) wc.border_width = c->bw; + if (c->iskeyboard) { + return; + } + /* Get number of clients for the selected monitor */ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); @@ -1867,6 +1934,10 @@ unmanage(Client *c, int destroyed) Monitor *m = c->mon; XWindowChanges wc; + if (c->iskeyboard) { + updategeom(); + } + if (c->swallowing) { unswallow(c); return;