Commit Diff


commit - 4af386f434d5ca3de733951d4f73dd134e879cc2
commit + 161060a46346fa0beeb48b55ed28b2cd330bc4e8
blob - 8013efa56f01f1dc95427eb7498c5545b6b2beb6
blob + 807b8e743aa79f2b6c01b572d420c770b1f5a057
--- src/libdraw/Makefile
+++ src/libdraw/Makefile
@@ -99,6 +99,7 @@ OFILES=\
 	x11-mouse.$O\
 	x11-pixelbits.$O\
 	x11-unload.$O\
+	x11-wsys.$O\
 	devdraw.$O\
 	unix.$O\
 
blob - 41b30620f22e982acc7c164d41bb2a747056d663
blob + 1b19fc1c42a98bf81368b1a519134304a3175651
--- src/libdraw/arith.c
+++ src/libdraw/arith.c
@@ -167,8 +167,6 @@ drawld2chan[] = {
 	CMAP8,
 };
 
-int log2[] = { -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5 };
-
 u32int
 setalpha(u32int color, uchar alpha)
 {
blob - b0036385dbcfa82285fbf70d45dddebb0d6cb011
blob + f4749867140703b0d41a0343a126fc6c1131414a
--- src/libdraw/devdraw.c
+++ src/libdraw/devdraw.c
@@ -138,6 +138,7 @@ void
 _initdisplaymemimage(Display *d, Memimage *m)
 {
 	screenimage = m;
+	m->screenref = 1;
 	client0 = mallocz(sizeof(Client), 1);
 	if(client0 == nil){
 		fprint(2, "initdraw: allocating client0: out of memory");
@@ -165,7 +166,16 @@ _drawreplacescreenimage(Memimage *m)
 	 * about the resize through external means, so all we
 	 * need to do is this assignment.
 	 */
+	Memimage *om;
+
+	qlock(&sdraw.lk);
+	om = screenimage;
 	screenimage = m;
+	m->screenref = 1;
+	if(om && --om->screenref == 0){
+		_freememimage(om);
+	}
+	qunlock(&sdraw.lk);
 }
 
 static
@@ -399,6 +409,8 @@ drawinstall(Client *client, int id, Memimage *i, DScre
 	d->name = 0;
 	d->vers = 0;
 	d->image = i;
+	if(i->screenref)
+		++i->screenref;
 	d->nfchar = 0;
 	d->fchar = 0;
 	d->fromname = 0;
@@ -534,11 +546,9 @@ drawfreedimage(DImage *dimage)
 		drawfreedimage(dimage->fromname);
 		goto Return;
 	}
-	//if(dimage->image == screenimage)	/* don't free the display */
-	//	goto Return;
 	ds = dimage->dscreen;
+	l = dimage->image;
 	if(ds){
-		l = dimage->image;
 		if(l->data == screenimage->data)
 			addflush(l->layer->screenr);
 		if(l->layer->refreshfn == drawrefresh)	/* else true owner will clean up */
@@ -549,8 +559,12 @@ drawfreedimage(DImage *dimage)
 		else
 			memlfree(l);
 		drawfreedscreen(ds);
-	}else
-		freememimage(dimage->image);
+	}else{
+		if(l->screenref==0)
+			freememimage(l);
+		else if(--l->screenref==0)
+			_freememimage(l);
+	}
     Return:
 	free(dimage->fchar);
 	free(dimage);
@@ -732,6 +746,7 @@ _drawmsgread(Display *d, void *a, int n)
 {
 	int inbuf;
 
+	qlock(&sdraw.lk);
 	inbuf = d->obufp - d->obuf; 
 	if(n > inbuf)
 		n = inbuf;
@@ -740,6 +755,7 @@ _drawmsgread(Display *d, void *a, int n)
 	if(inbuf)
 		memmove(d->obuf, d->obufp-inbuf, inbuf);
 	d->obufp = d->obuf+inbuf;
+	qunlock(&sdraw.lk);
 	return n;
 }
 
@@ -776,6 +792,7 @@ _drawmsgwrite(Display *d, void *v, int n)
 	Refreshfn reffn;
 	Refx *refx;
 
+	qlock(&sdraw.lk);
 	d->obufp = d->obuf;
 	a = v;
 	m = 0;
@@ -1516,6 +1533,7 @@ _drawmsgwrite(Display *d, void *v, int n)
 			continue;
 		}
 	}
+	qunlock(&sdraw.lk);
 	return oldn - n;
 
 Enodrawimage:
@@ -1527,9 +1545,11 @@ Enodrawscreen:
 Eshortdraw:
 	err = "short draw message";
 	goto error;
+/*
 Eshortread:
 	err = "draw read too short";
 	goto error;
+*/
 Eimageexists:
 	err = "image id in use";
 	goto error;
@@ -1551,6 +1571,7 @@ Enotfont:
 Eindex:
 	err = "character index out of range";
 	goto error;
+/*
 Enoclient:
 	err = "no such draw client";
 	goto error;
@@ -1560,6 +1581,7 @@ Edepth:
 Enameused:
 	err = "image name in use";
 	goto error;
+*/
 Enoname:
 	err = "no image with that name";
 	goto error;
@@ -1580,7 +1602,8 @@ Ebadarg:
 	goto error;
 
 error:
-	drawerror(display, err);
+	werrstr("%s", err);
+	qunlock(&sdraw.lk);
 	return -1;
 }
 
blob - 632e82385919aeab2525903b0cb38df0591f09cd
blob + 7053c171c6837abc070e5a995598ee503f8e65a7
--- src/libdraw/md-line.c
+++ src/libdraw/md-line.c
@@ -10,6 +10,7 @@ enum
 	Arrow3 = 3,
 };
 
+/*
 static
 int
 lmin(int a, int b)
@@ -18,6 +19,7 @@ lmin(int a, int b)
 		return a;
 	return b;
 }
+*/
 
 static
 int
blob - dc16e379b744c75f93ae55af57276e668c5fa783
blob + e9fa3f849b3460c32388918c7ca23cd73d194ba8
--- src/libdraw/openfont.c
+++ src/libdraw/openfont.c
@@ -2,6 +2,8 @@
 #include <libc.h>
 #include <draw.h>
 
+extern vlong _drawflength(int);
+
 Font*
 openfont(Display *d, char *name)
 {
@@ -13,7 +15,7 @@ openfont(Display *d, char *name)
 	if(fd < 0)
 		return 0;
 
-	n = flength(fd);
+	n = _drawflength(fd);
 	buf = malloc(n+1);
 	if(buf == 0){
 		close(fd);
blob - bcb4e3a1ef7f49020f50ab0852c4501683de9d5d
blob + bf397cb5b5f18b964e7060ca4be45d0e7bcf7bb8
--- src/libdraw/subfontname.c
+++ src/libdraw/subfontname.c
@@ -29,7 +29,9 @@ subfontname(char *cfname, char *fname, int maxdepth)
 	if(maxdepth > 8)
 		maxdepth = 8;
 
-	for(i=log2[maxdepth]; i>=0; i--){
+	for(i=3; i>=0; i--){
+		if((1<<i) > maxdepth)
+			continue;
 		/* try i-bit grey */
 		snprint(tmp2, sizeof tmp2, "%s.%d", t, i);
 		if(access(tmp2, AREAD) == 0)
blob - 2203b0876e47137bc3ca1d18e7ce7e879f7e09db
blob + 491bc66c866c2ab163d1d8995f0f68820c48872a
--- src/libdraw/unix.c
+++ src/libdraw/unix.c
@@ -5,7 +5,7 @@
 #include <draw.h>
 
 vlong
-flength(int fd)
+_drawflength(int fd)
 {
 	struct stat s;
 
blob - 19475c747818d4a7b05b110e632f7dc164d34729
blob + 458efc61fdee4de8974315802a1ecd8d0fc6a274
--- src/libdraw/x11-alloc.c
+++ src/libdraw/x11-alloc.c
@@ -37,20 +37,21 @@ xallocmemimage(Rectangle r, u32int chan, int pixmap)
 	}
 
 	/*
-	 * Allocate backing store.  What we call a 32-bit image
-	 * the X server calls a 24-bit image.
+	 * Allocate backing store.
 	 */
-	d = m->depth;
+	if(chan == GREY1)
+		d = 1;
+	else
+		d = _x.depth;
 	if(pixmap != PMundef)
 		xm->pixmap = pixmap;
 	else
-		xm->pixmap = XCreatePixmap(_x.display, _x.drawable,
-			Dx(r), Dy(r), d==32 ? 24 : d);
+		xm->pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), d);
 
 	/*
 	 * We want to align pixels on word boundaries.
 	 */
-	if(d == 24)
+	if(m->depth == 24)
 		offset = r.min.x&3;
 	else
 		offset = r.min.x&(31/m->depth);
@@ -60,7 +61,7 @@ xallocmemimage(Rectangle r, u32int chan, int pixmap)
 	/*
 	 * Wrap our data in an XImage structure.
 	 */
-	xi = XCreateImage(_x.display, _x.vis, d==32 ? 24 : d,
+	xi = XCreateImage(_x.display, _x.vis, d,
 		ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r),
 		32, m->width*sizeof(u32int));
 	if(xi == nil){
blob - ee91791d9794c4cb8aef91cc76f170d07047abed
blob + 97438740e899e297802ca550fcf6ef45aa59e4aa
--- src/libdraw/x11-draw.c
+++ src/libdraw/x11-draw.c
@@ -17,7 +17,6 @@ void
 memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp,
 	Memimage *mask, Point mp, int op)
 {
-	int drew;
 	Memdrawparam *par;
 
 	if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
@@ -116,6 +115,7 @@ xdraw(Memdrawparam *par)
 			}
 		}else{
 			/* this doesn't work on rob's mac?  */
+			return 0;
 			gc = _x.gcsimplesrc;
 			if(dst->chan == CMAP8 && _x.usetable)
 				sdval = _x.tox11[sdval];
blob - 85543e838e934f1288d01fba26ff0e372c20da09
blob + 28f6ae4009c89b8dcb73e4f4991a313c6ba6f4f7
--- src/libdraw/x11-init.c
+++ src/libdraw/x11-init.c
@@ -71,7 +71,7 @@ getimage0(Display *d)
 		fprint(2, "cannot read screen info: %r\n");
 		abort();
 	}
-	
+
 	n = _drawmsgread(d, info, sizeof info);
 	if(n != 12*12){
 		fprint(2, "short screen info\n");
@@ -113,8 +113,8 @@ xerror(XDisplay *d, XErrorEvent *e)
 {
 	char buf[200];
 
-	print("X error: error_code=%d, request_code=%d, minor=%d\n",
-		e->error_code, e->request_code, e->minor_code);
+	print("X error: error_code=%d, request_code=%d, minor=%d disp=%p\n",
+		e->error_code, e->request_code, e->minor_code, d);
 	XGetErrorText(d, e->error_code, buf, sizeof buf);
 	print("%s\n", buf);
 	return 0;
@@ -179,6 +179,13 @@ xattach(char *label)
 		_x.usetable = 1;
 	}
 	else
+	if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi)
+	|| XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){
+		_x.vis = xvi.visual;
+		_x.depth = 15;
+		_x.usetable = 1;
+	}
+	else
 	if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi)
 	|| XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){
 		_x.vis = xvi.visual;
@@ -226,6 +233,9 @@ xattach(char *label)
 				break;
 			case 8:
 				_x.chan = CMAP8;
+				break;
+			case 15:
+				_x.chan = RGB15;
 				break;
 			case 16: /* how to tell RGB15? */
 				_x.chan = RGB16;
@@ -264,7 +274,7 @@ xattach(char *label)
 
 	memset(&attr, 0, sizeof attr);
 	attr.colormap = _x.cmap;
-	attr.background_pixel = 0;
+	attr.background_pixel = ~0;
 	attr.border_pixel = 0;
 	_x.drawable = XCreateWindow(
 		_x.display,	/* display */
@@ -274,7 +284,7 @@ xattach(char *label)
 		Dx(r),		/* width */
 	 	Dy(r),		/* height */
 		0,		/* border width */
-		_x.depth,	/* depth */
+		DefaultDepthOfScreen(xscreen),	/* depth */
 		InputOutput,	/* class */
 		_x.vis,		/* visual */
 				/* valuemask */
@@ -328,6 +338,7 @@ xattach(char *label)
 	 */
 	_x.screenr = r;
 	_x.screenpm = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth);
+	_x.nextscreenpm = _x.screenpm;
 	_x.screenimage = xallocmemimage(r, _x.chan, _x.screenpm);
 
 	/*
@@ -354,18 +365,22 @@ xattach(char *label)
 	XFlush(_x.display);
 
 	/*
-	 * Lots of display connections for various threads.
+	 * Lots of display connections for various procs.
 	 */
 	_x.kbdcon	= XOpenDisplay(NULL);
 	_x.mousecon	= XOpenDisplay(NULL);
 	_x.snarfcon	= XOpenDisplay(NULL);
 
+	if(0) fprint(2, "x: display=%p kbd=%p mouse=%p snarf=%p\n",
+		_x.display, _x.kbdcon, _x.mousecon, _x.snarfcon);
+
 	_x.black	= xscreen->black_pixel;
 	_x.white	= xscreen->white_pixel;
 
 	return _x.screenimage;
 
 err0:
+fprint(2, "%r\n");
 	/*
 	 * Should do a better job of cleaning up here.
 	 */
@@ -551,6 +566,14 @@ setupcmap(XWindow w)
 void
 flushmemscreen(Rectangle r)
 {
+	if(_x.nextscreenpm != _x.screenpm){
+		qlock(&_x.screenlock);
+		XSync(_x.display, False);
+		XFreePixmap(_x.display, _x.screenpm);
+		_x.screenpm = _x.nextscreenpm;
+		qunlock(&_x.screenlock);
+	}
+
 	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
 		return;
 	XCopyArea(_x.display, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
@@ -564,6 +587,11 @@ xexpose(XEvent *e, XDisplay *xd)
 	XExposeEvent *xe;
 	Rectangle r;
 
+	qlock(&_x.screenlock);
+	if(_x.screenpm != _x.nextscreenpm){
+		qunlock(&_x.screenlock);
+		return;
+	}
 	xe = (XExposeEvent*)e;
 	r.min.x = xe->x;
 	r.min.y = xe->y;
@@ -571,17 +599,29 @@ xexpose(XEvent *e, XDisplay *xd)
 	r.max.y = xe->y+xe->height;
 	XCopyArea(xd, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
 		Dx(r), Dy(r), r.min.x, r.min.y);
-	XFlush(xd);
+	XSync(xd, False);
+	qunlock(&_x.screenlock);
 }
 
 int
 xconfigure(XEvent *e, XDisplay *xd)
 {
+	Rectangle r;
 	XConfigureEvent *xe = (XConfigureEvent*)e;
 
 	if(xe->width == Dx(_x.screenr) && xe->height == Dy(_x.screenr))
 		return 0;
-	_x.newscreenr = Rect(0, 0, xe->width, xe->height);
+	if(xe->width==0 || xe->height==0)
+		fprint(2, "ignoring resize to %dx%d\n", xe->width, xe->height);
+	r = Rect(0, 0, xe->width, xe->height);
+	qlock(&_x.screenlock);
+	if(_x.screenpm != _x.nextscreenpm){
+		XCopyArea(xd, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
+			Dx(r), Dy(r), r.min.x, r.min.y);
+		XSync(xd, False);
+	}
+	qunlock(&_x.screenlock);
+	_x.newscreenr = r;
 	return 1;
 }
 
@@ -598,7 +638,9 @@ xreplacescreenimage(void)
 
 	pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth);
 	m = xallocmemimage(r, _x.chan, pixmap);
-	_x.screenpm = pixmap;
+	if(_x.nextscreenpm != _x.screenpm)
+		XFreePixmap(_x.display, _x.nextscreenpm);
+	_x.nextscreenpm = pixmap;
 	_x.screenr = r;
 	_drawreplacescreenimage(m);
 	return 1;
blob - 49ee3fbba8f20d2e01d7d7e6181d6d168e3a0100
blob + 35fd31ea2a07675971e1e83da45b975e003357f6
--- src/libdraw/x11-itrans.c
+++ src/libdraw/x11-itrans.c
@@ -254,5 +254,131 @@ xsetcursor(Cursor *c)
 	XFreePixmap(_x.display, xsrc);
 	XFreePixmap(_x.display, xmask);
 	XFlush(_x.display);
+}
+
+struct {
+	char buf[SnarfSize];
+	QLock lk;
+} clip;
+
+char*
+xgetsnarf(XDisplay *xd)
+{
+	uchar *data, *xdata;
+	Atom type;
+	ulong len, lastlen, dummy;
+	int fmt, i;
+	XWindow w;
+
+	qlock(&clip.lk);
+	w = XGetSelectionOwner(xd, XA_PRIMARY);
+	if(w == _x.drawable){
+		data = (uchar*)strdup(clip.buf);
+		goto out;
+	}
+	if(w == None){
+		data = nil;
+		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 zero the 
+	 * property, request our buddy to fill it in for us, and wait until
+	 * he's done.
+	 */
+	XChangeProperty(xd, _x.drawable, XA_PRIMARY, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
+	XConvertSelection(xd, XA_PRIMARY, XA_STRING, None, _x.drawable, CurrentTime);
+	XFlush(xd);
+	lastlen = 0;
+	for(i=0; i<30; i++){
+		usleep(100*1000);
+		XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, 0, 0, AnyPropertyType,
+			&type, &fmt, &dummy, &len, &data);
+		if(lastlen == len && len > 0)
+			break;
+		lastlen = len;
+	}
+	if(i == 30){
+		data = nil;
+		goto out;
+	}
+	/* get the property */
+	data = nil;
+	XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, SnarfSize/4, 0, 
+		AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
+	if(type != XA_STRING || len == 0){
+		if(xdata)
+			XFree(xdata);
+		data = nil;
+	}else{
+		if(xdata){
+			data = strdup((char*)xdata);
+			XFree(xdata);
+		}else
+			data = nil;
+	}
+out:
+	qunlock(&clip.lk);
+	return data;
 }
 
+void
+xputsnarf(XDisplay *xd, char *data)
+{
+	if(strlen(data) >= SnarfSize)
+		return;
+	qlock(&clip.lk);
+	strcpy(clip.buf, data);
+	/*
+	 * BUG: This is wrong.  Instead, we should send an event to the
+	 * mouse connection telling it to call XSetSelectionOwner.
+	 */
+	XSetSelectionOwner(_x.mousecon, XA_PRIMARY, _x.drawable, CurrentTime);
+	XFlush(xd);
+	qunlock(&clip.lk);
+}
+
+int
+xselect(XEvent *e, XDisplay *xd)
+{
+	XEvent r;
+	XSelectionRequestEvent *xe;
+
+	memset(&r, 0, sizeof r);
+	xe = (XSelectionRequestEvent*)e;
+	if(1 || xe->target == XA_STRING){
+		qlock(&clip.lk);
+		XChangeProperty(xd, xe->requestor, xe->property, XA_STRING, 8,
+			PropModeReplace, (uchar*)clip.buf, strlen(clip.buf)+1);
+		qunlock(&clip.lk);
+		r.xselection.property = xe->property;
+	}else{
+		fprint(2, "asked for a %d\n", xe->target);
+		r.xselection.property = None;
+	}
+
+	r.xselection.display = xe->display;
+	/* r.xselection.property filled above */
+	r.xselection.target = xe->target;
+	r.xselection.type = SelectionNotify;
+	r.xselection.requestor = xe->requestor;
+	r.xselection.time = xe->time;
+	r.xselection.send_event = True;
+	r.xselection.selection = xe->selection;
+	XSendEvent(xd, xe->requestor, False, 0, &r);
+	XFlush(xd);
+	return 0;
+}
+
+void
+putsnarf(char *data)
+{
+	xputsnarf(_x.snarfcon, data);
+}
+
+char*
+getsnarf(void)
+{
+	return xgetsnarf(_x.snarfcon);
+}
+
blob - 188e52bf467d1fd352b4755cdd4f9f42d5aa2716
blob + 92b57814c987dd9e49e76ce9a33b158f1cf87ba7
--- src/libdraw/x11-keyboard.c
+++ src/libdraw/x11-keyboard.c
@@ -41,8 +41,8 @@ _ioproc(void *arg)
 	kc = arg;
 	threadsetname("kbdproc");
 	kc->pid = getpid();
+	XSelectInput(_x.kbdcon, _x.drawable, KeyPressMask);
 	for(;;){
-		XSelectInput(_x.kbdcon, _x.drawable, KeyPressMask);
 		XWindowEvent(_x.kbdcon, _x.drawable, KeyPressMask, &xevent);
 		switch(xevent.type){
 		case KeyPress:
blob - 9fffe34e1046c51d5ba96f990ff6490d109f93d1
blob + 514926da652cc0da5517f6032477c6b8b80e78d1
--- src/libdraw/x11-memdraw.h
+++ src/libdraw/x11-memdraw.h
@@ -54,7 +54,9 @@ struct Xprivate {
 	XDisplay	*mousecon;
 	Rectangle	newscreenr;
 	Memimage*	screenimage;
+	QLock		screenlock;
 	XDrawable	screenpm;
+	XDrawable	nextscreenpm;
 	Rectangle	screenr;
 	XDisplay	*snarfcon;
 	int		toplan9[256];
@@ -73,11 +75,13 @@ extern void	xfillcolor(Memimage*, Rectangle, u32int);
 extern void	xfreexdata(Memimage*);
 extern XImage	*xgetxdata(Memimage*, Rectangle);
 extern void	xputxdata(Memimage*, Rectangle);
+extern void	_initdisplaymemimage(Display*, Memimage*);
 
 struct Mouse;
 extern int	xtoplan9mouse(XEvent*, struct Mouse*);
 extern int	xtoplan9kbd(XEvent*);
 extern void	xexpose(XEvent*, XDisplay*);
+extern int	xselect(XEvent*, XDisplay*);
 extern int	xconfigure(XEvent*, XDisplay*);
 extern void	flushmemscreen(Rectangle);
 extern void	xmoveto(Point);
blob - c6a2685107163432d19f99a2ba4f5783a3997c8f
blob + 6b5b3922af805dd27d62e48c3fbc6a513fdc2b48
--- src/libdraw/x11-mouse.c
+++ src/libdraw/x11-mouse.c
@@ -48,6 +48,7 @@ void
 _ioproc(void *arg)
 {
 	int one;
+	ulong mask;
 	Mouse m;
 	Mousectl *mc;
 	XEvent xevent;
@@ -57,9 +58,10 @@ _ioproc(void *arg)
 	threadsetname("mouseproc");
 	memset(&m, 0, sizeof m);
 	mc->pid = getpid();
+	mask = MouseMask|ExposureMask|StructureNotifyMask;
+	XSelectInput(_x.mousecon, _x.drawable, mask);
 	for(;;){
-		XSelectInput(_x.mousecon, _x.drawable, MouseMask|ExposureMask|StructureNotifyMask);
-		XWindowEvent(_x.mousecon, _x.drawable, MouseMask|ExposureMask|StructureNotifyMask, &xevent);
+		XNextEvent(_x.mousecon, &xevent);
 		switch(xevent.type){
 		case Expose:
 			xexpose(&xevent, _x.mousecon);
@@ -68,6 +70,9 @@ _ioproc(void *arg)
 			if(xconfigure(&xevent, _x.mousecon))
 				nbsend(mc->resizec, &one);
 			continue;
+		case SelectionRequest:
+			xselect(&xevent, _x.mousecon);
+			continue;
 		case ButtonPress:
 		case ButtonRelease:
 		case MotionNotify: