2019-12-02 18:23:00 +00:00
|
|
|
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <X11/X.h>
|
|
|
|
#include <X11/Xos.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include "dat.h"
|
|
|
|
#include "fns.h"
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
nobuttons(XButtonEvent* e) /* Einstuerzende */
|
2019-12-02 18:23:00 +00:00
|
|
|
{
|
2021-02-26 18:01:22 +00:00
|
|
|
int state;
|
2019-12-02 18:23:00 +00:00
|
|
|
|
2021-02-26 18:01:22 +00:00
|
|
|
state = (e->state & AllButtonMask);
|
|
|
|
return (e->type == ButtonRelease) && (state & (state - 1)) == 0;
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
grab(Window w, Window constrain, int mask, Cursor curs, int t) {
|
|
|
|
int status;
|
2019-12-02 18:23:00 +00:00
|
|
|
|
2021-02-26 18:01:22 +00:00
|
|
|
if (t == 0) t = timestamp();
|
|
|
|
status = XGrabPointer(
|
|
|
|
dpy, w, False, mask, GrabModeAsync, GrabModeAsync, constrain, curs, t);
|
|
|
|
return status;
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-02-26 18:01:22 +00:00
|
|
|
ungrab(XButtonEvent* e) {
|
|
|
|
XEvent ev;
|
|
|
|
|
|
|
|
if (!nobuttons(e))
|
|
|
|
for (;;) {
|
|
|
|
XMaskEvent(dpy, ButtonMask | ButtonMotionMask, &ev);
|
|
|
|
if (ev.type == MotionNotify) continue;
|
|
|
|
e = &ev.xbutton;
|
|
|
|
if (nobuttons(e)) break;
|
|
|
|
}
|
|
|
|
XUngrabPointer(dpy, e->time);
|
|
|
|
curtime = e->time;
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-26 18:01:22 +00:00
|
|
|
drawstring(
|
|
|
|
Display* dpy, ScreenInfo* s, Menu* m, int wide, int high, int i,
|
|
|
|
int selected) {
|
|
|
|
int tx, ty;
|
|
|
|
|
|
|
|
tx = (wide - XTextWidth(font, m->item[i], strlen(m->item[i]))) / 2;
|
|
|
|
ty = i * high + font->ascent + 1;
|
|
|
|
XFillRectangle(
|
|
|
|
dpy,
|
|
|
|
s->menuwin,
|
|
|
|
selected ? s->gcmenubgs : s->gcmenubg,
|
|
|
|
0,
|
|
|
|
i * high,
|
|
|
|
wide,
|
|
|
|
high);
|
|
|
|
XDrawString(
|
|
|
|
dpy,
|
|
|
|
s->menuwin,
|
|
|
|
selected ? s->gcmenufgs : s->gcmenufg,
|
|
|
|
tx,
|
|
|
|
ty,
|
|
|
|
m->item[i],
|
|
|
|
strlen(m->item[i]));
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
menuhit(XButtonEvent* e, Menu* m) {
|
|
|
|
XEvent ev;
|
|
|
|
int i, n, cur, old, wide, high, status, drawn, warp;
|
|
|
|
int x, y, dx, dy, xmax, ymax;
|
|
|
|
ScreenInfo* s;
|
|
|
|
|
|
|
|
if (font == 0) return -1;
|
|
|
|
s = getscreen(e->root);
|
|
|
|
if (s == 0 || e->window == s->menuwin) /* ugly event mangling */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
dx = 0;
|
|
|
|
for (n = 0; m->item[n]; n++) {
|
|
|
|
wide = XTextWidth(font, m->item[n], strlen(m->item[n])) + 4;
|
|
|
|
if (wide > dx) dx = wide;
|
|
|
|
}
|
|
|
|
wide = dx;
|
|
|
|
cur = m->lasthit;
|
|
|
|
if (cur >= n) cur = n - 1;
|
|
|
|
|
|
|
|
high = font->ascent + font->descent + 1;
|
|
|
|
dy = n * high;
|
|
|
|
x = e->x - wide / 2;
|
|
|
|
y = e->y - cur * high - high / 2;
|
|
|
|
warp = 0;
|
|
|
|
xmax = DisplayWidth(dpy, s->num);
|
|
|
|
ymax = DisplayHeight(dpy, s->num);
|
|
|
|
if (x < 0) {
|
|
|
|
e->x -= x;
|
|
|
|
x = 0;
|
|
|
|
warp++;
|
|
|
|
}
|
|
|
|
if (x + wide >= xmax) {
|
|
|
|
e->x -= x + wide - xmax;
|
|
|
|
x = xmax - wide;
|
|
|
|
warp++;
|
|
|
|
}
|
|
|
|
if (y < 0) {
|
|
|
|
e->y -= y;
|
|
|
|
y = 0;
|
|
|
|
warp++;
|
|
|
|
}
|
|
|
|
if (y + dy >= ymax) {
|
|
|
|
e->y -= y + dy - ymax;
|
|
|
|
y = ymax - dy;
|
|
|
|
warp++;
|
|
|
|
}
|
|
|
|
if (warp) setmouse(e->x, e->y, s);
|
|
|
|
XMoveResizeWindow(dpy, s->menuwin, x, y, dx, dy);
|
|
|
|
XSelectInput(dpy, s->menuwin, MenuMask);
|
|
|
|
XMapRaised(dpy, s->menuwin);
|
|
|
|
status = grab(s->menuwin, None, MenuGrabMask, None, e->time);
|
|
|
|
if (status != GrabSuccess) {
|
|
|
|
/* graberror("menuhit", status); */
|
|
|
|
XUnmapWindow(dpy, s->menuwin);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
drawn = 0;
|
|
|
|
for (;;) {
|
|
|
|
XMaskEvent(dpy, MenuMask, &ev);
|
|
|
|
switch (ev.type) {
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "ryudo: menuhit: unknown ev.type %d\n", ev.type);
|
|
|
|
break;
|
|
|
|
case ButtonPress: break;
|
|
|
|
case ButtonRelease:
|
|
|
|
if (ev.xbutton.button != e->button) break;
|
|
|
|
x = ev.xbutton.x;
|
|
|
|
y = ev.xbutton.y;
|
|
|
|
i = y / high;
|
|
|
|
if (cur >= 0 && y >= cur * high - 3 && y < (cur + 1) * high + 3)
|
|
|
|
i = cur;
|
|
|
|
if (x < 0 || x > wide || y < -3)
|
|
|
|
i = -1;
|
|
|
|
else if (i < 0 || i >= n)
|
|
|
|
i = -1;
|
|
|
|
else
|
|
|
|
m->lasthit = i;
|
|
|
|
if (!nobuttons(&ev.xbutton)) i = -1;
|
|
|
|
ungrab(&ev.xbutton);
|
|
|
|
XUnmapWindow(dpy, s->menuwin);
|
|
|
|
return i;
|
|
|
|
case MotionNotify:
|
|
|
|
if (!drawn) break;
|
|
|
|
x = ev.xbutton.x;
|
|
|
|
y = ev.xbutton.y;
|
|
|
|
old = cur;
|
|
|
|
cur = y / high;
|
|
|
|
if (old >= 0 && y >= old * high - 3 && y < (old + 1) * high + 3)
|
|
|
|
cur = old;
|
|
|
|
if (x < 0 || x > wide || y < -3)
|
|
|
|
cur = -1;
|
|
|
|
else if (cur < 0 || cur >= n)
|
|
|
|
cur = -1;
|
|
|
|
if (cur == old) break;
|
|
|
|
if (old >= 0 && old < n) drawstring(dpy, s, m, wide, high, old, 0);
|
|
|
|
if (cur >= 0 && cur < n) drawstring(dpy, s, m, wide, high, cur, 1);
|
|
|
|
break;
|
|
|
|
case Expose:
|
|
|
|
XClearWindow(dpy, s->menuwin);
|
|
|
|
for (i = 0; i < n; i++) drawstring(dpy, s, m, wide, high, i, cur == i);
|
|
|
|
drawn = 1;
|
|
|
|
}
|
|
|
|
}
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
2021-02-26 18:01:22 +00:00
|
|
|
Client*
|
|
|
|
selectwin(int release, int* shift, ScreenInfo* s) {
|
|
|
|
XEvent ev;
|
|
|
|
XButtonEvent* e;
|
|
|
|
int status;
|
|
|
|
Window w;
|
|
|
|
Client* c;
|
|
|
|
|
|
|
|
status = grab(s->root, s->root, ButtonMask, s->target, 0);
|
|
|
|
if (status != GrabSuccess) {
|
|
|
|
graberror("selectwin", status); /* */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
w = None;
|
|
|
|
for (;;) {
|
|
|
|
XMaskEvent(dpy, ButtonMask, &ev);
|
|
|
|
e = &ev.xbutton;
|
|
|
|
switch (ev.type) {
|
|
|
|
case ButtonPress:
|
|
|
|
if (e->button != Button3) {
|
|
|
|
ungrab(e);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
w = e->subwindow;
|
|
|
|
if (!release) {
|
|
|
|
c = getclient(w, 0);
|
|
|
|
if (c == 0) ungrab(e);
|
|
|
|
if (shift != 0) *shift = (e->state & ShiftMask) != 0;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ButtonRelease:
|
|
|
|
ungrab(e);
|
|
|
|
if (e->button != Button3 || e->subwindow != w) return 0;
|
|
|
|
if (shift != 0) *shift = (e->state & ShiftMask) != 0;
|
|
|
|
return getclient(w, 0);
|
|
|
|
}
|
|
|
|
}
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
sweepcalc(Client* c, int x, int y, BorderOrient bl, int ignored) {
|
|
|
|
int dx, dy, sx, sy;
|
|
|
|
|
|
|
|
dx = x - c->x;
|
|
|
|
dy = y - c->y;
|
|
|
|
sx = sy = 1;
|
|
|
|
x += dx;
|
|
|
|
if (dx < 0) {
|
|
|
|
dx = -dx;
|
|
|
|
sx = -1;
|
|
|
|
}
|
|
|
|
y += dy;
|
|
|
|
if (dy < 0) {
|
|
|
|
dy = -dy;
|
|
|
|
sy = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
dx -= 2 * BORDER;
|
|
|
|
dy -= 2 * BORDER;
|
|
|
|
|
|
|
|
if (!c->is9term) {
|
|
|
|
if (dx < c->min_dx) dx = c->min_dx;
|
|
|
|
if (dy < c->min_dy) dy = c->min_dy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c->size.flags & PResizeInc) {
|
|
|
|
dx = c->min_dx + (dx - c->min_dx) / c->size.width_inc * c->size.width_inc;
|
|
|
|
dy = c->min_dy + (dy - c->min_dy) / c->size.height_inc * c->size.height_inc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c->size.flags & PMaxSize) {
|
|
|
|
if (dx > c->size.max_width) dx = c->size.max_width;
|
|
|
|
if (dy > c->size.max_height) dy = c->size.max_height;
|
|
|
|
}
|
|
|
|
c->dx = sx * (dx + 2 * BORDER);
|
|
|
|
c->dy = sy * (dy + 2 * BORDER);
|
|
|
|
|
|
|
|
return ignored;
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
dragcalc(Client* c, int x, int y, BorderOrient bl, int ignored) {
|
|
|
|
c->x += x;
|
|
|
|
c->y += y;
|
2019-12-02 18:23:00 +00:00
|
|
|
|
2021-02-26 18:01:22 +00:00
|
|
|
return ignored;
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
pullcalc(Client* c, int x, int y, BorderOrient bl, int init) {
|
|
|
|
int dx, dy, sx, sy, px, py, spx, spy, rdx, rdy, xoff, yoff, xcorn, ycorn;
|
|
|
|
|
|
|
|
px = c->x;
|
|
|
|
py = c->y;
|
|
|
|
dx = c->dx;
|
|
|
|
dy = c->dy;
|
|
|
|
sx = sy = 1;
|
|
|
|
spx = spy = 0;
|
|
|
|
xoff = yoff = 0;
|
|
|
|
xcorn = ycorn = 0;
|
|
|
|
|
|
|
|
switch (bl) {
|
|
|
|
case BorderN:
|
|
|
|
py = y;
|
|
|
|
dy = (c->y + c->dy) - y;
|
|
|
|
spy = 1;
|
|
|
|
yoff = y - c->y;
|
|
|
|
break;
|
|
|
|
case BorderS:
|
|
|
|
dy = y - c->y;
|
|
|
|
yoff = (c->y + c->dy) - y;
|
|
|
|
break;
|
|
|
|
case BorderE:
|
|
|
|
dx = x - c->x;
|
|
|
|
xoff = (c->x + c->dx) - x;
|
|
|
|
break;
|
|
|
|
case BorderW:
|
|
|
|
px = x;
|
|
|
|
dx = (c->x + c->dx) - x;
|
|
|
|
spx = 1;
|
|
|
|
xoff = x - c->x;
|
|
|
|
break;
|
|
|
|
case BorderNNW:
|
|
|
|
case BorderWNW:
|
|
|
|
px = x;
|
|
|
|
dx = (c->x + c->dx) - x;
|
|
|
|
spx = 1;
|
|
|
|
py = y;
|
|
|
|
dy = (c->y + c->dy) - y;
|
|
|
|
spy = 1;
|
|
|
|
xoff = x - c->x;
|
|
|
|
yoff = y - c->y;
|
|
|
|
break;
|
|
|
|
case BorderNNE:
|
|
|
|
case BorderENE:
|
|
|
|
dx = x - c->x;
|
|
|
|
py = y;
|
|
|
|
dy = (c->y + c->dy) - y;
|
|
|
|
spy = 1;
|
|
|
|
xoff = (c->x + c->dx) - x;
|
|
|
|
yoff = y - c->y;
|
|
|
|
break;
|
|
|
|
case BorderSSE:
|
|
|
|
case BorderESE:
|
|
|
|
dx = x - c->x;
|
|
|
|
dy = y - c->y;
|
|
|
|
xoff = (c->x + c->dx) - x;
|
|
|
|
yoff = (c->y + c->dy) - y;
|
|
|
|
break;
|
|
|
|
case BorderSSW:
|
|
|
|
case BorderWSW:
|
|
|
|
px = x;
|
|
|
|
dx = (c->x + c->dx) - x;
|
|
|
|
spx = 1;
|
|
|
|
dy = y - c->y;
|
|
|
|
xoff = x - c->x;
|
|
|
|
yoff = (c->y + c->dy) - y;
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
switch (bl) {
|
|
|
|
case BorderNNW:
|
|
|
|
case BorderNNE:
|
|
|
|
case BorderSSW:
|
|
|
|
case BorderSSE: xcorn = 1; break;
|
|
|
|
case BorderWNW:
|
|
|
|
case BorderENE:
|
|
|
|
case BorderWSW:
|
|
|
|
case BorderESE: ycorn = 1; break;
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!init || xoff < 0 || (xcorn && xoff > CORNER) ||
|
|
|
|
(!xcorn && xoff > BORDER) || yoff < 0 || (ycorn && yoff > CORNER) ||
|
|
|
|
(!ycorn && yoff > BORDER)) {
|
|
|
|
xoff = 0;
|
|
|
|
yoff = 0;
|
|
|
|
init = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (debug)
|
|
|
|
fprintf(
|
|
|
|
stderr,
|
|
|
|
"c %dx%d+%d+%d m +%d+%d r %dx%d+%d+%d sp (%d,%d) bl %d\n",
|
|
|
|
c->dx,
|
|
|
|
c->dy,
|
|
|
|
c->x,
|
|
|
|
c->y,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
dx,
|
|
|
|
dy,
|
|
|
|
px,
|
|
|
|
py,
|
|
|
|
spx,
|
|
|
|
spy,
|
|
|
|
bl);
|
|
|
|
if (dx < 0) {
|
|
|
|
dx = -dx;
|
|
|
|
sx = -1;
|
|
|
|
}
|
|
|
|
if (dy < 0) {
|
|
|
|
dy = -dy;
|
|
|
|
sy = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remember requested size;
|
|
|
|
* after applying size hints we may have to correct position
|
|
|
|
*/
|
|
|
|
rdx = sx * dx;
|
|
|
|
rdy = sy * dy;
|
|
|
|
|
|
|
|
/* apply size hints */
|
|
|
|
dx -= (2 * BORDER - xoff);
|
|
|
|
dy -= (2 * BORDER - yoff);
|
|
|
|
|
|
|
|
if (!c->is9term) {
|
|
|
|
if (dx < c->min_dx) dx = c->min_dx;
|
|
|
|
if (dy < c->min_dy) dy = c->min_dy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c->size.flags & PResizeInc) {
|
|
|
|
dx = c->min_dx + (dx - c->min_dx) / c->size.width_inc * c->size.width_inc;
|
|
|
|
dy = c->min_dy + (dy - c->min_dy) / c->size.height_inc * c->size.height_inc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c->size.flags & PMaxSize) {
|
|
|
|
if (dx > c->size.max_width) dx = c->size.max_width;
|
|
|
|
if (dy > c->size.max_height) dy = c->size.max_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set size and position */
|
|
|
|
c->dx = sx * (dx + 2 * BORDER);
|
|
|
|
c->dy = sy * (dy + 2 * BORDER);
|
|
|
|
c->x = px;
|
|
|
|
c->y = py;
|
|
|
|
|
|
|
|
/* compensate position for size changed due to size hints */
|
|
|
|
if (spx) c->x -= c->dx - rdx;
|
|
|
|
if (spy) c->y -= c->dy - rdy;
|
|
|
|
|
|
|
|
return init;
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-26 18:01:22 +00:00
|
|
|
xcopy(
|
|
|
|
int fwd, Display* dpy, Drawable src, Drawable dst, GC gc, int x, int y,
|
|
|
|
int dx, int dy, int x1, int y1) {
|
|
|
|
if (fwd)
|
|
|
|
XCopyArea(dpy, src, dst, gc, x, y, dx, dy, x1, y1);
|
|
|
|
else
|
|
|
|
XCopyArea(dpy, dst, src, gc, x1, y1, dx, dy, x, y);
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-02-26 18:01:22 +00:00
|
|
|
drawbound(Client* c, int drawing) {
|
|
|
|
int x, y, dx, dy;
|
|
|
|
ScreenInfo* s;
|
|
|
|
|
|
|
|
if (debug)
|
|
|
|
fprintf(
|
|
|
|
stderr, "drawbound %d %dx%d+%d+%d\n", drawing, c->dx, c->dy, c->x, c->y);
|
|
|
|
|
|
|
|
s = c->screen;
|
|
|
|
x = c->x;
|
|
|
|
y = c->y;
|
|
|
|
dx = c->dx;
|
|
|
|
dy = c->dy;
|
|
|
|
if (dx < 0) {
|
|
|
|
x += dx;
|
|
|
|
dx = -dx;
|
|
|
|
}
|
|
|
|
if (dy < 0) {
|
|
|
|
y += dy;
|
|
|
|
dy = -dy;
|
|
|
|
}
|
|
|
|
if (dx <= 2 || dy <= 2) return;
|
|
|
|
|
|
|
|
if (solidsweep) {
|
|
|
|
if (drawing == -1) {
|
|
|
|
XUnmapWindow(dpy, s->sweepwin);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
x += BORDER;
|
|
|
|
y += BORDER;
|
|
|
|
dx -= 2 * BORDER;
|
|
|
|
dy -= 2 * BORDER;
|
|
|
|
|
|
|
|
if (drawing) {
|
|
|
|
XMoveResizeWindow(dpy, s->sweepwin, x, y, dx, dy);
|
|
|
|
XSelectInput(dpy, s->sweepwin, MenuMask);
|
|
|
|
XMapRaised(dpy, s->sweepwin);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawing == -1) return;
|
|
|
|
|
|
|
|
xcopy(drawing, dpy, s->root, s->bkup[0], s->gccopy, x, y, dx, BORDER, 0, 0);
|
|
|
|
xcopy(
|
|
|
|
drawing,
|
|
|
|
dpy,
|
|
|
|
s->root,
|
|
|
|
s->bkup[0],
|
|
|
|
s->gccopy,
|
|
|
|
x,
|
|
|
|
y + dy - BORDER,
|
|
|
|
dx,
|
|
|
|
BORDER,
|
|
|
|
dx,
|
|
|
|
0);
|
|
|
|
xcopy(drawing, dpy, s->root, s->bkup[1], s->gccopy, x, y, BORDER, dy, 0, 0);
|
|
|
|
xcopy(
|
|
|
|
drawing,
|
|
|
|
dpy,
|
|
|
|
s->root,
|
|
|
|
s->bkup[1],
|
|
|
|
s->gccopy,
|
|
|
|
x + dx - BORDER,
|
|
|
|
y,
|
|
|
|
BORDER,
|
|
|
|
dy,
|
|
|
|
0,
|
|
|
|
dy);
|
|
|
|
|
|
|
|
if (drawing) {
|
|
|
|
XFillRectangle(dpy, s->root, s->gcred, x, y, dx, BORDER);
|
|
|
|
XFillRectangle(dpy, s->root, s->gcred, x, y + dy - BORDER, dx, BORDER);
|
|
|
|
XFillRectangle(dpy, s->root, s->gcred, x, y, BORDER, dy);
|
|
|
|
XFillRectangle(dpy, s->root, s->gcred, x + dx - BORDER, y, BORDER, dy);
|
|
|
|
}
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-02-26 18:01:22 +00:00
|
|
|
misleep(int msec) {
|
|
|
|
struct timeval t;
|
2019-12-02 18:23:00 +00:00
|
|
|
|
2021-02-26 18:01:22 +00:00
|
|
|
t.tv_sec = msec / 1000;
|
|
|
|
t.tv_usec = (msec % 1000) * 1000;
|
|
|
|
select(0, 0, 0, 0, &t);
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
sweepdrag(
|
|
|
|
Client* c, int but, XButtonEvent* e0, BorderOrient bl,
|
|
|
|
int (*recalc)(Client*, int, int, BorderOrient, int)) {
|
|
|
|
XEvent ev;
|
|
|
|
int idle;
|
|
|
|
int cx, cy, rx, ry;
|
|
|
|
int ox, oy, odx, ody;
|
|
|
|
XButtonEvent* e;
|
|
|
|
int notmoved;
|
|
|
|
|
|
|
|
notmoved = 1;
|
|
|
|
ox = c->x;
|
|
|
|
oy = c->y;
|
|
|
|
odx = c->dx;
|
|
|
|
ody = c->dy;
|
|
|
|
c->x -= BORDER;
|
|
|
|
c->y -= BORDER;
|
|
|
|
c->dx += 2 * BORDER;
|
|
|
|
c->dy += 2 * BORDER;
|
|
|
|
if (bl != BorderUnknown || e0 == 0)
|
|
|
|
getmouse(&cx, &cy, c->screen);
|
|
|
|
else
|
|
|
|
getmouse(&c->x, &c->y, c->screen);
|
|
|
|
XGrabServer(dpy);
|
|
|
|
if (bl != BorderUnknown) { notmoved = recalc(c, cx, cy, bl, notmoved); }
|
|
|
|
drawbound(c, 1);
|
|
|
|
idle = 0;
|
|
|
|
for (;;) {
|
|
|
|
if (XCheckMaskEvent(dpy, ButtonMask, &ev) == 0) {
|
|
|
|
getmouse(&rx, &ry, c->screen);
|
|
|
|
if (rx != cx || ry != cy || ++idle > 300) {
|
|
|
|
drawbound(c, 0);
|
|
|
|
if (rx == cx && ry == cy) {
|
|
|
|
XUngrabServer(dpy);
|
|
|
|
XFlush(dpy);
|
|
|
|
misleep(500);
|
|
|
|
XGrabServer(dpy);
|
|
|
|
idle = 0;
|
|
|
|
}
|
|
|
|
if (e0 || bl != BorderUnknown)
|
|
|
|
notmoved = recalc(c, rx, ry, bl, notmoved);
|
|
|
|
else
|
|
|
|
notmoved = recalc(c, rx - cx, ry - cy, bl, notmoved);
|
|
|
|
cx = rx;
|
|
|
|
cy = ry;
|
|
|
|
drawbound(c, 1);
|
|
|
|
XFlush(dpy);
|
|
|
|
}
|
|
|
|
misleep(50);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
e = &ev.xbutton;
|
|
|
|
switch (ev.type) {
|
|
|
|
case ButtonPress:
|
|
|
|
case ButtonRelease:
|
|
|
|
drawbound(c, 0);
|
|
|
|
ungrab(e);
|
|
|
|
XUngrabServer(dpy);
|
|
|
|
if (e->button != but && c->init) goto bad;
|
|
|
|
if (c->dx < 0) {
|
|
|
|
c->x += c->dx;
|
|
|
|
c->dx = -c->dx;
|
|
|
|
}
|
|
|
|
if (c->dy < 0) {
|
|
|
|
c->y += c->dy;
|
|
|
|
c->dy = -c->dy;
|
|
|
|
}
|
|
|
|
c->x += BORDER;
|
|
|
|
c->y += BORDER;
|
|
|
|
c->dx -= 2 * BORDER;
|
|
|
|
c->dy -= 2 * BORDER;
|
|
|
|
if (c->dx < 4 || c->dy < 4 || c->dx < c->min_dx || c->dy < c->min_dy)
|
|
|
|
goto bad;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2019-12-02 18:23:00 +00:00
|
|
|
bad:
|
2021-02-26 18:01:22 +00:00
|
|
|
if (debug) fprintf(stderr, "sweepdrag bad\n");
|
|
|
|
c->x = ox;
|
|
|
|
c->y = oy;
|
|
|
|
c->dx = odx;
|
|
|
|
c->dy = ody;
|
|
|
|
drawbound(c, -1);
|
|
|
|
return 0;
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
sweep(Client* c, int but, XButtonEvent* ignored) {
|
|
|
|
XEvent ev;
|
|
|
|
int status;
|
|
|
|
XButtonEvent* e;
|
|
|
|
ScreenInfo* s;
|
|
|
|
|
|
|
|
s = c->screen;
|
|
|
|
c->dx = 0;
|
|
|
|
c->dy = 0;
|
|
|
|
status = grab(s->root, s->root, ButtonMask, s->sweep0, 0);
|
|
|
|
if (status != GrabSuccess) {
|
|
|
|
graberror("sweep", status); /* */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
XMaskEvent(dpy, ButtonMask, &ev);
|
|
|
|
e = &ev.xbutton;
|
|
|
|
if (e->button != but) {
|
|
|
|
ungrab(e);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
XChangeActivePointerGrab(dpy, ButtonMask, s->boxcurs, e->time);
|
|
|
|
return sweepdrag(c, but, e, BorderUnknown, sweepcalc);
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
pull(Client* c, int but, XButtonEvent* e) {
|
|
|
|
int status;
|
|
|
|
ScreenInfo* s;
|
|
|
|
BorderOrient bl;
|
|
|
|
|
|
|
|
bl = borderorient(c, e->x, e->y);
|
|
|
|
/* assert(bl > BorderUnknown && bl < NBorder); */
|
|
|
|
|
|
|
|
s = c->screen;
|
|
|
|
status = grab(s->root, s->root, ButtonMask, s->bordcurs[bl], 0);
|
|
|
|
if (status != GrabSuccess) {
|
|
|
|
graberror("pull", status); /* */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sweepdrag(c, but, 0, bl, pullcalc);
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-02-26 18:01:22 +00:00
|
|
|
drag(Client* c, int but) {
|
|
|
|
int status;
|
|
|
|
ScreenInfo* s;
|
|
|
|
|
|
|
|
s = c->screen;
|
|
|
|
status = grab(s->root, s->root, ButtonMask, s->boxcurs, 0);
|
|
|
|
if (status != GrabSuccess) {
|
|
|
|
graberror("drag", status); /* */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return sweepdrag(c, but, 0, BorderUnknown, dragcalc);
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-02-26 18:01:22 +00:00
|
|
|
getmouse(int* x, int* y, ScreenInfo* s) {
|
|
|
|
Window dw1, dw2;
|
|
|
|
int t1, t2;
|
|
|
|
unsigned int t3;
|
2019-12-02 18:23:00 +00:00
|
|
|
|
2021-02-26 18:01:22 +00:00
|
|
|
XQueryPointer(dpy, s->root, &dw1, &dw2, x, y, &t1, &t2, &t3);
|
|
|
|
if (debug) fprintf(stderr, "getmouse: %d %d\n", *x, *y);
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-02-26 18:01:22 +00:00
|
|
|
setmouse(int x, int y, ScreenInfo* s) {
|
|
|
|
XWarpPointer(dpy, None, s->root, None, None, None, None, x, y);
|
2019-12-02 18:23:00 +00:00
|
|
|
}
|