dwm

Mahdi's build of dwm
git clone git://mahdi.pw/dwm.git
Log | Files | Refs | README | LICENSE

dwm-placemouse-6.3.diff (7743B)


      1 From 399cb51f86d259d0d15d2db767d31c9e030c0528 Mon Sep 17 00:00:00 2001
      2 From: Bakkeby <[email protected]>
      3 Date: Mon, 10 Jan 2022 13:18:37 +0100
      4 Subject: [PATCH] Adding placemouse patch
      5 
      6 ---
      7  config.def.h |  12 +++-
      8  dwm.c        | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++
      9  2 files changed, 177 insertions(+), 1 deletion(-)
     10 
     11 diff --git a/config.def.h b/config.def.h
     12 index a2ac963..caaebf6 100644
     13 --- a/config.def.h
     14 +++ b/config.def.h
     15 @@ -105,7 +105,17 @@ static Button buttons[] = {
     16  	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} },
     17  	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },
     18  	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
     19 -	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} },
     20 +	/* placemouse options, choose which feels more natural:
     21 +	 *    0 - tiled position is relative to mouse cursor
     22 +	 *    1 - tiled postiion is relative to window center
     23 +	 *    2 - mouse pointer warps to window center
     24 +	 *
     25 +	 * The moveorplace uses movemouse or placemouse depending on the floating state
     26 +	 * of the selected client. Set up individual keybindings for the two if you want
     27 +	 * to control these separately (i.e. to retain the feature to move a tiled window
     28 +	 * into a floating position).
     29 +	 */
     30 +	{ ClkClientWin,         MODKEY,         Button1,        moveorplace,    {.i = 1} },
     31  	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} },
     32  	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} },
     33  	{ ClkTagBar,            0,              Button1,        view,           {0} },
     34 diff --git a/dwm.c b/dwm.c
     35 index a96f33c..5d57e18 100644
     36 --- a/dwm.c
     37 +++ b/dwm.c
     38 @@ -49,6 +49,8 @@
     39  #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
     40  #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
     41                                 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
     42 +#define INTERSECTC(x,y,w,h,z)   (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \
     43 +                               * MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y)))
     44  #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
     45  #define LENGTH(X)               (sizeof X / sizeof X[0])
     46  #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
     47 @@ -93,6 +95,7 @@ struct Client {
     48  	int bw, oldbw;
     49  	unsigned int tags;
     50  	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
     51 +	int beingmoved;
     52  	Client *next;
     53  	Client *snext;
     54  	Monitor *mon;
     55 @@ -184,10 +187,13 @@ static void maprequest(XEvent *e);
     56  static void monocle(Monitor *m);
     57  static void motionnotify(XEvent *e);
     58  static void movemouse(const Arg *arg);
     59 +static void moveorplace(const Arg *arg);
     60  static Client *nexttiled(Client *c);
     61 +static void placemouse(const Arg *arg);
     62  static void pop(Client *);
     63  static void propertynotify(XEvent *e);
     64  static void quit(const Arg *arg);
     65 +static Client *recttoclient(int x, int y, int w, int h);
     66  static Monitor *recttomon(int x, int y, int w, int h);
     67  static void resize(Client *c, int x, int y, int w, int h, int interact);
     68  static void resizeclient(Client *c, int x, int y, int w, int h);
     69 @@ -1136,6 +1142,14 @@ motionnotify(XEvent *e)
     70  	mon = m;
     71  }
     72  
     73 +void
     74 +moveorplace(const Arg *arg) {
     75 +	if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating)))
     76 +		movemouse(arg);
     77 +	else
     78 +		placemouse(arg);
     79 +}
     80 +
     81  void
     82  movemouse(const Arg *arg)
     83  {
     84 @@ -1203,6 +1217,139 @@ nexttiled(Client *c)
     85  	return c;
     86  }
     87  
     88 +void
     89 +placemouse(const Arg *arg)
     90 +{
     91 +	int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0;
     92 +	Client *c, *r = NULL, *at, *prevr;
     93 +	Monitor *m;
     94 +	XEvent ev;
     95 +	XWindowAttributes wa;
     96 +	Time lasttime = 0;
     97 +	int attachmode, prevattachmode;
     98 +	attachmode = prevattachmode = -1;
     99 +
    100 +	if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */
    101 +		return;
    102 +	if (c->isfullscreen) /* no support placing fullscreen windows by mouse */
    103 +		return;
    104 +	restack(selmon);
    105 +	prevr = c;
    106 +	if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
    107 +		None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
    108 +		return;
    109 +
    110 +	c->isfloating = 0;
    111 +	c->beingmoved = 1;
    112 +
    113 +	XGetWindowAttributes(dpy, c->win, &wa);
    114 +	ocx = wa.x;
    115 +	ocy = wa.y;
    116 +
    117 +	if (arg->i == 2) // warp cursor to client center
    118 +		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2);
    119 +
    120 +	if (!getrootptr(&x, &y))
    121 +		return;
    122 +
    123 +	do {
    124 +		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
    125 +		switch (ev.type) {
    126 +		case ConfigureRequest:
    127 +		case Expose:
    128 +		case MapRequest:
    129 +			handler[ev.type](&ev);
    130 +			break;
    131 +		case MotionNotify:
    132 +			if ((ev.xmotion.time - lasttime) <= (1000 / 60))
    133 +				continue;
    134 +			lasttime = ev.xmotion.time;
    135 +
    136 +			nx = ocx + (ev.xmotion.x - x);
    137 +			ny = ocy + (ev.xmotion.y - y);
    138 +
    139 +			if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap))
    140 +				freemove = 1;
    141 +
    142 +			if (freemove)
    143 +				XMoveWindow(dpy, c->win, nx, ny);
    144 +
    145 +			if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon)
    146 +				selmon = m;
    147 +
    148 +			if (arg->i == 1) { // tiled position is relative to the client window center point
    149 +				px = nx + wa.width / 2;
    150 +				py = ny + wa.height / 2;
    151 +			} else { // tiled position is relative to the mouse cursor
    152 +				px = ev.xmotion.x;
    153 +				py = ev.xmotion.y;
    154 +			}
    155 +
    156 +			r = recttoclient(px, py, 1, 1);
    157 +
    158 +			if (!r || r == c)
    159 +				break;
    160 +
    161 +			attachmode = 0; // below
    162 +			if (((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)) {
    163 +				if (abs(r->y - py) < r->h / 2)
    164 +					attachmode = 1; // above
    165 +			} else if (abs(r->x - px) < r->w / 2)
    166 +				attachmode = 1; // above
    167 +
    168 +			if ((r && r != prevr) || (attachmode != prevattachmode)) {
    169 +				detachstack(c);
    170 +				detach(c);
    171 +				if (c->mon != r->mon) {
    172 +					arrangemon(c->mon);
    173 +					c->tags = r->mon->tagset[r->mon->seltags];
    174 +				}
    175 +
    176 +				c->mon = r->mon;
    177 +				r->mon->sel = r;
    178 +
    179 +				if (attachmode) {
    180 +					if (r == r->mon->clients)
    181 +						attach(c);
    182 +					else {
    183 +						for (at = r->mon->clients; at->next != r; at = at->next);
    184 +						c->next = at->next;
    185 +						at->next = c;
    186 +					}
    187 +				} else {
    188 +					c->next = r->next;
    189 +					r->next = c;
    190 +				}
    191 +
    192 +				attachstack(c);
    193 +				arrangemon(r->mon);
    194 +				prevr = r;
    195 +				prevattachmode = attachmode;
    196 +			}
    197 +			break;
    198 +		}
    199 +	} while (ev.type != ButtonRelease);
    200 +	XUngrabPointer(dpy, CurrentTime);
    201 +
    202 +	if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) {
    203 +		detach(c);
    204 +		detachstack(c);
    205 +		arrangemon(c->mon);
    206 +		c->mon = m;
    207 +		c->tags = m->tagset[m->seltags];
    208 +		attach(c);
    209 +		attachstack(c);
    210 +		selmon = m;
    211 +	}
    212 +
    213 +	focus(c);
    214 +	c->beingmoved = 0;
    215 +
    216 +	if (nx != -9999)
    217 +		resize(c, nx, ny, c->w, c->h, 0);
    218 +	arrangemon(c->mon);
    219 +}
    220 +
    221  void
    222  pop(Client *c)
    223  {
    224 @@ -1255,6 +1402,21 @@ quit(const Arg *arg)
    225  	running = 0;
    226  }
    227  
    228 +Client *
    229 +recttoclient(int x, int y, int w, int h)
    230 +{
    231 +	Client *c, *r = NULL;
    232 +	int a, area = 0;
    233 +
    234 +	for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) {
    235 +		if ((a = INTERSECTC(x, y, w, h, c)) > area) {
    236 +			area = a;
    237 +			r = c;
    238 +		}
    239 +	}
    240 +	return r;
    241 +}
    242 +
    243  Monitor *
    244  recttomon(int x, int y, int w, int h)
    245  {
    246 @@ -1285,6 +1447,10 @@ resizeclient(Client *c, int x, int y, int w, int h)
    247  	c->oldy = c->y; c->y = wc.y = y;
    248  	c->oldw = c->w; c->w = wc.width = w;
    249  	c->oldh = c->h; c->h = wc.height = h;
    250 +
    251 +	if (c->beingmoved)
    252 +		return;
    253 +
    254  	wc.border_width = c->bw;
    255  	XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
    256  	configure(c);
    257 -- 
    258 2.19.1
    259