package xmu import ( "xgob" "xgob/util" "xgob/xproto" ) /* The main difference between this and C/libXmu is that this version searches for the client window in the shallowest windows first, and C/libXmu searches the topmost windows first. This change allows us to avoid as many round-trips as possible. */ func tryChildren(c *xgob.Connection, children []xproto.Window) xproto.Window { queryCookies := make([]chan xproto.QueryTreeReply, 0) propCookies := make([]chan xproto.GetPropertyReply, 0) state := util.Atom(c, "WM_STATE") for { if len(children) == 0 { break } // Reset cookie jars queryCookies = queryCookies[:0] propCookies = propCookies[:0] for _, child := range children { propCookies = append(propCookies, xproto.GetProperty(c, false, child, state, xproto.Atom(0), 0, 0)) queryCookies = append(queryCookies, xproto.QueryTree(c, child)) } c.Flush() for i, cookie := range propCookies { s := <-cookie if s.Error == nil && s.Type != xproto.Atom(0) { return children[i] } } children = children[:0] for _, cookie := range queryCookies { children = append(children, (<-cookie).Children...) } } return 0 } func ClientWindow(c *xgob.Connection, win xproto.Window) xproto.Window { stateCookie := xproto.GetProperty(c, false, win, util.Atom(c, "WM_STATE"), xproto.Atom(0), 0, 0) treeCookie := xproto.QueryTree(c, win) c.Flush() state := <-stateCookie if state.Error != nil && state.Type != xproto.Atom(0) { return win } tree := <-treeCookie if rv := tryChildren(c, tree.Children); rv != 0 { win = rv } return win }