diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index c07d0399a..a3ee0010c 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -161,6 +161,7 @@ struct _ClutterStagePrivate guint accept_focus : 1; guint motion_events_enabled : 1; guint has_custom_perspective : 1; + guint stage_was_relayout : 1; }; enum @@ -1059,6 +1060,7 @@ _clutter_stage_maybe_relayout (ClutterActor *actor) if (!CLUTTER_ACTOR_IN_RELAYOUT (stage)) { priv->relayout_pending = FALSE; + priv->stage_was_relayout = TRUE; CLUTTER_NOTE (ACTOR, "Recomputing layout"); @@ -1129,6 +1131,58 @@ clutter_stage_do_redraw (ClutterStage *stage) stage); } +static GSList * +_clutter_stage_check_updated_pointers (ClutterStage *stage) +{ + ClutterStagePrivate *priv = stage->priv; + ClutterDeviceManager *device_manager; + GSList *updating = NULL; + const GSList *devices; + cairo_rectangle_int_t clip; + ClutterPoint point; + gboolean has_clip; + + has_clip = _clutter_stage_window_get_redraw_clip_bounds (priv->impl, &clip); + + device_manager = clutter_device_manager_get_default (); + devices = clutter_device_manager_peek_devices (device_manager); + + for (; devices != NULL; devices = devices->next) + { + ClutterInputDevice *dev = devices->data; + + if (clutter_input_device_get_device_mode (dev) != + CLUTTER_INPUT_MODE_MASTER) + continue; + + switch (clutter_input_device_get_device_type (dev)) + { + case CLUTTER_POINTER_DEVICE: + case CLUTTER_TABLET_DEVICE: + case CLUTTER_PEN_DEVICE: + case CLUTTER_ERASER_DEVICE: + case CLUTTER_CURSOR_DEVICE: + if (!clutter_input_device_get_coords (dev, NULL, &point)) + continue; + + if (!has_clip || + (point.x >= clip.x && point.x < clip.x + clip.width && + point.y >= clip.y && point.y < clip.y + clip.height)) + updating = g_slist_prepend (updating, dev); + break; + default: + /* Any other devices don't need checking, either because they + * don't have x/y coordinates, or because they're implicitly + * grabbed on an actor by default as it's the case of + * touch(screens). + */ + break; + } + } + + return updating; +} + /** * _clutter_stage_do_update: * @stage: A #ClutterStage @@ -1141,6 +1195,10 @@ gboolean _clutter_stage_do_update (ClutterStage *stage) { ClutterStagePrivate *priv = stage->priv; + gboolean stage_was_relayout = priv->stage_was_relayout; + GSList *pointers = NULL; + + priv->stage_was_relayout = FALSE; /* if the stage is being destroyed, or if the destruction already * happened and we don't have an StageWindow any more, then we @@ -1161,6 +1219,9 @@ _clutter_stage_do_update (ClutterStage *stage) if (!priv->redraw_pending) return FALSE; + if (stage_was_relayout) + pointers = _clutter_stage_check_updated_pointers (stage); + clutter_stage_maybe_finish_queue_redraws (stage); clutter_stage_do_redraw (stage); @@ -1178,6 +1239,12 @@ _clutter_stage_do_update (ClutterStage *stage) } #endif /* CLUTTER_ENABLE_DEBUG */ + while (pointers) + { + _clutter_input_device_update (pointers->data, NULL, TRUE); + pointers = g_slist_delete_link (pointers, pointers); + } + return TRUE; }