x11-init.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       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 }