I forward X halfway around the world and the mouse move/resize as implemented
in dwm brings things to a screeching halt.
I noticed that the non-solid move/resize in evilwm works much better because
it doesn't demand the client to redraw a billion times as you drag the mouse
because it just draws a wire frame of the window as you drag.
I have included a patch for dwm-5.8.2 in which I basically stole the wire
frame move/resize code from evilwm and adapted it for dwm.
If anyone is interested I'll do a patch for a more modern release.
diff -up dwm-5.8.2/dwm.c dwm-5.8.2-wired/dwm.c
--- dwm-5.8.2/dwm.c 2010-06-04 06:39:15.000000000 -0400
+++ dwm-5.8.2-wired/dwm.c 2012-06-01 22:58:02.000000000 -0400
@@ -101,6 +101,7 @@ typedef struct {
unsigned long sel[ColLast];
Drawable drawable;
GC gc;
+ GC invert_gc;
struct {
int ascent;
int descent;
@@ -177,6 +178,7 @@ static void drawbar(Monitor *m);
static void drawbars(void);
static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long
col[ColLast]);
static void drawtext(const char *text, unsigned long col[ColLast], Bool
invert);
+static void draw_outline(int x, int y, int w, int h, int bw);
static void enternotify(XEvent *e);
static void expose(XEvent *e);
static void focus(Client *c);
@@ -489,6 +491,7 @@ cleanup(void) {
XUngrabKey(dpy, AnyKey, AnyModifier, root);
XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc);
+ XFreeGC(dpy, dc.invert_gc);
XFreeCursor(dpy, cursor[CurNormal]);
XFreeCursor(dpy, cursor[CurResize]);
XFreeCursor(dpy, cursor[CurMove]);
@@ -787,6 +790,11 @@ drawtext(const char *text, unsigned long
else
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
+void draw_outline(int x, int y, int w, int h, int bw) {
+ XDrawRectangle(dpy, root, dc.invert_gc,
+ x-bw, y-bw,
+ w+2*bw-1, h+2*bw-1);
+}
void
enternotify(XEvent *e) {
@@ -1194,7 +1202,7 @@ monocle(Monitor *m) {
void
movemouse(const Arg *arg) {
- int x, y, ocx, ocy, nx, ny;
+ int x, y, ocx, ocy, nx, ny, first;
Client *c;
Monitor *m;
XEvent ev;
@@ -1202,13 +1210,14 @@ movemouse(const Arg *arg) {
if(!(c = selmon->sel))
return;
restack(selmon);
- ocx = c->x;
- ocy = c->y;
+ nx = ocx = c->x;
+ ny = ocy = c->y;
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync,
GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess)
return;
if(!getrootptr(&x, &y))
return;
+ first=1;
do {
XMaskEvent(dpy,
MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
switch (ev.type) {
@@ -1218,6 +1227,10 @@ movemouse(const Arg *arg) {
handler[ev.type](&ev);
break;
case MotionNotify:
+ if (!first) {
+ draw_outline(nx, ny, c->w, c->h, c->bw); /*
clear */
+ XUngrabServer(dpy);
+ }
nx = ocx + (ev.xmotion.x - x);
ny = ocy + (ev.xmotion.y - y);
if(snap && nx >= selmon->wx && nx <= selmon->wx +
selmon->ww
@@ -1234,11 +1247,20 @@ movemouse(const Arg *arg) {
&& (abs(nx - c->x) > snap || abs(ny - c->y) >
snap))
togglefloating(NULL);
}
- if(!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, nx, ny, c->w, c->h, True);
+ if(!selmon->lt[selmon->sellt]->arrange ||
c->isfloating) {
+ if (!first) XSync(dpy, False);
+ XGrabServer(dpy);
+ draw_outline(nx, ny, c->w, c->h, c->bw);
+ first=0;
+ }
break;
}
} while(ev.type != ButtonRelease);
+ if (!first) {
+ draw_outline(nx, ny, c->w, c->h, c->bw); /* clear */
+ XUngrabServer(dpy);
+ if (nx != ocx || ny != ocy) resize(c, nx, ny, c->w, c->h, True);
+ }
XUngrabPointer(dpy, CurrentTime);
if((m = ptrtomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) {
sendmon(c, m);
@@ -1357,7 +1379,7 @@ resizeclient(Client *c, int x, int y, in
void
resizemouse(const Arg *arg) {
- int ocx, ocy;
+ int ocx, ocy, ocw, och, first;
int nw, nh;
Client *c;
Monitor *m;
@@ -1368,10 +1390,13 @@ resizemouse(const Arg *arg) {
restack(selmon);
ocx = c->x;
ocy = c->y;
+ ocw = nw = c->w;
+ och = nh = c->h;
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync,
GrabModeAsync,
None, cursor[CurResize], CurrentTime) != GrabSuccess)
return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h +
c->bw - 1);
+ first=1;
do {
XMaskEvent(dpy,
MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
switch(ev.type) {
@@ -1381,6 +1406,10 @@ resizemouse(const Arg *arg) {
handler[ev.type](&ev);
break;
case MotionNotify:
+ if (!first) {
+ draw_outline(c->x, c->y, nw, nh, c->bw); /*
clear */
+ XUngrabServer(dpy);
+ }
nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
if(snap && nw >= selmon->wx && nw <= selmon->wx +
selmon->ww
@@ -1390,11 +1419,20 @@ 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, True);
+ if(!selmon->lt[selmon->sellt]->arrange ||
c->isfloating) {
+ if (!first) XSync(dpy, False);
+ XGrabServer(dpy);
+ draw_outline(c->x, c->y, nw, nh, c->bw);
+ first=0;
+ }
break;
}
} while(ev.type != ButtonRelease);
+ if (!first) {
+ draw_outline(c->x, c->y, nw, nh, c->bw); /* clear */
+ XUngrabServer(dpy);
+ if (nw != ocw || nh != och) resize(c, c->x, c->y, nw, nh, True);
+ }
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));
@@ -1519,6 +1557,7 @@ setmfact(const Arg *arg) {
void
setup(void) {
XSetWindowAttributes wa;
+ XGCValues gv;
/* clean up any zombies immediately */
sigchld(0);
@@ -1552,6 +1591,12 @@ setup(void) {
dc.sel[ColFG] = getcolor(selfgcolor);
dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh,
DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, NULL);
+
+ gv.function = GXinvert;
+ gv.subwindow_mode = IncludeInferiors;
+ gv.line_width = 1; /* opt_bw */
+ dc.invert_gc = XCreateGC(dpy, root, GCFunction | GCSubwindowMode |
GCLineWidth, &gv);
+
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);