wayland: Refactor MetaWaylandSurfaceRoleCursor

Move into a standalone meta-wayland-surface-role-cursor.[ch], and
make generic enough to work for pointe and additional (eg. tablet)
cursors.

Most notably, the sprite is now kept completely internal to the
cursor role, and updates are routed through the given
MetaCursorRenderer (which may be the default one for the pointer,
or something else).

The way cursor updates after cursor surface destruction has also
been reworked, the pointer will just keep track of the last cursor
surface, so older surfaces being destroyed don't trigger pointer
rechecks/updates.
This commit is contained in:
Carlos Garnacho
2015-10-21 16:36:44 +02:00
parent 1acfcbda6c
commit 5849275b76
5 changed files with 374 additions and 237 deletions

View File

@ -54,6 +54,7 @@
#include "meta-wayland-private.h"
#include "meta-wayland-surface.h"
#include "meta-wayland-buffer.h"
#include "meta-wayland-surface-role-cursor.h"
#include "meta-xwayland.h"
#include "meta-cursor.h"
#include "meta-cursor-tracker-private.h"
@ -73,24 +74,6 @@
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
struct _MetaWaylandSurfaceRoleCursor
{
MetaWaylandSurfaceRole parent;
int hot_x;
int hot_y;
MetaCursorSprite *cursor_sprite;
MetaWaylandBuffer *buffer;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
meta_wayland_surface_role_cursor,
META_TYPE_WAYLAND_SURFACE_ROLE);
static void
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer);
static MetaWaylandPointerClient *
meta_wayland_pointer_client_new (void)
{
@ -501,6 +484,12 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer)
(gpointer) meta_wayland_pointer_on_cursor_changed,
pointer);
if (pointer->cursor_surface && pointer->cursor_surface_destroy_id)
{
g_signal_handler_disconnect (pointer->cursor_surface,
pointer->cursor_surface_destroy_id);
}
meta_wayland_pointer_set_focus (pointer, NULL);
g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
@ -928,7 +917,7 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
*sy = wl_fixed_from_double (yf);
}
static void
void
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
{
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
@ -942,7 +931,7 @@ meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (pointer->cursor_surface->role);
cursor_sprite = cursor_role->cursor_sprite;
cursor_sprite = meta_wayland_surface_role_cursor_get_sprite (cursor_role);
}
meta_cursor_tracker_set_window_cursor (cursor_tracker, cursor_sprite);
@ -954,68 +943,14 @@ meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
}
static void
update_cursor_sprite_texture (MetaWaylandSurface *surface)
ensure_update_cursor_surface (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface)
{
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (meta_get_backend ());
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
MetaCursorSprite *cursor_sprite = cursor_role->cursor_sprite;
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
if (pointer->cursor_surface != surface)
return;
g_return_if_fail (!buffer || buffer->texture);
if (buffer)
{
meta_cursor_sprite_set_texture (cursor_sprite,
buffer->texture,
cursor_role->hot_x * surface->scale,
cursor_role->hot_y * surface->scale);
if (cursor_role->buffer)
{
struct wl_resource *buffer_resource;
g_assert (cursor_role->buffer == buffer);
buffer_resource = buffer->resource;
meta_cursor_renderer_realize_cursor_from_wl_buffer (cursor_renderer,
cursor_sprite,
buffer_resource);
meta_wayland_surface_unref_buffer_use_count (surface);
g_clear_object (&cursor_role->buffer);
}
}
else
{
meta_cursor_sprite_set_texture (cursor_sprite, NULL, 0, 0);
}
if (cursor_sprite == meta_cursor_tracker_get_displayed_cursor (cursor_tracker))
meta_cursor_renderer_force_update (cursor_renderer);
}
static void
cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite,
int x,
int y,
MetaWaylandSurfaceRoleCursor *cursor_role)
{
MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_role);
MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role);
MetaDisplay *display = meta_get_display ();
MetaScreen *screen = display->screen;
const MetaMonitorInfo *monitor;
if (!meta_xwayland_is_xwayland_surface (surface))
{
monitor = meta_screen_get_monitor_for_point (screen, x, y);
if (monitor)
meta_cursor_sprite_set_texture_scale (cursor_sprite,
(float)monitor->scale / surface->scale);
}
meta_wayland_surface_update_outputs (surface);
pointer->cursor_surface = NULL;
meta_wayland_pointer_update_cursor_surface (pointer);
}
static void
@ -1025,14 +960,28 @@ meta_wayland_pointer_set_cursor_surface (MetaWaylandPointer *pointer,
MetaWaylandSurface *prev_cursor_surface;
prev_cursor_surface = pointer->cursor_surface;
if (prev_cursor_surface == cursor_surface)
return;
pointer->cursor_surface = cursor_surface;
if (prev_cursor_surface != cursor_surface)
if (prev_cursor_surface)
{
if (prev_cursor_surface)
meta_wayland_surface_update_outputs (prev_cursor_surface);
meta_wayland_pointer_update_cursor_surface (pointer);
meta_wayland_surface_update_outputs (prev_cursor_surface);
g_signal_handler_disconnect (prev_cursor_surface,
pointer->cursor_surface_destroy_id);
}
if (cursor_surface)
{
pointer->cursor_surface_destroy_id =
g_signal_connect_swapped (cursor_surface, "destroy",
G_CALLBACK (ensure_update_cursor_surface),
pointer);
}
meta_wayland_pointer_update_cursor_surface (pointer);
}
static void
@ -1066,23 +1015,15 @@ pointer_set_cursor (struct wl_client *client,
if (surface)
{
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (meta_get_backend ());
MetaWaylandSurfaceRoleCursor *cursor_role;
cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
if (!cursor_role->cursor_sprite)
{
cursor_role->cursor_sprite = meta_cursor_sprite_new ();
g_signal_connect_object (cursor_role->cursor_sprite,
"prepare-at",
G_CALLBACK (cursor_sprite_prepare_at),
cursor_role,
0);
}
cursor_role->hot_x = hot_x;
cursor_role->hot_y = hot_y;
update_cursor_sprite_texture (surface);
meta_wayland_surface_role_cursor_set_renderer (cursor_role,
cursor_renderer);
meta_wayland_surface_role_cursor_set_hotspot (cursor_role,
hot_x, hot_y);
}
meta_wayland_pointer_set_cursor_surface (pointer, surface);
@ -1255,136 +1196,3 @@ meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
MetaWaylandSeat *seat = wl_container_of (pointer, seat, pointer);
return seat;
}
static void
cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
if (buffer)
{
g_set_object (&cursor_role->buffer, buffer);
meta_wayland_surface_ref_buffer_use_count (surface);
}
meta_wayland_surface_queue_pending_frame_callbacks (surface);
}
static void
cursor_surface_role_pre_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
if (pending->newly_attached && cursor_role->buffer)
{
meta_wayland_surface_unref_buffer_use_count (surface);
g_clear_object (&cursor_role->buffer);
}
}
static void
cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
if (pending->newly_attached)
{
g_set_object (&cursor_role->buffer, buffer);
if (cursor_role->buffer)
meta_wayland_surface_ref_buffer_use_count (surface);
}
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
if (pending->newly_attached)
update_cursor_sprite_texture (surface);
}
static gboolean
cursor_surface_role_is_on_output (MetaWaylandSurfaceRole *role,
MetaMonitorInfo *monitor)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (role);
MetaWaylandPointer *pointer = &surface->compositor->seat->pointer;
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (meta_get_backend ());
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
MetaCursorSprite *displayed_cursor_sprite;
MetaRectangle rect;
if (surface != pointer->cursor_surface)
return FALSE;
displayed_cursor_sprite =
meta_cursor_tracker_get_displayed_cursor (cursor_tracker);
if (!displayed_cursor_sprite)
return FALSE;
if (cursor_role->cursor_sprite != displayed_cursor_sprite)
return FALSE;
rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
cursor_role->cursor_sprite);
return meta_rectangle_overlap (&rect, &monitor->rect);
}
static void
cursor_surface_role_dispose (GObject *object)
{
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (object);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object));
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandPointer *pointer = &compositor->seat->pointer;
if (pointer->cursor_surface == surface)
pointer->cursor_surface = NULL;
meta_wayland_pointer_update_cursor_surface (pointer);
g_clear_object (&cursor_role->cursor_sprite);
if (cursor_role->buffer)
{
meta_wayland_surface_unref_buffer_use_count (surface);
g_clear_object (&cursor_role->buffer);
}
G_OBJECT_CLASS (meta_wayland_surface_role_cursor_parent_class)->dispose (object);
}
static void
meta_wayland_surface_role_cursor_init (MetaWaylandSurfaceRoleCursor *role)
{
}
static void
meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
surface_role_class->assigned = cursor_surface_role_assigned;
surface_role_class->pre_commit = cursor_surface_role_pre_commit;
surface_role_class->commit = cursor_surface_role_commit;
surface_role_class->is_on_output = cursor_surface_role_is_on_output;
object_class->dispose = cursor_surface_role_dispose;
}