From d6869e63031719675f0eb836db2e75422391705c Mon Sep 17 00:00:00 2001 From: speediegq Date: Tue, 11 Oct 2022 14:01:22 +0200 Subject: [PATCH] implement dragmfact properly --- docs/keybinds | 2 +- mouse.h | 4 +- options.h | 13 ++-- speedwm.c | 191 ++++++++++++++++++++++++++++++++++++++++++-------- toggle.h | 1 - 5 files changed, 171 insertions(+), 40 deletions(-) diff --git a/docs/keybinds b/docs/keybinds index e8e4fbd..4eee6ec 100644 --- a/docs/keybinds +++ b/docs/keybinds @@ -164,7 +164,7 @@ - Focused window (Super+Alt+Left click) | Move the focused window around - Focused window (Super+Alt+Middle click) | Make the focused window floating - Focused window title (Middle click) | Rotate stack - - Dragging (Super+Right click) | Increase/decrease size of each window + - Dragging (Super+Right click) | Increase/decrease size of each window (mfact) - Dragging (SuperControl+Right click) | Increase/decrease cfact - Root window (Right click) | List .desktop entries and open them diff --git a/mouse.h b/mouse.h index 741d7cd..61733c3 100644 --- a/mouse.h +++ b/mouse.h @@ -14,10 +14,10 @@ static const Button buttons[] = { { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1 } }, { ClkLtSymbol, 0, Button2, cyclelayout, {.i = -1 } }, { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkClientWin, MODIFIER1|ControlMask, Button3, dragcfact, {0} }, { ClkClientWin, MODIFIER1, Button1, moveorplace, {.i = 1} }, { ClkClientWin, MODIFIER1, Button2, togglefloating, {0} }, - { ClkClientWin, MODIFIER1, Button3, resizemouse, {0} }, + { ClkClientWin, MODIFIER1|ControlMask, Button3, dragcfact, {0} }, + { ClkClientWin, MODIFIER1, Button3, dragmfact, {0} }, { ClkStatusText, 0, Button1, spawn, {.v = statuscmd } }, { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } }, { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } }, diff --git a/options.h b/options.h index 8e26e03..9e29dbb 100644 --- a/options.h +++ b/options.h @@ -89,6 +89,7 @@ static int savefloat = 1; /* Save position of floating static int refreshrules = 1; /* Refresh rules when a CLASS or TITLE changes */ static int i3nmaster = 0; /* Enable i3-gaps like nmaster (1/0) */ static int mousemfact = 1; /* Enable adjusting mfact using the mouse (1/0) */ +static int mousecfact = 1; /* Enable adjusting cfact using the mouse (1/0) */ static float mfact = 0.50; /* Default mfact value. 0.50 = each gets half the available space */ static float lowestmfact = 0.05; /* Lowest possible mfact value on top of the existing. */ @@ -173,14 +174,14 @@ static int fullscreenhidebar = 1; /* Hide the bar when full scr static int lockfullscreen = 1; /* Window icon options */ -static int iconsize = 10; /* size of the icon */ -static int iconspacing = 5; /* spacing between the title and icon */ +static int iconsize = 10; /* Size of the icon */ +static int iconspacing = 5; /* Spacing between the title and icon */ /* Bar options */ static int barposition = 1; /* Bar position. Top: 1, Bottom: 0 */ -static int barheight = 8; /* Bar height in px, 0 = calculate automatically */ -static int barpaddingv = 10; /* Vertical bar padding in px. */ -static int barpaddingh = 10; /* Horizontal bar padding in px. */ +static int barheight = 8; /* Bar height in pixels, 0 = calculate automatically */ +static int barpaddingv = 10; /* Vertical bar padding in pixels. */ +static int barpaddingh = 10; /* Horizontal bar padding in pixels. */ /* Layout indicator options */ static int layoutposition = 1; /* Layout indicator on the left (1) or on the right (0) */ @@ -189,7 +190,7 @@ static int layoutposition = 1; /* Layout indicator on the le static int systraypinning = 0; /* Show systray on focused monitor (0) or () to pin to a specific monitor */ static int systrayonleft = 0; /* Systray position. Right: 0, Left: 1. */ static int systrayspacing = 2; /* Systray spacing in pixels */ -static int showsystray = 0; /* Show systray by default (0) or show (1) */ +static int showsystray = 0; /* Show systray by default (1) or hide (1) */ /* Tag text options */ static int underline = 0; /* Underline tags (1) or not (0) */ diff --git a/speedwm.c b/speedwm.c index bf29eef..82245bb 100644 --- a/speedwm.c +++ b/speedwm.c @@ -93,7 +93,7 @@ #define MWM_DECOR_TITLE (1 << 3) /* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { CurNormal, CurResize, CurMove, CurResizeHorzArrow, CurResizeVertArrow, CurLast }; /* cursor */ /* color schemes */ enum { SchemeNormBorder, @@ -368,6 +368,9 @@ static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); static Monitor *dirtomon(int dir); +#if USEMOUSE +static void dragmfact(const Arg *arg); +#endif static void drawbar(Monitor *m); static void drawbars(void); #if USEROUNDCORNERS @@ -1701,6 +1704,10 @@ dirtomon(int dir) void dragcfact(const Arg *arg) { + + if (!mousecfact) + return; + int prev_x, prev_y, dist_x, dist_y; float fact; Client *c; @@ -1952,6 +1959,154 @@ drawstatusbar(Monitor *m, int bh, char* stext) { return ret; } +#if USEMOUSE +void +dragmfact(const Arg *arg) +{ + + if (!mousemfact) + return; + + 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, fixed = 0; // layout configuration + double fact; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + m = selmon; + + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + + ax = m->wx; + ay = m->wy; + ah = m->wh; + aw = m->ww; + + if (!n) + return; + #if LAYOUT_CM + else if (m->lt[m->sellt]->arrange == ¢eredmaster && (fixed || n - m->nmaster > 1)) + center = 1; + #endif + #if LAYOUT_CFM + else if (m->lt[m->sellt]->arrange == ¢eredfloatingmaster) + center = 1; + #endif + #if LAYOUT_BSTACK + else if (m->lt[m->sellt]->arrange == &bstack) + horizontal = 1; + #endif + #if LAYOUT_BSTACKH + else if (m->lt[m->sellt]->arrange == &bstackhoriz) + horizontal = 1; + #endif + + /* do not allow mfact to be modified under certain conditions */ + if (!m->lt[m->sellt]->arrange // floating layout + || (!fixed && m->nmaster && n <= m->nmaster) // no master + #if LAYOUT_MONOCLE + || m->lt[m->sellt]->arrange == &monocle + #endif + #if LAYOUT_GRID + || m->lt[m->sellt]->arrange == &grid + #endif + #if LAYOUT_HGRID + || m->lt[m->sellt]->arrange == &horizgrid + #endif + #if LAYOUT_DGRID + || m->lt[m->sellt]->arrange == &dynamicgrid + #endif + #if LAYOUT_NGRID + || m->lt[m->sellt]->arrange == &nrowgrid + #endif + ) + return; + + ay += oh; + ax += ov; + aw -= 2*ov; + ah -= 2*oh; + + if (center) { + if (horizontal) { + px = ax + aw / 2; + py = ay + ah / 2 + (ah - 2*ih) * (m->mfact / 2.0) + ih / 2; + } else { // vertical split + px = ax + aw / 2 + (aw - 2*iv) * m->mfact / 2.0 + iv / 2; + py = ay + ah / 2; + } + } else if (horizontal) { + px = ax + aw / 2; + if (mirror) + py = ay + (ah - ih) * (1.0 - m->mfact) + ih / 2; + else + py = ay + ((ah - ih) * m->mfact) + ih / 2; + } else { // vertical split + if (mirror) + px = ax + (aw - iv) * (1.0 - m->mfact) + iv / 2; + else + px = ax + ((aw - iv) * m->mfact) + iv / 2; + py = ay + ah / 2; + } + + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[horizontal ? CurResizeVertArrow : CurResizeHorzArrow]->cursor, CurrentTime) != GrabSuccess) + return; + 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 (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); + + 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)); +} +#endif + void drawbar(Monitor *m) { @@ -3490,19 +3645,7 @@ resizemouse(const Arg *arg) if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) return; - - if (!mousemfact) { - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - } else { - 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) - ); - } - } + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); do { XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); @@ -3520,15 +3663,13 @@ resizemouse(const Arg *arg) nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if (!mousemfact) { - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + 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) { if (!c->isfloating && selmon->lt[selmon->sellt]->arrange && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) togglefloating(NULL); } - } if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, c->x, c->y, nw, nh, 1); @@ -3536,19 +3677,7 @@ resizemouse(const Arg *arg) } } while (ev.type != ButtonRelease); - 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 { - if (mousemfact) { - 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) - ); - } - } - + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); XUngrabPointer(dpy, CurrentTime); while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { @@ -4523,6 +4652,8 @@ setup(void) cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); cursor[CurResize] = drw_cur_create(drw, XC_sizing); cursor[CurMove] = drw_cur_create(drw, XC_fleur); + cursor[CurResizeHorzArrow] = drw_cur_create(drw, XC_sb_h_double_arrow); + cursor[CurResizeVertArrow] = drw_cur_create(drw, XC_sb_v_double_arrow); /* init appearance */ scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *)); scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], alphas[i], 3); diff --git a/toggle.h b/toggle.h index 6a1dbe4..47809db 100644 --- a/toggle.h +++ b/toggle.h @@ -43,7 +43,6 @@ Not compatible with BSDs so for those, set this to 0. */ #define LAYOUT_TILE54 1 /* Whether or not to include the 5:4 tiling layout */ #define LAYOUT_MONOCLE 1 /* Whether or not to include the monocle layout */ #define LAYOUT_GRID 1 /* Whether or not to include the grid layout */ -#define LAYOUT_GLGRID 1 /* Whether or not to include the gapless grid layout */ #define LAYOUT_FIBO 1 /* Whether or not to include the fibonacci layout */ #define LAYOUT_DWINDLE 1 /* Whether or not to include the dwindle layout */ #define LAYOUT_SPIRAL 1 /* Whether or not to include the spiral layout */