Magnum::Platform::Sdl2Application class

SDL2 application.

Application using the Simple DirectMedia Layer toolkit. Supports keyboard and mouse handling. This application library is available for all platforms for which SDL2 is ported except Android (thus is avaiable also on Emscripten, see respective sections in Corrade's and Magnum's building documentation).

Bootstrap application

Fully contained base application using Sdl2Application along with CMake setup is available in base branch of Magnum Bootstrap repository, download it as tar.gz or zip file. After extracting the downloaded archive you can build and run the application with these four commands:

mkdir build && cd build
cmake ..
cmake --build .
./src/MyApplication # or ./src/Debug/MyApplication

See Usage with CMake for more information.

Bootstrap application for Emscripten

The dedicated application implementation for Emscripten is EmscriptenApplication, which also provides a bootstrap project along with full HTML markup and CMake setup. Sdl2Application however supports Emscripten as well — set up the bootstrap application as described in the EmscriptenApplication docs and then change src/CMakeLists.txt and the #include to use Sdl2Application for both the native and the web build.

Bootstrap application for iOS

Fully contained base application using Sdl2Application for both desktop and iOS build along with pre-filled *.plist is available in base-ios branch of Magnum Bootstrap repository, download it as tar.gz or zip file. After extracting the downloaded archive, you can do the desktop build in the same way as above. For the iOS build you also need to put the contents of toolchains repository from https://github.com/mosra/toolchains in toolchains/ subdirectory.

Then create build directory and run cmake to generate the Xcode project. Set CMAKE_OSX_ROOT to SDK you want to target and enable all desired architectures in CMAKE_OSX_ARCHITECTURES. Set CMAKE_PREFIX_PATH to the directory where you have all the dependencies.

mkdir build-ios && cd build-ios
cmake .. \
    -DCMAKE_TOOLCHAIN_FILE=path/to/toolchains/generic/iOS.cmake \
    -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk \
    -DCMAKE_OSX_ARCHITECTURES="arm64;armv7;armv7s" \
    -DCMAKE_PREFIX_PATH=~/ios-libs \
    -G Xcode

You can then open the generated project file in Xcode and build/deploy it from there.

Bootstrap application for Windows RT

Fully contained base application using Sdl2Application for both desktop and Windows Phone / Windows Store build along with all required plumbing is available in base-winrt branch of Magnum Bootstrap repository, download it as zip file. After extracting the downloaded archive, you can do the desktop build in the same way as above.

For the Windows RT build you need to provide your own *.pfx certificate file and pass it to CMake in a SIGNING_CERTIFICATE variable. The bootstrap application assumes that SDL2 and ANGLE is built as DLL and both Corrade and Magnum are built statically. Assuming the native Corrade installation is in C:/Sys and all WinRT dependencies are in C:/Sys-winrt, the build can be done similarly to the following:

mkdir build-winrt && cd build-winrt
cmake .. ^
    -DCORRADE_RC_EXECUTABLE="C:/Sys/bin/corrade-rc.exe" ^
    -DCMAKE_PREFIX_PATH="C:/Sys-winrt" ^
    -DCMAKE_SYSTEM_NAME=WindowsStore ^
    -DCMAKE_SYSTEM_VERSION=8.1 ^
    -G "Visual Studio 14 2015" ^
    -DSIGNING_CERTIFICATE=<path-to-your-pfx-file>
cmake --build .

Change WindowsStore to WindowsPhone if you want to build for Windows Phone instead. The build-winrt/src/AppPackages directory will then contain the final package along with a PowerShell script for easy local installation.

General usage

This application library depends on the SDL2 library version 2.0.6 and newer. On Emscripten, the builtin minimal SDL implementation is used. The application library is built if MAGNUM_WITH_SDL2APPLICATION is enabled when building Magnum. To use this library with CMake, request the Sdl2Application component of the Magnum package and link to the Magnum::Sdl2Application target:

find_package(Magnum REQUIRED Sdl2Application)

# ...
target_link_libraries(your-app PRIVATE Magnum::Sdl2Application)

Additionally, if you're using Magnum as a CMake subproject, bundle the SDL repository and do the following before calling find_package() to ensure it's enabled, as the library is not built by default. If you want to use system-installed SDL2, omit the first part and point CMAKE_PREFIX_PATH to its installation dir if necessary.

# This is the most minimal set of features which still make Sdl2Application
# work. If you need something from these, remove the setting. The SDL_AUDIO and
# SDL_EVENT options should not be needed either as Magnum doesn't use them, but
# if they're disabled they causes compiler or linker errors. Either SDL_DLOPEN
# or SDL_LOADSO needs to be enabled depending on the system to allow linking
# dependencies at runtime, so it's better to just leave them both on. The
# SDL_TIMERS option is important for rendering performance.
set(SDL_ATOMIC OFF CACHE BOOL "" FORCE)
set(SDL_CPUINFO OFF CACHE BOOL "" FORCE)
set(SDL_FILE OFF CACHE BOOL "" FORCE)
set(SDL_FILESYSTEM OFF CACHE BOOL "" FORCE)
set(SDL_HAPTIC OFF CACHE BOOL "" FORCE)
set(SDL_LOCALE OFF CACHE BOOL "" FORCE)
set(SDL_POWER OFF CACHE BOOL "" FORCE)
set(SDL_RENDER OFF CACHE BOOL "" FORCE)
set(SDL_SENSOR OFF CACHE BOOL "" FORCE)
# This assumes you want to have SDL as a static library. If not, set SDL_STATIC
# to OFF instead.
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
add_subdirectory(SDL EXCLUDE_FROM_ALL)

set(MAGNUM_WITH_SDL2APPLICATION ON CACHE BOOL "" FORCE)
add_subdirectory(magnum EXCLUDE_FROM_ALL)

If no other application is requested, you can also use the generic Magnum::Application alias to simplify porting. Again, see Downloading and building and Usage with CMake for more information.

In C++ code you need to implement at least drawEvent() to be able to draw on the screen. The subclass can be then used directly in main() — see convenience macro MAGNUM_SDL2APPLICATION_MAIN(). See Platform support for more information.

class MyApplication: public Platform::Sdl2Application {
    // implement required methods...
};
MAGNUM_SDL2APPLICATION_MAIN(MyApplication)

If no other application header is included, this class is also aliased to Platform::Application and the macro is aliased to MAGNUM_APPLICATION_MAIN() to simplify porting.

Touch input in SDL2

The application recognizes touch input and reports it as Pointer::Finger and PointerEventSource::Touch. Because both mouse and touch events are exposed through a unified PointerEvent / PointerMoveEvent interface, there's no need for compatibility mouse events to be synthesized from touch events and vice versa, and thus given behavior is disabled in SDL. Pen input is still reported as a mouse because SDL has dedicated support for pen stylus only since SDL 3.

In case of a multi-touch scenario, PointerEvent::isPrimary() / PointerMoveEvent::isPrimary() can be used to distinguish the primary touch from secondary. For example, if an application doesn't need to recognize gestures like pinch to zoom or rotate, it can ignore all non-primary pointer events. PointerEventSource::Mouse events are always marked as primary, for touch input the first pressed finger is marked as primary and all following pressed fingers are non-primary. Note that there can be up to one primary pointer for each pointer event source, e.g. a finger and a mouse press may both be marked as primary. On the other hand, in a multi-touch scenario, if the first (and thus primary) finger is lifted, no other finger becomes primary until all others are lifted as well. The same logic is implemented in EmscriptenApplication and AndroidApplication.

If gesture recognition is desirable, PointerEvent::id() / PointerMoveEvent::id() contains a pointer ID that's unique among all pointer event sources, which can be used to track movements of secondary, tertiary and further touch points. The ID allocation is platform-specific and you can't rely on it to be contiguous or in any bounded range — for example, each new touch may generate a new ID that's only used until given finger is lifted, and then never again. For PointerEventSource::Mouse the ID is a constant, as there's always just a single mouse cursor.

See also Handling mouse, touch and pen events for general information about handling pointer input in a portable way. There's also a Platform::TwoFingerGesture helper for recognition of common two-finger gestures for zoom, rotation and pan.

Platform-specific behavior

Power management

SDL by default prevents the computer from powering off the or screen going to sleep. While possibly useful for game-like use cases, it's generally undesirable for regular applications. Sdl2Application turns this behavior off. You can restore SDL's default behavior by disabling the corresponding SDL hint through an environment variable or through SDL_SetHint() from your application.

SDL_VIDEO_ALLOW_SCREENSAVER=0 ./your-app

POSIX specifics

On POSIX systems, SDL by default intercepts the SIGTERM signal and generates an exit event for it, instead of doing the usual application exit. This would mean that if the application fails to set ExitEvent::setAccepted() in an exitEvent() override for some reason, pressing Ctrl C would not terminate it either and you'd have to forcibly kill it instead. Sdl2Application turns this behavior off, making exitEvent() behave consistently with other application implementations such as GlfwApplication. You can turn this behavior back on by enabling the corresponding SDL hint through an environment variable:

SDL_NO_SIGNAL_HANDLERS=1 ./your-app

See also the SDL Wiki for details.

Linux specifics

SDL by default attempts to disable compositing, which may cause ugly flickering for non-fullscreen apps (KWin, among others, is known to respect this setting). When using SDL >= 2.0.8, Sdl2Application turns this behavior off, keeping the compositor running to avoid the flicker. You can turn this behavior back on by enabling the corresponding SDL hint through an environment variable or through SDL_SetHint() from your application.

SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR=1 ./your-app

If you're running an older version of SDL, you can disallow apps from bypassing the compositor in system-wide KWin settings.

iOS specifics

Leaving a default (zero) window size in Configuration will cause the app to autodetect it based on the actual device screen size. This also depends on DPI awareness, see below for details.

As noted in the iOS platform guide, a lot of options needs to be set via a *.plist file. Some options can be configured from runtime when creating the SDL2 application window, see documentation of a particular value for details:

Emscripten specifics

On Emscripten, the builtin minimal SDL implementation is used, which is sufficiently complete, yet without a too large impact on binary sizes. In particular, the full SDL2 implementation, available when the -s USE_SDL=2 option is set, is not used, as it only significantly increases the generated binary size without really offering more. In any case, EmscriptenApplication is now the preferred application implementation for the web. It offers a broader range of features, more efficient idle behavior and smaller code size.

Leaving a default (zero) window size in Configuration will cause the app to use a window size that corresponds to CSS pixel size of the <canvas> element. The size is then multiplied by DPI scaling value, see DPI awareness below for details.

If you enable Configuration::WindowFlag::Resizable, the canvas will be resized when size of the canvas changes and you get viewportEvent(). If the flag is not enabled, no canvas resizing is performed.

OpenGL ES specifics

For OpenGL ES, SDL2 defaults to a "desktop GLES" context of the system driver. Because Magnum has the opposite default behavior, if MAGNUM_TARGET_GLES is not defined, Sdl2Application sets the SDL_HINT_OPENGL_ES_DRIVER hint to 1, forcing it to load symbols from a dedicated libGLES library instead, making SDL and Magnum consistently use the same OpenGL entrypoints. This change also allows ANGLE to be used on Windows simply by placing the corresponding libEGL.dll and libGLESv2.dll files next to the application executable.

DPI awareness

On displays that match the platform default DPI (96 or 72), Configuration::setSize() will create the window in exactly the requested size and the framebuffer pixels will match display pixels 1:1. On displays that have different DPI, there are three possible scenarios, listed below. It's possible to fine tune the behavior either using extra parameters passed to Configuration::setSize() or via the --magnum-dpi-scaling command-line option (or the equivalent $MAGNUM_DPI_SCALING environment variable).

  • Framebuffer DPI scaling. The window is created with exactly the requested size and all event coordinates are reported also relative to that size. However, the window backing framebuffer has a different size. This is only supported on macOS and iOS. See HiDPI (Retina) support for details how to enable it. Equivalent to passing Configuration::DpiScalingPolicy::Framebuffer to Configuration::setSize() or framebuffer via command line / environment.
  • Virtual DPI scaling. Scales the window based on DPI scaling setting in the system. For example if a 800x600 window is requested and DPI scaling is set to 200%, the resulting window will have 1600x1200 pixels. The backing framebuffer will have the same size. This is supported on Linux and Windows; on Windows the application is first checked for DPI awareness as described in HiDPI support and if the application is not DPI-aware, 1:1 scaling is used. Equivalent to passing Configuration::DpiScalingPolicy::Virtual to Configuration::setSize() or virtual on command line.
  • Physical DPI scaling. Takes the requested window size as a physical size that a window would have on platform's default DPI and scales it to have the same physical size on given display physical DPI. So, for example on a display with 240 DPI the window size will be 2000x1500 in pixels, but it will be 21 centimeters wide, the same as a 800x600 window would be on a 96 DPI display. On platforms that don't have a concept of a window (such as mobile platforms or Emscripten), it causes the framebuffer to match display pixels 1:1 without any scaling. This is supported on Linux and all mobile platforms (except iOS) and Emscripten. On Windows this is equivalent to virtual DPI scaling but without doing an explicit check for DPI awareness first. Equivalent to passing Configuration::DpiScalingPolicy::Physical to Configuration::setSize() or physical via command line / environment.

Besides the above, it's possible to supply a custom DPI scaling value to Configuration::setSize() or the --magnum-dpi-scaling command-line option (or environment variable). Using --magnum-dpi-scaling <number> will make the scaling same in both directions, with --magnum-dpi-scaling "<horizontal> <vertical>" the scaling will be different in each direction. On desktop systems custom DPI scaling value will affect physical window size (with the content being scaled), on mobile and web it will affect sharpness of the contents.

The default is depending on the platform:

With windowSize(), framebufferSize() and dpiScaling() having a different relation on each platform, the way to calculate context scaling consistently everywhere is using this expression:

Vector2 scaling = Vector2{framebufferSize()}*dpiScaling()/Vector2{windowSize()};

If your application is saving and restoring window size, it's advisable to take dpiScaling() into account:

  • Either divide the window size by the DPI scaling value and use that to restore the window next time — but note this might accumulate slight differences in window sizes over time, especially if fractional scaling is involved.
  • Or save the scaled size and use Configuration::setSize(const Vector2i&, const Vector2&) with 1.0f as custom DPI scaling next time — but this doesn't properly handle cases where the window is opened on a display with different DPI.

Public types

struct Arguments
Application arguments.
class Configuration
Configuration.
class ExitEvent
Exit event.
class GLConfiguration
OpenGL context configuration.
class InputEvent
Base for input events.
class KeyEvent
Key event.
class MouseEvent deprecated in Git master
Mouse event.
class MouseMoveEvent deprecated in Git master
Mouse move event.
class MouseScrollEvent deprecated in Git master
Mouse scroll event.
class MultiGestureEvent deprecated in Git master
Multi gesture event.
class PointerEvent new in Git master
Pointer event.
class PointerMoveEvent new in Git master
Pointer move event.
class ScrollEvent new in Git master
Scroll event.
class TextEditingEvent
Text editing event.
class TextInputEvent
Text input event.
class ViewportEvent
Viewport event.
enum class Modifier: Uint16 { Shift = KMOD_SHIFT, Ctrl = KMOD_CTRL, Alt = KMOD_ALT, Super = KMOD_GUI, AltGr = KMOD_MODE, CapsLock = KMOD_CAPS, NumLock = KMOD_NUM } new in Git master
Keyboard modifier.
enum class Key: SDL_Keycode { Unknown = SDLK_UNKNOWN, LeftShift = SDLK_LSHIFT, RightShift = SDLK_RSHIFT, LeftCtrl = SDLK_LCTRL, RightCtrl = SDLK_RCTRL, LeftAlt = SDLK_LALT, RightAlt = SDLK_RALT, LeftSuper = SDLK_LGUI, RightSuper = SDLK_RGUI, AltGr = SDLK_MODE, Enter = SDLK_RETURN, Esc = SDLK_ESCAPE, Up = SDLK_UP, Down = SDLK_DOWN, Left = SDLK_LEFT, Right = SDLK_RIGHT, Home = SDLK_HOME, End = SDLK_END, PageUp = SDLK_PAGEUP, PageDown = SDLK_PAGEDOWN, Backspace = SDLK_BACKSPACE, Insert = SDLK_INSERT, Delete = SDLK_DELETE, F1 = SDLK_F1, F2 = SDLK_F2, F3 = SDLK_F3, F4 = SDLK_F4, F5 = SDLK_F5, F6 = SDLK_F6, F7 = SDLK_F7, F8 = SDLK_F8, F9 = SDLK_F9, F10 = SDLK_F10, F11 = SDLK_F11, F12 = SDLK_F12, Space = SDLK_SPACE, Tab = SDLK_TAB, Quote = SDLK_QUOTE new in 2020.06, Comma = SDLK_COMMA, Period = SDLK_PERIOD, Minus = SDLK_MINUS, Plus = SDLK_PLUS, Slash = SDLK_SLASH, Percent = SDLK_PERCENT, Semicolon = SDLK_SEMICOLON, Equal = SDLK_EQUALS, LeftBracket = SDLK_LEFTBRACKET new in 2020.06, RightBracket = SDLK_RIGHTBRACKET new in 2020.06, Backslash = SDLK_BACKSLASH new in 2020.06, Backquote = SDLK_BACKQUOTE new in 2020.06, Zero = SDLK_0, One = SDLK_1, Two = SDLK_2, Three = SDLK_3, Four = SDLK_4, Five = SDLK_5, Six = SDLK_6, Seven = SDLK_7, Eight = SDLK_8, Nine = SDLK_9, A = SDLK_a, B = SDLK_b, C = SDLK_c, D = SDLK_d, E = SDLK_e, F = SDLK_f, G = SDLK_g, H = SDLK_h, I = SDLK_i, J = SDLK_j, K = SDLK_k, L = SDLK_l, M = SDLK_m, N = SDLK_n, O = SDLK_o, P = SDLK_p, Q = SDLK_q, R = SDLK_r, S = SDLK_s, T = SDLK_t, U = SDLK_u, V = SDLK_v, W = SDLK_w, X = SDLK_x, Y = SDLK_y, Z = SDLK_z, CapsLock = SDLK_CAPSLOCK new in Git master, ScrollLock = SDLK_SCROLLLOCK new in Git master, NumLock = SDLK_NUMLOCKCLEAR new in Git master, PrintScreen = SDLK_PRINTSCREEN new in Git master, Pause = SDLK_PAUSE new in Git master, Menu = SDLK_APPLICATION new in Git master, NumZero = SDLK_KP_0, NumOne = SDLK_KP_1, NumTwo = SDLK_KP_2, NumThree = SDLK_KP_3, NumFour = SDLK_KP_4, NumFive = SDLK_KP_5, NumSix = SDLK_KP_6, NumSeven = SDLK_KP_7, NumEight = SDLK_KP_8, NumNine = SDLK_KP_9, NumDecimal = SDLK_KP_DECIMAL, NumDivide = SDLK_KP_DIVIDE, NumMultiply = SDLK_KP_MULTIPLY, NumSubtract = SDLK_KP_MINUS, NumAdd = SDLK_KP_PLUS, NumEnter = SDLK_KP_ENTER, NumEqual = SDLK_KP_EQUALS } new in Git master
Key.
enum class PointerEventSource: UnsignedByte { Mouse, Touch } new in Git master
Pointer event source.
enum class Pointer: UnsignedByte { MouseLeft = 1 << 0, MouseMiddle = 1 << 1, MouseRight = 1 << 2, MouseButton4 = 1 << 3, MouseButton5 = 1 << 4, Finger = 1 << 5 } new in Git master
Pointer type.
using Modifiers = Containers::EnumSet<Modifier> new in Git master
Set of keyboard modifiers.
using Pointers = Containers::EnumSet<Pointer> new in Git master
Set of pointer types.

Public static functions

static auto keyName(Key key) -> Containers::StringView new in Git master
Name for given key.
static auto scanCodeName(UnsignedInt scanCode) -> Containers::StringView new in Git master
Name for given key scan code.
static auto keyToScanCode(Key key) -> Containers::Optional<UnsignedInt> new in Git master
Scan code for given key.
static auto scanCodeToKey(UnsignedInt scanCode) -> Containers::Optional<Key> new in Git master
Scan code for given key.

Constructors, destructors, conversion operators

Sdl2Application(const Arguments& arguments, const Configuration& configuration, const GLConfiguration& glConfiguration) explicit
Construct with an OpenGL context.
Sdl2Application(const Arguments& arguments, const Configuration& configuration = Configuration{}) explicit
Construct without explicit GPU context configuration.
Sdl2Application(const Arguments& arguments, NoCreateT) explicit
Construct without creating a window.
Sdl2Application(const Sdl2Application&) deleted
Copying is not allowed.
Sdl2Application(Sdl2Application&&) deleted
Moving is not allowed.

Public functions

auto operator=(const Sdl2Application&) -> Sdl2Application& deleted
Copying is not allowed.
auto operator=(Sdl2Application&&) -> Sdl2Application& deleted
Moving is not allowed.
auto exec() -> int
Execute application main loop.
auto mainLoopIteration() -> bool
Run one iteration of application main loop.
void exit(int exitCode = 0)
Exit application.
auto window() -> SDL_Window*
Underlying window handle.
auto glContext() -> SDL_GLContext new in 2019.10
Underlying OpenGL context.

Protected functions

void create(const Configuration& configuration, const GLConfiguration& glConfiguration)
Create a window with given configuration for OpenGL context.
void create(const Configuration& configuration)
Create a window with given configuration.
void create()
Create a window with default configuration and OpenGL context.
auto tryCreate(const Configuration& configuration, const GLConfiguration& glConfiguration) -> bool
Try to create context with given configuration for OpenGL context.
auto tryCreate(const Configuration& configuration) -> bool
Try to create context with given configuration.

Screen handling

auto windowSize() const -> Vector2i
Window size.
void setWindowSize(const Vector2i& size) new in 2020.06
Set window size.
void setMinWindowSize(const Vector2i& size) new in 2019.10
Set minimum window size.
void setMaxWindowSize(const Vector2i& size) new in 2019.10
Set maximal window size.
auto framebufferSize() const -> Vector2i
Framebuffer size.
auto dpiScaling() const -> Vector2
DPI scaling.
auto dpiScaling(const Configuration& configuration) -> Vector2
DPI scaling for given configuration.
void setWindowTitle(Containers::StringView title) new in 2019.10
Set window title.
void setWindowIcon(const ImageView2D& image) new in 2020.06
Set window icon.
void setContainerCssClass(Containers::StringView cssClass)
Set container CSS class.
void swapBuffers()
Swap buffers.
auto swapInterval() const -> Int
Swap interval.
auto setSwapInterval(Int interval) -> bool
Set swap interval.
void setMinimalLoopPeriod(Nanoseconds time) new in Git master
Set minimal loop period.
void setMinimalLoopPeriod(UnsignedInt milliseconds) deprecated in Git master
Set minimal loop period.
void redraw()
Redraw immediately.
void viewportEvent(ViewportEvent& event) private virtual
Viewport event.
void drawEvent() private pure virtual
Draw event.

Keyboard handling

void keyPressEvent(KeyEvent& event) private virtual
Key press event.
void keyReleaseEvent(KeyEvent& event) private virtual
Key release event.

Pointer handling

enum class Cursor: UnsignedInt { Arrow, TextInput, Wait, Crosshair, WaitArrow, ResizeNWSE, ResizeNESW, ResizeWE, ResizeNS, ResizeAll, No, Hand, Hidden, HiddenLocked } new in 2020.06
Cursor type.
void setCursor(Cursor cursor) new in 2020.06
Set cursor type.
auto cursor() -> Cursor new in 2020.06
Get current cursor type.
void warpCursor(const Vector2i& position)
Warp mouse cursor to given coordinates.
auto isMouseLocked() const -> bool deprecated in 2020.06
Whether mouse is locked.
void setMouseLocked(bool enabled) deprecated in 2020.06
Enable or disable mouse locking.
void pointerPressEvent(PointerEvent& event) private virtual new in Git master
Pointer press event.
void mousePressEvent(MouseEvent& event) deprecated in Git master private virtual
Mouse press event.
void pointerReleaseEvent(PointerEvent& event) private virtual new in Git master
Pointer release event.
void mouseReleaseEvent(MouseEvent& event) deprecated in Git master private virtual
Mouse release event.
void pointerMoveEvent(PointerMoveEvent& event) private virtual new in Git master
Pointer move event.
void mouseMoveEvent(MouseMoveEvent& event) deprecated in Git master private virtual
Mouse move event.
void scrollEvent(ScrollEvent& event) private virtual new in Git master
Scroll event.
void mouseScrollEvent(MouseScrollEvent& event) deprecated in Git master private virtual
Mouse move event.
void multiGestureEvent(MultiGestureEvent& event) deprecated in Git master private virtual
Multi gesture event.

Text input handling

auto isTextInputActive() -> bool
Whether text input is active.
void startTextInput()
Start text input.
void stopTextInput()
Stop text input.
void setTextInputRect(const Range2Di& rect)
Set text input rectangle.
void textInputEvent(TextInputEvent& event) private virtual
Text input event.
void textEditingEvent(TextEditingEvent& event) private virtual
Text editing event.

Special events

void tickEvent() protected virtual
Tick event.
void exitEvent(ExitEvent& event) private virtual
Exit event.
void anyEvent(SDL_Event& event) private virtual
Any event.

Enum documentation

enum class Magnum::Platform::Sdl2Application::Key: SDL_Keycode new in Git master

Key.

Enumerators
Unknown

Unknown key

LeftShift

Left Shift

RightShift

Right Shift

LeftCtrl

Left Ctrl

RightCtrl

Right Ctrl

LeftAlt

Left Alt

RightAlt

Right Alt

LeftSuper

Left Super key (Windows/⌘)

RightSuper

Right Super key (Windows/⌘)

AltGr

AltGr

Enter

Enter

Esc

Escape

Up

Up arrow

Down

Down arrow

Left

Left arrow

Right

Right arrow

Home

Home

End

End

PageUp

Page up

PageDown

Page down

Backspace

Backspace

Insert

Insert

Delete

Delete

F1

F1

F2

F2

F3

F3

F4

F4

F5

F5

F6

F6

F7

F7

F8

F8

F9

F9

F10

F10

F11

F11

F12

F12

Space

Space

Tab

Tab

Quote new in 2020.06

Quote (')

Comma

Comma

Period

Period

Minus

Minus

Plus

Plus. On the US keyboard layout this may only be representable as Shift =.

Slash

Slash

Percent

Percent. On the US keyboard layout this may only be representable as Shift 5.

Semicolon

Semicolon (;)

Equal

Equal

LeftBracket new in 2020.06

Left bracket ([)

RightBracket new in 2020.06

Right bracket (])

Backslash new in 2020.06

Backslash (\)

Backquote new in 2020.06

Backquote (`)

Zero

Zero

One

One

Two

Two

Three

Three

Four

Four

Five

Five

Six

Six

Seven

Seven

Eight

Eight

Nine

Nine

A

Letter A

B

Letter B

C

Letter C

D

Letter D

E

Letter E

F

Letter F

G

Letter G

H

Letter H

I

Letter I

J

Letter J

K

Letter K

L

Letter L

M

Letter M

N

Letter N

O

Letter O

P

Letter P

Q

Letter Q

R

Letter R

S

Letter S

T

Letter T

U

Letter U

V

Letter V

W

Letter W

X

Letter X

Y

Letter Y

Z

Letter Z

CapsLock new in Git master

Caps lock

ScrollLock new in Git master

Scroll lock

NumLock new in Git master

Num lock

PrintScreen new in Git master

Print screen

Pause new in Git master

Pause

Menu new in Git master

Menu

NumZero

Numpad zero

NumOne

Numpad one

NumTwo

Numpad two

NumThree

Numpad three

NumFour

Numpad four

NumFive

Numpad five

NumSix

Numpad six

NumSeven

Numpad seven

NumEight

Numpad eight

NumNine

Numpad nine

NumDecimal

Numpad decimal

NumDivide

Numpad divide

NumMultiply

Numpad multiply

NumSubtract

Numpad subtract

NumAdd

Numpad add

NumEnter

Numpad enter

NumEqual

Numpad equal

enum class Magnum::Platform::Sdl2Application::PointerEventSource: UnsignedByte new in Git master

Pointer event source.

Enumerators
Mouse

The event is coming from a mouse. Corresponds to the SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP and SDL_MOUSEMOTION events.

Touch

The event is coming from a touch contact. Corresponds to the SDL_FINGERDOWN, SDL_FINGERUP and SDL_FINGERMOTION events.

enum class Magnum::Platform::Sdl2Application::Pointer: UnsignedByte new in Git master

Pointer type.

Enumerators
MouseLeft

Left mouse button. Corresponds to SDL_BUTTON_LEFT / SDL_BUTTON_LMASK.

MouseMiddle

Middle mouse button. Corresponds to SDL_BUTTON_MIDDLE / SDL_BUTTON_MMASK.

MouseRight

Right mouse button. Corresponds to SDL_BUTTON_RIGHT / SDL_BUTTON_RMASK.

MouseButton4

Fourth mouse button, such as wheel left. Corresponds to SDL_BUTTON_X1 / SDL_BUTTON_X1MASK.

MouseButton5

Fifth mouse button, such as wheel right. Corresponds to SDL_BUTTON_X2 / SDL_BUTTON_X2MASK.

Finger

Finger

enum class Magnum::Platform::Sdl2Application::Cursor: UnsignedInt new in 2020.06

Cursor type.

Enumerators
Arrow

Arrow

TextInput

Text input

Wait

Wait

Crosshair

Crosshair

WaitArrow

Small wait cursor

ResizeNWSE

Double arrow pointing northwest and southeast

ResizeNESW

Double arrow pointing northeast and southwest

ResizeWE

Double arrow pointing west and east

ResizeNS

Double arrow pointing north and south

ResizeAll

Four pointed arrow pointing north, south, east, and west

No

Slashed circle or crossbones

Hand

Hand

Hidden

Hidden

HiddenLocked

Hidden and locked. When the mouse is locked, only MouseMoveEvent::relativePosition() is changing, absolute position stays the same.

Typedef documentation

typedef Containers::EnumSet<Pointer> Magnum::Platform::Sdl2Application::Pointers new in Git master

Set of pointer types.

Function documentation

static Containers::StringView Magnum::Platform::Sdl2Application::keyName(Key key) new in Git master

Name for given key.

Human-readable localized UTF-8 name for given key, intended for displaying to the user in e.g. a key binding configuration. If there is no name for given key, empty string is returned. The returned view is always Containers::StringViewFlag::NullTerminated and is valid at least until the next call to this function, to KeyEvent::keyName() const or to the underlying SDL_GetKeyName() API.

static Containers::StringView Magnum::Platform::Sdl2Application::scanCodeName(UnsignedInt scanCode) new in Git master

Name for given key scan code.

Human-readable localized UTF-8 name for given scancode. Note that unlike keyName(), the scancode names are not consistent across platforms. If there is no name for given scancode, empty string is returned. The returned view is always Containers::StringViewFlag::NullTerminated and is valid at least until the next call to this function, to KeyEvent::scanCodeName() const or to the underlying SDL_GetScancodeName() API.

static Containers::Optional<UnsignedInt> Magnum::Platform::Sdl2Application::keyToScanCode(Key key) new in Git master

Scan code for given key.

If key doesn't correspond to a physical key supported on given platform, returns Containers::NullOpt. Note that this is implemented as a linear lookup inside SDL, prefer to query the scan code directly via KeyEvent::scanCode() rather than converting it from a KeyEvent::key() at a later time.

static Containers::Optional<Key> Magnum::Platform::Sdl2Application::scanCodeToKey(UnsignedInt scanCode) new in Git master

Scan code for given key.

If scanCode isn't a known scan code, returns Containers::NullOpt.

Magnum::Platform::Sdl2Application::Sdl2Application(const Arguments& arguments, const Configuration& configuration, const GLConfiguration& glConfiguration) explicit

Construct with an OpenGL context.

Parameters
arguments Application arguments
configuration Application configuration
glConfiguration OpenGL context configuration

Creates application with default or user-specified configuration. See Configuration for more information. The program exits if the context cannot be created, see tryCreate() for an alternative.

Magnum::Platform::Sdl2Application::Sdl2Application(const Arguments& arguments, const Configuration& configuration = Configuration{}) explicit

Construct without explicit GPU context configuration.

If Configuration::WindowFlag::Contextless is present or Magnum was not built with MAGNUM_TARGET_GL, this creates a window without any GPU context attached, leaving that part on the user.

If none of the flags is present and Magnum was built with MAGNUM_TARGET_GL, this is equivalent to calling Sdl2Application(const Arguments&, const Configuration&, const GLConfiguration&) with default-constructed GLConfiguration.

See also Enabling or disabling features for more information.

Magnum::Platform::Sdl2Application::Sdl2Application(const Arguments& arguments, NoCreateT) explicit

Construct without creating a window.

Parameters
arguments Application arguments

Unlike above, the window is not created and must be created later with create() or tryCreate().

int Magnum::Platform::Sdl2Application::exec()

Execute application main loop.

Returns Value for returning from main()

Calls mainLoopIteration() in a loop until exit() is called. See MAGNUM_SDL2APPLICATION_MAIN() for usage information.

bool Magnum::Platform::Sdl2Application::mainLoopIteration()

Run one iteration of application main loop.

Returns false if exit() was called and the application should exit, true otherwise

Called internally from exec(). If you want to have better control over how the main loop behaves, you can call this function yourself from your own main() function instead of it being called automatically from exec() / MAGNUM_SDL2APPLICATION_MAIN().

void Magnum::Platform::Sdl2Application::exit(int exitCode = 0)

Exit application.

Parameters
exitCode The exit code the application should return

When called from application constructor, it will cause the application to exit immediately after constructor ends, without entering the event loop. When called from within an event handler, it will cause it to exit at the start of next event loop iteration. Compared to requesting an application exit using the window close button or the Alt F4 / Cmd Q keyboard shortcut, the exitEvent() isn't called when using this function.

Calling this function from an application constructor is recommended over std::exit() or Fatal, which exit without calling destructors on local scope. Note that, however, you need to explicitly return after calling it, as it can't exit the constructor on its own:

MyApplication::MyApplication(const Arguments& arguments):
    Platform::Application{arguments, NoCreate}
{
    // …

    if(!everythingGoingAsExpected) {
        exit(1);
        return;
    }

    // …
}

SDL_Window* Magnum::Platform::Sdl2Application::window()

Underlying window handle.

Use in case you need to call SDL functionality directly. Returns nullptr in case the window was not created yet.

SDL_GLContext Magnum::Platform::Sdl2Application::glContext() new in 2019.10

Underlying OpenGL context.

Use in case you need to call SDL functionality directly. Returns nullptr in case the context was not created yet.

void Magnum::Platform::Sdl2Application::create(const Configuration& configuration, const GLConfiguration& glConfiguration) protected

Create a window with given configuration for OpenGL context.

Parameters
configuration Application configuration
glConfiguration OpenGL context configuration

Must be called only if the context wasn't created by the constructor itself, i.e. when passing NoCreate to it. Error message is printed and the program exits if the context cannot be created, see tryCreate() for an alternative.

On desktop GL, if version is not specified in glConfiguration, the application first tries to create core context (OpenGL 3.2+ on macOS, OpenGL 3.1+ elsewhere) and if that fails, falls back to compatibility OpenGL 2.1 context.

void Magnum::Platform::Sdl2Application::create(const Configuration& configuration) protected

Create a window with given configuration.

If Configuration::WindowFlag::Contextless is present or Magnum was not built with MAGNUM_TARGET_GL, this creates a window without any GPU context attached, leaving that part on the user.

If none of the flags is present and Magnum was built with MAGNUM_TARGET_GL, this is equivalent to calling create(const Configuration&, const GLConfiguration&) with default-constructed GLConfiguration.

See also Enabling or disabling features for more information.

void Magnum::Platform::Sdl2Application::create() protected

Create a window with default configuration and OpenGL context.

Equivalent to calling create(const Configuration&) with default-constructed Configuration.

bool Magnum::Platform::Sdl2Application::tryCreate(const Configuration& configuration, const GLConfiguration& glConfiguration) protected

Try to create context with given configuration for OpenGL context.

Unlike create(const Configuration&, const GLConfiguration&) returns false if the context cannot be created, true otherwise.

bool Magnum::Platform::Sdl2Application::tryCreate(const Configuration& configuration) protected

Try to create context with given configuration.

Unlike create(const Configuration&) returns false if the context cannot be created, true otherwise.

Vector2i Magnum::Platform::Sdl2Application::windowSize() const

Window size.

Window size to which all input event coordinates can be related. Note that, especially on HiDPI systems, it may be different from framebufferSize(). Expects that a window is already created. See DPI awareness for more information.

void Magnum::Platform::Sdl2Application::setWindowSize(const Vector2i& size) new in 2020.06

Set window size.

Parameters
size The size, in screen coordinates

To make the sizing work independently of the display DPI, size is internally multiplied with dpiScaling() before getting applied. Expects that a window is already created.

void Magnum::Platform::Sdl2Application::setMinWindowSize(const Vector2i& size) new in 2019.10

Set minimum window size.

Parameters
size The minimum size, in screen coordinates

Note that, unlike in GlfwApplication, SDL2 doesn't have a way to disable/remove a size limit. To make the sizing work independently of the display DPI, size is internally multiplied with dpiScaling() before getting applied. Expects that a window is already created.

void Magnum::Platform::Sdl2Application::setMaxWindowSize(const Vector2i& size) new in 2019.10

Set maximal window size.

Parameters
size The maximum size, in screen coordinates

Note that, unlike in GlfwApplication, SDL2 doesn't have a way to disable/remove a size limit. To make the sizing work independently of the display DPI, size is internally multiplied with dpiScaling() before getting applied. Expects that a window is already created.

Vector2i Magnum::Platform::Sdl2Application::framebufferSize() const

Framebuffer size.

Size of the default framebuffer. Note that, especially on HiDPI systems, it may be different from windowSize(). Expects that a window is already created. See DPI awareness for more information.

Vector2 Magnum::Platform::Sdl2Application::dpiScaling() const

DPI scaling.

How the content should be scaled relative to system defaults for given windowSize(). If a window is not created yet, returns zero vector, use dpiScaling(const Configuration&) for calculating a value independently. See DPI awareness for more information.

Vector2 Magnum::Platform::Sdl2Application::dpiScaling(const Configuration& configuration)

DPI scaling for given configuration.

Calculates DPI scaling that would be used when creating a window with given configuration. Takes into account DPI scaling policy and custom scaling specified on the command-line. See DPI awareness for more information.

void Magnum::Platform::Sdl2Application::setWindowTitle(Containers::StringView title) new in 2019.10

Set window title.

The title is expected to be encoded in UTF-8.

void Magnum::Platform::Sdl2Application::setWindowIcon(const ImageView2D& image) new in 2020.06

Set window icon.

The image is expected to be with origin at bottom left (which is the default for imported images) and in one of PixelFormat::RGB8Unorm, PixelFormat::RGB8Srgb, PixelFormat::RGBA8Unorm or PixelFormat::RGBA8Srgb formats. Unlike GlfwApplication::setWindowIcon(), SDL doesn't provide a way to supply multiple images in different sizes.

void Magnum::Platform::Sdl2Application::setContainerCssClass(Containers::StringView cssClass)

Set container CSS class.

Assigns given CSS class to the <div class="mn-container"> enclosing the application <canvas>. Useful for example to change aspect ratio of the view or stretch it to cover the full page. See Modifying page style, canvas size and aspect ratio for more information about possible values. Note that this replaces any existing class (except for .mn-container, which is kept), to set multiple classes separate them with whitespace.

void Magnum::Platform::Sdl2Application::swapBuffers()

Swap buffers.

Paints currently rendered framebuffer on screen.

bool Magnum::Platform::Sdl2Application::setSwapInterval(Int interval)

Set swap interval.

Set 0 for no VSync, 1 for enabled VSync. Some platforms support -1 for late swap tearing. Prints error message and returns false if swap interval cannot be set, true otherwise. Default is driver-dependent, you can query the value with swapInterval().

void Magnum::Platform::Sdl2Application::setMinimalLoopPeriod(Nanoseconds time) new in Git master

Set minimal loop period.

This setting reduces the main loop frequency in case setSwapInterval() wasn't called at all, was called with 0, the call failed, or no drawing is done and just tickEvent() is being executed. The time is expected to be non-negative, default is 0_nsec (i.e., looping at maximum frequency). If the application is drawing on the screen and VSync was enabled by calling setSwapInterval(), this setting is ignored.

Note that SDL timer resolution is just milliseconds, so anything below 1.0_msec will behave the same as 0_nsec. As the VSync default is driver-dependent, setSwapInterval() has to be explicitly called to make the interaction between the two work correctly.

void Magnum::Platform::Sdl2Application::setMinimalLoopPeriod(UnsignedInt milliseconds)

Set minimal loop period.

void Magnum::Platform::Sdl2Application::redraw()

Redraw immediately.

Marks the window for redrawing, resulting in call to drawEvent() in the next iteration. You can call it from drawEvent() itself to redraw immediately without waiting for user input.

void Magnum::Platform::Sdl2Application::viewportEvent(ViewportEvent& event) virtual private

Viewport event.

Called when window size changes. The default implementation does nothing. If you want to respond to size changes, you should pass the new framebuffer size to GL::DefaultFramebuffer::setViewport() (if using OpenGL) and possibly elsewhere (to SceneGraph::Camera::setViewport(), other framebuffers...) and the new window size and DPI scaling to APIs that respond to user events or scale UI elements.

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 windowSize(), size of the backing framebuffer via framebufferSize() and DPI scaling using dpiScaling(). See DPI awareness for detailed info about these values.

void Magnum::Platform::Sdl2Application::drawEvent() pure virtual private

Draw event.

Called when the screen is redrawn. You should clean the framebuffer using GL::DefaultFramebuffer::clear() (if using OpenGL) and then add your own drawing functions. After drawing is finished, call swapBuffers(). If you want to draw immediately again, call also redraw().

void Magnum::Platform::Sdl2Application::keyPressEvent(KeyEvent& event) virtual private

Key press event.

Called when a key is pressed. Default implementation does nothing.

void Magnum::Platform::Sdl2Application::keyReleaseEvent(KeyEvent& event) virtual private

Key release event.

Called when a key is released. Default implementation does nothing.

void Magnum::Platform::Sdl2Application::setCursor(Cursor cursor) new in 2020.06

Set cursor type.

Expects that a window is already created. Default is Cursor::Arrow.

void Magnum::Platform::Sdl2Application::warpCursor(const Vector2i& position)

Warp mouse cursor to given coordinates.

bool Magnum::Platform::Sdl2Application::isMouseLocked() const

Whether mouse is locked.

void Magnum::Platform::Sdl2Application::setMouseLocked(bool enabled)

Enable or disable mouse locking.

void Magnum::Platform::Sdl2Application::pointerPressEvent(PointerEvent& event) virtual private new in Git master

Pointer press event.

Called when either a mouse or a finger is pressed. Note that if at least one mouse button is already pressed and another button gets pressed in addition, pointerMoveEvent() with the new combination is called, not this function.

On builds with MAGNUM_BUILD_DEPRECATED enabled, if the pointer is primary, default implementation delegates to mousePressEvent(), interpreting Pointer::Finger as MouseEvent::Button::Left. On builds with deprecated functionality disabled, default implementation does nothing.

void Magnum::Platform::Sdl2Application::mousePressEvent(MouseEvent& event) virtual private

Mouse press event.

Default implementation does nothing.

void Magnum::Platform::Sdl2Application::pointerReleaseEvent(PointerEvent& event) virtual private new in Git master

Pointer release event.

Called when either a mouse or a finger is released. Note that if multiple mouse buttons are pressed and one of these is released, pointerMoveEvent() with the new combination is called, not this function.

On builds with MAGNUM_BUILD_DEPRECATED enabled, if the pointer is primary, default implementation delegates to mouseReleaseEvent(), interpreting Pointer::Finger as MouseEvent::Button::Left. On builds with deprecated functionality disabled, default implementation does nothing.

void Magnum::Platform::Sdl2Application::mouseReleaseEvent(MouseEvent& event) virtual private

Mouse release event.

Default implementation does nothing.

void Magnum::Platform::Sdl2Application::pointerMoveEvent(PointerMoveEvent& event) virtual private new in Git master

Pointer move event.

Called when any of the currently pressed pointers is moved or changes its properties. Gets called also if the set of pressed mouse buttons changes.

On builds with MAGNUM_BUILD_DEPRECATED enabled, if the pointer is primary, default implementation delegates to mouseMoveEvent(), or if PointerMoveEvent::pointer() is not Containers::NullOpt, to either mousePressEvent() or mouseReleaseEvent(). Pointer::Finger is interpreted as MouseEvent::Button::Left. On builds with deprecated functionality disabled, default implementation does nothing.

void Magnum::Platform::Sdl2Application::mouseMoveEvent(MouseMoveEvent& event) virtual private

Mouse move event.

Default implementation does nothing.

void Magnum::Platform::Sdl2Application::scrollEvent(ScrollEvent& event) virtual private new in Git master

Scroll event.

Called when a scrolling device is used (mouse wheel or scrolling area on a touchpad).

On builds with MAGNUM_BUILD_DEPRECATED enabled, default implementation delegates to mouseScrollEvent(). On builds with deprecated functionality disabled, default implementation does nothing.

void Magnum::Platform::Sdl2Application::mouseScrollEvent(MouseScrollEvent& event) virtual private

Mouse move event.

Default implementation does nothing.

void Magnum::Platform::Sdl2Application::multiGestureEvent(MultiGestureEvent& event) virtual private

Multi gesture event.

Called when the user performs a gesture using multiple fingers. Default implementation does nothing.

bool Magnum::Platform::Sdl2Application::isTextInputActive()

Whether text input is active.

If text input is active, text input events go to textInputEvent() and textEditingEvent().

void Magnum::Platform::Sdl2Application::startTextInput()

Start text input.

Starts text input that will go to textInputEvent() and textEditingEvent().

void Magnum::Platform::Sdl2Application::stopTextInput()

Stop text input.

Stops text input that went to textInputEvent() and textEditingEvent().

void Magnum::Platform::Sdl2Application::setTextInputRect(const Range2Di& rect)

Set text input rectangle.

The rect defines an area where the text is being displayed, for example to hint the system where to place on-screen keyboard.

void Magnum::Platform::Sdl2Application::textInputEvent(TextInputEvent& event) virtual private

Text input event.

Called when text input is active and the text is being input.

void Magnum::Platform::Sdl2Application::textEditingEvent(TextEditingEvent& event) virtual private

Text editing event.

Called when text input is active and the text is being edited.

void Magnum::Platform::Sdl2Application::tickEvent() virtual protected

Tick event.

If implemented, this function is called periodically after processing all input events and before draw event even though there might be no input events and redraw is not requested. Useful e.g. for asynchronous task polling. Use setMinimalLoopPeriod() / setSwapInterval() to control main loop frequency.

If this implementation gets called from its override, it will effectively stop the tick event from being fired and the app returns back to waiting for input events. This can be used to disable the tick event when not needed.

void Magnum::Platform::Sdl2Application::exitEvent(ExitEvent& event) virtual private

Exit event.

If implemented, it allows the application to react to an application exit (for example to save its internal state) and suppress it as well (for example to show a exit confirmation dialog). The default implementation calls ExitEvent::setAccepted() on event, which tells the application that it's safe to exit.

SDL has special behavior on POSIX systems regarding SIGINT and SIGTERM handling, see POSIX specifics for more information.

void Magnum::Platform::Sdl2Application::anyEvent(SDL_Event& event) virtual private

Any event.

Called in case a SDL event is not handled by any other event functions above.