1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
package xmu
import (
"xgob"
"xgob/util/atom"
"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 := atom.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, atom.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
rv := tryChildren(c, tree.Children)
if rv == 0 {
return win
}
return rv
}
|