func NewXHandle(display string) (*xhandle, error) { c, err := xgb.NewConnDisplay(display) if err != nil { return nil, err } s := xproto.Setup(c) screen := s.DefaultScreen(c) kb, err := NewKeyboard(s, c) if err != nil { return nil, err } h := &xhandle{ conn: c, root: screen.Root, Events: make([]Event, 0, 1000), EvtsLck: &sync.RWMutex{}, keyboard: kb, Keys: make(map[int]map[xproto.Window]map[Input][]Key), KeysLck: &sync.RWMutex{}, } return h, nil }
func newHeads(X *xgb.Conn) heads { var primaryHead *head var primaryOutput randr.Output root := xproto.Setup(X).DefaultScreen(X).Root resources, err := randr.GetScreenResourcesCurrent(X, root).Reply() if err != nil { log.Fatalf("Could not get screen resources: %s.", err) } primaryOutputReply, _ := randr.GetOutputPrimary(X, root).Reply() if primaryOutputReply != nil { primaryOutput = primaryOutputReply.Output } hds := make([]head, 0, len(resources.Outputs)) off := make([]string, 0) disconnected := make([]string, 0) for i, output := range resources.Outputs { oinfo, err := randr.GetOutputInfo(X, output, 0).Reply() if err != nil { log.Fatalf("Could not get output info for screen %d: %s.", i, err) } outputName := string(oinfo.Name) if oinfo.Connection != randr.ConnectionConnected { disconnected = append(disconnected, outputName) continue } if oinfo.Crtc == 0 { off = append(off, outputName) continue } crtcinfo, err := randr.GetCrtcInfo(X, oinfo.Crtc, 0).Reply() if err != nil { log.Fatalf("Could not get crtc info for screen (%d, %s): %s.", i, outputName, err) } head := newHead(output, outputName, crtcinfo) if output == primaryOutput { primaryHead = &head } hds = append(hds, head) } if primaryHead == nil && len(hds) > 0 { tmp := hds[0] primaryHead = &tmp } hdsPrim := heads{ primary: primaryHead, heads: hds, off: off, disconnected: disconnected, } sort.Sort(hdsPrim) return hdsPrim }
// Lock grabs the keyboard and pointer locking the X11 display func Lock(X *xgb.Conn) error { screen := xproto.Setup(X).DefaultScreen(X) passEventsToOwner := false kbCookie := xproto.GrabKeyboard(X, passEventsToOwner, screen.Root, xproto.TimeCurrentTime, xproto.GrabModeAsync, xproto.GrabModeAsync) kbReply, err := kbCookie.Reply() if err != nil { return err } if kbReply.Status != xproto.GrabStatusSuccess { return fmt.Errorf("GrabKeyboard status %v", grabStatus(kbReply.Status)) } ptrCookie := xproto.GrabPointer(X, passEventsToOwner, screen.Root, 0, xproto.GrabModeAsync, xproto.GrabModeAsync, xproto.AtomNone, xproto.AtomNone, xproto.TimeCurrentTime) ptrReply, err := ptrCookie.Reply() if err != nil { xproto.UngrabKeyboard(X, xproto.TimeCurrentTime) return err } if ptrReply.Status != xproto.GrabStatusSuccess { return fmt.Errorf("GrabPointer status %v", grabStatus(kbReply.Status)) } return nil }
func getPrimaryScreenBestResolution() (w uint16, h uint16) { // if connect to x failed, just return 1024x768 w, h = 1024, 768 XU, err := xgbutil.NewConn() if err != nil { return } err = randr.Init(XU.Conn()) if err != nil { return } _, err = randr.QueryVersion(XU.Conn(), 1, 4).Reply() if err != nil { return } Root := xproto.Setup(XU.Conn()).DefaultScreen(XU.Conn()).Root resources, err := randr.GetScreenResources(XU.Conn(), Root).Reply() if err != nil { return } bestModes := make([]uint32, 0) for _, output := range resources.Outputs { reply, err := randr.GetOutputInfo(XU.Conn(), output, 0).Reply() if err == nil && reply.NumModes > 1 { bestModes = append(bestModes, uint32(reply.Modes[0])) } } w, h = 0, 0 for _, m := range resources.Modes { for _, id := range bestModes { if id == m.Id { bw, bh := m.Width, m.Height if w == 0 || h == 0 { w, h = bw, bh } else if uint32(bw)*uint32(bh) < uint32(w)*uint32(h) { w, h = bw, bh } } } } if w == 0 || h == 0 { // get resource failed, use root window's geometry rootRect := xwindow.RootGeometry(XU) w, h = uint16(rootRect.Width()), uint16(rootRect.Height()) } if w == 0 || h == 0 { w, h = 1024, 768 // default value } logger.Debugf("primary screen's best resolution is %dx%d", w, h) return }
func Load(c *xgb.Conn) error { ctxs = make(map[string]*gcontext) scr := xproto.Setup(c).DefaultScreen(c) err := loadGCS(c, scr) if err != nil { return err } return nil }
func (m *Mouse) Move(args *MoveArgs, reply *int) error { //fmt.Printf("%#v\n", args) screen := xproto.Setup(m.x11).DefaultScreen(m.x11) cookie := xtest.FakeInputChecked(m.x11, xproto.MotionNotify, 0, 0, screen.Root, int16(args.X), int16(args.Y), 0) if cookie.Check() != nil { fmt.Println("FakeInput failed") } return nil }
func ScreenRect() (image.Rectangle, error) { c, err := xgb.NewConn() if err != nil { return image.Rectangle{}, err } defer c.Close() screen := xproto.Setup(c).DefaultScreen(c) x := screen.WidthInPixels y := screen.HeightInPixels return image.Rect(0, 0, int(x), int(y)), nil }
func main() { X, err := xgb.NewConn() if err != nil { log.Fatal(err) } // Get the window id of the root window. setup := xproto.Setup(X) root := setup.DefaultScreen(X).Root // Get the atom id (i.e., intern an atom) of "_NET_ACTIVE_WINDOW". aname := "_NET_ACTIVE_WINDOW" activeAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Fatal(err) } // Get the atom id (i.e., intern an atom) of "_NET_WM_NAME". aname = "_NET_WM_NAME" nameAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Fatal(err) } // Get the actual value of _NET_ACTIVE_WINDOW. // Note that 'reply.Value' is just a slice of bytes, so we use an // XGB helper function, 'Get32', to pull an unsigned 32-bit integer out // of the byte slice. We then convert it to an X resource id so it can // be used to get the name of the window in the next GetProperty request. reply, err := xproto.GetProperty(X, false, root, activeAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Fatal(err) } windowId := xproto.Window(xgb.Get32(reply.Value)) fmt.Printf("Active window id: %X\n", windowId) // Now get the value of _NET_WM_NAME for the active window. // Note that this time, we simply convert the resulting byte slice, // reply.Value, to a string. reply, err = xproto.GetProperty(X, false, windowId, nameAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Fatal(err) } fmt.Printf("Active window name: %s\n", string(reply.Value)) }
func NewXHandle(display string, ewhm []string) (*xhandle, error) { c, err := xgb.NewConnDisplay(display) if err != nil { return nil, err } setup := xproto.Setup(c) screen := setup.DefaultScreen(c) meta, err := mkMeta(screen, c) if err != nil { return nil, err } motion, err := mkMotion(screen, c) if err != nil { return nil, err } h := &xhandle{ conn: c, setup: setup, screen: screen, root: screen.Root, meta: meta, motion: motion, Events: make([]Event, 0, 1000), EvtsLck: &sync.RWMutex{}, } mr := NewMotionRecorder(h.conn, h.root, h.motion) h.pointer = NewPointer(mr) h.Windower = NewWindower(h.conn, h.root) h.InputFocus = NewInputFocus(h.conn, h.root) h.Atomic = atomic.New(h.conn) EWMH := ewmh.New(h.conn, h.root, h.Atomic) err = EWMH.SupportedSet(ewhm) if err != nil { return nil, err } h.Ewmh = NewEwmh(EWMH) //h.Ewmh.Set("string name", h.root, h.meta) return h, nil }
func (b *brightness) adjust(Xu *xgbutil.XUtil, increase bool) error { X := Xu.Conn() root := xproto.Setup(X).DefaultScreen(X).Root screens, err := randr.GetScreenResources(X, root).Reply() if err != nil { return fmt.Errorf("getting screen: %v", err) } for _, output := range screens.Outputs { query, err := randr.QueryOutputProperty(X, output, b.prop).Reply() if err != nil { if _, ok := err.(xproto.NameError); ok { // this output has no backlight continue } return fmt.Errorf("query backlight: %v", err) } if !query.Range { return errors.New("backlight brightness range not specified") } if len(query.ValidValues) != 2 { return fmt.Errorf("expected min and max, got: %v", query.ValidValues) } min, max := query.ValidValues[0], query.ValidValues[1] // log.Printf("backlight range: %d .. %d", min, max) get, err := randr.GetOutputProperty(X, output, b.prop, xproto.AtomNone, 0, 4, false, false).Reply() if err != nil { return fmt.Errorf("get backlight property: %v", err) } if get.Type != xproto.AtomInteger || get.NumItems != 1 || get.Format != 32 { return fmt.Errorf("backlight property value looks wrong") } old := *(*int32)(unsafe.Pointer(&get.Data[0])) // log.Printf("backlight data: %d", old) bri := delta5(old, min, max, increase) data := (*[4]byte)(unsafe.Pointer(&bri))[:] if err := randr.ChangeOutputPropertyChecked(X, output, b.prop, xproto.AtomInteger, 32, xproto.PropModeReplace, 1, data).Check(); err != nil { return err } } return nil }
func main() { // os.Setenv("DISPLAY", "localhost:6080") c, err := xgb.NewConn() if err != nil { fmt.Println(err) return } screen := xproto.Setup(c).DefaultScreen(c) rect := image.Rect(0, 0, int(screen.WidthInPixels), int(screen.HeightInPixels)) x, y := rect.Dx(), rect.Dy() xImg, err := xproto.GetImage(c, xproto.ImageFormatZPixmap, xproto.Drawable(screen.Root), int16(rect.Min.X), int16(rect.Min.Y), uint16(x), uint16(y), 0xffffffff).Reply() if err != nil { fmt.Println("Error: %s\r\n", err) } data := xImg.Data for i := 0; i < len(data); i += 4 { data[i], data[i+2], data[i+3] = data[i+2], data[i], 255 } img := &image.RGBA{ data, 4 * x, image.Rect(0, 0, x, y)} z.FcheckParents("screen") f := z.FileW("screen") defer f.Close() png := jpeg.Encode(f, img, &jpeg.Options{90}) fmt.Printf("End with png: %v", png) }
func (logger *WindowLogger) getCurWindowTitle() (name string, err error) { // Get the window id of the root window. setup := xproto.Setup(logger.X11Connection) root := setup.DefaultScreen(logger.X11Connection).Root // Get the atom id (i.e., intern an atom) of "_NET_ACTIVE_WINDOW". aname := "_NET_ACTIVE_WINDOW" activeAtom, err := xproto.InternAtom(logger.X11Connection, true, uint16(len(aname)), aname).Reply() if err != nil { return "", err } // Get the atom id (i.e., intern an atom) of "_NET_WM_NAME". aname = "_NET_WM_NAME" nameAtom, err := xproto.InternAtom(logger.X11Connection, true, uint16(len(aname)), aname).Reply() if err != nil { return "", err } // Get the actual value of _NET_ACTIVE_WINDOW. // Note that 'reply.Value' is just a slice of bytes, so we use an // XGB helper function, 'Get32', to pull an unsigned 32-bit integer out // of the byte slice. We then convert it to an X resource id so it can // be used to get the name of the window in the next GetProperty request. reply, err := xproto.GetProperty(logger.X11Connection, false, root, activeAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { return "", err } windowId := xproto.Window(xgb.Get32(reply.Value)) // Now get the value of _NET_WM_NAME for the active window. // Note that this time, we simply convert the resulting byte slice, // reply.Value, to a string. reply, err = xproto.GetProperty(logger.X11Connection, false, windowId, nameAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { return "", err } return string(reply.Value), nil }
func newScreenImpl(xc *xgb.Conn) (*screenImpl, error) { s := &screenImpl{ xc: xc, xsi: xproto.Setup(xc).DefaultScreen(xc), buffers: map[shm.Seg]*bufferImpl{}, uploads: map[uint16]completion{}, windows: map[xproto.Window]*windowImpl{}, } if err := s.initAtoms(); err != nil { return nil, err } if err := s.initPictformats(); err != nil { return nil, err } if err := s.initWindow32(); err != nil { return nil, err } go s.run() return s, nil }
func main() { var serve *bool = flag.Bool("serve", false, "Listen for connections") flag.Usage = usage flag.Parse() if remote := os.Getenv("SSH_CONNECTION"); remote == "" && len(flag.Args()) != 0 { invoked_as := os.Args[0] actual_binary, err := os.Readlink("/proc/self/exe") if err != nil { log.Panic("/proc/self/exe doesn't exist!") } log.Print("Invoked as: '", invoked_as, "' (actual=", actual_binary, ")") log.Panic("Not yet implemented: Would have run locally") return } c, err := xgb.NewConn() if err != nil { log.Panic("cannot connect: %v\n", err) } s := xproto.Setup(c).DefaultScreen(c) rl_execute_reply, err := xproto.InternAtom(c, false, uint16(len(atomname)), atomname).Reply() if err != nil { panic(err) } rl_execute_atom := rl_execute_reply.Atom if *serve { //log.Printf("c = %v, s = %v, a = %v", c, s, rl_execute_atom) start_server(c, s, rl_execute_atom) } else { if len(flag.Args()) == 0 { usage() } connect(c, s, rl_execute_atom, fixup_args(flag.Args())) } }
func subscribeXEvents(ch chan<- Event, done <-chan struct{}) { X, err := xgb.NewConn() if err != nil { ch <- Event{Error: err} return } defer X.Close() if err = randr.Init(X); err != nil { ch <- Event{Error: err} return } root := xproto.Setup(X).DefaultScreen(X).Root eventMask := randr.NotifyMaskScreenChange | randr.NotifyMaskCrtcChange | randr.NotifyMaskOutputChange | randr.NotifyMaskOutputProperty err = randr.SelectInputChecked(X, root, uint16(eventMask)).Check() if err != nil { ch <- Event{Error: err} return } for { ev, err := X.WaitForEvent() select { case ch <- Event{Event: ev, Error: err}: case <-time.After(eventSendTimeout): continue case <-done: return } if err != nil { log.Fatal(err) } } }
func CaptureRect(rect image.Rectangle) (*image.RGBA, error) { c, err := xgb.NewConn() if err != nil { return nil, err } defer c.Close() screen := xproto.Setup(c).DefaultScreen(c) x, y := rect.Dx(), rect.Dy() xImg, err := xproto.GetImage(c, xproto.ImageFormatZPixmap, xproto.Drawable(screen.Root), int16(rect.Min.X), int16(rect.Min.Y), uint16(x), uint16(y), 0xffffffff).Reply() if err != nil { return nil, err } data := xImg.Data for i := 0; i < len(data); i += 4 { data[i], data[i+2], data[i+3] = data[i+2], data[i], 255 } img := &image.RGBA{data, 4 * x, image.Rect(0, 0, x, y)} return img, nil }
func Open(c *xgb.Conn, ctx, title, text string) (*Window, error) { gc, ok := ctxs[ctx] if !ok { return nil, BadContextError(ctx) } scr := xproto.Setup(c).DefaultScreen(c) wdwid, err := xproto.NewWindowId(c) if err != nil { return nil, err } lines := cutLines(c, gc.width-2*gc.border, gc.font, text) height := uint32(len(lines)) * gc.fontHeight var mask uint32 = xproto.CwBackPixel | xproto.CwOverrideRedirect | xproto.CwEventMask values := make([]uint32, 3) values[0] = scr.WhitePixel values[1] = 1 values[2] = xproto.EventMaskExposure err = xproto.CreateWindowChecked(c, xproto.WindowClassCopyFromParent, wdwid, scr.Root, 0, 0, uint16(gc.width), uint16(height+2*gc.border), 1, xproto.WindowClassInputOutput, scr.RootVisual, mask, values).Check() if err != nil { return nil, err } xproto.ChangeProperty(c, xproto.PropModeReplace, wdwid, xproto.AtomWmName, xproto.AtomString, 8, uint32(len(title)), []byte(title)) var wdw Window wdw.id = wdwid wdw.conn = c wdw.lines = lines wdw.gc = gc wdw.geom = types.Geometry{0, 0, int32(gc.width), int32(height + 2*gc.border)} return &wdw, nil }
func default1() { X, err := xgb.NewConn() if err != nil { fmt.Println(err) return } wid, _ := xproto.NewWindowId(X) screen := xproto.Setup(X).DefaultScreen(X) xproto.CreateWindow(X, screen.RootDepth, wid, screen.Root, 0, 0, 500, 500, 0, xproto.WindowClassInputOutput, screen.RootVisual, xproto.CwBackPixel|xproto.CwEventMask, []uint32{ 0xffffffff, xproto.EventMaskStructureNotify | xproto.EventMaskKeyPress | xproto.EventMaskKeyRelease}) xproto.MapWindow(X, wid) for { ev, xerr := X.WaitForEvent() if ev == nil && xerr == nil { fmt.Println("Both event and error are nil. Exiting...") return } if ev != nil { fmt.Println("Event: %s\r\n", ev) } if xerr != nil { fmt.Println("Error: %s\r\n", xerr) } } }
func Focused(c *xgb.Conn) uint32 { incookie := xproto.GetInputFocus(c) rep, err := incookie.Reply() if err != nil { return 0 } win := rep.Focus trcookie := xproto.TranslateCoordinates(c, win, xproto.Setup(c).DefaultScreen(c).Root, 0, 0) att, err := trcookie.Reply() if err != nil { return 0 } x, y := int32(att.DstX), int32(att.DstY) for i, size := range sizes { if size.X <= x && size.X+size.W >= x && size.Y <= y && size.Y+size.H >= y { return uint32(i) } } return 0 }
func setStatus(status []byte, X *xgb.Conn) { screen := xproto.Setup(X).DefaultScreen(X) fmt.Println(string(status)) setWindowTitle(status, X, screen.Root) }
func main() { X, _ := xgb.NewConn() // Every extension must be initialized before it can be used. err := randr.Init(X) if err != nil { log.Fatal(err) } // Get the root window on the default screen. root := xproto.Setup(X).DefaultScreen(X).Root // Gets the current screen resources. Screen resources contains a list // of names, crtcs, outputs and modes, among other things. resources, err := randr.GetScreenResources(X, root).Reply() if err != nil { log.Fatal(err) } // Iterate through all of the outputs and show some of their info. for _, output := range resources.Outputs { info, err := randr.GetOutputInfo(X, output, 0).Reply() if err != nil { log.Fatal(err) } bestMode := info.Modes[0] for _, mode := range resources.Modes { if mode.Id == uint32(bestMode) { fmt.Printf("Width: %d, Height: %d\n", mode.Width, mode.Height) } } } fmt.Println("\n") // Iterate through all of the crtcs and show some of their info. for _, crtc := range resources.Crtcs { info, err := randr.GetCrtcInfo(X, crtc, 0).Reply() if err != nil { log.Fatal(err) } fmt.Printf("X: %d, Y: %d, Width: %d, Height: %d\n", info.X, info.Y, info.Width, info.Height) } // Tell RandR to send us events. (I think these are all of them, as of 1.3.) err = randr.SelectInputChecked(X, root, randr.NotifyMaskScreenChange| randr.NotifyMaskCrtcChange| randr.NotifyMaskOutputChange| randr.NotifyMaskOutputProperty).Check() if err != nil { log.Fatal(err) } // Listen to events and just dump them to standard out. // A more involved approach will have to read the 'U' field of // RandrNotifyEvent, which is a union (really a struct) of type // RanrNotifyDataUnion. for { ev, err := X.WaitForEvent() if err != nil { log.Fatal(err) } fmt.Println(ev) } }
func main() { X, err := xgb.NewConn() if err != nil { fmt.Println(err) return } wid, _ := xproto.NewWindowId(X) screen := xproto.Setup(X).DefaultScreen(X) xproto.CreateWindow(X, screen.RootDepth, wid, screen.Root, 0, 0, 240, 240, 0, xproto.WindowClassInputOutput, screen.RootVisual, xproto.CwBackPixel|xproto.CwEventMask, []uint32{ // values must be in the order defined by the protocol 0xffffffff, xproto.EventMaskStructureNotify | xproto.EventMaskKeyPress | xproto.EventMaskKeyRelease}) xproto.MapWindow(X, wid) fmt.Printf("%d %d\n", screen.AllowedDepths[0].Visuals[0].VisualId, screen.RootVisual) var ( ux, uy float64 = 1, 1 fe cairo.FontExtents te cairo.TextExtents text = "joy" x, y, px, dashlength float64 ) surface := cairo.NewSurfaceFromXCB(xproto.Drawable(wid), screen.AllowedDepths[0].Visuals[0], 240, 240) surface.Scale(240, 240) surface.SetFontSize(0.5) /* Drawing code goes here */ surface.SetSourceRGB(0.0, 0.0, 0.0) surface.SelectFontFace("Georgia", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) surface.FontExtents(&fe) ux, uy = surface.DeviceToUserDistance(ux, uy) if ux > uy { px = ux } else { px = uy } surface.FontExtents(&fe) surface.TextExtents(text, &te) x = 0.5 - te.X_bearing - te.Width/2 y = 0.5 - fe.Descent + fe.Height/2 /* baseline, descent, ascent, height */ surface.SetLineWidth(4 * px) dashlength = 9 * px surface.SetDash([]float64{dashlength}, 0) surface.SetSourceRGBA(0, 0.6, 0, 0.5) surface.MoveTo(x+te.X_bearing, y) surface.RelLineTo(te.Width, 0) surface.MoveTo(x+te.X_bearing, y+fe.Descent) surface.RelLineTo(te.Width, 0) surface.MoveTo(x+te.X_bearing, y-fe.Ascent) surface.RelLineTo(te.Width, 0) surface.MoveTo(x+te.X_bearing, y-fe.Height) surface.RelLineTo(te.Width, 0) surface.Stroke() /* extents: width & height */ surface.SetSourceRGBA(0, 0, 0.75, 0.5) surface.SetLineWidth(px) dashlength = 3 * px surface.SetDash([]float64{dashlength}, 0) surface.Rectangle(x+te.X_bearing, y+te.Y_bearing, te.Width, te.Height) surface.Stroke() /* text */ surface.MoveTo(x, y) surface.SetSourceRGB(0, 0, 0) surface.ShowText(text) /* bearing */ surface.SetDash(nil, 0) surface.SetLineWidth(2 * px) surface.SetSourceRGBA(0, 0, 0.75, 0.5) surface.MoveTo(x, y) surface.RelLineTo(te.X_bearing, te.Y_bearing) surface.Stroke() /* text's advance */ surface.SetSourceRGBA(0, 0, 0.75, 0.5) surface.Arc(x+te.X_advance, y+te.Y_advance, 5*px, 0, 2*math.Pi) surface.Fill() /* reference point */ surface.Arc(x, y, 5*px, 0, 2*math.Pi) surface.SetSourceRGBA(0.75, 0, 0, 0.5) surface.Fill() surface.Finish() surface.Destroy() for { ev, xerr := X.WaitForEvent() if ev == nil && xerr == nil { // fmt.Println("Both event and error are nil. Exiting...") return } if ev != nil { // fmt.Printf("Event: %s\n", ev) } if xerr != nil { // fmt.Printf("Error: %s\n", xerr) } } }
func main() { // Open the connection to the X server X, err := xgb.NewConn() if err != nil { log.Fatal(err) } // geometric objects points := []xproto.Point{ {10, 10}, {10, 20}, {20, 10}, {20, 20}} polyline := []xproto.Point{ {50, 10}, {5, 20}, // rest of points are relative {25, -20}, {10, 10}} segments := []xproto.Segment{ {100, 10, 140, 30}, {110, 25, 130, 60}} rectangles := []xproto.Rectangle{ {10, 50, 40, 20}, {80, 50, 10, 40}} arcs := []xproto.Arc{ {10, 100, 60, 40, 0, 90 << 6}, {90, 100, 55, 40, 0, 270 << 6}} setup := xproto.Setup(X) // Get the first screen screen := setup.DefaultScreen(X) // Create black (foreground) graphic context foreground, _ := xproto.NewGcontextId(X) mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures) values := []uint32{screen.BlackPixel, 0} xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values) // Ask for our window's Id win, _ := xproto.NewWindowId(X) winDrawable := xproto.Drawable(win) // Create the window mask = uint32(xproto.CwBackPixel | xproto.CwEventMask) values = []uint32{screen.WhitePixel, xproto.EventMaskExposure} xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth win, // Window Id screen.Root, // Parent Window 0, 0, // x, y 150, 150, // width, height 10, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual mask, values) // masks // Map the window on the screen xproto.MapWindow(X, win) for { evt, err := X.WaitForEvent() switch evt.(type) { case xproto.ExposeEvent: /* We draw the points */ xproto.PolyPoint(X, xproto.CoordModeOrigin, winDrawable, foreground, points) /* We draw the polygonal line */ xproto.PolyLine(X, xproto.CoordModePrevious, winDrawable, foreground, polyline) /* We draw the segments */ xproto.PolySegment(X, winDrawable, foreground, segments) /* We draw the rectangles */ xproto.PolyRectangle(X, winDrawable, foreground, rectangles) /* We draw the arcs */ xproto.PolyArc(X, winDrawable, foreground, arcs) default: /* Unknown event type, ignore it */ } if err != nil { log.Fatal(err) } } return }
func main() { // Open the connection to the X server X, err := xgb.NewConn() if err != nil { log.Fatal(err) } defer X.Close() // geometric objects points := []xproto.Point{ {10, 10}, {10, 20}, {20, 10}, {20, 20}} polyline := []xproto.Point{ {50, 10}, {5, 20}, // rest of points are relative {25, -20}, {10, 10}} segments := []xproto.Segment{ {100, 10, 140, 30}, {110, 25, 130, 60}} rectangles := []xproto.Rectangle{ {10, 50, 40, 20}, {80, 50, 10, 40}} arcs := []xproto.Arc{ {10, 100, 60, 40, 0, 90 << 6}, {90, 100, 55, 40, 0, 270 << 6}} setup := xproto.Setup(X) // Get the first screen screen := setup.DefaultScreen(X) // Create black (foreground) graphic context foreground, _ := xproto.NewGcontextId(X) mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures) values := []uint32{screen.BlackPixel, 0} xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values) // Ask for our window's Id win, _ := xproto.NewWindowId(X) winDrawable := xproto.Drawable(win) // Create the window mask = uint32(xproto.CwBackPixel | xproto.CwEventMask) values = []uint32{screen.WhitePixel, xproto.EventMaskExposure} xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth win, // Window Id screen.Root, // Parent Window 0, 0, // x, y 150, 150, // width, height 10, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual mask, values) // masks // Map the window on the screen xproto.MapWindow(X, win) // Obey the window-delete protocol tp := "WM_PROTOCOLS" prp := "WM_DELETE_WINDOW" typeAtom, _ := xproto.InternAtom(X, true, uint16(len(tp)), tp).Reply() propertyAtom, _ := xproto.InternAtom(X, true, uint16(len(prp)), prp).Reply() // It turns out that we need the window ID as a byte-stream... WTF!! // xprop.ChangeProp(xu, win, 8, "WM_NAME", "STRING", ([]byte)(name)) // ChangeProp(xu *xgbutil.XUtil, win xproto.Window, format byte, prop string, typ string, data []byte) data := make([]byte, 4) xgb.Put32(data, uint32(propertyAtom.Atom)) xproto.ChangeProperty(X, xproto.PropModeReplace, win, typeAtom.Atom, xproto.AtomAtom, 32, 1, data) for { evt, err := X.WaitForEvent() fmt.Printf("An event of type %T occured.\n", evt) if evt == nil && err == nil { fmt.Println("Exiting....") return } else if err != nil { log.Fatal(err) } switch event := evt.(type) { case xproto.ExposeEvent: /* We draw the points */ xproto.PolyPoint(X, xproto.CoordModeOrigin, winDrawable, foreground, points) /* We draw the polygonal line */ xproto.PolyLine(X, xproto.CoordModePrevious, winDrawable, foreground, polyline) /* We draw the segments */ xproto.PolySegment(X, winDrawable, foreground, segments) /* We draw the rectangles */ xproto.PolyRectangle(X, winDrawable, foreground, rectangles) /* We draw the arcs */ xproto.PolyArc(X, winDrawable, foreground, arcs) case xproto.ClientMessageEvent: if len(event.Data.Data32) > 0 { data := xproto.Atom(event.Data.Data32[0]) if data == propertyAtom.Atom { return } else { atomName, _ := xproto.GetAtomName(X, data).Reply() fmt.Println(atomName.Name) } } else { atomName, _ := xproto.GetAtomName(X, event.Type).Reply() fmt.Println(atomName.Name) } default: /* Unknown event type, ignore it */ } } return }
func main() { // Open the connection to the X server X, err := xgb.NewConn() if err != nil { log.Fatal(err) } defer X.Close() setup := xproto.Setup(X) // Get the first screen screen := setup.DefaultScreen(X) // Replace existing window manager wmName := fmt.Sprintf("WM_S%d", X.DefaultScreen) managerAtom, err := xproto.InternAtom(X, true, uint16(len(wmName)), wmName).Reply() if err != nil { log.Fatal(err) } fakeWindow, _ := xproto.NewWindowId(X) xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth fakeWindow, // Window Id screen.Root, // Parent Window -1000, -1000, // x, y 1, 1, // width, height 0, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual xproto.CwEventMask|xproto.CwOverrideRedirect, []uint32{1, xproto.EventMaskPropertyChange}) // masks xproto.MapWindow(X, fakeWindow) err = xproto.SetSelectionOwnerChecked(X, fakeWindow, managerAtom.Atom, xproto.TimeCurrentTime).Check() if err != nil { fmt.Println("foo") log.Fatal(err) } arcs := []xproto.Arc{ {10, 100, 60, 40, 0, 90 << 6}, {90, 100, 55, 40, 0, 270 << 6}} // Create black (foreground) graphic context foreground, _ := xproto.NewGcontextId(X) mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures) values := []uint32{screen.BlackPixel, 0} xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values) // Ask for our window's Id win, _ := xproto.NewWindowId(X) winDrawable := xproto.Drawable(win) // Create the window mask = uint32(xproto.CwBackPixel | xproto.CwEventMask) values = []uint32{screen.WhitePixel, xproto.EventMaskExposure} xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth win, // Window Id screen.Root, // Parent Window 0, 0, // x, y 150, 150, // width, height 10, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual mask, values) // masks // Map the window on the screen xproto.MapWindow(X, win) // Obey the window-delete protocol tp := "WM_PROTOCOLS" prp := "WM_DELETE_WINDOW" typeAtom, _ := xproto.InternAtom(X, true, uint16(len(tp)), tp).Reply() propertyAtom, _ := xproto.InternAtom(X, true, uint16(len(prp)), prp).Reply() data := make([]byte, 4) xgb.Put32(data, uint32(propertyAtom.Atom)) xproto.ChangeProperty(X, xproto.PropModeReplace, win, typeAtom.Atom, xproto.AtomAtom, 32, 1, data) // Main loop for { evt, err := X.WaitForEvent() fmt.Printf("An event of type %T occured.\n", evt) if evt == nil && err == nil { fmt.Println("Exiting....") return } else if err != nil { log.Fatal(err) } switch event := evt.(type) { case xproto.ExposeEvent: /* We draw the arcs */ xproto.PolyArc(X, winDrawable, foreground, arcs) case xproto.ClientMessageEvent: if len(event.Data.Data32) > 0 { data := xproto.Atom(event.Data.Data32[0]) if data == propertyAtom.Atom { return } else { atomName, _ := xproto.GetAtomName(X, data).Reply() fmt.Println(atomName.Name) } } else { atomName, _ := xproto.GetAtomName(X, event.Type).Reply() fmt.Println(atomName.Name) } default: /* Unknown event type, ignore it */ } } return }
// NewConnXgb use the specific xgb.Conn to create a new XUtil. // // NewConn, NewConnDisplay are wrapper of this function. func NewConnXgb(c *xgb.Conn) (*XUtil, error) { setup := xproto.Setup(c) screen := setup.DefaultScreen(c) // Initialize our central struct that stores everything. xu := &XUtil{ conn: c, Quit: false, Evqueue: make([]EventOrError, 0, 1000), EvqueueLck: &sync.RWMutex{}, setup: setup, screen: screen, root: screen.Root, eventTime: xproto.Timestamp(0), // last event time Atoms: make(map[string]xproto.Atom, 50), AtomsLck: &sync.RWMutex{}, AtomNames: make(map[xproto.Atom]string, 50), AtomNamesLck: &sync.RWMutex{}, Callbacks: make(map[int]map[xproto.Window][]Callback, 33), CallbacksLck: &sync.RWMutex{}, Hooks: make([]CallbackHook, 0), HooksLck: &sync.RWMutex{}, Keymap: nil, // we don't have anything yet Modmap: nil, KeyRedirect: 0, Keybinds: make(map[KeyKey][]CallbackKey, 10), KeybindsLck: &sync.RWMutex{}, Keygrabs: make(map[KeyKey]int, 10), Keystrings: make([]KeyString, 0, 10), Mousebinds: make(map[MouseKey][]CallbackMouse, 10), MousebindsLck: &sync.RWMutex{}, Mousegrabs: make(map[MouseKey]int, 10), InMouseDrag: false, MouseDragStepFun: nil, MouseDragEndFun: nil, ErrorHandler: func(err xgb.Error) { Logger.Println(err) }, } var err error = nil // Create a general purpose graphics context xu.gc, err = xproto.NewGcontextId(xu.conn) if err != nil { return nil, err } xproto.CreateGC(xu.conn, xu.gc, xproto.Drawable(xu.root), xproto.GcForeground, []uint32{xu.screen.WhitePixel}) // Create a dummy window xu.dummy, err = xproto.NewWindowId(xu.conn) if err != nil { return nil, err } xproto.CreateWindow(xu.conn, xu.Screen().RootDepth, xu.dummy, xu.RootWin(), -1000, -1000, 1, 1, 0, xproto.WindowClassInputOutput, xu.Screen().RootVisual, xproto.CwEventMask|xproto.CwOverrideRedirect, []uint32{1, xproto.EventMaskPropertyChange}) xproto.MapWindow(xu.conn, xu.dummy) // Register the Xinerama extension... because it doesn't cost much. err = xinerama.Init(xu.conn) // If we can't register Xinerama, that's okay. Output something // and move on. if err != nil { Logger.Printf("WARNING: %s\n", err) Logger.Printf("MESSAGE: The 'xinerama' package cannot be used " + "because the XINERAMA extension could not be loaded.") } return xu, nil }
func main() { var err error xConn, err = xgb.NewConn() if err != nil { log.Fatal(err) } if err = xinerama.Init(xConn); err != nil { log.Fatal(err) } xSetup := xp.Setup(xConn) if len(xSetup.Roots) != 1 { log.Fatalf("X setup has unsupported number of roots: %d", len(xSetup.Roots)) } rootXWin = xSetup.Roots[0].Root becomeTheWM() initAtoms() initDesktop(&xSetup.Roots[0]) initKeyboardMapping() initScreens() // Manage any existing windows. if tree, err := xp.QueryTree(xConn, rootXWin).Reply(); err != nil { log.Fatal(err) } else if tree != nil { for _, c := range tree.Children { if c == desktopXWin { continue } attrs, err := xp.GetWindowAttributes(xConn, c).Reply() if attrs == nil || err != nil { continue } if attrs.OverrideRedirect || attrs.MapState == xp.MapStateUnmapped { continue } manage(c, false) } } // Process X events. eeChan := make(chan xEventOrError) go func() { for { e, err := xConn.WaitForEvent() eeChan <- xEventOrError{e, err} } }() for { for i, c := range checkers { if err := c.Check(); err != nil { log.Println(err) } checkers[i] = nil } checkers = checkers[:0] select { case f := <-proactiveChan: f() case ee := <-eeChan: if ee.error != nil { log.Println(ee.error) continue } switch e := ee.event.(type) { case xp.ButtonPressEvent: eventTime = e.Time handleButtonPress(e) case xp.ButtonReleaseEvent: eventTime = e.Time case xp.ClientMessageEvent: // No-op. case xp.ConfigureNotifyEvent: // No-op. case xp.ConfigureRequestEvent: handleConfigureRequest(e) case xp.DestroyNotifyEvent: // No-op. case xp.EnterNotifyEvent: eventTime = e.Time handleEnterNotify(e) case xp.ExposeEvent: handleExpose(e) case xp.KeyPressEvent: eventTime, keyRootX, keyRootY, keyState = e.Time, e.RootX, e.RootY, e.State handleKeyPress(e) case xp.KeyReleaseEvent: eventTime, keyRootX, keyRootY, keyState = e.Time, 0, 0, 0 case xp.MapNotifyEvent: // No-op. case xp.MappingNotifyEvent: // No-op. case xp.MapRequestEvent: manage(e.Window, true) case xp.MotionNotifyEvent: eventTime = e.Time handleMotionNotify(e) case xp.UnmapNotifyEvent: unmanage(e.Window) default: log.Printf("unhandled event: %v", ee.event) } } } }
func main() { X, err := xgb.NewConn() if err != nil { fmt.Println(err) return } // xproto.Setup retrieves the Setup information from the setup bytes // gathered during connection. setup := xproto.Setup(X) // This is the default screen with all its associated info. screen := setup.DefaultScreen(X) // Any time a new resource (i.e., a window, pixmap, graphics context, etc.) // is created, we need to generate a resource identifier. // If the resource is a window, then use xproto.NewWindowId. If it's for // a pixmap, then use xproto.NewPixmapId. And so on... wid, _ := xproto.NewWindowId(X) // CreateWindow takes a boatload of parameters. xproto.CreateWindow(X, screen.RootDepth, wid, screen.Root, 0, 0, 500, 500, 0, xproto.WindowClassInputOutput, screen.RootVisual, 0, []uint32{}) // This call to ChangeWindowAttributes could be factored out and // included with the above CreateWindow call, but it is left here for // instructive purposes. It tells X to send us events when the 'structure' // of the window is changed (i.e., when it is resized, mapped, unmapped, // etc.) and when a key press or a key release has been made when the // window has focus. // We also set the 'BackPixel' to white so that the window isn't butt ugly. xproto.ChangeWindowAttributes(X, wid, xproto.CwBackPixel|xproto.CwEventMask, []uint32{ // values must be in the order defined by the protocol 0xffffffff, xproto.EventMaskStructureNotify | xproto.EventMaskKeyPress | xproto.EventMaskKeyRelease}) // MapWindow makes the window we've created appear on the screen. // We demonstrated the use of a 'checked' request here. // A checked request is a fancy way of saying, "do error handling // synchronously." Namely, if there is a problem with the MapWindow request, // we'll get the error *here*. If we were to do a normal unchecked // request (like the above CreateWindow and ChangeWindowAttributes // requests), then we would only see the error arrive in the main event // loop. // // Typically, checked requests are useful when you need to make sure they // succeed. Since they are synchronous, they incur a round trip cost before // the program can continue, but this is only going to be noticeable if // you're issuing tons of requests in succession. // // Note that requests without replies are by default unchecked while // requests *with* replies are checked by default. err = xproto.MapWindowChecked(X, wid).Check() if err != nil { fmt.Printf("Checked Error for mapping window %d: %s\n", wid, err) } else { fmt.Printf("Map window %d successful!\n", wid) } // This is an example of an invalid MapWindow request and what an error // looks like. err = xproto.MapWindowChecked(X, 0).Check() if err != nil { fmt.Printf("Checked Error for mapping window 0x1: %s\n", err) } else { // neva fmt.Printf("Map window 0x1 successful!\n") } // Start the main event loop. for { // WaitForEvent either returns an event or an error and never both. // If both are nil, then something went wrong and the loop should be // halted. // // An error can only be seen here as a response to an unchecked // request. ev, xerr := X.WaitForEvent() if ev == nil && xerr == nil { fmt.Println("Both event and error are nil. Exiting...") return } if ev != nil { fmt.Printf("Event: %s\n", ev) } if xerr != nil { fmt.Printf("Error: %s\n", xerr) } } }
// Listen ... func Listen(fn func(e Event)) error { X, err := xgb.NewConn() if err != nil { log.Fatal(err) } setup := xproto.Setup(X) root := setup.DefaultScreen(X).Root var prevWindowID xproto.Window var prevClasses []string for { <-time.After(msRefresh * time.Millisecond) // From one of the xgb examples. aname := "_NET_ACTIVE_WINDOW" activeAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Println(err) continue } reply, err := xproto.GetProperty(X, false, root, activeAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Println(err) continue } windowID := xproto.Window(xgb.Get32(reply.Value)) aname = "WM_CLASS" nameAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Println(err) continue } reply, err = xproto.GetProperty(X, false, windowID, nameAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Println(err) continue } classes := stringSlice(reply.Value) // Check if active window has changed since last time. if windowID != prevWindowID { fn(Lost{ WMClass: prevClasses, }) fn(Gained{ WMClass: classes, }) prevWindowID = windowID prevClasses = classes } } }