Unified · Split
| @@ -32,6 +32,11 @@ enum { · 31 unmodified lines | |||
| 32 | CursorSize= 32 | 32 | CursorSize= 32 |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | /* snarf buffer size */ | ||
| 36 | enum{ | ||
| 37 | SnarfSize= 100*1024 | ||
| 38 | }; | ||
| 39 | |||
| 35 | /* Datatypes: */ | 40 | /* Datatypes: */ |
| 36 | typedef struct Client Client; | 41 | typedef struct Client Client; |
| 37 | typedef struct DImage DImage; | 42 | typedef struct DImage DImage; |
| @@ -44,6 +49,7 @@ typedef struct Kbdbuf Kbdbuf; · 6 unmodified lines | |||
| 44 | typedef struct Refresh Refresh; | 49 | typedef struct Refresh Refresh; |
| 45 | typedef struct Refx Refx; | 50 | typedef struct Refx Refx; |
| 46 | typedef struct Cursor Cursor; | 51 | typedef struct Cursor Cursor; |
| 52 | typedef struct Clip Clip; | ||
| 47 | typedef struct Window Window; | 53 | typedef struct Window Window; |
| 48 | 54 | ||
| 49 | /* Drawing device */ | 55 | /* Drawing device */ |
| @@ -167,6 +173,12 @@ struct Cursor { · 117 unmodified lines | |||
| 167 | uchar mask[(CursorSize/8)*CursorSize]; | 173 | uchar mask[(CursorSize/8)*CursorSize]; |
| 168 | }; | 174 | }; |
| 169 | 175 | ||
| 176 | /* snarf buffer */ | ||
| 177 | struct Clip | ||
| 178 | { | ||
| 179 | char buf[SnarfSize]; | ||
| 180 | }; | ||
| 181 | |||
| 170 | /* Window system */ | 182 | /* Window system */ |
| 171 | struct Window | 183 | struct Window |
| 172 | { | 184 | { |
| @@ -194,4 +206,5 @@ int nwindow; · 21 unmodified lines | |||
| 194 | Window **window; | 206 | Window **window; |
| 195 | int nclient; | 207 | int nclient; |
| 196 | Client **client; | 208 | Client **client; |
| 209 | Clip clip; | ||
| 197 | 210 | ||
| @@ -49,3 +49,5 @@ int xupdatelabel(Window*); · 48 unmodified lines | |||
| 49 | void xtopwindow(Window*); | 49 | void xtopwindow(Window*); |
| 50 | void xresizewindow(Window*, Rectangle); | 50 | void xresizewindow(Window*, Rectangle); |
| 51 | void xsetcursor(Window*); | 51 | void xsetcursor(Window*); |
| 52 | char* xgetsnarf(Window*); | ||
| 53 | void xputsnarf(Window*, char*); | ||
| @@ -140,6 +140,8 @@ static IxpDirtab* dirtab[] = { · 139 unmodified lines | |||
| 140 | typedef char* (*MsgFunc)(void*, IxpMsg*); | 140 | typedef char* (*MsgFunc)(void*, IxpMsg*); |
| 141 | typedef char* (*BufFunc)(void*); | 141 | typedef char* (*BufFunc)(void*); |
| 142 | 142 | ||
| 143 | static char *snarfbuf; | ||
| 144 | |||
| 143 | static void | 145 | static void |
| 144 | dostat(IxpStat *s, IxpFileId *f) { | 146 | dostat(IxpStat *s, IxpFileId *f) { |
| 145 | s->type = 0; | 147 | s->type = 0; |
| @@ -367,6 +369,13 @@ fs_open(Ixp9Req *r) { · 221 unmodified lines | |||
| 367 | w->mouseopen = 1; | 369 | w->mouseopen = 1; |
| 368 | ixp_pending_pushfid(w->mousep, r->fid); | 370 | ixp_pending_pushfid(w->mousep, r->fid); |
| 369 | break; | 371 | break; |
| 372 | case FsFSnarf: | ||
| 373 | if((r->ifcall.topen.mode&3) == ORDWR){ | ||
| 374 | /* one at a time please */ | ||
| 375 | ixp_respond(r, Enoperm); | ||
| 376 | return; | ||
| 377 | } | ||
| 378 | break; | ||
| 370 | } | 379 | } |
| 371 | 380 | ||
| 372 | if((r->ifcall.topen.mode&3) == OEXEC | 381 | if((r->ifcall.topen.mode&3) == OEXEC |
| @@ -388,7 +397,7 @@ fs_walk(Ixp9Req *r) { · 15 unmodified lines | |||
| 388 | 397 | ||
| 389 | void | 398 | void |
| 390 | fs_read(Ixp9Req *r) { | 399 | fs_read(Ixp9Req *r) { |
| 391 | char buf[512]; | 400 | char buf[512], *s; |
| 392 | int n; | 401 | int n; |
| 393 | IxpFileId *f; | 402 | IxpFileId *f; |
| 394 | Client *cl; | 403 | Client *cl; |
| @@ -461,6 +470,7 @@ fs_read(Ixp9Req *r) { · 66 unmodified lines | |||
| 461 | } | 470 | } |
| 462 | n = readrefresh(buf, r->ifcall.io.count, cl); | 471 | n = readrefresh(buf, r->ifcall.io.count, cl); |
| 463 | if(n > 0) { | 472 | if(n > 0) { |
| 473 | |||
| 464 | ixp_srv_readbuf(r, buf, n); | 474 | ixp_srv_readbuf(r, buf, n); |
| 465 | ixp_respond(r, nil); | 475 | ixp_respond(r, nil); |
| 466 | } | 476 | } |
| @@ -472,6 +482,11 @@ fs_read(Ixp9Req *r) { · 5 unmodified lines | |||
| 472 | ixp_srv_readbuf(r, w->label, strlen(w->label)); | 482 | ixp_srv_readbuf(r, w->label, strlen(w->label)); |
| 473 | ixp_respond(r, nil); | 483 | ixp_respond(r, nil); |
| 474 | return; | 484 | return; |
| 485 | case FsFSnarf: | ||
| 486 | s= xgetsnarf(w); | ||
| 487 | ixp_srv_readbuf(r, s, strlen(s)); | ||
| 488 | ixp_respond(r, nil); | ||
| 489 | return; | ||
| 475 | case FsFWctl: | 490 | case FsFWctl: |
| 476 | // XXX TODO: visible, current | 491 | // XXX TODO: visible, current |
| 477 | sprint(buf, "%11d %11d %11d %11d %s %s ", w->orig.x + w->screenr.min.x, w->orig.y + w->screenr.min.y, w->screenr.max.x, w->screenr.max.y, "visible", "current"); | 492 | sprint(buf, "%11d %11d %11d %11d %s %s ", w->orig.x + w->screenr.min.x, w->orig.y + w->screenr.min.y, w->screenr.max.x, w->screenr.max.y, "visible", "current"); |
| @@ -534,7 +549,7 @@ fs_stat(Ixp9Req *r) { · 56 unmodified lines | |||
| 534 | 549 | ||
| 535 | void | 550 | void |
| 536 | fs_write(Ixp9Req *r) { | 551 | fs_write(Ixp9Req *r) { |
| 537 | char *label; | 552 | char *label, *p; |
| 538 | char err[256]; | 553 | char err[256]; |
| 539 | IxpFileId *f; | 554 | IxpFileId *f; |
| 540 | Window *w; | 555 | Window *w; |
| @@ -602,11 +617,38 @@ fs_write(Ixp9Req *r) { · 61 unmodified lines | |||
| 602 | label[r->ifcall.twrite.count] = 0; | 617 | label[r->ifcall.twrite.count] = 0; |
| 603 | setlabel(w, label); | 618 | setlabel(w, label); |
| 604 | break; | 619 | break; |
| 620 | case FsFSnarf: | ||
| 621 | if(r->ifcall.twrite.offset+r->ifcall.twrite.count >= SnarfSize){ | ||
| 622 | ixp_respond(r, "too much snarf"); | ||
| 623 | return; | ||
| 624 | } | ||
| 625 | if(r->ifcall.twrite.count == 0){ | ||
| 626 | r->ofcall.io.count = r->ifcall.io.count; | ||
| 627 | break; | ||
| 628 | } | ||
| 629 | if(snarfbuf == nil) | ||
| 630 | r->ofcall.io.count = 0; | ||
| 631 | else | ||
| 632 | r->ofcall.io.count = strlen(snarfbuf); | ||
| 633 | if(r->ifcall.twrite.offset+r->ifcall.twrite.count > r->ofcall.io.count){ | ||
| 634 | r->ofcall.io.count = r->ifcall.twrite.offset+r->ifcall.twrite.count; | ||
| 635 | p = malloc(r->ofcall.io.count+1); | ||
| 636 | if(p == nil){ | ||
| 637 | ixp_respond(r, Enomem); | ||
| 638 | return; | ||
| 639 | } | ||
| 640 | if(snarfbuf){ | ||
| 641 | strcpy(p, snarfbuf); | ||
| 642 | free(snarfbuf); | ||
| 643 | } | ||
| 644 | snarfbuf = p; | ||
| 645 | } | ||
| 646 | memmove(snarfbuf+r->ifcall.twrite.offset, r->ifcall.twrite.data, r->ifcall.twrite.count); | ||
| 647 | break; | ||
| 605 | case FsFWctl: | 648 | case FsFWctl: |
| 606 | r->ofcall.io.count = r->ifcall.io.count; | 649 | r->ofcall.io.count = r->ifcall.io.count; |
| 607 | wctlmesg(w, r->ifcall.twrite.data, r->ofcall.rwrite.count, err); | 650 | wctlmesg(w, r->ifcall.twrite.data, r->ofcall.rwrite.count, err); |
| 608 | ixp_respond(r, nil); | 651 | break; |
| 609 | return; | ||
| 610 | } | 652 | } |
| 611 | ixp_respond(r, nil); | 653 | ixp_respond(r, nil); |
| 612 | } | 654 | } |
| @@ -639,8 +681,19 @@ fs_clunk(Ixp9Req *r) { · 26 unmodified lines | |||
| 639 | } | 681 | } |
| 640 | 682 | ||
| 641 | // TODO: ../../inferno-os/emu/port/devdraw.c:971 | 683 | // TODO: ../../inferno-os/emu/port/devdraw.c:971 |
| 642 | if(f->tab.type == FsFCtl) | 684 | switch(f->tab.type){ |
| 685 | case FsFCtl: | ||
| 643 | cl->busy = 0; | 686 | cl->busy = 0; |
| 687 | case FsFSnarf: | ||
| 688 | if(r->fid->omode == OWRITE){ | ||
| 689 | if(snarfbuf) | ||
| 690 | xputsnarf(w, snarfbuf); | ||
| 691 | else | ||
| 692 | xputsnarf(w, ""); | ||
| 693 | } | ||
| 694 | free(snarfbuf); | ||
| 695 | |||
| 696 | } | ||
| 644 | if(!iswindow(f->tab.type) && (decref(&cl->r)==0)) | 697 | if(!iswindow(f->tab.type) && (decref(&cl->r)==0)) |
| 645 | drawfree(cl); | 698 | drawfree(cl); |
| 646 | ixp_respond(r, nil); | 699 | ixp_respond(r, nil); |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | #include <memlayer.h> | 4 | #include <memlayer.h> |
| 5 | #include <cursor.h> | 5 | #include <cursor.h> |
| 6 | #include "dat.h" | 6 | #include "dat.h" |
| 7 | #include "fns.h" | ||
| 7 | #include "inc.h" | 8 | #include "inc.h" |
| 8 | #include "x.h" | 9 | #include "x.h" |
| 9 | 10 | ||
| @@ -182,6 +183,9 @@ xinit(void) · 172 unmodified lines | |||
| 182 | setupcmap(xconn.root); | 183 | setupcmap(xconn.root); |
| 183 | } | 184 | } |
| 184 | xconn.screenrect = Rect(0, 0, WidthOfScreen(xconn.screen), HeightOfScreen(xconn.screen)); | 185 | xconn.screenrect = Rect(0, 0, WidthOfScreen(xconn.screen), HeightOfScreen(xconn.screen)); |
| 186 | |||
| 187 | xinitclipboard(); | ||
| 188 | |||
| 185 | return 0; | 189 | return 0; |
| 186 | } | 190 | } |
| 187 | 191 | ||
| @@ -75,6 +75,10 @@ NextEvent: · 74 unmodified lines | |||
| 75 | writekbd(w, -1);; | 75 | writekbd(w, -1);; |
| 76 | break; | 76 | break; |
| 77 | 77 | ||
| 78 | case SelectionRequest: | ||
| 79 | xselect(&xev); | ||
| 80 | break; | ||
| 81 | |||
| 78 | default: | 82 | default: |
| 79 | break; | 83 | break; |
| 80 | } | 84 | } |
| @@ -178,6 +182,7 @@ mouseevent(Window *w, XEvent xev) · 97 unmodified lines | |||
| 178 | { | 182 | { |
| 179 | Mouse m; | 183 | Mouse m; |
| 180 | 184 | ||
| 185 | xsetsnarfowner(w); | ||
| 181 | if(xtoplan9mouse(&xev, &m) < 0) | 186 | if(xtoplan9mouse(&xev, &m) < 0) |
| 182 | return; | 187 | return; |
| 183 | // debugev("Mouse event at window %d: x=%d y=%d b=%d\n", w->id, m.xy.x, m.xy.y, m.buttons); | 188 | // debugev("Mouse event at window %d: x=%d y=%d b=%d\n", w->id, m.xy.x, m.xy.y, m.buttons); |
| @@ -8,6 +8,14 @@ · 7 unmodified lines | |||
| 8 | #include "inc.h" | 8 | #include "inc.h" |
| 9 | #include "x.h" | 9 | #include "x.h" |
| 10 | 10 | ||
| 11 | /* for copy/paste, lifted from plan9ports via drawterm */ | ||
| 12 | static int putsnarf, assertsnarf; | ||
| 13 | static Atom clipboard; | ||
| 14 | static Atom utf8string; | ||
| 15 | static Atom targets; | ||
| 16 | static Atom text; | ||
| 17 | static Atom compoundtext; | ||
| 18 | |||
| 11 | long keysym2ucs(KeySym); | 19 | long keysym2ucs(KeySym); |
| 12 | int | 20 | int |
| 13 | xtoplan9kbd(XEvent *e) | 21 | xtoplan9kbd(XEvent *e) |
| @@ -126,16 +134,6 @@ xtoplan9mouse(XEvent *e, Mouse *m) · 112 unmodified lines | |||
| 126 | XButtonEvent *be; | 134 | XButtonEvent *be; |
| 127 | XMotionEvent *me; | 135 | XMotionEvent *me; |
| 128 | 136 | ||
| 129 | /* TODO | ||
| 130 | if(_x.putsnarf != _x.assertsnarf){ | ||
| 131 | _x.assertsnarf = _x.putsnarf; | ||
| 132 | XSetSelectionOwner(_x.display, XA_PRIMARY, _x.drawable, CurrentTime); | ||
| 133 | if(_x.clipboard != None) | ||
| 134 | XSetSelectionOwner(_x.display, _x.clipboard, _x.drawable, CurrentTime); | ||
| 135 | XFlush(_x.display); | ||
| 136 | } | ||
| 137 | */ | ||
| 138 | |||
| 139 | switch(e->type){ | 137 | switch(e->type){ |
| 140 | case ButtonPress: | 138 | case ButtonPress: |
| 141 | be = (XButtonEvent*)e; | 139 | be = (XButtonEvent*)e; |
| @@ -222,3 +220,207 @@ xtoplan9mouse(XEvent *e, Mouse *m) · 80 unmodified lines | |||
| 222 | m->buttons |= 16; | 220 | m->buttons |= 16; |
| 223 | return 0; | 221 | return 0; |
| 224 | } | 222 | } |
| 223 | |||
| 224 | /* | ||
| 225 | * Cut and paste. Just couldn't stand to make this simple... | ||
| 226 | */ | ||
| 227 | |||
| 228 | void | ||
| 229 | xinitclipboard(void){ | ||
| 230 | clipboard = XInternAtom(xconn.display, "CLIPBOARD", False); | ||
| 231 | utf8string = XInternAtom(xconn.display, "UTF8_STRING", False); | ||
| 232 | targets = XInternAtom(xconn.display, "TARGETS", False); | ||
| 233 | text = XInternAtom(xconn.display, "TEXT", False); | ||
| 234 | compoundtext = XInternAtom(xconn.display, "COMPOUND_TEXT", False); | ||
| 235 | } | ||
| 236 | |||
| 237 | void | ||
| 238 | xsetsnarfowner(Window *w) | ||
| 239 | { | ||
| 240 | Xwin *xw; | ||
| 241 | |||
| 242 | xw = w->x; | ||
| 243 | if(putsnarf != assertsnarf){ | ||
| 244 | assertsnarf = putsnarf; | ||
| 245 | XSetSelectionOwner(xconn.display, XA_PRIMARY, xw->drawable, CurrentTime); | ||
| 246 | if(clipboard != None) | ||
| 247 | XSetSelectionOwner(xconn.display, clipboard, xw->drawable, CurrentTime); | ||
| 248 | XFlush(xconn.display); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | char* | ||
| 253 | xgetsnarf(Window *window) | ||
| 254 | { | ||
| 255 | uchar *data, *xdata; | ||
| 256 | Atom clipboard, type, prop; | ||
| 257 | unsigned long len, lastlen, dummy; | ||
| 258 | int fmt, i; | ||
| 259 | XWindow w, xdrawable; | ||
| 260 | XDisplay *xd; | ||
| 261 | Xwin *xw; | ||
| 262 | |||
| 263 | /* | ||
| 264 | * Have we snarfed recently and the X server hasn't caught up? | ||
| 265 | */ | ||
| 266 | if(putsnarf != assertsnarf) | ||
| 267 | goto mine; | ||
| 268 | |||
| 269 | xd = xconn.display; | ||
| 270 | xw = window->x; | ||
| 271 | xdrawable = xw->drawable; | ||
| 272 | |||
| 273 | /* | ||
| 274 | * Is there a primary selection (highlighted text in an xterm)? | ||
| 275 | */ | ||
| 276 | clipboard = XA_PRIMARY; | ||
| 277 | w = XGetSelectionOwner(xd, XA_PRIMARY); | ||
| 278 | if(w == xdrawable){ | ||
| 279 | mine: | ||
| 280 | data = (uchar*)strdup(clip.buf); | ||
| 281 | goto out; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* | ||
| 285 | * If not, is there a clipboard selection? | ||
| 286 | */ | ||
| 287 | if(w == None && clipboard != None){ | ||
| 288 | clipboard = clipboard; | ||
| 289 | w = XGetSelectionOwner(xd, clipboard); | ||
| 290 | if(w == xdrawable) | ||
| 291 | goto mine; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * If not, give up. | ||
| 296 | */ | ||
| 297 | if(w == None){ | ||
| 298 | data = nil; | ||
| 299 | goto out; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* | ||
| 303 | * We should be waiting for SelectionNotify here, but it might never | ||
| 304 | * come, and we have no way to time out. Instead, we will clear | ||
| 305 | * local property #1, request our buddy to fill it in for us, and poll | ||
| 306 | * until he's done or we get tired of waiting. | ||
| 307 | * | ||
| 308 | * We should try to go for utf8string instead of XA_STRING, | ||
| 309 | * but that would add to the polling. | ||
| 310 | */ | ||
| 311 | prop = 1; | ||
| 312 | XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); | ||
| 313 | XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime); | ||
| 314 | XFlush(xd); | ||
| 315 | lastlen = 0; | ||
| 316 | for(i=0; i<10 || (lastlen!=0 && i<30); i++){ | ||
| 317 | usleep(10*1000); | ||
| 318 | XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType, | ||
| 319 | &type, &fmt, &dummy, &len, &data); | ||
| 320 | if(lastlen == len && len > 0) | ||
| 321 | break; | ||
| 322 | lastlen = len; | ||
| 323 | } | ||
| 324 | if(i == 10){ | ||
| 325 | data = nil; | ||
| 326 | goto out; | ||
| 327 | } | ||
| 328 | /* get the property */ | ||
| 329 | data = nil; | ||
| 330 | XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(unsigned long), 0, | ||
| 331 | AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); | ||
| 332 | if((type != XA_STRING && type != utf8string) || len == 0){ | ||
| 333 | if(xdata) | ||
| 334 | XFree(xdata); | ||
| 335 | data = nil; | ||
| 336 | }else{ | ||
| 337 | if(xdata){ | ||
| 338 | data = (uchar*)strdup((char*)xdata); | ||
| 339 | XFree(xdata); | ||
| 340 | }else | ||
| 341 | data = nil; | ||
| 342 | } | ||
| 343 | out: | ||
| 344 | return (char*)data; | ||
| 345 | } | ||
| 346 | |||
| 347 | void | ||
| 348 | xputsnarf(Window *window, char *data) | ||
| 349 | { | ||
| 350 | XButtonEvent e; | ||
| 351 | XWindow xdrawable; | ||
| 352 | Xwin *xw; | ||
| 353 | |||
| 354 | if(strlen(data) >= SnarfSize) | ||
| 355 | return; | ||
| 356 | strcpy(clip.buf, data); | ||
| 357 | |||
| 358 | xw = window->x; | ||
| 359 | xdrawable = xw->drawable; | ||
| 360 | |||
| 361 | /* leave note for mouse proc to assert selection ownership */ | ||
| 362 | putsnarf++; | ||
| 363 | |||
| 364 | /* send mouse a fake event so snarf is announced */ | ||
| 365 | memset(&e, 0, sizeof e); | ||
| 366 | e.type = ButtonPress; | ||
| 367 | e.window = xdrawable; | ||
| 368 | e.state = ~0; | ||
| 369 | e.button = ~0; | ||
| 370 | XSendEvent(xconn.display, xdrawable, True, ButtonPressMask, (XEvent*)&e); | ||
| 371 | XFlush(xconn.display); | ||
| 372 | } | ||
| 373 | |||
| 374 | void | ||
| 375 | xselect(XEvent *e) | ||
| 376 | { | ||
| 377 | char *name; | ||
| 378 | XEvent r; | ||
| 379 | XSelectionRequestEvent *xe; | ||
| 380 | Atom a[4]; | ||
| 381 | XDisplay *xd; | ||
| 382 | |||
| 383 | if(e->xany.type != SelectionRequest) | ||
| 384 | return; | ||
| 385 | |||
| 386 | xd = xconn.display; | ||
| 387 | |||
| 388 | memset(&r, 0, sizeof r); | ||
| 389 | xe = (XSelectionRequestEvent*)e; | ||
| 390 | if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n", | ||
| 391 | xe->target, xe->requestor, xe->property, xe->selection); | ||
| 392 | r.xselection.property = xe->property; | ||
| 393 | if(xe->target == targets){ | ||
| 394 | a[0] = XA_STRING; | ||
| 395 | a[1] = utf8string; | ||
| 396 | a[2] = text; | ||
| 397 | a[3] = compoundtext; | ||
| 398 | |||
| 399 | XChangeProperty(xd, xe->requestor, xe->property, xe->target, | ||
| 400 | 8, PropModeReplace, (uchar*)a, sizeof a); | ||
| 401 | }else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){ | ||
| 402 | /* if the target is STRING we're supposed to reply with Latin1 XXX */ | ||
| 403 | XChangeProperty(xd, xe->requestor, xe->property, xe->target, | ||
| 404 | 8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf)); | ||
| 405 | }else{ | ||
| 406 | iprint("get %d\n", xe->target); | ||
| 407 | name = XGetAtomName(xd, xe->target); | ||
| 408 | if(name == nil) | ||
| 409 | iprint("XGetAtomName failed\n"); | ||
| 410 | else if(strcmp(name, "TIMESTAMP") != 0) | ||
| 411 | iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target); | ||
| 412 | r.xselection.property = None; | ||
| 413 | } | ||
| 414 | |||
| 415 | r.xselection.display = xe->display; | ||
| 416 | /* r.xselection.property filled above */ | ||
| 417 | r.xselection.target = xe->target; | ||
| 418 | r.xselection.type = SelectionNotify; | ||
| 419 | r.xselection.requestor = xe->requestor; | ||
| 420 | r.xselection.time = xe->time; | ||
| 421 | r.xselection.send_event = True; | ||
| 422 | r.xselection.selection = xe->selection; | ||
| 423 | XSendEvent(xd, xe->requestor, False, 0, &r); | ||
| 424 | XFlush(xd); | ||
| 425 | } | ||
| 426 | |||
| @@ -70,3 +70,6 @@ void xmovewindow(Window*, Rectangle); · 69 unmodified lines | |||
| 70 | void xputxdata(Memimage*, Rectangle); | 70 | void xputxdata(Memimage*, Rectangle); |
| 71 | void xmemimagedraw(Memimage*, Rectangle, Memimage*, Point, | 71 | void xmemimagedraw(Memimage*, Rectangle, Memimage*, Point, |
| 72 | Memimage*, Point, int); | 72 | Memimage*, Point, int); |
| 73 | void xinitclipboard(void); | ||
| 74 | void xsetsnarfowner(Window*); | ||
| 75 | void xselect(XEvent*); | ||