func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Get a list of all client ids. clientids, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } // Iterate through each client, find its name and find its size. for _, clientid := range clientids { name, err := ewmh.WmNameGet(X, clientid) // If there was a problem getting _NET_WM_NAME or if its empty, // try the old-school version. if err != nil || len(name) == 0 { name, err = icccm.WmNameGet(X, clientid) // If we still can't find anything, give up. if err != nil || len(name) == 0 { name = "N/A" } } // Now find the geometry, including decorations, of the client window. // Note that DecorGeometry actually traverses the window tree by // issuing QueryTree requests until a top-level window (i.e., its // parent is the root window) is found. The geometry of *that* window // is then returned. dgeom, err := xwindow.New(X, clientid).DecorGeometry() if err != nil { log.Printf("Could not get geometry for %s (0x%X) because: %s", name, clientid, err) continue } fmt.Printf("%s (0x%x)\n", name, clientid) fmt.Printf("\tGeometry: %s\n", dgeom) } }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Start generating other source events. otherChan := otherSource() // Start generating X events (by sending client messages to root window). go xSource(X) // Listen to those X events. xwindow.New(X, X.RootWin()).Listen(xproto.EventMaskSubstructureNotify) // Respond to those X events. xevent.ClientMessageFun( func(X *xgbutil.XUtil, ev xevent.ClientMessageEvent) { atmName, err := xprop.AtomName(X, ev.Type) if err != nil { log.Fatal(err) } fmt.Printf("ClientMessage: %d. %s\n", ev.Data.Data32[0], atmName) }).Connect(X, X.RootWin()) // Instead of using the usual xevent.Main, we use xevent.MainPing. // It runs the main event loop inside a goroutine and returns ping // channels, which are sent benign values right before an event is // dequeued and right after that event has finished running all callbacks // associated with it, respectively. pingBefore, pingAfter, pingQuit := xevent.MainPing(X) for { select { case <-pingBefore: // Wait for the event to finish processing. <-pingAfter case otherVal := <-otherChan: fmt.Printf("Processing other event: %d\n", otherVal) case <-pingQuit: fmt.Printf("xevent loop has quit") return } } }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Wrap the root window in a nice Window type. root := xwindow.New(X, X.RootWin()) // Get the geometry of the root window. rgeom, err := root.Geometry() if err != nil { log.Fatal(err) } // Get the rectangles for each of the active physical heads. // These are returned sorted in order from left to right and then top // to bottom. // But first check if Xinerama is enabled. If not, use root geometry. var heads xinerama.Heads if X.ExtInitialized("XINERAMA") { heads, err = xinerama.PhysicalHeads(X) if err != nil { log.Fatal(err) } } else { heads = xinerama.Heads{rgeom} } // Fetch the list of top-level client window ids currently managed // by the running window manager. clients, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } // Output the head geometry before modifying them. fmt.Println("Workarea for each head:") for i, head := range heads { fmt.Printf("\tHead #%d: %s\n", i+1, head) } // For each client, check to see if it has struts, and if so, apply // them to our list of head rectangles. for _, clientid := range clients { strut, err := ewmh.WmStrutPartialGet(X, clientid) if err != nil { // no struts for this client continue } // Apply the struts to our heads. // This modifies 'heads' in place. xrect.ApplyStrut(heads, uint(rgeom.Width()), uint(rgeom.Height()), strut.Left, strut.Right, strut.Top, strut.Bottom, strut.LeftStartY, strut.LeftEndY, strut.RightStartY, strut.RightEndY, strut.TopStartX, strut.TopEndX, strut.BottomStartX, strut.BottomEndX) } // Now output the head geometry again after modification. fmt.Println("Workarea for each head after applying struts:") for i, head := range heads { fmt.Printf("\tHead #%d: %s\n", i+1, head) } }