Browse Source

Platform: replace inline EM_ASM() with an external JS library.

Same as the corresponding change in Corrade, this allows each function
to explicitly specify its dependencies, making it no longer depending on
what a particular Emscripten version decides to include by default, or
forcing users to painstakingly fill the EXPORTED_FUNCTIONS array when
linking the final executable.

It also allows the code to eventually get conditionally included or not
with preprocessor branches, for example to not include environment
queries for code that won't ever access Node.js console.
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
c3422cdd6b
  1. 8
      doc/changelog.dox
  2. 21
      modules/FindMagnum.cmake
  3. 34
      src/Magnum/Platform/CMakeLists.txt
  4. 189
      src/Magnum/Platform/EmscriptenApplication.cpp
  5. 137
      src/Magnum/Platform/Platform.js.in
  6. 53
      src/Magnum/Platform/Sdl2Application.cpp

8
doc/changelog.dox

@ -958,9 +958,11 @@ See also:
- The Emscripten toolchain now looks for `lib*.a` files in addition to `*.bc`
for better compatibility with 3rd party toolchains and package managers
like Vcpkg (see [mosra/magnum#520](https://github.com/mosra/magnum/issues/520)).
- @ref Platform::Sdl2Application and @ref Platform::EmscriptenApplication now
use `UTF8ToString` instead of `AsciiToString` as the latter is no longer
included by default on Emscripten 3.1.21+ (see [mosra/magnum#619](https://github.com/mosra/magnum/issues/619)).
- The Emscripten build now uses `--js-library` instead of inline `EM_ASM()`
for calling into JavaScript. This allows it to properly specify its runtime
dependencies without risking breakages when new Emscripten versions make
more JS API functions optional, and circumvents the need for users to
specify `-s EXPORTED_FUNCTIONS` on their side. See [mosra/magnum#619](https://github.com/mosra/magnum/issues/619).
@subsection changelog-latest-bugfixes Bug fixes

21
modules/FindMagnum.cmake

@ -162,6 +162,7 @@
# MAGNUM_*_LIBRARY - Component libraries (w/o dependencies)
# MAGNUM_*_LIBRARY_DEBUG - Debug version of given library, if found
# MAGNUM_*_LIBRARY_RELEASE - Release version of given library, if found
# MAGNUM_PLATFORM_JS - Path to MagnumPlatform.js file
# MAGNUM_BINARY_INSTALL_DIR - Binary installation directory
# MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory
# MAGNUM_DATA_INSTALL_DIR - Data installation directory
@ -696,7 +697,17 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES android EGL::EGL)
# EmscriptenApplication has no additional dependencies
# Emscripten application dependencies
elseif(_component STREQUAL EmscriptenApplication)
# Emscripten has various stuff implemented in JS
if(CORRADE_TARGET_EMSCRIPTEN)
find_file(MAGNUM_PLATFORM_JS MagnumPlatform.js
PATH_SUFFIXES lib)
set_property(TARGET Magnum::${_component} APPEND PROPERTY
# TODO switch to INTERFACE_LINK_OPTIONS and SHELL: once
# we require CMake 3.13 unconditionally
INTERFACE_LINK_LIBRARIES "--js-library ${MAGNUM_PLATFORM_JS}")
endif()
# GLFW application dependencies
elseif(_component STREQUAL GlfwApplication)
@ -752,6 +763,14 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
elseif(CORRADE_TARGET_UNIX)
set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
# Emscripten has various stuff implemented in JS
elseif(CORRADE_TARGET_EMSCRIPTEN)
find_file(MAGNUM_PLATFORM_JS MagnumPlatform.js
PATH_SUFFIXES lib)
set_property(TARGET Magnum::${_component} APPEND PROPERTY
# TODO switch to INTERFACE_LINK_OPTIONS and SHELL: once
# we require CMake 3.13 unconditionally
INTERFACE_LINK_LIBRARIES "--js-library ${MAGNUM_PLATFORM_JS}")
endif()
# With GLVND (since CMake 3.11) we need to explicitly link to

34
src/Magnum/Platform/CMakeLists.txt

@ -203,6 +203,24 @@ if(CORRADE_TARGET_EMSCRIPTEN AND (MAGNUM_WITH_EMSCRIPTENAPPLICATION OR MAGNUM_WI
if(EMSCRIPTEN_VERSION VERSION_LESS 1.39.5)
message(SEND_ERROR "Emscripten 1.39.5+, which enables DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR by default, is required to build EmscriptenApplication and Sdl2Application. Found version ${EMSCRIPTEN_VERSION}.")
endif()
# Patch the Platform.js file to contain only __deps that match given
# Emscripten version. No, there's no known better way. See the comment in
# the file itself for details.
if(EMSCRIPTEN_VERSION VERSION_LESS 3.1.35)
set(MagnumPlatform_EMSCRIPTEN_3135_ONLY "//") # Haha
else()
set(MagnumPlatform_EMSCRIPTEN_3135_ONLY "/* Emscripten 3.1.35+ */")
endif()
if(EMSCRIPTEN_VERSION VERSION_LESS 2.0.10)
set(MagnumPlatform_EMSCRIPTEN_2010_ONLY "//") # Haha
else()
set(MagnumPlatform_EMSCRIPTEN_2010_ONLY "/* Emscripten 2.0.10+ */")
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Platform.js.in
${CMAKE_CURRENT_BINARY_DIR}/Platform.js)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Platform.js DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} RENAME MagnumPlatform.js)
endif()
# Emscripten application
@ -232,6 +250,14 @@ if(MAGNUM_WITH_EMSCRIPTENAPPLICATION)
if(MAGNUM_TARGET_GL)
target_link_libraries(MagnumEmscriptenApplication PUBLIC MagnumGL)
endif()
if(CORRADE_TARGET_EMSCRIPTEN)
# TODO switch to target_link_options() and SHELL: once we require CMake
# 3.13 unconditionally
target_link_libraries(MagnumEmscriptenApplication PUBLIC "--js-library ${CMAKE_CURRENT_BINARY_DIR}/Platform.js")
# TODO this adds the dependency only on 3.13+ and only for Make/Ninja,
# any better option?
set_property(TARGET MagnumEmscriptenApplication APPEND PROPERTY INTERFACE_LINK_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Platform.js)
endif()
install(FILES ${MagnumEmscriptenApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumEmscriptenApplication
@ -344,6 +370,14 @@ if(MAGNUM_WITH_SDL2APPLICATION)
MagnumGL
${MagnumSomeContext_LIBRARY})
endif()
if(CORRADE_TARGET_EMSCRIPTEN)
# TODO switch to target_link_options() and SHELL: once we require CMake
# 3.13 unconditionally
target_link_libraries(MagnumSdl2Application PUBLIC "--js-library ${CMAKE_CURRENT_BINARY_DIR}/Platform.js")
# TODO this adds the dependency only on 3.13+ and only for Make/Ninja,
# any better option?
set_property(TARGET MagnumSdl2Application APPEND PROPERTY INTERFACE_LINK_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Platform.js)
endif()
install(FILES ${MagnumSdl2Application_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumSdl2Application

189
src/Magnum/Platform/EmscriptenApplication.cpp

@ -43,6 +43,18 @@
#include "Magnum/GL/Version.h"
#endif
#ifdef CORRADE_TARGET_EMSCRIPTEN
/* Implemented in Platform.js.in */
extern "C" {
char* magnumPlatformCanvasId();
char* magnumPlatformKeyboardListeningElement();
void magnumPlatformSetWindowTitle(const char* string, std::size_t size);
void magnumPlatformSetContainerCssClass(const char* string, std::size_t size);
void magnumPlatformSetCursor(const char* string, std::size_t size);
void magnumPlatformRequestAnimationFrame(int(*callback)(void*), void* state);
}
#endif
namespace Magnum { namespace Platform {
using namespace Containers::Literals;
@ -178,20 +190,7 @@ namespace {
}
Containers::String canvasId() {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
/* Note: can't use let or const, as that breaks closure compiler:
ERROR - [JSC_LANGUAGE_FEATURE] This language feature is only
supported for ECMASCRIPT6 mode or better: const declaration. */
char* id = reinterpret_cast<char*>(EM_ASM_INT({
var id = '#' + Module['canvas'].id;
var bytes = lengthBytesUTF8(id) + 1;
var memory = _malloc(bytes);
stringToUTF8(id, memory, bytes);
return memory;
}));
#pragma GCC diagnostic pop
return Containers::String{id, [](char* data, std::size_t) { std::free(data); }};
return Containers::String{magnumPlatformCanvasId(), [](char* data, std::size_t) { std::free(data); }};
}
}
@ -434,23 +433,11 @@ Vector2i EmscriptenApplication::framebufferSize() const {
#endif
void EmscriptenApplication::setWindowTitle(const Containers::StringView title) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
EM_ASM_({document.title = UTF8ToString($0, $1);}, title.data(), title.size());
#pragma GCC diagnostic pop
magnumPlatformSetWindowTitle(title.data(), title.size());
}
void EmscriptenApplication::setContainerCssClass(const Containers::StringView cssClass) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
EM_ASM_({
/* Handle also the classic #container for backwards compatibility. We
also need to preserve the mn-container otherwise next time we'd have
no way to look for it anymore. */
(Module['canvas'].closest('.mn-container') ||
document.getElementById('container')).className = (['mn-container', UTF8ToString($0, $1)]).join(' ');
}, cssClass.data(), cssClass.size());
#pragma GCC diagnostic pop
magnumPlatformSetContainerCssClass(cssClass.data(), cssClass.size());
/* Trigger a potential viewport event -- we don't poll the canvas size like
Sdl2Application does, so it needs to be done explicitly */
@ -539,32 +526,12 @@ void EmscriptenApplication::setupCallbacks(bool resizable) {
return e.isAccepted();
}));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
/* document and window are 'specialEventTargets' in emscripten, matching
EMSCRIPTEN_EVENT_TARGET_DOCUMENT and EMSCRIPTEN_EVENT_TARGET_WINDOW.
As the lookup happens with the passed parameter and arrays support
element lookup via strings, we can unify the code by returning string of
1 or 2 if the target is document or window. */
/* Note: can't use let or const, as that breaks closure compiler:
ERROR - [JSC_LANGUAGE_FEATURE] This language feature is only
supported for ECMASCRIPT6 mode or better: const declaration. */
char* const keyboardListeningElement = reinterpret_cast<char*>(EM_ASM_INT({
var element = Module['keyboardListeningElement'] || document;
if(element === document) return 1; /* EMSCRIPTEN_EVENT_TARGET_DOCUMENT */
if(element === window) return 2; /* EMSCRIPTEN_EVENT_TARGET_WINDOW */
if('id' in element) {
var id = '#' + element.id;
var bytes = lengthBytesUTF8(id) + 1;
var memory = _malloc(bytes);
stringToUTF8(id, memory, bytes);
return memory;
}
return 0;
}));
#pragma GCC diagnostic pop
char* const keyboardListeningElement = magnumPlatformKeyboardListeningElement();
/* If the element is a heap-allocated string, ensure it gets properly freed
after */
@ -650,43 +617,43 @@ void EmscriptenApplication::setupAnimationFrame(bool forceAnimationFrame) {
namespace {
constexpr const char* CursorMap[] {
"auto",
"default",
"none",
"context-menu",
"help",
"pointer",
"progress",
"wait",
"cell",
"crosshair",
"text",
"vertical-text",
"alias",
"copy",
"move",
"no-drop",
"not-allowed",
"grab",
"grabbing",
"all-scroll",
"col-resize",
"row-resize",
"n-resize",
"e-resize",
"s-resize",
"w-resize",
"ne-resize",
"nw-resize",
"se-resize",
"sw-resize",
"ew-resize",
"ns-resize",
"nesw-resize",
"nwse-resize",
"zoom-in",
"zoom-out"
constexpr Containers::StringView CursorMap[]{
"auto"_s,
"default"_s,
"none"_s,
"context-menu"_s,
"help"_s,
"pointer"_s,
"progress"_s,
"wait"_s,
"cell"_s,
"crosshair"_s,
"text"_s,
"vertical-text"_s,
"alias"_s,
"copy"_s,
"move"_s,
"no-drop"_s,
"not-allowed"_s,
"grab"_s,
"grabbing"_s,
"all-scroll"_s,
"col-resize"_s,
"row-resize"_s,
"n-resize"_s,
"e-resize"_s,
"s-resize"_s,
"w-resize"_s,
"ne-resize"_s,
"nw-resize"_s,
"se-resize"_s,
"sw-resize"_s,
"ew-resize"_s,
"ns-resize"_s,
"nesw-resize"_s,
"nwse-resize"_s,
"zoom-in"_s,
"zoom-out"_s
};
}
@ -694,10 +661,8 @@ constexpr const char* CursorMap[] {
void EmscriptenApplication::setCursor(Cursor cursor) {
_cursor = cursor;
CORRADE_INTERNAL_ASSERT(UnsignedInt(cursor) < Containers::arraySize(CursorMap));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
EM_ASM_({Module['canvas'].style.cursor = UTF8ToString($0);}, CursorMap[UnsignedInt(cursor)]);
#pragma GCC diagnostic pop
magnumPlatformSetCursor(CursorMap[UnsignedInt(cursor)].data(),
CursorMap[UnsignedInt(cursor)].size());
}
EmscriptenApplication::Cursor EmscriptenApplication::cursor() {
@ -753,49 +718,7 @@ void EmscriptenApplication::redraw() {
/* Start requestAnimationFrame loop */
_flags |= Flag::LoopActive;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
EM_ASM({
/* Animation frame callback */
var drawEvent = function() {
var id = window.requestAnimationFrame(drawEvent);
/* Call our callback via function pointer taking an int and
returning int as well. This used to be
if(!dynCall('ii', $0, [$1])) {
but since 2.0.10 the dynCall isn't exported by default anymore:
https://github.com/emscripten-core/emscripten/commit/496967e00735c1523299e116dc692572d3d6d082
and making it exported again doing so involves crazy shit with
CMake 3.13-only features and a ton of backslashes:
target_link_options(MagnumEmscriptenApplication INTERFACE
"SHELL:-s \"DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=['\${xylophone}dynCall']\""
"SHELL:-s \"EXPORTED_FUNCTIONS=['_main', 'dynCall']\"")
(the ${xylophone} is needed because CMake expands that to
`\$${xylophone}dynCall` for some reason, which then the shell
collapses to `$dynCall` (assuming a $xylophone env var doesn't
exist, which it shoulndn't, but also it's 2021 and so everything
is possible), and no amount of \\\\$$$ helps avoiding that
xylophone); but doing so means we forever hardcode what
functions are exported and thus whatever extra Emscripten needs
to export will be overridden by this, causing only pain and
misery.
So instead we rely on the implementation details of dynCall,
which are actually really simple:
https://github.com/emscripten-core/emscripten/blob/496967e00735c1523299e116dc692572d3d6d082/src/library.js#L3730-L3747
and PRAY it doesn't change again in the future. */
if(!wasmTable.get($0).apply(null, [$1])) {
window.cancelAnimationFrame(id);
}
};
window.requestAnimationFrame(drawEvent);
}, _callback, this);
#pragma GCC diagnostic pop
magnumPlatformRequestAnimationFrame(_callback, this);
}
void EmscriptenApplication::exit(int) {

137
src/Magnum/Platform/Platform.js.in

@ -0,0 +1,137 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* JavaScript called by C++ code in EmscriptenApplication and Sdl2Application.
Doing it this way instead of having it inline with EM_ASM(), because this
provides an actually usable way of expressing dependencies. With EM_ASM()
one would instead have to pass
-s EXPORTED_FUNCTIONS=[...]
to the linker, and OF COURSE there still isn't a way to combine multiple of
those together: https://github.com/emscripten-core/emscripten/issues/19058
Which would mean shifting the burden of specifying all possible exported
functions to the end user, which has no way to know if the list is correct
until the actual code needing given function gets called!
Note: can't use let or const, as that breaks closure compiler:
ERROR - [JSC_LANGUAGE_FEATURE] This language feature is only supported for
ECMASCRIPT6 mode or better: const declaration.
Also, lengthBytesUTF8, stringToUTF8 and UTF8ToString are only made library
functions as of https://github.com/emscripten-core/emscripten/pull/19097
(Emscripten 3.1.35), before that they cause an error if included in __deps.
There's (of course, what else to expect) no way to query Emscripten version
from within the JS library file, and there's also no useful change in the
predefined setting variables between 3.1.34 and 35 I could rely on. Well,
except for STRUCT_INFO, which got removed from settings_internal.js in 35,
but the dumb-as-a-rock preprocessor in src/parseTools.js doesn't even
recognize #ifndef, tells me to use #if if I attempt to use #ifdef, and then
while it does what's expected on 3.1.34, on 3.1.35 it fails on
ReferenceError: STRUCT_INFO is not defined
Ourageously stupid. All of this. So what I do instead is passing this file
through configure_file() and replacing MagnumPlatform_EMSCRIPTEN_3135_ONLY
with a // on older versions. */
mergeInto(LibraryManager.library, {
/* Used by both EmscriptenApplication and Sdl2Application */
magnumPlatformSetContainerCssClass__deps: [
${MagnumPlatform_EMSCRIPTEN_3135_ONLY} '$UTF8ToString'
],
magnumPlatformSetContainerCssClass: function(string, size) {
/* Handle also the classic #container for backwards compatibility. We
also need to preserve the mn-container otherwise next time we'd have
no way to look for it anymore.
Using UTF8ToString() instead of AsciiToString() as it has an
explicit size parameter and thus doesn't need a null-terminated
input, which would potentially require yet another allocation.
UTF8ToString() is also used elsewhere while AsciiToString() isn't,
so even while AsciiToString() is significantly smaller it would
still cause the JS to get bigger compared to using UTF8ToString()
everywhere. */
(Module['canvas'].closest('.mn-container') ||
document.getElementById('container')).className = (['mn-container', UTF8ToString(string, size)]).join(' ');
},
magnumPlatformSetCursor__deps: [
${MagnumPlatform_EMSCRIPTEN_3135_ONLY} '$UTF8ToString'
],
magnumPlatformSetCursor: function(string, size) {
/* This could again use AsciiToString() but here we can pass explicit
size and avoid a length calculation */
Module['canvas'].style.cursor = UTF8ToString(string, size);
},
/* Used by EmscriptenApplication only */
magnumPlatformCanvasId__deps: ['malloc',
${MagnumPlatform_EMSCRIPTEN_3135_ONLY} '$lengthBytesUTF8', '$stringToUTF8'
],
magnumPlatformCanvasId: function() {
var id = '#' + Module['canvas'].id;
var bytes = lengthBytesUTF8(id) + 1;
var memory = _malloc(bytes);
stringToUTF8(id, memory, bytes);
return memory;
},
magnumPlatformSetWindowTitle__deps: [
${MagnumPlatform_EMSCRIPTEN_3135_ONLY} '$UTF8ToString'
],
magnumPlatformSetWindowTitle: function(string, size) {
document.title = UTF8ToString(string, size);
},
magnumPlatformKeyboardListeningElement__deps: ['malloc',
${MagnumPlatform_EMSCRIPTEN_3135_ONLY} '$lengthBytesUTF8', '$stringToUTF8'
],
magnumPlatformKeyboardListeningElement: function() {
var element = Module['keyboardListeningElement'] || document;
if(element === document) return 1; /* EMSCRIPTEN_EVENT_TARGET_DOCUMENT */
if(element === window) return 2; /* EMSCRIPTEN_EVENT_TARGET_WINDOW */
if('id' in element) {
var id = '#' + element.id;
/* This could theoretically also use just stringToAscii(), but
as stringToUTF8() is used elsewhere stringToAscii() would still
inflate the JS even though it's smaller. */
var bytes = lengthBytesUTF8(id) + 1;
var memory = _malloc(bytes);
stringToUTF8(id, memory, bytes);
return memory;
}
return 0;
},
magnumPlatformRequestAnimationFrame__deps: [
${MagnumPlatform_EMSCRIPTEN_2010_ONLY} '$dynCall'
],
magnumPlatformRequestAnimationFrame: function(callback, state) {
var drawEvent = function() {
var id = window.requestAnimationFrame(drawEvent);
if(!dynCall('ii', callback, [state]))
window.cancelAnimationFrame(id);
};
window.requestAnimationFrame(drawEvent);
},
});
// kate: hl javascript

53
src/Magnum/Platform/Sdl2Application.cpp

@ -68,6 +68,14 @@
#include <windows.h>
#endif
#ifdef CORRADE_TARGET_EMSCRIPTEN
/* Implemented in Platform.js.in */
extern "C" {
void magnumPlatformSetContainerCssClass(const char* string, std::size_t size);
void magnumPlatformSetCursor(const char* string, std::size_t size);
}
#endif
namespace Magnum { namespace Platform {
using namespace Containers::Literals;
@ -752,16 +760,7 @@ Vector2i Sdl2Application::framebufferSize() const {
#ifdef CORRADE_TARGET_EMSCRIPTEN
void Sdl2Application::setContainerCssClass(const Containers::StringView cssClass) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
EM_ASM_({
/* Handle also the classic #container for backwards compatibility. We
also need to preserve the mn-container otherwise next time we'd have
no way to look for it anymore. */
(Module['canvas'].closest('.mn-container') ||
document.getElementById('container')).className = (['mn-container', UTF8ToString($0, $1)]).join(' ');
}, cssClass.data(), cssClass.size());
#pragma GCC diagnostic pop
magnumPlatformSetContainerCssClass(cssClass.data(), cssClass.size());
}
#endif
@ -1047,20 +1046,20 @@ constexpr SDL_SystemCursor CursorMap[] {
SDL_SYSTEM_CURSOR_HAND
};
#else
constexpr const char* CursorMap[] {
"default",
"text",
"wait",
"crosshair",
"progress",
"nwse-resize",
"nesw-resize",
"ew-resize",
"ns-resize",
"move",
"not-allowed",
"pointer",
"none"
constexpr Containers::StringView CursorMap[] {
"default"_s,
"text"_s,
"wait"_s,
"crosshair"_s,
"progress"_s,
"nwse-resize"_s,
"nesw-resize"_s,
"ew-resize"_s,
"ns-resize"_s,
"move"_s,
"not-allowed"_s,
"pointer"_s,
"none"_s
/* Hidden & locked not supported yet */
};
#endif
@ -1099,10 +1098,8 @@ void Sdl2Application::setCursor(Cursor cursor) {
CORRADE_ASSERT(_surface, "Platform::Sdl2Application::setCursor(): no window opened", );
_cursor = cursor;
CORRADE_INTERNAL_ASSERT(UnsignedInt(cursor) < Containers::arraySize(CursorMap));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
EM_ASM_({Module['canvas'].style.cursor = UTF8ToString($0);}, CursorMap[UnsignedInt(cursor)]);
#pragma GCC diagnostic pop
magnumPlatformSetCursor(CursorMap[UnsignedInt(cursor)].data(),
CursorMap[UnsignedInt(cursor)].size());
#endif
}

Loading…
Cancel
Save