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" query1, buf := xproto.InternAtom(X, nil, true, uint16(len(aname)), aname) activeAtom, err := query1.Reply() if err != nil { log.Fatal(err) } // Get the atom id (i.e., intern an atom) of "_NET_WM_NAME". aname = "_NET_WM_NAME" query2, buf := xproto.InternAtom(X, buf, true, uint16(len(aname)), aname) nameAtom, err := query2.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. query3, buf := xproto.GetProperty(X, buf, false, root, activeAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1) reply, err := query3.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. query4, buf := xproto.GetProperty(X, buf, false, windowId, nameAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1) reply, err = query4.Reply() if err != nil { log.Fatal(err) } fmt.Printf("Active window name: %s\n", string(reply.Value)) }
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. query1, buf := randr.GetScreenResources(X, nil, root) resources, err := query1.Reply() if err != nil { log.Fatal(err) } // Iterate through all of the outputs and show some of their info. for _, output := range resources.Outputs { var query2 randr.GetOutputInfoCookie query2, buf = randr.GetOutputInfo(X, buf, output, 0) info, err := query2.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 { var query3 randr.GetCrtcInfoCookie query3, buf = randr.GetCrtcInfo(X, buf, crtc, 0) info, err := query3.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.) query4, buf := randr.SelectInputChecked(X, buf, root, randr.NotifyMaskScreenChange| randr.NotifyMaskCrtcChange| randr.NotifyMaskOutputChange| randr.NotifyMaskOutputProperty) err = query4.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 } // 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, nil, 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, nil, 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. query, buf := xproto.MapWindowChecked(X, nil, wid) err = query.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. query, buf = xproto.MapWindowChecked(X, buf, 0) err = query.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) } } }