You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
3.4 KiB
153 lines
3.4 KiB
void |
|
moveorplace(const Arg *arg) { |
|
if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating))) |
|
movemouse(arg); |
|
else |
|
placemouse(arg); |
|
} |
|
|
|
void |
|
placemouse(const Arg *arg) |
|
{ |
|
int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0; |
|
Client *c, *r = NULL, *at, *prevr; |
|
Monitor *m; |
|
XEvent ev; |
|
XWindowAttributes wa; |
|
Time lasttime = 0; |
|
int attachmode, prevattachmode; |
|
attachmode = prevattachmode = -1; |
|
|
|
if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */ |
|
return; |
|
if (c->isfullscreen) /* no support placing fullscreen windows by mouse */ |
|
return; |
|
restack(selmon); |
|
prevr = c; |
|
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
|
None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) |
|
return; |
|
|
|
c->isfloating = 0; |
|
c->beingmoved = 1; |
|
|
|
XGetWindowAttributes(dpy, c->win, &wa); |
|
ocx = wa.x; |
|
ocy = wa.y; |
|
|
|
if (arg->i == 2) // warp cursor to client center |
|
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2); |
|
|
|
if (!getrootptr(&x, &y)) |
|
return; |
|
|
|
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 / 60)) |
|
continue; |
|
lasttime = ev.xmotion.time; |
|
|
|
nx = ocx + (ev.xmotion.x - x); |
|
ny = ocy + (ev.xmotion.y - y); |
|
|
|
if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap)) |
|
freemove = 1; |
|
|
|
if (freemove) |
|
XMoveWindow(dpy, c->win, nx, ny); |
|
|
|
if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon) |
|
selmon = m; |
|
|
|
if (arg->i == 1) { // tiled position is relative to the client window center point |
|
px = nx + wa.width / 2; |
|
py = ny + wa.height / 2; |
|
} else { // tiled position is relative to the mouse cursor |
|
px = ev.xmotion.x; |
|
py = ev.xmotion.y; |
|
} |
|
|
|
r = recttoclient(px, py, 1, 1); |
|
|
|
if (!r || r == c) |
|
break; |
|
|
|
if ((((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w) |
|
&& (abs(r->y - py) < r->h / 2)) || (abs(r->x - px) < r->w / 2)) |
|
attachmode = 1; // above |
|
else |
|
attachmode = 0; // below |
|
|
|
if ((r && r != prevr) || (attachmode != prevattachmode)) { |
|
detachstack(c); |
|
detach(c); |
|
if (c->mon != r->mon) |
|
arrangemon(c->mon); |
|
|
|
c->mon = r->mon; |
|
r->mon->sel = r; |
|
|
|
if (attachmode) { |
|
if (r == r->mon->clients) |
|
attach(c); |
|
else { |
|
for (at = r->mon->clients; at->next != r; at = at->next); |
|
c->next = at->next; |
|
at->next = c; |
|
} |
|
} else { |
|
c->next = r->next; |
|
r->next = c; |
|
} |
|
|
|
attachstack(c); |
|
arrangemon(r->mon); |
|
prevr = r; |
|
prevattachmode = attachmode; |
|
} |
|
break; |
|
} |
|
} while (ev.type != ButtonRelease); |
|
XUngrabPointer(dpy, CurrentTime); |
|
|
|
if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) { |
|
detach(c); |
|
detachstack(c); |
|
arrangemon(c->mon); |
|
c->mon = m; |
|
c->tags = m->tagset[m->seltags]; |
|
attach(c); |
|
attachstack(c); |
|
selmon = m; |
|
} |
|
|
|
focus(c); |
|
c->beingmoved = 0; |
|
|
|
if (nx != -9999) |
|
resize(c, nx, ny, c->w, c->h, 0); |
|
arrangemon(c->mon); |
|
} |
|
|
|
Client * |
|
recttoclient(int x, int y, int w, int h) |
|
{ |
|
Client *c, *r = NULL; |
|
int a, area = 0; |
|
|
|
for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) { |
|
if ((a = INTERSECTC(x, y, w, h, c)) > area) { |
|
area = a; |
|
r = c; |
|
} |
|
} |
|
return r; |
|
} |
|
|
|
|