History

Rewrite X11 snarf. Maybe this will be better.

Russ Cox committed 21 years ago

Commit 54ca86f1 parent a43c1e63 files · +256 −161Browse files

Unified · Split

3 files
  1. gui-x11/screen.c +235 −161
  2. kern/devdraw.c +18 −0
  3. kern/fns.h +3 −0
gui-x11/screen.c+235−161
@@ -16,9 +16,9 @@ · 15 unmodified lines
16 */16 */
17#define Point IPoint17#define Point IPoint
18#define Rectangle IRectangle18#define Rectangle IRectangle
19#define Display IDisplay19#define Display IDisplay
20#define Font IFont20#define Font IFont
21#define Screen IScreen21#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
81static void xkeyboard(XEvent*);81static void xkeyboard(XEvent*);
82static void xmapping(XEvent*);82static void xmapping(XEvent*);
83static void xdestroy(XEvent*);83static void xdestroy(XEvent*);
84static void xselect(XEvent*);84static void xselect(XEvent*, Display*);
85static void xproc(void*);85static void xproc(void*);
86static Memimage* xinitscreen(void);86static Memimage* xinitscreen(void);
87static void initmap(Window);87static void initmap(Window);
@@ -89,16 +89,18 @@ static GC creategc(Drawable); · 1 unmodified line
89static void graphicscmap(XColor*);89static 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
102static int putsnarf, assertsnarf;
103
102extern Memimage* xallocmemimage(IRectangle, ulong, int);104extern Memimage* xallocmemimage(IRectangle, ulong, int);
103Memimage *gscreen;105Memimage *gscreen;
104Screeninfo screen;106Screeninfo screen;
@@ -134,6 +136,7 @@ attachscreen(IRectangle *r, ulong *chan, int *depth, · 29 unmodified lines
134void136void
135flushmemscreen(IRectangle r)137flushmemscreen(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
160void163void
161mouseset(IPoint xy)164mouseset(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
167static Cursor xcursor;172static 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
199void206void
200cursorarrow(void)207cursorarrow(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
210static void219static 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
627static void
628xselection(XEvent *e)
629{
630 XSelectionRequestEvent *xre;
631 XSelectionEvent *xe;
632}
633
634static void636static void
635xmapping(XEvent *e)637xmapping(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
924typedef struct Clip Clip;946int
925struct Clip947atlocalconsole(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
934Clip clip;
935 951
936enum {952 p = getenv("DRAWTERM_ATLOCALCONSOLE");
937 Chunk = 2048953 if(p && atoi(p) == 1)
938};954 return 1;
939 955
940static void956 p = getenv("DISPLAY");
941xselect(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 xkmcon971 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
990int980/*
991haveclip(void *a)981 * Cut and paste. Just couldn't stand to make this simple...
982 */
983
984typedef struct Clip Clip;
985struct Clip
992{986{
993 return clip.want == clip.have;987 char buf[SnarfSize];
994}988 QLock lk;
989};
990Clip clip;
995 991
996#undef long /* sic */992#undef long /* sic */
997char*993#undef ulong
998clipread(void)994
995static 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 }else1078 }else
1036 data = nil;1079 data = nil;
1037 }1080 }
1081out:
1038 qunlock(&clip.lk);1082 qunlock(&clip.lk);
1039 return (char*)data;1083 return (char*)data;
1040}1084}
1041 1085
1042int1086static void
1043clipwrite(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 event1101 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
1066int1110static void
1067atlocalconsole(void)1111xselect(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;1120if(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)1156char*
1083 return 1;1157clipread(void)
1158{
1159 return _xgetsnarf(xsnarfcon);
1160}
1084 1161
1085 /* try to match against system name (i.e. for ssh) */1162int
1086 if(gethostname(buf, sizeof buf) == 0){1163clipwrite(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
kern/devdraw.c+18−0
@@ -183,6 +183,24 @@ static char Eoldname[] = "named image no longer valid"; · 182 unmodified lines
183static char Enamed[] = "image already has name";183static char Enamed[] = "image already has name";
184static char Ewrongname[] = "wrong name for image";184static char Ewrongname[] = "wrong name for image";
185 185
186int
187drawcanqlock(void)
188{
189 return canqlock(&sdraw.lk);
190}
191
192void
193drawqlock(void)
194{
195 qlock(&sdraw.lk);
196}
197
198void
199drawqunlock(void)
200{
201 qunlock(&sdraw.lk);
202}
203
186static int204static int
187drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp)205drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp)
188{206{
kern/fns.h+3−0
@@ -79,6 +79,9 @@ Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*); · 78 unmodified lines
79int devwstat(Chan*, uchar*, int);79int devwstat(Chan*, uchar*, int);
80void drawactive(int);80void drawactive(int);
81void drawcmap(void);81void drawcmap(void);
82int drawcanqlock(void);
83void drawqlock(void);
84void drawqunlock(void);
82void dumpaproc(Proc*);85void dumpaproc(Proc*);
83void dumpqueues(void);86void dumpqueues(void);
84void dumpregs(Ureg*);87void dumpregs(Ureg*);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t