stage: Refactor the cursor drawing code into a generic "overlay" system

This isn't really anything but a really small actor system. This will be
used for DND cursors as well.
This commit is contained in:
Jasper St. Pierre 2014-08-21 14:47:39 -04:00
parent 9ecbac365b
commit c7fa446ee7

View File

@ -28,31 +28,82 @@
#include <meta/meta-backend.h> #include <meta/meta-backend.h>
#include <meta/util.h> #include <meta/util.h>
struct _MetaStagePrivate { typedef struct {
CoglPipeline *pipeline; gboolean enabled;
MetaCursorReference *cursor; CoglPipeline *pipeline;
CoglTexture *texture;
MetaRectangle current_rect; MetaRectangle current_rect;
MetaRectangle previous_rect; MetaRectangle previous_rect;
gboolean previous_is_valid; gboolean previous_is_valid;
} MetaOverlay;
struct _MetaStagePrivate {
MetaOverlay cursor_overlay;
}; };
typedef struct _MetaStagePrivate MetaStagePrivate; typedef struct _MetaStagePrivate MetaStagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE); G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
static void static void
update_pipeline (MetaStage *stage) meta_overlay_init (MetaOverlay *overlay)
{ {
MetaStagePrivate *priv = meta_stage_get_instance_private (stage); CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
if (priv->cursor) overlay->pipeline = cogl_pipeline_new (ctx);
}
static void
meta_overlay_free (MetaOverlay *overlay)
{
if (overlay->pipeline)
cogl_object_unref (overlay->pipeline);
}
static void
meta_overlay_set (MetaOverlay *overlay,
CoglTexture *texture,
MetaRectangle *rect)
{
if (overlay->texture != texture)
{ {
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL); overlay->texture = texture;
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
if (texture)
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, texture);
overlay->enabled = TRUE;
}
else
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, NULL);
overlay->enabled = FALSE;
}
} }
else
cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL); overlay->current_rect = *rect;
}
static void
meta_overlay_paint (MetaOverlay *overlay)
{
g_assert (meta_is_wayland_compositor ());
if (!overlay->enabled)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
overlay->pipeline,
overlay->current_rect.x,
overlay->current_rect.y,
overlay->current_rect.x +
overlay->current_rect.width,
overlay->current_rect.y +
overlay->current_rect.height);
overlay->previous_rect = overlay->current_rect;
overlay->previous_is_valid = TRUE;
} }
static void static void
@ -61,42 +112,18 @@ meta_stage_finalize (GObject *object)
MetaStage *stage = META_STAGE (object); MetaStage *stage = META_STAGE (object);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage); MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
if (priv->pipeline) meta_overlay_free (&priv->cursor_overlay);
cogl_object_unref (priv->pipeline);
}
static void
paint_cursor (MetaStage *stage)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
g_assert (meta_is_wayland_compositor ());
if (!priv->cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
priv->pipeline,
priv->current_rect.x,
priv->current_rect.y,
priv->current_rect.x +
priv->current_rect.width,
priv->current_rect.y +
priv->current_rect.height);
priv->previous_rect = priv->current_rect;
priv->previous_is_valid = TRUE;
} }
static void static void
meta_stage_paint (ClutterActor *actor) meta_stage_paint (ClutterActor *actor)
{ {
MetaStage *stage = META_STAGE (actor); MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor); CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
if (meta_is_wayland_compositor ()) meta_overlay_paint (&priv->cursor_overlay);
paint_cursor (stage);
} }
static void static void
@ -113,10 +140,9 @@ meta_stage_class_init (MetaStageClass *klass)
static void static void
meta_stage_init (MetaStage *stage) meta_stage_init (MetaStage *stage)
{ {
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaStagePrivate *priv = meta_stage_get_instance_private (stage); MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
priv->pipeline = cogl_pipeline_new (ctx); meta_overlay_init (&priv->cursor_overlay);
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE); clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
} }
@ -130,29 +156,29 @@ meta_stage_new (void)
} }
static void static void
queue_redraw (MetaStage *stage) queue_redraw_for_overlay (MetaStage *stage,
MetaOverlay *overlay)
{ {
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
cairo_rectangle_int_t clip; cairo_rectangle_int_t clip;
/* Clear the location the cursor was at before, if we need to. */ /* Clear the location the overlay was at before, if we need to. */
if (priv->previous_is_valid) if (overlay->previous_is_valid)
{ {
clip.x = priv->previous_rect.x; clip.x = overlay->previous_rect.x;
clip.y = priv->previous_rect.y; clip.y = overlay->previous_rect.y;
clip.width = priv->previous_rect.width; clip.width = overlay->previous_rect.width;
clip.height = priv->previous_rect.height; clip.height = overlay->previous_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
priv->previous_is_valid = FALSE; overlay->previous_is_valid = FALSE;
} }
/* And queue a redraw for the current cursor location. */ /* Draw the overlay at the new position */
if (priv->cursor) if (overlay->enabled)
{ {
clip.x = priv->current_rect.x; clip.x = overlay->current_rect.x;
clip.y = priv->current_rect.y; clip.y = overlay->current_rect.y;
clip.width = priv->current_rect.width; clip.width = overlay->current_rect.width;
clip.height = priv->current_rect.height; clip.height = overlay->current_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
} }
} }
@ -163,13 +189,15 @@ meta_stage_set_cursor (MetaStage *stage,
MetaRectangle *rect) MetaRectangle *rect)
{ {
MetaStagePrivate *priv = meta_stage_get_instance_private (stage); MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CoglTexture *texture;
if (priv->cursor != cursor) g_assert (meta_is_wayland_compositor ());
{
priv->cursor = cursor;
update_pipeline (stage);
}
priv->current_rect = *rect; if (cursor)
queue_redraw (stage); texture = meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
else
texture = NULL;
meta_overlay_set (&priv->cursor_overlay, texture, rect);
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
} }