Browse Source

Platform: rework DPI awareness and resize event in EmscriptenApp.

By mistake I thought it's the same as in Emscripten's SDL, but there
Emscripten does some emulation to ensure windowSize() ==
framebufferSize().

For the resize event it's possible to hook into the window resize
callback instead of polling for the size every frame, That's much more
efficient.
pull/300/head
Vladimír Vondruš 7 years ago
parent
commit
8254e16c91
  1. 159
      src/Magnum/Platform/EmscriptenApplication.cpp
  2. 198
      src/Magnum/Platform/EmscriptenApplication.h
  3. 7
      src/Magnum/Platform/Sdl2Application.h
  4. 8
      src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp

159
src/Magnum/Platform/EmscriptenApplication.cpp

@ -238,10 +238,13 @@ Vector2 EmscriptenApplication::dpiScaling(const Configuration& configuration) co
return configuration.dpiScaling();
}
/* Take device pixel ratio on Emscripten */
const Vector2 dpiScaling{Implementation::emscriptenDpiScaling()};
Debug{verbose} << "Platform::EmscriptenApplication: physical DPI scaling" << dpiScaling.x();
return dpiScaling;
/* Unlike Sdl2Application, not taking device pixel ratio into account
because here we have window size different from framebuffer size.
However, in order to actually calculate the framebuffer size we need to
query the device pixel ratio. That's done in tryCreate() below, here it
is returning 1.0 to be consistent with behavior on other platforms where
it's either windowSize == 1 */
return Vector2{1.0f};
}
bool EmscriptenApplication::tryCreate(const Configuration& configuration) {
@ -250,19 +253,14 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration) {
return tryCreate(configuration, GLConfiguration{});
}
#endif
if(configuration.windowFlags() & Configuration::WindowFlag::Resizable) {
_flags |= Flag::Resizable;
}
_dpiScaling = dpiScaling(configuration);
if(!configuration.size().isZero()) {
const Vector2i scaledCanvasSize = configuration.size()*_dpiScaling;
emscripten_set_canvas_element_size("#canvas", scaledCanvasSize.x(), scaledCanvasSize.y());
}
/* Resize window and match it to the selected format */
const Vector2i canvasSizei{windowSize()};
_lastKnownCanvasSize = canvasSizei;
const Vector2i size = _dpiScaling*canvasSizei;
emscripten_set_canvas_element_size("#canvas", size.x(), size.y());
setupCallbacks();
setupCallbacks(!!(configuration.windowFlags() & Configuration::WindowFlag::Resizable));
return true;
}
@ -270,11 +268,6 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration) {
#ifdef MAGNUM_TARGET_GL
bool EmscriptenApplication::tryCreate(const Configuration& configuration, const GLConfiguration& glConfiguration) {
CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::EmscriptenApplication::tryCreate(): window with OpenGL context already created", false);
if(configuration.windowFlags() & Configuration::WindowFlag::Resizable) {
_flags |= Flag::Resizable;
}
_dpiScaling = dpiScaling(configuration);
/* Create emscripten WebGL context */
EmscriptenWebGLContextAttributes attrs;
@ -313,11 +306,34 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const
#error unsupported OpenGL ES version
#endif
/* Resize window and match it to the selected format */
const Vector2i canvasSizei{windowSize()};
_lastKnownCanvasSize = canvasSizei;
const Vector2i size = _dpiScaling*canvasSizei;
emscripten_set_canvas_element_size("#canvas", size.x(), size.y());
std::ostream* verbose = _verboseLog ? Debug::output() : nullptr;
/* Fetch device pixel ratio. Together with DPI scaling (which is 1.0 by
default) this will define framebuffer size. See class docs for why is it
done like that. */
_devicePixelRatio = Vector2{Float(emscripten_get_device_pixel_ratio())};
Debug{verbose} << "Platform::EmscriptenApplication: device pixel ratio" << _devicePixelRatio.x();
/* Get CSS canvas size and cache it. This is used later to detect canvas
resizes in emscripten_set_resize_callback() and fire viewport events,
because browsers are only required to fire resize events on the window
and not on particular DOM elements. */
_lastKnownCanvasSize = windowSize();
/* By default Emscripten creates a 300x150 canvas. That's so freaking
random I'm getting mad. Use the real (CSS pixels) canvas size instead,
if the size is not hardcoded from the configuration. This is then
multiplied by the DPI scaling. */
Vector2i canvasSize;
if(!configuration.size().isZero()) {
canvasSize = configuration.size();
} else {
canvasSize = _lastKnownCanvasSize;
Debug{verbose} << "Platform::EmscriptenApplication::tryCreate(): autodetected canvas size" << canvasSize;
}
_dpiScaling = dpiScaling(configuration);
const Vector2i scaledCanvasSize = canvasSize*_dpiScaling*_devicePixelRatio;
emscripten_set_canvas_element_size("#canvas", scaledCanvasSize.x(), scaledCanvasSize.y());
/* Create surface and context */
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context =
@ -334,7 +350,7 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const
CORRADE_INTERNAL_ASSERT_OUTPUT(
emscripten_webgl_make_context_current(context) == EMSCRIPTEN_RESULT_SUCCESS);
setupCallbacks();
setupCallbacks(!!(configuration.windowFlags() & Configuration::WindowFlag::Resizable));
/* Return true if the initialization succeeds */
return _context->tryCreate();
@ -342,20 +358,71 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const
#endif
Vector2i EmscriptenApplication::windowSize() const {
double w, h;
emscripten_get_element_css_size("#canvas", &w, &h);
return {Int(w), Int(h)};
Vector2d size;
/* Emscripten 1.38.27 changed to generic CSS selectors from element IDs
depending on -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 being
set (which we can't detect at compile time). Fortunately, using #canvas
works the same way both in the previous versions and the current one.
Unfortunately, this is also the only value that works the same way for
both. Further details at
https://github.com/emscripten-core/emscripten/pull/7977 */
/** @todo don't hardcode "#canvas" everywhere, make it configurable from outside */
emscripten_get_element_css_size("#canvas", &size.x(), &size.y());
return Vector2i{Math::round(size)};
}
#ifdef MAGNUM_TARGET_GL
Vector2i EmscriptenApplication::framebufferSize() const {
Vector2i size;
/* See above why hardcoded */
emscripten_get_canvas_element_size("#canvas", &size.x(), &size.y());
return size;
}
#endif
void EmscriptenApplication::swapBuffers() {
emscripten_webgl_commit_frame();
}
void EmscriptenApplication::setupCallbacks() {
void EmscriptenApplication::setupCallbacks(bool resizable) {
/* Since 1.38.17 all emscripten_set_*_callback() are macros. Play it safe
and wrap all lambdas in () to avoid the preprocessor getting upset when
seeing commas */
/* Set up the resize callback. Because browsers are only required to fire
resize events on the window and not on particular DOM elements, we need
to cache the last known canvas size and fire the event only if that
changes. Better than polling for this change in every frame like
Sdl2Application does, but still not ideal. */
if(resizable) {
#ifdef EMSCRIPTEN_EVENT_TARGET_WINDOW
const char* target = EMSCRIPTEN_EVENT_TARGET_WINDOW;
#else
const char* target = "#window";
#endif
auto cb = [](int, const EmscriptenUiEvent*, void* userData) -> Int {
EmscriptenApplication& app = *static_cast<EmscriptenApplication*>(userData);
/* See windowSize() for why we hardcode "#canvas" here */
const Vector2i canvasSize{app.windowSize()};
if(canvasSize != app._lastKnownCanvasSize) {
app._lastKnownCanvasSize = canvasSize;
const Vector2i size = canvasSize*app._dpiScaling*app._devicePixelRatio;
emscripten_set_canvas_element_size("#canvas", size.x(), size.y());
ViewportEvent e{canvasSize,
#ifdef MAGNUM_TARGET_GL
app.framebufferSize(),
#endif
app._dpiScaling, app._devicePixelRatio};
app.viewportEvent(e);
app._flags |= Flag::Redraw;
}
return false; /** @todo what does ignoring a resize event mean? */
};
emscripten_set_resize_callback(target, this, false, cb);
}
/* See windowSize() for why we hardcode "#canvas" here */
emscripten_set_mousedown_callback("#canvas", this, false,
([](int, const EmscriptenMouseEvent* event, void* userData) -> Int {
MouseEvent e{event};
@ -483,38 +550,10 @@ EmscriptenApplication::GLConfiguration::GLConfiguration():
#endif
void EmscriptenApplication::mainLoopIteration() {
/* The resize event is not fired on window resize, so poll for the canvas
size here. But only if the window was requested to be resizable, to
avoid resizing the canvas when the user doesn't want that. Related
issue: https://github.com/kripken/emscripten/issues/1731
As this is caused by the DOM3 events spec only requiring browsers to
fire the resize event for `window` not generally for all DOM elemenets,
it also applies to `emscripten_set_resize_callback`. */
if(_flags & Flag::Resizable) {
/* Emscripten 1.38.27 changed to generic CSS selectors from element
IDs depending on -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1
being set (which we can't detect at compile time). See above for the
reason why we hardcode #canvas here. */
const Vector2i canvasSizei{windowSize()};
if(canvasSizei != _lastKnownCanvasSize) {
_lastKnownCanvasSize = canvasSizei;
const Vector2i size = _dpiScaling*canvasSizei;
emscripten_set_canvas_element_size("#canvas", size.x(), size.y());
#ifdef MAGNUM_TARGET_GL
ViewportEvent e{size, size, _dpiScaling};
#else
ViewportEvent e{size, _dpiScaling};
#endif
viewportEvent(e);
_flags |= Flag::Redraw;
}
}
if(!(_flags & Flag::Redraw)) return;
if(_flags & Flag::Redraw) {
_flags &= ~Flag::Redraw;
drawEvent();
}
_flags &= ~Flag::Redraw;
drawEvent();
}
void EmscriptenApplication::exec() {

198
src/Magnum/Platform/EmscriptenApplication.h

@ -135,8 +135,75 @@ MAGNUM_EMSCRIPTENAPPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included, this class is also aliased to
@cpp Platform::Application @ce and the macro is aliased to @cpp MAGNUM_APPLICATION_MAIN() @ce
to simplify porting.
@cpp Platform::Application @ce and the macro is aliased to
@cpp MAGNUM_APPLICATION_MAIN() @ce to simplify porting.
@section Platform-EmscriptenApplication-browser Browser-specific behavior
Leaving a default (zero) size in @ref Configuration will cause the app to use a
size that corresponds to *CSS pixel size* of the @cb{.html} <canvas> @ce
element. The size is then multiplied by DPI scaling value, see
@ref Platform-EmscriptenApplication-dpi "DPI awareness" below for details.
If you enable @ref Configuration::WindowFlag::Resizable, the canvas will be
resized when size of the canvas changes and you get @ref viewportEvent(). If
the flag is not enabled, no canvas resizing is performed.
Unlike desktop platforms, the browser has no concept of application exit code,
so the return value of @ref exec() is always @cpp 0 @ce and whatever is passed
to @ref exit(int) is ignored.
@section Platform-EmscriptenApplication-webgl WebGL-specific behavior
While WebGL itself requires all extensions to be
[enabled explicitly](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Using_Extensions),
by default Emscripten enables all supported extensions that don't have a
negative effect on performance to simplify porting. This is controlled by
@ref GLConfiguration::Flag::EnableExtensionsByDefault and the flag is enabled
by default. When disabled, you are expected to enable desired extensions
manually using @m_class{m-doc-external} [emscripten_webgl_enable_extension()](https://emscripten.org/docs/api_reference/html5.h.html#c.emscripten_webgl_enable_extension).
@attention Because @ref GLConfiguration::Flag::EnableExtensionsByDefault is
among default flags, calling @ref GLConfiguration::setFlags() will reset
this default, causing crashes at runtime when extension functionality is
used. To be safe, you might want to use @ref GLConfiguration::addFlags()
and @ref GLConfiguration::clearFlags() instead.
@section Platform-EmscriptenApplication-dpi DPI awareness
Since this application targets only web browsers, DPI handling isn't as general
as in case of @ref Sdl2Application or @ref GlfwApplication. See
@ref Platform-Sdl2Application-dpi "Sdl2Application DPI awareness" documentation
for a guide covering all platform differences.
For this application in particular, @ref windowSize() can be different than
@ref framebufferSize() on HiDPI displays --- which is different from
@ref Sdl2Application behavior on Emscripten. By default, @ref dpiScaling() is
@cpp 1.0f @ce in both dimensions but it can be overriden using custom DPI
scaling --- the `--magnum-dpi-scaling` command-line options are supported the
same way as in @ref Sdl2Application, only in the form of URL GET parameters,
similarly to all other @ref platforms-html5-environment "command-line options".
Having @ref dpiScaling() set to @cpp 1.0f @ce is done in order to have
consistent behavior with other platforms --- platforms have either
@ref windowSize() equivalent to @ref framebufferSize() and then
@ref dpiScaling() specifies the UI scale (Windows/Linux/Android-like) or
@ref windowSize() different from @ref framebufferSize() (which defines the UI
scale) and then @ref dpiScaling() is @cpp 1.0f @ce (macOS/iOS-like), so this
is the second case. The actual device pixel ratio is expressed in the ratio of
@ref windowSize() and @ref framebufferSize() so crossplatform code shouldn't
have a need to query it, however for completeness it's exposed in
@ref devicePixelRatio() and @ref ViewportEvent::devicePixelRatio().
Setting custom DPI scaling will affect @ref framebufferSize()
(larger values making the canvas backing framebuffer larger and vice versa),
@ref windowSize() will stay unaffected as it's controlled by the CSS, and
@ref devicePixelRatio() will stay the same as well as it's defined by the
browser.
To avoid confusion, documentation of all @ref EmscriptenApplication APIs always
mentions only the web case, consult equivalent APIs in @ref Sdl2Application or
@ref GlfwApplication for behavior in those implementations.
*/
class EmscriptenApplication {
public:
@ -319,22 +386,41 @@ class EmscriptenApplication {
/**
* @brief Canvas size
*
* Note that this method is named "windowSize" to be API compatible with
* Application implementations on other platforms.
*
* Window size to which all input event coordinates can be related.
* Canvas size to which all input event coordinates can be related.
* On HiDPI displays, canvas size can be different from
* @ref framebufferSize(). See @ref Platform-Sdl2Application-dpi for
* more information. Note that this method is named "window size" to be
* API-compatible with Application implementations on other platforms.
*/
Vector2i windowSize() const;
#if defined(MAGNUM_TARGET_GL) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* @brief Framebuffer size
*
* On HiDPI displays, framebuffer size can be different from
* @ref windowSize(). See @ref Platform-EmscriptenApplication-dpi for
* more information.
*
* @note This function is available only if Magnum is compiled with
* @ref MAGNUM_TARGET_GL enabled (done by default). See
* @ref building-features for more information.
*
* @see @ref Sdl2Application::framebufferSize()
*/
Vector2i framebufferSize() const;
#endif
/**
* @brief DPI scaling
*
* How the content should be scaled relative to system defaults for
* given @ref windowSize(). If a window is not created yet, returns
* zero vector, use @ref dpiScaling(const Configuration&) const for
* calculating a value independently. See @ref Platform-Sdl2Application-dpi
* for more information.
* @see @ref Sdl2Application::dpiScaling(), @ref framebufferSize()
* calculating a value depending on user configuration. By default set
* to @cpp 1.0 @ce, see @ref Platform-EmscriptenApplication-dpi for
* more information.
* @see @ref framebufferSize(), @ref devicePixelRatio()
*/
Vector2 dpiScaling() const { return _dpiScaling; }
@ -343,27 +429,21 @@ class EmscriptenApplication {
*
* Calculates DPI scaling that would be used when creating a window
* with given @p configuration. Takes into account DPI scaling policy
* and custom scaling specified on the command-line. See
* @ref Platform-Sdl2Application-dpi for more information.
* and custom scaling specified via URL GET parameters. See
* @ref Platform-EmscriptenApplication-dpi for more information.
* @ref devicePixelRatio()
*/
Vector2 dpiScaling(const Configuration& configuration) const;
#if defined(MAGNUM_TARGET_GL) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* @brief Framebuffer size
*
* Always the same as @ref windowSize() on
* @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". See
* @ref Platform-Sdl2Application-dpi for more information.
* @brief Device pixel ratio
*
* @note This function is available only if Magnum is compiled with
* @ref MAGNUM_TARGET_GL enabled (done by default). See
* @ref building-features for more information.
*
* @see @ref Sdl2Application::framebufferSize()
* Crossplatform code shouldn't need to query this value because the
* pixel ratio is already expressed in the ratio of @ref windowSize()
* and @ref framebufferSize() values.
* @see @ref dpiScaling()
*/
Vector2i framebufferSize() const { return windowSize(); }
#endif
Vector2 devicePixelRatio() const { return _devicePixelRatio; }
protected:
/**
@ -488,16 +568,16 @@ class EmscriptenApplication {
private:
enum class Flag: UnsignedByte {
Redraw = 1 << 0,
Resizable = 1 << 1,
TextInputActive = 1 << 2,
TextInputActive = 1 << 1
};
typedef Containers::EnumSet<Flag> Flags;
CORRADE_ENUMSET_FRIEND_OPERATORS(Flags)
void setupCallbacks();
/* Sorry, but can't use Configuration::WindowFlags here :( */
void setupCallbacks(bool resizable);
Vector2 _dpiScaling;
Vector2 _devicePixelRatio, _dpiScaling;
Vector2i _lastKnownCanvasSize;
Flags _flags;
@ -783,12 +863,11 @@ class EmscriptenApplication::Configuration {
* @param dpiScaling Custom DPI scaling value
*
* Default is a zero vector, meaning a value that matches the display
* or canvas size is autodetected. See @ref Platform-Sdl2Application-dpi
* for more information.
* When @p dpiScaling is not a zero vector, this function sets the DPI
* scaling directly. The resulting @ref EmscriptenApplication::windowSize()
* is @cpp size*dpiScaling @ce and @ref EmscriptenApplication::dpiScaling()
* is @p dpiScaling.
* or canvas size is autodetected. See
* @ref Platform-EmscriptenApplication-dpi for more information. When
* @p dpiScaling is not a zero vector, this function sets the DPI
* scaling directly. The resulting @ref windowSize() is
* @cpp size*dpiScaling @ce and @ref dpiScaling() is @p dpiScaling.
*/
Configuration& setSize(const Vector2i& size, const Vector2& dpiScaling = {}) {
_size = size;
@ -800,8 +879,8 @@ class EmscriptenApplication::Configuration {
* @brief Custom DPI scaling
*
* If zero, the devices pixel ratio has a priority over this value.
* The `--magnum-dpi-scaling` command-line option has a priority
* over any application-set value.
* The `--magnum-dpi-scaling` option (specified via URL GET parameters)
* has a priority over any application-set value.
* @see @ref setSize(const Vector2i&, const Vector2&)
*/
Vector2 dpiScaling() const { return _dpiScaling; }
@ -850,11 +929,11 @@ class EmscriptenApplication::ViewportEvent {
/**
* @brief Canvas size
*
* Note that this method is named "windowSize" to be API compatible with
* Application implementations on other platforms.
*
* Equivalent to @ref framebufferSize(). See @ref Platform-Sdl2Application-dpi
* for more information.
* On HiDPI displays, window size can be different from
* @ref framebufferSize(). See @ref Platform-EmscriptenApplication-dpi
* for more information. Note that this method is named "window size"
* to be API-compatible with Application implementations on other
* platforms.
* @see @ref EmscriptenApplication::windowSize()
*/
Vector2i windowSize() const { return _windowSize; }
@ -863,8 +942,9 @@ class EmscriptenApplication::ViewportEvent {
/**
* @brief Framebuffer size
*
* Equivalent to @ref windowSize(). See
* @ref Platform-Sdl2Application-dpi for more information.
* On HiDPI displays, framebuffer size can be different from
* @ref windowSize(). See @ref Platform-EmscriptenApplication-dpi for
* more information.
*
* @note This function is available only if Magnum is compiled with
* @ref MAGNUM_TARGET_GL enabled (done by default). See
@ -878,35 +958,47 @@ class EmscriptenApplication::ViewportEvent {
/**
* @brief DPI scaling
*
* On some platforms moving an app between displays can result in DPI
* scaling value being changed in tandem with a canvas/framebuffer
* size. Simply resizing a canvas doesn't change the DPI scaling value.
* See @ref Platform-Sdl2Application-dpi for more information.
* On some platforms moving a browser window between displays can
* result in DPI scaling value being changed in tandem with a
* canvas/framebuffer size. Simply resizing the canvas doesn't change
* the DPI scaling value. See @ref Platform-EmscriptenApplication-dpi
* for more information.
* @see @ref EmscriptenApplication::dpiScaling()
*/
Vector2 dpiScaling() const { return _dpiScaling; }
/**
* @brief Device pixel ratio
*
* On some platforms moving a browser window between displays can
* result in device pixel ratio value being changed. Crossplatform code
* shouldn't need to query this value because the ratio is already
* expressed in the ratio of @ref windowSize() and @ref framebufferSize()
* values. See @ref Platform-EmscriptenApplication-dpi for more
* information.
* @see @ref EmscriptenApplication::devicePixelRatio()
*/
Vector2 devicePixelRatio() const { return _devicePixelRatio; }
private:
friend EmscriptenApplication;
explicit ViewportEvent(
const Vector2i& windowSize,
explicit ViewportEvent(const Vector2i& windowSize,
#ifdef MAGNUM_TARGET_GL
const Vector2i& framebufferSize,
#endif
const Vector2& dpiScaling):
const Vector2& dpiScaling, const Vector2& devicePixelRatio):
_windowSize{windowSize},
#ifdef MAGNUM_TARGET_GL
_framebufferSize{framebufferSize},
#endif
_dpiScaling{dpiScaling} {}
_dpiScaling{dpiScaling}, _devicePixelRatio{devicePixelRatio} {}
const Vector2i _windowSize;
#ifdef MAGNUM_TARGET_GL
const Vector2i _framebufferSize;
#endif
const Vector2 _dpiScaling;
const Vector2 _dpiScaling, _devicePixelRatio;
};
/**

7
src/Magnum/Platform/Sdl2Application.h

@ -365,7 +365,12 @@ The default is depending on the platform:
scaling, taken from [Window.getDevicePixelRatio()](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio). The
@ref windowSize() and @ref framebufferSize() is always the same,
@ref dpiScaling() contains the queried DPI scaling value. The value can be
overriden using custom DPI scaling.
overriden using custom DPI scaling. Note that this is different from the
behavior in @ref EmscriptenApplication --- Emscripten's SDL implementation
has some additional emulation code that reports event coordinates in
framebuffer pixels instead of CSS pixels. See
@ref Platform-EmscriptenApplication-dpi "EmscriptenApplication DPI awareness docs"
for more information.
If your application is saving and restoring window size, it's advisable to take
@ref dpiScaling() into account:

8
src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp

@ -39,6 +39,12 @@ struct EmscriptenApplicationTest: Platform::Application {
//, GLConfiguration{}.setFlags({})
} {
Debug{} << "window size" << windowSize()
#ifdef MAGNUM_TARGET_GL
<< framebufferSize()
#endif
<< dpiScaling() << devicePixelRatio();
/* This uses a VAO on WebGL 1, so it will crash in case GL flags are
missing EnableExtensionsByDefault (uncomment above) */
GL::Mesh mesh;
@ -54,7 +60,7 @@ struct EmscriptenApplicationTest: Platform::Application {
#ifdef MAGNUM_TARGET_GL
/* For testing HiDPI resize events */
void viewportEvent(ViewportEvent& event) override {
Debug{} << "viewport event" << event.windowSize() << event.framebufferSize() << event.dpiScaling();
Debug{} << "viewport event" << event.windowSize() << event.framebufferSize() << event.dpiScaling() << event.devicePixelRatio();
}
#endif

Loading…
Cancel
Save