Skip to content

Add explicit display backend configuration - #345

Draft
chruffins wants to merge 9 commits into
mainfrom
hypeship/wayland-display-backend
Draft

Add explicit display backend configuration#345
chruffins wants to merge 9 commits into
mainfrom
hypeship/wayland-display-backend

Conversation

@chruffins

@chruffins chruffins commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

summary

  • retain native Wayland browser startup and CDP display controls
  • add a Weston-native capture helper using the compositor screenshooter protocol and persistent wl_shm frames
  • switch Weston to desktop-shell so the capture protocol is available
  • wire Neko startup to select the Wayland capture helper when DISPLAY_BACKEND=wayland
  • keep the Neko image configurable for local validation while the companion Neko change is reviewed

validation

  • full kernel-headful image build passed
  • helper compiled with -Wall -Wextra -Werror
  • Weston + Chromium produced 320x240 raw frames at 5 FPS
  • Wayland and X11 API tests from the existing commits passed

dependency

The default Neko image remains unchanged until the companion Wayland backend change is released. Wayland WebRTC stays disabled in deployed images until that dependency is available and end-to-end live-view validation passes.


Note

High Risk
Touches display startup, Chromium launch, input/screenshot APIs, and recording capture. Wayland paths change core computer-control and media pipelines; a misconfigured backend can break headful sessions.

Overview
Adds an explicit DISPLAY_BACKEND (x11 default, wayland) so headful Chromium can run on Weston instead of X11, without silently falling back.

On Wayland, the wrapper starts Weston, Chromium uses Ozone/Wayland, and computer APIs (mouse, keys, type, scroll, drag, screenshot, resize) go through CDP rather than xdotool/X11. Recordings and CDP-monitor screenshots also capture via CDP PNG frames instead of x11grab.

The image builds a Weston screenshooter helper (weston-capture) and Neko is started with Wayland capture flags when that backend is selected. The Neko base image is parameterized for local validation; X11 remains the production default.

Reviewed by Cursor Bugbot for commit a38b174. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread server/cmd/api/api/display.go
}

func (s *ApiService) doPressKey(ctx context.Context, body oapi.PressKeyRequest) error {
if s.usesWayland() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Mouse position still uses xdotool

Medium Severity

GetMousePosition always runs xdotool getmouselocation and is not routed through the Wayland CDP input path. With DISPLAY_BACKEND=wayland there is no X display, so the endpoint returns 500 instead of the pointer position.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 793b3fb. Configure here.

}
final := chromiumflags.MergeFlagsWithRuntimeTokens(baseFlags, runtimeTokens)
final = withDefaultPrivateNetworkBypass(final)
final = append(final, displayFlags...)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ozone flags overwrite enable-features

Medium Severity

Wayland display flags are appended after merged CHROMIUM_FLAGS, including a separate --enable-features=UseOzonePlatform. Chromium last-token-wins for --enable-features, so that token replaces any earlier feature list from base or runtime flags rather than merging with it.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by learned rule: Chromium flag merging must preserve last-token-wins ordering

Reviewed by Cursor Bugbot for commit 793b3fb. Configure here.

events = append(events, cdpclient.MouseEvent{Type: "mouseMoved", X: float64(point[0]), Y: float64(point[1])})
}
end := body.Path[len(body.Path)-1]
events = append(events, cdpclient.MouseEvent{Type: "mouseReleased", X: float64(end[0]), Y: float64(end[1]), Button: button, ClickCount: 1})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wayland drag omits pressed buttons

Medium Severity

Wayland drag sends mouseMoved events with coordinates only. CDP Input.dispatchMouseEvent needs a non-zero buttons bitmask (and usually button) on moves between press and release, otherwise pages see hover rather than a drag.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 793b3fb. Configure here.

}); err != nil {
return &executionError{msg: fmt.Sprintf("failed to press Wayland key: %v", err)}
}
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wayland key path ignores hold duration

Medium Severity

doPressKeyWayland immediately emits paired keyDown/keyUp and never reads duration or hold_keys. Unlike click types, which are rejected as unsupported, those fields are silently dropped so held keys and modifiers do not behave as on X11.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 793b3fb. Configure here.

}
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Recording dies on first capture error

High Severity

streamFrames returns on the first CaptureFrame or write error, which closes ffmpeg stdin and ends the Wayland recording. Transient CDP failures (devtools not ready, navigation, Chromium restart, oversized screenshot frames) therefore stop capture for good instead of retrying, with no error recorded on the recorder.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5a7066d. Configure here.

Comment thread server/cmd/api/main.go
captureClient = nil
}
return frame, err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hung capture blocks all recordings

Medium Severity

Wayland CaptureFrame holds a process-wide mutex for the full CDP screenshot and uses a non-cancelable context with no timeout. If DevTools stalls, streamFrames never observes exited, the mutex stays locked, and later recordings (and further frames) block indefinitely.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5a7066d. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 7 total unresolved issues (including 6 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c415be4. Configure here.

@@ -0,0 +1,8 @@
[program:weston]
command=/bin/bash -c 'exec weston --backend=headless-backend.so --use-pixman --debug --shell=desktop-shell.so --socket="${WAYLAND_DISPLAY:-wayland-0}" --width="${WIDTH:-1920}" --height="${HEIGHT:-1080}" --idle-time=0'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Desktop shell restores window chrome

Medium Severity

Switching Weston from kiosk-shell.so to desktop-shell.so drops the always-fullscreen kiosk behavior. Desktop shell defaults to a top panel and window decorations, so Chromium no longer fills the configured WIDTH×HEIGHT output. Compositor capture then includes that chrome, and CDP viewport size can fall short of the intended display (for example 1920×1024 versus 1920×1080).

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c415be4. Configure here.

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