| @@ -16,9 +16,9 @@ · 15 unmodified lines |
| 16 | */ | 16 | */ |
| 17 | #define Point IPoint | 17 | #define Point IPoint |
| 18 | #define Rectangle IRectangle | 18 | #define Rectangle IRectangle |
| 19 | #define Display IDisplay | 19 | #define Display IDisplay |
| 20 | #define Font IFont | 20 | #define Font IFont |
| 21 | #define Screen IScreen | 21 | #define Screen IScreen |
| 22 | | 22 | |
| 23 | #include <u.h> | 23 | #include <u.h> |
| 24 | #include <libc.h> | 24 | #include <libc.h> |
| @@ -81,7 +81,7 @@ static void xmouse(XEvent*); · 56 unmodified lines |
| 81 | static void xkeyboard(XEvent*); | 81 | static void xkeyboard(XEvent*); |
| 82 | static void xmapping(XEvent*); | 82 | static void xmapping(XEvent*); |
| 83 | static void xdestroy(XEvent*); | 83 | static void xdestroy(XEvent*); |
| 84 | static void xselect(XEvent*); | 84 | static void xselect(XEvent*, Display*); |
| 85 | static void xproc(void*); | 85 | static void xproc(void*); |
| 86 | static Memimage* xinitscreen(void); | 86 | static Memimage* xinitscreen(void); |
| 87 | static void initmap(Window); | 87 | static void initmap(Window); |
| @@ -89,16 +89,18 @@ static GC creategc(Drawable); · 1 unmodified line |
| 89 | static void graphicscmap(XColor*); | 89 | static void graphicscmap(XColor*); |
| 90 | int xscreendepth; | 90 | int xscreendepth; |
| 91 | Drawable xscreenid; | 91 | Drawable xscreenid; |
| 92 | Display* xdisplay; | 92 | Display* xdisplay; /* used holding draw lock */ |
| 93 | Display* xkmcon; | 93 | Display* xkmcon; /* used only in xproc */ |
| 94 | Display* xsnarfcon; | 94 | Display* xsnarfcon; /* used holding clip.lk */ |
| 95 | Visual *xvis; | 95 | Visual *xvis; |
| 96 | GC xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc; | 96 | GC xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc; |
| 97 | GC xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0; | 97 | GC xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0; |
| 98 | ulong xblack; | 98 | ulong xblack; |
| 99 | ulong xwhite; | 99 | ulong xwhite; |
| 100 | ulong xscreenchan; | 100 | ulong xscreenchan; |
| 101 | | 101 | |
| | 102 | static int putsnarf, assertsnarf; |
| | 103 | |
| 102 | extern Memimage* xallocmemimage(IRectangle, ulong, int); | 104 | extern Memimage* xallocmemimage(IRectangle, ulong, int); |
| 103 | Memimage *gscreen; | 105 | Memimage *gscreen; |
| 104 | Screeninfo screen; | 106 | Screeninfo screen; |
| @@ -134,6 +136,7 @@ attachscreen(IRectangle *r, ulong *chan, int *depth, · 29 unmodified lines |
| 134 | void | 136 | void |
| 135 | flushmemscreen(IRectangle r) | 137 | flushmemscreen(IRectangle r) |
| 136 | { | 138 | { |
| | 139 | assert(!drawcanqlock()); |
| 137 | if(r.min.x >= r.max.x || r.min.y >= r.max.y) | 140 | if(r.min.x >= r.max.x || r.min.y >= r.max.y) |
| 138 | return; | 141 | return; |
| 139 | XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y); | 142 | XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y); |
| @@ -160,8 +163,10 @@ revbyte(int b) · 20 unmodified lines |
| 160 | void | 163 | void |
| 161 | mouseset(IPoint xy) | 164 | mouseset(IPoint xy) |
| 162 | { | 165 | { |
| | 166 | drawqlock(); |
| 163 | XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y); | 167 | XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y); |
| 164 | XFlush(xdisplay); | 168 | XFlush(xdisplay); |
| | 169 | drawqunlock(); |
| 165 | } | 170 | } |
| 166 | | 171 | |
| 167 | static Cursor xcursor; | 172 | static Cursor xcursor; |
| @@ -180,6 +185,7 @@ setcursor(void) · 12 unmodified lines |
| 180 | mask[i] = revbyte(cursor.set[i] | cursor.clr[i]); | 185 | mask[i] = revbyte(cursor.set[i] | cursor.clr[i]); |
| 181 | } | 186 | } |
| 182 | | 187 | |
| | 188 | drawqlock(); |
| 183 | fg = map[0]; | 189 | fg = map[0]; |
| 184 | bg = map[255]; | 190 | bg = map[255]; |
| 185 | xsrc = XCreateBitmapFromData(xdisplay, xdrawable, src, 16, 16); | 191 | xsrc = XCreateBitmapFromData(xdisplay, xdrawable, src, 16, 16); |
| @@ -194,17 +200,20 @@ setcursor(void) · 8 unmodified lines |
| 194 | XFreePixmap(xdisplay, xsrc); | 200 | XFreePixmap(xdisplay, xsrc); |
| 195 | XFreePixmap(xdisplay, xmask); | 201 | XFreePixmap(xdisplay, xmask); |
| 196 | XFlush(xdisplay); | 202 | XFlush(xdisplay); |
| | 203 | drawqunlock(); |
| 197 | } | 204 | } |
| 198 | | 205 | |
| 199 | void | 206 | void |
| 200 | cursorarrow(void) | 207 | cursorarrow(void) |
| 201 | { | 208 | { |
| | 209 | drawqlock(); |
| 202 | if(xcursor != 0){ | 210 | if(xcursor != 0){ |
| 203 | XFreeCursor(xdisplay, xcursor); | 211 | XFreeCursor(xdisplay, xcursor); |
| 204 | xcursor = 0; | 212 | xcursor = 0; |
| 205 | } | 213 | } |
| 206 | XUndefineCursor(xdisplay, xdrawable); | 214 | XUndefineCursor(xdisplay, xdrawable); |
| 207 | XFlush(xdisplay); | 215 | XFlush(xdisplay); |
| | 216 | drawqunlock(); |
| 208 | } | 217 | } |
| 209 | | 218 | |
| 210 | static void | 219 | static void |
| @@ -229,7 +238,7 @@ xproc(void *arg) · 18 unmodified lines |
| 229 | for(;;) { | 238 | for(;;) { |
| 230 | //XWindowEvent(xkmcon, xdrawable, mask, &event); | 239 | //XWindowEvent(xkmcon, xdrawable, mask, &event); |
| 231 | XNextEvent(xkmcon, &event); | 240 | XNextEvent(xkmcon, &event); |
| 232 | xselect(&event); | 241 | xselect(&event, xkmcon); |
| 233 | xkeyboard(&event); | 242 | xkeyboard(&event); |
| 234 | xmouse(&event); | 243 | xmouse(&event); |
| 235 | xexpose(&event); | 244 | xexpose(&event); |
| @@ -464,11 +473,11 @@ xinitscreen(void) · 228 unmodified lines |
| 464 | exit(0); | 473 | exit(0); |
| 465 | } | 474 | } |
| 466 | | 475 | |
| 467 | clipboard = XInternAtom(xkmcon, "CLIPBOARD", False); | 476 | clipboard = XInternAtom(xkmcon, "CLIPBOARD", False); |
| 468 | utf8string = XInternAtom(xkmcon, "UTF8_STRING", False); | 477 | utf8string = XInternAtom(xkmcon, "UTF8_STRING", False); |
| 469 | targets = XInternAtom(xkmcon, "TARGETS", False); | 478 | targets = XInternAtom(xkmcon, "TARGETS", False); |
| 470 | text = XInternAtom(xkmcon, "TEXT", False); | 479 | text = XInternAtom(xkmcon, "TEXT", False); |
| 471 | compoundtext = XInternAtom(xkmcon, "COMPOUND_TEXT", False); | 480 | compoundtext = XInternAtom(xkmcon, "COMPOUND_TEXT", False); |
| 472 | | 481 | |
| 473 | xblack = screen->black_pixel; | 482 | xblack = screen->black_pixel; |
| 474 | xwhite = screen->white_pixel; | 483 | xwhite = screen->white_pixel; |
| @@ -624,13 +633,6 @@ xdestroy(XEvent *e) · 149 unmodified lines |
| 624 | exit(0); | 633 | exit(0); |
| 625 | } | 634 | } |
| 626 | | 635 | |
| 627 | static void | | |
| 628 | xselection(XEvent *e) | | |
| 629 | { | | |
| 630 | XSelectionRequestEvent *xre; | | |
| 631 | XSelectionEvent *xe; | | |
| 632 | } | | |
| 633 | | | |
| 634 | static void | 636 | static void |
| 635 | xmapping(XEvent *e) | 637 | xmapping(XEvent *e) |
| 636 | { | 638 | { |
| @@ -691,7 +693,7 @@ xkeyboard(XEvent *e) · 54 unmodified lines |
| 691 | return; | 693 | return; |
| 692 | | 694 | |
| 693 | | 695 | |
| 694 | XLookupString(e,NULL,0,&k,NULL); | 696 | XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL); |
| 695 | | 697 | |
| 696 | if(k == XK_Multi_key || k == NoSymbol) | 698 | if(k == XK_Multi_key || k == NoSymbol) |
| 697 | return; | 699 | return; |
| @@ -781,12 +783,14 @@ xkeyboard(XEvent *e) · 83 unmodified lines |
| 781 | case XK_Super_R: | 783 | case XK_Super_R: |
| 782 | case XK_Hyper_L: | 784 | case XK_Hyper_L: |
| 783 | case XK_Hyper_R: | 785 | case XK_Hyper_R: |
| 784 | return; | 786 | return; |
| 785 | default: /* not ISO-1 or tty control */ | 787 | default: /* not ISO-1 or tty control */ |
| 786 | if(k>0xff) { | 788 | if(k>0xff){ |
| 787 | k = keysym2ucs(k); /* supplied by X */ | 789 | k = keysym2ucs(k); /* supplied by X */ |
| 788 | if(k == -1) return; | 790 | if(k == -1) |
| 789 | } | 791 | return; |
| | 792 | } |
| | 793 | break; |
| 790 | } | 794 | } |
| 791 | } | 795 | } |
| 792 | | 796 | |
| @@ -811,9 +815,27 @@ xmouse(XEvent *e) · 18 unmodified lines |
| 811 | XButtonEvent *be; | 815 | XButtonEvent *be; |
| 812 | XMotionEvent *me; | 816 | XMotionEvent *me; |
| 813 | | 817 | |
| | 818 | if(putsnarf != assertsnarf){ |
| | 819 | assertsnarf = putsnarf; |
| | 820 | XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime); |
| | 821 | if(clipboard != None) |
| | 822 | XSetSelectionOwner(xkmcon, clipboard, xdrawable, CurrentTime); |
| | 823 | XFlush(xkmcon); |
| | 824 | } |
| | 825 | |
| 814 | switch(e->type){ | 826 | switch(e->type){ |
| 815 | case ButtonPress: | 827 | case ButtonPress: |
| 816 | be = (XButtonEvent *)e; | 828 | be = (XButtonEvent *)e; |
| | 829 | /* |
| | 830 | * Fake message, just sent to make us announce snarf. |
| | 831 | * Apparently state and button are 16 and 8 bits on |
| | 832 | * the wire, since they are truncated by the time they |
| | 833 | * get to us. |
| | 834 | */ |
| | 835 | if(be->send_event |
| | 836 | && (~be->state&0xFFFF)==0 |
| | 837 | && (~be->button&0xFF)==0) |
| | 838 | return; |
| 817 | ms.xy.x = be->x; | 839 | ms.xy.x = be->x; |
| 818 | ms.xy.y = be->y; | 840 | ms.xy.y = be->y; |
| 819 | s = be->state; | 841 | s = be->state; |
| @@ -921,174 +943,226 @@ setcolor(ulong i, ulong r, ulong g, ulong b) · 101 unmodified lines |
| 921 | /* no-op */ | 943 | /* no-op */ |
| 922 | } | 944 | } |
| 923 | | 945 | |
| 924 | typedef struct Clip Clip; | 946 | int |
| 925 | struct Clip | 947 | atlocalconsole(void) |
| 926 | { | 948 | { |
| 927 | char buf[SnarfSize]; | 949 | char *p, *q; |
| 928 | ulong n; | 950 | char buf[128]; |
| 929 | int want, have; | | |
| 930 | QLock lk; | | |
| 931 | Rendez vous; | | |
| 932 | }; | | |
| 933 | | | |
| 934 | Clip clip; | | |
| 935 | | 951 | |
| 936 | enum { | 952 | p = getenv("DRAWTERM_ATLOCALCONSOLE"); |
| 937 | Chunk = 2048 | 953 | if(p && atoi(p) == 1) |
| 938 | }; | 954 | return 1; |
| 939 | | 955 | |
| 940 | static void | 956 | p = getenv("DISPLAY"); |
| 941 | xselect(XEvent *e) | 957 | if(p == nil) |
| 942 | { | 958 | return 0; |
| 943 | XSelectionRequestEvent *q; | | |
| 944 | XEvent r; | | |
| 945 | Atom a[4]; | | |
| 946 | char *name; | | |
| 947 | | 959 | |
| | 960 | /* extract host part */ |
| | 961 | q = strchr(p, ':'); |
| | 962 | if(q == nil) |
| | 963 | return 0; |
| | 964 | *q = 0; |
| 948 | | 965 | |
| 949 | if(e->type != SelectionRequest) | 966 | if(strcmp(p, "") == 0) |
| 950 | return; | 967 | return 1; |
| 951 | | 968 | |
| 952 | /* | 969 | /* try to match against system name (i.e. for ssh) */ |
| 953 | * The lock is around the whole routine because we use the | 970 | if(gethostname(buf, sizeof buf) == 0){ |
| 954 | * lock to make sure two people aren't sending on xkmcon | 971 | if(strcmp(p, buf) == 0) |
| 955 | * at once. | 972 | return 1; |
| 956 | */ | 973 | if(strncmp(p, buf, strlen(p)) == 0 && buf[strlen(p)]=='.') |
| 957 | q = (XSelectionRequestEvent*)e; | 974 | return 1; |
| 958 | | | |
| 959 | r.xselection.property = q->property; | | |
| 960 | if(q->target == targets) { | | |
| 961 | a[0] = XA_STRING; | | |
| 962 | a[1] = utf8string; | | |
| 963 | a[2] = text; | | |
| 964 | a[3] = compoundtext; | | |
| 965 | | | |
| 966 | XChangeProperty(xkmcon, q->requestor, q->property, q->target, | | |
| 967 | 8, PropModeReplace, (uchar*)a, sizeof a); | | |
| 968 | }else if(q->target == XA_STRING || q->target == utf8string || q->target == text || q->target == compoundtext){ | | |
| 969 | qlock(&clip.lk); | | |
| 970 | XChangeProperty(xkmcon, q->requestor, q->property, q->target, 8, | | |
| 971 | PropModeReplace, (uchar*)clip.buf, strlen(clip.buf)); | | |
| 972 | qunlock(&clip.lk); | | |
| 973 | }else { | | |
| 974 | name = XGetAtomName(xkmcon, q->target); | | |
| 975 | if(strcmp(name, "TIMESTAMP") != 0) | | |
| 976 | fprint(2, "%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)q->target); | | |
| 977 | r.xselection.property = None; | | |
| 978 | } | 975 | } |
| 979 | | 976 | |
| 980 | r.xselection.type = SelectionNotify; | 977 | return 0; |
| 981 | r.xselection.display = q->display; | | |
| 982 | r.xselection.requestor = q->requestor; | | |
| 983 | r.xselection.selection = q->selection; | | |
| 984 | r.xselection.target = q->target; | | |
| 985 | r.xselection.time = q->time; | | |
| 986 | XSendEvent(xkmcon, q->requestor, False, 0, &r); | | |
| 987 | XFlush(xkmcon); | | |
| 988 | } | 978 | } |
| 989 | | 979 | |
| 990 | int | 980 | /* |
| 991 | haveclip(void *a) | 981 | * Cut and paste. Just couldn't stand to make this simple... |
| | 982 | */ |
| | 983 | |
| | 984 | typedef struct Clip Clip; |
| | 985 | struct Clip |
| 992 | { | 986 | { |
| 993 | return clip.want == clip.have; | 987 | char buf[SnarfSize]; |
| 994 | } | 988 | QLock lk; |
| | 989 | }; |
| | 990 | Clip clip; |
| 995 | | 991 | |
| 996 | #undef long /* sic */ | 992 | #undef long /* sic */ |
| 997 | char* | 993 | #undef ulong |
| 998 | clipread(void) | 994 | |
| | 995 | static char* |
| | 996 | _xgetsnarf(Display *xd) |
| 999 | { | 997 | { |
| | 998 | uchar *data, *xdata; |
| | 999 | Atom clipboard, type, prop; |
| | 1000 | ulong len, lastlen, dummy; |
| | 1001 | int fmt, i; |
| 1000 | Window w; | 1002 | Window w; |
| 1001 | XEvent e; | | |
| 1002 | Atom type; | | |
| 1003 | unsigned long len, lleft, left, dummy; | | |
| 1004 | int i, fmt, res; | | |
| 1005 | uchar *data; | | |
| 1006 | | 1003 | |
| 1007 | qlock(&clip.lk); | 1004 | qlock(&clip.lk); |
| 1008 | w = XGetSelectionOwner(xsnarfcon, XA_PRIMARY); | 1005 | /* |
| 1009 | if(w == xdrawable) | 1006 | * Have we snarfed recently and the X server hasn't caught up? |
| | 1007 | */ |
| | 1008 | if(putsnarf != assertsnarf) |
| | 1009 | goto mine; |
| | 1010 | |
| | 1011 | /* |
| | 1012 | * Is there a primary selection (highlighted text in an xterm)? |
| | 1013 | */ |
| | 1014 | clipboard = XA_PRIMARY; |
| | 1015 | w = XGetSelectionOwner(xd, XA_PRIMARY); |
| | 1016 | if(w == xdrawable){ |
| | 1017 | mine: |
| 1010 | data = (uchar*)strdup(clip.buf); | 1018 | data = (uchar*)strdup(clip.buf); |
| 1011 | else if(w == None) | 1019 | goto out; |
| | 1020 | } |
| | 1021 | |
| | 1022 | /* |
| | 1023 | * If not, is there a clipboard selection? |
| | 1024 | */ |
| | 1025 | if(w == None && clipboard != None){ |
| | 1026 | clipboard = clipboard; |
| | 1027 | w = XGetSelectionOwner(xd, clipboard); |
| | 1028 | if(w == xdrawable) |
| | 1029 | goto mine; |
| | 1030 | } |
| | 1031 | |
| | 1032 | /* |
| | 1033 | * If not, give up. |
| | 1034 | */ |
| | 1035 | if(w == None){ |
| 1012 | data = nil; | 1036 | data = nil; |
| 1013 | else { | 1037 | goto out; |
| 1014 | /* | 1038 | } |
| 1015 | * we're supposed to get a notification, but we seem not to, | 1039 | |
| 1016 | * so let's just watch and see when the buffer stabilizes. | 1040 | /* |
| 1017 | * if you know how to fix this, mail rsc@plan9.bell-labs.com. | 1041 | * We should be waiting for SelectionNotify here, but it might never |
| 1018 | */ | 1042 | * come, and we have no way to time out. Instead, we will clear |
| 1019 | XChangeProperty(xsnarfcon, xdrawable, XA_PRIMARY, XA_STRING, 8, PropModeReplace, | 1043 | * local property #1, request our buddy to fill it in for us, and poll |
| 1020 | (uchar*)"", 0); | 1044 | * until he's done or we get tired of waiting. |
| 1021 | XConvertSelection(xsnarfcon, XA_PRIMARY, XA_STRING, None, xdrawable, CurrentTime); | 1045 | * |
| 1022 | XFlush(xsnarfcon); | 1046 | * We should try to go for utf8string instead of XA_STRING, |
| 1023 | for(i=0; i<30; i++){ | 1047 | * but that would add to the polling. |
| 1024 | osmsleep(100); | 1048 | */ |
| 1025 | XGetWindowProperty(xsnarfcon, xdrawable, XA_STRING, 0, 0, 0, AnyPropertyType, | 1049 | prop = 1; |
| 1026 | &type, &fmt, &len, &left, &data); | 1050 | XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); |
| 1027 | if(lleft == left && left > 0) | 1051 | XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime); |
| 1028 | break; | 1052 | XFlush(xd); |
| 1029 | lleft = left; | 1053 | lastlen = 0; |
| 1030 | } | 1054 | for(i=0; i<10 || (lastlen!=0 && i<30); i++){ |
| 1031 | if(left > 0){ | 1055 | usleep(100*1000); |
| 1032 | res = XGetWindowProperty(xsnarfcon, xdrawable, XA_STRING, 0, left, 0, | 1056 | XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType, |
| 1033 | AnyPropertyType, &type, &fmt, &len, &dummy, &data); | 1057 | &type, &fmt, &dummy, &len, &data); |
| 1034 | data = (uchar*)strdup(data); | 1058 | if(lastlen == len && len > 0) |
| | 1059 | break; |
| | 1060 | lastlen = len; |
| | 1061 | } |
| | 1062 | if(i == 10){ |
| | 1063 | data = nil; |
| | 1064 | goto out; |
| | 1065 | } |
| | 1066 | /* get the property */ |
| | 1067 | data = nil; |
| | 1068 | XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(ulong), 0, |
| | 1069 | AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); |
| | 1070 | if((type != XA_STRING && type != utf8string) || len == 0){ |
| | 1071 | if(xdata) |
| | 1072 | XFree(xdata); |
| | 1073 | data = nil; |
| | 1074 | }else{ |
| | 1075 | if(xdata){ |
| | 1076 | data = (uchar*)strdup((char*)xdata); |
| | 1077 | XFree(xdata); |
| 1035 | }else | 1078 | }else |
| 1036 | data = nil; | 1079 | data = nil; |
| 1037 | } | 1080 | } |
| | 1081 | out: |
| 1038 | qunlock(&clip.lk); | 1082 | qunlock(&clip.lk); |
| 1039 | return (char*)data; | 1083 | return (char*)data; |
| 1040 | } | 1084 | } |
| 1041 | | 1085 | |
| 1042 | int | 1086 | static void |
| 1043 | clipwrite(char *buf) | 1087 | _xputsnarf(Display *xd, char *data) |
| 1044 | { | 1088 | { |
| 1045 | int n; | 1089 | XButtonEvent e; |
| 1046 | | 1090 | |
| 1047 | n = strlen(buf); | 1091 | if(strlen(data) >= SnarfSize) |
| | 1092 | return; |
| 1048 | qlock(&clip.lk); | 1093 | qlock(&clip.lk); |
| 1049 | if(n >= SnarfSize) | 1094 | strcpy(clip.buf, data); |
| 1050 | n = SnarfSize - 1; | 1095 | |
| 1051 | memmove(clip.buf, buf, n); | 1096 | /* leave note for mouse proc to assert selection ownership */ |
| 1052 | clip.buf[n] = 0; | 1097 | putsnarf++; |
| 1053 | clip.n = n; | 1098 | |
| 1054 | /* | 1099 | /* send mouse a fake event so snarf is announced */ |
| 1055 | * xkmcon so that we get the event in the select loop. | 1100 | memset(&e, 0, sizeof e); |
| 1056 | * It seems to be okay to send a message and read an event | 1101 | e.type = ButtonPress; |
| 1057 | * from a Display* at the same time. Let's hope so. | 1102 | e.window = xdrawable; |
| 1058 | */ | 1103 | e.state = ~0; |
| 1059 | XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime); | 1104 | e.button = ~0; |
| 1060 | XFlush(xkmcon); | 1105 | XSendEvent(xd, xdrawable, True, ButtonPressMask, (XEvent*)&e); |
| | 1106 | XFlush(xd); |
| 1061 | qunlock(&clip.lk); | 1107 | qunlock(&clip.lk); |
| 1062 | return n; | | |
| 1063 | } | 1108 | } |
| 1064 | #define long int /* sic */ | | |
| 1065 | | 1109 | |
| 1066 | int | 1110 | static void |
| 1067 | atlocalconsole(void) | 1111 | xselect(XEvent *e, Display *xd) |
| 1068 | { | 1112 | { |
| 1069 | char *p, *q; | 1113 | char *name; |
| 1070 | char buf[128]; | 1114 | XEvent r; |
| | 1115 | XSelectionRequestEvent *xe; |
| | 1116 | Atom a[4]; |
| 1071 | | 1117 | |
| 1072 | p = getenv("DISPLAY"); | 1118 | memset(&r, 0, sizeof r); |
| 1073 | if(p == nil) | 1119 | xe = (XSelectionRequestEvent*)e; |
| 1074 | return 0; | 1120 | if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d\n", |
| | 1121 | xe->target, xe->requestor, xe->property, xe->selection); |
| | 1122 | r.xselection.property = xe->property; |
| | 1123 | if(xe->target == targets){ |
| | 1124 | a[0] = XA_STRING; |
| | 1125 | a[1] = utf8string; |
| | 1126 | a[2] = text; |
| | 1127 | a[3] = compoundtext; |
| | 1128 | |
| | 1129 | XChangeProperty(xd, xe->requestor, xe->property, xe->target, |
| | 1130 | 8, PropModeReplace, (uchar*)a, sizeof a); |
| | 1131 | }else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){ |
| | 1132 | /* if the target is STRING we're supposed to reply with Latin1 XXX */ |
| | 1133 | qlock(&clip.lk); |
| | 1134 | XChangeProperty(xd, xe->requestor, xe->property, xe->target, |
| | 1135 | 8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf)); |
| | 1136 | qunlock(&clip.lk); |
| | 1137 | }else{ |
| | 1138 | name = XGetAtomName(xd, xe->target); |
| | 1139 | if(strcmp(name, "TIMESTAMP") != 0) |
| | 1140 | fprint(2, "%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target); |
| | 1141 | r.xselection.property = None; |
| | 1142 | } |
| 1075 | | 1143 | |
| 1076 | /* extract host part */ | 1144 | r.xselection.display = xe->display; |
| 1077 | q = strchr(p, ':'); | 1145 | /* r.xselection.property filled above */ |
| 1078 | if(q == nil) | 1146 | r.xselection.target = xe->target; |
| 1079 | return 0; | 1147 | r.xselection.type = SelectionNotify; |
| 1080 | *q = 0; | 1148 | r.xselection.requestor = xe->requestor; |
| | 1149 | r.xselection.time = xe->time; |
| | 1150 | r.xselection.send_event = True; |
| | 1151 | r.xselection.selection = xe->selection; |
| | 1152 | XSendEvent(xd, xe->requestor, False, 0, &r); |
| | 1153 | XFlush(xd); |
| | 1154 | } |
| 1081 | | 1155 | |
| 1082 | if(strcmp(p, "") == 0) | 1156 | char* |
| 1083 | return 1; | 1157 | clipread(void) |
| | 1158 | { |
| | 1159 | return _xgetsnarf(xsnarfcon); |
| | 1160 | } |
| 1084 | | 1161 | |
| 1085 | /* try to match against system name (i.e. for ssh) */ | 1162 | int |
| 1086 | if(gethostname(buf, sizeof buf) == 0){ | 1163 | clipwrite(char *buf) |
| 1087 | if(strcmp(p, buf) == 0) | 1164 | { |
| 1088 | return 1; | 1165 | _xputsnarf(xsnarfcon, buf); |
| 1089 | if(strncmp(p, buf, strlen(p)) == 0 && buf[strlen(p)]=='.') | | |
| 1090 | return 1; | | |
| 1091 | } | | |
| 1092 | | | |
| 1093 | return 0; | 1166 | return 0; |
| 1094 | } | 1167 | } |
| | 1168 | |