Skip to content

window: don't allocate a swapchain for 0x0 windows, handle reconfigure/next failures - #130

Closed
kallegrens wants to merge 1 commit into
hyprwm:mainfrom
kallegrens:fix/zero-size-swapchain
Closed

window: don't allocate a swapchain for 0x0 windows, handle reconfigure/next failures#130
kallegrens wants to merge 1 commit into
hyprwm:mainfrom
kallegrens:fix/zero-size-swapchain

Conversation

@kallegrens

Copy link
Copy Markdown

Problem

A Wayland compositor may send wp_fractional_scale_v1.preferred_scale before the first xdg configure, i.e. while the window's logical size is still 0x0. On such an event, CWaylandWindow's scale handler calls onScaleUpdate()configure(m_waylandState.logicalSize)resizeSwapchain({0,0}), which:

  1. calls CSwapchain::reconfigure() with .length = 2 and a zero size — under current aquamarine this clears the swapchain but leaves options.length = 2 with zero buffers,
  2. ignores the reconfigure() return value, and
  3. unconditionally feeds next() results into CWaylandBuffer, which would also dereference a null buffer at buffer->dmabuf() if next() ever returned nullptr.

The result is a guaranteed std::out_of_range crash on the first render attempt:

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 1) >= this->size() (which is 0)

#8  Aquamarine::CSwapchain::next(int*)
#9  Hyprtoolkit::IWaylandWindow::resizeSwapchain(Hyprutils::Math::Vector2D const&)
#10 Hyprtoolkit::IWaylandWindow::configure(Hyprutils::Math::Vector2D const&, unsigned int)
#11 Hyprtoolkit::_CWpFractionalScaleV1PreferredScale(void*, void*, unsigned int)

Reproduced 100% of the time with hyprpolkitagent under niri on a fractional-scaled (150%) output.

Fix

In IWaylandWindow::resizeSwapchain():

  • return early when the pixel size is zero — there is nothing to allocate yet; the subsequent xdg configure with the real size goes through the full path as before,
  • check the reconfigure() return value and bail out on failure instead of proceeding with a stale swapchain,
  • check next() for nullptr before constructing a CWaylandBuffer (which would null-deref otherwise).

After this, the previously guaranteed crash under niri + 150% fractional scaling is gone and the window renders/authenticates correctly.

Note: there is also an aquamarine-side inconsistency (the swapchain clearing branch leaves options.length > 0 with zero buffers), which I've fixed separately in hyprwm/aquamarine — see hyprwm/aquamarine#379. The two are independent: either one alone stops the crash, but both should hold the invariant.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

Hi @kallegrens,

Thanks for your contribution! Unfortunately, Hyprland and hypr* no longer
accept contributions from unvouched contributors.

To get vouched, please see our contributing guide at wiki.hypr.land/Contributing-and-Debugging

This PR has been closed automatically and will not be re-opened.

@github-actions github-actions Bot closed this Sep 3, 2026
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.

1 participant