Commit Diff


commit - 703c2d41ac5462f5d82e781b50d051a4a579416c
commit + 0335ceaeb695ab5e92d0d0cd1f554373056c8696
blob - 3952b869d1d19a0fba4f2c9422fefddb0e2f0cca
blob + 4e4a4476ef430177805e5583a2a9734b462ff137
--- src/cmd/devdraw/mkfile
+++ src/cmd/devdraw/mkfile
@@ -18,3 +18,5 @@ HFILES=\
 $O.drawclient: drawclient.$O drawfcall.$O
 	$LD -o $target $prereq
 
+$O.snarf: x11-alloc.$O x11-cload.$O x11-draw.$O x11-fill.$O x11-get.$O x11-init.$O x11-itrans.$O x11-keysym2ucs.$O x11-load.$O x11-pixelbits.$O x11-unload.$O x11-wsys.$O snarf.$O latin1.$O devdraw.$O
+	$LD -o $target $prereq
blob - /dev/null
blob + 1e7a93a1cb862387fda12eca24c572c3125ba272 (mode 644)
--- /dev/null
+++ src/cmd/devdraw/snarf.c
@@ -0,0 +1,110 @@
+#include <u.h>
+#include <sys/select.h>
+#include <errno.h>
+#include "x11-inc.h"
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <memlayer.h>
+#include <keyboard.h>
+#include <mouse.h>
+#include <cursor.h>
+#include <drawfcall.h>
+#include "x11-memdraw.h"
+#include "devdraw.h"
+
+#undef time
+
+#define MouseMask (\
+	ButtonPressMask|\
+	ButtonReleaseMask|\
+	PointerMotionMask|\
+	Button1MotionMask|\
+	Button2MotionMask|\
+	Button3MotionMask)
+
+#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|EnterWindowMask|LeaveWindowMask
+
+void runxevent(XEvent*);
+
+void
+usage(void)
+{
+	fprint(2, "usage: snarf [-a] [-o | text]\n");
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	int apple;
+	int out;
+
+	apple = 0;
+	out = 0;
+
+	ARGBEGIN{
+	case 'a':
+		apple = 1;
+		break;
+	case 'o':
+		out = 1;
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	if(out && argc != 0)
+		usage();
+	if(!out && argc != 1)
+		usage();
+
+	_x.fd = -1;
+
+	memimageinit();
+	_xattach("snarf", "20x20");
+
+	XSelectInput(_x.display, _x.drawable, Mask);
+	XFlush(_x.display);
+
+	if(out){
+		char *s;
+		if(apple)
+			s = _applegetsnarf();
+		else
+			s = _xgetsnarf();
+		write(1, s, strlen(s));
+		write(1, "\n", 1);
+		exits(0);
+	}else{
+		_xputsnarf(argv[0]);
+		for(;;){
+			XEvent event;
+			XNextEvent(_x.display, &event);
+			runxevent(&event);
+		}
+	}
+}
+
+/*
+ * Handle an incoming X event.
+ */
+void
+runxevent(XEvent *xev)
+{
+	switch(xev->type){
+	case Expose:
+		_xexpose(xev);
+		break;
+	
+	case DestroyNotify:
+		if(_xdestroy(xev))
+			exits(0);
+		break;
+
+	case SelectionRequest:
+		_xselect(xev);
+		break;
+	}
+}
+
blob - 81c5351cec2acb4d0de9a0a7903a5a1687844941
blob + fdd2bf8dcd96b309a405cc53f368642569425b49
--- src/cmd/devdraw/x11-itrans.c
+++ src/cmd/devdraw/x11-itrans.c
@@ -382,13 +382,61 @@ struct {
 #endif
 } clip;
 
-char*
-_xgetsnarf(void)
+static uchar*
+_xgetsnarffrom(XWindow w, Atom clipboard, Atom target, int timeout0, int timeout)
 {
-	uchar *data, *xdata;
-	Atom clipboard, type, prop;
+	Atom prop, type;
 	ulong len, lastlen, dummy;
 	int fmt, i;
+	uchar *data, *xdata;
+
+	/*
+	 * We should be waiting for SelectionNotify here, but it might never
+	 * come, and we have no way to time out.  Instead, we will clear
+	 * local property #1, request our buddy to fill it in for us, and poll
+	 * until he's done or we get tired of waiting.
+	 */
+	prop = 1;
+	XChangeProperty(_x.display, _x.drawable, prop, target, 8, PropModeReplace, (uchar*)"", 0);
+	XConvertSelection(_x.display, clipboard, target, prop, _x.drawable, CurrentTime);
+	XFlush(_x.display);
+	lastlen = 0;
+	timeout0 = (timeout0 + 9)/10;
+	timeout = (timeout + 9)/10;
+	for(i=0; i<timeout0 || (lastlen!=0 && i<timeout); i++){
+		usleep(10*1000);
+		XGetWindowProperty(_x.display, _x.drawable, prop, 0, 0, 0, AnyPropertyType,
+			&type, &fmt, &dummy, &len, &xdata);
+		if(lastlen == len && len > 0)
+			break;
+		lastlen = len;
+		XFree(xdata);
+	}
+	if(len == 0)
+		return nil;
+
+	/* get the property */
+	xdata = nil;
+	XGetWindowProperty(_x.display, _x.drawable, prop, 0, SnarfSize/sizeof(ulong), 0, 
+		AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
+	if((type != target && type != XA_STRING && type != _x.utf8string) || len == 0){
+		if(xdata)
+			XFree(xdata);
+		return nil;
+	}
+	if(xdata){
+		data = (uchar*)strdup((char*)xdata);
+		XFree(xdata);
+		return data;
+	}
+	return nil;
+}
+
+char*
+_xgetsnarf(void)
+{
+	uchar *data;
+	Atom clipboard;
 	XWindow w;
 
 	qlock(&clip.lk);
@@ -427,47 +475,11 @@ _xgetsnarf(void)
 		goto out;
 	}
 		
-	/*
-	 * We should be waiting for SelectionNotify here, but it might never
-	 * come, and we have no way to time out.  Instead, we will clear
-	 * local property #1, request our buddy to fill it in for us, and poll
-	 * until he's done or we get tired of waiting.
-	 *
-	 * We should try to go for _x.utf8string instead of XA_STRING,
-	 * but that would add to the polling.
-	 */
-	prop = 1;
-	XChangeProperty(_x.display, _x.drawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
-	XConvertSelection(_x.display, clipboard, XA_STRING, prop, _x.drawable, CurrentTime);
-	XFlush(_x.display);
-	lastlen = 0;
-	for(i=0; i<10 || (lastlen!=0 && i<30); i++){
-		usleep(100*1000);
-		XGetWindowProperty(_x.display, _x.drawable, prop, 0, 0, 0, AnyPropertyType,
-			&type, &fmt, &dummy, &len, &data);
-		if(lastlen == len && len > 0)
-			break;
-		lastlen = len;
+	if((data = _xgetsnarffrom(w, clipboard, _x.utf8string, 10, 100)) == nil)
+	if((data = _xgetsnarffrom(w, clipboard, XA_STRING, 10, 100)) == nil){
+		/* nothing left to do */
 	}
-	if(i == 10){
-		data = nil;
-		goto out;
-	}
-	/* get the property */
-	data = nil;
-	XGetWindowProperty(_x.display, _x.drawable, prop, 0, SnarfSize/sizeof(ulong), 0, 
-		AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
-	if((type != XA_STRING && type != _x.utf8string) || len == 0){
-		if(xdata)
-			XFree(xdata);
-		data = nil;
-	}else{
-		if(xdata){
-			data = (uchar*)strdup((char*)xdata);
-			XFree(xdata);
-		}else
-			data = nil;
-	}
+
 out:
 	qunlock(&clip.lk);
 	return (char*)data;