From e8997cb05e7f9da6c9c6951ea06262d937de4d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 3 Aug 2020 21:36:20 +0200 Subject: wasm: factor visual viewport scale into dpr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default, mobile browsers create a (layout) viewport much wider than the visual viewport in order to be compatible with web pages created with desktop browsers in mind. This means that the default view is zoomed out. This zoom is not reflected in window.devicePixelRatio, and Qt ends up setting the canvas render size to be larger than actually needed. The window.visualViewport.scale property reflects this “mobile” zoom level: add it as a devicePixelRatio factor. (The value will be less than 1 when zoomed out). User pinch-to-zoom may change the zoom level and resize the visual viewport; install a resize handler as well. For now we limit the devicePixelRatio value in order to avoid creating gigantic backing store images - this is something we can revisit later on. Pick-to: 5.15 Task-number: QTBUG-85662 Change-Id: I96db6121fe17a6c213216e04e4724efc93a9b66a Reviewed-by: Lorn Potter --- src/plugins/platforms/wasm/qwasmintegration.cpp | 14 ++++++++++++++ src/plugins/platforms/wasm/qwasmscreen.cpp | 23 +++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index 0d196ec099..15d396f479 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -87,6 +87,12 @@ static void qtUpdateDpi() QWasmIntegration::get()->updateDpi(); } +static void resizeAllScreens(emscripten::val event) +{ + Q_UNUSED(event); + QWasmIntegration::get()->resizeAllScreens(); +} + EMSCRIPTEN_BINDINGS(qtQWasmIntegraton) { function("qtBrowserBeforeUnload", &browserBeforeUnload); @@ -94,6 +100,7 @@ EMSCRIPTEN_BINDINGS(qtQWasmIntegraton) function("qtRemoveCanvasElement", &removeCanvasElement); function("qtResizeCanvasElement", &resizeCanvasElement); function("qtUpdateDpi", &qtUpdateDpi); + function("qtResizeAllScreens", &resizeAllScreens); } QWasmIntegration *QWasmIntegration::s_instance; @@ -136,6 +143,13 @@ QWasmIntegration::QWasmIntegration() return 0; }; emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, 1, onWindowResize); + + // install visualViewport resize handler which picks up size and scale change on mobile. + emscripten::val visualViewport = emscripten::val::global("window")["visualViewport"]; + if (!visualViewport.isUndefined()) { + visualViewport.call("addEventListener", val("resize"), + val::module_property("qtResizeAllScreens")); + } } QWasmIntegration::~QWasmIntegration() diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index 0f1fd886d0..be9d35cdef 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -127,12 +127,23 @@ QDpi QWasmScreen::logicalDpi() const qreal QWasmScreen::devicePixelRatio() const { - // FIXME: The effective device pixel ratio may be different from the - // HTML window dpr if the OpenGL driver/GPU allocates a less than - // full resolution surface. Use emscripten_webgl_get_drawing_buffer_size() - // and compute the dpr instead. - double htmlWindowDpr = emscripten::val::global("window")["devicePixelRatio"].as(); - return qreal(htmlWindowDpr); + // window.devicePixelRatio gives us the scale factor between CSS and device pixels. + // This property reflects hardware configuration, and also browser zoom on desktop. + // + // window.visualViewport.scale gives us the zoom factor on mobile. If the html page is + // configured with "" then this scale + // factor will be 1. Omitting the viewport configuration typically results on a zoomed-out + // viewport, with a scale factor <1. User pinch-zoom will change the scale factor; an event + // handler is installed in the QWasmIntegration constructor. Changing zoom level on desktop + // does not appear to change visualViewport.scale. + // + // The effective devicePixelRatio is the product of these two scale factors, upper-bounded + // by window.devicePixelRatio in order to avoid e.g. allocating a 10x widget backing store. + double dpr = emscripten::val::global("window")["devicePixelRatio"].as(); + emscripten::val visualViewport = emscripten::val::global("window")["visualViewport"]; + double scale = visualViewport.isUndefined() ? 1.0 : visualViewport["scale"].as(); + double effectiveDevicePixelRatio = std::min(dpr * scale, dpr); + return qreal(effectiveDevicePixelRatio); } QString QWasmScreen::name() const -- cgit v1.2.3