diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f3912c3..7fb4d491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ### Changed ### Fixed +- `set_viewport` and `resize` turned touch emulation off on every desktop viewport, which reset hover and pointer and + undid `--blink-settings` overrides. `mobile:` defaults to `nil` and leaves touch as is, `false` turns it off [#664] ### Removed diff --git a/docs/14-emulation.md b/docs/14-emulation.md index c6d9d5b7..f796382b 100644 --- a/docs/14-emulation.md +++ b/docs/14-emulation.md @@ -14,7 +14,8 @@ Overrides device screen dimensions and emulates viewport. When `:mobile` is * :width `Integer`, viewport width. `0` by default * :height `Integer`, viewport height. `0` by default * :scale_factor `Float`, device scale factor. `0` by default - * :mobile `Boolean`, whether to emulate mobile device and enable touch. `false` by default + * :mobile `Boolean | nil`, `true` emulates a mobile device with touch, `false` a desktop without touch, `nil` a + desktop and leaves touch emulation as is. `nil` by default ```ruby page.set_viewport(width: 1000, height: 600, scale_factor: 3) @@ -29,3 +30,7 @@ size preset: ```ruby page.set_viewport(mobile: true) ``` + +Turning touch emulation off with `mobile: false` makes Chrome reset hover and pointer media features to the +detected input devices, which undoes `--blink-settings` overrides such as `primaryHoverType` until the next +navigation. Leave `:mobile` out unless the page was switched to mobile before. diff --git a/lib/ferrum/page.rb b/lib/ferrum/page.rb index 5c5d3c04..3597d5b0 100644 --- a/lib/ferrum/page.rb +++ b/lib/ferrum/page.rb @@ -191,14 +191,12 @@ def close_connection # # @param [Float] scale_factor device scale factor value. 0 disables the override # - # @param [Boolean] mobile whether to emulate mobile device and enable touch + # @param [Boolean, nil] mobile `true` emulates a mobile device with touch, `false` a desktop without touch, `nil` + # a desktop and leaves touch emulation as is. Turning touch off resets hover and pointer to the detected input + # devices, which undoes `--blink-settings` overrides until the next navigation # - def set_viewport(width: 0, height: 0, scale_factor: 0, mobile: false) - command( - "Emulation.setTouchEmulationEnabled", - enabled: mobile, - maxTouchPoints: 1 - ) + def set_viewport(width: 0, height: 0, scale_factor: 0, mobile: nil) + command("Emulation.setTouchEmulationEnabled", enabled: mobile, maxTouchPoints: 1) unless mobile.nil? command( "Emulation.setDeviceMetricsOverride", @@ -206,7 +204,7 @@ def set_viewport(width: 0, height: 0, scale_factor: 0, mobile: false) width: width, height: height, deviceScaleFactor: scale_factor, - mobile: mobile + mobile: mobile || false ) end diff --git a/sig/ferrum/page.rbs b/sig/ferrum/page.rbs index 259aa687..b73620fe 100644 --- a/sig/ferrum/page.rbs +++ b/sig/ferrum/page.rbs @@ -57,7 +57,7 @@ module Ferrum def close_connection: () -> void - def set_viewport: (?width: ::Integer, ?height: ::Integer, ?scale_factor: ::Float, ?mobile: bool) -> Hash[String, untyped] + def set_viewport: (?width: ::Integer, ?height: ::Integer, ?scale_factor: ::Float, ?mobile: bool?) -> Hash[String, untyped] def resize: (?width: ::Numeric?, ?height: ::Numeric?, ?fullscreen: bool) -> Hash[String, untyped] diff --git a/spec/page_spec.rb b/spec/page_spec.rb index e73a5fee..272a6d57 100644 --- a/spec/page_spec.rb +++ b/spec/page_spec.rb @@ -305,6 +305,32 @@ def is_mobile? end.not_to(change { is_mobile? }) end end + + context "when mobile is not given" do + it "keeps the pointer type set with --blink-settings", :launch do + browser = Ferrum::Browser.new(browser_options: { "blink-settings" => "primaryPointerType=2,availablePointerTypes=2" }) + browser.go_to(base_url) + + expect do + browser.set_viewport(width: 500, height: 300) + end.not_to(change { browser.evaluate("matchMedia('(pointer: coarse)').matches") }.from(true)) + ensure + browser&.quit + end + end + + context "when mobile was true before" do + it "disables touch/mobile emulation again" do + page.go_to("/") + page.set_viewport(mobile: true) + page.reload + + expect do + page.set_viewport(mobile: false) + page.reload + end.to change { is_mobile? }.from(true).to(false) + end + end end describe "#on" do