stage-view: Add API to inhibit cursor overlay painting

This adds some plumbing to get the "default" paint flags for regular
stage painting, where one either wants to paint the overlay, or not.

If inhibited, the 'no-cursors' paint flag is used, otherwise the 'none'
flag. This will be used to allow having a per stage view hw cursor
state.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This commit is contained in:
Jonas Ådahl 2022-12-21 18:30:29 +01:00
parent 5d35138df0
commit f4b76727db
8 changed files with 119 additions and 9 deletions

View File

@ -1634,3 +1634,15 @@ clutter_stage_view_invalidate_input_devices (ClutterStageView *view)
priv->needs_update_devices = TRUE; priv->needs_update_devices = TRUE;
} }
ClutterPaintFlag
clutter_stage_view_get_default_paint_flags (ClutterStageView *view)
{
ClutterStageViewClass *view_class =
CLUTTER_STAGE_VIEW_GET_CLASS (view);
if (view_class->get_default_paint_flags)
return view_class->get_default_paint_flags (view);
else
return CLUTTER_PAINT_FLAG_NONE;
}

View File

@ -28,6 +28,7 @@
#include "clutter-macros.h" #include "clutter-macros.h"
#include "clutter-frame-clock.h" #include "clutter-frame-clock.h"
#include "clutter-types.h"
#define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ()) #define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ())
CLUTTER_EXPORT CLUTTER_EXPORT
@ -52,6 +53,8 @@ struct _ClutterStageViewClass
cairo_rectangle_int_t *dst_rect); cairo_rectangle_int_t *dst_rect);
ClutterFrame * (* new_frame) (ClutterStageView *view); ClutterFrame * (* new_frame) (ClutterStageView *view);
ClutterPaintFlag (* get_default_paint_flags) (ClutterStageView *view);
}; };
CLUTTER_EXPORT CLUTTER_EXPORT
@ -90,4 +93,7 @@ gboolean clutter_stage_view_has_shadowfb (ClutterStageView *view);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_view_schedule_update_now (ClutterStageView *view); void clutter_stage_view_schedule_update_now (ClutterStageView *view);
CLUTTER_EXPORT
ClutterPaintFlag clutter_stage_view_get_default_paint_flags (ClutterStageView *view);
#endif /* __CLUTTER_STAGE_VIEW_H__ */ #endif /* __CLUTTER_STAGE_VIEW_H__ */

View File

@ -412,6 +412,7 @@ clutter_stage_do_paint_view (ClutterStage *stage,
CoglFramebuffer *fb; CoglFramebuffer *fb;
ClutterColor bg_color; ClutterColor bg_color;
int n_rectangles; int n_rectangles;
ClutterPaintFlag paint_flags;
n_rectangles = redraw_clip ? cairo_region_num_rectangles (redraw_clip) : 0; n_rectangles = redraw_clip ? cairo_region_num_rectangles (redraw_clip) : 0;
if (redraw_clip && n_rectangles < MAX_FRUSTA) if (redraw_clip && n_rectangles < MAX_FRUSTA)
@ -445,10 +446,12 @@ clutter_stage_do_paint_view (ClutterStage *stage,
_clutter_stage_paint_volume_stack_free_all (stage); _clutter_stage_paint_volume_stack_free_all (stage);
paint_flags = clutter_stage_view_get_default_paint_flags (view);
paint_context = clutter_paint_context_new_for_view (view, paint_context = clutter_paint_context_new_for_view (view,
redraw_clip, redraw_clip,
clip_frusta, clip_frusta,
CLUTTER_PAINT_FLAG_NONE); paint_flags);
if (frame) if (frame)
clutter_paint_context_assign_frame (paint_context, frame); clutter_paint_context_assign_frame (paint_context, frame);

View File

@ -54,6 +54,7 @@ typedef struct _ClutterLayoutMeta ClutterLayoutMeta;
typedef struct _ClutterActorMeta ClutterActorMeta; typedef struct _ClutterActorMeta ClutterActorMeta;
typedef struct _ClutterLayoutManager ClutterLayoutManager; typedef struct _ClutterLayoutManager ClutterLayoutManager;
typedef struct _ClutterActorIter ClutterActorIter; typedef struct _ClutterActorIter ClutterActorIter;
typedef struct _ClutterPaintContext ClutterPaintContext;
typedef struct _ClutterPaintNode ClutterPaintNode; typedef struct _ClutterPaintNode ClutterPaintNode;
typedef struct _ClutterContent ClutterContent; /* dummy */ typedef struct _ClutterContent ClutterContent; /* dummy */
typedef struct _ClutterScrollActor ClutterScrollActor; typedef struct _ClutterScrollActor ClutterScrollActor;
@ -90,6 +91,8 @@ typedef struct _ClutterInputFocus ClutterInputFocus;
typedef union _ClutterEvent ClutterEvent; typedef union _ClutterEvent ClutterEvent;
typedef enum _ClutterPaintFlag ClutterPaintFlag;
/** /**
* ClutterEventSequence: * ClutterEventSequence:
* *

View File

@ -28,16 +28,10 @@
#include <cairo.h> #include <cairo.h>
#include "clutter/clutter-mutter.h" #include "backends/meta-stage-view.h"
G_BEGIN_DECLS G_BEGIN_DECLS
#define META_TYPE_STAGE_VIEW (meta_stage_view_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaStageView,
meta_stage_view,
META, STAGE_VIEW,
ClutterStageView)
struct _MetaStageViewClass struct _MetaStageViewClass
{ {

View File

@ -34,6 +34,8 @@ typedef struct _MetaStageViewPrivate
guint notify_presented_handle_id; guint notify_presented_handle_id;
CoglFrameClosure *frame_cb_closure; CoglFrameClosure *frame_cb_closure;
int inhibit_cursor_overlay_count;
} MetaStageViewPrivate; } MetaStageViewPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaStageView, meta_stage_view, G_DEFINE_TYPE_WITH_PRIVATE (MetaStageView, meta_stage_view,
@ -130,6 +132,19 @@ meta_stage_view_constructed (GObject *object)
G_OBJECT_CLASS (meta_stage_view_parent_class)->constructed (object); G_OBJECT_CLASS (meta_stage_view_parent_class)->constructed (object);
} }
static ClutterPaintFlag
meta_stage_view_get_default_paint_flags (ClutterStageView *clutter_view)
{
MetaStageView *view = META_STAGE_VIEW (clutter_view);
MetaStageViewPrivate *priv =
meta_stage_view_get_instance_private (view);
if (priv->inhibit_cursor_overlay_count > 0)
return CLUTTER_PAINT_FLAG_NO_CURSORS;
else
return CLUTTER_PAINT_FLAG_NONE;
}
static void static void
meta_stage_view_init (MetaStageView *view) meta_stage_view_init (MetaStageView *view)
{ {
@ -143,9 +158,13 @@ static void
meta_stage_view_class_init (MetaStageViewClass *klass) meta_stage_view_class_init (MetaStageViewClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_CLASS (klass);
object_class->constructed = meta_stage_view_constructed; object_class->constructed = meta_stage_view_constructed;
object_class->dispose = meta_stage_view_dispose; object_class->dispose = meta_stage_view_dispose;
view_class->get_default_paint_flags =
meta_stage_view_get_default_paint_flags;
} }
ClutterDamageHistory * ClutterDamageHistory *
@ -202,3 +221,23 @@ meta_stage_view_perform_fake_swap (MetaStageView *view,
notify_presented_idle, notify_presented_idle,
closure, g_free); closure, g_free);
} }
void
meta_stage_view_inhibit_cursor_overlay (MetaStageView *view)
{
MetaStageViewPrivate *priv =
meta_stage_view_get_instance_private (view);
priv->inhibit_cursor_overlay_count++;
}
void
meta_stage_view_uninhibit_cursor_overlay (MetaStageView *view)
{
MetaStageViewPrivate *priv =
meta_stage_view_get_instance_private (view);
g_return_if_fail (priv->inhibit_cursor_overlay_count > 0);
priv->inhibit_cursor_overlay_count--;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2022 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_STAGE_VIEW_H
#define META_STAGE_VIEW_H
#include "clutter/clutter-mutter.h"
#define META_TYPE_STAGE_VIEW (meta_stage_view_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaStageView,
meta_stage_view,
META, STAGE_VIEW,
ClutterStageView)
void meta_stage_view_inhibit_cursor_overlay (MetaStageView *view);
void meta_stage_view_uninhibit_cursor_overlay (MetaStageView *view);
#endif /* META_STAGE_VIEW_H */

View File

@ -379,13 +379,33 @@ queue_redraw_clutter_rect (MetaStage *stage,
.width = ceilf (rect->size.width), .width = ceilf (rect->size.width),
.height = ceilf (rect->size.height) .height = ceilf (rect->size.height)
}; };
GList *l;
/* Since we're flooring the coordinates, we need to enlarge the clip by the /* Since we're flooring the coordinates, we need to enlarge the clip by the
* difference between the actual coordinate and the floored value */ * difference between the actual coordinate and the floored value */
clip.width += ceilf (rect->origin.x - clip.x) * 2; clip.width += ceilf (rect->origin.x - clip.x) * 2;
clip.height += ceilf (rect->origin.y - clip.y) * 2; clip.height += ceilf (rect->origin.y - clip.y) * 2;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); for (l = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage));
l;
l = l->next)
{
ClutterStageView *view = l->data;
cairo_rectangle_int_t view_layout;
cairo_rectangle_int_t view_clip;
if (clutter_stage_view_get_default_paint_flags (view) &
CLUTTER_PAINT_FLAG_NO_CURSORS)
continue;
clutter_stage_view_get_layout (view, &view_layout);
if (meta_rectangle_intersect (&clip, &view_layout, &view_clip))
{
clutter_stage_view_add_redraw_clip (view, &view_clip);
clutter_stage_view_schedule_update (view);
}
}
} }
static void static void