Merge lp:~smspillaz/compiz-core/compiz-core.decor_sync_996901 into lp:compiz-core/0.9.8
- compiz-core.decor_sync_996901
- Merge into 0.9.8
Status: | Merged |
---|---|
Merged at revision: | 3137 |
Proposed branch: | lp:~smspillaz/compiz-core/compiz-core.decor_sync_996901 |
Merge into: | lp:compiz-core/0.9.8 |
Diff against target: |
1474 lines (+856/-67) 15 files modified
gtk/window-decorator/decorator.c (+55/-25) gtk/window-decorator/events.c (+12/-1) gtk/window-decorator/gtk-window-decorator.c (+9/-0) gtk/window-decorator/gtk-window-decorator.h (+8/-0) gtk/window-decorator/wnck.c (+13/-11) include/decoration.h (+18/-0) libdecoration/decoration.c (+86/-0) plugins/decor/CMakeLists.txt (+3/-1) plugins/decor/src/decor.cpp (+99/-22) plugins/decor/src/decor.h (+35/-7) plugins/decor/src/pixmap-requests/CMakeLists.txt (+62/-0) plugins/decor/src/pixmap-requests/include/pixmap-requests.h (+188/-0) plugins/decor/src/pixmap-requests/src/pixmap-requests.cpp (+93/-0) plugins/decor/src/pixmap-requests/tests/CMakeLists.txt (+15/-0) plugins/decor/src/pixmap-requests/tests/pixmap-requests/src/test-decor-pixmap-requests.cpp (+160/-0) |
To merge this branch: | bzr merge lp:~smspillaz/compiz-core/compiz-core.decor_sync_996901 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel van Vugt | Approve | ||
Alan Griffiths | Approve | ||
Review via email: mp+105344@code.launchpad.net |
Description of the change
Add synchronization primitives to the decoration protocol so that there isn't a race where we bind a texture that's being freed.
Things changed
* update_
* decor_post_pending : tells the decorated process that a new decoration is pending
* decor_post_request : tells the decorator that a new pixmap can be drawn to
* decor_post_
I also did some necessary refactoring so we could get this under test, namely:
DecorPixmap class (implements DecorPixmapInte
X11DecorPixmapR
X11DecorPixmapR
X11PixmapDeletor class (implements DecorPixmapDele
DecorationListF
DecorationInter
Tests included (Google Mock)
Resubmitted to cover a potential race condition in LP#996901
Alan Griffiths (alan-griffiths) wrote : | # |
Sam Spilsbury (smspillaz) wrote : | # |
> Looks sensible - but so did the version that caused problems.
A race condition in the untested part of the code. we should look into getting gtk-window-
triplesqaurednine (triplesquarednine) wrote : | # |
@Sam,
I just tested this branch and it works.
if you like i can still test r3131 to see what the actual problem was, but it would appear your changes in this branch work.
cheerz
Sam Spilsbury (smspillaz) wrote : | # |
> @Sam,
>
> I just tested this branch and it works.
>
> if you like i can still test r3131 to see what the actual problem was, but it
> would appear your changes in this branch work.
>
> cheerz
It's probably worth mentioning as it would be a needle in the haystack in the diff due to the speedy revert
635 if (!d->decorated)
636 return FALSE;
637
There was a race where a window could have its decoration resources freed by the time compiz got back to us about whether or not it was ok to re-update decorations.
As a side note, this particular part of the code has always suffered from such race conditions which can lead to random crashes. It is worth looking into a way that we can fix this, but like I said earlier, I fear that larger architectural changes may be required.
Alan Griffiths (alan-griffiths) : | # |
Daniel van Vugt (vanvugt) wrote : | # |
Unfortunately, I find gtk-window-
(gdb) bt
#0 max_window_
#1 0x000000000041a377 in request_
#2 0x00000000004173c7 in active_
#3 0x00007fd8312ad354 in g_cclosure_
#4 0x00007fd8312a9eca in ?? () from /usr/lib/
#5 0x00007fd8312c2741 in g_signal_
#6 0x00007fd8312c3242 in g_signal_emit () from /usr/lib/
#7 0x00007fd8329404d0 in ?? () from /usr/lib/
#8 0x00007fd8329413f4 in ?? () from /usr/lib/
#9 0x00007fd830fecc9a in g_main_
#10 0x00007fd830fed060 in ?? () from /lib/x86_
#11 0x00007fd830fed45a in g_main_loop_run () from /lib/x86_
#12 0x00007fd8324242f7 in gtk_main () from /usr/lib/
#13 0x000000000040af84 in main (argc=2, argv=0x7fff0347
(gdb)
Daniel van Vugt (vanvugt) wrote : | # |
valgrind confirms the first memory error before the crash has the same stack as gdb reports above.
- 3134. By Sam Spilsbury
-
Also don't bother asking the compositor to update the decoration
when the window is undecorated anyways
Daniel van Vugt (vanvugt) wrote : | # |
Approved revision 3134.
Preview Diff
1 | === modified file 'gtk/window-decorator/decorator.c' |
2 | --- gtk/window-decorator/decorator.c 2012-05-09 22:31:15 +0000 |
3 | +++ gtk/window-decorator/decorator.c 2012-05-15 07:20:22 +0000 |
4 | @@ -564,6 +564,52 @@ |
5 | } |
6 | } |
7 | |
8 | +/* |
9 | + * request_update_window_decoration_size |
10 | + * Description: asks the rendering process to allow a size update |
11 | + * for pixmap synchronization */ |
12 | + |
13 | + |
14 | +gboolean |
15 | +request_update_window_decoration_size (WnckWindow *win) |
16 | +{ |
17 | + decor_t *d; |
18 | + gint width, height; |
19 | + gint x, y, w, h, name_width; |
20 | + |
21 | + if (win == NULL) |
22 | + return FALSE; |
23 | + |
24 | + d = g_object_get_data (G_OBJECT (win), "decor"); |
25 | + |
26 | + if (!d->decorated) |
27 | + return FALSE; |
28 | + |
29 | + /* Get the geometry of the window, we'll need it later */ |
30 | + wnck_window_get_client_window_geometry (win, &x, &y, &w, &h); |
31 | + |
32 | + /* Get the width of the name */ |
33 | + name_width = max_window_name_width (win); |
34 | + |
35 | + /* Ask the theme to tell us how much space it needs. If this is not successful |
36 | + * update the decoration name and return false */ |
37 | + if (!(*theme_calc_decoration_size) (d, w, h, name_width, &width, &height)) |
38 | + { |
39 | + update_window_decoration_name (win); |
40 | + return FALSE; |
41 | + } |
42 | + |
43 | + d->width = width; |
44 | + d->height = height; |
45 | + |
46 | + decor_post_pending (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), |
47 | + wnck_window_get_xid (win), |
48 | + populate_frame_type (d), |
49 | + populate_frame_state (d), |
50 | + populate_frame_actions (d)); |
51 | + |
52 | + return TRUE; |
53 | +} |
54 | |
55 | /* |
56 | * update_window_decoration_size |
57 | @@ -581,8 +627,6 @@ |
58 | decor_t *d; |
59 | GdkPixmap *pixmap, *buffer_pixmap = NULL; |
60 | Picture picture; |
61 | - gint width, height; |
62 | - gint x, y, w, h, name_width; |
63 | Display *xdisplay; |
64 | XRenderPictFormat *format; |
65 | |
66 | @@ -591,30 +635,19 @@ |
67 | |
68 | d = g_object_get_data (G_OBJECT (win), "decor"); |
69 | |
70 | + if (!d->decorated) |
71 | + return FALSE; |
72 | + |
73 | xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); |
74 | |
75 | - /* Get the geometry of the window, we'll need it later */ |
76 | - wnck_window_get_client_window_geometry (win, &x, &y, &w, &h); |
77 | - |
78 | - /* Get the width of the name */ |
79 | - name_width = max_window_name_width (win); |
80 | - |
81 | - /* Ask the theme to tell us how much space it needs. If this is not successful |
82 | - * update the decoration name and return false */ |
83 | - if (!(*theme_calc_decoration_size) (d, w, h, name_width, &width, &height)) |
84 | - { |
85 | - update_window_decoration_name (win); |
86 | - return FALSE; |
87 | - } |
88 | - |
89 | gdk_error_trap_push (); |
90 | |
91 | /* Get the correct depth for the frame window in reparenting mode, otherwise |
92 | * enforce 32 */ |
93 | if (d->frame_window) |
94 | - pixmap = create_pixmap (width, height, d->frame->style_window_rgb); |
95 | + pixmap = create_pixmap (d->width, d->height, d->frame->style_window_rgb); |
96 | else |
97 | - pixmap = create_pixmap (width, height, d->frame->style_window_rgba); |
98 | + pixmap = create_pixmap (d->width, d->height, d->frame->style_window_rgba); |
99 | |
100 | gdk_flush (); |
101 | |
102 | @@ -628,9 +661,9 @@ |
103 | gdk_error_trap_push (); |
104 | |
105 | if (d->frame_window) |
106 | - buffer_pixmap = create_pixmap (width, height, d->frame->style_window_rgb); |
107 | + buffer_pixmap = create_pixmap (d->width, d->height, d->frame->style_window_rgb); |
108 | else |
109 | - buffer_pixmap = create_pixmap (width, height, d->frame->style_window_rgba); |
110 | + buffer_pixmap = create_pixmap (d->width, d->height, d->frame->style_window_rgba); |
111 | |
112 | gdk_flush (); |
113 | |
114 | @@ -649,7 +682,7 @@ |
115 | |
116 | /* Destroy the old pixmaps and pictures */ |
117 | if (d->pixmap) |
118 | - g_object_unref (G_OBJECT (d->pixmap)); |
119 | + g_hash_table_insert (destroyed_pixmaps_table, GINT_TO_POINTER (GDK_PIXMAP_XID (d->pixmap)), d->pixmap); |
120 | |
121 | if (d->buffer_pixmap) |
122 | g_object_unref (G_OBJECT (d->buffer_pixmap)); |
123 | @@ -667,9 +700,6 @@ |
124 | |
125 | d->picture = picture; |
126 | |
127 | - d->width = width; |
128 | - d->height = height; |
129 | - |
130 | d->prop_xid = wnck_window_get_xid (win); |
131 | |
132 | update_window_decoration_name (win); |
133 | @@ -1205,7 +1235,7 @@ |
134 | d->context = NULL; |
135 | d->width = d->height = 0; |
136 | |
137 | - update_window_decoration_size (win); |
138 | + request_update_window_decoration_size (win); |
139 | update_event_windows (win); |
140 | } |
141 | } |
142 | |
143 | === modified file 'gtk/window-decorator/events.c' |
144 | --- gtk/window-decorator/events.c 2012-05-09 22:31:15 +0000 |
145 | +++ gtk/window-decorator/events.c 2012-05-15 07:20:22 +0000 |
146 | @@ -1014,7 +1014,7 @@ |
147 | update_window_decoration_state (win); |
148 | update_window_decoration_actions (win); |
149 | update_window_decoration_icon (win); |
150 | - update_window_decoration_size (win); |
151 | + request_update_window_decoration_size (win); |
152 | update_event_windows (win); |
153 | } |
154 | else |
155 | @@ -1069,6 +1069,17 @@ |
156 | } |
157 | } |
158 | } |
159 | + else if (xevent->xclient.message_type == decor_request_atom) |
160 | + { |
161 | + WnckWindow *win = wnck_window_get (xevent->xclient.window); |
162 | + |
163 | + if (win) |
164 | + update_window_decoration_size (win); |
165 | + } |
166 | + else if (xevent->xclient.message_type == decor_delete_pixmap_atom) |
167 | + { |
168 | + g_hash_table_remove (destroyed_pixmaps_table, GINT_TO_POINTER (xevent->xclient.data.l[0])); |
169 | + } |
170 | default: |
171 | break; |
172 | } |
173 | |
174 | === modified file 'gtk/window-decorator/gtk-window-decorator.c' |
175 | --- gtk/window-decorator/gtk-window-decorator.c 2012-05-09 22:31:15 +0000 |
176 | +++ gtk/window-decorator/gtk-window-decorator.c 2012-05-15 07:20:22 +0000 |
177 | @@ -48,6 +48,9 @@ |
178 | Atom toolkit_action_atom; |
179 | Atom toolkit_action_window_menu_atom; |
180 | Atom toolkit_action_force_quit_dialog_atom; |
181 | +Atom decor_request_atom; |
182 | +Atom decor_pending_atom; |
183 | +Atom decor_delete_pixmap_atom; |
184 | |
185 | Atom net_wm_state_atom; |
186 | Atom net_wm_state_modal_atom; |
187 | @@ -103,6 +106,7 @@ |
188 | GtkWidget *switcher_label; |
189 | |
190 | GHashTable *frame_table; |
191 | +GHashTable *destroyed_pixmaps_table; |
192 | GtkWidget *action_menu = NULL; |
193 | gboolean action_menu_mapped = FALSE; |
194 | decor_color_t _title_color[2]; |
195 | @@ -305,6 +309,10 @@ |
196 | net_wm_state_atom = XInternAtom (xdisplay,"_NET_WM_STATE", 0); |
197 | net_wm_state_modal_atom = XInternAtom (xdisplay, "_NET_WM_STATE_MODAL", 0); |
198 | |
199 | + decor_request_atom = XInternAtom (xdisplay, "_COMPIZ_DECOR_REQUEST", 0); |
200 | + decor_pending_atom = XInternAtom (xdisplay, "_COMPIZ_DECOR_PENDING", 0); |
201 | + decor_delete_pixmap_atom = XInternAtom (xdisplay, "_COMPIZ_DECOR_DELETE_PIXMAP", 0); |
202 | + |
203 | status = decor_acquire_dm_session (xdisplay, |
204 | gdk_screen_get_number (gdkscreen), |
205 | "gwd", replace, &dm_sn_timestamp); |
206 | @@ -390,6 +398,7 @@ |
207 | xformat_rgb = XRenderFindStandardFormat (xdisplay, PictStandardRGB24); |
208 | |
209 | frame_table = g_hash_table_new (NULL, NULL); |
210 | + destroyed_pixmaps_table = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); |
211 | |
212 | if (!create_tooltip_window ()) |
213 | { |
214 | |
215 | === modified file 'gtk/window-decorator/gtk-window-decorator.h' |
216 | --- gtk/window-decorator/gtk-window-decorator.h 2012-05-09 22:31:15 +0000 |
217 | +++ gtk/window-decorator/gtk-window-decorator.h 2012-05-15 07:20:22 +0000 |
218 | @@ -306,6 +306,9 @@ |
219 | extern Atom toolkit_action_force_quit_dialog_atom; |
220 | extern Atom net_wm_state_atom; |
221 | extern Atom net_wm_state_modal_atom; |
222 | +extern Atom decor_request_atom; |
223 | +extern Atom decor_pending_atom; |
224 | +extern Atom decor_delete_pixmap_atom; |
225 | |
226 | extern Time dm_sn_timestamp; |
227 | |
228 | @@ -511,6 +514,7 @@ |
229 | |
230 | /* list of all decorations */ |
231 | extern GHashTable *frame_table; |
232 | +extern GHashTable *destroyed_pixmaps_table; |
233 | |
234 | /* action menu */ |
235 | extern GtkWidget *action_menu; |
236 | @@ -628,9 +632,13 @@ |
237 | void |
238 | destroy_bare_frame (); |
239 | |
240 | +/* Don't use directly */ |
241 | gboolean |
242 | update_window_decoration_size (WnckWindow *win); |
243 | |
244 | +gboolean |
245 | +request_update_window_decoration_size (WnckWindow *win); |
246 | + |
247 | void |
248 | update_window_decoration_name (WnckWindow *win); |
249 | |
250 | |
251 | === modified file 'gtk/window-decorator/wnck.c' |
252 | --- gtk/window-decorator/wnck.c 2012-05-09 22:31:15 +0000 |
253 | +++ gtk/window-decorator/wnck.c 2012-05-15 07:20:22 +0000 |
254 | @@ -80,7 +80,7 @@ |
255 | |
256 | if (d->decorated) |
257 | { |
258 | - if (!update_window_decoration_size (win)) |
259 | + if (!request_update_window_decoration_size (win)) |
260 | queue_decor_draw (d); |
261 | } |
262 | } |
263 | @@ -102,7 +102,7 @@ |
264 | d->client_width = width; |
265 | d->client_height = height; |
266 | |
267 | - update_window_decoration_size (win); |
268 | + request_update_window_decoration_size (win); |
269 | update_event_windows (win); |
270 | } |
271 | } |
272 | @@ -128,7 +128,7 @@ |
273 | if (d->decorated) |
274 | { |
275 | update_window_decoration_state (win); |
276 | - if (!update_window_decoration_size (win)) |
277 | + if (!request_update_window_decoration_size (win)) |
278 | queue_decor_draw (d); |
279 | |
280 | update_event_windows (win); |
281 | @@ -143,7 +143,7 @@ |
282 | if (d->decorated) |
283 | { |
284 | update_window_decoration_actions (win); |
285 | - if (!update_window_decoration_size (win)) |
286 | + if (!request_update_window_decoration_size (win)) |
287 | queue_decor_draw (d); |
288 | |
289 | update_event_windows (win); |
290 | @@ -422,7 +422,7 @@ |
291 | update_window_decoration_state (win); |
292 | update_window_decoration_actions (win); |
293 | update_window_decoration_icon (win); |
294 | - update_window_decoration_size (win); |
295 | + request_update_window_decoration_size (win); |
296 | |
297 | update_event_windows (win); |
298 | } |
299 | @@ -585,7 +585,7 @@ |
300 | if (win) |
301 | { |
302 | d = g_object_get_data (G_OBJECT (win), "decor"); |
303 | - if (d && d->pixmap) |
304 | + if (d) |
305 | { |
306 | d->active = wnck_window_is_active (win); |
307 | |
308 | @@ -642,8 +642,9 @@ |
309 | * then we need to redraw the decoration anyways |
310 | * since the image would have changed */ |
311 | if (d->win != NULL && |
312 | - !update_window_decoration_size (d->win) && |
313 | - d->decorated) |
314 | + !request_update_window_decoration_size (d->win) && |
315 | + d->decorated && |
316 | + d->pixmap) |
317 | queue_decor_draw (d); |
318 | |
319 | } |
320 | @@ -653,7 +654,7 @@ |
321 | if (win) |
322 | { |
323 | d = g_object_get_data (G_OBJECT (win), "decor"); |
324 | - if (d && d->pixmap) |
325 | + if (d) |
326 | { |
327 | d->active = wnck_window_is_active (win); |
328 | |
329 | @@ -710,8 +711,9 @@ |
330 | * then we need to redraw the decoration anyways |
331 | * since the image would have changed */ |
332 | if (d->win != NULL && |
333 | - !update_window_decoration_size (d->win) && |
334 | - d->decorated) |
335 | + !request_update_window_decoration_size (d->win) && |
336 | + d->decorated && |
337 | + d->pixmap) |
338 | queue_decor_draw (d); |
339 | |
340 | } |
341 | |
342 | === modified file 'include/decoration.h' |
343 | --- include/decoration.h 2012-05-09 22:31:15 +0000 |
344 | +++ include/decoration.h 2012-05-15 07:20:22 +0000 |
345 | @@ -492,6 +492,24 @@ |
346 | XEvent *event, |
347 | Time dm_sn_timestamp); |
348 | |
349 | +int |
350 | +decor_post_pending (Display *xdisplay, |
351 | + Window client, |
352 | + unsigned int frame_state, |
353 | + unsigned int frame_type, |
354 | + unsigned int frame_actions); |
355 | + |
356 | +int |
357 | +decor_post_delete_pixmap (Display *xdisplay, |
358 | + Pixmap pixmap); |
359 | + |
360 | +int |
361 | +decor_post_generate_request (Display *xdisplay, |
362 | + Window client, |
363 | + unsigned int frame_type, |
364 | + unsigned int frame_state, |
365 | + unsigned int frame_actions); |
366 | + |
367 | #ifdef __cplusplus |
368 | } |
369 | #endif |
370 | |
371 | === modified file 'libdecoration/decoration.c' |
372 | --- libdecoration/decoration.c 2012-05-09 22:31:15 +0000 |
373 | +++ libdecoration/decoration.c 2012-05-15 07:20:22 +0000 |
374 | @@ -2877,6 +2877,92 @@ |
375 | } |
376 | |
377 | int |
378 | +decor_post_pending (Display *xdisplay, |
379 | + Window client, |
380 | + unsigned int frame_state, |
381 | + unsigned int frame_type, |
382 | + unsigned int frame_actions) |
383 | +{ |
384 | + XEvent event; |
385 | + |
386 | + Atom decor_pending = XInternAtom (xdisplay, "_COMPIZ_DECOR_PENDING", FALSE); |
387 | + |
388 | + /* Send a client message indicating that a new |
389 | + * decoration can be generated for this window |
390 | + */ |
391 | + event.xclient.type = ClientMessage; |
392 | + event.xclient.window = client; |
393 | + event.xclient.message_type = decor_pending; |
394 | + event.xclient.format = 32; |
395 | + event.xclient.data.l[0] = frame_type; |
396 | + event.xclient.data.l[1] = frame_state; |
397 | + event.xclient.data.l[2] = frame_actions; |
398 | + event.xclient.data.l[3] = 0; |
399 | + event.xclient.data.l[4] = 0; |
400 | + |
401 | + XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0, |
402 | + StructureNotifyMask, &event); |
403 | + |
404 | + return 1; |
405 | +} |
406 | + |
407 | +int |
408 | +decor_post_generate_request (Display *xdisplay, |
409 | + Window client, |
410 | + unsigned int frame_type, |
411 | + unsigned int frame_state, |
412 | + unsigned int frame_actions) |
413 | +{ |
414 | + XEvent event; |
415 | + |
416 | + Atom decor_request = XInternAtom (xdisplay, "_COMPIZ_DECOR_REQUEST", FALSE); |
417 | + |
418 | + /* Send a client message indicating that a new |
419 | + * decoration can be generated for this window |
420 | + */ |
421 | + event.xclient.type = ClientMessage; |
422 | + event.xclient.window = client; |
423 | + event.xclient.message_type = decor_request; |
424 | + event.xclient.format = 32; |
425 | + event.xclient.data.l[0] = frame_type; |
426 | + event.xclient.data.l[1] = frame_state; |
427 | + event.xclient.data.l[2] = frame_actions; |
428 | + event.xclient.data.l[3] = 0; |
429 | + event.xclient.data.l[4] = 0; |
430 | + |
431 | + XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0, |
432 | + StructureNotifyMask, &event); |
433 | + |
434 | + return 1; |
435 | +} |
436 | + |
437 | +int |
438 | +decor_post_delete_pixmap (Display *xdisplay, |
439 | + Pixmap pixmap) |
440 | +{ |
441 | + XEvent event; |
442 | + |
443 | + Atom decor_delete_pixmap = XInternAtom (xdisplay, "_COMPIZ_DECOR_DELETE_PIXMAP", FALSE); |
444 | + |
445 | + /* Send a client message indicating that a new |
446 | + * decoration can be generated for this window |
447 | + */ |
448 | + event.xclient.type = ClientMessage; |
449 | + event.xclient.window = DefaultRootWindow (xdisplay); |
450 | + event.xclient.message_type = decor_delete_pixmap; |
451 | + event.xclient.format = 32; |
452 | + event.xclient.data.l[0] = pixmap; |
453 | + event.xclient.data.l[1] = 0; |
454 | + event.xclient.data.l[2] = 0; |
455 | + event.xclient.data.l[3] = 0; |
456 | + event.xclient.data.l[4] = 0; |
457 | + |
458 | + XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0, |
459 | + StructureNotifyMask, &event); |
460 | + |
461 | + return 1; |
462 | +} |
463 | +int |
464 | decor_acquire_dm_session (Display *xdisplay, |
465 | int screen, |
466 | const char *name, |
467 | |
468 | === modified file 'plugins/decor/CMakeLists.txt' |
469 | --- plugins/decor/CMakeLists.txt 2012-05-09 22:31:15 +0000 |
470 | +++ plugins/decor/CMakeLists.txt 2012-05-15 07:20:22 +0000 |
471 | @@ -4,10 +4,12 @@ |
472 | include (CompizCommon) |
473 | |
474 | include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/clip-groups/include/) |
475 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/pixmap-requests/include/) |
476 | |
477 | -compiz_plugin(decor PLUGINDEPS composite opengl LIBRARIES decoration compiz_decor_clip_groups) |
478 | +compiz_plugin(decor PLUGINDEPS composite opengl LIBRARIES decoration compiz_decor_clip_groups compiz_decor_pixmap_requests) |
479 | |
480 | add_subdirectory (src/clip-groups) |
481 | +add_subdirectory (src/pixmap-requests) |
482 | |
483 | if (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_DECOR) |
484 | |
485 | |
486 | === modified file 'plugins/decor/src/decor.cpp' |
487 | --- plugins/decor/src/decor.cpp 2012-05-09 22:31:15 +0000 |
488 | +++ plugins/decor/src/decor.cpp 2012-05-15 07:20:22 +0000 |
489 | @@ -311,7 +311,6 @@ |
490 | } |
491 | |
492 | static bool bindFailed; |
493 | - |
494 | /* |
495 | * DecorTexture::DecorTexture |
496 | * |
497 | @@ -322,7 +321,7 @@ |
498 | * for this pixmap |
499 | */ |
500 | |
501 | -DecorTexture::DecorTexture (Pixmap pixmap) : |
502 | +DecorTexture::DecorTexture (DecorPixmapInterface::Ptr pixmap) : |
503 | status (true), |
504 | refCount (1), |
505 | pixmap (pixmap), |
506 | @@ -332,7 +331,7 @@ |
507 | Window root; |
508 | int i; |
509 | |
510 | - if (!XGetGeometry (screen->dpy (), pixmap, &root, |
511 | + if (!XGetGeometry (screen->dpy (), pixmap->getPixmap (), &root, |
512 | &i, &i, &width, &height, &ui, &depth)) |
513 | { |
514 | status = false; |
515 | @@ -340,7 +339,7 @@ |
516 | } |
517 | |
518 | bindFailed = false; |
519 | - textures = GLTexture::bindPixmapToTexture (pixmap, width, height, depth); |
520 | + textures = GLTexture::bindPixmapToTexture (pixmap->getPixmap (), width, height, depth); |
521 | if (textures.size () != 1) |
522 | { |
523 | bindFailed = true; |
524 | @@ -351,7 +350,7 @@ |
525 | if (!DecorScreen::get (screen)->optionGetMipmap ()) |
526 | textures[0]->setMipmap (false); |
527 | |
528 | - damage = XDamageCreate (screen->dpy (), pixmap, |
529 | + damage = XDamageCreate (screen->dpy (), pixmap->getPixmap (), |
530 | XDamageReportRawRectangles); |
531 | } |
532 | |
533 | @@ -386,13 +385,16 @@ |
534 | return NULL; |
535 | |
536 | foreach (DecorTexture *t, textures) |
537 | - if (t->pixmap == pixmap) |
538 | + if (t->pixmap->getPixmap () == pixmap) |
539 | { |
540 | t->refCount++; |
541 | return t; |
542 | } |
543 | |
544 | - DecorTexture *texture = new DecorTexture (pixmap); |
545 | + X11PixmapDeletor::Ptr dl = boost::make_shared <X11PixmapDeletor> (screen->dpy ()); |
546 | + DecorPixmap::Ptr pm = boost::make_shared <DecorPixmap> (pixmap, dl); |
547 | + |
548 | + DecorTexture *texture = new DecorTexture (boost::shared_static_cast <DecorPixmapInterface> (pm)); |
549 | |
550 | if (!texture->status) |
551 | { |
552 | @@ -528,7 +530,8 @@ |
553 | long *prop, |
554 | unsigned int size, |
555 | unsigned int type, |
556 | - unsigned int nOffset) |
557 | + unsigned int nOffset, |
558 | + DecorPixmapRequestorInterface *requestor) |
559 | { |
560 | unsigned int frameType, frameState, frameActions; |
561 | Pixmap pixmap = None; |
562 | @@ -576,7 +579,7 @@ |
563 | throw std::exception (); |
564 | } |
565 | |
566 | - return Decoration::Ptr (new Decoration (type, border, input, maxBorder, maxInput, frameType, frameState, frameActions, minWidth, minHeight, pixmap, quad, nQuad)); |
567 | + return Decoration::Ptr (new Decoration (type, border, input, maxBorder, maxInput, frameType, frameState, frameActions, minWidth, minHeight, pixmap, quad, nQuad, id, requestor)); |
568 | } |
569 | |
570 | Decoration::Decoration (int type, |
571 | @@ -591,7 +594,9 @@ |
572 | unsigned int minHeight, |
573 | Pixmap pixmap, |
574 | const boost::shared_array <decor_quad_t> &quad, |
575 | - unsigned int nQuad) : |
576 | + unsigned int nQuad, |
577 | + Window owner, |
578 | + DecorPixmapRequestorInterface *requestor) : |
579 | texture (DecorScreen::get (screen)->getTexture (pixmap)), |
580 | border (border.left, border.right, border.top, border.bottom), |
581 | input (input.left, input.right, input.top, input.bottom), |
582 | @@ -604,7 +609,9 @@ |
583 | frameActions (frameActions), |
584 | quad (quad), |
585 | nQuad (nQuad), |
586 | - type (type) |
587 | + type (type), |
588 | + updateState (0), |
589 | + mPixmapReceiver (requestor, this) |
590 | { |
591 | int left, right, top, bottom; |
592 | int x1, y1, x2, y2; |
593 | @@ -665,6 +672,30 @@ |
594 | DecorScreen::get (screen)->releaseTexture (texture); |
595 | } |
596 | |
597 | +DecorPixmapReceiverInterface & |
598 | +Decoration::receiverInterface () |
599 | +{ |
600 | + return mPixmapReceiver; |
601 | +} |
602 | + |
603 | +unsigned int |
604 | +Decoration::getFrameType () const |
605 | +{ |
606 | + return frameType; |
607 | +} |
608 | + |
609 | +unsigned int |
610 | +Decoration::getFrameState () const |
611 | +{ |
612 | + return frameState; |
613 | +} |
614 | + |
615 | +unsigned int |
616 | +Decoration::getFrameActions () const |
617 | +{ |
618 | + return frameActions; |
619 | +} |
620 | + |
621 | /* |
622 | * DecorationList is a class which allows multiple decorations |
623 | * to be stored in a list and read from a window property, which |
624 | @@ -700,7 +731,8 @@ |
625 | |
626 | bool |
627 | DecorationList::updateDecoration (Window id, |
628 | - Atom decorAtom) |
629 | + Atom decorAtom, |
630 | + DecorPixmapRequestorInterface *requestor) |
631 | { |
632 | unsigned long n, nleft; |
633 | unsigned char *data; |
634 | @@ -709,6 +741,12 @@ |
635 | int result, format; |
636 | unsigned int type; |
637 | |
638 | + /* Dispatch any new updates */ |
639 | + foreach (const Decoration::Ptr &d, mList) |
640 | + { |
641 | + d->mPixmapReceiver.update (); |
642 | + } |
643 | + |
644 | result = XGetWindowProperty (screen->dpy (), id, |
645 | decorAtom, 0L, |
646 | PROP_HEADER_SIZE + 6 * (BASE_PROP_SIZE + |
647 | @@ -778,7 +816,9 @@ |
648 | maxBorder.top = d->maxBorder.top; |
649 | maxBorder.bottom = d->maxBorder.bottom; |
650 | |
651 | - int num = decor_match_pixmap (prop, n, &d->texture->pixmap, &input, &border, &maxInput, &maxBorder, |
652 | + Pixmap pm = d->texture->pixmap->getPixmap (); |
653 | + |
654 | + int num = decor_match_pixmap (prop, n, &pm, &input, &border, &maxInput, &maxBorder, |
655 | d->minWidth, d->minHeight, d->frameType, d->frameState, d->frameActions, |
656 | d->quad.get (), d->nQuad); |
657 | if (num != -1) |
658 | @@ -796,7 +836,7 @@ |
659 | try |
660 | { |
661 | std::list <Decoration::Ptr>::iterator it = mList.begin (); |
662 | - Decoration::Ptr d = Decoration::create (id, prop, n, type, i); |
663 | + Decoration::Ptr d = Decoration::create (id, prop, n, type, i, requestor); |
664 | |
665 | /* Try to replace an existing decoration */ |
666 | for (; it != mList.end (); it++) |
667 | @@ -881,7 +921,7 @@ |
668 | { |
669 | bindFailed = false; |
670 | |
671 | - decor.updateDecoration (window->id (), dScreen->winDecorAtom); |
672 | + decor.updateDecoration (window->id (), dScreen->winDecorAtom, &mRequestor); |
673 | if (bindFailed) |
674 | pixmapFailed = true; |
675 | else |
676 | @@ -1250,6 +1290,22 @@ |
677 | return (decorActions == 0); |
678 | } |
679 | |
680 | +DecorationInterface::Ptr |
681 | +DecorationList::findMatchingDecoration (unsigned int frameType, |
682 | + unsigned int frameState, |
683 | + unsigned int frameActions) |
684 | +{ |
685 | + foreach (const Decoration::Ptr &d, mList) |
686 | + { |
687 | + if (d->frameType == frameType && |
688 | + d->frameState == frameState && |
689 | + d->frameActions == frameActions) |
690 | + return boost::shared_static_cast <DecorationInterface> (d); |
691 | + } |
692 | + |
693 | + return DecorationInterface::Ptr (); |
694 | +} |
695 | + |
696 | /* |
697 | * DecorationList::findMatchingDecoration |
698 | * |
699 | @@ -2074,7 +2130,7 @@ |
700 | { |
701 | for (i = 0; i < DECOR_NUM; i++) |
702 | { |
703 | - decor[i].updateDecoration (screen->root (), decorAtom[i]); |
704 | + decor[i].updateDecoration (screen->root (), decorAtom[i], &mRequestor); |
705 | } |
706 | } |
707 | else |
708 | @@ -2286,6 +2342,7 @@ |
709 | isSwitcher = false; |
710 | } |
711 | |
712 | + |
713 | /* |
714 | * DecorScreen::handleEvent |
715 | * |
716 | @@ -2320,6 +2377,18 @@ |
717 | if (w) |
718 | DecorWindow::get (w)->update (true); |
719 | } |
720 | + /* A decoration is pending creation, allow it to be created */ |
721 | + if (event->xclient.message_type == decorPendingAtom) |
722 | + { |
723 | + CompWindow *w = screen->findWindow (event->xclient.window); |
724 | + |
725 | + if (w) |
726 | + { |
727 | + DecorWindow *dw = DecorWindow::get (w); |
728 | + |
729 | + dw->mRequestor.handlePending (event->xclient.data.l); |
730 | + } |
731 | + } |
732 | default: |
733 | /* Check for damage events. If the output or input window |
734 | * or a texture is updated then damage output extents. |
735 | @@ -2334,7 +2403,7 @@ |
736 | |
737 | foreach (DecorTexture *t, textures) |
738 | { |
739 | - if (t->pixmap == de->drawable) |
740 | + if (t->pixmap->getPixmap () == de->drawable) |
741 | { |
742 | foreach (CompWindow *w, screen->windows ()) |
743 | { |
744 | @@ -2394,7 +2463,6 @@ |
745 | DECOR_WINDOW (w); |
746 | |
747 | dw->updateDecoration (); |
748 | - |
749 | dw->update (true); |
750 | } |
751 | } |
752 | @@ -2427,7 +2495,8 @@ |
753 | if (event->xproperty.atom == decorAtom[i]) |
754 | { |
755 | decor[i].updateDecoration (screen->root (), |
756 | - decorAtom[i]); |
757 | + decorAtom[i], |
758 | + &mRequestor); |
759 | |
760 | foreach (CompWindow *w, screen->windows ()) |
761 | DecorWindow::get (w)->update (true); |
762 | @@ -2944,8 +3013,11 @@ |
763 | 0, |
764 | None, |
765 | boost::shared_array <decor_quad_t> (NULL), |
766 | - 0)), |
767 | - mMenusClipGroup (CompMatch ("type=Dock | type=DropdownMenu | type=PopupMenu")) |
768 | + 0, |
769 | + screen->root (), |
770 | + NULL)), |
771 | + mMenusClipGroup (CompMatch ("type=Dock | type=DropdownMenu | type=PopupMenu")), |
772 | + mRequestor (screen->dpy (), screen->root (), &(decor[DECOR_ACTIVE])) |
773 | { |
774 | supportingDmCheckAtom = |
775 | XInternAtom (s->dpy (), DECOR_SUPPORTING_DM_CHECK_ATOM_NAME, 0); |
776 | @@ -2967,6 +3039,10 @@ |
777 | XInternAtom (s->dpy (), DECOR_TYPE_WINDOW_ATOM_NAME, 0); |
778 | decorSwitchWindowAtom = |
779 | XInternAtom (s->dpy (), DECOR_SWITCH_WINDOW_ATOM_NAME, 0); |
780 | + decorPendingAtom = |
781 | + XInternAtom (s->dpy (), "_COMPIZ_DECOR_PENDING", 0); |
782 | + decorRequestAtom = |
783 | + XInternAtom (s->dpy (), "_COMPIZ_DECOR_REQUEST", 0); |
784 | requestFrameExtentsAtom = |
785 | XInternAtom (s->dpy (), "_NET_REQUEST_FRAME_EXTENTS", 0); |
786 | shadowColorAtom = |
787 | @@ -3023,7 +3099,8 @@ |
788 | frameExtentsRequested (false), |
789 | mClipGroup (NULL), |
790 | mOutputRegion (window->outputRect ()), |
791 | - mInputRegion (window->inputRect ()) |
792 | + mInputRegion (window->inputRect ()), |
793 | + mRequestor (screen->dpy (), w->id (), &decor) |
794 | { |
795 | WindowInterface::setHandler (window); |
796 | |
797 | |
798 | === modified file 'plugins/decor/src/decor.h' |
799 | --- plugins/decor/src/decor.h 2012-05-09 22:31:15 +0000 |
800 | +++ plugins/decor/src/decor.h 2012-05-15 07:20:22 +0000 |
801 | @@ -25,6 +25,7 @@ |
802 | |
803 | #include <boost/shared_ptr.hpp> |
804 | #include <boost/shared_array.hpp> |
805 | +#include <boost/make_shared.hpp> |
806 | #include <core/window.h> |
807 | #include <core/pluginclasshandler.h> |
808 | |
809 | @@ -34,6 +35,7 @@ |
810 | #include <core/windowextents.h> |
811 | |
812 | #include <clip-groups.h> |
813 | +#include <pixmap-requests.h> |
814 | |
815 | #include "decor_options.h" |
816 | |
817 | @@ -76,30 +78,36 @@ |
818 | class DecorTexture { |
819 | |
820 | public: |
821 | - DecorTexture (Pixmap pixmap); |
822 | + DecorTexture (DecorPixmapInterface::Ptr pixmap); |
823 | ~DecorTexture (); |
824 | |
825 | public: |
826 | bool status; |
827 | int refCount; |
828 | - Pixmap pixmap; |
829 | + DecorPixmapInterface::Ptr pixmap; |
830 | Damage damage; |
831 | GLTexture::List textures; |
832 | }; |
833 | |
834 | class DecorWindow; |
835 | |
836 | -class Decoration { |
837 | +class Decoration : |
838 | + public DecorationInterface |
839 | +{ |
840 | |
841 | public: |
842 | |
843 | typedef boost::shared_ptr <Decoration> Ptr; |
844 | |
845 | + static const unsigned int UpdateRequested = 1 << 0; |
846 | + static const unsigned int UpdatesPending = 1 << 1; |
847 | + |
848 | static Decoration::Ptr create (Window id, |
849 | long *prop, |
850 | unsigned int size, |
851 | unsigned int type, |
852 | - unsigned int nOffset); |
853 | + unsigned int nOffset, |
854 | + DecorPixmapRequestorInterface *requestor); |
855 | |
856 | Decoration (int type, |
857 | const decor_extents_t &border, |
858 | @@ -113,10 +121,18 @@ |
859 | unsigned int minHeight, |
860 | Pixmap pixmap, |
861 | const boost::shared_array <decor_quad_t> &quad, |
862 | - unsigned int nQuad); |
863 | + unsigned int nQuad, |
864 | + Window owner, |
865 | + DecorPixmapRequestorInterface *); |
866 | |
867 | ~Decoration (); |
868 | |
869 | + DecorPixmapReceiverInterface & receiverInterface (); |
870 | + |
871 | + unsigned int getFrameType () const; |
872 | + unsigned int getFrameState () const; |
873 | + unsigned int getFrameActions () const; |
874 | + |
875 | public: |
876 | int refCount; |
877 | DecorTexture *texture; |
878 | @@ -133,12 +149,19 @@ |
879 | boost::shared_array <decor_quad_t> quad; |
880 | int nQuad; |
881 | int type; |
882 | + |
883 | + unsigned int updateState; |
884 | + X11DecorPixmapReceiver mPixmapReceiver; |
885 | }; |
886 | |
887 | -class DecorationList |
888 | +class DecorationList : |
889 | + public DecorationListFindMatchingInterface |
890 | { |
891 | public: |
892 | - bool updateDecoration (Window id, Atom decorAtom); |
893 | + bool updateDecoration (Window id, Atom decorAtom, DecorPixmapRequestorInterface *requestor); |
894 | + DecorationInterface::Ptr findMatchingDecoration(unsigned int frameType, |
895 | + unsigned int frameState, |
896 | + unsigned int frameActions); |
897 | const Decoration::Ptr & findMatchingDecoration (CompWindow *w, bool sizeCheck); |
898 | void clear () |
899 | { |
900 | @@ -215,6 +238,8 @@ |
901 | Atom shadowColorAtom; |
902 | Atom shadowInfoAtom; |
903 | Atom decorSwitchWindowAtom; |
904 | + Atom decorPendingAtom; |
905 | + Atom decorRequestAtom; |
906 | |
907 | Window dmWin; |
908 | int dmSupports; |
909 | @@ -229,6 +254,7 @@ |
910 | CompTimer decoratorStart; |
911 | |
912 | MatchedDecorClipGroup mMenusClipGroup; |
913 | + X11DecorPixmapRequestor mRequestor; |
914 | }; |
915 | |
916 | class DecorWindow : |
917 | @@ -334,6 +360,8 @@ |
918 | DecorClipGroupInterface *mClipGroup; |
919 | CompRegion mOutputRegion; |
920 | CompRegion mInputRegion; |
921 | + |
922 | + X11DecorPixmapRequestor mRequestor; |
923 | }; |
924 | |
925 | class DecorPluginVTable : |
926 | |
927 | === added directory 'plugins/decor/src/pixmap-requests' |
928 | === added file 'plugins/decor/src/pixmap-requests/CMakeLists.txt' |
929 | --- plugins/decor/src/pixmap-requests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
930 | +++ plugins/decor/src/pixmap-requests/CMakeLists.txt 2012-05-15 07:20:22 +0000 |
931 | @@ -0,0 +1,62 @@ |
932 | +pkg_check_modules ( |
933 | + GLIBMM |
934 | + REQUIRED |
935 | + glibmm-2.4 glib-2.0 |
936 | +) |
937 | + |
938 | +INCLUDE_DIRECTORIES ( |
939 | + ${CMAKE_CURRENT_SOURCE_DIR}/include |
940 | + ${CMAKE_CURRENT_SOURCE_DIR}/src |
941 | + |
942 | + ${compiz_SOURCE_DIR}/src/point/include |
943 | + ${compiz_SOURCE_DIR}/src/rect/include |
944 | + ${compiz_SOURCE_DIR}/src/window/geometry/include |
945 | + ${compiz_SOURCE_DIR}/src/window/geometry-saver/include |
946 | + ${compiz_SOURCE_DIR}/src/window/extents/include |
947 | + ${compiz_SOURCE_DIR}/include |
948 | + |
949 | + ${Boost_INCLUDE_DIRS} |
950 | + |
951 | + ${GLIBMM_INCLUDE_DIRS} |
952 | +) |
953 | + |
954 | +LINK_DIRECTORIES (${GLIBMM_LIBRARY_DIRS}) |
955 | + |
956 | +SET ( |
957 | + PUBLIC_HEADERS |
958 | +) |
959 | + |
960 | +SET ( |
961 | + PRIVATE_HEADERS |
962 | + ${CMAKE_CURRENT_SOURCE_DIR}/include/pixmap-requests.h |
963 | +) |
964 | + |
965 | +SET( |
966 | + SRCS |
967 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/pixmap-requests.cpp |
968 | +) |
969 | + |
970 | +ADD_LIBRARY( |
971 | + compiz_decor_pixmap_requests STATIC |
972 | + |
973 | + ${SRCS} |
974 | + |
975 | + ${PUBLIC_HEADERS} |
976 | + ${PRIVATE_HEADERS} |
977 | +) |
978 | + |
979 | +if (COMPIZ_BUILD_TESTING) |
980 | +ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests ) |
981 | +endif (COMPIZ_BUILD_TESTING) |
982 | + |
983 | +SET_TARGET_PROPERTIES( |
984 | + compiz_decor_pixmap_requests PROPERTIES |
985 | + PUBLIC_HEADER "${PUBLIC_HEADERS}" |
986 | +) |
987 | + |
988 | +TARGET_LINK_LIBRARIES( |
989 | + compiz_decor_pixmap_requests |
990 | + |
991 | + compiz_core |
992 | + ${GLIBMM_LIBRARIES} |
993 | +) |
994 | |
995 | === added directory 'plugins/decor/src/pixmap-requests/include' |
996 | === added file 'plugins/decor/src/pixmap-requests/include/pixmap-requests.h' |
997 | --- plugins/decor/src/pixmap-requests/include/pixmap-requests.h 1970-01-01 00:00:00 +0000 |
998 | +++ plugins/decor/src/pixmap-requests/include/pixmap-requests.h 2012-05-15 07:20:22 +0000 |
999 | @@ -0,0 +1,188 @@ |
1000 | +/* |
1001 | + * Copyright © 2005 Novell, Inc. |
1002 | + * |
1003 | + * Permission to use, copy, modify, distribute, and sell this software |
1004 | + * and its documentation for any purpose is hereby granted without |
1005 | + * fee, provided that the above copyright notice appear in all copies |
1006 | + * and that both that copyright notice and this permission notice |
1007 | + * appear in supporting documentation, and that the name of |
1008 | + * Novell, Inc. not be used in advertising or publicity pertaining to |
1009 | + * distribution of the software without specific, written prior permission. |
1010 | + * Novell, Inc. makes no representations about the suitability of this |
1011 | + * software for any purpose. It is provided "as is" without express or |
1012 | + * implied warranty. |
1013 | + * |
1014 | + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
1015 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
1016 | + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
1017 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
1018 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
1019 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
1020 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1021 | + * |
1022 | + * Author: David Reveman <davidr@novell.com> |
1023 | + */ |
1024 | + |
1025 | +#ifndef _COMPIZ_DECOR_PIXMAP_REQUESTS_H |
1026 | +#define _COMPIZ_DECOR_PIXMAP_REQUESTS_H |
1027 | + |
1028 | +#include <boost/shared_ptr.hpp> |
1029 | +#include <boost/shared_array.hpp> |
1030 | +#include <boost/make_shared.hpp> |
1031 | +#include <decoration.h> |
1032 | + |
1033 | +#include <X11/Xlib.h> |
1034 | + |
1035 | +class DecorPixmapInterface |
1036 | +{ |
1037 | + public: |
1038 | + |
1039 | + typedef boost::shared_ptr <DecorPixmapInterface> Ptr; |
1040 | + |
1041 | + virtual ~DecorPixmapInterface () {}; |
1042 | + |
1043 | + virtual Pixmap getPixmap () = 0; |
1044 | +}; |
1045 | + |
1046 | +class DecorPixmapReceiverInterface |
1047 | +{ |
1048 | + public: |
1049 | + |
1050 | + virtual ~DecorPixmapReceiverInterface () {} |
1051 | + |
1052 | + virtual void pending () = 0; |
1053 | + virtual void update () = 0; |
1054 | +}; |
1055 | + |
1056 | +/* So far, nothing particularly interesting here |
1057 | + * we just need a way to pass around pointers for |
1058 | + * testing */ |
1059 | +class DecorationInterface |
1060 | +{ |
1061 | + public: |
1062 | + |
1063 | + typedef boost::shared_ptr <DecorationInterface> Ptr; |
1064 | + |
1065 | + virtual ~DecorationInterface () {} |
1066 | + |
1067 | + virtual DecorPixmapReceiverInterface & receiverInterface () = 0; |
1068 | + virtual unsigned int getFrameType () const = 0; |
1069 | + virtual unsigned int getFrameState () const = 0; |
1070 | + virtual unsigned int getFrameActions () const = 0; |
1071 | +}; |
1072 | + |
1073 | +class DecorPixmapDeletionInterface |
1074 | +{ |
1075 | + public: |
1076 | + |
1077 | + typedef boost::shared_ptr <DecorPixmapDeletionInterface> Ptr; |
1078 | + |
1079 | + virtual ~DecorPixmapDeletionInterface () {} |
1080 | + |
1081 | + virtual int postDeletePixmap (Pixmap pixmap) = 0; |
1082 | +}; |
1083 | + |
1084 | +class X11PixmapDeletor : |
1085 | + public DecorPixmapDeletionInterface |
1086 | +{ |
1087 | + public: |
1088 | + |
1089 | + typedef boost::shared_ptr <X11PixmapDeletor> Ptr; |
1090 | + |
1091 | + X11PixmapDeletor (Display *dpy) : |
1092 | + mDisplay (dpy) |
1093 | + { |
1094 | + } |
1095 | + |
1096 | + int postDeletePixmap (Pixmap pixmap) { return decor_post_delete_pixmap (mDisplay, pixmap); } |
1097 | + |
1098 | + private: |
1099 | + |
1100 | + Display *mDisplay; |
1101 | +}; |
1102 | + |
1103 | +class DecorPixmap : |
1104 | + public DecorPixmapInterface |
1105 | +{ |
1106 | + public: |
1107 | + |
1108 | + typedef boost::shared_ptr <DecorPixmap> Ptr; |
1109 | + |
1110 | + DecorPixmap (Pixmap p, DecorPixmapDeletionInterface::Ptr deletor); |
1111 | + ~DecorPixmap (); |
1112 | + |
1113 | + Pixmap getPixmap (); |
1114 | + |
1115 | + private: |
1116 | + |
1117 | + Pixmap mPixmap; |
1118 | + DecorPixmapDeletionInterface::Ptr mDeletor; |
1119 | +}; |
1120 | + |
1121 | +class DecorPixmapRequestorInterface |
1122 | +{ |
1123 | + public: |
1124 | + |
1125 | + virtual ~DecorPixmapRequestorInterface () {} |
1126 | + |
1127 | + virtual int postGenerateRequest (unsigned int frameType, |
1128 | + unsigned int frameState, |
1129 | + unsigned int frameActions) = 0; |
1130 | + |
1131 | + virtual void handlePending (long *data) = 0; |
1132 | +}; |
1133 | + |
1134 | +class DecorationListFindMatchingInterface |
1135 | +{ |
1136 | + public: |
1137 | + |
1138 | + virtual ~DecorationListFindMatchingInterface () {} |
1139 | + |
1140 | + virtual DecorationInterface::Ptr findMatchingDecoration (unsigned int frameType, |
1141 | + unsigned int frameState, |
1142 | + unsigned int frameActions) = 0; |
1143 | +}; |
1144 | + |
1145 | +class X11DecorPixmapRequestor : |
1146 | + public DecorPixmapRequestorInterface |
1147 | +{ |
1148 | + public: |
1149 | + |
1150 | + X11DecorPixmapRequestor (Display *dpy, |
1151 | + Window xid, |
1152 | + DecorationListFindMatchingInterface *listFinder); |
1153 | + |
1154 | + int postGenerateRequest (unsigned int frameType, |
1155 | + unsigned int frameState, |
1156 | + unsigned int frameActions); |
1157 | + |
1158 | + void handlePending (long *data); |
1159 | + |
1160 | + private: |
1161 | + |
1162 | + Display *mDpy; |
1163 | + Window mWindow; |
1164 | + DecorationListFindMatchingInterface *mListFinder; |
1165 | +}; |
1166 | + |
1167 | +class X11DecorPixmapReceiver : |
1168 | + public DecorPixmapReceiverInterface |
1169 | +{ |
1170 | + public: |
1171 | + |
1172 | + static const unsigned int UpdateRequested = 1 << 0; |
1173 | + static const unsigned int UpdatesPending = 1 << 1; |
1174 | + |
1175 | + X11DecorPixmapReceiver (DecorPixmapRequestorInterface *, |
1176 | + DecorationInterface *decor); |
1177 | + |
1178 | + void pending (); |
1179 | + void update (); |
1180 | + private: |
1181 | + |
1182 | + unsigned int mUpdateState; |
1183 | + DecorPixmapRequestorInterface *mDecorPixmapRequestor; |
1184 | + DecorationInterface *mDecoration; |
1185 | +}; |
1186 | + |
1187 | +#endif |
1188 | |
1189 | === added directory 'plugins/decor/src/pixmap-requests/src' |
1190 | === added file 'plugins/decor/src/pixmap-requests/src/pixmap-requests.cpp' |
1191 | --- plugins/decor/src/pixmap-requests/src/pixmap-requests.cpp 1970-01-01 00:00:00 +0000 |
1192 | +++ plugins/decor/src/pixmap-requests/src/pixmap-requests.cpp 2012-05-15 07:20:22 +0000 |
1193 | @@ -0,0 +1,93 @@ |
1194 | +#include "pixmap-requests.h" |
1195 | +#include <boost/foreach.hpp> |
1196 | +#include <algorithm> |
1197 | + |
1198 | +#ifndef foreach |
1199 | +#define foreach BOOST_FOREACH |
1200 | +#endif |
1201 | + |
1202 | +DecorPixmap::DecorPixmap (Pixmap pixmap, DecorPixmapDeletionInterface::Ptr d) : |
1203 | + mPixmap (pixmap), |
1204 | + mDeletor (d) |
1205 | +{ |
1206 | +} |
1207 | + |
1208 | +DecorPixmap::~DecorPixmap () |
1209 | +{ |
1210 | + mDeletor->postDeletePixmap (mPixmap); |
1211 | +} |
1212 | + |
1213 | +Pixmap |
1214 | +DecorPixmap::getPixmap () |
1215 | +{ |
1216 | + return mPixmap; |
1217 | +} |
1218 | + |
1219 | +X11DecorPixmapReceiver::X11DecorPixmapReceiver (DecorPixmapRequestorInterface *requestor, |
1220 | + DecorationInterface *decor) : |
1221 | + mUpdateState (0), |
1222 | + mDecorPixmapRequestor (requestor), |
1223 | + mDecoration (decor) |
1224 | +{ |
1225 | +} |
1226 | + |
1227 | +void |
1228 | +X11DecorPixmapReceiver::pending () |
1229 | +{ |
1230 | + if (mUpdateState & X11DecorPixmapReceiver::UpdateRequested) |
1231 | + mUpdateState |= X11DecorPixmapReceiver::UpdatesPending; |
1232 | + else |
1233 | + { |
1234 | + mUpdateState |= X11DecorPixmapReceiver::UpdateRequested; |
1235 | + |
1236 | + mDecorPixmapRequestor->postGenerateRequest (mDecoration->getFrameType (), |
1237 | + mDecoration->getFrameState (), |
1238 | + mDecoration->getFrameActions ()); |
1239 | + } |
1240 | +} |
1241 | + |
1242 | +void X11DecorPixmapReceiver::update () |
1243 | +{ |
1244 | + if (mUpdateState & X11DecorPixmapReceiver::UpdatesPending) |
1245 | + mDecorPixmapRequestor->postGenerateRequest (mDecoration->getFrameType (), |
1246 | + mDecoration->getFrameState (), |
1247 | + mDecoration->getFrameActions ()); |
1248 | + |
1249 | + mUpdateState = 0; |
1250 | +} |
1251 | + |
1252 | +X11DecorPixmapRequestor::X11DecorPixmapRequestor (Display *dpy, |
1253 | + Window window, |
1254 | + DecorationListFindMatchingInterface *listFinder) : |
1255 | + mDpy (dpy), |
1256 | + mWindow (window), |
1257 | + mListFinder (listFinder) |
1258 | +{ |
1259 | +} |
1260 | + |
1261 | +int |
1262 | +X11DecorPixmapRequestor::postGenerateRequest (unsigned int frameType, |
1263 | + unsigned int frameState, |
1264 | + unsigned int frameActions) |
1265 | +{ |
1266 | + return decor_post_generate_request (mDpy, |
1267 | + mWindow, |
1268 | + frameType, |
1269 | + frameState, |
1270 | + frameActions); |
1271 | +} |
1272 | + |
1273 | +void |
1274 | +X11DecorPixmapRequestor::handlePending (long *data) |
1275 | +{ |
1276 | + DecorationInterface::Ptr d = mListFinder->findMatchingDecoration (static_cast <unsigned int> (data[0]), |
1277 | + static_cast <unsigned int> (data[1]), |
1278 | + static_cast <unsigned int> (data[2])); |
1279 | + |
1280 | + if (d) |
1281 | + d->receiverInterface ().pending (); |
1282 | + else |
1283 | + postGenerateRequest (static_cast <unsigned int> (data[0]), |
1284 | + static_cast <unsigned int> (data[1]), |
1285 | + static_cast <unsigned int> (data[2])); |
1286 | +} |
1287 | |
1288 | === added directory 'plugins/decor/src/pixmap-requests/tests' |
1289 | === added file 'plugins/decor/src/pixmap-requests/tests/CMakeLists.txt' |
1290 | --- plugins/decor/src/pixmap-requests/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1291 | +++ plugins/decor/src/pixmap-requests/tests/CMakeLists.txt 2012-05-15 07:20:22 +0000 |
1292 | @@ -0,0 +1,15 @@ |
1293 | +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
1294 | + |
1295 | +add_executable (compiz_test_decor_pixmap_requests |
1296 | + ${CMAKE_CURRENT_SOURCE_DIR}/pixmap-requests/src/test-decor-pixmap-requests.cpp) |
1297 | + |
1298 | +target_link_libraries (compiz_test_decor_pixmap_requests |
1299 | + compiz_decor_pixmap_requests |
1300 | + decoration |
1301 | + ${GTEST_BOTH_LIBRARIES} |
1302 | + ${GMOCK_LIBRARY} |
1303 | + ${GMOCK_MAIN_LIBRARY} |
1304 | + ${CMAKE_THREAD_LIBS_INIT} # Link in pthread. |
1305 | + ) |
1306 | + |
1307 | +gtest_add_tests (compiz_test_decor_pixmap_requests "" ${CMAKE_CURRENT_SOURCE_DIR}/pixmap-requests/src/test-decor-pixmap-requests.cpp) |
1308 | |
1309 | === added directory 'plugins/decor/src/pixmap-requests/tests/pixmap-requests' |
1310 | === added directory 'plugins/decor/src/pixmap-requests/tests/pixmap-requests/src' |
1311 | === added file 'plugins/decor/src/pixmap-requests/tests/pixmap-requests/src/test-decor-pixmap-requests.cpp' |
1312 | --- plugins/decor/src/pixmap-requests/tests/pixmap-requests/src/test-decor-pixmap-requests.cpp 1970-01-01 00:00:00 +0000 |
1313 | +++ plugins/decor/src/pixmap-requests/tests/pixmap-requests/src/test-decor-pixmap-requests.cpp 2012-05-15 07:20:22 +0000 |
1314 | @@ -0,0 +1,160 @@ |
1315 | +/* |
1316 | + * Copyright © 2012 Canonical Ltd. |
1317 | + * |
1318 | + * Permission to use, copy, modify, distribute, and sell this software |
1319 | + * and its documentation for any purpose is hereby granted without |
1320 | + * fee, provided that the above copyright notice appear in all copies |
1321 | + * and that both that copyright notice and this permission notice |
1322 | + * appear in supporting documentation, and that the name of |
1323 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
1324 | + * distribution of the software without specific, written prior permission. |
1325 | + * Canonical Ltd. makes no representations about the suitability of this |
1326 | + * software for any purpose. It is provided "as is" without express or |
1327 | + * implied warranty. |
1328 | + * |
1329 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
1330 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
1331 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
1332 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
1333 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
1334 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
1335 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1336 | + * |
1337 | + * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com> |
1338 | + */ |
1339 | + |
1340 | +#include <gtest/gtest.h> |
1341 | +#include <gmock/gmock.h> |
1342 | +#include <iostream> |
1343 | +#include "pixmap-requests.h" |
1344 | + |
1345 | +using ::testing::Return; |
1346 | + |
1347 | +class DecorPixmapRequestsTest : |
1348 | + public ::testing::Test |
1349 | +{ |
1350 | +}; |
1351 | + |
1352 | +class MockDecorPixmapDeletor : |
1353 | + public DecorPixmapDeletionInterface |
1354 | +{ |
1355 | + public: |
1356 | + |
1357 | + MOCK_METHOD1 (postDeletePixmap, int (Pixmap p)); |
1358 | +}; |
1359 | + |
1360 | +class MockDecorPixmapReceiver : |
1361 | + public DecorPixmapReceiverInterface |
1362 | +{ |
1363 | + public: |
1364 | + |
1365 | + MOCK_METHOD0 (pending, void ()); |
1366 | + MOCK_METHOD0 (update, void ()); |
1367 | +}; |
1368 | + |
1369 | +class MockDecoration : |
1370 | + public DecorationInterface |
1371 | +{ |
1372 | + public: |
1373 | + |
1374 | + MOCK_METHOD0 (receiverInterface, DecorPixmapReceiverInterface & ()); |
1375 | + MOCK_CONST_METHOD0 (getFrameType, unsigned int ()); |
1376 | + MOCK_CONST_METHOD0 (getFrameState, unsigned int ()); |
1377 | + MOCK_CONST_METHOD0 (getFrameActions, unsigned int ()); |
1378 | +}; |
1379 | + |
1380 | +class MockDecorationListFindMatching : |
1381 | + public DecorationListFindMatchingInterface |
1382 | +{ |
1383 | + public: |
1384 | + |
1385 | + MOCK_METHOD3 (findMatchingDecoration, DecorationInterface::Ptr (unsigned int, unsigned int, unsigned int)); |
1386 | +}; |
1387 | + |
1388 | +class MockDecorPixmapRequestor : |
1389 | + public DecorPixmapRequestorInterface |
1390 | +{ |
1391 | + public: |
1392 | + |
1393 | + MOCK_METHOD3 (postGenerateRequest, int (unsigned int, unsigned int, unsigned int)); |
1394 | + MOCK_METHOD1 (handlePending, void (long *)); |
1395 | +}; |
1396 | + |
1397 | +TEST(DecorPixmapRequestsTest, TestDestroyPixmapDeletes) |
1398 | +{ |
1399 | + boost::shared_ptr <MockDecorPixmapDeletor> mockDeletor = boost::make_shared <MockDecorPixmapDeletor> (); |
1400 | + DecorPixmap pm (1, boost::shared_static_cast<DecorPixmapDeletionInterface> (mockDeletor)); |
1401 | + |
1402 | + EXPECT_CALL (*(mockDeletor.get ()), postDeletePixmap (1)).WillOnce (Return (1)); |
1403 | +} |
1404 | + |
1405 | +TEST(DecorPixmapRequestsTest, TestPendingGeneratesRequest) |
1406 | +{ |
1407 | + MockDecorPixmapRequestor mockRequestor; |
1408 | + MockDecoration mockDecoration; |
1409 | + X11DecorPixmapReceiver receiver (&mockRequestor, &mockDecoration); |
1410 | + |
1411 | + EXPECT_CALL (mockDecoration, getFrameActions ()).WillOnce (Return (3)); |
1412 | + EXPECT_CALL (mockDecoration, getFrameState ()).WillOnce (Return (2)); |
1413 | + EXPECT_CALL (mockDecoration, getFrameType ()).WillOnce (Return (1)); |
1414 | + |
1415 | + EXPECT_CALL (mockRequestor, postGenerateRequest (1, 2, 3)); |
1416 | + |
1417 | + receiver.pending (); |
1418 | +} |
1419 | + |
1420 | +TEST(DecorPixmapRequestsTest, TestPendingGeneratesOnlyOneRequest) |
1421 | +{ |
1422 | + MockDecorPixmapRequestor mockRequestor; |
1423 | + MockDecoration mockDecoration; |
1424 | + X11DecorPixmapReceiver receiver (&mockRequestor, &mockDecoration); |
1425 | + |
1426 | + EXPECT_CALL (mockDecoration, getFrameActions ()).WillOnce (Return (3)); |
1427 | + EXPECT_CALL (mockDecoration, getFrameState ()).WillOnce (Return (2)); |
1428 | + EXPECT_CALL (mockDecoration, getFrameType ()).WillOnce (Return (1)); |
1429 | + |
1430 | + EXPECT_CALL (mockRequestor, postGenerateRequest (1, 2, 3)); |
1431 | + |
1432 | + receiver.pending (); |
1433 | + receiver.pending (); |
1434 | +} |
1435 | + |
1436 | +TEST(DecorPixmapRequestsTest, TestUpdateGeneratesRequestIfNewOnePending) |
1437 | +{ |
1438 | + MockDecorPixmapRequestor mockRequestor; |
1439 | + MockDecoration mockDecoration; |
1440 | + X11DecorPixmapReceiver receiver (&mockRequestor, &mockDecoration); |
1441 | + |
1442 | + EXPECT_CALL (mockDecoration, getFrameActions ()).WillOnce (Return (3)); |
1443 | + EXPECT_CALL (mockDecoration, getFrameState ()).WillOnce (Return (2)); |
1444 | + EXPECT_CALL (mockDecoration, getFrameType ()).WillOnce (Return (1)); |
1445 | + |
1446 | + EXPECT_CALL (mockRequestor, postGenerateRequest (1, 2, 3)); |
1447 | + |
1448 | + receiver.pending (); |
1449 | + receiver.pending (); |
1450 | + |
1451 | + EXPECT_CALL (mockDecoration, getFrameActions ()).WillOnce (Return (3)); |
1452 | + EXPECT_CALL (mockDecoration, getFrameState ()).WillOnce (Return (2)); |
1453 | + EXPECT_CALL (mockDecoration, getFrameType ()).WillOnce (Return (1)); |
1454 | + |
1455 | + EXPECT_CALL (mockRequestor, postGenerateRequest (1, 2, 3)); |
1456 | + |
1457 | + receiver.update (); |
1458 | +} |
1459 | + |
1460 | +TEST(DecorPixmapRequestsTest, TestUpdateGeneratesNoRequestIfNoNewOnePending) |
1461 | +{ |
1462 | + MockDecorPixmapRequestor mockRequestor; |
1463 | + MockDecoration mockDecoration; |
1464 | + X11DecorPixmapReceiver receiver (&mockRequestor, &mockDecoration); |
1465 | + |
1466 | + EXPECT_CALL (mockDecoration, getFrameActions ()).WillOnce (Return (3)); |
1467 | + EXPECT_CALL (mockDecoration, getFrameState ()).WillOnce (Return (2)); |
1468 | + EXPECT_CALL (mockDecoration, getFrameType ()).WillOnce (Return (1)); |
1469 | + |
1470 | + EXPECT_CALL (mockRequestor, postGenerateRequest (1, 2, 3)); |
1471 | + |
1472 | + receiver.pending (); |
1473 | + receiver.update (); |
1474 | +} |
Looks sensible - but so did the version that caused problems.