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
|
import itertools as it, operator as op, functools as ft
from .dta import cached, ProxyObject
from Xlib import X, display
@cached
def _xlib_dpy(): return display.Display()
@cached
def _xlib_atom(name):
return _xlib_dpy().intern_atom(name, only_if_exists=1)
def _xlib_iter():
def __xlib_iter(win):
try: leaves = win.query_tree().children
except AttributeError: pass
else:
return it.chain( leaves,
it.chain.from_iterable(it.imap(__xlib_iter, leaves)) )
dpy = _xlib_dpy()
return it.chain.from_iterable(
__xlib_iter(dpy.screen(scr).root)
for scr in xrange(dpy.screen_count()) )
def _xlib_filter_pid(pid, xwin):
prop = xwin.get_property(
_xlib_atom('_NET_WM_PID'), X.AnyPropertyType, 0, 1 )
if prop and prop.value[0] == pid: return True
else: return False
class Window(ProxyObject):
@classmethod
def from_xwin(cls, xwin, xwin_iter=None):
import gtk
win = cls(gtk.gdk.window_foreign_new(xwin.id))
if xwin_iter is not None: win._xwin_iter = xwin_iter
win._xwin = xwin
return win
@classmethod
def by_pid(cls, pid):
xwin_iter = it.ifilter(ft.partial(
_xlib_filter_pid, pid ), _xlib_iter())
try: xwin = xwin_iter.next()
except StopIteration: return None
else:
win = cls.from_xwin(xwin, xwin_iter)
return win
@classmethod
def get_active(cls, screen=None):
import gtk
if screen is None: screen = gtk.gdk.screen_get_default()
if screen.supports_net_wm_hint('_NET_ACTIVE_WINDOW') \
and screen.supports_net_wm_hint('_NET_WM_WINDOW_TYPE'):
win_gdk = screen.get_active_window()
else: return None
# Check if 'window' is actually a desktop
try:
if win_gdk.get_property('_NET_WM_WINDOW_TYPE')[-1][0] == \
'_NET_WM_WINDOW_TYPE_DESKTOP': return None
except TypeError: pass
win_proxy = cls(win_gdk)
return win_proxy
def __iter__(self):
'Cycle thru classmethod-matched windows'
yield self
while True:
try: yield self.next()
except StopIteration: break
def next(self):
'Cycle thru classmethod-matched windows'
return self.__class__.from_xwin(self._xwin_iter.next(), self._xwin_iter)
_xwin = None
@property
def _xlib_win(self):
if self._xwin: return self._xwin
else:
xlib_win = self._xwin = \
_xlib_dpy().create_resource_object('window', self.xid)
return xlib_win
def bounds_chk(self, jitter=None, state=None):
import gtk
if state is not None and self.get_state() & state: return True
xlib_props = self._xlib_win.get_property(
_xlib_atom('_NET_WM_STATE'), X.AnyPropertyType, 0, 100 )
if xlib_props and ( # feel teh backhand of human-readable varz! ;)
_xlib_atom('_NET_WM_STATE_FULLSCREEN') in xlib_props.value
or ( state & gtk.gdk.WINDOW_STATE_MAXIMIZED
and not state & gtk.gdk.WINDOW_STATE_FULLSCREEN
and (_xlib_atom('_NET_WM_STATE_MAXIMIZED_HORZ') in xlib_props.value
and _xlib_atom('_NET_WM_STATE_MAXIMIZED_VERT') in xlib_props.value) ) ):
return True
if jitter is not None:
screen = self.get_screen()
if max(it.imap(abs, it.imap( op.sub, self.get_size(),
(screen.get_width(), screen.get_height()) ))) <= jitter: return True
return False
@property
def maximized(self):
import gtk
return self.bounds_chk( 50,
gtk.gdk.WINDOW_STATE_MAXIMIZED )
@property
def fullscreen(self):
import gtk
return self.bounds_chk( 0,
gtk.gdk.WINDOW_STATE_FULLSCREEN )
@property
def pid(self):
xlib_props = self._xlib_win.get_property(
_xlib_atom('_NET_WM_PID'), X.AnyPropertyType, 0, 100 )
return xlib_props.value[0]
|