implement dragmfact properly

This commit is contained in:
speediegq 2022-10-11 14:01:22 +02:00
parent 69f32740b9
commit d6869e6303
5 changed files with 171 additions and 40 deletions

View file

@ -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

View file

@ -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 } },

View file

@ -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 (<monitor number>) 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) */

185
speedwm.c
View file

@ -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 == &centeredmaster && (fixed || n - m->nmaster > 1))
center = 1;
#endif
#if LAYOUT_CFM
else if (m->lt[m->sellt]->arrange == &centeredfloatingmaster)
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)
);
}
}
do {
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
@ -3520,7 +3663,6 @@ 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
&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
{
@ -3528,7 +3670,6 @@ resizemouse(const Arg *arg)
&& (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)
);
}
}
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);

View file

@ -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 */