Merge lp:~sil2100/compiz-core/cherry_rev3137 into lp:compiz-core

Proposed by Łukasz Zemczak
Status: Merged
Merged at revision: 3103
Proposed branch: lp:~sil2100/compiz-core/cherry_rev3137
Merge into: lp:compiz-core
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:~sil2100/compiz-core/cherry_rev3137
Reviewer Review Type Date Requested Status
Daniel van Vugt Approve
Review via email: mp+110572@code.launchpad.net

Commit message

Cherry-picked from compiz trunk (rev 3137):
Add synchronization primitives to the decoration protocol so that there isn't a race where we bind a texture that's being freed. (LP: #454218) (LP: #929989)

Description of the change

Cherry picked from 0.9.8 branch:

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_window_decoration_size made semi-private, users should use request_update_window_decoration_size instead, which prepares for a pixmap update and sends a message to the decorated process that a new pixmap is waiting.
 * 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_delete_pixmap : tells the decorator that a pixmap is no longer in use by the decorated process and can be deleted by the server

I also did some necessary refactoring so we could get this under test, namely:

DecorPixmap class (implements DecorPixmapInterface): a simple RAII class which ensures that a DecorPixmapDeletionInterface is invoked to delete the server side pixmap when the DecorPixmap class is destructed

X11DecorPixmapReceiver class (implements DecorPixmapReceiverInterface): a per-decoration owned class which tracks the update state of the pixmap owned by the decoration from the decorator, calls through to appropriate methods on a DecorPixmapRequestorInterface to request new pixmaps (ensuring that chattyness is reduced to when a) the decorator tells us that a new pixmap is ready and b) when a new pixmap was already pending and we need to fetch the newest one)

X11DecorPixmapRequestor class (implements DecorPixmapRequestorInterface): a per-window owned class which handles dispatch to the decorator (eg decor_post_pending) and requests from the decorator in _COMPIZ_DECOR_PENDING messages to communicate when decorations should be redrawn at new sizes

X11PixmapDeletor class (implements DecorPixmapDeletionInterface): a per-pixmap class which sends decor_post_delete_pixmap to the decorator when a pixmap is no longer in use by the decor plugin

DecorationListFindMatchingInterface: an interface implemented by DecorationList to find a decoration matching a specified criteria

DecorationInterface: an interface implemented by Decoration to get the receiver and properties about that decoration.

Tests included (Google Mock)

Resubmitted to cover a potential race condition in LP#996901

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I assume the ABI changes here don't affect Unity builds?... Better to ask a silly question now than later :)

Revision history for this message
Łukasz Zemczak (sil2100) wrote :

Good question, it seems they actually might. So hm, this cherry-pick might not be entirely safe. Daniel - could you somehow mark bug-fixes in bug reports which break the ABI? This would make picking changes for SRUs much easier.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Yes, we're meant to update abiversion.h so it should be easy to tell. But people often forget :(

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

It works and the bugs appear fixed.

I can't run the test cases for some reason, but that's not caused by this proposal in particular. See bug 1014957.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'gtk/window-decorator/decorator.c'
2--- gtk/window-decorator/decorator.c 2012-03-30 07:01:48 +0000
3+++ gtk/window-decorator/decorator.c 2012-06-15 17:09:21 +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-03-30 07:01:48 +0000
145+++ gtk/window-decorator/events.c 2012-06-15 17:09:21 +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-03-30 07:01:48 +0000
176+++ gtk/window-decorator/gtk-window-decorator.c 2012-06-15 17:09:21 +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-03-30 07:01:48 +0000
217+++ gtk/window-decorator/gtk-window-decorator.h 2012-06-15 17:09:21 +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-03-30 07:01:48 +0000
253+++ gtk/window-decorator/wnck.c 2012-06-15 17:09:21 +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-02-09 07:48:57 +0000
344+++ include/decoration.h 2012-06-15 17:09:21 +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-02-27 06:43:04 +0000
373+++ libdecoration/decoration.c 2012-06-15 17:09:21 +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-03-30 14:29:18 +0000
470+++ plugins/decor/CMakeLists.txt 2012-06-15 17:09:21 +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-04-23 05:50:23 +0000
488+++ plugins/decor/src/decor.cpp 2012-06-15 17:09:21 +0000
489@@ -303,7 +303,6 @@
490 }
491
492 static bool bindFailed;
493-
494 /*
495 * DecorTexture::DecorTexture
496 *
497@@ -314,7 +313,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@@ -324,7 +323,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@@ -332,7 +331,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@@ -343,7 +342,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@@ -378,13 +377,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@@ -520,7 +522,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@@ -568,7 +571,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@@ -583,7 +586,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@@ -596,7 +601,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@@ -657,6 +664,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@@ -692,7 +723,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@@ -701,6 +733,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@@ -770,7 +808,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@@ -788,7 +828,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@@ -873,7 +913,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@@ -1230,6 +1270,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@@ -2053,7 +2109,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@@ -2261,6 +2317,7 @@
709 isSwitcher = false;
710 }
711
712+
713 /*
714 * DecorScreen::handleEvent
715 *
716@@ -2295,6 +2352,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@@ -2309,7 +2378,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@@ -2368,7 +2437,6 @@
745 {
746 DECOR_WINDOW (w);
747 dw->updateDecoration ();
748-
749 dw->update (true);
750 }
751 }
752@@ -2401,7 +2469,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@@ -2935,8 +3004,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@@ -2958,6 +3030,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@@ -3013,7 +3089,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-04-23 05:50:23 +0000
800+++ plugins/decor/src/decor.h 2012-06-15 17:09:21 +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@@ -335,6 +361,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-06-15 17:09:21 +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-06-15 17:09:21 +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-06-15 17:09:21 +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-06-15 17:09:21 +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-06-15 17:09:21 +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+}

Subscribers

People subscribed via source and target branches