fix floatrules and scratchpad resizing on togglebar

This commit is contained in:
Luca Bilke 2022-09-16 17:38:31 +02:00
commit 17bc5dfdee
No known key found for this signature in database
GPG key ID: 7B77C51E8C779E75

183
dwm.c
View file

@ -111,10 +111,8 @@ 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;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow, hasfloatrule;
pid_t pid;
int floatborderpx;
int hasfloatbw;
char scratchkey;
Client *next;
Client *snext;
@ -172,8 +170,7 @@ typedef struct {
int isterminal;
int noswallow;
float floatx, floaty, floatw, floath;
int floatborderpx;
int monitor;
int borderpx;
} Rule;
/* Xresources preferences */
@ -190,7 +187,9 @@ typedef struct {
} ResourcePref;
/* function declarations */
static void applyrules(Client *c);
static int matchrules(Client *c);
static void applyfloatrules(Client *c, int ri);
static void applyrules(Client *c, int ri);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
@ -356,70 +355,110 @@ struct Pertag {
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
/* function implementations */
void
applyrules(Client *c)
int
matchrules(Client *c)
{
const char *class, *instance;
unsigned int i;
unsigned int ri;
const Rule *r;
Monitor *m;
XClassHint ch = { NULL, NULL };
/* rule matching */
c->isfloating = 0;
c->tags = 0;
c->scratchkey = 0;
XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken;
instance = ch.res_name ? ch.res_name : broken;
for (i = 0; i < LENGTH(rules); i++) {
r = &rules[i];
for (ri = 0; ri < LENGTH(rules); ri++) {
r = &rules[ri];
if ((!r->title || strstr(c->name, r->title))
&& (!r->class || strstr(class, r->class))
&& (!r->instance || strstr(instance, r->instance)))
{
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
c->isterminal = r->isterminal;
c->noswallow = r->noswallow;
c->isfloating = r->isfloating;
c->tags |= r->tags;
c->scratchkey = r->scratchkey;
if (r->floatborderpx >= 0) {
c->floatborderpx = r->floatborderpx;
c->hasfloatbw = 1;
}
- (bh + m->by);
if (r->isfloating) {
if (r->floatw > 1) c->w = r->floatw - c->floatborderpx * 2;
else if (r->floatw > 0) c->w = (int)((float)c->mon->mw * r->floatw - c->floatborderpx * 2);
if (r->floath > 1) c->h = r->floath - c->floatborderpx * 2 - (bh + m->by);
else if (r->floath > 0) c->h = (int)((float)c->mon->mh * r->floath - c->floatborderpx * 2) - (bh + m->by);
if (r->floatx > 1) c->x = c->mon->mx + r->floatx;
else if (r->floatx > 0) c->x = c->mon->mx + (int)((float)c->mon->mw * r->floatx - (float)c->w / 2);
else if (r->floatx == 0);
else if (r->floatx > -1) c->x = c->mon->mx + c->mon->mw + (int)((float)c->mon->mw * r->floatx - (float)c->w / 2);
else c->x = c->mon->mx + c->mon->mw + r->floatx - c->w;
if (r->floaty > 1) c->y = c->mon->my + r->floaty;
else if (r->floaty > 0) c->y = c->mon->my + (int)((float)c->mon->mh * r->floaty - (float)c->h / 2);
else if (r->floaty == 0);
else if (r->floaty > -1) c->y = c->mon->my + c->mon->mh + (int)((float)c->mon->mh * r->floaty - (float)c->h / 2);
else c->y = c->mon->my + c->mon->mh + r->floaty - c->h;
}
&& (!r->instance || strstr(instance, r->instance))) {
if (ch.res_class)
XFree(ch.res_class);
if (ch.res_name)
XFree(ch.res_name);
return ri;
}
}
if (ch.res_class)
XFree(ch.res_class);
if (ch.res_name)
XFree(ch.res_name);
return False;
}
void
applyfloatrules(Client *c, int ri)
{
const Rule *r;
ri = (ri) ? ri : matchrules(c);
if (ri) {
r = &rules[ri];
if (r->floatw > 1)
c->w = r->floatw;
else if (r->floatw > 0)
c->w = (int)((float)c->mon->ww * r->floatw);
c->w = MIN(c->w, c->mon->ww) - c->bw * 2;
if (r->floath > 1)
c->h = r->floath;
else if (r->floath > 0)
c->h = (int)((float)c->mon->wh * r->floath);
c->h = MIN(c->h, c->mon->wh) - c->bw * 2;
if (r->floatx > 1)
c->x = r->floatx;
else if (r->floatx > 0)
c->x = (int)((float)c->mon->ww * r->floatx - (float)WIDTH(c) / 2);
else if (r->floatx == 0)
;
else if (r->floatx > -1)
c->x = c->mon->ww + (int)((float)c->mon->ww * r->floatx - (float)WIDTH(c) / 2);
else
c->x = c->mon->ww + r->floatx - WIDTH(c);
if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
c->x = c->mon->ww - WIDTH(c);
c->x = MAX(c->x + c->mon->wx, c->mon->wx);
if (r->floaty > 1)
c->y = r->floaty;
else if (r->floaty > 0)
c->y = (int)((float)c->mon->wh * r->floaty - (float)HEIGHT(c) / 2);
else if (r->floaty == 0)
;
else if (r->floaty > -1)
c->y = c->mon->wh + (int)((float)c->mon->wh * r->floaty - (float)HEIGHT(c) / 2);
else
c->y = c->mon->wh + r->floaty - HEIGHT(c);
if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh)
c->y = c->mon->wh - HEIGHT(c);
c->y = MAX(c->y + c->mon->wy, c->mon->wy);
}
}
void
applyrules(Client *c, int ri)
{
const Rule *r;
ri = (ri) ? ri : matchrules(c);
c->isfloating = 0;
c->tags = 0;
c->scratchkey = 0;
c->bw = borderpx;
if (ri) {
c->hasfloatrule = True;
r = &rules[ri];
c->isterminal = r->isterminal;
c->noswallow = r->noswallow;
c->isfloating = r->isfloating;
c->tags |= r->tags;
c->scratchkey = r->scratchkey;
if (r->borderpx >= 0)
c->bw = r->borderpx;
if (c->isfloating) {
applyfloatrules(c, ri);
}
}
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
}
@ -1457,6 +1496,8 @@ manage(Window w, XWindowAttributes *wa)
Client *c, *t = NULL, *term = NULL;
Window trans = None;
XWindowChanges wc;
int ri;
c = ecalloc(1, sizeof(Client));
c->win = w;
@ -1468,16 +1509,20 @@ manage(Window w, XWindowAttributes *wa)
c->h = c->oldh = wa->height;
c->oldbw = wa->border_width;
ri = False;
updatetitle(c);
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
c->tags = t->tags;
} else {
c->mon = selmon;
applyrules(c);
ri = matchrules(c);
applyrules(c, ri);
term = termforwin(c);
}
/* We can't repeat this code if a window has a floating rule, because that is handled by applyfloatrules() */
if (!c->isfloating) {
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)
@ -1486,10 +1531,7 @@ manage(Window w, XWindowAttributes *wa)
/* 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);
if (c->hasfloatbw)
c->bw = c->floatborderpx;
else
c->bw = borderpx;
}
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
@ -1500,10 +1542,10 @@ manage(Window w, XWindowAttributes *wa)
updatewmhints(c);
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
grabbuttons(c, 0);
if (!c->isfloating)
c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating)
XRaiseWindow(dpy, c->win);
else
c->isfloating = c->oldstate = trans != None || c->isfixed;
attachtop(c);
attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
@ -1736,7 +1778,7 @@ recttomon(int x, int y, int w, int h)
void
resize(Client *c, int x, int y, int w, int h, int interact)
{
if (applysizehints(c, &x, &y, &w, &h, interact))
if (applysizehints(c, &x, &y, &w, &h, interact) || c->hasfloatrule)
resizeclient(c, x, y, w, h);
}
@ -1749,9 +1791,6 @@ resizeclient(Client *c, int x, int y, int w, int h)
c->oldy = c->y; c->y = wc.y = y;
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
if (c->isfloating && c->hasfloatbw && !c->isfullscreen)
wc.border_width = c->floatborderpx;
else
wc.border_width = c->bw;
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
configure(c);
@ -2112,11 +2151,15 @@ showhide(Client *c)
{
if (!c)
return;
if (c->isfloating) {
applyfloatrules(c, False);
}
if (ISVISIBLE(c)) {
/* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) {
resize(c, c->x, c->y, c->w, c->h, 0);
}
showhide(c->snext);
} else {
/* hide clients bottom up */
@ -2257,6 +2300,7 @@ tagmon(const Arg *arg)
void
togglebar(const Arg *arg)
{
printf("toggling bar\n");
selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
updatebarpos(selmon);
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
@ -2296,7 +2340,10 @@ togglescratch(const Arg *arg)
break;
}
if (found) {
if(m != selmon);
applyfloatrules(c, False);
if(m != selmon){
sendmon(c, selmon);
}
else {
c->tags = ISVISIBLE(c) ? 0 : selmon->tagset[selmon->seltags];
focus(NULL);