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

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/compiz-core/compiz-core.decor_synchronization
Merge into: lp:compiz-core/0.9.8
Prerequisite: lp:~smspillaz/compiz-core/compiz-core.work_923683
Diff against target: 591 lines (+267/-34)
9 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 (+7/-7)
include/decoration.h (+18/-0)
libdecoration/decoration.c (+86/-0)
plugins/decor/src/decor.cpp (+72/-2)
plugins/decor/src/decor.h (+7/-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
Review via email: mp+102689@code.launchpad.net

This proposal has been superseded by a proposal from 2012-04-20.

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.

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

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

review: Needs Resubmitting
3016. By Sam Spilsbury

Merge lp:compiz-core

3017. By Sam Spilsbury

Merge lp:~smspillaz/compiz-core/compiz-core.work_923683

3018. By Sam Spilsbury

Merge

3019. By Sam Spilsbury

We don't need a pixmap to determine whether or not the window is active or not

We only need the pixmap in order to determine whether or not the window
should be redrawin in place

3020. By Sam Spilsbury

Refactored the pixmap request / release interface so we can test it

3021. By Sam Spilsbury

Put it all in separate files

3022. By Sam Spilsbury

Test destroying a pixmap also deletes it

3023. By Sam Spilsbury

Added some more mocks

3024. By Sam Spilsbury

Tests

Unmerged revisions

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-20 07:34:19 +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-20 07:34:19 +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-20 07:34:19 +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-20 07:34:19 +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-20 07:34:19 +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@@ -642,7 +642,7 @@
283 * then we need to redraw the decoration anyways
284 * since the image would have changed */
285 if (d->win != NULL &&
286- !update_window_decoration_size (d->win) &&
287+ !request_update_window_decoration_size (d->win) &&
288 d->decorated)
289 queue_decor_draw (d);
290
291@@ -710,7 +710,7 @@
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+ !request_update_window_decoration_size (d->win) &&
297 d->decorated)
298 queue_decor_draw (d);
299
300
301=== modified file 'include/decoration.h'
302--- include/decoration.h 2012-02-09 07:48:57 +0000
303+++ include/decoration.h 2012-04-20 07:34:19 +0000
304@@ -492,6 +492,24 @@
305 XEvent *event,
306 Time dm_sn_timestamp);
307
308+int
309+decor_post_pending (Display *xdisplay,
310+ Window client,
311+ unsigned int frame_state,
312+ unsigned int frame_type,
313+ unsigned int frame_actions);
314+
315+int
316+decor_post_delete_pixmap (Display *xdisplay,
317+ Pixmap pixmap);
318+
319+int
320+decor_post_generate_request (Display *xdisplay,
321+ Window client,
322+ unsigned int frame_type,
323+ unsigned int frame_state,
324+ unsigned int frame_actions);
325+
326 #ifdef __cplusplus
327 }
328 #endif
329
330=== modified file 'libdecoration/decoration.c'
331--- libdecoration/decoration.c 2012-02-27 06:43:04 +0000
332+++ libdecoration/decoration.c 2012-04-20 07:34:19 +0000
333@@ -2877,6 +2877,92 @@
334 }
335
336 int
337+decor_post_pending (Display *xdisplay,
338+ Window client,
339+ unsigned int frame_state,
340+ unsigned int frame_type,
341+ unsigned int frame_actions)
342+{
343+ XEvent event;
344+
345+ Atom decor_pending = XInternAtom (xdisplay, "_COMPIZ_DECOR_PENDING", FALSE);
346+
347+ /* Send a client message indicating that a new
348+ * decoration can be generated for this window
349+ */
350+ event.xclient.type = ClientMessage;
351+ event.xclient.window = client;
352+ event.xclient.message_type = decor_pending;
353+ event.xclient.format = 32;
354+ event.xclient.data.l[0] = frame_type;
355+ event.xclient.data.l[1] = frame_state;
356+ event.xclient.data.l[2] = frame_actions;
357+ event.xclient.data.l[3] = 0;
358+ event.xclient.data.l[4] = 0;
359+
360+ XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0,
361+ StructureNotifyMask, &event);
362+
363+ return 1;
364+}
365+
366+int
367+decor_post_generate_request (Display *xdisplay,
368+ Window client,
369+ unsigned int frame_type,
370+ unsigned int frame_state,
371+ unsigned int frame_actions)
372+{
373+ XEvent event;
374+
375+ Atom decor_request = XInternAtom (xdisplay, "_COMPIZ_DECOR_REQUEST", FALSE);
376+
377+ /* Send a client message indicating that a new
378+ * decoration can be generated for this window
379+ */
380+ event.xclient.type = ClientMessage;
381+ event.xclient.window = client;
382+ event.xclient.message_type = decor_request;
383+ event.xclient.format = 32;
384+ event.xclient.data.l[0] = frame_type;
385+ event.xclient.data.l[1] = frame_state;
386+ event.xclient.data.l[2] = frame_actions;
387+ event.xclient.data.l[3] = 0;
388+ event.xclient.data.l[4] = 0;
389+
390+ XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0,
391+ StructureNotifyMask, &event);
392+
393+ return 1;
394+}
395+
396+int
397+decor_post_delete_pixmap (Display *xdisplay,
398+ Pixmap pixmap)
399+{
400+ XEvent event;
401+
402+ Atom decor_delete_pixmap = XInternAtom (xdisplay, "_COMPIZ_DECOR_DELETE_PIXMAP", FALSE);
403+
404+ /* Send a client message indicating that a new
405+ * decoration can be generated for this window
406+ */
407+ event.xclient.type = ClientMessage;
408+ event.xclient.window = DefaultRootWindow (xdisplay);
409+ event.xclient.message_type = decor_delete_pixmap;
410+ event.xclient.format = 32;
411+ event.xclient.data.l[0] = pixmap;
412+ event.xclient.data.l[1] = 0;
413+ event.xclient.data.l[2] = 0;
414+ event.xclient.data.l[3] = 0;
415+ event.xclient.data.l[4] = 0;
416+
417+ XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0,
418+ StructureNotifyMask, &event);
419+
420+ return 1;
421+}
422+int
423 decor_acquire_dm_session (Display *xdisplay,
424 int screen,
425 const char *name,
426
427=== modified file 'plugins/decor/src/decor.cpp'
428--- plugins/decor/src/decor.cpp 2012-04-20 07:34:18 +0000
429+++ plugins/decor/src/decor.cpp 2012-04-20 07:34:19 +0000
430@@ -347,6 +347,8 @@
431
432 DecorTexture::~DecorTexture ()
433 {
434+ decor_post_delete_pixmap (screen->dpy (), pixmap);
435+
436 if (damage)
437 XDamageDestroy (screen->dpy (), damage);
438 }
439@@ -366,6 +368,9 @@
440 Window root;
441 int i;
442
443+ if (pixmap)
444+ decor_post_delete_pixmap (screen->dpy (), pixmap);
445+
446 pixmap = src;
447
448 if (!XGetGeometry (screen->dpy (), pixmap, &root,
449@@ -390,6 +395,12 @@
450 if (!DecorScreen::get (screen)->optionGetMipmap ())
451 textures[0]->setMipmap (false);
452
453+ if (damage)
454+ XDamageDestroy (screen->dpy (), damage);
455+
456+ damage = XDamageCreate (screen->dpy (), pixmap,
457+ XDamageReportRawRectangles);
458+
459 return true;
460 }
461
462@@ -629,7 +640,8 @@
463 frameActions (frameActions),
464 quad (quad),
465 nQuad (nQuad),
466- type (type)
467+ type (type),
468+ updateState (0)
469 {
470 int left, right, top, bottom;
471 int x1, y1, x2, y2;
472@@ -734,6 +746,19 @@
473 int result, format;
474 unsigned int type;
475
476+ /* Dispatch any new updates */
477+ foreach (const Decoration::Ptr &d, mList)
478+ {
479+ if (d->updateState & Decoration::UpdatesPending)
480+ decor_post_generate_request (screen->dpy (),
481+ id,
482+ d->frameType,
483+ d->frameState,
484+ d->frameActions);
485+
486+ d->updateState = 0;
487+ }
488+
489 result = XGetWindowProperty (screen->dpy (), id,
490 decorAtom, 0L,
491 PROP_HEADER_SIZE + 6 * (BASE_PROP_SIZE +
492@@ -2345,6 +2370,48 @@
493 if (w)
494 DecorWindow::get (w)->update (true);
495 }
496+ /* A decoration is pending creation, allow it to be created */
497+ if (event->xclient.message_type == decorPendingAtom)
498+ {
499+ CompWindow *w = screen->findWindow (event->xclient.window);
500+
501+ if (w)
502+ {
503+ DecorWindow *dw = DecorWindow::get (w);
504+ bool found = false;
505+
506+ foreach (const Decoration::Ptr &d, dw->decor.mList)
507+ {
508+ if (d->frameType == static_cast <unsigned int> (event->xclient.data.l[0]) &&
509+ d->frameState == static_cast <unsigned int> (event->xclient.data.l[1]) &&
510+ d->frameActions == static_cast <unsigned int> (event->xclient.data.l[2]))
511+ {
512+ if (d->updateState & Decoration::UpdateRequested)
513+ d->updateState |= Decoration::UpdatesPending;
514+ else
515+ {
516+ d->updateState |= Decoration::UpdateRequested;
517+
518+ decor_post_generate_request (screen->dpy (),
519+ event->xclient.window,
520+ event->xclient.data.l[0],
521+ event->xclient.data.l[1],
522+ event->xclient.data.l[2]);
523+ }
524+
525+ found = true;
526+ break;
527+ }
528+ }
529+
530+ if (!found)
531+ decor_post_generate_request (screen->dpy (),
532+ event->xclient.window,
533+ event->xclient.data.l[0],
534+ event->xclient.data.l[1],
535+ event->xclient.data.l[2]);
536+ }
537+ }
538 default:
539 /* Check for damage events. If the output or input window
540 * or a texture is updated then damage output extents.
541@@ -2419,7 +2486,6 @@
542 DECOR_WINDOW (w);
543
544 dw->updateDecoration ();
545-
546 dw->update (true);
547 }
548 }
549@@ -2992,6 +3058,10 @@
550 XInternAtom (s->dpy (), DECOR_TYPE_WINDOW_ATOM_NAME, 0);
551 decorSwitchWindowAtom =
552 XInternAtom (s->dpy (), DECOR_SWITCH_WINDOW_ATOM_NAME, 0);
553+ decorPendingAtom =
554+ XInternAtom (s->dpy (), "_COMPIZ_DECOR_PENDING", 0);
555+ decorRequestAtom =
556+ XInternAtom (s->dpy (), "_COMPIZ_DECOR_REQUEST", 0);
557 requestFrameExtentsAtom =
558 XInternAtom (s->dpy (), "_NET_REQUEST_FRAME_EXTENTS", 0);
559 shadowColorAtom =
560
561=== modified file 'plugins/decor/src/decor.h'
562--- plugins/decor/src/decor.h 2012-04-20 07:34:18 +0000
563+++ plugins/decor/src/decor.h 2012-04-20 07:34:19 +0000
564@@ -97,6 +97,9 @@
565
566 typedef boost::shared_ptr <Decoration> Ptr;
567
568+ static const unsigned int UpdateRequested = 1 << 0;
569+ static const unsigned int UpdatesPending = 1 << 1;
570+
571 static Decoration::Ptr create (Window id,
572 long *prop,
573 unsigned int size,
574@@ -135,6 +138,8 @@
575 boost::shared_array <decor_quad_t> quad;
576 int nQuad;
577 int type;
578+
579+ unsigned int updateState;
580 };
581
582 class DecorationList
583@@ -217,6 +222,8 @@
584 Atom shadowColorAtom;
585 Atom shadowInfoAtom;
586 Atom decorSwitchWindowAtom;
587+ Atom decorPendingAtom;
588+ Atom decorRequestAtom;
589
590 Window dmWin;
591 int dmSupports;

Subscribers

People subscribed via source and target branches