Skip to content

output: create session lock surface before mode commit#1025

Merged
PointerDilemma merged 1 commit into
hyprwm:mainfrom
UncleJ4ck:main
May 28, 2026
Merged

output: create session lock surface before mode commit#1025
PointerDilemma merged 1 commit into
hyprwm:mainfrom
UncleJ4ck:main

Conversation

@UncleJ4ck

@UncleJ4ck UncleJ4ck commented May 21, 2026

Copy link
Copy Markdown
Contributor

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 left m_sessionLockSurface null.

Once the session activated and the real mode landed, wl_output.done arrived and the setDone handler created the surface. But then hyprlock had to go through get_lock_surface, wait for Hyprland to respond with configure, 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 monitorMode listener on SSessionLockSurface when it receives get_lock_surface. If the surface exists before the mode change, modeChanged fires sendConfigure() 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:

Session got deactivated!
drm: Connector DP-3 connected
Monitor DP-3 has NO FALLBACK MODES, and an INVALID one was requested: 2560x1440@59.95Hz
Added new monitor with name DP-3 at [-1, -1] with size [0, 0]
[IWaylandProtocol] Registered global [WLOutput (DP-3)]
...
Session got activated!
Monitor DP-3: requested 2560x1440@59.95Hz, using preferred mode 2560x1440@59.95Hz
drm: Modesetting DP-3 with 2560x1440@59.95Hz

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 a wp_viewport.set_destination(0, 0) protocol error and a zero dimension wl_egl_window_create() call, both of which would have crashed or killed the connection if we had let them through.

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 PointerDilemma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for digging into this and describing it nicely in your PR.

@PointerDilemma PointerDilemma merged commit ab83d0d into hyprwm:main May 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants