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 }
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 GetOutputs(X *xgbutil.XUtil) (outputs []*randr.GetOutputInfoReply) { resources, err := randr.GetScreenResources(X.Conn(), X.RootWin()).Reply() if err != nil { return nil } for _, output := range resources.Outputs { oinfo, err := randr.GetOutputInfo(X.Conn(), output, 0).Reply() if err != nil { return nil } outputs = append(outputs, oinfo) } return outputs }
// GetOutputByName fetches an output by name. // FIXME: It's really ugly to just throw away the OutputInfo after using it. See // if there's a better way to do this. func GetOutputByName(X *xgbutil.XUtil, name string) (randr.Output, error) { res, err := randr.GetScreenResources(X.Conn(), X.RootWin()).Reply() if err != nil { return 0, err } var ( oinfo *randr.GetOutputInfoReply output randr.Output ) for _, output = range res.Outputs { oinfo, err = randr.GetOutputInfo(X.Conn(), output, 0).Reply() if err != nil { return 0, err } // See if we've found the correct output. if string(oinfo.Name) == name { break } } return output, nil }
// OutputRect creates a Rectangle fitting the active CRTC of the given output. // Returns the Zero Rectangle and an error if anything goes wrong. If the output // is disabled, the ZR will be returned. func OutputRect(X *xgbutil.XUtil, output randr.Output) (image.Rectangle, error) { oinfo, err := randr.GetOutputInfo(X.Conn(), output, 0).Reply() if err != nil { return image.ZR, err } if oinfo.Crtc == 0 { // this output is disabled return image.ZR, nil } crtc, err := randr.GetCrtcInfo(X.Conn(), oinfo.Crtc, 0).Reply() if err != nil { return image.ZR, err } x, y := int(crtc.X), int(crtc.Y) w, h := int(crtc.Width), int(crtc.Height) return image.Rectangle{ image.Point{x, y}, image.Point{x + w, y + h}, }, nil }
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 (ms Monitors) Update(e *Euclid, x XHandle, mergeOverlapping, removeUnplugged, removeDisabled bool) bool { c := x.Conn() sres, err := randr.GetScreenResources(c, x.Root()).Reply() if err != nil { return false } var r []*randr.GetOutputInfoReply for _, o := range sres.Outputs { rp, _ := randr.GetOutputInfo(c, o, xproto.TimeCurrentTime).Reply() r = append(r, rp) } for _, m := range ms { m.wired = false } for i, info := range r { if info != nil { if info.Crtc != 0 { ir, _ := randr.GetCrtcInfo(c, info.Crtc, xproto.TimeCurrentTime).Reply() if ir != nil { rect := xproto.Rectangle{ir.X, ir.Y, ir.Width, ir.Height} m := ms.fromId(sres.Outputs[i]) if m != nil { m.rectangle = rect m.UpdateRoot() for _, d := range m.desktops { for _, _ = range d.clients { //mm.Translate(mm, n.Client) } } //mm.Arrange() m.wired = true } else { m := ms.Add(e, x, rect) m.name = string(info.Name) m.id = sres.Outputs[i] } } } else if !removeDisabled && info.Connection != randr.ConnectionDisconnected { m := ms.fromId(sres.Outputs[i]) if m != nil { m.wired = true } } } } gpo, _ := randr.GetOutputPrimary(c, x.Root()).Reply() if gpo != nil { primary := ms.fromId(gpo.Output) if primary != nil { primary.primary = true if ms.Focused() != primary { primary.focused = true } //ewmh_update_current_desktop(); } } if mergeOverlapping { ms.mergeOverlapping() } if removeUnplugged { ms.removeUnplugged() } //update_motion_recorder(); return ms.Number() > 0 }