diff options
Diffstat (limited to 'src/libdraw/x11-itrans.c')
-rw-r--r-- | src/libdraw/x11-itrans.c | 130 |
1 files changed, 113 insertions, 17 deletions
diff --git a/src/libdraw/x11-itrans.c b/src/libdraw/x11-itrans.c index 35fd31ea..b4d9e689 100644 --- a/src/libdraw/x11-itrans.c +++ b/src/libdraw/x11-itrans.c @@ -11,8 +11,8 @@ #include <keyboard.h> #include "x11-memdraw.h" -int -xtoplan9kbd(XEvent *e) +static int +_xtoplan9kbd(XEvent *e) { int ind, k, md; @@ -117,16 +117,82 @@ xtoplan9kbd(XEvent *e) return k; } +static Rune* +xtoplan9latin1(XEvent *e) +{ + static Rune k[10]; + static int alting, nk; + int n; + int r; + + r = _xtoplan9kbd(e); + if(r < 0) + return nil; + if(alting){ + k[nk++] = r; + n = _latin1(k, nk); + if(n > 0){ + alting = 0; + k[0] = n; + k[1] = 0; + return k; + } + if(n == -1){ + alting = 0; + k[nk] = 0; + return k; + } + /* n < -1, need more input */ + return nil; + }else if(r == Kalt){ + alting = 1; + nk = 0; + return nil; + }else{ + k[0] = r; + k[1] = 0; + return k; + } +} + +int +xtoplan9kbd(XEvent *e) +{ + static Rune *r; + + if(e == (XEvent*)-1){ + assert(r); + r--; + return 0; + } + if(e) + r = xtoplan9latin1(e); + if(r && *r) + return *r++; + return -1; +} + int -xtoplan9mouse(XEvent *e, Mouse *m) +xtoplan9mouse(XDisplay *xd, XEvent *e, Mouse *m) { int s; XButtonEvent *be; XMotionEvent *me; + if(_x.putsnarf != _x.assertsnarf){ + _x.assertsnarf = _x.putsnarf; + XSetSelectionOwner(_x.mousecon, XA_PRIMARY, _x.drawable, CurrentTime); + if(_x.clipboard != None) + XSetSelectionOwner(_x.mousecon, _x.clipboard, _x.drawable, CurrentTime); + XFlush(xd); + } + switch(e->type){ case ButtonPress: be = (XButtonEvent*)e; + /* Fake message, just sent to make us announce snarf. */ + if(be->send_event && be->state==~0 && be->button==~0) + return -1; /* BUG? on mac need to inherit these from elsewhere? */ m->xy.x = be->x; m->xy.y = be->y; @@ -265,34 +331,55 @@ char* xgetsnarf(XDisplay *xd) { uchar *data, *xdata; - Atom type; + Atom clipboard, type, prop; ulong len, lastlen, dummy; int fmt, i; XWindow w; qlock(&clip.lk); + /* + * Is there a primary selection (highlighted text in an xterm)? + */ + clipboard = XA_PRIMARY; w = XGetSelectionOwner(xd, XA_PRIMARY); if(w == _x.drawable){ + mine: data = (uchar*)strdup(clip.buf); goto out; } + + /* + * If not, is there a clipboard selection? + */ + if(w == None && _x.clipboard != None){ + clipboard = _x.clipboard; + w = XGetSelectionOwner(xd, _x.clipboard); + if(w == _x.drawable) + goto mine; + } + + /* + * If not, give up. + */ 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. + * 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. */ - XChangeProperty(xd, _x.drawable, XA_PRIMARY, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); - XConvertSelection(xd, XA_PRIMARY, XA_STRING, None, _x.drawable, CurrentTime); + prop = 1; + XChangeProperty(xd, _x.drawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); + XConvertSelection(xd, clipboard, XA_STRING, prop, _x.drawable, CurrentTime); XFlush(xd); lastlen = 0; - for(i=0; i<30; i++){ + for(i=0; i<10 || (lastlen!=0 && i<30); i++){ usleep(100*1000); - XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, 0, 0, AnyPropertyType, + XGetWindowProperty(xd, _x.drawable, prop, 0, 0, 0, AnyPropertyType, &type, &fmt, &dummy, &len, &data); if(lastlen == len && len > 0) break; @@ -304,7 +391,7 @@ xgetsnarf(XDisplay *xd) } /* get the property */ data = nil; - XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, SnarfSize/4, 0, + XGetWindowProperty(xd, _x.drawable, prop, 0, SnarfSize/sizeof(ulong), 0, AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); if(type != XA_STRING || len == 0){ if(xdata) @@ -325,16 +412,25 @@ out: void xputsnarf(XDisplay *xd, char *data) { + XButtonEvent e; + 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); + + /* leave note for mouse proc to assert selection ownership */ + _x.putsnarf++; + + /* send mouse a fake event so snarf is announced */ + memset(&e, 0, sizeof e); + e.type = ButtonPress; + e.window = _x.drawable; + e.state = ~0; + e.button = ~0; + XSendEvent(xd, _x.drawable, True, ButtonPressMask, (XEvent*)&e); XFlush(xd); + qunlock(&clip.lk); } |