func Ellipse(x, y, a, b int, n, f bool) { // x0, y0 := C.int(x-a), C.int(y-b) if f { if !n { C.XSetFunction(display, graphicsContext, C.GXinvert) } // C.GXcopyInverted ? if !xxb { C.XFillArc(display, C.Drawable(window), graphicsContext, C.int(x0), C.int(y0), C.uint(2*a), C.uint(2*b), 0, 64*360) } C.XFillArc(display, C.Drawable(pixmap), graphicsContext, C.int(x0), C.int(y0), C.uint(2*a), C.uint(2*b), 0, 64*360) } else { if !n { C.XSetFunction(display, graphicsContext, C.GXinvert) } if !xxb { C.XDrawArc(display, C.Drawable(window), graphicsContext, C.int(x0), C.int(y0), C.uint(2*a), C.uint(2*b), 0, 64*360) } C.XDrawArc(display, C.Drawable(pixmap), graphicsContext, C.int(x0), C.int(y0), C.uint(2*a), C.uint(2*b), 0, 64*360) } if !n { C.XSetFunction(display, graphicsContext, C.GXcopy) } C.XFlush(display) }
func Clr(x, y, w, h uint) { // C.XSetForeground(display, graphicsContext, cc(col.ScreenB)) C.XFillRectangle(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y), C.uint(w), C.uint(h)) C.XFillRectangle(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y), C.uint(w), C.uint(h)) C.XSetForeground(display, graphicsContext, cc(col.ScreenF)) C.XFlush(display) }
func CreateXWindow(width, height int) (*XWindow, error) { C.XInitThreads() W := &XWindow{} W.Display = C.XOpenDisplay(nil) if W.Display == nil { return &XWindow{}, errors.New("Can't open display") } W.Window = C.XCreateSimpleWindow(W.Display, C.XDefaultRootWindow(W.Display), 0, 0, C.uint(width), C.uint(height), 0, 0, 0xFF151515) C.XSetWindowBackgroundPixmap(W.Display, W.Window, 0) // This avoids flickering on resize C.XMapWindow(W.Display, W.Window) C.XStoreName(W.Display, W.Window, C.CString("gowitt")) C.XSelectInput(W.Display, W.Window, C.ExposureMask|C.KeyPressMask|C.ButtonPressMask) C.XFlush(W.Display) // Cairo W.Surface = C.cairo_xlib_surface_create(W.Display, C.Drawable(W.Window), C.XDefaultVisual(W.Display, 0), C.int(width), C.int(height)) C.cairo_xlib_surface_set_size(W.Surface, C.int(width), C.int(height)) W.Cairo = C.cairo_create(W.Surface) // Pango InitLayoutsCache(W.Cairo) W.PangoContext = C.pango_cairo_create_context(W.Cairo) W.FontDesc = C.pango_font_description_from_string(C.CString("Sans 10")) W.AttrList = C.pango_attr_list_new() placeholderImage = C.cairo_image_surface_create_from_png(C.CString("test.png")) W.UserImages = NewImageCache(func() { var ev C.XEvent exev := (*C.XExposeEvent)(unsafe.Pointer(&ev)) exev._type = C.Expose exev.count = 0 exev.window = W.Window exev.send_event = 1 exev.display = W.Display C.XSendEvent(W.Display, W.Window, 0, C.ExposureMask, &ev) C.XFlush(W.Display) }) return W, nil }
func Colours(F, B col.Colour) { // if !initialized { return } // C.XSetForeground (display, graphicsContext, C.ulong(col.CodeF)) // C.XSetBackground (display, graphicsContext, C.ulong(col.CodeB)) C.XSetForeground(display, graphicsContext, cc(col.ActualF)) C.XSetBackground(display, graphicsContext, cc(col.ActualB)) C.XFlush(display) }
func Invert(x, y, x1, y1 uint) { // if x > x1 || y > y1 { } // desaster C.XSetFunction(display, graphicsContext, C.GXinvert) if !xxb { C.XFillRectangle(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y), C.uint(x1-x+1), C.uint(y1-y+1)) } C.XFillRectangle(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y), C.uint(x1-x+1), C.uint(y1-y+1)) C.XSetFunction(display, graphicsContext, C.GXcopy) C.XFlush(display) }
func Line(x, y, x1, y1 int, n bool) { // if !n { C.XSetFunction(display, graphicsContext, C.GXinvert) } if !xxb { C.XDrawLine(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y), C.int(x1), C.int(y1)) } C.XDrawLine(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y), C.int(x1), C.int(y1)) if !n { C.XSetFunction(display, graphicsContext, C.GXcopy) } C.XFlush(display) }
func Point(x, y int, n bool) { // if !n { C.XSetFunction(display, graphicsContext, C.GXinvert) } if !xxb { C.XDrawPoint(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y)) } C.XDrawPoint(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y)) if !n { C.XSetFunction(display, graphicsContext, C.GXcopy) } C.XFlush(display) }
func sendKey(disp *C.struct__XDisplay, strname string) { if disp == nil { fmt.Println("no X11 display available") return } var mod _Ctype_KeyCode if strings.HasPrefix(strname, "Ctrl+") { strname = strname[len("Ctrl+"):] modkey := "Control_L" mod = C.XKeysymToKeycode(disp, C.XStringToKeysym(C.CString(modkey))) if debug { fmt.Printf("send key %T (Control) code=%v\n", mod, mod) } C.XTestFakeKeyEvent(disp, C.uint(mod), 1, 0) C.XFlush(disp) } chstr := C.CString(strname) keysym := C.XStringToKeysym(chstr) keycode := C.XKeysymToKeycode(disp, keysym) if debug { fmt.Printf("send key (%s) sym=%v code=%v\n", strname, keysym, keycode) } C.XTestFakeKeyEvent(disp, C.uint(keycode), 1, 0) C.XFlush(disp) C.XTestFakeKeyEvent(disp, C.uint(keycode), 0, 0) C.XFlush(disp) if debug { fmt.Printf("hit key %v (keysym %v keycode %v)\n", strname, keysym, keycode) } fmt.Printf("mod is == %v\n", mod) if mod != 0 { C.XTestFakeKeyEvent(disp, C.uint(mod), 0, 0) C.XFlush(disp) } }
func Buf(on bool) { // if xxb == on { return } xxb = on if on { C.XSetForeground(display, graphicsContext, cc(col.ScreenB)) C.XFillRectangle(display, C.Drawable(pixmap), graphicsContext, 0, 0, C.uint(xx), C.uint(yy)) C.XSetForeground(display, graphicsContext, cc(col.ScreenF)) C.XFlush(display) } else { pp2ff() } }
func Write(s string, x, y int, t bool) { // n := C.uint(len(s)) if !t { C.XSetForeground(display, graphicsContext, C.ulong(col.CodeB)) if !xxb { C.XFillRectangle(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y), n*C.uint(ZB), C.uint(ZH)) } C.XFillRectangle(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y), n*C.uint(ZB), C.uint(ZH)) C.XSetForeground(display, graphicsContext, C.ulong(col.CodeF)) } cs := C.CString(s) if !xxb { C.XDrawString(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y)+ZA, cs, C.int(n)) } C.XDrawString(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y)+ZA, cs, C.int(n)) C.free(unsafe.Pointer(cs)) C.XFlush(display) }
// Loop runs the main X loop. func (dpy *Display) Loop(uwin ui.Win) { win := uwin.(*Window) awaitEvent := make(chan bool) go func() { xfd := int(C.XConnectionNumber(dpy.dpy)) for { <-awaitEvent err := waitUntilReadable(xfd) if err != nil { log.Fatalf("select %#v", err) } dpy.eventReady <- true } }() C.XFlush(dpy.dpy) awaitEvent <- true draw := false for { nextFrame := dpy.anims.NextFrame(draw) select { case <-dpy.eventReady: dpy.processXEvents(win) awaitEvent <- true case <-dpy.drawReady: draw = true case t := <-nextFrame: dpy.anims.Run() // log.Printf("draw %s", t) t = t cr := cairo.Create(win.bufSurface.Surface) win.delegate.Draw(cr) win.repaint(0, 0, win.width, win.height) C.XSync(dpy.dpy, 0) draw = false case f := <-dpy.funcs: f() case <-dpy.quit: return } } }
func Decode(x, y, w, h uint, b []byte) { // const M = C.ulong(1<<32 - 1) ////////////////////////////////////////////////////////////////////////////////////////////// steals a lot of time ximg := C.XGetImage(display, C.Drawable(window), C.int(x), C.int(y), C.uint(w), C.uint(h), M, C.XYPixmap) ////////////////////////////////////////////////////////////////////////////////////////////// steals a lot of time n := uint(0) // var pixel C.ulong for j := uint(0); j < h; j++ { for i := uint(0); i < w; i++ { pixel := (C.ulong)(obj.Decode(n, b[n:n+4]).(uint)) C.xPutPixel(ximg, C.int(i), C.int(j), pixel) // C.XPutPixel (ximg, C.int(i), C.int(j), pixel) n += 4 } } C.XPutImage(display, C.Drawable(window), graphicsContext, ximg, 0, 0, C.int(x), C.int(y), C.uint(w), C.uint(h)) C.XCopyArea(display, C.Drawable(window), C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y), C.uint(w), C.uint(h), C.int(x), C.int(y)) C.XFlush(display) C.xDestroyImage(ximg) // C.XDestroyImage (ximg) }
func PolygonFull(X, Y []int, n bool) { // l := len(X) if len(Y) != l { return } p := make([]C.XPoint, l) for i := 0; i < l; i++ { p[i].x, p[i].y = C.short(X[i]), C.short(Y[i]) } if !n { C.XSetFunction(display, graphicsContext, C.GXcopyInverted) } if !xxb { C.XFillPolygon(display, C.Drawable(window), graphicsContext, &p[0], C.int(l), C.Convex, C.CoordModeOrigin) } C.XFillPolygon(display, C.Drawable(pixmap), graphicsContext, &p[0], C.int(l), C.Convex, C.CoordModeOrigin) if !n { C.XSetFunction(display, graphicsContext, C.GXcopy) } C.XFlush(display) }
func Segments(X, Y, X1, Y1 []int, n bool) { // l := len(X) if len(Y) != l { return } s := make([]C.XSegment, l) for i := 0; i < l; i++ { s[i].x1, s[i].y1, s[i].x2, s[i].y2 = C.short(X[i]), C.short(Y[i]), C.short(X1[i]), C.short(Y1[i]) } if !n { C.XSetFunction(display, graphicsContext, C.GXinvert) } if !xxb { C.XDrawSegments(display, C.Drawable(window), graphicsContext, &s[0], C.int(l)) } C.XDrawSegments(display, C.Drawable(pixmap), graphicsContext, &s[0], C.int(l)) if !n { C.XSetFunction(display, graphicsContext, C.GXcopy) } C.XFlush(display) }
func Switch(x, y uint) { // if xx == maxX && yy == maxY { C.sw(display, window, window0, netwm_state, fullscreen, C.int(0)) } xx, yy = C.uint(x), C.uint(y) if xx == maxX && yy == maxY { C.sw(display, window, window0, netwm_state, fullscreen, C.int(1)) } else { C.XResizeWindow(display, window, xx, yy) // resizerequest.width, resizerequest.height C.XFlush(display) } C.XFreePixmap(display, pixmap) pixmap = C.XCreatePixmap(display, C.Drawable(window), xx, yy, bitdepth) C.XFreePixmap(display, pixmap1) pixmap1 = C.XCreatePixmap(display, C.Drawable(window), xx, yy, bitdepth) C.XSetForeground(display, graphicsContext, cc(col.ActualB)) // C.XFillRectangle(display, C.Drawable(window), graphicsContext, 0, 0, xx, yy) C.XFillRectangle(display, C.Drawable(pixmap), graphicsContext, 0, 0, xx, yy) C.XFillRectangle(display, C.Drawable(pixmap1), graphicsContext, 0, 0, xx, yy) MouseDef(0, 0, int(xx-1), int(yy-1)) // var E *C.XEvent // C.XNextEvent (display, E) // et:= C.typ (&E) // et == *E.type // switch et { case C.Expose, C.ConfigureNotify: // for C.XCheckTypedEvent (display, C.int(et), E) == C.True { } // case C.ReparentNotify: // ; // default: // C.XPutBackEvent (display, E) // } WarpMouse(int(xx)/2, int(yy)/2) // C.XSync (display, C.False) // if navi.initialized (naviFd) { // go catchNavi () // } }
func Rectangle(x, y, w, h int, n, f bool) { // if f { if !n { C.XSetFunction(display, graphicsContext, C.GXinvert) } // C.GXcopyInverted ? if !xxb { C.XFillRectangle(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y), C.uint(w), C.uint(h)) } C.XFillRectangle(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y), C.uint(w), C.uint(h)) } else { if !n { C.XSetFunction(display, graphicsContext, C.GXinvert) } if !xxb { C.XDrawRectangle(display, C.Drawable(window), graphicsContext, C.int(x), C.int(y), C.uint(w), C.uint(h)) } C.XDrawRectangle(display, C.Drawable(pixmap), graphicsContext, C.int(x), C.int(y), C.uint(w), C.uint(h)) } if !n { C.XSetFunction(display, graphicsContext, C.GXcopy) } C.XFlush(display) }
// processXEvents does one read from the X fd, then processes all pending // events. func (dpy *Display) processXEvents(win *Window) { var event C.XEvent events := C.XEventsQueued(dpy.dpy, C.QueuedAfterReading) for i := 0; i < int(events); i++ { C.XNextEvent(dpy.dpy, &event) e := &event typ := xEventType(*(*C.int)(unsafe.Pointer(e))) // log.Printf("typ %s", typ.String()) switch typ { case C.ConfigureNotify: e := (*C.XConfigureEvent)(unsafe.Pointer(e)) win.resize(int(e.width), int(e.height)) case C.Expose: e := (*C.XExposeEvent)(unsafe.Pointer(e)) win.repaint(int(e.x), int(e.y), int(e.width), int(e.height)) case C.KeyPress: e := (*C.XKeyEvent)(unsafe.Pointer(e)) key := keys.Key{} if e.state&C.ControlMask != 0 { key.Mods |= keys.ModControl } if e.state&C.Mod1Mask != 0 { key.Mods |= keys.ModMeta } var buf [8]byte var keysym C.KeySym C.XLookupString(e, (*C.char)(unsafe.Pointer(&buf)), 8, &keysym, nil) nulpos := bytes.Index(buf[:], []byte{0}) if nulpos > 0 { if nulpos > 1 { log.Printf("xlib: overlong key %q", buf[:nulpos]) } key.Sym = keys.Sym(buf[0]) if key.Mods&keys.ModControl != 0 { // Undo Ctl-A => "ASCII control character" mapping. key.Sym += 'a' - 1 } } else { // See /usr/include/X11/keysymdef.h switch keysym { case C.XK_Left: key.Sym = keys.Left case C.XK_Right: key.Sym = keys.Right case C.XK_Up: key.Sym = keys.Up case C.XK_Down: key.Sym = keys.Down case C.XK_Shift_L, C.XK_Shift_R: case C.XK_Control_L, C.XK_Control_R: case C.XK_Meta_L, C.XK_Meta_R: case C.XK_Alt_L, C.XK_Alt_R: case C.XK_Super_L, C.XK_Super_R: case C.XK_Hyper_L, C.XK_Hyper_R: case C.XK_Caps_Lock: // ignore for now default: log.Printf("xlib: unhandled keysym %#v: %#v", keysym, e) } } win.delegate.Key(key) case C.KeyRelease: // ignore case C.ButtonPress: e := (*C.XButtonEvent)(unsafe.Pointer(e)) switch e.button { case 4, 5: dy := -1 if e.button == 5 { dy = 1 } win.delegate.Scroll(dy) case 6, 7: // TODO horizontal scroll. default: log.Printf("unhandled button %#v", e) } case C.MapNotify: win.delegate.Mapped() case C.ReparentNotify: // ignore default: if typ > C.GenericEvent { // Cairo triggers shm events, which show up as extension // events with greater ids than C.GenericEvent. continue } log.Printf("unhandled ev %s", typ.String()) } } C.XFlush(dpy.dpy) }
func WarpMouse(x, y int) { // C.XWarpPointer(display, C.None, window, 0, 0, 0, 0, C.int(x), C.int(y)) C.XFlush(display) }
func pp2ff() { // C.XCopyArea(display, C.Drawable(pixmap), C.Drawable(window), graphicsContext, 0, 0, xx, yy, 0, 0) C.XFlush(display) }