shell: Don't move or reconfigure surfaces until we get the new buffer
Going from fullscreen to toplevel will restore the surface position immediately. This will move the fullscreen surface to where the toplevel surface was before, which will flicker for a frame of two before the resized, non-fullscreen buffer is attached. Instead, only change the surface geometry when we get the new buffer.
This commit is contained in:
parent
407ef64e17
commit
7f366e7053
187
src/shell.c
187
src/shell.c
|
@ -115,7 +115,7 @@ struct shell_surface {
|
|||
struct shell_surface *parent;
|
||||
struct desktop_shell *shell;
|
||||
|
||||
enum shell_surface_type type;
|
||||
enum shell_surface_type type, next_type;
|
||||
int32_t saved_x, saved_y;
|
||||
bool saved_position_valid;
|
||||
bool saved_rotation_valid;
|
||||
|
@ -706,19 +706,95 @@ reset_shell_surface_type(struct shell_surface *surface)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_surface_type(struct shell_surface *shsurf)
|
||||
{
|
||||
struct weston_surface *surface = shsurf->surface;
|
||||
struct shell_surface *pshsurf = shsurf->parent;
|
||||
struct weston_surface *pes;
|
||||
struct shell_surface *priv;
|
||||
struct desktop_shell *shell = shsurf->shell;
|
||||
|
||||
reset_shell_surface_type(shsurf);
|
||||
|
||||
shsurf->type = shsurf->next_type;
|
||||
shsurf->next_type = SHELL_SURFACE_NONE;
|
||||
|
||||
switch (shsurf->type) {
|
||||
case SHELL_SURFACE_TOPLEVEL:
|
||||
break;
|
||||
case SHELL_SURFACE_TRANSIENT:
|
||||
pes = pshsurf->surface;
|
||||
weston_surface_set_position(surface,
|
||||
pes->geometry.x + shsurf->popup.x,
|
||||
pes->geometry.y + shsurf->popup.y);
|
||||
break;
|
||||
|
||||
case SHELL_SURFACE_MAXIMIZED:
|
||||
shsurf->saved_x = surface->geometry.x;
|
||||
shsurf->saved_y = surface->geometry.y;
|
||||
shsurf->saved_position_valid = true;
|
||||
break;
|
||||
|
||||
case SHELL_SURFACE_FULLSCREEN:
|
||||
shsurf->saved_x = surface->geometry.x;
|
||||
shsurf->saved_y = surface->geometry.y;
|
||||
shsurf->saved_position_valid = true;
|
||||
|
||||
if (!wl_list_empty(&shsurf->rotation.transform.link)) {
|
||||
wl_list_remove(&shsurf->rotation.transform.link);
|
||||
wl_list_init(&shsurf->rotation.transform.link);
|
||||
shsurf->surface->geometry.dirty = 1;
|
||||
shsurf->saved_rotation_valid = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHELL_SURFACE_BACKGROUND:
|
||||
wl_list_for_each(priv, &shell->backgrounds, link) {
|
||||
if (priv->output == shsurf->output) {
|
||||
priv->surface->output = NULL;
|
||||
wl_list_remove(&priv->surface->layer_link);
|
||||
wl_list_remove(&priv->link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_insert(&shell->backgrounds, &shsurf->link);
|
||||
|
||||
weston_surface_set_position(surface, shsurf->output->x,
|
||||
shsurf->output->y);
|
||||
break;
|
||||
|
||||
case SHELL_SURFACE_PANEL:
|
||||
wl_list_for_each(priv, &shell->panels, link) {
|
||||
if (priv->output == shsurf->output) {
|
||||
priv->surface->output = NULL;
|
||||
wl_list_remove(&priv->surface->layer_link);
|
||||
wl_list_remove(&priv->link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_insert(&shell->panels, &shsurf->link);
|
||||
|
||||
weston_surface_set_position(surface, shsurf->output->x,
|
||||
shsurf->output->y);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_toplevel(struct shell_surface *shsurf)
|
||||
{
|
||||
if (reset_shell_surface_type(shsurf))
|
||||
return;
|
||||
|
||||
shsurf->type = SHELL_SURFACE_TOPLEVEL;
|
||||
shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
|
||||
}
|
||||
|
||||
static void
|
||||
shell_surface_set_toplevel(struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
|
||||
{
|
||||
struct shell_surface *surface = resource->data;
|
||||
|
||||
|
@ -732,19 +808,12 @@ shell_surface_set_transient(struct wl_client *client,
|
|||
int x, int y, uint32_t flags)
|
||||
{
|
||||
struct shell_surface *shsurf = resource->data;
|
||||
struct weston_surface *es = shsurf->surface;
|
||||
struct shell_surface *pshsurf = parent_resource->data;
|
||||
struct weston_surface *pes = pshsurf->surface;
|
||||
|
||||
if (reset_shell_surface_type(shsurf))
|
||||
return;
|
||||
|
||||
/* assign to parents output */
|
||||
shsurf->output = pes->output;
|
||||
weston_surface_set_position(es, pes->geometry.x + x,
|
||||
pes->geometry.y + y);
|
||||
|
||||
shsurf->type = SHELL_SURFACE_TRANSIENT;
|
||||
shsurf->parent = parent_resource->data;
|
||||
shsurf->popup.x = x;
|
||||
shsurf->popup.y = y;
|
||||
shsurf->next_type = SHELL_SURFACE_TRANSIENT;
|
||||
}
|
||||
|
||||
static struct desktop_shell *
|
||||
|
@ -789,13 +858,6 @@ shell_surface_set_maximized(struct wl_client *client,
|
|||
else
|
||||
shsurf->output = get_default_output(es->compositor);
|
||||
|
||||
if (reset_shell_surface_type(shsurf))
|
||||
return;
|
||||
|
||||
shsurf->saved_x = es->geometry.x;
|
||||
shsurf->saved_y = es->geometry.y;
|
||||
shsurf->saved_position_valid = true;
|
||||
|
||||
shell = shell_surface_get_shell(shsurf);
|
||||
panel_height = get_output_panel_height(shell, es->output);
|
||||
edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
|
||||
|
@ -804,7 +866,7 @@ shell_surface_set_maximized(struct wl_client *client,
|
|||
es->output->current->width,
|
||||
es->output->current->height - panel_height);
|
||||
|
||||
shsurf->type = SHELL_SURFACE_MAXIMIZED;
|
||||
shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -941,28 +1003,14 @@ shell_surface_set_fullscreen(struct wl_client *client,
|
|||
else
|
||||
shsurf->output = get_default_output(es->compositor);
|
||||
|
||||
if (reset_shell_surface_type(shsurf))
|
||||
return;
|
||||
|
||||
shsurf->fullscreen_output = shsurf->output;
|
||||
shsurf->fullscreen.type = method;
|
||||
shsurf->fullscreen.framerate = framerate;
|
||||
shsurf->type = SHELL_SURFACE_FULLSCREEN;
|
||||
|
||||
shsurf->saved_x = es->geometry.x;
|
||||
shsurf->saved_y = es->geometry.y;
|
||||
shsurf->saved_position_valid = true;
|
||||
shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
|
||||
|
||||
if (weston_surface_is_mapped(es))
|
||||
shsurf->force_configure = 1;
|
||||
|
||||
if (!wl_list_empty(&shsurf->rotation.transform.link)) {
|
||||
wl_list_remove(&shsurf->rotation.transform.link);
|
||||
wl_list_init(&shsurf->rotation.transform.link);
|
||||
shsurf->surface->geometry.dirty = 1;
|
||||
shsurf->saved_rotation_valid = true;
|
||||
}
|
||||
|
||||
wl_shell_surface_send_configure(&shsurf->resource, 0,
|
||||
shsurf->output->current->width,
|
||||
shsurf->output->current->height);
|
||||
|
@ -1210,6 +1258,7 @@ create_shell_surface(void *shell, struct weston_surface *surface,
|
|||
weston_matrix_init(&shsurf->rotation.rotation);
|
||||
|
||||
shsurf->type = SHELL_SURFACE_NONE;
|
||||
shsurf->next_type = SHELL_SURFACE_NONE;
|
||||
|
||||
*ret = shsurf;
|
||||
}
|
||||
|
@ -1318,31 +1367,11 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
struct wl_resource *output_resource,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
struct desktop_shell *shell = resource->data;
|
||||
struct shell_surface *shsurf = surface_resource->data;
|
||||
struct weston_surface *surface = shsurf->surface;
|
||||
struct shell_surface *priv;
|
||||
|
||||
if (reset_shell_surface_type(shsurf))
|
||||
return;
|
||||
|
||||
wl_list_for_each(priv, &shell->backgrounds, link) {
|
||||
if (priv->output == output_resource->data) {
|
||||
priv->surface->output = NULL;
|
||||
wl_list_remove(&priv->surface->layer_link);
|
||||
wl_list_remove(&priv->link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shsurf->type = SHELL_SURFACE_BACKGROUND;
|
||||
shsurf->next_type = SHELL_SURFACE_BACKGROUND;
|
||||
shsurf->output = output_resource->data;
|
||||
|
||||
wl_list_insert(&shell->backgrounds, &shsurf->link);
|
||||
|
||||
weston_surface_set_position(surface, shsurf->output->x,
|
||||
shsurf->output->y);
|
||||
|
||||
desktop_shell_send_configure(resource, 0,
|
||||
surface_resource,
|
||||
shsurf->output->current->width,
|
||||
|
@ -1355,31 +1384,11 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
struct wl_resource *output_resource,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
struct desktop_shell *shell = resource->data;
|
||||
struct shell_surface *shsurf = surface_resource->data;
|
||||
struct weston_surface *surface = shsurf->surface;
|
||||
struct shell_surface *priv;
|
||||
|
||||
if (reset_shell_surface_type(shsurf))
|
||||
return;
|
||||
|
||||
wl_list_for_each(priv, &shell->panels, link) {
|
||||
if (priv->output == output_resource->data) {
|
||||
priv->surface->output = NULL;
|
||||
wl_list_remove(&priv->surface->layer_link);
|
||||
wl_list_remove(&priv->link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shsurf->type = SHELL_SURFACE_PANEL;
|
||||
shsurf->next_type = SHELL_SURFACE_PANEL;
|
||||
shsurf->output = output_resource->data;
|
||||
|
||||
wl_list_insert(&shell->panels, &shsurf->link);
|
||||
|
||||
weston_surface_set_position(surface, shsurf->output->x,
|
||||
shsurf->output->y);
|
||||
|
||||
desktop_shell_send_configure(resource, 0,
|
||||
surface_resource,
|
||||
shsurf->output->current->width,
|
||||
|
@ -1404,9 +1413,6 @@ desktop_shell_set_lock_surface(struct wl_client *client,
|
|||
struct desktop_shell *shell = resource->data;
|
||||
struct shell_surface *surface = surface_resource->data;
|
||||
|
||||
if (reset_shell_surface_type(surface))
|
||||
return;
|
||||
|
||||
shell->prepare_event_sent = false;
|
||||
|
||||
if (!shell->locked)
|
||||
|
@ -1418,7 +1424,7 @@ desktop_shell_set_lock_surface(struct wl_client *client,
|
|||
wl_signal_add(&surface_resource->destroy_signal,
|
||||
&shell->lock_surface_listener);
|
||||
|
||||
shell->lock_surface->type = SHELL_SURFACE_LOCK;
|
||||
shell->lock_surface->next_type = SHELL_SURFACE_LOCK;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2127,6 +2133,10 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
|
|||
struct shell_surface *shsurf = get_shell_surface(es);
|
||||
struct desktop_shell *shell = shsurf->shell;
|
||||
|
||||
if (shsurf->next_type != SHELL_SURFACE_NONE &&
|
||||
shsurf->type != shsurf->next_type)
|
||||
set_surface_type(shsurf);
|
||||
|
||||
if (!weston_surface_is_mapped(es)) {
|
||||
map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
|
||||
} else if (shsurf->force_configure || sx != 0 || sy != 0 ||
|
||||
|
@ -2243,10 +2253,7 @@ screensaver_set_surface(struct wl_client *client,
|
|||
struct shell_surface *surface = shell_surface_resource->data;
|
||||
struct weston_output *output = output_resource->data;
|
||||
|
||||
if (reset_shell_surface_type(surface))
|
||||
return;
|
||||
|
||||
surface->type = SHELL_SURFACE_SCREENSAVER;
|
||||
surface->next_type = SHELL_SURFACE_SCREENSAVER;
|
||||
|
||||
surface->fullscreen_output = output;
|
||||
surface->output = output;
|
||||
|
|
Loading…
Reference in New Issue