mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 04:22:05 +00:00
[x11] Fix a race condition when resizing a stage
There is a race condition when we resize a stage before showing it on X11. The race goes like this: - clutter_init() creates the default stage and realize it, which will cause a 640x480 Window to be created - call set_size(800, 600) on the stage will cause the Window to be resized to 800x600 - call show() on the stage for the first time will cause COGL to set up an 800 by 600 GL viewport - the Window will be mapped, which will cause X to notify the window manager that the Window should be resized to 800x600 - the window manager will approve the resize - X resizes the drawable to 800x600 To fix the race, we need to defer COGL from setting up the viewport until we receive a ConfigureNotify event and the X server has resized the Drawable. In order to defer the call to cogl_setup_viewport() we add a new private flag, CLUTTER_STAGE_IN_RESIZE; the flag is checked whenever we need to change the viewport size along with the SYNC_MATRICES private flag. Thus, cogl_setup_viewport() will be called only if SYNC_MATRICES is set and IN_RESIZE is not set.
This commit is contained in:
parent
efd7ad7e55
commit
00a3c69868
@ -147,7 +147,8 @@ _clutter_stage_maybe_relayout (ClutterActor *stage)
|
|||||||
void
|
void
|
||||||
_clutter_stage_maybe_setup_viewport (ClutterStage *stage)
|
_clutter_stage_maybe_setup_viewport (ClutterStage *stage)
|
||||||
{
|
{
|
||||||
if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
|
if ((CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES) &&
|
||||||
|
!(CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_STAGE_IN_RESIZE))
|
||||||
{
|
{
|
||||||
ClutterPerspective perspective;
|
ClutterPerspective perspective;
|
||||||
guint width, height;
|
guint width, height;
|
||||||
|
@ -62,7 +62,8 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
CLUTTER_ACTOR_IN_PAINT = 1 << 4, /* Used to avoid recursion */
|
CLUTTER_ACTOR_IN_PAINT = 1 << 4, /* Used to avoid recursion */
|
||||||
CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5, /* Used to avoid recursion */
|
CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5, /* Used to avoid recursion */
|
||||||
CLUTTER_TEXTURE_IN_CLONE_PAINT = 1 << 6 /* Used for safety in clones */
|
CLUTTER_TEXTURE_IN_CLONE_PAINT = 1 << 6, /* Used for safety in clones */
|
||||||
|
CLUTTER_STAGE_IN_RESIZE = 1 << 7 /* Used to mark stage resizes */
|
||||||
} ClutterPrivateFlags;
|
} ClutterPrivateFlags;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -438,6 +438,12 @@ event_translate (ClutterBackend *backend,
|
|||||||
xevent->xconfigure.height);
|
xevent->xconfigure.height);
|
||||||
|
|
||||||
stage_x11->handling_configure = FALSE;
|
stage_x11->handling_configure = FALSE;
|
||||||
|
|
||||||
|
/* the resize process is complete, so we can remove the
|
||||||
|
* in-resize flag and allow the viewport to be resized
|
||||||
|
*/
|
||||||
|
CLUTTER_UNSET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper),
|
||||||
|
CLUTTER_STAGE_IN_RESIZE);
|
||||||
}
|
}
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -282,13 +282,30 @@ clutter_stage_x11_allocate (ClutterActor *self,
|
|||||||
queue. Handling the first event will undo the work of setting
|
queue. Handling the first event will undo the work of setting
|
||||||
the second property which will cause it to keep generating
|
the second property which will cause it to keep generating
|
||||||
events in an infinite loop. See bug #810 */
|
events in an infinite loop. See bug #810 */
|
||||||
if (stage_x11->xwin != None
|
if (stage_x11->xwin != None &&
|
||||||
&& !stage_x11->is_foreign_xwin
|
!stage_x11->is_foreign_xwin &&
|
||||||
&& !stage_x11->handling_configure)
|
!stage_x11->handling_configure)
|
||||||
XResizeWindow (stage_x11->xdpy,
|
{
|
||||||
stage_x11->xwin,
|
XResizeWindow (stage_x11->xdpy,
|
||||||
stage_x11->xwin_width,
|
stage_x11->xwin,
|
||||||
stage_x11->xwin_height);
|
stage_x11->xwin_width,
|
||||||
|
stage_x11->xwin_height);
|
||||||
|
|
||||||
|
/* resizing is an asynchronous process; to avoid races
|
||||||
|
* with the window manager, we flag the wrapper as being
|
||||||
|
* "in resize", so that the SYNC_MATRICES flag will not
|
||||||
|
* cause a call to cogl_get_viewport().
|
||||||
|
*
|
||||||
|
* the flag is unset inside clutter-event-x11.c, after
|
||||||
|
* we receive a ConfigureNotify event. XXX - need to
|
||||||
|
* check what happens when running without a window manager
|
||||||
|
*/
|
||||||
|
CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper),
|
||||||
|
CLUTTER_STAGE_IN_RESIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper),
|
||||||
|
CLUTTER_ACTOR_SYNC_MATRICES);
|
||||||
|
|
||||||
clutter_stage_x11_fix_window_size (stage_x11);
|
clutter_stage_x11_fix_window_size (stage_x11);
|
||||||
|
|
||||||
@ -298,9 +315,6 @@ clutter_stage_x11_allocate (ClutterActor *self,
|
|||||||
clutter_actor_unrealize (self);
|
clutter_actor_unrealize (self);
|
||||||
clutter_actor_realize (self);
|
clutter_actor_realize (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper),
|
|
||||||
CLUTTER_ACTOR_SYNC_MATRICES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* chain up to fill in actor->priv->allocation */
|
/* chain up to fill in actor->priv->allocation */
|
||||||
@ -769,4 +783,3 @@ clutter_stage_x11_unmap (ClutterStageX11 *stage_x11)
|
|||||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
|
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
|
||||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_MAPPED);
|
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_MAPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user