backends: Allow multiple "SW" cursor overlays on the stage
All the upper layers are prepared for multiple onscreen cursors, but this. All MetaCursorRenderers created would poke the same internal MetaOverlay in the stage. This will lead to multiple cursor renderers resorting to the "SW" rendering paths (as it can be seen with tablet support) to reuse the same overlay, thus leading to flickering when a different MetaCursorRenderer takes over the overlay. Fix this by allowing per-cursor-renderer overlays, their lifetime is attached to the cursor renderer, so is expected to be tear down if the relevant device (eg. tablet) disappears.
This commit is contained in:
parent
2cec7ac596
commit
362ab781dd
@ -40,6 +40,7 @@ struct _MetaCursorRendererPrivate
|
||||
int current_x, current_y;
|
||||
|
||||
MetaCursorSprite *displayed_cursor;
|
||||
MetaOverlay *stage_overlay;
|
||||
gboolean handled_by_backend;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
@ -63,12 +64,16 @@ queue_redraw (MetaCursorRenderer *renderer,
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
if (!priv->stage_overlay)
|
||||
priv->stage_overlay = meta_stage_create_cursor_overlay (META_STAGE (stage));
|
||||
|
||||
if (cursor_sprite && !priv->handled_by_backend)
|
||||
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
meta_stage_set_cursor (META_STAGE (stage), texture, &rect);
|
||||
meta_stage_update_cursor_overlay (META_STAGE (stage), priv->stage_overlay,
|
||||
texture, &rect);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -81,9 +86,26 @@ meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_finalize (GObject *object)
|
||||
{
|
||||
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
if (priv->stage_overlay)
|
||||
meta_stage_remove_cursor_overlay (META_STAGE (stage), priv->stage_overlay);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_cursor_renderer_finalize;
|
||||
klass->update_cursor = meta_cursor_renderer_real_update_cursor;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
typedef struct {
|
||||
struct _MetaOverlay {
|
||||
gboolean enabled;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
@ -36,22 +36,26 @@ typedef struct {
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
} MetaOverlay;
|
||||
};
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
MetaOverlay cursor_overlay;
|
||||
GList *overlays;
|
||||
gboolean is_active;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
|
||||
|
||||
static void
|
||||
meta_overlay_init (MetaOverlay *overlay)
|
||||
static MetaOverlay *
|
||||
meta_overlay_new ()
|
||||
{
|
||||
MetaOverlay *overlay;
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
overlay = g_slice_new0 (MetaOverlay);
|
||||
overlay->pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
return overlay;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -59,6 +63,8 @@ meta_overlay_free (MetaOverlay *overlay)
|
||||
{
|
||||
if (overlay->pipeline)
|
||||
cogl_object_unref (overlay->pipeline);
|
||||
|
||||
g_slice_free (MetaOverlay, overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -111,8 +117,15 @@ meta_stage_finalize (GObject *object)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
GList *l = priv->overlays;
|
||||
|
||||
meta_overlay_free (&priv->cursor_overlay);
|
||||
while (l)
|
||||
{
|
||||
meta_overlay_free (l->data);
|
||||
l = g_list_delete_link (l, l);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_stage_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -120,10 +133,12 @@ meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
GList *l;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
meta_overlay_paint (&priv->cursor_overlay);
|
||||
for (l = priv->overlays; l; l = l->next)
|
||||
meta_overlay_paint (l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -166,10 +181,6 @@ meta_stage_class_init (MetaStageClass *klass)
|
||||
static void
|
||||
meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_init (&priv->cursor_overlay);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
}
|
||||
|
||||
@ -209,17 +220,43 @@ queue_redraw_for_overlay (MetaStage *stage,
|
||||
}
|
||||
}
|
||||
|
||||
MetaOverlay *
|
||||
meta_stage_create_cursor_overlay (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaOverlay *overlay;
|
||||
|
||||
overlay = meta_overlay_new ();
|
||||
priv->overlays = g_list_prepend (priv->overlays, overlay);
|
||||
|
||||
return overlay;
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
meta_stage_remove_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
GList *link;
|
||||
|
||||
link = g_list_find (priv->overlays, overlay);
|
||||
if (!link)
|
||||
return;
|
||||
|
||||
priv->overlays = g_list_delete_link (priv->overlays, link);
|
||||
meta_overlay_free (overlay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_update_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor () || texture == NULL);
|
||||
|
||||
meta_overlay_set (&priv->cursor_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
|
||||
meta_overlay_set (overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, overlay);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -36,6 +36,7 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _MetaStage MetaStage;
|
||||
typedef struct _MetaStageClass MetaStageClass;
|
||||
typedef struct _MetaOverlay MetaOverlay;
|
||||
|
||||
struct _MetaStageClass
|
||||
{
|
||||
@ -51,7 +52,12 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_stage_new (void);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
|
||||
void meta_stage_remove_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay);
|
||||
|
||||
void meta_stage_update_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user