Package dtk ::
Package ui ::
Module mplayer_window
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from constant import EDGE_DICT
24 from draw import draw_window_shadow, draw_window_frame
25 from skin_config import skin_config
26 from theme import ui_theme
27 import cairo
28 import gobject
29 import gtk
30 from utils import (cairo_state, propagate_expose, resize_window,
31 set_cursor, get_event_root_coords, enable_shadow,
32 is_double_click, move_window)
33
35 """
36 Special Window class for mplayer.
37
38 Generally speaking, compared with Window class, it uses a different shadow mechanism.
39
40 @undocumented: adjust_window_shadow
41 @undocumented: get_cursor_type
42 @undocumented: expose_window
43 @undocumented: shape_window
44 @undocumented: shape_window_frame
45 @undocumented: shape_window_shadow
46 @undocumented: expose_window_background
47 @undocumented: expose_window_shadow
48 @undocumented: expose_window_frame
49 @undocumented: motion_notify
50 @undocumented: double_click_window
51 @undocumented: monitor_window_state
52 """
53
54 - def __init__(self,
55 enable_resize=False,
56 shadow_radius=6,
57 window_type=gtk.WINDOW_TOPLEVEL):
58 """
59 Initialise the Window class.
60
61 @param enable_resize: If True, the window will be set resizable. By default, it's False.
62 @param shadow_radius: The radius of the shadow.
63 @param window_type: A flag of type gtk._gtk.WindowType, which indicates the type of the window. By default, it's gtk.WINDOW_TOPLEVEL.
64 """
65
66 gtk.Window.__init__(self, window_type)
67 skin_config.wrap_skin_window(self)
68 self.set_decorated(False)
69 self.add_events(gtk.gdk.ALL_EVENTS_MASK)
70 self.shadow_radius = shadow_radius
71 self.frame_radius = 2
72 self.shadow_is_visible = True
73 self.enable_resize = enable_resize
74 self.window_frame = gtk.VBox()
75 self.add(self.window_frame)
76 self.shape_flag = True
77
78
79
80
81 self.shadow_visible = False
82
83 if enable_shadow(self) and self.shadow_visible:
84 self.shadow_padding = self.shadow_radius - self.frame_radius
85 else:
86 self.shadow_padding = 0
87
88
89 if enable_shadow(self) and self.shadow_visible:
90 self.window_shadow = gtk.Window(gtk.WINDOW_TOPLEVEL)
91 self.window_shadow.add_events(gtk.gdk.ALL_EVENTS_MASK)
92 self.window_shadow.set_decorated(False)
93 self.window_shadow.set_colormap(gtk.gdk.Screen().get_rgba_colormap())
94 self.window_shadow.set_transient_for(self)
95 self.window_shadow.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_MENU)
96
97
98 self.connect_after("expose-event", self.expose_window)
99 self.connect("size-allocate", self.shape_window)
100 self.connect("window-state-event", self.monitor_window_state)
101 self.connect("configure-event", self.adjust_window_shadow)
102
103 if enable_shadow(self) and self.shadow_visible:
104 self.window_shadow.connect("expose-event", self.expose_window_shadow)
105 self.window_shadow.connect("size-allocate", self.shape_window_shadow)
106 self.window_shadow.connect("button-press-event", self.resize_window)
107 self.window_shadow.connect("motion-notify-event", self.motion_notify)
108
110 """
111 Internal function to adjust postion and size of the shadow of the window.
112
113 @param widget: the widget of type gtk.Widget.
114 @param event: the event of gtk.gdk.Event.
115 """
116 if enable_shadow(self) and self.shadow_visible:
117 (x, y) = self.get_position()
118 (width, height) = self.get_size()
119
120 self.window_shadow.get_window().move_resize(
121 x - self.shadow_padding, y - self.shadow_padding,
122 width + self.shadow_padding * 2, height + self.shadow_padding * 2
123 )
124
126 """
127 Show the window.
128 """
129 self.show_all()
130
131 if enable_shadow(self) and self.shadow_visible:
132 self.window_shadow.show_all()
133
135 """
136 Internal function to expose the window.
137
138 @param widget: A window of type Gtk.Widget.
139 @param event: The expose event of type gtk.gdk.Event.
140
141 @return: Always return True.
142 """
143
144 cr = widget.window.cairo_create()
145 rect = widget.allocation
146 x, y, w, h = rect.x, rect.y, rect.width, rect.height
147
148
149 cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
150 cr.set_operator(cairo.OPERATOR_SOURCE)
151 cr.paint()
152
153
154 with cairo_state(cr):
155 cr.rectangle(x + 2, y, w - 4, 1)
156 cr.rectangle(x + 1, y + 1, w - 2, 1)
157 cr.rectangle(x, y + 2, w, h - 4)
158 cr.rectangle(x + 2, y + h - 1, w - 4, 1)
159 cr.rectangle(x + 1, y + h - 2, w - 2, 1)
160
161 cr.clip()
162
163 skin_config.render_background(cr, self, x, y)
164
165
166 self.draw_mask(cr, x, y, w, h)
167
168
169 draw_window_frame(cr, x, y, w, h,
170 ui_theme.get_alpha_color("window_frame_outside_1"),
171 ui_theme.get_alpha_color("window_frame_outside_2"),
172 ui_theme.get_alpha_color("window_frame_outside_3"),
173 ui_theme.get_alpha_color("window_frame_inside_1"),
174 ui_theme.get_alpha_color("window_frame_inside_2"),
175 )
176
177
178 propagate_expose(widget, event)
179
180 return True
181
183 '''
184 Draw mask interface, you should implement it you own.
185
186 @param cr: Cairo context.
187 @param x: X coordinate of draw area.
188 @param y: Y coordinate of draw area.
189 @param w: Width of draw area.
190 @param h: Height of draw area.
191 '''
192 pass
193
195 """
196 Enable window shape.
197
198 @param shape_flag: The flag that indicates the shape.
199 """
200 self.shape_flag = shape_flag
201 self.shape_window(self, self.get_allocation())
202
204 """
205 Internal function to draw the shaped window.
206
207 @param widget: A widget of type gtk.Widget.
208 @param rect: The bounding region of the window.
209 """
210 if rect.width > 0 and rect.height > 0:
211
212 x, y, w, h = rect.x, rect.y, rect.width, rect.height
213 bitmap = gtk.gdk.Pixmap(None, w, h, 1)
214 cr = bitmap.cairo_create()
215
216
217 cr.set_source_rgb(0.0, 0.0, 0.0)
218 cr.set_operator(cairo.OPERATOR_CLEAR)
219 cr.paint()
220
221
222 cr.set_source_rgb(1.0, 1.0, 1.0)
223 cr.set_operator(cairo.OPERATOR_OVER)
224
225 if not self.shape_flag:
226
227 cr.rectangle(x, y, w, h)
228 elif self.window != None and self.window.get_state() == gtk.gdk.WINDOW_STATE_FULLSCREEN:
229
230 cr.rectangle(x, y, w, h)
231 else:
232 cr.rectangle(x + 2, y, w - 4, 1)
233 cr.rectangle(x + 1, y + 1, w - 2, 1)
234 cr.rectangle(x, y + 2, w, h - 4)
235 cr.rectangle(x + 1, y + h - 2, w - 2, 1)
236 cr.rectangle(x + 2, y + h - 1, w - 4, 1)
237 cr.fill()
238
239
240 widget.shape_combine_mask(bitmap, 0, 0)
241
242
243 self.queue_draw()
244
245 if enable_shadow(self) and self.shadow_visible:
246 self.window_shadow.queue_draw()
247
249 """
250 Internal function to draw the shaped window's shadow.
251
252 @param widget: A widget of type gtk.Widget.
253 @param rect: The bounding region of the window.
254 """
255 if rect.width > 0 and rect.height > 0:
256
257 x, y, w, h = rect.x, rect.y, rect.width, rect.height
258 bitmap = gtk.gdk.Pixmap(None, w, h, 1)
259 cr = bitmap.cairo_create()
260
261
262 cr.set_source_rgb(0.0, 0.0, 0.0)
263 cr.set_operator(cairo.OPERATOR_CLEAR)
264 cr.paint()
265
266
267 cr.set_source_rgb(1.0, 1.0, 1.0)
268 cr.set_operator(cairo.OPERATOR_OVER)
269
270
271 cr.rectangle(x, y, w, self.shadow_padding)
272 cr.rectangle(x, y + self.shadow_padding, self.shadow_padding, h - self.shadow_padding * 2)
273 cr.rectangle(x + w - self.shadow_padding, y + self.shadow_padding, self.shadow_padding, h - self.shadow_padding * 2)
274 cr.rectangle(x, y + h - self.shadow_padding, w, self.shadow_padding)
275
276
277 cr.rectangle(x + self.shadow_padding, y + self.shadow_padding, 2, 1)
278 cr.rectangle(x + w - self.shadow_padding - 2, y + self.shadow_padding, 2, 1)
279 cr.rectangle(x + self.shadow_padding, y + h - self.shadow_padding - 1, 2, 1)
280 cr.rectangle(x + w - self.shadow_padding - 2, y + h - self.shadow_padding - 1, 2, 1)
281
282
283 cr.rectangle(x + self.shadow_padding, y + self.shadow_padding + 1, 1, 1)
284 cr.rectangle(x + w - self.shadow_padding - 1, y + self.shadow_padding + 1, 1, 1)
285 cr.rectangle(x + self.shadow_padding, y + h - self.shadow_padding - 2, 1, 1)
286 cr.rectangle(x + w - self.shadow_padding - 1, y + h - self.shadow_padding - 2, 1, 1)
287
288 cr.fill()
289
290
291 widget.shape_combine_mask(bitmap, 0, 0)
292
293
294 self.queue_draw()
295
296 if enable_shadow(self) and self.shadow_visible:
297 self.window_shadow.queue_draw()
298
300 """
301 Internal fucntion to expose the window shadow.
302
303 @param widget: the window of gtk.Widget.
304 @param event: The expose event of type gtk.gdk.Event.
305 """
306 if self.shadow_is_visible:
307
308 cr = widget.window.cairo_create()
309 rect = widget.allocation
310 x, y, w, h = rect.x, rect.y, rect.width, rect.height
311
312
313 cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
314 cr.set_operator(cairo.OPERATOR_SOURCE)
315 cr.paint()
316
317
318 draw_window_shadow(cr, x, y, w, h, self.shadow_radius, self.shadow_padding, ui_theme.get_shadow_color("window_shadow"))
319
321 """
322 Hide the window shadow.
323 """
324 self.shadow_is_visible = False
325
326 if enable_shadow(self) and self.shadow_visible:
327 self.window_shadow.hide_all()
328
330 """
331 Show the window shadow.
332 """
333 self.shadow_is_visible = True
334
335 if enable_shadow(self) and self.shadow_visible:
336 self.window_shadow.show_all()
337
339 """
340 An interface which indicates whether the window could be maximized, you should implement this function you own.
341 @return: Always return False.
342 """
343 return False
344
346 """
347 Monitor window state, add shadow when window at maximized or fullscreen status. Otherwise hide shadow.
348
349 @param widget: The window of type gtk.Widget.
350 @param event: The event of gtk.gdk.Event.
351 """
352 window_state = self.window.get_state()
353 if window_state in [gtk.gdk.WINDOW_STATE_MAXIMIZED, gtk.gdk.WINDOW_STATE_FULLSCREEN]:
354 self.hide_shadow()
355
356 if self.is_disable_window_maximized():
357 self.unmaximize()
358 else:
359 self.show_shadow()
360
361 self.adjust_window_shadow(widget, event)
362
364 """
365 Minimize the window. Make it iconified.
366 """
367 self.iconify()
368
370 """
371 Toggle the window size between maximized size and normal size.
372 """
373 window_state = self.window.get_state()
374 if window_state == gtk.gdk.WINDOW_STATE_MAXIMIZED:
375 self.unmaximize()
376 else:
377 self.maximize()
378
380 """
381 Toggle the window between fullscreen mode and normal size.
382 """
383 window_state = self.window.get_state()
384 if window_state == gtk.gdk.WINDOW_STATE_FULLSCREEN:
385 self.unfullscreen()
386 else:
387 self.fullscreen()
388
390 """
391 Close the window. Send the destroy signal to the program.
392
393 @return: Always return False.
394 """
395
396
397 self.hide_all()
398
399 self.emit("destroy")
400
401 return False
402
404 """
405 Resize the window.
406
407 @param widget: The window of type gtk.Widget.
408 @param event: A signal of type gtk.gdk.Event.
409 """
410 if self.enable_resize:
411 edge = self.get_edge()
412 if edge != None:
413 resize_window(self, event, self, edge)
414
416 """
417 Add move event callback.
418
419 @param widget: A widget of type gtk.Widget.
420 """
421 widget.connect("button-press-event", lambda w, e: move_window(w, e, self))
422
424 """
425 Add toggle event callback.
426
427 @param widget: A widget of type gtk.Widget.
428 """
429 widget.connect("button-press-event", self.double_click_window)
430
432 """
433 Internal function to double click event handler of the window. It will maximize the window.
434
435 @param widget: A widget of type gtk.Widget.
436 @param event: A event of type gtk.gdk.Event.
437
438 @return: Always return False.
439 """
440 if is_double_click(event):
441 self.toggle_max_window()
442
443 return False
444
446 """
447 Internal callback for `motion-notify-event` signal.
448
449 @param widget: A widget of gtk.Widget.
450 @param event: The motion-notify-event of type gtk.gdk.Event
451 """
452 if self.enable_resize and self.shadow_is_visible:
453 self.cursor_type = self.get_cursor_type(event)
454 set_cursor(self.window_shadow, self.cursor_type)
455
457 """
458 Get the edge which the cursor is on, according to the cursor type.
459
460 @return: If there is a corresponding cursor type, return an instance of gtk.gdk.WindowEdge, else return None.
461 """
462 if EDGE_DICT.has_key(self.cursor_type):
463 return EDGE_DICT[self.cursor_type]
464 else:
465 return None
466
468 """
469 Get the cursor position.
470
471 @param event: An event of type gtk.gdk.Event.
472
473 @return: If the cursor is on the frame of the window, return the cursor position. Otherwise return None.
474 """
475
476 (ex, ey) = get_event_root_coords(event)
477
478
479 rect = self.window_shadow.get_allocation()
480 (wx, wy) = self.window_shadow.get_position()
481 ww = rect.width
482 wh = rect.height
483
484
485 if wx <= ex <= wx + self.shadow_padding:
486 if wy <= ey <= wy + self.shadow_padding * 2:
487 return gtk.gdk.TOP_LEFT_CORNER
488 elif wy + wh - (self.shadow_padding * 2) <= ey <= wy + wh:
489 return gtk.gdk.BOTTOM_LEFT_CORNER
490 elif wy + self.shadow_padding < ey < wy + wh - self.shadow_padding:
491 return gtk.gdk.LEFT_SIDE
492 else:
493 return None
494 elif wx + ww - self.shadow_padding <= ex <= wx + ww:
495 if wy <= ey <= wy + self.shadow_padding * 2:
496 return gtk.gdk.TOP_RIGHT_CORNER
497 elif wy + wh - (self.shadow_padding * 2) <= ey <= wy + wh:
498 return gtk.gdk.BOTTOM_RIGHT_CORNER
499 elif wy + self.shadow_padding < ey < wy + wh - self.shadow_padding:
500 return gtk.gdk.RIGHT_SIDE
501 else:
502 return None
503 elif wx + self.shadow_padding < ex < wx + ww - self.shadow_padding:
504 if wy <= ey <= wy + self.shadow_padding:
505 return gtk.gdk.TOP_SIDE
506 elif wy + wh - self.shadow_padding <= ey <= wy + wh:
507 return gtk.gdk.BOTTOM_SIDE
508 else:
509 return None
510 else:
511 return None
512
514 """
515 Get the shadow size.
516
517 @return: Always return (0, 0)
518 """
519 return (0, 0)
520
521 gobject.type_register(MplayerWindow)
522
523 if __name__ == "__main__":
524 window = MplayerWindow()
525 window.connect("destroy", lambda w: gtk.main_quit())
526 window.set_size_request(500, 500)
527 window.move(100, 100)
528
529 window.show_window()
530
531 gtk.main()
532