[stage] Fix some races to do with window resizing
When we resize, we relied on the stage's allocate to re-initialise the GL viewport. Unfortunately, if we resized within Clutter, the new size was cached before the window is actually resized, so glViewport wasn't being called after resizing (some of the time, it's a race condition). Change the way resizing works slightly so that we only resize when the geometry size doesn't match our preferred size, and queue a relayout on ConfigureNotify so the glViewport gets called. Also change window creation slightly so that setting the size of a window before it's realized works correctly.
This commit is contained in:
parent
0d428655e2
commit
2fcb644e4f
@ -182,6 +182,7 @@ clutter_stage_allocate (ClutterActor *self,
|
|||||||
ClutterAllocationFlags flags)
|
ClutterAllocationFlags flags)
|
||||||
{
|
{
|
||||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||||
|
ClutterGeometry geom = { 0, };
|
||||||
gboolean origin_changed;
|
gboolean origin_changed;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
|
||||||
@ -192,6 +193,11 @@ clutter_stage_allocate (ClutterActor *self,
|
|||||||
|
|
||||||
width = clutter_actor_box_get_width (box);
|
width = clutter_actor_box_get_width (box);
|
||||||
height = clutter_actor_box_get_height (box);
|
height = clutter_actor_box_get_height (box);
|
||||||
|
_clutter_stage_window_get_geometry (priv->impl, &geom);
|
||||||
|
|
||||||
|
/* XXX: Until Cogl becomes fully responsible for backend windows Clutter
|
||||||
|
* need to manually keep it informed of the current window size */
|
||||||
|
_cogl_onscreen_clutter_backend_set_size (geom.width, geom.height);
|
||||||
|
|
||||||
/* if the stage is fixed size (for instance, it's using a frame-buffer)
|
/* if the stage is fixed size (for instance, it's using a frame-buffer)
|
||||||
* then we simply ignore any allocation request and override the
|
* then we simply ignore any allocation request and override the
|
||||||
@ -201,10 +207,6 @@ clutter_stage_allocate (ClutterActor *self,
|
|||||||
{
|
{
|
||||||
ClutterActorClass *klass;
|
ClutterActorClass *klass;
|
||||||
|
|
||||||
/* XXX: Until Cogl becomes fully responsible for backend windows Clutter
|
|
||||||
* need to manually keep it informed of the current window size */
|
|
||||||
_cogl_onscreen_clutter_backend_set_size (width, height);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (LAYOUT,
|
CLUTTER_NOTE (LAYOUT,
|
||||||
"Following allocation to %dx%d (origin %s)",
|
"Following allocation to %dx%d (origin %s)",
|
||||||
width, height,
|
width, height,
|
||||||
@ -213,20 +215,15 @@ clutter_stage_allocate (ClutterActor *self,
|
|||||||
klass = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
klass = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
||||||
klass->allocate (self, box, flags);
|
klass->allocate (self, box, flags);
|
||||||
|
|
||||||
_clutter_stage_window_resize (priv->impl, width, height);
|
/* Ensure the window is sized correctly */
|
||||||
|
if ((geom.width != width) || (geom.height != height))
|
||||||
|
_clutter_stage_window_resize (priv->impl, width, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ClutterActorBox override = { 0, };
|
ClutterActorBox override = { 0, };
|
||||||
ClutterGeometry geom = { 0, };
|
|
||||||
ClutterActorClass *klass;
|
ClutterActorClass *klass;
|
||||||
|
|
||||||
_clutter_stage_window_get_geometry (priv->impl, &geom);
|
|
||||||
|
|
||||||
/* XXX: Until Cogl becomes fully responsible for backend windows Clutter
|
|
||||||
* need to manually keep it informed of the current window size */
|
|
||||||
_cogl_onscreen_clutter_backend_set_size (geom.width, geom.height);
|
|
||||||
|
|
||||||
override.x1 = 0;
|
override.x1 = 0;
|
||||||
override.y1 = 0;
|
override.y1 = 0;
|
||||||
override.x2 = geom.width;
|
override.x2 = geom.width;
|
||||||
@ -2335,7 +2332,6 @@ clutter_stage_set_minimum_size (ClutterStage *stage,
|
|||||||
guint width,
|
guint width,
|
||||||
guint height)
|
guint height)
|
||||||
{
|
{
|
||||||
gboolean resize;
|
|
||||||
ClutterGeometry geom;
|
ClutterGeometry geom;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||||
@ -2347,20 +2343,18 @@ clutter_stage_set_minimum_size (ClutterStage *stage,
|
|||||||
if (stage->priv->impl == NULL)
|
if (stage->priv->impl == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
resize = FALSE;
|
|
||||||
_clutter_stage_window_get_geometry (stage->priv->impl, &geom);
|
_clutter_stage_window_get_geometry (stage->priv->impl, &geom);
|
||||||
|
|
||||||
if (geom.width < width)
|
if (geom.width > width)
|
||||||
resize = TRUE;
|
|
||||||
else
|
|
||||||
width = geom.width;
|
width = geom.width;
|
||||||
|
|
||||||
if (geom.height < height)
|
if (geom.height > height)
|
||||||
resize = TRUE;
|
|
||||||
else
|
|
||||||
height = geom.height;
|
height = geom.height;
|
||||||
|
|
||||||
if (resize)
|
/* Call resize to ensure that the minimum size is enforced by
|
||||||
|
* the backend.
|
||||||
|
*/
|
||||||
|
if (CLUTTER_ACTOR_IS_MAPPED (stage))
|
||||||
_clutter_stage_window_resize (stage->priv->impl, width, height);
|
_clutter_stage_window_resize (stage->priv->impl, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
|
|||||||
XSetWindowAttributes xattr;
|
XSetWindowAttributes xattr;
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
XVisualInfo *xvisinfo;
|
XVisualInfo *xvisinfo;
|
||||||
|
gfloat width, height;
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "Creating stage X window");
|
CLUTTER_NOTE (MISC, "Creating stage X window");
|
||||||
|
|
||||||
@ -133,6 +134,18 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
|
|||||||
xvisinfo->visual,
|
xvisinfo->visual,
|
||||||
AllocNone);
|
AllocNone);
|
||||||
mask = CWBorderPixel | CWColormap;
|
mask = CWBorderPixel | CWColormap;
|
||||||
|
|
||||||
|
/* Call get_size - this will either get the geometry size (which
|
||||||
|
* before we create the window is set to 640x480), or if a size
|
||||||
|
* is set, it will get that. This lets you set a size on the
|
||||||
|
* stage before it's realized.
|
||||||
|
*/
|
||||||
|
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper),
|
||||||
|
&width,
|
||||||
|
&height);
|
||||||
|
stage_x11->xwin_width = (gint)width;
|
||||||
|
stage_x11->xwin_height = (gint)height;
|
||||||
|
|
||||||
stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
|
stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
|
||||||
backend_x11->xwin_root,
|
backend_x11->xwin_root,
|
||||||
0, 0,
|
0, 0,
|
||||||
@ -144,9 +157,11 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
|
|||||||
xvisinfo->visual,
|
xvisinfo->visual,
|
||||||
mask, &xattr);
|
mask, &xattr);
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x",
|
CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
|
||||||
stage_window,
|
stage_window,
|
||||||
(unsigned int) stage_x11->xwin);
|
(unsigned int) stage_x11->xwin,
|
||||||
|
stage_x11->xwin_width,
|
||||||
|
stage_x11->xwin_height);
|
||||||
|
|
||||||
XFree (xvisinfo);
|
XFree (xvisinfo);
|
||||||
}
|
}
|
||||||
|
@ -482,6 +482,9 @@ event_translate (ClutterBackend *backend,
|
|||||||
xevent->xconfigure.width,
|
xevent->xconfigure.width,
|
||||||
xevent->xconfigure.height);
|
xevent->xconfigure.height);
|
||||||
|
|
||||||
|
stage_x11->xwin_width = xevent->xconfigure.width;
|
||||||
|
stage_x11->xwin_height = xevent->xconfigure.height;
|
||||||
|
|
||||||
clutter_actor_set_size (CLUTTER_ACTOR (stage),
|
clutter_actor_set_size (CLUTTER_ACTOR (stage),
|
||||||
xevent->xconfigure.width,
|
xevent->xconfigure.width,
|
||||||
xevent->xconfigure.height);
|
xevent->xconfigure.height);
|
||||||
@ -493,6 +496,16 @@ event_translate (ClutterBackend *backend,
|
|||||||
* to set up the GL viewport with the new size
|
* to set up the GL viewport with the new size
|
||||||
*/
|
*/
|
||||||
clutter_stage_ensure_viewport (stage);
|
clutter_stage_ensure_viewport (stage);
|
||||||
|
|
||||||
|
/* Also queue a relayout - we want glViewport to be called
|
||||||
|
* with the correct values, and this is done in ClutterStage
|
||||||
|
* via _cogl_onscreen_clutter_backend_set_size ().
|
||||||
|
*
|
||||||
|
* We queue a relayout, because if this ConfigureNotify is
|
||||||
|
* in response to a size we set in the application, the
|
||||||
|
* set_size above is essentially a null-op.
|
||||||
|
*/
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
|
||||||
}
|
}
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -219,27 +219,26 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
|
|||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height);
|
CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height);
|
||||||
|
|
||||||
if (width != stage_x11->xwin_width ||
|
if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin)
|
||||||
height != stage_x11->xwin_height)
|
|
||||||
{
|
{
|
||||||
stage_x11->xwin_width = width;
|
clutter_stage_x11_fix_window_size (stage_x11, width, height);
|
||||||
stage_x11->xwin_height = height;
|
|
||||||
|
|
||||||
if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin)
|
if (width != stage_x11->xwin_width ||
|
||||||
|
height != stage_x11->xwin_height)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)",
|
CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)",
|
||||||
G_STRLOC,
|
G_STRLOC,
|
||||||
(unsigned int) stage_x11->xwin,
|
(unsigned int) stage_x11->xwin,
|
||||||
stage_x11->xwin_width,
|
width,
|
||||||
stage_x11->xwin_height);
|
height);
|
||||||
|
|
||||||
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper,
|
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper,
|
||||||
CLUTTER_STAGE_IN_RESIZE);
|
CLUTTER_STAGE_IN_RESIZE);
|
||||||
|
|
||||||
XResizeWindow (backend_x11->xdpy,
|
XResizeWindow (backend_x11->xdpy,
|
||||||
stage_x11->xwin,
|
stage_x11->xwin,
|
||||||
stage_x11->xwin_width,
|
width,
|
||||||
stage_x11->xwin_height);
|
height);
|
||||||
|
|
||||||
/* If the viewport hasn't previously been initialized then even
|
/* If the viewport hasn't previously been initialized then even
|
||||||
* though we can't guarantee that the server will honour our request
|
* though we can't guarantee that the server will honour our request
|
||||||
@ -249,17 +248,14 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
|
|||||||
{
|
{
|
||||||
ClutterPerspective perspective;
|
ClutterPerspective perspective;
|
||||||
clutter_stage_get_perspective (stage, &perspective);
|
clutter_stage_get_perspective (stage, &perspective);
|
||||||
_cogl_setup_viewport (stage_x11->xwin_width,
|
_cogl_setup_viewport (width,
|
||||||
stage_x11->xwin_height,
|
height,
|
||||||
perspective.fovy,
|
perspective.fovy,
|
||||||
perspective.aspect,
|
perspective.aspect,
|
||||||
perspective.z_near,
|
perspective.z_near,
|
||||||
perspective.z_far);
|
perspective.z_far);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resize)
|
|
||||||
clutter_stage_x11_fix_window_size (stage_x11, width, height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user