📄 screen.c
字号:
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <stdio.h>#include <X11/Xlib.h>#include <X11/Xatom.h>#include <X11/Xutil.h>#include <X11/keysym.h>#include "keysym2ucs.h"/* * alias defs for image types to overcome name conflicts */#define Point IPoint#define Rectangle IRectangle#define Display IDisplay#define Font IFont#define Screen IScreen#include "u.h"#include "lib.h"#include "dat.h"#include "fns.h"#include "user.h"#include "draw.h"#include "memdraw.h"#include "keyboard.h"#include "screen.h"#undef time#undef Point#undef Rectangle#undef Display#undef Font#undef Screentypedef struct ICursor ICursor;struct ICursor{ int w; int h; int hotx; int hoty; char *src; char *mask;};#define ABS(x) ((x) < 0 ? -(x) : (x))enum{ DblTime = 300 /* double click time in msec */};XColor map[256]; /* Plan 9 colormap array */XColor map7[128]; /* Plan 9 colormap array */uchar map7to8[128][2];Colormap xcmap; /* Default shared colormap */int plan9tox11[256]; /* Values for mapping between */int x11toplan9[256]; /* X11 and Plan 9 */int x24bitswap = 0; /* swap endian for 24bit RGB */int xtblbit;extern int mousequeue;/* for copy/paste, lifted from plan9ports */Atom clipboard; Atom utf8string;Atom targets;Atom text;Atom compoundtext;static Drawable xdrawable;/* static Atom wm_take_focus; */static void xexpose(XEvent*);static void xmouse(XEvent*);static void xkeyboard(XEvent*);static void xmapping(XEvent*);static void xdestroy(XEvent*);static void xselect(XEvent*, Display*);static void xproc(void*);static Memimage* xinitscreen(void);static void initmap(Window);static GC creategc(Drawable);static void graphicscmap(XColor*); int xscreendepth; Drawable xscreenid; Display* xdisplay; /* used holding draw lock */ Display* xkmcon; /* used only in xproc */ Display* xsnarfcon; /* used holding clip.lk */ Visual *xvis; GC xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc; GC xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0; ulong xblack; ulong xwhite; ulong xscreenchan;static int putsnarf, assertsnarf;extern Memimage* xallocmemimage(IRectangle, ulong, int);Memimage *gscreen;Screeninfo screen;XImage *ximage;voidscreeninit(void){ _memmkcmap(); gscreen = xinitscreen(); kproc("xscreen", xproc, nil); memimageinit(); terminit(); drawqlock(); flushmemscreen(gscreen->r); drawqunlock();}uchar*attachscreen(IRectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X){ *r = gscreen->r; *chan = gscreen->chan; *depth = gscreen->depth; *width = gscreen->width; *X = gscreen->X; *softscreen = 1; return gscreen->data->bdata;}voidflushmemscreen(IRectangle r){ assert(!drawcanqlock()); if(r.min.x >= r.max.x || r.min.y >= r.max.y) return; XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y); XFlush(xdisplay);}static intrevbyte(int b){ int r; r = 0; r |= (b&0x01) << 7; r |= (b&0x02) << 5; r |= (b&0x04) << 3; r |= (b&0x08) << 1; r |= (b&0x10) >> 1; r |= (b&0x20) >> 3; r |= (b&0x40) >> 5; r |= (b&0x80) >> 7; return r;}voidmouseset(IPoint xy){ drawqlock(); XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y); XFlush(xdisplay); drawqunlock();}static Cursor xcursor;voidsetcursor(void){ Cursor xc; XColor fg, bg; Pixmap xsrc, xmask; int i; uchar src[2*16], mask[2*16]; for(i=0; i<2*16; i++){ src[i] = revbyte(cursor.set[i]); mask[i] = revbyte(cursor.set[i] | cursor.clr[i]); } drawqlock(); fg = map[0]; bg = map[255]; xsrc = XCreateBitmapFromData(xdisplay, xdrawable, (char*)src, 16, 16); xmask = XCreateBitmapFromData(xdisplay, xdrawable, (char*)mask, 16, 16); xc = XCreatePixmapCursor(xdisplay, xsrc, xmask, &fg, &bg, -cursor.offset.x, -cursor.offset.y); if(xc != 0) { XDefineCursor(xdisplay, xdrawable, xc); if(xcursor != 0) XFreeCursor(xdisplay, xcursor); xcursor = xc; } XFreePixmap(xdisplay, xsrc); XFreePixmap(xdisplay, xmask); XFlush(xdisplay); drawqunlock();}voidcursorarrow(void){ drawqlock(); if(xcursor != 0){ XFreeCursor(xdisplay, xcursor); xcursor = 0; } XUndefineCursor(xdisplay, xdrawable); XFlush(xdisplay); drawqunlock();}static voidxproc(void *arg){ ulong mask; XEvent event; mask = KeyPressMask| ButtonPressMask| ButtonReleaseMask| PointerMotionMask| Button1MotionMask| Button2MotionMask| Button3MotionMask| Button4MotionMask| Button5MotionMask| ExposureMask| StructureNotifyMask; XSelectInput(xkmcon, xdrawable, mask); for(;;) { //XWindowEvent(xkmcon, xdrawable, mask, &event); XNextEvent(xkmcon, &event); xselect(&event, xkmcon); xkeyboard(&event); xmouse(&event); xexpose(&event); xmapping(&event); xdestroy(&event); }}static intshutup(Display *d, XErrorEvent *e){ char buf[200]; iprint("X error: error code=%d, request_code=%d, minor=%d\n", e->error_code, e->request_code, e->minor_code); XGetErrorText(d, e->error_code, buf, sizeof(buf)); iprint("%s\n", buf); USED(d); USED(e); return 0;}static intpanicshutup(Display *d){ panic("x error"); return -1;}static Memimage*xinitscreen(void){ Memimage *gscreen; int i, xsize, ysize, pmid; char *argv[2]; char *disp_val; Window rootwin; IRectangle r; XWMHints hints; Screen *screen; XVisualInfo xvi; int rootscreennum; XTextProperty name; XClassHint classhints; XSizeHints normalhints; XSetWindowAttributes attrs; XPixmapFormatValues *pfmt; int n; xscreenid = 0; xdrawable = 0; xdisplay = XOpenDisplay(NULL); if(xdisplay == 0){ disp_val = getenv("DISPLAY"); if(disp_val == 0) disp_val = "not set"; iprint("drawterm: open %r, DISPLAY is %s\n", disp_val); exit(0); } XSetErrorHandler(shutup); XSetIOErrorHandler(panicshutup); rootscreennum = DefaultScreen(xdisplay); rootwin = DefaultRootWindow(xdisplay); xscreendepth = DefaultDepth(xdisplay, rootscreennum); if(XMatchVisualInfo(xdisplay, rootscreennum, 16, TrueColor, &xvi) || XMatchVisualInfo(xdisplay, rootscreennum, 16, DirectColor, &xvi)){ xvis = xvi.visual; xscreendepth = 16; xtblbit = 1; } else if(XMatchVisualInfo(xdisplay, rootscreennum, 24, TrueColor, &xvi) || XMatchVisualInfo(xdisplay, rootscreennum, 24, DirectColor, &xvi)){ xvis = xvi.visual; xscreendepth = 24; xtblbit = 1; } else if(XMatchVisualInfo(xdisplay, rootscreennum, 8, PseudoColor, &xvi) || XMatchVisualInfo(xdisplay, rootscreennum, 8, StaticColor, &xvi)){ if(xscreendepth > 8) panic("drawterm: can't deal with colormapped depth %d screens\n", xscreendepth); xvis = xvi.visual; xscreendepth = 8; } else{ if(xscreendepth != 8) panic("drawterm: can't deal with depth %d screens\n", xscreendepth); xvis = DefaultVisual(xdisplay, rootscreennum); } /* * xscreendepth is only the number of significant pixel bits, * not the total. We need to walk the display list to find * how many actual bits are being used per pixel. */ xscreenchan = 0; /* not a valid channel */ pfmt = XListPixmapFormats(xdisplay, &n); for(i=0; i<n; i++){ if(pfmt[i].depth == xscreendepth){ switch(pfmt[i].bits_per_pixel){ case 1: /* untested */ xscreenchan = GREY1; break; case 2: /* untested */ xscreenchan = GREY2; break; case 4: /* untested */ xscreenchan = GREY4; break; case 8: xscreenchan = CMAP8; break; case 16: /* uses 16 rather than 15, empirically. */ xscreenchan = RGB16; break; case 24: /* untested (impossible?) */ xscreenchan = RGB24; break; case 32: xscreenchan = CHAN4(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8); break; } } } if(xscreenchan == 0) panic("drawterm: unknown screen pixel format\n"); screen = DefaultScreenOfDisplay(xdisplay); xcmap = DefaultColormapOfScreen(screen); if(xvis->class != StaticColor){ graphicscmap(map); initmap(rootwin); } r.min = ZP; r.max.x = WidthOfScreen(screen); r.max.y = HeightOfScreen(screen); xsize = Dx(r)*3/4; ysize = Dy(r)*3/4; attrs.colormap = xcmap; attrs.background_pixel = 0; attrs.border_pixel = 0; /* attrs.override_redirect = 1;*/ /* WM leave me alone! |CWOverrideRedirect */ xdrawable = XCreateWindow(xdisplay, rootwin, 0, 0, xsize, ysize, 0, xscreendepth, InputOutput, xvis, CWBackPixel|CWBorderPixel|CWColormap, &attrs); /* * set up property as required by ICCCM */ name.value = (uchar*)"drawterm"; name.encoding = XA_STRING; name.format = 8; name.nitems = strlen((char*)name.value); normalhints.flags = USSize|PMaxSize; normalhints.max_width = Dx(r); normalhints.max_height = Dy(r); normalhints.width = xsize; normalhints.height = ysize; hints.flags = InputHint|StateHint; hints.input = 1; hints.initial_state = NormalState; classhints.res_name = "drawterm"; classhints.res_class = "Drawterm"; argv[0] = "drawterm"; argv[1] = nil; XSetWMProperties(xdisplay, xdrawable, &name, /* XA_WM_NAME property for ICCCM */ &name, /* XA_WM_ICON_NAME */ argv, /* XA_WM_COMMAND */ 1, /* argc */ &normalhints, /* XA_WM_NORMAL_HINTS */ &hints, /* XA_WM_HINTS */ &classhints); /* XA_WM_CLASS */ XFlush(xdisplay); /* * put the window on the screen */ XMapWindow(xdisplay, xdrawable); XFlush(xdisplay); xscreenid = XCreatePixmap(xdisplay, xdrawable, Dx(r), Dy(r), xscreendepth); gscreen = xallocmemimage(r, xscreenchan, xscreenid); xgcfill = creategc(xscreenid); XSetFillStyle(xdisplay, xgcfill, FillSolid); xgccopy = creategc(xscreenid); xgcsimplesrc = creategc(xscreenid); XSetFillStyle(xdisplay, xgcsimplesrc, FillStippled); xgczero = creategc(xscreenid); xgcreplsrc = creategc(xscreenid); XSetFillStyle(xdisplay, xgcreplsrc, FillTiled); pmid = XCreatePixmap(xdisplay, xdrawable, 1, 1, 1); xgcfill0 = creategc(pmid); XSetForeground(xdisplay, xgcfill0, 0); XSetFillStyle(xdisplay, xgcfill0, FillSolid); xgccopy0 = creategc(pmid); xgcsimplesrc0 = creategc(pmid); XSetFillStyle(xdisplay, xgcsimplesrc0, FillStippled); xgczero0 = creategc(pmid); xgcreplsrc0 = creategc(pmid); XSetFillStyle(xdisplay, xgcreplsrc0, FillTiled); XFreePixmap(xdisplay, pmid); XSetForeground(xdisplay, xgccopy, plan9tox11[0]); XFillRectangle(xdisplay, xscreenid, xgccopy, 0, 0, xsize, ysize); xkmcon = XOpenDisplay(NULL); if(xkmcon == 0){ disp_val = getenv("DISPLAY"); if(disp_val == 0) disp_val = "not set"; iprint("drawterm: open %r, DISPLAY is %s\n", disp_val); exit(0); } xsnarfcon = XOpenDisplay(NULL); if(xsnarfcon == 0){ disp_val = getenv("DISPLAY"); if(disp_val == 0) disp_val = "not set"; iprint("drawterm: open %r, DISPLAY is %s\n", disp_val); exit(0); } clipboard = XInternAtom(xkmcon, "CLIPBOARD", False); utf8string = XInternAtom(xkmcon, "UTF8_STRING", False); targets = XInternAtom(xkmcon, "TARGETS", False); text = XInternAtom(xkmcon, "TEXT", False); compoundtext = XInternAtom(xkmcon, "COMPOUND_TEXT", False); xblack = screen->black_pixel; xwhite = screen->white_pixel; return gscreen;}static voidgraphicscmap(XColor *map){ int r, g, b, cr, cg, cb, v, num, den, idx, v7, idx7; for(r=0; r!=4; r++) { for(g = 0; g != 4; g++) { for(b = 0; b!=4; b++) { for(v = 0; v!=4; v++) { den=r; if(g > den) den=g; if(b > den) den=b; /* divide check -- pick grey shades */ if(den==0) cr=cg=cb=v*17; else { num=17*(4*den+v); cr=r*num/den; cg=g*num/den; cb=b*num/den; } idx = r*64 + v*16 + ((g*4 + b + v - r) & 15); map[idx].red = cr*0x0101; map[idx].green = cg*0x0101; map[idx].blue = cb*0x0101; map[idx].pixel = idx; map[idx].flags = DoRed|DoGreen|DoBlue; v7 = v >> 1; idx7 = r*32 + v7*16 + g*4 + b; if((v & 1) == v7){ map7to8[idx7][0] = idx; if(den == 0) { /* divide check -- pick grey shades */ cr = ((255.0/7.0)*v7)+0.5; cg = cr; cb = cr; } else { num=17*15*(4*den+v7*2)/14; cr=r*num/den; cg=g*num/den; cb=b*num/den; } map7[idx7].red = cr*0x0101; map7[idx7].green = cg*0x0101; map7[idx7].blue = cb*0x0101; map7[idx7].pixel = idx7; map7[idx7].flags = DoRed|DoGreen|DoBlue; } else map7to8[idx7][1] = idx; } } } }}/* * Initialize and install the drawterm colormap as a private colormap for this * application. Drawterm gets the best colors here when it has the cursor focus. */ static void initmap(Window w){ XColor c; int i; ulong p, pp; char buf[30]; if(xscreendepth <= 1) return; if(xscreendepth >= 24) { /* The pixel value returned from XGetPixel needs to * be converted to RGB so we can call rgb2cmap() * to translate between 24 bit X and our color. Unfortunately, * the return value appears to be display server endian * dependant. Therefore, we run some heuristics to later * determine how to mask the int value correctly. * Yeah, I know we can look at xvis->byte_order but * some displays say MSB even though they run on LSB. * Besides, this is more anal. */ if(xscreendepth != DefaultDepth(xdisplay, DefaultScreen(xdisplay))) xcmap = XCreateColormap(xdisplay, w, xvis, AllocNone); c = map[19]; /* find out index into colormap for our RGB */ if(!XAllocColor(xdisplay, xcmap, &c)) panic("drawterm: screen-x11 can't alloc color"); p = c.pixel; pp = rgb2cmap((p>>16)&0xff,(p>>8)&0xff,p&0xff); if(pp!=map[19].pixel) { /* check if endian is other way */ pp = rgb2cmap(p&0xff,(p>>8)&0xff,(p>>16)&0xff); if(pp!=map[19].pixel) panic("cannot detect x server byte order"); switch(xscreenchan){ case RGB24:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -