3 # manage a list of current windows and allow a selected
5 # I'm using Xlib for this, which doesn't have a built-in event
6 # mechanism like gtk does in gobject.
7 # So if you want to make sure property change notify events
8 # get handled, you need to arrange that read events on
9 # winlist.fd are passed to winlist.events.
10 # e.g. gobject.io_add_watch(winlist.fd, gobject.IO_IN, winlist.events)
15 import Xlib.protocol.event
18 def __init__(self, win, name, pid, list):
25 msg = Xlib.protocol.event.ClientMessage(window = self.win,
26 client_type = self.list.ACTIVE_WINDOW,
27 data = (32, [0,0,0,0,0])
30 mask = (Xlib.X.SubstructureRedirectMask |
31 Xlib.X.SubstructureNotifyMask)
32 self.list.root.send_event(msg, event_mask = mask)
34 self.win.raise_window()
35 #p = w.query_tree().parent
39 self.list.display.flush()
42 msg = Xlib.protocol.event.ClientMessage(window = self.win,
43 client_type = self.list.CLOSE_WINDOW,
44 data = (32, [0,0,0,0,0])
47 mask = (Xlib.X.SubstructureRedirectMask |
48 Xlib.X.SubstructureNotifyMask)
49 self.list.root.send_event(msg, event_mask = mask)
50 self.list.display.flush()
54 self.display = Xlib.display.Display()
55 self.root = self.display.screen().root
58 self.WM_STRUT = self.display.intern_atom('_NET_WM_STRUT')
59 self.CARDINAL = self.display.intern_atom('CARDINAL')
60 self.ACTIVE_WINDOW = self.display.intern_atom('_NET_ACTIVE_WINDOW')
61 self.CLOSE_WINDOW = self.display.intern_atom('_NET_CLOSE_WINDOW')
62 self.NAME = self.display.intern_atom('WM_NAME')
63 self.STRING = self.display.intern_atom('STRING')
64 self.PID = self.display.intern_atom('_NET_WM_PID')
65 self.LIST = self.display.intern_atom('_NET_CLIENT_LIST_STACKING')
66 self.WINDOW = self.display.intern_atom('WINDOW')
68 self.fd = self.display.fileno()
69 self.change_handle = None
71 self.root.change_attributes(event_mask = Xlib.X.PropertyChangeMask )
75 def add_win(self, id):
78 w = self.display.create_resource_object('window', id)
79 p = w.get_property(self.WM_STRUT, self.CARDINAL, 0, 100)
83 p = w.get_property(self.NAME, self.STRING, 0, 100)
84 if p and p.format == 8:
86 name = name.replace('&','&')
87 name = name.replace('<','<')
88 name = name.replace('>','>')
92 p = w.get_property(self.PID, self.CARDINAL, 0, 100)
93 if p and p.format == 32:
98 self.winfo[id] = mywindow(w, name, pid, self)
103 l = self.root.get_property(self.LIST, self.WINDOW, 0, 100)
108 self.windows = windows
110 if self.change_handle:
113 def clean_winfo(self):
116 if w not in self.windows:
121 def events(self, *a):
122 i = self.display.pending_events()
124 event = self.display.next_event()
125 self.handle_event(event)
129 def handle_event(self, event):
130 if event.atom != self.LIST:
135 def top(self, num = 0):
136 if num > len(self.windows) or num < 0:
138 return self.winfo[self.windows[-1-num]]
140 def on_change(self, func):
141 self.change_handle = func
144 if __name__ == '__main__':
147 print i, w.winfo[i].name
149 event = w.display.next_event()
150 if w.handle_event(event):
151 print "First is", w.top(1).name