-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathwindowcontrol.py
88 lines (74 loc) · 2.98 KB
/
windowcontrol.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
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('Wnck', '3.0')
from gi.repository import Wnck, GLib
import glib_wrappers
class Window(object):
BROWSERS_WM_CLASSES = ["Navigator.Firefox", "google-chrome.Google-chrome", "Navigator.firefox-beta"]
def __init__(self):
self.xid = None
self.pid = None
self.wm_class = None
self.title = None
self.destkop_id = None
self.hostname = None
def is_browser(self):
return self.wm_class in self.BROWSERS_WM_CLASSES
class WindowControl(object):
LIST_WINDOWS_COMMAND = ["wmctrl", "-lpx"]
def async_list_windows(self, callback):
stdout = glib_wrappers.async_run_subprocess(self.LIST_WINDOWS_COMMAND)
io = GLib.IOChannel(stdout)
def list_windows_callback(*_, **__):
output = io.read()
windows = self.parse_wlist_output(output)
icons = self._get_icons()
for window in windows:
window.icon = icons.get(window.xid, None)
callback(windows)
io.add_watch(GLib.IO_IN | GLib.IO_HUP, list_windows_callback)
@staticmethod
def focus_on_window(window_id):
window_id = hex(window_id)
command = ["wmctrl", "-ia", window_id]
glib_wrappers.async_run_subprocess(command)
def async_focus_on_window(self, window_id):
window_id = hex(window_id)
command = ["wmctrl", "-iR", window_id]
glib_wrappers.async_run_subprocess(command)
@staticmethod
def parse_wlist_output(wlist_output):
windows = list()
for line in wlist_output.splitlines():
window = Window()
line = line.decode('utf-8')
xid_hex_str, line = line.split(" ", 1)
window.xid = int(xid_hex_str, 16)
line = line.lstrip()
window.desktop_id, line = line.split(" ", 1)
line = line.lstrip()
pid_str, line = line.split(" ", 1)
window.pid = int(pid_str)
line = line.lstrip()
window.wm_class, line = line.split(" ", 1)
if window.wm_class == "N/A":
continue
line = line.lstrip()
window.hostname, line = line.split(" ", 1)
window.title = line.lstrip()
if window.title == "Desktop":
continue
# Filter out non-existing windows, see https://askubuntu.com/questions/1345101/what-is-72-27bdh-and-0-27bdh
if window.title.startswith('@') and (window.title.endswith(';BDH') or window.title.endswith(';BDHF')):
continue
windows.append(window)
return windows
def _get_icons(self):
screen = Wnck.Screen.get_default()
# The following is needed in order to wait for windows to ready
while Gtk.events_pending():
Gtk.main_iteration()
screen.force_update()
icons = {w.get_xid(): w.get_icon() for w in screen.get_windows()}
return icons