Skip to content

Keep hover and pointer overrides on desktop set_viewport - #665

Merged
route merged 3 commits into
rubycdp:mainfrom
top-sigrid:fix/664-set-viewport-touch-reset
Oct 27, 2026
Merged

route merged 3 commits into
rubycdp:mainfrom
top-sigrid:fix/664-set-viewport-touch-reset

Conversation

@top-sigrid

@top-sigrid top-sigrid commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #664.

Since #618, Page#set_viewport sends Emulation.setTouchEmulationEnabled on every call, so a desktop viewport sends enabled: false, and so does Page#resize. Chrome handles enabled: false by resetting hover and pointer to the input devices it detected, even if touch emulation was never on. That undoes --blink-settings overrides such as the hover and pointer flag recommended in rubycdp/cuprite#282: on headless Linux, (hover: hover) and (pointer: fine) stop matching after set_viewport or resize.

set_viewport now sends enabled: false only when the page goes back to a desktop viewport after set_viewport(mobile: true), and only once; mobile: true still turns touch emulation on as before. That's the rule Chromium follows for its own resets since Chrome 141 (a65c088), and Playwright never sends enabled: false at all.

Not covered: a page switched from mobile: true back to desktop still has to get enabled: false, so it still loses --blink-settings hover and pointer. No CDP command sets them directly.

Behavior change: touch emulation turned on with a raw page.command is no longer turned off by a desktop set_viewport, as in 0.18.0.

Specs:

  • The new :launch spec starts Chrome with primaryPointerType=2,availablePointerTypes=2 and checks (pointer: coarse) right after set_viewport. Neither Linux nor macOS reports a coarse pointer by itself, so the reset shows on both.
  • A second spec checks that going back from mobile: true still turns touch emulation off. It passes with and without the fix and guards the branch that still sends enabled: false.
  • A unit spec checks that enabled: false is sent only once after a mobile viewport, not on every later desktop call.

Checks, rebased on 082de04:

  • Without the fix, the :launch spec and the unit spec fail on macOS (Chrome 155.0.8059.40) and on Linux (Chrome for Testing 155.0.8059.84 in Docker).
  • With the fix, bundle exec rake on macOS: 670 examples, 0 failures, 4 pending. spec/unit/page_spec.rb and spec/page_spec.rb on Linux: 31 examples, 0 failures.

Since rubycdp#618, set_viewport sent Emulation.setTouchEmulationEnabled on every call, so every desktop
viewport and every resize sent enabled: false. Chrome answers that by resetting hover and pointer
to the detected input devices, even if touch emulation was never on, which undoes --blink-settings
overrides. On headless Linux, which has no input devices, (hover: hover) and (pointer: fine)
stopped matching after set_viewport or resize.

set_viewport now sends enabled: false only when the page goes back to a desktop viewport after
set_viewport(mobile: true), and only once. Chromium follows the same rule for its own resets since
Chrome 141 (Chromium commit a65c088).

Fixes rubycdp#664
route added 2 commits October 27, 2026 16:09
…on as is

A desktop set_viewport or resize no longer sends setTouchEmulationEnabled, so --blink-settings hover and pointer stay.
mobile: true still turns touch on and an explicit mobile: false turns it off. Replaces the per-page touch emulation
state, so the unit spec for it is removed. Refs rubycdp#664
@route

route commented Oct 27, 2026

Copy link
Copy Markdown
Member

Thanks for the thorough investigation, the repro and the Chromium pointers made this easy to verify.

I pushed two commits on top of your branch: a merge of main (the CHANGELOG conflicted after the 0.20.0 release) and a change to how the fix works.

Instead of tracking @touch_emulation_enabled on the page, set_viewport's mobile: now defaults to nil:

  • mobile: true emulates a mobile device with touch, as before
  • mobile: false emulates a desktop and turns touch emulation off
  • nil, the default, emulates a desktop and leaves touch emulation as is, so resize and a plain set_viewport(width:, height:) no longer send setTouchEmulationEnabled at all

Why: whether to send enabled: false depends on what happened earlier on the page, and the page object shouldn't have to remember that. CDP has no getter for touch emulation, and reading navigator.maxTouchPoints before every resize costs a round trip. With nil, the caller says what they want: leave mobile: out and hover/pointer stay, pass false to go back from a mobile viewport.

Your feature specs are kept as they were; the --blink-settings one moved under a "when mobile is not given" context. The unit spec was removed, since it checked the per-page state that no longer exists. The emulation docs describe the nil default and the hover/pointer reset that mobile: false causes.

@route
route merged commit 3f6a173 into rubycdp:main Oct 27, 2026
7 checks passed
@route

route commented Oct 27, 2026

Copy link
Copy Markdown
Member

I'm merging but let me know if I miss anything in my version

@top-sigrid

Copy link
Copy Markdown
Contributor Author

Your feature specs are kept as they were; the --blink-settings one moved under a "when mobile is not given" context. The unit spec was removed, since it checked the per-page state that no longer exists. The emulation docs describe the nil default and the hover/pointer reset that mobile: false causes.

Thanks for getting to this so quickly! I'll have a look over your changes, but that seems sensible on first sight.

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.

set_viewport and resize undo --blink-settings hover/pointer overrides since 0.19.0

2 participants