diff --git a/doc/changelog.dox b/doc/changelog.dox index b8dfb56ba..f71d2d36f 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -67,6 +67,9 @@ r>>) @ref Platform::AndroidApplication::dpiScaling() and @ref Platform::AndroidApplication::ViewportEvent::dpiScaling() for compatibility with other application implementations +- Implemented handling of @ref Platform::AndroidApplication::viewportEvent() + and documenting how to get Android to call it instead of relaunching the + app from scratch @subsection changelog-latest-changes Changes and improvements diff --git a/doc/platforms-android.dox b/doc/platforms-android.dox index 6e381cb20..4a85468fa 100644 --- a/doc/platforms-android.dox +++ b/doc/platforms-android.dox @@ -147,7 +147,10 @@ version is: - + @@ -180,6 +183,16 @@ pixel size. That is not supported by @ref Platform::AndroidApplication since there's [no reliable way](https://stackoverflow.com/q/17481341) to get the actual size used for events in that case. +@anchor platforms-android-apps-manifest-screen-resize + +The @cb{.xml} @ce +attribute is needed in order to make the application properly receive a +viewport event. By default it's being outright killed and recreated when device +orientation changes for questionable "performance reasons". If you really want +to handle orientation changes that way, remove `screenSize` from the set. +Among other options is restricting the app to only portrait or landscape screen +orientation. + Consult [the Android developer documentation](https://developer.android.com/guide/topics/manifest/manifest-intro.html) for further information about the manifest file. diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp index 0325aa03a..15dbbd041 100644 --- a/src/Magnum/Platform/AndroidApplication.cpp +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -228,6 +228,16 @@ void AndroidApplication::commandEvent(android_app* state, int32_t cmd) { case APP_CMD_LOST_FOCUS: /** @todo Make use of these */ break; + + case APP_CMD_CONFIG_CHANGED: { + /* This says "the current device configuration has changed", which + is about as vague as it can get. It seems to be that this gets + emitted when screen orientation changes, for example. Fire the + viewport event in this case. */ + ViewportEvent e{{ANativeWindow_getWidth(data.instance->_state->window), + ANativeWindow_getHeight(data.instance->_state->window)}}; + data.instance->viewportEvent(e); + } break; } } diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 8b7f63a1b..3e3800922 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -128,6 +128,15 @@ 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. +@section Platform-AndroidApplication-resizing Responding to viewport events + +Unlike in desktop application implementations, where this is controlled via +@ref Sdl2Application::Configuration::WindowFlag::Resizable, for example, on +Android you have to describe this in the `AndroidManifest.xml` file, as by +default the application gets killed and relaunched on screen orientation +change. See the @ref platforms-android-apps-manifest-screen-resize "manifest file docs" +for more information. + @section Platform-AndroidApplication-output-redirection Redirecting output to Android log buffer The application by default redirects @ref Corrade::Utility::Debug "Debug", @@ -361,7 +370,32 @@ class AndroidApplication { #else private: #endif - /** @copydoc GlfwApplication::viewportEvent(ViewportEvent&) */ + /** + * @brief Viewport event + * + * Called when window size changes, for example after device + * orientation change. The default implementation does nothing. If you + * want to respond to size changes, you should pass the new size to + * @ref GL::DefaultFramebuffer::setViewport() (if using OpenGL) and + * possibly elsewhere (to @ref SceneGraph::Camera::setViewport(), other + * framebuffers...). + * + * @attention Android by default kills and fully recreates the + * application on device orientation change instead of calling the + * viewport event. To prevent that, you need to modify the + * `AndroidManifest.xml` file. See the + * @ref platforms-android-apps-manifest-screen-resize "manifest file docs" + * for more information. + * + * Note that this function might not get called at all if the window + * size doesn't change. You should configure the initial state of your + * cameras, framebuffers etc. in application constructor rather than + * relying on this function to be called. Size of the window can be + * retrieved using @ref windowSize(), size of the backing framebuffer + * via @ref framebufferSize() and DPI scaling using @ref dpiScaling(). + * See @ref Platform-GlfwApplication-dpi for detailed info about these + * values. + */ virtual void viewportEvent(ViewportEvent& event); #ifdef MAGNUM_BUILD_DEPRECATED diff --git a/src/Magnum/Platform/Test/AndroidManifest.xml b/src/Magnum/Platform/Test/AndroidManifest.xml index f54c2f736..83fa37f5a 100644 --- a/src/Magnum/Platform/Test/AndroidManifest.xml +++ b/src/Magnum/Platform/Test/AndroidManifest.xml @@ -3,7 +3,10 @@ - +