func connect(c *xgb.Conn, s *xproto.ScreenInfo, rl_execute_atom xproto.Atom, args []string) { log.Println("Connecting with args:", args) tree, err := xproto.QueryTree(c, s.Root).Reply() if err != nil { log.Panic("QueryTree failed:", err) } // Broadcast a property request to every window results := make([]xproto.GetPropertyCookie, len(tree.Children)) for ch, child := range tree.Children { results[ch] = xproto.GetProperty(c, false, child, rl_execute_atom, xproto.GetPropertyTypeAny, 0, 1024) } success := false // Get the responses, look for windows that can recieve our command for i, r := range results { reply, err := r.Reply() if err != nil { log.Panic("GetPropertyRequest failed:", err) } if reply.Format != 0 { data := []byte(strings.Join(args, "\x00")) err = xproto.ChangePropertyChecked(c, xproto.PropModeReplace, tree.Children[i], rl_execute_atom, xproto.AtomString, 8, uint32(len(data)), data).Check() log.Println(" .. sent") success = true } } if success != true { log.Println(" .. server not running? atom = ", rl_execute_atom) } }
// Parent queries the QueryTree and finds the parent window. func (w *Window) Parent() (*Window, error) { tree, err := xproto.QueryTree(w.X.Conn(), w.Id).Reply() if err != nil { return nil, fmt.Errorf("ParentWindow: Error retrieving parent window "+ "for %x: %s", w.Id, err) } return New(w.X, tree.Parent), nil }
// manageExistingClients traverse the window tree and tries to manage all // top-level clients. Clients that are not in the Unmapped state will be // managed. func manageExistingClients() { tree, err := xproto.QueryTree(wm.X.Conn(), wm.Root.Id).Reply() if err != nil { logger.Warning.Printf("Could not issue QueryTree request: %s", err) return } for _, potential := range tree.Children { // Ignore our own dummy window... if potential == wm.X.Dummy() { continue } attrs, err := xproto.GetWindowAttributes(wm.X.Conn(), potential).Reply() if err != nil { continue } if attrs.MapState == xproto.MapStateUnmapped { continue } logger.Message.Printf("Managing existing client %d", potential) xclient.New(potential) } }
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) } } } }