output: create session lock surface before mode commit#1025
Merged
Conversation
When an output appears during resume with an active session lock, Hyprland
registers the wl_output global at size {0, 0} while the DRM session is
still inactive. The size guard in createSessionLockSurface() rejected that
state, leaving m_sessionLockSurface null. When the session activated,
modeChanged fired and wl_output.done arrived with a valid mode. The setDone
handler created the surface but then had to go through get_lock_surface and
wait for Hyprland to respond with configure before rendering, so the lockdead
fallback texture stayed visible for that extra exchange.
Remove the size guard and handle size {0, 0} in configure() instead:
ack the serial first, then return early if the size is not positive. This
avoids a wp_viewport.set_destination(0, 0) protocol error and allows
Hyprland's monitorMode listener on SSessionLockSurface to fire
sendConfigure() directly on modeChanged without waiting for another
get_lock_surface request.
PointerDilemma
approved these changes
May 26, 2026
PointerDilemma
left a comment
Collaborator
There was a problem hiding this comment.
Thank you for digging into this and describing it nicely in your PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ran into this while connecting my dock after a suspend with the screen locked. The external monitors showed the lockdead texture briefly instead of the lock screen, which looked like the session had unlocked.
When a new output appears during resume, Hyprland registers the wl_output global at size {0, 0} while the DRM session is still inactive. Commits fail until the session activates, so the output enters the global registry with no valid mode. The size guard in
createSessionLockSurface()bailed out in that state and leftm_sessionLockSurfacenull.Once the session activated and the real mode landed,
wl_output.donearrived and thesetDonehandler created the surface. But then hyprlock had to go throughget_lock_surface, wait for Hyprland to respond withconfigure, and only then render. The lockdead fallback texture was visible for the whole duration of that extra wait.The actual fix is simpler than it sounds. Hyprland registers a
monitorModelistener onSSessionLockSurfacewhen it receivesget_lock_surface. If the surface exists before the mode change,modeChangedfiressendConfigure()directly without needing another full exchange. Creating the surface upfront is all that is needed.Here is what the Hyprland log looked like during the bad resume:
Remove the size guard and move the handling into
configure()instead. Ack the serial first, then return early if the size is not positive. That avoids awp_viewport.set_destination(0, 0)protocol error and a zero dimensionwl_egl_window_create()call, both of which would have crashed or killed the connection if we had let them through.