wayland-surface: Attach the buffer to a surface, even if it doesn't have a role

Currently, set_cursor isn't properly working. Often, the requests look
like this:

  cursor_surface = wl_compositor.create_surface()
  cursor_buffer = create_cursor_buffer()
  cursor_surface.attach(cursor_buffer, 0, 0)
  cursor_surface.commit()
  wl_pointer.set_cursor(cursor_surface, 7, 14)

But since the surface doesn't "have a role" when the commit comes in,
we ignore it, and don't do anything with the pending buffer. When
set_cursor is called, however, we don't immediately update anything
since it doesn't have a buffer.

This effectively means that set_cursor has unpredictable side effects.
Weston's toy toolkit reuses the same surface for every buffer, so it
only fails the first time. In clients that use a new surface for every
cursor sprite, the cursor is effectively invisible.

To solve this, change the code to always set the buffer for a surface,
even if it doesn't have any real role.
This commit is contained in:
Jasper St. Pierre 2014-02-01 17:05:14 -05:00
parent d74796ee80
commit 92e36e7076

View File

@ -250,34 +250,25 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer)
static void
cursor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
MetaWaylandBuffer *buffer = pending->buffer;
if (pending->newly_attached && buffer != surface->buffer_ref.buffer)
{
ensure_buffer_texture (buffer);
meta_wayland_buffer_reference (&surface->buffer_ref, buffer);
}
meta_wayland_seat_update_sprite (surface->compositor->seat);
if (buffer_changed)
meta_wayland_seat_update_sprite (surface->compositor->seat);
}
static gboolean
static void
actor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
gboolean changed = FALSE;
/* wl_surface.attach */
if (pending->newly_attached && buffer != surface->buffer_ref.buffer)
if (buffer_changed)
{
ensure_buffer_texture (buffer);
meta_wayland_buffer_reference (&surface->buffer_ref, buffer);
meta_surface_actor_attach_wayland_buffer (surface_actor, buffer);
changed = TRUE;
}
surface_process_damage (surface, pending->damage);
@ -286,15 +277,16 @@ actor_surface_commit (MetaWaylandSurface *surface,
meta_surface_actor_set_opaque_region (surface_actor, pending->opaque_region);
if (pending->input_region)
meta_surface_actor_set_input_region (surface_actor, pending->input_region);
return changed;
}
static void
toplevel_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
if (actor_surface_commit (surface, pending))
actor_surface_commit (surface, pending, buffer_changed);
if (buffer_changed)
{
MetaWindow *window = surface->window;
MetaWaylandBuffer *buffer = pending->buffer;
@ -398,7 +390,8 @@ move_double_buffered_state (MetaWaylandDoubleBufferedState *from,
static void
subsurface_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
/*
* If the sub-surface is in synchronous mode, post-pone the commit of its
@ -416,21 +409,26 @@ subsurface_surface_commit (MetaWaylandSurface *surface,
{
move_double_buffered_state (pending, &surface->sub.pending_surface_state);
}
else if (actor_surface_commit (surface, pending))
else
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
float x, y;
actor_surface_commit (surface, pending, buffer_changed);
if (buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
if (buffer_changed)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
float x, y;
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
x += pending->dx;
y += pending->dy;
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
if (buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
x += pending->dx;
y += pending->dy;
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
}
}
}
@ -448,13 +446,21 @@ commit_double_buffered_state (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
{
MetaWaylandCompositor *compositor = surface->compositor;
gboolean buffer_changed = FALSE;
/* wl_surface.attach */
if (pending->newly_attached && pending->buffer != surface->buffer_ref.buffer)
{
meta_wayland_buffer_reference (&surface->buffer_ref, pending->buffer);
buffer_changed = TRUE;
}
if (surface == compositor->seat->sprite)
cursor_surface_commit (surface, pending);
cursor_surface_commit (surface, pending, buffer_changed);
else if (surface->window)
toplevel_surface_commit (surface, pending);
toplevel_surface_commit (surface, pending, buffer_changed);
else if (surface->subsurface.resource)
subsurface_surface_commit (surface, pending);
subsurface_surface_commit (surface, pending, buffer_changed);
g_list_foreach (surface->subsurfaces,
parent_surface_committed,