x11-init.c (19677B)
1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "error.h" 7 #define Image IMAGE /* kernel has its own Image */ 8 #include <draw.h> 9 #include <memdraw.h> 10 #include <keyboard.h> 11 #include <cursor.h> 12 #include "screen.h" 13 #include "x11-inc.h" 14 15 #define argv0 "vxplan9" 16 17 Xprivate _x; 18 19 static int parsewinsize(char *s, Rectangle *r, int *havemin); 20 static void plan9cmap(void); 21 static XGC xgc(XDrawable, int, int); 22 static int setupcmap(XWindow); 23 24 static int 25 xerror(XDisplay *d, XErrorEvent *e) 26 { 27 char buf[200]; 28 29 if(e->request_code == 42) /* XSetInputFocus */ 30 return 0; 31 if(e->request_code == 18) /* XChangeProperty */ 32 return 0; 33 /* 34 * BadDrawable happens in apps that get resized a LOT, 35 * e.g. when KDE is configured to resize continuously 36 * during a window drag. 37 */ 38 if(e->error_code == 9) /* BadDrawable */ 39 return 0; 40 41 fprint(2, "X error: error_code=%d, request_code=%d, minor=%d disp=%p\n", 42 e->error_code, e->request_code, e->minor_code, d); 43 XGetErrorText(d, e->error_code, buf, sizeof buf); 44 fprint(2, "%s\n", buf); 45 return 0; 46 } 47 48 static int 49 xioerror(XDisplay *d) 50 { 51 /*print("X I/O error\n"); */ 52 restoretty(); 53 exit(0); 54 /*sysfatal("X I/O error\n");*/ 55 abort(); 56 return -1; 57 } 58 59 Memimage* 60 _xattach(char *label, char *winsize) 61 { 62 char *argv[2], *disp; 63 int i, havemin, height, mask, n, width, x, xrootid, y; 64 Rectangle r; 65 XClassHint classhint; 66 XDrawable pmid; 67 XPixmapFormatValues *pfmt; 68 XScreen *xscreen; 69 XSetWindowAttributes attr; 70 XSizeHints normalhint; 71 XTextProperty name; 72 XVisualInfo xvi; 73 XWindow xrootwin; 74 XWindowAttributes wattr; 75 XWMHints hint; 76 Atom atoms[2]; 77 78 /* 79 if(XInitThreads() == 0){ 80 fprint(2, "XInitThreads failed\n"); 81 abort(); 82 } 83 */ 84 85 /* 86 * Connect to X server. 87 */ 88 _x.display = XOpenDisplay(NULL); 89 if(_x.display == nil){ 90 disp = getenv("DISPLAY"); 91 werrstr("XOpenDisplay %s: %r", disp ? disp : ":0"); 92 free(disp); 93 return nil; 94 } 95 _x.fd = ConnectionNumber(_x.display); 96 XSetErrorHandler(xerror); 97 XSetIOErrorHandler(xioerror); 98 xrootid = DefaultScreen(_x.display); 99 xrootwin = DefaultRootWindow(_x.display); 100 101 /* 102 * Figure out underlying screen format. 103 */ 104 if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi) 105 || XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){ 106 _x.vis = xvi.visual; 107 _x.depth = 16; 108 } 109 else 110 if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi) 111 || XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){ 112 _x.vis = xvi.visual; 113 _x.depth = 15; 114 } 115 else 116 if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi) 117 || XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){ 118 _x.vis = xvi.visual; 119 _x.depth = 24; 120 } 121 else 122 if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi) 123 || XMatchVisualInfo(_x.display, xrootid, 8, StaticColor, &xvi)){ 124 if(_x.depth > 8){ 125 werrstr("can't deal with colormapped depth %d screens", 126 _x.depth); 127 goto err0; 128 } 129 _x.vis = xvi.visual; 130 _x.depth = 8; 131 } 132 else{ 133 _x.depth = DefaultDepth(_x.display, xrootid); 134 if(_x.depth != 8){ 135 werrstr("can't understand depth %d screen", _x.depth); 136 goto err0; 137 } 138 _x.vis = DefaultVisual(_x.display, xrootid); 139 } 140 141 if(DefaultDepth(_x.display, xrootid) == _x.depth) 142 _x.usetable = 1; 143 144 /* 145 * _x.depth is only the number of significant pixel bits, 146 * not the total number of pixel bits. We need to walk the 147 * display list to find how many actual bits are used 148 * per pixel. 149 */ 150 _x.chan = 0; 151 pfmt = XListPixmapFormats(_x.display, &n); 152 for(i=0; i<n; i++){ 153 if(pfmt[i].depth == _x.depth){ 154 switch(pfmt[i].bits_per_pixel){ 155 case 1: /* untested */ 156 _x.chan = GREY1; 157 break; 158 case 2: /* untested */ 159 _x.chan = GREY2; 160 break; 161 case 4: /* untested */ 162 _x.chan = GREY4; 163 break; 164 case 8: 165 _x.chan = CMAP8; 166 break; 167 case 15: 168 _x.chan = RGB15; 169 break; 170 case 16: /* how to tell RGB15? */ 171 _x.chan = RGB16; 172 break; 173 case 24: /* untested (impossible?) */ 174 _x.chan = RGB24; 175 break; 176 case 32: 177 _x.chan = XRGB32; 178 break; 179 } 180 } 181 } 182 if(_x.chan == 0){ 183 werrstr("could not determine screen pixel format"); 184 goto err0; 185 } 186 187 /* 188 * Set up color map if necessary. 189 */ 190 xscreen = DefaultScreenOfDisplay(_x.display); 191 _x.cmap = DefaultColormapOfScreen(xscreen); 192 if(_x.vis->class != StaticColor){ 193 plan9cmap(); 194 setupcmap(xrootwin); 195 } 196 197 /* 198 * We get to choose the initial rectangle size. 199 * This is arbitrary. In theory we should read the 200 * command line and allow the traditional X options. 201 */ 202 mask = 0; 203 x = 0; 204 y = 0; 205 if(winsize && winsize[0]){ 206 if(parsewinsize(winsize, &r, &havemin) < 0) 207 panic("bad window size: %r"); 208 }else{ 209 /* 210 * Parse the various X resources. Thanks to Peter Canning. 211 */ 212 char *screen_resources, *display_resources, *geom, 213 *geomrestype, *home, *file; 214 XrmDatabase database; 215 XrmValue geomres; 216 217 database = XrmGetDatabase(_x.display); 218 screen_resources = XScreenResourceString(xscreen); 219 if(screen_resources != nil){ 220 XrmCombineDatabase(XrmGetStringDatabase(screen_resources), &database, False); 221 XFree(screen_resources); 222 } 223 224 display_resources = XResourceManagerString(_x.display); 225 if(display_resources == nil){ 226 home = getenv("HOME"); 227 if(home!=nil && (file=smprint("%s/.Xdefaults", home)) != nil){ 228 XrmCombineFileDatabase(file, &database, False); 229 free(file); 230 } 231 }else 232 XrmCombineDatabase(XrmGetStringDatabase(display_resources), &database, False); 233 234 geom = smprint("%s.geometry", label); 235 if(geom && XrmGetResource(database, geom, nil, &geomrestype, &geomres)) 236 mask = XParseGeometry(geomres.addr, &x, &y, (uint*)&width, (uint*)&height); 237 free(geom); 238 239 if((mask & WidthValue) && (mask & HeightValue)){ 240 r = Rect(0, 0, width, height); 241 }else{ 242 r = Rect(0, 0, WidthOfScreen(xscreen)*3/4, 243 HeightOfScreen(xscreen)*3/4); 244 if(Dx(r) > Dy(r)*3/2) 245 r.max.x = r.min.x + Dy(r)*3/2; 246 if(Dy(r) > Dx(r)*3/2) 247 r.max.y = r.min.y + Dx(r)*3/2; 248 } 249 if(mask & XNegative){ 250 x += WidthOfScreen(xscreen); 251 } 252 if(mask & YNegative){ 253 y += HeightOfScreen(xscreen); 254 } 255 havemin = 0; 256 } 257 screenrect = Rect(0, 0, WidthOfScreen(xscreen), HeightOfScreen(xscreen)); 258 mouserect = Rect(0, 0, Dx(r), Dy(r)); 259 260 memset(&attr, 0, sizeof attr); 261 attr.colormap = _x.cmap; 262 attr.background_pixel = ~0; 263 attr.border_pixel = 0; 264 _x.drawable = XCreateWindow( 265 _x.display, /* display */ 266 xrootwin, /* parent */ 267 x, /* x */ 268 y, /* y */ 269 Dx(r), /* width */ 270 Dy(r), /* height */ 271 0, /* border width */ 272 _x.depth, /* depth */ 273 InputOutput, /* class */ 274 _x.vis, /* visual */ 275 /* valuemask */ 276 CWBackPixel|CWBorderPixel|CWColormap, 277 &attr /* attributes (the above aren't?!) */ 278 ); 279 280 /* 281 * Label and other properties required by ICCCCM. 282 */ 283 memset(&name, 0, sizeof name); 284 if(label == nil) 285 label = "pjw-face-here"; 286 name.value = (uchar*)label; 287 name.encoding = XA_STRING; 288 name.format = 8; 289 name.nitems = strlen((char*)name.value); 290 291 memset(&normalhint, 0, sizeof normalhint); 292 normalhint.flags = PSize|PMaxSize; 293 if(winsize && winsize[0]){ 294 normalhint.flags &= ~PSize; 295 normalhint.flags |= USSize; 296 normalhint.width = Dx(r); 297 normalhint.height = Dy(r); 298 }else{ 299 if((mask & WidthValue) && (mask & HeightValue)){ 300 normalhint.flags &= ~PSize; 301 normalhint.flags |= USSize; 302 normalhint.width = width; 303 normalhint.height = height; 304 } 305 if((mask & WidthValue) && (mask & HeightValue)){ 306 normalhint.flags |= USPosition; 307 normalhint.x = x; 308 normalhint.y = y; 309 } 310 } 311 312 normalhint.max_width = WidthOfScreen(xscreen); 313 normalhint.max_height = HeightOfScreen(xscreen); 314 315 memset(&hint, 0, sizeof hint); 316 hint.flags = InputHint|StateHint; 317 hint.input = 1; 318 hint.initial_state = NormalState; 319 320 memset(&classhint, 0, sizeof classhint); 321 classhint.res_name = label; 322 classhint.res_class = label; 323 324 argv[0] = label; 325 argv[1] = nil; 326 327 XSetWMProperties( 328 _x.display, /* display */ 329 _x.drawable, /* window */ 330 &name, /* XA_WM_NAME property */ 331 &name, /* XA_WM_ICON_NAME property */ 332 argv, /* XA_WM_COMMAND */ 333 1, /* argc */ 334 &normalhint, /* XA_WM_NORMAL_HINTS */ 335 &hint, /* XA_WM_HINTS */ 336 &classhint /* XA_WM_CLASSHINTS */ 337 ); 338 XFlush(_x.display); 339 340 if(havemin){ 341 XWindowChanges ch; 342 343 memset(&ch, 0, sizeof ch); 344 ch.x = r.min.x; 345 ch.y = r.min.y; 346 XConfigureWindow(_x.display, _x.drawable, CWX|CWY, &ch); 347 /* 348 * Must pretend origin is 0,0 for X. 349 */ 350 r = Rect(0,0,Dx(r),Dy(r)); 351 } 352 353 _x.kmcon = XOpenDisplay(NULL); 354 if(_x.kmcon == nil) 355 panic("XOpenDisplay kmcon"); 356 357 _x.snarfcon = XOpenDisplay(NULL); 358 if(_x.snarfcon == nil) 359 panic("XOpenDisplay snarfcon"); 360 361 /* 362 * Look up clipboard atom. 363 */ 364 _x.clipboard = XInternAtom(_x.display, "CLIPBOARD", False); 365 _x.utf8string = XInternAtom(_x.display, "UTF8_STRING", False); 366 _x.targets = XInternAtom(_x.display, "TARGETS", False); 367 _x.text = XInternAtom(_x.display, "TEXT", False); 368 _x.compoundtext = XInternAtom(_x.display, "COMPOUND_TEXT", False); 369 _x.takefocus = XInternAtom(_x.display, "WM_TAKE_FOCUS", False); 370 _x.losefocus = XInternAtom(_x.display, "_9WM_LOSE_FOCUS", False); 371 _x.wmprotos = XInternAtom(_x.display, "WM_PROTOCOLS", False); 372 _x.wmstate = XInternAtom(_x.display, "_NET_WM_STATE", False); 373 _x.wmfullscreen = XInternAtom(_x.display, "_NET_WM_STATE_FULLSCREEN", False); 374 375 atoms[0] = _x.takefocus; 376 atoms[1] = _x.losefocus; 377 XChangeProperty(_x.display, _x.drawable, _x.wmprotos, XA_ATOM, 32, 378 PropModeReplace, (uchar*)atoms, 2); 379 380 /* 381 * Put the window on the screen, check to see what size we actually got. 382 */ 383 XMapWindow(_x.display, _x.drawable); 384 XSync(_x.display, False); 385 386 if(!XGetWindowAttributes(_x.display, _x.drawable, &wattr)) 387 fprint(2, "XGetWindowAttributes failed\n"); 388 else if(wattr.width && wattr.height){ 389 if(wattr.width != Dx(r) || wattr.height != Dy(r)){ 390 r.max.x = r.min.x + wattr.width; 391 r.max.y = r.min.y + wattr.height; 392 } 393 }else 394 fprint(2, "XGetWindowAttributes: bad attrs\n"); 395 396 /* 397 * Allocate our local backing store. 398 */ 399 _x.screenr = r; 400 _x.screenpm = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth); 401 _x.nextscreenpm = _x.screenpm; 402 _x.screenimage = _xallocmemimage(r, _x.chan, _x.screenpm); 403 if(_x.screenimage == nil) 404 panic("_xallocmemimage failed"); 405 406 /* 407 * Figure out physical window location. 408 */ 409 int rx, ry; 410 XWindow w; 411 if(XTranslateCoordinates(_x.display, _x.drawable, 412 DefaultRootWindow(_x.display), 0, 0, &rx, &ry, &w)) 413 r = Rect(rx, ry, Dx(r), Dy(r)); 414 windowrect = r; 415 416 /* 417 * Allocate some useful graphics contexts for the future. 418 */ 419 _x.gcfill = xgc(_x.screenpm, FillSolid, -1); 420 _x.gccopy = xgc(_x.screenpm, -1, -1); 421 _x.gcsimplesrc = xgc(_x.screenpm, FillStippled, -1); 422 _x.gczero = xgc(_x.screenpm, -1, -1); 423 _x.gcreplsrc = xgc(_x.screenpm, FillTiled, -1); 424 425 pmid = XCreatePixmap(_x.display, _x.drawable, 1, 1, 1); 426 _x.gcfill0 = xgc(pmid, FillSolid, 0); 427 _x.gccopy0 = xgc(pmid, -1, -1); 428 _x.gcsimplesrc0 = xgc(pmid, FillStippled, -1); 429 _x.gczero0 = xgc(pmid, -1, -1); 430 _x.gcreplsrc0 = xgc(pmid, FillTiled, -1); 431 XFreePixmap(_x.display, pmid); 432 433 termreplacescreenimage(_x.screenimage); 434 return _x.screenimage; 435 436 err0: 437 /* 438 * Should do a better job of cleaning up here. 439 */ 440 XCloseDisplay(_x.display); 441 return nil; 442 } 443 444 int 445 _xsetlabel(char *label) 446 { 447 XTextProperty name; 448 449 /* 450 * Label and other properties required by ICCCCM. 451 */ 452 memset(&name, 0, sizeof name); 453 if(label == nil) 454 label = "pjw-face-here"; 455 name.value = (uchar*)label; 456 name.encoding = XA_STRING; 457 name.format = 8; 458 name.nitems = strlen((char*)name.value); 459 460 XSetWMProperties( 461 _x.display, /* display */ 462 _x.drawable, /* window */ 463 &name, /* XA_WM_NAME property */ 464 &name, /* XA_WM_ICON_NAME property */ 465 nil, /* XA_WM_COMMAND */ 466 0, /* argc */ 467 nil, /* XA_WM_NORMAL_HINTS */ 468 nil, /* XA_WM_HINTS */ 469 nil /* XA_WM_CLASSHINTS */ 470 ); 471 XFlush(_x.display); 472 return 0; 473 } 474 475 /* 476 * Create a GC with a particular fill style and XXX. 477 * Disable generation of GraphicsExpose/NoExpose events in the GC. 478 */ 479 static XGC 480 xgc(XDrawable d, int fillstyle, int foreground) 481 { 482 XGC gc; 483 XGCValues v; 484 485 memset(&v, 0, sizeof v); 486 v.function = GXcopy; 487 v.graphics_exposures = False; 488 gc = XCreateGC(_x.display, d, GCFunction|GCGraphicsExposures, &v); 489 if(fillstyle != -1) 490 XSetFillStyle(_x.display, gc, fillstyle); 491 if(foreground != -1) 492 XSetForeground(_x.display, gc, 0); 493 return gc; 494 } 495 496 /* 497 * Initialize map with the Plan 9 rgbv color map. 498 */ 499 static void 500 plan9cmap(void) 501 { 502 int r, g, b, cr, cg, cb, v, num, den, idx, v7, idx7; 503 static int once; 504 505 if(once) 506 return; 507 once = 1; 508 509 for(r=0; r!=4; r++) 510 for(g = 0; g != 4; g++) 511 for(b = 0; b!=4; b++) 512 for(v = 0; v!=4; v++){ 513 den=r; 514 if(g > den) 515 den=g; 516 if(b > den) 517 den=b; 518 /* divide check -- pick grey shades */ 519 if(den==0) 520 cr=cg=cb=v*17; 521 else { 522 num=17*(4*den+v); 523 cr=r*num/den; 524 cg=g*num/den; 525 cb=b*num/den; 526 } 527 idx = r*64 + v*16 + ((g*4 + b + v - r) & 15); 528 _x.map[idx].red = cr*0x0101; 529 _x.map[idx].green = cg*0x0101; 530 _x.map[idx].blue = cb*0x0101; 531 _x.map[idx].pixel = idx; 532 _x.map[idx].flags = DoRed|DoGreen|DoBlue; 533 534 v7 = v >> 1; 535 idx7 = r*32 + v7*16 + g*4 + b; 536 if((v & 1) == v7){ 537 _x.map7to8[idx7][0] = idx; 538 if(den == 0) { /* divide check -- pick grey shades */ 539 cr = ((255.0/7.0)*v7)+0.5; 540 cg = cr; 541 cb = cr; 542 } 543 else { 544 num=17*15*(4*den+v7*2)/14; 545 cr=r*num/den; 546 cg=g*num/den; 547 cb=b*num/den; 548 } 549 _x.map7[idx7].red = cr*0x0101; 550 _x.map7[idx7].green = cg*0x0101; 551 _x.map7[idx7].blue = cb*0x0101; 552 _x.map7[idx7].pixel = idx7; 553 _x.map7[idx7].flags = DoRed|DoGreen|DoBlue; 554 } 555 else 556 _x.map7to8[idx7][1] = idx; 557 } 558 } 559 560 /* 561 * Initialize and install the rgbv color map as a private color map 562 * for this application. It gets the best colors when it has the 563 * cursor focus. 564 * 565 * We always choose the best depth possible, but that might not 566 * be the default depth. On such "suboptimal" systems, we have to allocate an 567 * empty color map anyway, according to Axel Belinfante. 568 */ 569 static int 570 setupcmap(XWindow w) 571 { 572 char buf[30]; 573 int i; 574 uint32 p, pp; 575 XColor c; 576 577 if(_x.depth <= 1) 578 return 0; 579 580 if(_x.depth >= 24) { 581 if(_x.usetable == 0) 582 _x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocNone); 583 584 /* 585 * The pixel value returned from XGetPixel needs to 586 * be converted to RGB so we can call rgb2cmap() 587 * to translate between 24 bit X and our color. Unfortunately, 588 * the return value appears to be display server endian 589 * dependant. Therefore, we run some heuristics to later 590 * determine how to mask the int value correctly. 591 * Yeah, I know we can look at _x.vis->byte_order but 592 * some displays say MSB even though they run on LSB. 593 * Besides, this is more anal. 594 */ 595 c = _x.map[19]; /* known to have different R, G, B values */ 596 if(!XAllocColor(_x.display, _x.cmap, &c)){ 597 werrstr("XAllocColor: %r"); 598 return -1; 599 } 600 p = c.pixel; 601 pp = rgb2cmap((p>>16)&0xff,(p>>8)&0xff,p&0xff); 602 if(pp != _x.map[19].pixel) { 603 /* check if endian is other way */ 604 pp = rgb2cmap(p&0xff,(p>>8)&0xff,(p>>16)&0xff); 605 if(pp != _x.map[19].pixel){ 606 werrstr("cannot detect X server byte order"); 607 return -1; 608 } 609 610 switch(_x.chan){ 611 case RGB24: 612 _x.chan = BGR24; 613 break; 614 case XRGB32: 615 _x.chan = XBGR32; 616 break; 617 default: 618 werrstr("cannot byteswap channel %s", 619 chantostr(buf, _x.chan)); 620 break; 621 } 622 } 623 }else if(_x.vis->class == TrueColor || _x.vis->class == DirectColor){ 624 /* 625 * Do nothing. We have no way to express a 626 * mixed-endian 16-bit screen, so pretend they don't exist. 627 */ 628 if(_x.usetable == 0) 629 _x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocNone); 630 }else if(_x.vis->class == PseudoColor){ 631 if(_x.usetable == 0){ 632 _x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocAll); 633 XStoreColors(_x.display, _x.cmap, _x.map, 256); 634 for(i = 0; i < 256; i++){ 635 _x.tox11[i] = i; 636 _x.toplan9[i] = i; 637 } 638 }else{ 639 for(i = 0; i < 128; i++){ 640 c = _x.map7[i]; 641 if(!XAllocColor(_x.display, _x.cmap, &c)){ 642 werrstr("can't allocate colors in 7-bit map"); 643 return -1; 644 } 645 _x.tox11[_x.map7to8[i][0]] = c.pixel; 646 _x.tox11[_x.map7to8[i][1]] = c.pixel; 647 _x.toplan9[c.pixel] = _x.map7to8[i][0]; 648 } 649 } 650 }else{ 651 werrstr("unsupported visual class %d", _x.vis->class); 652 return -1; 653 } 654 return 0; 655 } 656 657 void 658 flushmemscreen(Rectangle r) 659 { 660 static Lock flushlock; 661 662 if(up && !up->nlocks.ref && _x.nextscreenpm != _x.screenpm){ 663 qlock(&_x.screenlock); 664 XSync(_x.display, False); 665 XFreePixmap(_x.display, _x.screenpm); 666 _x.screenpm = _x.nextscreenpm; 667 qunlock(&_x.screenlock); 668 } 669 670 if(r.min.x >= r.max.x || r.min.y >= r.max.y) 671 return; 672 lock(&flushlock); 673 XCopyArea(_x.display, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y, 674 Dx(r), Dy(r), r.min.x, r.min.y); 675 XFlush(_x.display); 676 unlock(&flushlock); 677 } 678 679 void 680 _xexpose(XEvent *e) 681 { 682 XExposeEvent *xe; 683 Rectangle r; 684 685 qlock(&_x.screenlock); 686 if(_x.screenpm != _x.nextscreenpm){ 687 qunlock(&_x.screenlock); 688 return; 689 } 690 xe = (XExposeEvent*)e; 691 r.min.x = xe->x; 692 r.min.y = xe->y; 693 r.max.x = xe->x+xe->width; 694 r.max.y = xe->y+xe->height; 695 XCopyArea(_x.display, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y, 696 Dx(r), Dy(r), r.min.x, r.min.y); 697 XSync(_x.display, False); 698 qunlock(&_x.screenlock); 699 } 700 701 int 702 _xdestroy(XEvent *e) 703 { 704 XDestroyWindowEvent *xe; 705 706 xe = (XDestroyWindowEvent*)e; 707 if(xe->window == _x.drawable){ 708 _x.destroyed = 1; 709 return 1; 710 } 711 return 0; 712 } 713 714 int 715 _xconfigure(XEvent *e) 716 { 717 Rectangle r; 718 XConfigureEvent *xe = (XConfigureEvent*)e; 719 720 if(!fullscreen){ 721 int rx, ry; 722 XWindow w; 723 if(XTranslateCoordinates(_x.kmcon, _x.drawable, DefaultRootWindow(_x.display), 0, 0, &rx, &ry, &w)) 724 windowrect = Rect(rx, ry, rx+xe->width, ry+xe->height); 725 } 726 727 if(xe->width == Dx(_x.screenr) && xe->height == Dy(_x.screenr)) 728 return 0; 729 r = Rect(0, 0, xe->width, xe->height); 730 mouserect = r; 731 732 qlock(&_x.screenlock); 733 if(_x.screenpm != _x.nextscreenpm){ 734 XCopyArea(_x.display, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y, 735 Dx(r), Dy(r), r.min.x, r.min.y); 736 XSync(_x.display, False); 737 } 738 qunlock(&_x.screenlock); 739 _x.newscreenr = r; 740 return 1; 741 } 742 743 int 744 _xreplacescreenimage(void) 745 { 746 Memimage *m; 747 XDrawable pixmap; 748 Rectangle r; 749 750 r = _x.newscreenr; 751 752 pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth); 753 m = _xallocmemimage(r, _x.chan, pixmap); 754 if(_x.nextscreenpm != _x.screenpm) 755 XFreePixmap(_x.display, _x.nextscreenpm); 756 _x.nextscreenpm = pixmap; 757 _x.screenr = r; 758 _x.screenimage = m; 759 termreplacescreenimage(m); 760 drawreplacescreenimage(m); 761 _x.screenpm = _x.nextscreenpm; 762 return 1; 763 } 764 765 static int 766 parsewinsize(char *s, Rectangle *r, int *havemin) 767 { 768 char c, *os; 769 int i, j, k, l; 770 771 os = s; 772 *havemin = 0; 773 *r = Rect(0,0,0,0); 774 if(!isdigit((uchar)*s)) 775 goto oops; 776 i = strtol(s, &s, 0); 777 if(*s == 'x'){ 778 s++; 779 if(!isdigit((uchar)*s)) 780 goto oops; 781 j = strtol(s, &s, 0); 782 r->max.x = i; 783 r->max.y = j; 784 if(*s == 0) 785 return 0; 786 if(*s != '@') 787 goto oops; 788 789 s++; 790 if(!isdigit((uchar)*s)) 791 goto oops; 792 i = strtol(s, &s, 0); 793 if(*s != ',' && *s != ' ') 794 goto oops; 795 s++; 796 if(!isdigit((uchar)*s)) 797 goto oops; 798 j = strtol(s, &s, 0); 799 if(*s != 0) 800 goto oops; 801 *r = rectaddpt(*r, Pt(i,j)); 802 *havemin = 1; 803 return 0; 804 } 805 806 c = *s; 807 if(c != ' ' && c != ',') 808 goto oops; 809 s++; 810 if(!isdigit((uchar)*s)) 811 goto oops; 812 j = strtol(s, &s, 0); 813 if(*s != c) 814 goto oops; 815 s++; 816 if(!isdigit((uchar)*s)) 817 goto oops; 818 k = strtol(s, &s, 0); 819 if(*s != c) 820 goto oops; 821 s++; 822 if(!isdigit((uchar)*s)) 823 goto oops; 824 l = strtol(s, &s, 0); 825 if(*s != 0) 826 goto oops; 827 *r = Rect(i,j,k,l); 828 *havemin = 1; 829 return 0; 830 831 oops: 832 werrstr("bad syntax in window size '%s'", os); 833 return -1; 834 }