-
Notifications
You must be signed in to change notification settings - Fork 16
/
tree.go
193 lines (173 loc) · 5.61 KB
/
tree.go
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package i3
import (
"encoding/json"
)
// NodeType indicates the specific kind of Node.
type NodeType string
// i3 currently implements the following node types:
const (
Root NodeType = "root"
OutputNode NodeType = "output"
Con NodeType = "con"
FloatingCon NodeType = "floating_con"
WorkspaceNode NodeType = "workspace"
DockareaNode NodeType = "dockarea"
)
// Layout indicates the layout of a Node.
type Layout string
// i3 currently implements the following layouts:
const (
SplitH Layout = "splith"
SplitV Layout = "splitv"
Stacked Layout = "stacked"
Tabbed Layout = "tabbed"
DockareaLayout Layout = "dockarea"
OutputLayout Layout = "output"
)
// BorderStyle indicates the border style of a node.
type BorderStyle string
// i3 currently implements the following border styles:
const (
NormalBorder BorderStyle = "normal"
NoBorder BorderStyle = "none"
PixelBorder BorderStyle = "pixel"
)
// Rect is a rectangle, used for various dimensions in Node, for example.
type Rect struct {
X int64 `json:"x"`
Y int64 `json:"y"`
Width int64 `json:"width"`
Height int64 `json:"height"`
}
// WindowProperties correspond to X11 window properties
//
// See https://build.i3wm.org/docs/ipc.html#_tree_reply
type WindowProperties struct {
Title string `json:"title"`
Instance string `json:"instance"`
Class string `json:"class"`
Role string `json:"window_role"`
Transient NodeID `json:"transient_for"`
}
// NodeID is an i3-internal ID for the node, which can be used to identify
// containers within the IPC interface.
type NodeID int64
// FullscreenMode indicates whether the container is fullscreened, and relative
// to where (its output, or globally). Note that all workspaces are considered
// fullscreened on their respective output.
type FullscreenMode int64
const (
FullscreenNone FullscreenMode = 0
FullscreenOutput FullscreenMode = 1
FullscreenGlobal FullscreenMode = 2
)
// FloatingType indicates the floating type of Node.
type FloatingType string
// i3 currently implements the following node types:
const (
AutoOff FloatingType = "auto_off"
AutoOn FloatingType = "auto_on"
UserOn FloatingType = "user_on"
UserOff FloatingType = "user_off"
)
// Node is a node in a Tree.
//
// See https://i3wm.org/docs/ipc.html#_tree_reply for more details.
type Node struct {
ID NodeID `json:"id"`
Name string `json:"name"` // window: title, container: internal name
Type NodeType `json:"type"`
Border BorderStyle `json:"border"`
CurrentBorderWidth int64 `json:"current_border_width"`
Layout Layout `json:"layout"`
Percent float64 `json:"percent"`
Rect Rect `json:"rect"` // absolute (= relative to X11 display)
WindowRect Rect `json:"window_rect"` // window, relative to Rect
DecoRect Rect `json:"deco_rect"` // decoration, relative to Rect
Geometry Rect `json:"geometry"` // original window geometry, absolute
Window int64 `json:"window"` // X11 window ID of the client window
WindowProperties WindowProperties `json:"window_properties"`
Urgent bool `json:"urgent"` // urgency hint set
Marks []string `json:"marks"`
Focused bool `json:"focused"`
WindowType string `json:"window_type"`
FullscreenMode FullscreenMode `json:"fullscreen_mode"`
Focus []NodeID `json:"focus"`
Nodes []*Node `json:"nodes"`
FloatingNodes []*Node `json:"floating_nodes"`
Floating FloatingType `json:"floating"`
ScratchpadState string `json:"scratchpad_state"`
AppID string `json:"app_id"` // if talking to Sway: Wayland App ID
Sticky bool `json:"sticky"`
}
// FindChild returns the first Node matching predicate, using pre-order
// depth-first search.
func (n *Node) FindChild(predicate func(*Node) bool) *Node {
if predicate(n) {
return n
}
for _, c := range n.Nodes {
if con := c.FindChild(predicate); con != nil {
return con
}
}
for _, c := range n.FloatingNodes {
if con := c.FindChild(predicate); con != nil {
return con
}
}
return nil
}
// FindFocused returns the first Node matching predicate from the sub-tree of
// directly and indirectly focused containers.
//
// As an example, consider this layout tree (simplified):
//
// root
// │
// HDMI2
// ╱ ╲
// … workspace 1
// ╱ ╲
// XTerm Firefox
//
// In this example, if Firefox is focused, FindFocused will return the first
// container matching predicate of root, HDMI2, workspace 1, Firefox (in this
// order).
func (n *Node) FindFocused(predicate func(*Node) bool) *Node {
if predicate(n) {
return n
}
if len(n.Focus) == 0 {
return nil
}
first := n.Focus[0]
for _, c := range n.Nodes {
if c.ID == first {
return c.FindFocused(predicate)
}
}
for _, c := range n.FloatingNodes {
if c.ID == first {
return c.FindFocused(predicate)
}
}
return nil
}
// Tree is an i3 layout tree, starting with Root.
type Tree struct {
// Root is the root node of the layout tree.
Root *Node
}
// GetTree returns i3’s layout tree.
//
// GetTree is supported in i3 ≥ v4.0 (2011-07-31).
func GetTree() (Tree, error) {
reply, err := roundTrip(messageTypeGetTree, nil)
if err != nil {
return Tree{}, err
}
var root Node
err = json.Unmarshal(reply.Payload, &root)
return Tree{Root: &root}, err
}