void Canvas::fillRectangle(const Rect& rect, const Color& color) { Point offset = absolutePosition(); XSetForeground(display()->xdisplay(), xgc(), color.uint()); XFillRectangle( display()->xdisplay(), xdrawable(), xgc(), rect.origin.x + offset.x, rect.origin.y + offset.y, rect.size.w, rect.size.h ); }
void Canvas::drawLine(const Point& a, const Point& b) { XSetForeground(display()->xdisplay(), xgc(), 0xffffff); Point offset = absolutePosition(); XDrawLine( display()->xdisplay(), xdrawable(), xgc(), a.x + offset.x, a.y + offset.y, b.x + offset.x, b.y + offset.y ); }
void Canvas::copyCanvas(const Canvas* canvas, const Rect& src, const Point& origin, bool copyAlpha) { Point offset = absolutePosition(); if ( (rgba() == false && canvas->rgba() == false) || (rgba() == true && canvas->rgba() == true && copyAlpha) ) { XCopyArea( display()->xdisplay(), canvas->xdrawable(), xdrawable(), xgc(), src.origin.x, src.origin.y, src.size.w, src.size.h, origin.x + offset.x, origin.y + offset.y ); } else { XRenderComposite( display()->xdisplay(), PictOpOver, canvas->xpicture(), None, xpicture(), src.origin.x, src.origin.y, 0, 0, origin.x + offset.x, origin.y + offset.y, src.size.w, src.size.h ); } }
Memimage* _xattach(char *label, char *winsize) { char *argv[2], *disp; int i, havemin, height, mask, n, width, x, xrootid, y; Rectangle r; XClassHint classhint; XDrawable pmid; XPixmapFormatValues *pfmt; XScreen *xscreen; XSetWindowAttributes attr; XSizeHints normalhint; XTextProperty name; XVisualInfo xvi; XWindow xrootwin; XWindowAttributes wattr; XWMHints hint; Atom atoms[2]; /* if(XInitThreads() == 0){ fprint(2, "XInitThreads failed\n"); abort(); } */ /* * Connect to X server. */ _x.display = XOpenDisplay(NULL); if(_x.display == nil){ disp = getenv("DISPLAY"); werrstr("XOpenDisplay %s: %r", disp ? disp : ":0"); free(disp); return nil; } _x.fd = ConnectionNumber(_x.display); XSetErrorHandler(xerror); XSetIOErrorHandler(xioerror); xrootid = DefaultScreen(_x.display); xrootwin = DefaultRootWindow(_x.display); /* * Figure out underlying screen format. */ if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi) || XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){ _x.vis = xvi.visual; _x.depth = 24; } else if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi) || XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){ _x.vis = xvi.visual; _x.depth = 16; } else if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi) || XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){ _x.vis = xvi.visual; _x.depth = 15; } else if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi) || XMatchVisualInfo(_x.display, xrootid, 8, StaticColor, &xvi)){ if(_x.depth > 8){ werrstr("can't deal with colormapped depth %d screens", _x.depth); goto err0; } _x.vis = xvi.visual; _x.depth = 8; } else{ _x.depth = DefaultDepth(_x.display, xrootid); if(_x.depth != 8){ werrstr("can't understand depth %d screen", _x.depth); goto err0; } _x.vis = DefaultVisual(_x.display, xrootid); } if(DefaultDepth(_x.display, xrootid) == _x.depth) _x.usetable = 1; /* * _x.depth is only the number of significant pixel bits, * not the total number of pixel bits. We need to walk the * display list to find how many actual bits are used * per pixel. */ _x.chan = 0; pfmt = XListPixmapFormats(_x.display, &n); for(i=0; i<n; i++){ if(pfmt[i].depth == _x.depth){ switch(pfmt[i].bits_per_pixel){ case 1: /* untested */ _x.chan = GREY1; break; case 2: /* untested */ _x.chan = GREY2; break; case 4: /* untested */ _x.chan = GREY4; break; case 8: _x.chan = CMAP8; break; case 15: _x.chan = RGB15; break; case 16: /* how to tell RGB15? */ _x.chan = RGB16; break; case 24: /* untested (impossible?) */ _x.chan = RGB24; break; case 32: _x.chan = XRGB32; break; } } } if(_x.chan == 0){ werrstr("could not determine screen pixel format"); goto err0; } /* * Set up color map if necessary. */ xscreen = DefaultScreenOfDisplay(_x.display); _x.cmap = DefaultColormapOfScreen(xscreen); if(_x.vis->class != StaticColor){ plan9cmap(); setupcmap(xrootwin); } /* * We get to choose the initial rectangle size. * This is arbitrary. In theory we should read the * command line and allow the traditional X options. */ mask = 0; x = 0; y = 0; if(winsize && winsize[0]){ if(parsewinsize(winsize, &r, &havemin) < 0) sysfatal("%r"); }else{ /* * Parse the various X resources. Thanks to Peter Canning. */ char *screen_resources, *display_resources, *geom, *geomrestype, *home, *file; XrmDatabase database; XrmValue geomres; database = XrmGetDatabase(_x.display); screen_resources = XScreenResourceString(xscreen); if(screen_resources != nil){ XrmCombineDatabase(XrmGetStringDatabase(screen_resources), &database, False); XFree(screen_resources); } display_resources = XResourceManagerString(_x.display); if(display_resources == nil){ home = getenv("HOME"); if(home!=nil && (file=smprint("%s/.Xdefaults", home)) != nil){ XrmCombineFileDatabase(file, &database, False); free(file); } free(home); }else XrmCombineDatabase(XrmGetStringDatabase(display_resources), &database, False); geom = smprint("%s.geometry", label); if(geom && XrmGetResource(database, geom, nil, &geomrestype, &geomres)) mask = XParseGeometry(geomres.addr, &x, &y, (uint*)&width, (uint*)&height); free(geom); if((mask & WidthValue) && (mask & HeightValue)){ r = Rect(0, 0, width, height); }else{ r = Rect(0, 0, WidthOfScreen(xscreen)*3/4, HeightOfScreen(xscreen)*3/4); if(Dx(r) > Dy(r)*3/2) r.max.x = r.min.x + Dy(r)*3/2; if(Dy(r) > Dx(r)*3/2) r.max.y = r.min.y + Dx(r)*3/2; } if(mask & XNegative){ x += WidthOfScreen(xscreen); } if(mask & YNegative){ y += HeightOfScreen(xscreen); } havemin = 0; } screenrect = Rect(0, 0, WidthOfScreen(xscreen), HeightOfScreen(xscreen)); windowrect = r; memset(&attr, 0, sizeof attr); attr.colormap = _x.cmap; attr.background_pixel = ~0; attr.border_pixel = 0; _x.drawable = XCreateWindow( _x.display, /* display */ xrootwin, /* parent */ x, /* x */ y, /* y */ Dx(r), /* width */ Dy(r), /* height */ 0, /* border width */ _x.depth, /* depth */ InputOutput, /* class */ _x.vis, /* visual */ /* valuemask */ CWBackPixel|CWBorderPixel|CWColormap, &attr /* attributes (the above aren't?!) */ ); /* * Label and other properties required by ICCCCM. */ memset(&name, 0, sizeof name); if(label == nil) label = "pjw-face-here"; name.value = (uchar*)label; name.encoding = XA_STRING; name.format = 8; name.nitems = strlen((char*)name.value); memset(&normalhint, 0, sizeof normalhint); normalhint.flags = PSize|PMaxSize; if(winsize && winsize[0]){ normalhint.flags &= ~PSize; normalhint.flags |= USSize; normalhint.width = Dx(r); normalhint.height = Dy(r); }else{ if((mask & WidthValue) && (mask & HeightValue)){ normalhint.flags &= ~PSize; normalhint.flags |= USSize; normalhint.width = width; normalhint.height = height; } if((mask & WidthValue) && (mask & HeightValue)){ normalhint.flags |= USPosition; normalhint.x = x; normalhint.y = y; } } normalhint.max_width = WidthOfScreen(xscreen); normalhint.max_height = HeightOfScreen(xscreen); memset(&hint, 0, sizeof hint); hint.flags = InputHint|StateHint; hint.input = 1; hint.initial_state = NormalState; memset(&classhint, 0, sizeof classhint); classhint.res_name = label; classhint.res_class = label; argv[0] = label; argv[1] = nil; XSetWMProperties( _x.display, /* display */ _x.drawable, /* window */ &name, /* XA_WM_NAME property */ &name, /* XA_WM_ICON_NAME property */ argv, /* XA_WM_COMMAND */ 1, /* argc */ &normalhint, /* XA_WM_NORMAL_HINTS */ &hint, /* XA_WM_HINTS */ &classhint /* XA_WM_CLASSHINTS */ ); XFlush(_x.display); if(havemin){ XWindowChanges ch; memset(&ch, 0, sizeof ch); ch.x = r.min.x; ch.y = r.min.y; XConfigureWindow(_x.display, _x.drawable, CWX|CWY, &ch); /* * Must pretend origin is 0,0 for X. */ r = Rect(0,0,Dx(r),Dy(r)); } /* * Look up clipboard atom. */ _x.clipboard = XInternAtom(_x.display, "CLIPBOARD", False); _x.utf8string = XInternAtom(_x.display, "UTF8_STRING", False); _x.targets = XInternAtom(_x.display, "TARGETS", False); _x.text = XInternAtom(_x.display, "TEXT", False); _x.compoundtext = XInternAtom(_x.display, "COMPOUND_TEXT", False); _x.takefocus = XInternAtom(_x.display, "WM_TAKE_FOCUS", False); _x.losefocus = XInternAtom(_x.display, "_9WM_LOSE_FOCUS", False); _x.wmprotos = XInternAtom(_x.display, "WM_PROTOCOLS", False); atoms[0] = _x.takefocus; atoms[1] = _x.losefocus; XChangeProperty(_x.display, _x.drawable, _x.wmprotos, XA_ATOM, 32, PropModeReplace, (uchar*)atoms, 2); /* * Put the window on the screen, check to see what size we actually got. */ XMapWindow(_x.display, _x.drawable); XSync(_x.display, False); if(!XGetWindowAttributes(_x.display, _x.drawable, &wattr)) fprint(2, "XGetWindowAttributes failed\n"); else if(wattr.width && wattr.height){ if(wattr.width != Dx(r) || wattr.height != Dy(r)){ r.max.x = wattr.width; r.max.y = wattr.height; } }else fprint(2, "XGetWindowAttributes: bad attrs\n"); /* * Allocate our local backing store. */ _x.screenr = r; _x.screenpm = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth); _x.nextscreenpm = _x.screenpm; _x.screenimage = _xallocmemimage(r, _x.chan, _x.screenpm); /* * Allocate some useful graphics contexts for the future. */ _x.gcfill = xgc(_x.screenpm, FillSolid, -1); _x.gccopy = xgc(_x.screenpm, -1, -1); _x.gcsimplesrc = xgc(_x.screenpm, FillStippled, -1); _x.gczero = xgc(_x.screenpm, -1, -1); _x.gcreplsrc = xgc(_x.screenpm, FillTiled, -1); pmid = XCreatePixmap(_x.display, _x.drawable, 1, 1, 1); _x.gcfill0 = xgc(pmid, FillSolid, 0); _x.gccopy0 = xgc(pmid, -1, -1); _x.gcsimplesrc0 = xgc(pmid, FillStippled, -1); _x.gczero0 = xgc(pmid, -1, -1); _x.gcreplsrc0 = xgc(pmid, FillTiled, -1); XFreePixmap(_x.display, pmid); return _x.screenimage; err0: /* * Should do a better job of cleaning up here. */ XCloseDisplay(_x.display); return nil; }