Skip to content

Skip resize + chromium restart when display already matches#255

Merged
rgarcia merged 4 commits into
mainfrom
hypeship/skip-noop-display-resize
May 29, 2026
Merged

Skip resize + chromium restart when display already matches#255
rgarcia merged 4 commits into
mainfrom
hypeship/skip-noop-display-resize

Conversation

@masnwilliams
Copy link
Copy Markdown
Contributor

@masnwilliams masnwilliams commented May 28, 2026

Summary

VM-side companion to the API-side short-circuit. Both PatchDisplay and the multipart ChromiumConfigure (when display is the only thing in the request) currently proceed through the full xrandr/xvfb resize plus a chromium restart even when the requested width/height/refresh-rate already match the current display state. This change detects the no-op and returns success immediately — skipping the idle check, recording stop, resize, and restart.

Sister PR on the API side: kernel/kernel#2233 (skips the configure call entirely when the request matches the pool image default). This PR catches the same case from the VM side, plus any caller that passes a non-default-but-already-current viewport.

Changes

  • Extract resolveDisplayParams so PatchDisplay and chromiumPrepareDisplay share one definition of "the request changes nothing."
  • PatchDisplay returns 200 immediately when changed == false.
  • chromiumPrepareDisplay returns a nil plan, which the caller already handles as skip-apply.

Test plan

  • go test ./cmd/api/api/ — new TestResolveDisplayParams covers matching dims with and without refresh-rate, mismatched width, refresh-rate-only mismatch, partial body, and nil body
  • Manual: deploy to a metro, send PatchDisplay {width:1920,height:1080} to an instance launched at 1920x1080, confirm no chromium restart in supervisor logs and no xrandr/xvfb activity

Note

Medium Risk
Changes core display resize and Chromium configure paths; incorrect sticky refresh-rate state could misclassify real resizes as no-ops, but scope is limited to idempotent display updates.

Overview
PatchDisplay and ChromiumConfigure display prep now treat “already at requested width/height/refresh rate” as a no-op: shared resolveDisplayParams merges the body with current state and sets changed. When nothing would change, PatchDisplay returns 200 immediately (skipping idle checks, recording stop, Xvfb/xrandr/CDP resize, and Chromium restart); chromiumPrepareDisplay returns a nil plan so the configure flow skips display apply.

On headless (Xvfb), xrandr often does not report refresh rate, so the VM adds lastHeadlessRefreshRate (updated on viewport override and after Xvfb resize) and getCurrentResolution falls back to that sticky value when the rate was not parsed—so repeat configure calls with the same non-default rate are recognized as no-ops, not mistaken for a change from the default 60 Hz.

Tests cover resolveDisplayParams cases and sticky refresh-rate behavior.

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

PatchDisplay and the multipart Configure both unconditionally proceeded
through xrandr/xvfb resize plus a chromium restart even when the
requested width/height/refresh-rate already matched the current display
state. Detect the no-op case and return success immediately — skipping
the idle check, recording stop, resize, and restart.

Extract the merge logic into resolveDisplayParams so both handlers share
one definition of "the request changes nothing."

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@masnwilliams masnwilliams marked this pull request as ready for review May 28, 2026 02:15
@firetiger-agent
Copy link
Copy Markdown

Firetiger deploy monitoring skipped

This PR didn't match the auto-monitor filter configured on your GitHub connection:

Any PR that changes the kernel API. Monitor changes to API endpoints (packages/api/cmd/api/) and Temporal workflows (packages/api/lib/temporal) in the kernel repo

Reason: PR modifies VM-side display handling logic, not kernel API endpoints (packages/api/cmd/api/) or Temporal workflows (packages/api/lib/temporal); the companion API-side changes mentioned are in a separate PR.

To monitor this PR anyway, reply with @firetiger monitor this.

@masnwilliams masnwilliams requested a review from hiroTamada May 28, 2026 02:55
Copy link
Copy Markdown
Contributor

@rgarcia rgarcia left a comment

Choose a reason for hiding this comment

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

requesting changes for one behavior gap:

  • server/cmd/api/api/display.go:198 — the no-op check includes refreshRate, but the headless/Xvfb path does not appear to persist or later recover the requested refresh rate. setViewportOverride stores it temporarily, but backgroundResizeXvfb clears that override once width/height match, and getCurrentResolutionFromXrandr falls back to 60 when xrandr output has no _rate suffix. so a headless request like 1280x720@25 can be applied, then after the background resize clears the override, the next identical request sees current as 1280x720@60 and is not treated as a no-op. this undercuts the “all three values equal” behavior for non-60 refresh rates on headless.

suggested fix: either persist the last requested refresh rate for Xvfb after the background resize, or normalize headless refresh semantics explicitly so the no-op comparison uses the same canonical value that future calls will observe.

@hiroTamada
Copy link
Copy Markdown
Contributor

Actually, would it be easier to talk to x-org and xfvb to get the current resolution rather than persisting viewport state in memory?

Xvfb does not surface a refresh rate via xrandr, so
getCurrentResolutionFromXrandr always falls back to 60. After the
background Xvfb resize cleared the viewport override, the next
identical request at a non-default rate (e.g. 1280x720@25) was
not detected as a no-op because the comparison saw 60.

Keep lastHeadlessRefreshRate as a sticky field that survives override
clears, and have getCurrentResolution prefer it whenever xrandr did not
surface a real rate. Set it from every headless apply path
(setViewportOverride, the synchronous PatchDisplay xvfb branch, and the
chromium-configure xvfb branch).
@masnwilliams masnwilliams requested a review from rgarcia May 29, 2026 15:42
@rgarcia rgarcia merged commit 11e1b04 into main May 29, 2026
12 of 13 checks passed
@rgarcia rgarcia deleted the hypeship/skip-noop-display-resize branch May 29, 2026 16:26
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.

3 participants