Skip to content

surface: Always set PHASE_PAINT as pending when updates are scheduled

Carlos Garnacho requested to merge wip/carlosg/stuck-frames into master

At times (most often when closing subsurfaces that are scheduling relayouts) the PHASE_PAINT handling gets broken with the following sequence:

  1. Surface receives wl_callback.done for the previous frame. Surface is thawed.
  2. A new update on the surface is scheduled. PHASE_PAINT is requested directly on the frame clock. priv->pending_phase is left unset in the surface.
  3. Surface gets frozen
  4. Frame clock processes the update scheduled at 2. The surface is frozen, so paint is prevented. PHASE_PAINT is considered handled.
  5. Compositor emits wl_callback.done again. Surface is thawed.
  6. At this point the machinery is off
    • The surface didn't paint but has pending update regions
    • priv->draw_needed is set in the toplevel and other portions of the widget tree
    • So queueing redraws is ineffective at eventually calling gdk_surface_schedule_update() again on the toplevel surface.
    • We don't paint anymore, so this broken state is not flushed until other subsurface changes manage to schedule the missing update.

To fix this, always set PHASE_PAINT in priv->pending_phase when doing gdk_surface_schedule_update(). If the frame clock turns around before the surface is thawed, it will still be waiting to be processed the next iteration.

Fixes: #3750 (closed)

Merge request reports