1 import gobject
2
3 from traylib import *
4 from traylib.icon import Icon
5 from traylib.icon_config import IconConfig
6 from traylib.winicon_config import WinIconConfig
7 from traylib.winmenu import (TYPE_SELECT,
8 TYPE_OPTIONS,
9 WindowMenu,
10 WindowActionMenu)
11
12
14 """
15 An L{Icon} representing a group of windows.
16 You can add/remove windows using the L{add_window()} and L{remove_window()}
17 methods.
18 """
19
20 - def __init__(self, icon_config, win_config):
21 """
22 Creates a new C{WinIcon}.
23
24 @param win_config: The C{WinConfig} controlling the configuration of the
25 C{WinIcon}.
26 """
27 assert isinstance(icon_config, IconConfig)
28 assert isinstance(win_config, WinIconConfig)
29
30 self.__win_config = win_config
31 win_config.add_configurable(self)
32 Icon.__init__(self, icon_config)
33
34 self.__name = ''
35 self.__windows = []
36 self.__visible_windows = []
37 self.__window_handlers = {}
38
39 self.connect("destroy", self.__destroy)
40
41 assert self.__name == ''
42 assert self.__windows == []
43 assert self.__visible_windows == []
44 assert self.__window_handlers == {}
45 assert self.__win_config == win_config
46 assert self.__win_config.has_configurable(self)
47
49 """
50 @return: {True} if all visible windows of the C{WinIcon} are minimized.
51 """
52 if not self.__visible_windows:
53 return False
54 for window in self.__visible_windows:
55 if not window.is_minimized():
56 return False
57 return True
58
60 """Updates the name by calling L{make_name()}"""
61 self.__name = self.make_name()
62 assert (self.__name == None or isinstance(self.__name, unicode)
63 or isinstance(self.__name, str))
64
66 """
67 Updates the list of visible windows. Also calls L{update_has_arrow()},
68 L{update_tooltip()}, L{update_zoom_factor()} and L{update_visibility()}.
69 """
70 self.__visible_windows = []
71 for window in self.__windows:
72 if self.window_is_visible(window):
73 self.__visible_windows.append(window)
74 self.update_has_arrow()
75 self.update_tooltip()
76 self.update_zoom_factor()
77 self.update_visibility()
78
80 """
81 If the active window is in the C{WinIcon}'s list of visible windows,
82 activates the window after the active window in the list of visible
83 windows. If not, the first visible window of the C{WinIcon} is
84 activated.
85 """
86 if not self.__visible_windows:
87 return False
88 active_window = screen.get_active_window()
89 found = False
90 for window in self.__visible_windows:
91 if found:
92 window.activate(time)
93 return True
94 if window == active_window:
95 found = True
96 self.__visible_windows[0].activate(time)
97 return True
98
100 """
101 If the active window is in the C{WinIcon}'s list of visible windows,
102 activates the window before the active window in the list of visible
103 windows. If not, the first visible window of the C{WinIcon} is
104 activated.
105 """
106 if not self.__visible_windows:
107 return False
108 active_window = screen.get_active_window()
109 found = False
110 last = len(self.__visible_windows) - 1
111 previous_window = self.__visible_windows[last]
112 for window in self.__visible_windows:
113 if window == active_window:
114 break
115 previous_window = window
116 previous_window.activate(time)
117 return True
118
120 """
121 Adds C{window} to the C{WinIcon}'s list of windows.
122
123 @param window: The window to be added.
124 """
125 if window in self.__windows:
126 return
127 if not self.should_have_window(window):
128 return
129 self.__window_handlers[window] = (
130 window.connect("name_changed",
131 self.__window_name_changed),
132 window.connect("state_changed",
133 self.__window_state_changed),
134 window.connect("workspace_changed",
135 self.__window_workspace_changed))
136 self.__windows.append(window)
137
138 if self.window_is_visible(window):
139 self.__visible_windows.append(window)
140
141 self.update_has_arrow()
142 self.update_zoom_factor()
143 self.update_tooltip()
144 self.update_visibility()
145
146 assert window in self.__windows
147 assert self.__window_handlers.get(window)
148
150 """
151 Removes C{window} from the C{WinIcon}'s list of windows.
152
153 @param window: The window to be removed.
154 """
155 if window not in self.__windows:
156 return
157 for handler in self.__window_handlers[window]:
158 window.disconnect(handler)
159 del self.__window_handlers[window]
160 self.__windows.remove(window)
161 if window in self.__visible_windows:
162 self.__visible_windows.remove(window)
163
164 self.update_has_arrow()
165 self.update_zoom_factor()
166 self.update_tooltip()
167 self.update_visibility()
168
169 assert window not in self.__windows
170 assert window not in self.__visible_windows
171 assert not self.__window_handlers.get(window)
172
174 """
175 @return: C{True} if the window should show up in the C{WinIcon}'s menu.
176 """
177 return (window in self.__windows
178 and not window.is_skip_tasklist()
179 and (self.__win_config.all_workspaces
180 or window.get_workspace() == screen.get_active_workspace()
181 or window.is_pinned()
182 or window.is_sticky()))
183
184
185
186
190
202
206
212
214 if self.window_is_visible(window):
215 if window not in self.__visible_windows:
216 self.__visible_windows.append(window)
217 else:
218 if window in self.__visible_windows:
219 self.__visible_windows.remove(window)
220
221
222
223
225 """
226 Determines the visibility.
227
228 @return: C{True} if the C{WinIcon} has any visible windows or if it
229 should not hide icons with no visible windows.
230 """
231 return (not self.should_hide_if_no_visible_windows()
232 or self.__visible_windows)
233
235 """
236 Determines the zoom factor.
237
238 @return: If the icon has the active window: C{1.5}
239 If the icon has only minimized windows: half the zoom factor
240 returned by C{Icon.make_zoom_factor()}
241 Else: the zoom factor returned by C{Icon.make_zoom_factor()}
242 """
243 if self.has_active_window:
244 return 1.5
245 zoom_factor = Icon.make_zoom_factor(self)
246 if self.is_minimized():
247 zoom_factor *= 0.66
248 return zoom_factor
249
251 """
252 Determines whether to show an arrow or not.
253
254 @return: C{True} if the icon has more than one visible window and its
255 C{WinConfig} is configured to show an arrow.
256 """
257 return self.__win_config.arrow and len(self.__visible_windows) > 1
258
266
267 - def click(self, time = 0L):
268 """
269 If the C{WinIcon} has only one visible window, it is activated or
270 minimized, depending on its current state. If it's on a different
271 workspace, that workspace is also activated.
272
273 @return: C{True} if some action could be performed.
274 """
275 if len(self.__visible_windows) != 1:
276 return False
277 window = self.__visible_windows[0]
278 if self.has_active_window and not window.is_minimized():
279 window.minimize()
280 else:
281 window.get_workspace().activate(time)
282 window.unminimize(time)
283 window.activate(time)
284 return True
285
287 """
288 @return: The menu when the C{WinIcon} was left-clicked.
289 If it has more than one visible window, returns a L{WindowMenu}
290 where a window can be selected to be activated. Else, returns
291 C{None}.
292 """
293 if len(self.__visible_windows) <= 1:
294 return None
295 if self.should_use_icon_for_winmenu():
296 icon = self.icon
297 else:
298 icon = None
299 return WindowMenu(self.__visible_windows,
300 TYPE_SELECT,
301 icon,
302 self.__name,
303 self.get_root_path(),
304 icon)
305
307 """
308 @return: The menu when the C{WinIcon} was right-clicked.
309 If it has more than one visible window, returns a L{WindowMenu}
310 with a submenu of window actions for each window.
311 If there's only one visible window, returns a L{WindowActionMenu}
312 for that window.
313 Else, returns C{None}.
314 """
315 if not self.__visible_windows:
316 return None
317 if len(self.__visible_windows) > 1:
318 if self.should_use_icon_for_winmenu():
319 icon = self.icon
320 else:
321 icon = None
322 return WindowMenu(self.__visible_windows,
323 TYPE_OPTIONS,
324 icon,
325 self.__name,
326 self.get_root_path(),
327 icon,
328 has_kill = self.menu_has_kill())
329 else:
330 return WindowActionMenu(self.__visible_windows[0],
331 has_kill = self.menu_has_kill())
332
334 """
335 Activates the next window.
336
337 @return: C{True} if the next window could be activated.
338 @see: WinIcon.activate_next_window()
339 """
340 return self.activate_next_window(time)
341
343 """
344 Activates the previous window.
345
346 @return: C{True} if the previous window could be activated.
347 @see: L{activate_previous_window()}
348 """
349 return self.activate_previous_window(time)
350
352 """
353 Activates the next window.
354
355 @return: C{True} if the next window could be activated.
356 @see: L{activate_next_window()}
357 """
358 return self.activate_next_window(time)
359
361 """
362 Override this to determine whether the C{WinIcon} should hide if it has
363 no visible windows anymore.
364
365 @return: C{True}
366 """
367 return True
368
370 """
371 Override this to determine whether the C{WinIcon}'s menu has a "kill"
372 menu item.
373
374 @return: C{True}
375 """
376 return True
377
378
379
380
383
386
387
388
389
391 """
392 Override this to determine the C{WinIcon}'s name.
393
394 @return: The new name of the C{WinIcon}.
395 """
396 return ''
397
400
403
406
407
408 name = property(lambda self : self.__name)
409 """
410 The C{WinIcon}'s name.
411 """
412
413 visible_windows = property(lambda self : self.__visible_windows)
414 """
415 The list of visible windows.
416 """
417
418 has_active_window = property(lambda self : screen.get_active_window() in self.__windows)
419 """
420 {True} if the C{WinIcon} has the active window.
421 """
422
423 has_visible_windows = property(lambda self : bool(self.__visible_windows))
424 """
425 {True} if the C{WinIcon} has any visible windows.
426 """
427
428 has_windows = property(lambda self : bool(self.__windows))
429 """
430 {True} if the C{WinIcon} has any windows.
431 """
432