Merge lp:~smspillaz/compiz-core/compiz-core.decor_synchronization into lp:compiz-core/0.9.8

Proposed by Sam Spilsbury
Status: Merged
Approved by: Sam Spilsbury
Approved revision: 3024
Merged at revision: 3131
Proposed branch: lp:~smspillaz/compiz-core/compiz-core.decor_synchronization
Merge into: lp:compiz-core/0.9.8
Diff against target: 1457 lines (+849/-66)
15 files modified
gtk/window-decorator/decorator.c (+48/-24)
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_synchronization
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Resubmitting
Alan Griffiths Pending
Review via email: mp+103444@code.launchpad.net

This proposal supersedes a proposal from 2012-04-25.

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_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)

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

I haven't reviewed this, but please fix and/or resubmit to resolve the conflicts.

review: Needs Resubmitting
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

For starters, there are non-trivial conflicts that need fixing.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I've linked the two related bugs that I think this branch is designed to fix. It seems to.

Regression: Active windows often get inactive title bar decorations. For example, if I open a new terminal (Ctrl+Shift+N) then the new window gets activated and focused (and is usable), but keeps inactive decorations. There's not a single window on my screen with active window decorations now.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

On Tue, 24 Apr 2012, Daniel van Vugt wrote:

> Review: Needs Fixing
>
> I've linked the two related bugs that I think this branch is designed to fix. It seems to.
>
> Regression: Active windows often get inactive title bar decorations. For
example, if I open a new terminal (Ctrl+Shift+N) then the new window gets
activated and focused (and is usable), but keeps inactive decorations.
There's not a single window on my screen with active window decorations now.\\\

I did not see this on my system. However, maybe it would be worth
requesting a pixmap redraw whenever the active state changes.

> --
> https://code.launchpad.net/~smspillaz/compiz-core/compiz-core.decor_synchronization/+merge/102801
> You are the owner of lp:~smspillaz/compiz-core/compiz-core.decor_synchronization.
>

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

I'll deal with this a little later.

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

Looks OK, works OK. As much as I would like to see compiz get smaller and simpler, I am very much liking the outcome of this branch.

And as far as I can tell, the header changes don't *seem* to break the ABI in a way that affects other packages/projects.

review: Approve
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> Looks OK, works OK. As much as I would like to see compiz get smaller and
> simpler, I am very much liking the outcome of this branch.
>
Look to simplicity of execution, not simplicity of code. Refactoring to make code testable may increase code size, but it doesn't increase complexity.

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

Please resubmit this branch. I just reverted it from lp:compiz-core because triplesquarednine found lots of crashes and bisected, finding this branch was the cause.

review: Needs Resubmitting

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

Subscribers

People subscribed via source and target branches