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 }
// NewBackground creates an xgraphics.Image which spans the entire screen, // initialized to black. func NewBackground(X *xgbutil.XUtil) (*xgraphics.Image, error) { res, err := randr.GetScreenResources(X.Conn(), X.RootWin()).Reply() if err != nil { return nil, err } var bgRect image.Rectangle for _, output := range res.Outputs { r, err := util.OutputRect(X, output) // NOTE: It doesn't really matter if this returns a Zero Rectangle. if err != nil { return nil, err } bgRect = bgRect.Union(r) } return xgraphics.New(X, bgRect), 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 }
// 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 }
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 }