diff --git a/config.def.h b/config.def.h --- a/config.def.h +++ b/config.def.h @@ -78,6 +78,15 @@ { MODKEY, XK_period, focusmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY|ControlMask, XK_l, togglehorizontalmax, {.i = +1} }, // Only maximize to the right + { MODKEY|ControlMask|ShiftMask, XK_l, togglehorizontalmax, {.i = 0} }, // Maximize both left and right + { MODKEY|ControlMask, XK_g, togglehorizontalmax, {.i = -1} }, // Only maximize to the left + { MODKEY|ControlMask, XK_r, toggleverticalmax, {.i = +1} }, + { MODKEY|ControlMask|ShiftMask, XK_r, toggleverticalmax, {.i = 0} }, + { MODKEY|ControlMask, XK_c, toggleverticalmax, {.i = -1} }, + { MODKEY|ControlMask, XK_m, togglemaximize, {.i = +1} }, // Force maximize + { MODKEY|ControlMask|ShiftMask, XK_m, togglemaximize, {.i = 0} }, // Toggle maximize + { MODKEY|ControlMask, XK_n, togglemaximize, {.i = -1} }, // Remove all maximization TAGKEYS( XK_1, 0) TAGKEYS( XK_2, 1) TAGKEYS( XK_3, 2) diff --git a/dwm.c b/dwm.c --- a/dwm.c +++ b/dwm.c @@ -91,7 +91,9 @@ int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + unsigned char maxmask; + int maxx1, maxy1, maxx2, maxy2; + Bool wasfloating, isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; Monitor *mon; @@ -1158,6 +1160,8 @@ updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, False); + c->wasfloating = False; + c->maxmask = 0; if(!c->isfloating) c->isfloating = c->oldstate = trans != None || c->isfixed; if(c->isfloating) @@ -1367,6 +1371,7 @@ 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; + c->maxmask = 0; wc.border_width = c->bw; XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); configure(c); diff --git a/maximize.c b/maximize.c new file mode 100644 --- /dev/null +++ b/maximize.c @@ -0,0 +1,114 @@ +#define MAX_LEFT (1 << 0) +#define MAX_RIGHT (1 << 2) +#define MAX_UP (1 << 4) +#define MAX_DOWN (1 << 6) + +#define IS_SET(q, w) ((q & w) != 0) +#define IS_FORCED(q, w) IS_SET((q << 1), w) +#ifndef MAX +#define MAX(a,b) (a > b ? a : b) +#endif + +int +new_value(unsigned char mask, unsigned char curmask, + unsigned char *newmask, unsigned char key, + int *reset_value, int new_reset_value, + int max_value, int old_value) { + if (IS_SET(key, mask) || + (IS_SET(key, curmask) && (!IS_SET(key, mask) && IS_FORCED(key, mask))) || + (!IS_SET(key, curmask) && (IS_SET(key, mask) && IS_FORCED(key, mask)))) { + + if (IS_SET(key, mask) && (!IS_SET(key,curmask) || IS_FORCED(key,mask))) + { + if (!IS_SET(key, curmask)) + *reset_value = new_reset_value; + *newmask |= key; + return max_value; + } else if ((IS_SET(key,curmask) && IS_SET(key, mask)) || + (!IS_SET(key, mask) && IS_FORCED(key, mask))) { + *newmask &= ~key; + return *reset_value; + } else { + *newmask &= ~key; + return old_value; + } + } else + return new_reset_value; +} + +void +maximize(unsigned char mask) { + XEvent ev; + int nx1, ny1, nx2, ny2; + unsigned char curmask; + unsigned char newmask; + + if(!selmon->sel || selmon->sel->isfixed) + return; + XRaiseWindow(dpy, selmon->sel->win); + newmask = curmask = selmon->sel->maxmask; + + if (curmask == 0) { + if(!selmon->lt[selmon->sellt]->arrange || selmon->sel->isfloating) + selmon->sel->wasfloating = True; + else { + togglefloating(NULL); + selmon->sel->wasfloating = False; + } + } + + nx1 = new_value(mask, curmask, &newmask, + MAX_LEFT, &selmon->sel->maxx1, + selmon->sel->x, + selmon->wx, + selmon->sel->oldx); + nx2 = new_value(mask, curmask, &newmask, + MAX_RIGHT, &selmon->sel->maxx2, + selmon->sel->x + selmon->sel->w, + selmon->wx + selmon->ww - 2*borderpx, + selmon->sel->oldw + selmon->sel->x); + ny1 = new_value(mask, curmask, &newmask, + MAX_UP, &selmon->sel->maxy1, + selmon->sel->y, + selmon->wy, + selmon->sel->oldy); + ny2 = new_value(mask, curmask, &newmask, + MAX_DOWN, &selmon->sel->maxy2, + selmon->sel->y + selmon->sel->h, + selmon->wy + selmon->wh - 2*borderpx, + selmon->sel->oldh + selmon->sel->y); + + + resizeclient(selmon->sel, nx1, ny1, MAX(nx2-nx1, 32), MAX(ny2-ny1, 32)); + + if ((newmask == 0) && (!selmon->sel->wasfloating)) + togglefloating(NULL); + selmon->sel->maxmask = newmask; + drawbar(selmon); + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +#define MAXIMIZE (MAX_LEFT | MAX_RIGHT | MAX_UP | MAX_DOWN) +#define UNMAXIMIZE (MAXIMIZE << 1) // Force all directions to 0 +#define FORCE_MAXIMIZE ~0 //(MAXIMIZE | (MAXIMIZE << 1)) + +void +togglemaximize(const Arg *arg) { + if (arg->i > 0) maximize(FORCE_MAXIMIZE); + else if (arg->i < 0) maximize(UNMAXIMIZE); + else maximize(MAXIMIZE); +} + +void +toggleverticalmax(const Arg *arg) { + if (arg->i < 0) maximize(MAX_DOWN); + else if (arg->i > 0) maximize(MAX_UP); + else maximize(MAX_DOWN | MAX_UP); +} + +void +togglehorizontalmax(const Arg *arg) { + if (arg->i < 0) maximize(MAX_LEFT); + else if (arg->i > 0) maximize(MAX_RIGHT); + else maximize(MAX_LEFT | MAX_RIGHT); +}