tLots of X fixes. - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 161060a46346fa0beeb48b55ed28b2cd330bc4e8
 (DIR) parent 4af386f434d5ca3de733951d4f73dd134e879cc2
 (HTM) Author: rsc <devnull@localhost>
       Date:   Sat, 11 Oct 2003 02:47:43 +0000
       
       Lots of X fixes.
       
       Diffstat:
         M src/libdraw/Makefile                |       1 +
         M src/libdraw/arith.c                 |       2 --
         M src/libdraw/devdraw.c               |      35 +++++++++++++++++++++++++------
         M src/libdraw/md-line.c               |       2 ++
         M src/libdraw/openfont.c              |       4 +++-
         M src/libdraw/subfontname.c           |       4 +++-
         M src/libdraw/unix.c                  |       2 +-
         M src/libdraw/x11-alloc.c             |      15 ++++++++-------
         M src/libdraw/x11-draw.c              |       2 +-
         M src/libdraw/x11-init.c              |      60 ++++++++++++++++++++++++++-----
         M src/libdraw/x11-itrans.c            |     126 +++++++++++++++++++++++++++++++
         M src/libdraw/x11-keyboard.c          |       2 +-
         M src/libdraw/x11-memdraw.h           |       4 ++++
         M src/libdraw/x11-mouse.c             |       9 +++++++--
       
       14 files changed, 237 insertions(+), 31 deletions(-)
       ---
 (DIR) diff --git a/src/libdraw/Makefile b/src/libdraw/Makefile
       t@@ -99,6 +99,7 @@ OFILES=\
                x11-mouse.$O\
                x11-pixelbits.$O\
                x11-unload.$O\
       +        x11-wsys.$O\
                devdraw.$O\
                unix.$O\
        
 (DIR) diff --git a/src/libdraw/arith.c b/src/libdraw/arith.c
       t@@ -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)
        {
 (DIR) diff --git a/src/libdraw/devdraw.c b/src/libdraw/devdraw.c
       t@@ -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");
       t@@ -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
       t@@ -399,6 +409,8 @@ drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
                d->name = 0;
                d->vers = 0;
                d->image = i;
       +        if(i->screenref)
       +                ++i->screenref;
                d->nfchar = 0;
                d->fchar = 0;
                d->fromname = 0;
       t@@ -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 */
       t@@ -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);
       t@@ -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;
       t@@ -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;
        }
        
       t@@ -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;
       t@@ -1516,6 +1533,7 @@ _drawmsgwrite(Display *d, void *v, int n)
                                continue;
                        }
                }
       +        qunlock(&sdraw.lk);
                return oldn - n;
        
        Enodrawimage:
       t@@ -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;
       t@@ -1551,6 +1571,7 @@ Enotfont:
        Eindex:
                err = "character index out of range";
                goto error;
       +/*
        Enoclient:
                err = "no such draw client";
                goto error;
       t@@ -1560,6 +1581,7 @@ Edepth:
        Enameused:
                err = "image name in use";
                goto error;
       +*/
        Enoname:
                err = "no image with that name";
                goto error;
       t@@ -1580,7 +1602,8 @@ Ebadarg:
                goto error;
        
        error:
       -        drawerror(display, err);
       +        werrstr("%s", err);
       +        qunlock(&sdraw.lk);
                return -1;
        }
        
 (DIR) diff --git a/src/libdraw/md-line.c b/src/libdraw/md-line.c
       t@@ -10,6 +10,7 @@ enum
                Arrow3 = 3,
        };
        
       +/*
        static
        int
        lmin(int a, int b)
       t@@ -18,6 +19,7 @@ lmin(int a, int b)
                        return a;
                return b;
        }
       +*/
        
        static
        int
 (DIR) diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c
       t@@ -2,6 +2,8 @@
        #include <libc.h>
        #include <draw.h>
        
       +extern vlong _drawflength(int);
       +
        Font*
        openfont(Display *d, char *name)
        {
       t@@ -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);
 (DIR) diff --git a/src/libdraw/subfontname.c b/src/libdraw/subfontname.c
       t@@ -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)
 (DIR) diff --git a/src/libdraw/unix.c b/src/libdraw/unix.c
       t@@ -5,7 +5,7 @@
        #include <draw.h>
        
        vlong
       -flength(int fd)
       +_drawflength(int fd)
        {
                struct stat s;
        
 (DIR) diff --git a/src/libdraw/x11-alloc.c b/src/libdraw/x11-alloc.c
       t@@ -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);
       t@@ -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){
 (DIR) diff --git a/src/libdraw/x11-draw.c b/src/libdraw/x11-draw.c
       t@@ -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)
       t@@ -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];
 (DIR) diff --git a/src/libdraw/x11-init.c b/src/libdraw/x11-init.c
       t@@ -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");
       t@@ -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;
       t@@ -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;
       t@@ -227,6 +234,9 @@ xattach(char *label)
                                case 8:
                                        _x.chan = CMAP8;
                                        break;
       +                        case 15:
       +                                _x.chan = RGB15;
       +                                break;
                                case 16: /* how to tell RGB15? */
                                        _x.chan = RGB16;
                                        break;
       t@@ -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 */
       t@@ -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 */
       t@@ -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);
        
                /*
       t@@ -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.
                 */
       t@@ -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,
       t@@ -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;
       t@@ -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;
        }
        
       t@@ -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;
 (DIR) diff --git a/src/libdraw/x11-itrans.c b/src/libdraw/x11-itrans.c
       t@@ -256,3 +256,129 @@ xsetcursor(Cursor *c)
                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);
       +}
       +
 (DIR) diff --git a/src/libdraw/x11-keyboard.c b/src/libdraw/x11-keyboard.c
       t@@ -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:
 (DIR) diff --git a/src/libdraw/x11-memdraw.h b/src/libdraw/x11-memdraw.h
       t@@ -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];
       t@@ -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);
 (DIR) diff --git a/src/libdraw/x11-mouse.c b/src/libdraw/x11-mouse.c
       t@@ -48,6 +48,7 @@ void
        _ioproc(void *arg)
        {
                int one;
       +        ulong mask;
                Mouse m;
                Mousectl *mc;
                XEvent xevent;
       t@@ -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);
       t@@ -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: