commit 579115c4308c2e4404a3da961b1d15535a3d1e6b
parent e606fc83a5a291c35947ff124a79459775c4dee2
Author: Kris Maglione <jg@suckless.org>
Date: Mon, 1 Dec 2008 07:43:20 -0500
Add cmd/click
Diffstat:
7 files changed, 223 insertions(+), 0 deletions(-)
diff --git a/cmd/click/Makefile 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
@@ -0,0 +1,77 @@
+/* Copyright ©2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "dat.h"
+#include <ctype.h>
+#include <string.h>
+#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
@@ -0,0 +1,27 @@
+#include <fmt.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <util.h>
+#include <ixp.h>
+#include <x11.h>
+
+#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
@@ -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
@@ -0,0 +1,82 @@
+/* Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#define EXTERN
+#include "dat.h"
+#include <X11/Xproto.h>
+#include <X11/extensions/XTest.h>
+#include <locale.h>
+#include <string.h>
+#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
@@ -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
@@ -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);