I'm posting these in the hope that someone finds them useful.  Sorry
if they've been done before.

tilemovemouse() lets you drag a client to a different position WITHOUT
floating it.  Reordering windows this way is fun.

buttonkillclient() runs killclient() and then hides all pointer events
from the remaining clients until all buttons are released.  It's
useful if you want to bind a mouse button on ClkClientWin to
killclient - without my wrapper, the pointer grab is lost when the
client dies, so the ButtonRelease gets sent to some other client.  If
you use button 2 for this, something embarrassing might get pasted
into a chat window :-).

Perhaps this could somehow be solved in grabbuttons() instead. I don't know.

I use them with hg tip, which is dwm 5.5 or 5.4 or something.
void
insertbefore(Client *a, Client *b)	/* insert a before b in the client list */
{
	Client **x = &clients;
	
	while(*x != b && *x)
		x = & (*x)->next;
	*x = a;
	a->next = b;
}

void
insertafter(Client *a, Client *b)	/* insert a after b in the client list */
{
	a->next = b->next;
	b->next = a;
}

void
tilemovemouse(const Arg *arg) {
	/* Could EnterNotify events be used instead? */
	Client *c, *d;
	XEvent ev;
	int x, y;
	Bool after;

	if(!(c = sel))
		return;
	if(c->isfloating || !lt[sellt]->arrange){
		movemouse(NULL);
		return;
	}
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
	None, cursor[CurMove], CurrentTime) != GrabSuccess)
		return;
	do {
		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
		switch (ev.type) {
		case ConfigureRequest:
		case Expose:
		case MapRequest:
			handler[ev.type](&ev);
			break;
		case MotionNotify:
			x = ev.xmotion.x;
			y = ev.xmotion.y;
			after = False;
			for(d = nexttiled(clients); d; d = nexttiled(d->next)){
				if(d == c)
					after = True;
				else if(INRECT(x, y, d->x, d->y, d->w+2*borderpx, d->h+2*borderpx)){
					detach(c);
					after ? insertafter(c, d) : insertbefore(c,d);
					arrange();
					break;
				}
			}
		}
	} while(ev.type != ButtonRelease);
	XUngrabPointer(dpy, CurrentTime);
}
#define NBUTTONS(m) (!!(m&Button1Mask)+!!(m&Button2Mask)+!!(m&Button3Mask)+!!(m&Button4Mask)+!!(m&Button5Mask))

/* or, equivalently:
int
nbuttons(int mask)
{
	int i = 0;
	
	if(m & Button1Mask) ++i;
	if(m & Button2Mask) ++i;
	if(m & Button3Mask) ++i;
	if(m & Button4Mask) ++i;
	if(m & Button5Mask) ++i;
	return i;
}
*/

void
buttonkillclient(const Arg *arg)
{
	XEvent ev;
	
	if(XGrabPointer(dpy, root, False, BUTTONMASK, GrabModeAsync, GrabModeAsync,
	None, None, CurrentTime) != GrabSuccess)
		return;
	killclient(NULL);
	for(;;) {
		XNextEvent(dpy, &ev);
		if(ev.type == ButtonRelease && NBUTTONS(ev.xbutton.state) == 1)
			break;
		if(handler[ev.type])
			handler[ev.type](&ev);
	}
	XUngrabPointer(dpy, CurrentTime);
}

Reply via email to