|  | /* 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 | 
|  | nobuttons(XButtonEvent *e)	/* Einstuerzende */ | 
|  | { | 
|  | int state; | 
|  |  | 
|  | state = (e->state & AllButtonMask); | 
|  | return (e->type == ButtonRelease) && (state & (state - 1)) == 0; | 
|  | } | 
|  |  | 
|  | int | 
|  | grab(Window w, Window constrain, int mask, Cursor curs, int t) | 
|  | { | 
|  | int status; | 
|  |  | 
|  | if(t == 0) | 
|  | t = timestamp(); | 
|  | status = XGrabPointer(dpy, w, False, mask, | 
|  | GrabModeAsync, GrabModeAsync, constrain, curs, t); | 
|  | return status; | 
|  | } | 
|  |  | 
|  | void | 
|  | 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; | 
|  | } | 
|  |  | 
|  | static void | 
|  | 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])); | 
|  | } | 
|  |  | 
|  | int | 
|  | 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, "rio: 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; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | 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); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | int | 
|  | 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; | 
|  | } | 
|  |  | 
|  | int | 
|  | dragcalc(Client *c, int x, int y, BorderOrient bl, int ignored) | 
|  | { | 
|  | c->x += x; | 
|  | c->y += y; | 
|  |  | 
|  | return ignored; | 
|  | } | 
|  |  | 
|  | int | 
|  | 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; | 
|  | } | 
|  |  | 
|  | static void | 
|  | 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); | 
|  | } | 
|  |  | 
|  | void | 
|  | 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); | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | misleep(int msec) | 
|  | { | 
|  | struct timeval t; | 
|  |  | 
|  | t.tv_sec = msec/1000; | 
|  | t.tv_usec = (msec%1000)*1000; | 
|  | select(0, 0, 0, 0, &t); | 
|  | } | 
|  |  | 
|  | int | 
|  | 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; | 
|  | } | 
|  | } | 
|  | bad: | 
|  | if(debug) fprintf(stderr, "sweepdrag bad\n"); | 
|  | c->x = ox; | 
|  | c->y = oy; | 
|  | c->dx = odx; | 
|  | c->dy = ody; | 
|  | drawbound(c, -1); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int | 
|  | 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); | 
|  | } | 
|  |  | 
|  | int | 
|  | 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); | 
|  | } | 
|  |  | 
|  | int | 
|  | 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); | 
|  | } | 
|  |  | 
|  | void | 
|  | getmouse(int *x, int *y, ScreenInfo *s) | 
|  | { | 
|  | Window dw1, dw2; | 
|  | int t1, t2; | 
|  | unsigned int t3; | 
|  |  | 
|  | XQueryPointer(dpy, s->root, &dw1, &dw2, x, y, &t1, &t2, &t3); | 
|  | if(debug) fprintf(stderr, "getmouse: %d %d\n", *x, *y); | 
|  | } | 
|  |  | 
|  | void | 
|  | setmouse(int x, int y, ScreenInfo *s) | 
|  | { | 
|  | XWarpPointer(dpy, None, s->root, None, None, None, None, x, y); | 
|  | } |