sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-movestackmouse-20260929-44dbc68.diff (4423B)


      1 From cf83ca2326c9ea6dffa0757fb4805d1f33cfa207 Mon Sep 17 00:00:00 2001
      2 From: Niky Kovalski <nikykovalski@gmail.com>
      3 Date: Tue, 29 Sep 2026 01:10:41 -0400
      4 Subject: [PATCH] movestackmouse
      5 
      6 Move focused window while dragging. Tiled windows will not be toggled to
      7 the floating state.
      8 ---
      9  config.def.h |  1 +
     10  dwm.1        |  3 ++
     11  dwm.c        | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++
     12  3 files changed, 86 insertions(+)
     13 
     14 diff --git a/config.def.h b/config.def.h
     15 index 81c3fc0..206261b 100644
     16 --- a/config.def.h
     17 +++ b/config.def.h
     18 @@ -107,6 +107,7 @@ static const Button buttons[] = {
     19  	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },
     20  	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
     21  	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} },
     22 +	{ ClkClientWin,    MODKEY|ShiftMask,    Button1,        movestackmouse, {0} },
     23  	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} },
     24  	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} },
     25  	{ ClkTagBar,            0,              Button1,        view,           {0} },
     26 diff --git a/dwm.1 b/dwm.1
     27 index ddc8321..de4bf91 100644
     28 --- a/dwm.1
     29 +++ b/dwm.1
     30 @@ -144,6 +144,9 @@ Add/remove all windows with nth tag to/from the view.
     31  Quit dwm.
     32  .SS Mouse commands
     33  .TP
     34 +.B Mod1\-Shift\-Button1
     35 +Move focused window while dragging. Tiled windows will not be toggled to the floating state.
     36 +.TP
     37  .B Mod1\-Button1
     38  Move focused window while dragging. Tiled windows will be toggled to the floating state.
     39  .TP
     40 diff --git a/dwm.c b/dwm.c
     41 index ab3a84c..3e9229e 100644
     42 --- a/dwm.c
     43 +++ b/dwm.c
     44 @@ -146,6 +146,8 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
     45  static void arrange(Monitor *m);
     46  static void arrangemon(Monitor *m);
     47  static void attach(Client *c);
     48 +static void attachafter(Client *c, Client *t);
     49 +static void attachbefore(Client *c, Client *t);
     50  static void attachstack(Client *c);
     51  static void buttonpress(XEvent *e);
     52  static void checkotherwm(void);
     53 @@ -183,6 +185,7 @@ static void maprequest(XEvent *e);
     54  static void monocle(Monitor *m);
     55  static void motionnotify(XEvent *e);
     56  static void movemouse(const Arg *arg);
     57 +static void movestackmouse(const Arg *arg);
     58  static Client *nexttiled(Client *c);
     59  static void pop(Client *c);
     60  static void propertynotify(XEvent *e);
     61 @@ -407,6 +410,25 @@ attach(Client *c)
     62  	c->mon->clients = c;
     63  }
     64  
     65 +void
     66 +attachafter(Client *c, Client *t)
     67 +{
     68 +	c->next = t->next;
     69 +	t->next = c;
     70 +}
     71 +
     72 +void
     73 +attachbefore(Client *c, Client *t)
     74 +{
     75 +	Client **tc;
     76 +
     77 +	for (tc = &t->mon->clients; *tc && *tc != t; tc = &(*tc)->next);
     78 +	if (*tc)
     79 +		c->next = (*tc)->next;
     80 +	c->next = *tc;
     81 +	*tc = c;
     82 +}
     83 +
     84  void
     85  attachstack(Client *c)
     86  {
     87 @@ -1202,6 +1224,66 @@ movemouse(const Arg *arg)
     88  	}
     89  }
     90  
     91 +void
     92 +movestackmouse(const Arg *arg)
     93 +{
     94 +	Client *c, *t;
     95 +	Monitor *m;
     96 +	XEvent ev;
     97 +	Time lasttime = 0;
     98 +	int isfound = 0;
     99 +
    100 +	if (!(c = selmon->sel))
    101 +		return;
    102 +	if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
    103 +		return;
    104 +	if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { /* fallback to movemouse */
    105 +		movemouse(NULL);
    106 +		return;
    107 +	}
    108 +	if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
    109 +		None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
    110 +		return;
    111 +	do {
    112 +		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
    113 +		switch(ev.type) {
    114 +		case ConfigureRequest:
    115 +		case Expose:
    116 +		case MapRequest:
    117 +			handler[ev.type](&ev);
    118 +			break;
    119 +		case MotionNotify:
    120 +			if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate))
    121 +				continue;
    122 +			lasttime = ev.xmotion.time;
    123 +			isfound = 0;
    124 +
    125 +			for (t = nexttiled(c->mon->clients); t; t = nexttiled(t->next)) {
    126 +				if (t == c) {
    127 +					isfound = 1;
    128 +					continue;
    129 +				}
    130 +				if (ev.xmotion.x_root >= t->x &&
    131 +					ev.xmotion.x_root < t->x + t->w + 2 * t->bw &&
    132 +					ev.xmotion.y_root >= t->y &&
    133 +					ev.xmotion.y_root < t->y + t->h + 2 * t->bw) {
    134 +						detach(c);
    135 +						isfound ? attachafter(c, t) : attachbefore(c, t);
    136 +						focus(c);
    137 +						arrange(c->mon);
    138 +						break;
    139 +				}
    140 +			}
    141 +			break;
    142 +		}
    143 +	} while (ev.type != ButtonRelease);
    144 +	XUngrabPointer(dpy, CurrentTime);
    145 +	if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
    146 +		selmon = m;
    147 +		focus(NULL);
    148 +	}
    149 +}
    150 +
    151  Client *
    152  nexttiled(Client *c)
    153  {
    154 -- 
    155 2.55.0
    156