-
Notifications
You must be signed in to change notification settings - Fork 0
/
wm.py
190 lines (156 loc) · 5.63 KB
/
wm.py
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
from xmlrpc.client import Boolean
from i3ipc import Connection, Event
from threading import Lock, Thread
class WindowManager():
def __init__(self, testing=False):
"""Manages the state changes of i3 and keeps a list of open in windows. Switching focus will shift windows the front of the list.
Args:
testing (bool, optional): Disable the connection to i3 for testing. Defaults to False.
"""
self._windows = []
self._lock = Lock()
if testing:
self._testing = True
return
else:
self._testing = False
self._i3 = Connection(auto_reconnect=True)
self._i3.on(Event.WINDOW_FOCUS, self._create_on_window_focus())
self._i3.on(Event.WINDOW_NEW, self._create_on_window_new())
self._i3.on(Event.WINDOW_CLOSE, self._create_on_window_close())
self._thread = Thread(target=self._i3.main)
self._thread.start()
def front(self) -> dict:
"""Get the front of the window list.
"""
self._lock.acquire()
front = None
try:
front = None if len(self._windows) == 0 else self._windows[0]
finally:
self._lock.release()
return front
def remove_window(self, id) -> None:
"""Remove window by id
Args:
id (string): id of window
"""
self._lock.acquire()
try:
self._windows = list(filter(lambda window: window['id'] != id, self._windows))
finally:
self._lock.release()
def add_window(self, id, name) -> None:
"""Add a window to the window list.
Args:
id (string): id of the window
name (string): name of the window
"""
self._lock.acquire()
try:
found = False
for window in self._windows:
if window['id'] == id:
found = True
if not found:
self._windows = [{'id': id, 'name': name}] + self._windows
finally:
self._lock.release()
def move_to_front(self, id) -> None:
"""Move window with id to the front of the list.
Args:
id (string): id of the window
"""
self._lock.acquire()
try:
window = list(filter(lambda window: window['id'] == id, self._windows))
if len(window) == 0:
return
self._windows = window + list(filter(lambda window: window['id'] != id, self._windows))
finally:
self._lock.release()
def flip(self) -> None:
"""Flip the order of the first two windows in the list
"""
if len(self._windows) < 2:
return
self._lock.acquire()
try:
self._windows = [self._windows[1]] + [self._windows[0]] + self._windows[2:]
finally:
self._lock.release()
def cmd(self, cmd) -> None:
"""Run i3 command
Args:
cmd (string): i3 command
"""
tmp =self._i3.command(cmd)
def reload(self) -> None:
"""Reload all window data
"""
self._lock.acquire()
try:
self._windows = []
cons = self._i3.get_tree().leaves()
while len(cons) != 0:
con = cons[0]
cons = cons[1:]
self._windows.append({'id': con.id, 'name': con.name})
finally:
self._lock.release()
self.move_to_front(self._i3.get_tree().find_focused().id)
def reload_names(self) -> None:
"""Reload the names of the windows in the window list
"""
self._lock.acquire()
try:
self._windows = [{'id': window['id'], 'name': self._i3.get_tree().find_by_id(window['id']).name} for window in self._windows]
finally:
self._lock.release()
def is_floating(self, id) -> Boolean:
"""Check if a window is floating
Args:
id (int): id of window to check
Returns:
Boolean: true if window is floating
"""
con = self._i3.get_tree().find_by_id(id)
if con == None:
return False
else:
return con.floating == 'auto_on' or con.floating == 'user_on'
def in_same_workspace(self, id1, id2):
con1 = self._i3.get_tree().find_by_id(id1)
con2 = self._i3.get_tree().find_by_id(id2)
if con1 == None or con2 == None:
return False
else:
workspace1 = con1.workspace()
workspace2 = con2.workspace()
if workspace1 == None or workspace2 == None:
return False
else:
return workspace1.id == workspace2.id
def exit(self) -> None:
"""Exit i3 loop and close thread.
"""
self._i3.main_quit()
self._thread.join()
def _create_on_window_focus(self):
"""Create on window focus event handler
"""
def closure(connection, e):
self.move_to_front(e.container.id)
return closure
def _create_on_window_new(self):
"""Create on window new event handler
"""
def closure(connection, e):
self.add_window(e.container.id, e.container.name)
return closure
def _create_on_window_close(self):
"""Create on window close event handler
"""
def closure(connection, e):
self.remove_window(e.container.id)
return closure