clutter: Do not check redraw area for pointer repicks
This looks like a relic of glReadPixels-based picking, the pointer might well be outside redrawn areas, yet still require a device update (e.g. in order to reflect the actor layout changes in the "clear area" info). Instead, always update all devices that are inside the view after relayouts, the tracking on the need for that update is now done on each ClutterStageView, instead of globally in the ClutterStage. This theoretically fixes situations where pointers might miss updating their "clear area" after the actor tree changed. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2117 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2257>
This commit is contained in:
parent
b31fb804df
commit
dbfde95c5c
@ -75,7 +75,8 @@ void _clutter_stage_maybe_setup_viewport (ClutterStage
|
|||||||
ClutterStageView *view);
|
ClutterStageView *view);
|
||||||
void clutter_stage_maybe_relayout (ClutterActor *stage);
|
void clutter_stage_maybe_relayout (ClutterActor *stage);
|
||||||
void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
|
void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
|
||||||
GSList * clutter_stage_find_updated_devices (ClutterStage *stage);
|
GSList * clutter_stage_find_updated_devices (ClutterStage *stage,
|
||||||
|
ClutterStageView *view);
|
||||||
void clutter_stage_update_devices (ClutterStage *stage,
|
void clutter_stage_update_devices (ClutterStage *stage,
|
||||||
GSList *devices);
|
GSList *devices);
|
||||||
void clutter_stage_finish_layout (ClutterStage *stage);
|
void clutter_stage_finish_layout (ClutterStage *stage);
|
||||||
|
@ -79,4 +79,6 @@ void clutter_stage_view_notify_presented (ClutterStageView *view,
|
|||||||
CLUTTER_EXPORT
|
CLUTTER_EXPORT
|
||||||
void clutter_stage_view_notify_ready (ClutterStageView *view);
|
void clutter_stage_view_notify_ready (ClutterStageView *view);
|
||||||
|
|
||||||
|
void clutter_stage_view_invalidate_input_devices (ClutterStageView *view);
|
||||||
|
|
||||||
#endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
|
#endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
|
||||||
|
@ -93,6 +93,7 @@ typedef struct _ClutterStageViewPrivate
|
|||||||
|
|
||||||
guint dirty_viewport : 1;
|
guint dirty_viewport : 1;
|
||||||
guint dirty_projection : 1;
|
guint dirty_projection : 1;
|
||||||
|
guint needs_update_devices : 1;
|
||||||
} ClutterStageViewPrivate;
|
} ClutterStageViewPrivate;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageView, clutter_stage_view, G_TYPE_OBJECT)
|
G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageView, clutter_stage_view, G_TYPE_OBJECT)
|
||||||
@ -1176,7 +1177,8 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
|||||||
|
|
||||||
clutter_stage_finish_layout (stage);
|
clutter_stage_finish_layout (stage);
|
||||||
|
|
||||||
devices = clutter_stage_find_updated_devices (stage);
|
if (priv->needs_update_devices)
|
||||||
|
devices = clutter_stage_find_updated_devices (stage, view);
|
||||||
|
|
||||||
frame = CLUTTER_FRAME_INIT;
|
frame = CLUTTER_FRAME_INIT;
|
||||||
|
|
||||||
@ -1200,6 +1202,7 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
|||||||
_clutter_stage_window_finish_frame (stage_window, view, &frame);
|
_clutter_stage_window_finish_frame (stage_window, view, &frame);
|
||||||
|
|
||||||
clutter_stage_update_devices (stage, devices);
|
clutter_stage_update_devices (stage, devices);
|
||||||
|
priv->needs_update_devices = FALSE;
|
||||||
|
|
||||||
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
|
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
|
||||||
clutter_stage_emit_after_update (stage, view);
|
clutter_stage_emit_after_update (stage, view);
|
||||||
@ -1522,3 +1525,12 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
|||||||
|
|
||||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_stage_view_invalidate_input_devices (ClutterStageView *view)
|
||||||
|
{
|
||||||
|
ClutterStageViewPrivate *priv =
|
||||||
|
clutter_stage_view_get_instance_private (view);
|
||||||
|
|
||||||
|
priv->needs_update_devices = TRUE;
|
||||||
|
}
|
||||||
|
@ -127,7 +127,6 @@ struct _ClutterStagePrivate
|
|||||||
|
|
||||||
int update_freeze_count;
|
int update_freeze_count;
|
||||||
|
|
||||||
gboolean needs_update_devices;
|
|
||||||
gboolean pending_finish_queue_redraws;
|
gboolean pending_finish_queue_redraws;
|
||||||
|
|
||||||
GHashTable *pointer_devices;
|
GHashTable *pointer_devices;
|
||||||
@ -785,6 +784,19 @@ clutter_stage_dequeue_actor_relayout (ClutterStage *stage,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_invalidate_views_devices (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterStageView *view = l->data;
|
||||||
|
|
||||||
|
clutter_stage_view_invalidate_input_devices (view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clutter_stage_maybe_relayout (ClutterActor *actor)
|
clutter_stage_maybe_relayout (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
@ -832,36 +844,33 @@ clutter_stage_maybe_relayout (ClutterActor *actor)
|
|||||||
CLUTTER_NOTE (ACTOR, "<<< Completed recomputing layout of %d subtrees", count);
|
CLUTTER_NOTE (ACTOR, "<<< Completed recomputing layout of %d subtrees", count);
|
||||||
|
|
||||||
if (count)
|
if (count)
|
||||||
priv->needs_update_devices = TRUE;
|
clutter_stage_invalidate_views_devices (stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList *
|
GSList *
|
||||||
clutter_stage_find_updated_devices (ClutterStage *stage)
|
clutter_stage_find_updated_devices (ClutterStage *stage,
|
||||||
|
ClutterStageView *view)
|
||||||
{
|
{
|
||||||
ClutterStagePrivate *priv = stage->priv;
|
ClutterStagePrivate *priv = stage->priv;
|
||||||
GSList *updating = NULL;
|
GSList *updating = NULL;
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
gpointer value;
|
gpointer value;
|
||||||
|
|
||||||
if (!priv->needs_update_devices)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
priv->needs_update_devices = FALSE;
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, priv->pointer_devices);
|
g_hash_table_iter_init (&iter, priv->pointer_devices);
|
||||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||||
{
|
{
|
||||||
PointerDeviceEntry *entry = value;
|
PointerDeviceEntry *entry = value;
|
||||||
ClutterStageView *view;
|
ClutterStageView *pointer_view;
|
||||||
const cairo_region_t *clip;
|
|
||||||
|
|
||||||
view = clutter_stage_get_view_at (stage, entry->coords.x, entry->coords.y);
|
pointer_view = clutter_stage_get_view_at (stage,
|
||||||
if (!view)
|
entry->coords.x,
|
||||||
|
entry->coords.y);
|
||||||
|
if (!pointer_view)
|
||||||
|
continue;
|
||||||
|
if (pointer_view != view)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
clip = clutter_stage_view_peek_redraw_clip (view);
|
updating = g_slist_prepend (updating, entry->device);
|
||||||
if (!clip || cairo_region_contains_point (clip, entry->coords.x, entry->coords.y))
|
|
||||||
updating = g_slist_prepend (updating, entry->device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return updating;
|
return updating;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user