diff --git a/README.md b/README.md index 4e8c117..2bff4ce 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: +2020-03-27 - Revamped the dragmfact patch to support both horizontal and vertical layout splits as well as centered master variants + 2020-03-25 - Added dragcfact patch 2020-03-23 - Added stacker patch @@ -149,10 +151,11 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - i.e. if topbar is 0 then dmenu will appear at the bottom and if 1 then dmenu will appear at the top - dragcfact - - lets you resize clients' size (i.e. modify cfact) by holding modkey + shift and dragging the mouse + - lets you resize clients' size (i.e. modify cfact) by holding modkey + shift + right-click and dragging the mouse - [dragmfact](https://dwm.suckless.org/patches/dragmfact/) - - lets you resize the split in the tile layout (i.e. modify mfact) by holding the modkey and dragging the mouse + - lets you resize the split in layouts (i.e. modify mfact) by holding the modkey + shift + left-click and dragging the mouse + - this is a bespoke patch that supports vertical and horizontal layout splits as well as centered master variants - [dwmc](http://dwm.suckless.org/patches/dwmc/) - a simple dwmc client using a fork of fsignal to communicate with dwm diff --git a/config.def.h b/config.def.h index 750285e..88aa852 100644 --- a/config.def.h +++ b/config.def.h @@ -954,6 +954,9 @@ static Button buttons[] = { #if DRAGCFACT_PATCH && CFACTS_PATCH { ClkClientWin, MODKEY|ShiftMask, Button3, dragcfact, {0} }, #endif // DRAGCFACT_PATCH + #if DRAGMFACT_PATCH + { ClkClientWin, MODKEY|ShiftMask, Button1, dragmfact, {0} }, + #endif // DRAGMFACT_PATCH { ClkTagBar, 0, Button1, view, {0} }, { ClkTagBar, 0, Button3, toggleview, {0} }, { ClkTagBar, MODKEY, Button1, tag, {0} }, diff --git a/dwm.c b/dwm.c index 88b9b84..5ad3bec 100644 --- a/dwm.c +++ b/dwm.c @@ -2473,32 +2473,9 @@ resizemouse(const Arg *arg) return; horizcorner = nx < c->w / 2; vertcorner = ny < c->h / 2; - #if DRAGMFACT_PATCH - if (c->isfloating || NULL == c->mon->lt[c->mon->sellt]->arrange) { - XWarpPointer (dpy, None, c->win, 0, 0, 0, 0, - horizcorner ? (-c->bw) : (c->w + c->bw - 1), - vertcorner ? (-c->bw) : (c->h + c->bw - 1) - ); - } else { - XWarpPointer(dpy, None, root, 0, 0, 0, 0, - selmon->mx + (selmon->ww * selmon->mfact), - selmon->my + (selmon->wh / 2) - ); - } - #else XWarpPointer (dpy, None, c->win, 0, 0, 0, 0, horizcorner ? (-c->bw) : (c->w + c->bw - 1), vertcorner ? (-c->bw) : (c->h + c->bw - 1)); - #endif // DRAGMFACT_PATCH - #elif DRAGMFACT_PATCH - if (c->isfloating || NULL == c->mon->lt[c->mon->sellt]->arrange) { - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - } else { - XWarpPointer(dpy, None, root, 0, 0, 0, 0, - selmon->mx + (selmon->ww * selmon->mfact), - selmon->my + (selmon->wh / 2) - ); - } #else XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); #endif // RESIZECORNERS_PATCH @@ -2523,7 +2500,6 @@ resizemouse(const Arg *arg) nw = MAX(horizcorner ? (ocx2 - nx) : (ev.xmotion.x - ocx - 2 * c->bw + 1), 1); nh = MAX(vertcorner ? (ocy2 - ny) : (ev.xmotion.y - ocy - 2 * c->bw + 1), 1); #endif // RESIZECORNERS_PATCH - #if !DRAGMFACT_PATCH if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) { @@ -2531,7 +2507,6 @@ resizemouse(const Arg *arg) && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) togglefloating(NULL); } - #endif // DRAGMFACT_PATCH if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { #if RESIZECORNERS_PATCH resize(c, nx, ny, nw, nh, 1); @@ -2556,35 +2531,9 @@ resizemouse(const Arg *arg) } } while (ev.type != ButtonRelease); #if RESIZECORNERS_PATCH - #if DRAGMFACT_PATCH - if (c->isfloating || NULL == c->mon->lt[c->mon->sellt]->arrange) { - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, - horizcorner ? (-c->bw) : (c->w + c->bw - 1), - vertcorner ? (-c->bw) : (c->h + c->bw - 1)); - } else { - selmon->mfact = (double) (ev.xmotion.x_root - selmon->mx) / (double) selmon->ww; - arrange(selmon); - XWarpPointer(dpy, None, root, 0, 0, 0, 0, - selmon->mx + (selmon->ww * selmon->mfact), - selmon->my + (selmon->wh / 2) - ); - } - #else XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, horizcorner ? (-c->bw) : (c->w + c->bw - 1), vertcorner ? (-c->bw) : (c->h + c->bw - 1)); - #endif // DRAGMFACT_PATCH - #elif DRAGMFACT_PATCH - if (c->isfloating || NULL == c->mon->lt[c->mon->sellt]->arrange) { - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - } else { - selmon->mfact = (double) (ev.xmotion.x_root - selmon->mx) / (double) selmon->ww; - arrange(selmon); - XWarpPointer(dpy, None, root, 0, 0, 0, 0, - selmon->mx + (selmon->ww * selmon->mfact), - selmon->my + (selmon->wh / 2) - ); - } #else XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); #endif // RESIZECORNERS_PATCH @@ -2862,9 +2811,9 @@ setlayout(const Arg *arg) #endif // PERTAG_PATCH #if FLEXTILE_DELUXE_LAYOUT - if (selmon->lt[selmon->sellt]->preset.nmaster != -1) + if (selmon->lt[selmon->sellt]->preset.nmaster && selmon->lt[selmon->sellt]->preset.nmaster != -1) selmon->nmaster = selmon->lt[selmon->sellt]->preset.nmaster; - if (selmon->lt[selmon->sellt]->preset.nstack != -1) + if (selmon->lt[selmon->sellt]->preset.nstack && selmon->lt[selmon->sellt]->preset.nstack != -1) selmon->nstack = selmon->lt[selmon->sellt]->preset.nstack; selmon->ltaxis[LAYOUT] = selmon->lt[selmon->sellt]->preset.layout; diff --git a/patch/dragmfact.c b/patch/dragmfact.c new file mode 100644 index 0000000..ee76647 --- /dev/null +++ b/patch/dragmfact.c @@ -0,0 +1,217 @@ +void +dragmfact(const Arg *arg) +{ + unsigned int n; + int py, px; // pointer coordinates + int ax, ay, aw, ah; // area position, width and height + int center = 0, horizontal = 0, mirror = 0; // layout configuration + double fact; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + m = selmon; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + ax = m->wx; + ay = m->wy; + ah = m->wh; + aw = m->ww; + + /* do not allow mfact to be modified under certain conditions */ + if (!m->lt[m->sellt]->arrange // floating + || (m->nmaster && n <= m->nmaster) // no master + #if MONOCLE_LAYOUT + || m->lt[m->sellt]->arrange == monocle + #endif // MONOCLE_LAYOUT + #if GRIDMODE_LAYOUT + || m->lt[m->sellt]->arrange == grid + #endif // GRIDMODE_LAYOUT + #if HORIZGRID_LAYOUT + || m->lt[m->sellt]->arrange == horizgrid + #endif // HORIZGRID_LAYOUT + #if GAPPLESSGRID_LAYOUT + || m->lt[m->sellt]->arrange == gaplessgrid + #endif // GAPPLESSGRID_LAYOUT + #if NROWGRID_LAYOUT + || m->lt[m->sellt]->arrange == nrowgrid + #endif // NROWGRID_LAYOUT + #if FLEXTILE_DELUXE_LAYOUT + || (m->lt[m->sellt]->arrange == flextile && m->ltaxis[LAYOUT] == NO_SPLIT) + #endif // FLEXTILE_DELUXE_LAYOUT + ) + return; + + #if FLEXTILE_DELUXE_LAYOUT + if (m->lt[m->sellt]->arrange == flextile) { + int layout = m->ltaxis[LAYOUT]; + if (layout < 0) { + mirror = 1; + layout *= -1; + } + if (layout > FLOATING_MASTER) + layout -= FLOATING_MASTER; + + if (layout == SPLIT_HORIZONTAL || layout == SPLIT_HORIZONTAL_DUAL_STACK) + horizontal = 1; + else if (layout == SPLIT_CENTERED_VERTICAL) + center = 1; + else if (layout == FLOATING_MASTER) { + center = 1; + if (aw < ah) + horizontal = 1; + } + else if (layout == SPLIT_CENTERED_HORIZONTAL) { + horizontal = 1; + center = 1; + } + } + #endif // FLEXTILE_DELUXE_LAYOUT + #if CENTEREDMASTER_LAYOUT + else if (m->lt[m->sellt]->arrange == centeredmaster) + center = 1; + #endif // CENTEREDMASTER_LAYOUT + #if CENTEREDFLOATINGMASTER_LAYOUT + else if (m->lt[m->sellt]->arrange == centeredfloatingmaster) + center = 1; + #endif // CENTEREDFLOATINGMASTER_LAYOUT + #if BSTACK_LAYOUT + else if (m->lt[m->sellt]->arrange == bstack) + horizontal = 1; + #endif // BSTACK_LAYOUT + #if BSTACKHORIZ_LAYOUT + else if (m->lt[m->sellt]->arrange == bstackhoriz) + horizontal = 1; + #endif // BSTACKHORIZ_LAYOUT + + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + + #if VANITYGAPS_PATCH + ay += oh; + ax += ov; + aw -= 2*ov; + ah -= 2*oh; + #endif // VANITYGAPS_PATCH + + if (center) { + if (horizontal) { + px = ax + aw / 2; + #if VANITYGAPS_PATCH + py = ay + ah / 2 + (ah - 2*ih) * (m->mfact / 2.0) + ih / 2; + #else + py = ay + ah / 2 + ah * m->mfact / 2.0; + #endif // VANITYGAPS_PATCH + } else { // vertical split + #if VANITYGAPS_PATCH + px = ax + aw / 2 + (aw - 2*iv) * m->mfact / 2.0 + iv / 2; + #else + px = ax + aw / 2 + aw * m->mfact / 2.0; + #endif // VANITYGAPS_PATCH + py = ay + ah / 2; + } + } else if (horizontal) { + px = ax + aw / 2; + if (mirror) + #if VANITYGAPS_PATCH + py = ay + (ah - ih) * (1.0 - m->mfact) + ih / 2; + #else + py = ay + (ah * (1.0 - m->mfact)); + #endif // VANITYGAPS_PATCH + else + #if VANITYGAPS_PATCH + py = ay + ((ah - ih) * m->mfact) + ih / 2; + #else + py = ay + (ah * m->mfact); + #endif // VANITYGAPS_PATCH + } else { // vertical split + if (mirror) + #if VANITYGAPS_PATCH + px = ax + (aw - iv) * (1.0 - m->mfact) + iv / 2; + #else + px = ax + (aw * m->mfact); + #endif // VANITYGAPS_PATCH + else + #if VANITYGAPS_PATCH + px = ax + ((aw - iv) * m->mfact) + iv / 2; + #else + px = ax + (aw * m->mfact); + #endif // VANITYGAPS_PATCH + py = ay + ah / 2; + } + + XWarpPointer(dpy, None, root, 0, 0, 0, 0, px, py); + + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 40)) + continue; + if (lasttime != 0) { + px = ev.xmotion.x; + py = ev.xmotion.y; + } + lasttime = ev.xmotion.time; + + #if VANITYGAPS_PATCH + if (center) + if (horizontal) + if (py - ay > ah / 2) + fact = (double) 1.0 - (ay + ah - py - ih / 2) * 2 / (double) (ah - 2*ih); + else + fact = (double) 1.0 - (py - ay - ih / 2) * 2 / (double) (ah - 2*ih); + else + if (px - ax > aw / 2) + fact = (double) 1.0 - (ax + aw - px - iv / 2) * 2 / (double) (aw - 2*iv); + else + fact = (double) 1.0 - (px - ax - iv / 2) * 2 / (double) (aw - 2*iv); + else + if (horizontal) + fact = (double) (py - ay - ih / 2) / (double) (ah - ih); + else + fact = (double) (px - ax - iv / 2) / (double) (aw - iv); + #else + if (center) + if (horizontal) + if (py - ay > ah / 2) + fact = (double) 1.0 - (ay + ah - py) * 2 / (double) ah; + else + fact = (double) 1.0 - (py - ay) * 2 / (double) ah; + else + if (px - ax > aw / 2) + fact = (double) 1.0 - (ax + aw - px) * 2 / (double) aw; + else + fact = (double) 1.0 - (px - ax) * 2 / (double) aw; + else + if (horizontal) + fact = (double) (py - ay) / (double) ah; + else + fact = (double) (px - ax) / (double) aw; + #endif // VANITYGAPS_PATCH + + if (!center && mirror) + fact = 1.0 - fact; + + setmfact(&((Arg) { .f = 1.0 + fact })); + px = ev.xmotion.x; + py = ev.xmotion.y; + break; + } + } while (ev.type != ButtonRelease); + + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} \ No newline at end of file diff --git a/patch/dragmfact.h b/patch/dragmfact.h new file mode 100644 index 0000000..6390b71 --- /dev/null +++ b/patch/dragmfact.h @@ -0,0 +1 @@ +static void dragmfact(const Arg *arg); \ No newline at end of file diff --git a/patch/include.c b/patch/include.c index b881f4d..5cbb942 100644 --- a/patch/include.c +++ b/patch/include.c @@ -167,6 +167,9 @@ #if XRDB_PATCH && !VTCOLORS_PATCH #include "xrdb.c" #endif +#if DRAGMFACT_PATCH +#include "dragmfact.c" +#endif /* Layouts */ #if BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || TILE_LAYOUT #include "layout_facts.c" diff --git a/patch/include.h b/patch/include.h index 9556675..5d6ee6c 100644 --- a/patch/include.h +++ b/patch/include.h @@ -29,6 +29,9 @@ #if DRAGCFACT_PATCH && CFACTS_PATCH #include "dragcfact.h" #endif +#if DRAGMFACT_PATCH +#include "dragmfact.h" +#endif #if DWMC_PATCH #include "dwmc.h" #elif FSIGNAL_PATCH diff --git a/patch/vanitygaps.h b/patch/vanitygaps.h index 5667be2..6c8d5cf 100644 --- a/patch/vanitygaps.h +++ b/patch/vanitygaps.h @@ -10,7 +10,7 @@ static void incrivgaps(const Arg *arg); static void togglegaps(const Arg *arg); /* Internals */ -#if CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || FIBONACCI_DWINDLE_LAYOUT || FIBONACCI_SPIRAL_LAYOUT || GAPPLESSGRID_LAYOUT || NROWGRID_LAYOUT || HORIZGRID_LAYOUT || BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || GRIDMODE_LAYOUT || FLEXTILE_DELUXE_LAYOUT || TILE_LAYOUT || (VANITYGAPS_MONOCLE_PATCH && MONOCLE_LAYOUT) +#if DRAGMFACT_PATCH || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || FIBONACCI_DWINDLE_LAYOUT || FIBONACCI_SPIRAL_LAYOUT || GAPPLESSGRID_LAYOUT || NROWGRID_LAYOUT || HORIZGRID_LAYOUT || BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || GRIDMODE_LAYOUT || FLEXTILE_DELUXE_LAYOUT || TILE_LAYOUT || (VANITYGAPS_MONOCLE_PATCH && MONOCLE_LAYOUT) static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); #endif static void setgaps(int oh, int ov, int ih, int iv); \ No newline at end of file