diff --git a/doc/platforms-html5.dox b/doc/platforms-html5.dox
index 156adf547..56520dfab 100644
--- a/doc/platforms-html5.dox
+++ b/doc/platforms-html5.dox
@@ -98,13 +98,13 @@ Magnum source to the `modules/` dir in your project so it is able to find the
WebGL libraries.
Magnum provides Emscripten application wrappers in @ref Platform::Sdl2Application
-and @ref Platform::EmscriptenApplication. See their documentation for more information
-about general usage. You can also use the Emscripten APIs directly or any other
-way.
+and @ref Platform::EmscriptenApplication. See their documentation for more
+information about general usage. You can also use the Emscripten APIs directly
+or any other way.
-@note @ref Platform::Sdl2Application and @ref Platform::EmscriptenApplication
- also contains a fully configured bootstrap projects that are ready to build
- and deploy. Check their documentation for details.
+@note @ref Platform::EmscriptenApplication also contains a fully configured
+ bootstrap project that is ready to build and deploy. Check its
+ documentation for details.
To target the web browser, you need to provide a HTML markup for your
application. Template one is below. The markup references two files,
@@ -198,9 +198,8 @@ EGL and WebGL libraries.
Windowless Magnum apps (i.e. apps that use the OpenGL context without a window)
can be run in the browser as well using the @ref Platform::WindowlessEglApplication
-class. See its documentation for more information
-about general usage. You can also use the Emscripten APIs directly or any other
-way.
+class. See its documentation for more information about general usage. You can
+also use the Emscripten APIs directly or any other way.
@note @ref Platform::WindowlessEglApplication also contains a fully configured
bootstrap project that's ready to build and deploy. Check its documentation
@@ -350,8 +349,8 @@ Module.doNotCaptureKeyboard = true;
@endcode
-The above is implicitly set for @ref Platform::WindowlessEglApplicaiton, because
-it does not have an event loop.
+The above is implicitly set for @ref Platform::WindowlessEglApplication,
+because it does not have an event loop.
@cb{.js} Module.doNotCaptureKeyboard @ce is not supported by
@ref Platform::EmscriptenApplication.
diff --git a/src/Magnum/Platform/EmscriptenApplication.cpp b/src/Magnum/Platform/EmscriptenApplication.cpp
index c84e5c13b..d7dcf3019 100644
--- a/src/Magnum/Platform/EmscriptenApplication.cpp
+++ b/src/Magnum/Platform/EmscriptenApplication.cpp
@@ -107,27 +107,25 @@ namespace {
};
/* Translate emscripten key code (as defined by
- https://www.w3.org/TR/uievents-code/#key-code-attribute-value)
- to Key enum.
-
- @param key Keyboard layout dependent key string, e.g. 'a', or '-'
- @param code Keyboard layout independent key string, e.g. 'KeyA' or 'Minus'.
- Note that the y key on some layouts may result in 'KeyZ'.
- */
+ https://www.w3.org/TR/uievents-code/#key-code-attribute-value)
+ to Key enum. `key` is a keyboard layout dependent key string, e.g. 'a',
+ or '-'; `code` is a keyboard layout independent key string, e.g. 'KeyA'
+ or 'Minus'. Note that the Y key on some layouts may result in 'KeyZ'. */
Key toKey(const EM_UTF8* const key, const EM_UTF8* const code) {
const std::size_t keyLength = std::strlen(key);
if(keyLength == 0) return Key::Unknown;
/* We use key for a-z as it gives us a keyboard layout respecting
- representation of the key, i.e. we get `z` for z depending on layout
- where code may give us `y` independent of the layout. */
+ representation of the key, i.e. we get `z` for z depending on layout
+ where code may give us `y` independent of the layout. */
if(keyLength == 1) {
if(key[0] >= 'a' && key[0] <= 'z') return Key(key[0]);
else if(key[0] >= 'A' && key[0] <= 'Z') return Key(key[0] - 'A' + 'a');
}
- /* We use code for 0-9 as it allows us to differentiate towards Numpad digits.
- For digits independent of numpad or not, key is e.g. '0' for Zero */
+ /* We use code for 0-9 as it allows us to differentiate towards Numpad
+ digits. For digits independent of numpad or not, key is e.g. '0' for
+ Zero */
const std::size_t codeLength = std::strlen(code);
if(Utility::String::viewBeginsWith({code, codeLength}, "Digit")) {
return Key(code[5]);
@@ -307,11 +305,9 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const
attrs.enableExtensionsByDefault =
!!(glConfiguration.flags() & GLConfiguration::Flag::EnableExtensionsByDefault);
- #ifdef MAGNUM_TARGET_GLES3
- /* WebGL 2 */
+ #ifdef MAGNUM_TARGET_GLES3 /* WebGL 2 */
attrs.majorVersion = 2;
- #elif defined(MAGNUM_TARGET_GLES2)
- /* WebGL 1 */
+ #elif defined(MAGNUM_TARGET_GLES2) /* WebGL 1 */
attrs.minorVersion = 1;
#else
#error unsupported OpenGL ES version
@@ -327,8 +323,8 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context =
emscripten_webgl_create_context("#canvas", &attrs);
if(!context) {
- /* When context creation fails, `context` is a negative integer matching
- EMSCRIPTEN_RESULT_* defines */
+ /* When context creation fails, `context` is a negative integer
+ matching EMSCRIPTEN_RESULT_* defines */
Error{} << "Platform::EmscriptenApplication::tryCreate(): cannot create WebGL context (EMSCRIPTEN_RESULT"
<< context << Debug::nospace << ")";
return false;
@@ -469,7 +465,7 @@ void EmscriptenApplication::stopTextInput() {
}
void EmscriptenApplication::setTextInputRect(const Range2Di&) {
- // TODO: Place a hidden input field at given rect
+ /** @todo place a hidden input field at given rect */
}
void EmscriptenApplication::viewportEvent(ViewportEvent&) {}
@@ -565,12 +561,11 @@ EmscriptenApplication::MouseMoveEvent::Modifiers EmscriptenApplication::MouseMov
Vector2 EmscriptenApplication::MouseScrollEvent::offset() const {
/* From emscripten's Browser.getMouseWheelDelta() function in
- library_browser.js:
+ library_browser.js:
- DOM_DELTA_PIXEL => 100 pixels = 1 step
- DOM_DELTA_LINE => 3 lines = 1 step
- DOM_DELTA_PAGE => 1 page = 80 steps
- */
+ DOM_DELTA_PIXEL => 100 pixels = 1 step
+ DOM_DELTA_LINE => 3 lines = 1 step
+ DOM_DELTA_PAGE => 1 page = 80 steps */
const Float f = (_event->deltaMode == DOM_DELTA_PIXEL) ? -0.01f :
((_event->deltaMode == DOM_DELTA_LINE) ? -1.0f/3.0f : -80.0f);
diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h
index 29c1fb20a..bc3b1cba3 100644
--- a/src/Magnum/Platform/EmscriptenApplication.h
+++ b/src/Magnum/Platform/EmscriptenApplication.h
@@ -65,16 +65,43 @@ in the @ref building-corrade-cross-emscripten "Corrade" and
@section Platform-EmscriptenApplication-bootstrap Bootstrap application
-Fully contained base application using @ref EmscriptenApplication for Emscripten
-build and CMake setup is available in `base-emscripten` branch of
+Fully contained base application using @ref Sdl2Application for desktop build
+and @ref EmscriptenApplication for Emscripten build along with full HTML markup
+and CMake setup is available in `base-emscripten` branch of the
[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository,
download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-emscripten.tar.gz)
or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-emscripten.zip)
-file. After extracting the downloaded archive, you can build in
-the same way as with @ref Sdl2Application.
+file. After extracting the downloaded archive, you can do the desktop build in
+the same way as with @ref Sdl2Application. For the Emscripten build you also
+need to put the contents of toolchains repository from
+https://github.com/mosra/toolchains in a `toolchains/` subdirectory. There are
+two toolchain files. The `generic/Emscripten.cmake` is for the classical
+(asm.js) build, the `generic/Emscripten-wasm.cmake` is for WebAssembly build.
+Don't forget to adapt `EMSCRIPTEN_PREFIX` variable in
+`toolchains/generic/Emscripten*.cmake` to path where Emscripten is installed;
+you can also pass it explicitly on command-line using `-DEMSCRIPTEN_PREFIX`.
+Default is `/usr/emscripten`.
+
+Then create build directory and run `cmake` and build/install commands in it.
+Set `CMAKE_PREFIX_PATH` to where you have all the dependencies installed, set
+`CMAKE_INSTALL_PREFIX` to have the files installed in proper location (a
+webserver, e.g. `/srv/http/emscripten`).
+
+@code{.sh}
+mkdir build-emscripten && cd build-emscripten
+cmake .. \
+ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten.cmake" \
+ -DCMAKE_PREFIX_PATH=/usr/lib/emscripten/system \
+ -DCMAKE_INSTALL_PREFIX=/srv/http/emscripten
+cmake --build .
+cmake --build . --target install
+@endcode
+
+You can then open `MyApplication.html` in your browser (through a webserver,
+e.g. http://localhost/emscripten/MyApplication.html).
Detailed information about deployment for Emscripten and all needed boilerplate
-together with a troubleshooting guide is available in @ref platforms-emscripten.
+together with a troubleshooting guide is available in @ref platforms-html5.
@section Platform-EmscriptenApplication-usage General usage
@@ -94,7 +121,7 @@ endif()
@endcode
If no other application is requested, you can also use the generic
-`Magnum::Application` alias to simplify porting. Again, see @ref building and
+`Magnum::Application` alias to simplify porting. See @ref building and
@ref cmake for more information.
In C++ code you need to implement at least @ref drawEvent() to be able to draw
@@ -409,8 +436,7 @@ class EmscriptenApplication {
/**
* @brief Whether text input is active
*
- * If text input is active, text input events go to @ref textInputEvent()
- * and @ref textEditingEvent().
+ * If text input is active, text input events go to @ref textInputEvent().
* @note Note that in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" the
* value is emulated and might not reflect external events like
* closing on-screen keyboard.
@@ -423,8 +449,7 @@ class EmscriptenApplication {
/**
* @brief Start text input
*
- * Starts text input that will go to @ref textInputEvent() and
- * @ref textEditingEvent().
+ * Starts text input that will go to @ref textInputEvent().
* @see @ref stopTextInput(), @ref isTextInputActive(),
* @ref setTextInputRect()
*/
@@ -433,10 +458,9 @@ class EmscriptenApplication {
/**
* @brief Stop text input
*
- * Stops text input that went to @ref textInputEvent() and
- * @ref textEditingEvent().
- * @see @ref startTextInput(), @ref isTextInputActive(), @ref textInputEvent()
- * @ref textEditingEvent()
+ * Stops text input that went to @ref textInputEvent().
+ * @see @ref startTextInput(), @ref isTextInputActive(),
+ * @ref textInputEvent()
*/
void stopTextInput();
@@ -492,7 +516,7 @@ CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::Flags)
/**
@brief WebGL context configuration
-Double-buffered RGBA canvas with depth and stencil buffers.
+The created context is always with a double-buffered OpenGL context.
@see @ref EmscriptenApplication(), @ref Configuration, @ref create(),
@ref tryCreate()
*/
@@ -501,80 +525,61 @@ class EmscriptenApplication::GLConfiguration {
/**
* @brief Context flag
*
- * @see @ref Flags, @ref setFlags(), @ref Context::Flag
- * @requires_gles Context flags are not available in WebGL.
+ * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/
enum class Flag: Int {
/**
- * Premultiplied alpha
- *
- * If set, the alpha channel of the rendering context will be
- * treated as representing premultiplied alpha values. If not set, the
- * alpha channel represents non-premultiplied alpha.
+ * Premultiplied alpha. If set, the alpha channel of the rendering
+ * context will be treated as representing premultiplied alpha
+ * values. If not set, the alpha channel represents
+ * non-premultiplied alpha.
*/
PremultipliedAlpha = 1 << 0,
/**
- * Preserve drawing buffer
- *
- * If set, the contents of the drawing buffer are preserved between
- * consecutive @ref EmscriptenApplication::drawEvent() calls. If not,
- * color, depth and stencil are cleared at before
- * @ref EmscriptenApplication::drawEvent().
- * Not setting this gives better performance.
+ * Preserve drawing buffer. If set, the contents of the drawing
+ * buffer are preserved between consecutive @ref drawEvent() calls.
+ * If not, color, depth and stencil are cleared before entering
+ * @ref drawEvent(). Not setting this gives better performance.
*/
PreserveDrawingBuffer = 1 << 1,
/**
- * Prefer low power to high performance
- *
- * If set, the WebGL power preference will be set to reduce power
- * consumption.
+ * Prefer low power to high performance. If set, the WebGL power
+ * preference will be set to reduce power consumption.
*/
PreferLowPowerToHighPerformance = 1 << 2,
/**
- * Fail if major performance caveat
- *
- * If set, requests context creation to abort if the browser is
- * only able to create a context that does not give good hardware-
- * accelerated performance.
+ * Fail if major performance caveat. If set, requests context
+ * creation to abort if the browser is only able to create a
+ * context that does not give good hardware-accelerated
+ * performance.
*/
FailIfMajorPerformanceCaveat = 1 << 3,
/**
- * Explicit swap control
- *
- * For more details, see the
- * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.explicitSwapControl)
- * for more details.
+ * Explicit swap control. For more details, see the
+ * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.explicitSwapControl).
*/
ExplicitSwapControl = 1 << 4,
/**
- * Enable WebGL extensions by default
- *
- * For more details, see the
- * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.enableExtensionsByDefault)
- * for more details.
+ * Enable WebGL extensions by default. Enabled by default. For more
+ * details, see @ref Platform-EmscriptenApplication-webgl and the
+ * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.enableExtensionsByDefault).
*/
EnableExtensionsByDefault = 1 << 5,
/**
- * Render via offscreen back buffer
- *
- * For more details, see the
- * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.renderViaOffscreenBackBuffer)
- * for more details.
+ * Render via offscreen back buffer. For more details, see the
+ * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.renderViaOffscreenBackBuffer).
*/
RenderViaOffscreenBackBuffer = 1 << 6,
/**
- * Proxy content to main thread
- *
- * For more details, see the
- * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.proxyContextToMainThread)
- * for more details.
+ * Proxy content to main thread. For more details, see the
+ * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.proxyContextToMainThread).
*/
ProxyContextToMainThread = 1 << 7
};
@@ -582,15 +587,13 @@ class EmscriptenApplication::GLConfiguration {
/**
* @brief Context flags
*
- * @see @ref setFlags(), @ref Context::Flags
+ * @see @ref setFlags(), @ref GL::Context::Flags
*/
typedef Containers::EnumSet Flags;
/*implicit*/ GLConfiguration();
- /**
- * @brief Context flags
- */
+ /** @brief Context flags */
Flags flags() const { return _flags; }
/**
@@ -714,7 +717,6 @@ CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::GLConfiguration::Flags)
/**
@brief Configuration
-Double-buffered RGBA canvas with depth and stencil buffers.
@see @ref EmscriptenApplication(), @ref GLConfiguration, @ref create(),
@ref tryCreate()
*/
@@ -736,6 +738,13 @@ class EmscriptenApplication::Configuration {
*/
Contextless = 1 << 0,
+ /**
+ * Resizable canvas. This causes the framebuffer to be resized
+ * when the @cb{.html}