diff --git a/cmd/click/Makefile b/cmd/click/Makefile new file mode 100644 index 00000000..e5e5fb3e --- /dev/null +++ b/cmd/click/Makefile @@ -0,0 +1,21 @@ +ROOT= ../.. +include ${ROOT}/mk/hdr.mk +include ${ROOT}/mk/wmii.mk + +main.c: ${ROOT}/mk/wmii.mk + +TARG = click +HFILES= dat.h fns.h + +LIB = ${LIBIXP} +LDFLAGS += -lm ${LIBX11} -lXext -lXtst -lregexp9 -lbio -lfmt -lutf +CFLAGS += ${INCX11} -DVERSION=\"${VERSION}\" \ + -DIXP_NEEDAPI=86 +OBJ = main \ + _util \ + ../wmii/map \ + ../wmii/x11 \ + ../util + +include ${ROOT}/mk/one.mk + diff --git a/cmd/click/_util.c b/cmd/click/_util.c new file mode 100644 index 00000000..94fe37e0 --- /dev/null +++ b/cmd/click/_util.c @@ -0,0 +1,77 @@ +/* Copyright ©2008 Kris Maglione + * See LICENSE file for license details. + */ +#include "dat.h" +#include +#include +#include "fns.h" + +#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1)) +static int +getbase(const char **s, long *sign) { + const char *p; + int ret; + + ret = 10; + *sign = 1; + if(**s == '-') { + *sign = -1; + *s += 1; + }else if(**s == '+') + *s += 1; + + p = *s; + if(!strbcmp(p, "0x")) { + *s += 2; + ret = 16; + } + else if(isdigit(p[0])) { + if(p[1] == 'r') { + *s += 2; + ret = p[0] - '0'; + } + else if(isdigit(p[1]) && p[2] == 'r') { + *s += 3; + ret = 10*(p[0]-'0') + (p[1]-'0'); + } + } + else if(p[0] == '0') { + ret = 8; + } + if(ret != 10 && (**s == '-' || **s == '+')) + *sign = 0; + return ret; +} + +bool +getlong(const char *s, long *ret) { + const char *end; + char *rend; + int base; + long sign; + + end = s+strlen(s); + base = getbase(&s, &sign); + if(sign == 0) + return false; + + *ret = sign * strtol(s, &rend, base); + return (end == rend); +} + +bool +getulong(const char *s, ulong *ret) { + const char *end; + char *rend; + int base; + long sign; + + end = s+strlen(s); + base = getbase(&s, &sign); + if(sign < 1) + return false; + + *ret = strtoul(s, &rend, base); + return (end == rend); +} + diff --git a/cmd/click/dat.h b/cmd/click/dat.h new file mode 100644 index 00000000..5096865e --- /dev/null +++ b/cmd/click/dat.h @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define BLOCK(x) do { x; }while(0) + +#ifndef EXTERN +# define EXTERN extern +#endif + +EXTERN Window win; + +EXTERN char buffer[8092]; +EXTERN char* _buffer; + +static char* const _buf_end = buffer + sizeof buffer; + +#define bufclear() \ + BLOCK( _buffer = buffer; _buffer[0] = '\0' ) +#define bufprint(...) \ + _buffer = seprint(_buffer, _buf_end, __VA_ARGS__) + diff --git a/cmd/click/fns.h b/cmd/click/fns.h new file mode 100644 index 00000000..d41b8400 --- /dev/null +++ b/cmd/click/fns.h @@ -0,0 +1,4 @@ + +bool getlong(const char*, long*); +bool getulong(const char*, ulong*); + diff --git a/cmd/click/main.c b/cmd/click/main.c new file mode 100644 index 00000000..bf0966d5 --- /dev/null +++ b/cmd/click/main.c @@ -0,0 +1,82 @@ +/* Copyright ©2006-2008 Kris Maglione + * See LICENSE file for license details. + */ +#define EXTERN +#include "dat.h" +#include +#include +#include +#include +#include "fns.h" + +static const char version[] = "click-"VERSION", ©2008 Kris Maglione\n"; + +static void +usage(void) { + fatal("usage: %s [window]\n", argv0); +} + +static void +click(Window *w, Point p) { + Point rp, restore; + + restore = querypointer(&scr.root); + + rp = translate(w, &scr.root, p); + + XTestFakeMotionEvent(display, 0, rp.x, rp.y, 0); + + XTestFakeButtonEvent(display, 1, true, 0); + XTestFakeButtonEvent(display, 1, false, 0); + + rp = getwinrect(w).max; + XTestFakeMotionEvent(display, 0, rp.x - 1, rp.y - 1, 0); + + return; + XButtonEvent e = { 0, }; + + e.root = scr.root.w; + e.window = w->w; + e.same_screen = true; + + e.x = p.x; + e.y = p.y; + e.x_root = rp.x; + e.y_root = rp.y; + e.button = 1; /* Hopefully ignored, except enough to do the trick. */ + + e.type = ButtonPress; + sendevent(w, true, ButtonPressMask, (XEvent*)&e); + e.type = ButtonRelease; + e.state = Button1Mask; + sendevent(w, true, ButtonReleaseMask, (XEvent*)&e); +} + +int +main(int argc, char *argv[]) { + char *s; + + ARGBEGIN{ + default: + usage(); + }ARGEND; + + setlocale(LC_CTYPE, ""); + + initdisplay(); + + s = ARGF(); + if(s && !getulong(s, &win.w)) + usage(); + if (!s) + win.w = getfocus(); + + if(argc) + usage(); + + click(&win, Pt(0, 0)); + + XCloseDisplay(display); + return 0; +} + diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c index d259ac88..1c75ca7b 100644 --- a/cmd/wmii/x11.c +++ b/cmd/wmii/x11.c @@ -898,6 +898,17 @@ getprop_string(Window *w, char *name) { return str; } +Rectangle +getwinrect(Window *w) { + XWindowAttributes wa; + Point p; + + if(!XGetWindowAttributes(display, w->w, &wa)) + return ZR; + p = translate(w, &scr.root, ZP); + return rectaddpt(Rect(0, 0, wa.width, wa.height), p); +} + void setfocus(Window *w, int mode) { XSetInputFocus(display, w->w, mode, CurrentTime); diff --git a/include/x11.h b/include/x11.h index 038ca2f7..8fa2164a 100644 --- a/include/x11.h +++ b/include/x11.h @@ -254,6 +254,7 @@ long winprotocols(Window*); Atom xatom(char*); void sendmessage(Window*, char*, long, long, long, long, long); XRectangle XRect(Rectangle); +Rectangle getwinrect(Window*); Rectangle gravitate(Rectangle dst, Rectangle src, Point grav); Rectangle insetrect(Rectangle, int); Rectangle rectaddpt(Rectangle, Point);