diff --git a/doc/portability.dox b/doc/portability.dox new file mode 100644 index 000000000..673ca1f42 --- /dev/null +++ b/doc/portability.dox @@ -0,0 +1,177 @@ +namespace Magnum { +/** @page portability Writing portable applications +@brief How to support different platforms and different OpenGL capabilities within one codebase. + +@tableofcontents + +@section portability-target Target-specific code + +If %Magnum is compiled with e.g. OpenGL ES 2.0 support, some features present +in desktop version are not available. It means that some classes, functions +and enum values are simply not included in headers. It is designed this way to +make porting easier -- it is better to fail at compile time on e.g. undefined +enum value than fail at runtime in some corner case because given texture +format is not supported. + +If you include Magnum.h, you get these predefined macros: + + - `MAGNUM_TARGET_GLES` if targetting OpenGL ES 2.0 or 3.0 + - `MAGNUM_TARGET_GLES2` if targetting OpenGL ES 2.0 + - `MAGNUM_TARGET_NACL` if targetting Google Chrome Native Client + +Example usage: +@code +#ifndef MAGNUM_TARGET_GLES +Mesh::setPolygonMode(Mesh::PolygonMode::Lines); +// draw mesh as wireframe... +#else +// use different mesh, as polygon mode is not supported in OpenGL ES... +#endif +@endcode + +Each feature is marked accordingly if it is not available in some targets. See +also @ref requires-gl and @ref requires-gles30. + +@section portability-compiler Compiler-specific code + +%Magnum is attempting to be future-proof and as intuitive for users as +possible. Many features from C++11 are used to simplify things and make them +faster and more secure, but on the other hand it requires fairly recent +compiler with good enough support of the new standard. Currently %Magnum is +written with GCC 4.7 and Clang 3.1 in mind, but support for some other +compilers is also available: + + - GCC 4.6 support can be explicitly enabled with CMake option + `MAGNUM_GCC46_COMPATIBILITY` + +The options are also available as predefined macros when including Magnum.h. + +Each feature is marked accordingly if it is not available on some compilers, +see @ref SceneGraph::DrawableGroup3D for an example. It is up to you (or your +platform) which compiler your code will support, code written for GCC 4.7 will +work also on Magnum compiled with support for older compilers. + +@section portability-extensions Extension-aware code + +Some functionality is depending on support of particular extension and thus +the decision cannot be made at compile time. Header Extensions.h contains list +of extensions, which you can pass to Context::isExtensionSupported() and +decide based on that: +@code +if(Context::instance()->isExtensionSupported()) { + // draw mesh with wireframe on top in one pass using geometry shader... +} else { + // draw underlying mesh... + Mesh::setPolygonMode(Mesh::PolygonMode::Lines); + // draw mesh as wirefreame in second pass... +} +@endcode + +You can also decide on particular OpenGL version using Context::isVersionSupported(), +but remember that some features from that version might be available even if +the drivers don't expose that version. + +Each feature is marked accordingly if it needs specific extension or specific +OpenGL version. Various classes in %Magnum are taking advantage of some +extensions and enable faster code paths if given extension is available, for +example @ref AbstractShaderProgram-performance-optimization "AbstractShaderProgram", +@ref AbstractTexture-performance-optimization "AbstractTexture" or +@ref Mesh-performance-optimization "Mesh". See also @ref required-extensions. + +@section portability-shaders Portable shaders + +%Shaders are probably the most painful thing to port. There are many issues to +address - different shader syntax (`in`/`out` vs. `attribute` and `varying` +etc.), explicit vs. implicit methods to specify vertex attribute, uniform and +texture uniform locations, required precision qualifiers in OpenGL ES etc. + +Shader class allows you to explicitly specify shader version and based on that +you can decide on the syntax in your shader code. You can also use +Context::supportedVersion() to conveniently select highest supported version +from a list: +@code +// MyShader.vert +#if __VERSION__ < 130 +#define in attribute +#define out varying +#endif + +in vec4 position; +in vec3 normal; + +out vec4 transformedNormal; + +void main() { + // ... +} +@endcode +@code +// MyShader.cpp +Version version = Context::instance()->supportedVersion({Version::GL430, Version::GL330, Version::GL210}); +attachShader(Shader::fromFile(version, "MyShader.vert")); +@endcode + +All shaders in Shaders namespace support desktop OpenGL starting from version +2.1 and also OpenGL ES 2.0 and 3.0. Feel free to look into their sources to +see how portability is handled there. + +@section portability-applications Platform-specific application support + +Your application might run on Windows box, on some embedded Linux or even in +browser - each platform has different requirements how to create entry point +to the application, how to handle input events, how to create window and +OpenGL context etc. Namespace Platform contains base classes for applications +which are abstracting most of it for your convenience. + +All the classes support limited form of static polymorphism, which means you +can switch to another base class and probably don't need to change any other +code. It has its limitations, though - some toolkits don't support all keys, +mouse movement events etc. + +In most cases the entry point is classic `main()` function, but some platforms +(e.g. Native Client) have different requirements. To make things easier, entry +points are handled using macros, which take care of the rest. Each application +has its own specific macro and if no other application header is included, the +macro is also aliased to MAGNUM_APPLICATION_MAIN() to save you typing. + +Example application, which targets both embedded Linux (using plain X and EGL) +and desktop (using SDL2 toolkit). Thanks to static polymorphism most of the +functions will work on both without changes: +@code +#ifndef MAGNUM_TARGET_GLES +#include +#else +#include +#endif + +#ifndef MAGNUM_TARGET_GLES +typedef Platform::Sdl2Application ApplicationBase; +#else +typedef Platform::XEglApplication ApplicationBase; +#endif + +class MyApplication: public ApplicationBase { + public: + MyApplication(int& argc, char** argv): ApplicationBase(argc, argv, "My Application") { + // ... + } + + protected: + void viewportEvent(const Math::Vector2& size) override { + // ... + } + + void drawEvent() override { + // ... + } + + void keyPressEvent(Key key, Modifiers modifiers, const Math::Vector2& position) { + // ... + } +}; + +MAGNUM_APPLICATION_MAIN(MyApplication) +@endcode + +*/ +} diff --git a/doc/tips.dox b/doc/tips.dox index dfaea8909..85e0d6ad4 100644 --- a/doc/tips.dox +++ b/doc/tips.dox @@ -1,8 +1,9 @@ namespace Magnum { /** @page tips Tips and tricks -@brief Hints for better productivity and performance +@brief Hints for better productivity and performance. -- @subpage compilation-speedup - @copybrief compilation-speedup +- @subpage portability - @copybrief portability - @subpage best-practices - @copybrief best-practices +- @subpage compilation-speedup - @copybrief compilation-speedup */ } diff --git a/src/Color.h b/src/Color.h index 044fc3579..6af5ba7d5 100644 --- a/src/Color.h +++ b/src/Color.h @@ -141,6 +141,7 @@ range @f$ [0.0, 1.0] @f$. @see Color4 +@todo Hue in degrees so users can use deg() @todo Signed normalization to [-1.0, 1.0] like in OpenGL? */ /* Not using template specialization because some internal functions are diff --git a/src/Platform/AbstractXApplication.h b/src/Platform/AbstractXApplication.h index 0cc4c3e3e..aef67aef4 100644 --- a/src/Platform/AbstractXApplication.h +++ b/src/Platform/AbstractXApplication.h @@ -105,15 +105,16 @@ class AbstractXApplication { */ enum class Modifier: unsigned int { Shift = ShiftMask, /**< Shift */ - CapsLock = LockMask, /**< Caps lock */ Ctrl = ControlMask, /**< Ctrl */ Alt = Mod1Mask, /**< Alt */ - NumLock = Mod2Mask, /**< Num lock */ AltGr = Mod5Mask, /**< AltGr */ LeftButton = Button1Mask, /**< Left mouse button */ MiddleButton = Button2Mask, /**< Middle mouse button */ - RightButton = Button3Mask /**< Right mouse button */ + RightButton = Button3Mask, /**< Right mouse button */ + + CapsLock = LockMask, /**< Caps lock */ + NumLock = Mod2Mask /**< Num lock */ }; /** @@ -129,6 +130,7 @@ class AbstractXApplication { * @see keyPressEvent(), keyReleaseEvent() */ enum class Key: KeySym { + Enter = XK_Return, /**< Enter */ Esc = XK_Escape, /**< Escape */ Up = XK_Up, /**< Up arrow */ @@ -296,6 +298,34 @@ class AbstractXApplication { Flags flags; }; +/** @hideinitializer +@param className Class name + +Can be used as equivalent to the following code to achieve better portability, +see @ref portability-applications for more information. +@code +int main(int argc, char** argv) { + className app(argc, argv); + return app.exec(); +} +@endcode +When no other application header is included this macro is also aliased to +`MAGNUM_APPLICATION_MAIN()`. +*/ +#define MAGNUM_XAPPLICATION_MAIN(className) \ + int main(int argc, char** argv) { \ + className app(argc, argv); \ + return app.exec(); \ + } + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_APPLICATION_MAIN +#define MAGNUM_APPLICATION_MAIN(className) MAGNUM_XAPPLICATION_MAIN(className) +#else +#undef MAGNUM_APPLICATION_MAIN +#endif +#endif + CORRADE_ENUMSET_OPERATORS(AbstractXApplication::Modifiers) CORRADE_ENUMSET_OPERATORS(AbstractXApplication::Flags) diff --git a/src/Platform/GlutApplication.h b/src/Platform/GlutApplication.h index aa30a55f3..caf34fb17 100644 --- a/src/Platform/GlutApplication.h +++ b/src/Platform/GlutApplication.h @@ -43,16 +43,13 @@ support for changing cursor and mouse tracking and warping. @section GlutApplication-usage Usage You need to implement at least drawEvent() and viewportEvent() to be able to -draw on the screen. The subclass can be then used directly in `main()`, for -example: +draw on the screen. The subclass can be then used directly in `main()` - see +convenience macro MAGNUM_GLUTAPPLICATION_MAIN(). @code class MyApplication: public Magnum::Platform::GlutApplication { // implement required methods... }; -int main(int argc, char** argv) { - MyApplication c(argc, argv); - return c.exec(); -} +MAGNUM_GLUTAPPLICATION_MAIN(MyApplication) @endcode */ class GlutApplication { @@ -269,6 +266,34 @@ class GlutApplication { Context* c; }; +/** @hideinitializer +@param className Class name + +Can be used as equivalent to the following code to achieve better portability, +see @ref portability-applications for more information. +@code +int main(int argc, char** argv) { + className app(argc, argv); + return app.exec(); +} +@endcode +When no other application header is included this macro is also aliased to +`MAGNUM_APPLICATION_MAIN()`. +*/ +#define MAGNUM_GLUTAPPLICATION_MAIN(className) \ + int main(int argc, char** argv) { \ + className app(argc, argv); \ + return app.exec(); \ + } + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_APPLICATION_MAIN +#define MAGNUM_APPLICATION_MAIN(className) MAGNUM_GLUTAPPLICATION_MAIN(className) +#else +#undef MAGNUM_APPLICATION_MAIN +#endif +#endif + /* Implementations for inline functions with unused parameters */ inline void GlutApplication::keyPressEvent(Key, const Math::Vector2&) {} inline void GlutApplication::mousePressEvent(MouseButton, const Math::Vector2&) {} diff --git a/src/Platform/GlxApplication.h b/src/Platform/GlxApplication.h index 95535cce0..f17d683be 100644 --- a/src/Platform/GlxApplication.h +++ b/src/Platform/GlxApplication.h @@ -32,16 +32,13 @@ Uses GlxContextHandler. @section GlxApplication-usage Usage You need to implement at least drawEvent() and viewportEvent() to be able to -draw on the screen. The subclass can be then used directly in `main()`, for -example: +draw on the screen. The subclass can be then used directly in `main()` - see +convenience macro MAGNUM_XAPPLICATION_MAIN(). @code class MyApplication: public Magnum::Platform::GlxApplication { // implement required methods... }; -int main(int argc, char** argv) { - MyApplication c(argc, argv); - return c.exec(); -} +MAGNUM_XAPPLICATION_MAIN(MyApplication) @endcode */ class GlxApplication: public AbstractXApplication { diff --git a/src/Platform/NaClApplication.cpp b/src/Platform/NaClApplication.cpp index 401233f9d..9db9afa6b 100644 --- a/src/Platform/NaClApplication.cpp +++ b/src/Platform/NaClApplication.cpp @@ -16,8 +16,8 @@ #include "NaClApplication.h" #include -#include #include +#include #include "Context.h" @@ -48,6 +48,10 @@ NaClApplication::NaClApplication(PP_Instance instance, const Math::Vector2pp_resource()); c = new Context; + + /* Enable input handling for mouse and keyboard */ + RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE|PP_INPUTEVENT_CLASS_WHEEL); + RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); } NaClApplication::~NaClApplication() { @@ -74,6 +78,31 @@ void NaClApplication::DidChangeView(const pp::View& view) { drawEvent(); } +bool NaClApplication::HandleInputEvent(const pp::InputEvent& event) { + /* Assume everything is properly sequential here */ + CORRADE_INTERNAL_ASSERT(!(flags & Flag::SwapInProgress)); + + switch(event.GetType()) { + case PP_INPUTEVENT_TYPE_KEYDOWN: { + pp::KeyboardInputEvent keyEvent(event); + keyPressEvent(static_cast(keyEvent.GetKeyCode()), static_cast(keyEvent.GetModifiers()), {}); + break; + } case PP_INPUTEVENT_TYPE_KEYUP: { + pp::KeyboardInputEvent keyEvent(event); + keyReleaseEvent(static_cast(keyEvent.GetKeyCode()), static_cast(keyEvent.GetModifiers()), {}); + break; + } default: return false; + } + + /* Not need to redraw => assume the event was ignored */ + if(!(flags & Flag::Redraw)) return false; + + /* Redraw */ + flags &= ~Flag::Redraw; + drawEvent(); + return true; +} + void NaClApplication::swapBuffers() { /* Swap already in progress, do nothing */ if(flags & Flag::SwapInProgress) return; diff --git a/src/Platform/NaClApplication.h b/src/Platform/NaClApplication.h index bb0ecd3e0..69f64d140 100644 --- a/src/Platform/NaClApplication.h +++ b/src/Platform/NaClApplication.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -105,9 +106,134 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { * Marks the window for redrawing, resulting in call of drawEvent() * in the next iteration. */ - inline void redraw() { - flags |= Flag::Redraw; - } + inline void redraw() { flags |= Flag::Redraw; } + + /*@}*/ + + /** @{ @name Keyboard handling */ + + public: + /** + * @brief %Modifier + * + * @todo AltGr + PP_INPUTEVENT_MODIFIER_ISKEYPAD, PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT + * @see Modifiers, keyPressEvent(), keyReleaseEvent() + */ + enum class Modifier: std::uint32_t { + Shift = PP_INPUTEVENT_MODIFIER_SHIFTKEY, /**< Shift */ + Ctrl = PP_INPUTEVENT_MODIFIER_CONTROLKEY, /**< Ctrl */ + Alt = PP_INPUTEVENT_MODIFIER_ALTKEY, /**< Alt */ + Meta = PP_INPUTEVENT_MODIFIER_METAKEY, /**< Meta */ + + LeftButton = PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN, /**< Left mouse button */ + MiddleButton = PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN, /**< Middle mouse button */ + RightButton = PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN, /**< Right mouse button */ + + CapsLock = PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY, /**< Caps lock */ + NumLock = PP_INPUTEVENT_MODIFIER_NUMLOCKKEY /**< Num lock */ + }; + + /** + * @brief Set of modifiers + * + * @see keyPressEvent(), keyReleaseEvent() + */ + typedef Corrade::Containers::EnumSet Modifiers; + + /** + * @brief Key + * + * @todo Slash, percent, equal to be compatible with *XApplication + * @see keyPressEvent(), keyReleaseEvent() + */ + enum class Key: std::uint32_t { + Enter = 0x0D, /**< Enter */ + Esc = 0x1B, /**< Escape */ + + Up = 0x26, /**< Up arrow */ + Down = 0x28, /**< Down arrow */ + Left = 0x25, /**< Left arrow */ + Right = 0x27, /**< Right arrow */ + F1 = 0x70, /**< F1 */ + F2 = 0x71, /**< F2 */ + F3 = 0x72, /**< F3 */ + F4 = 0x73, /**< F4 */ + F5 = 0x74, /**< F5 */ + F6 = 0x75, /**< F6 */ + F7 = 0x76, /**< F7 */ + F8 = 0x77, /**< F8 */ + F9 = 0x78, /**< F9 */ + F10 = 0x79, /**< F10 */ + F11 = 0x7A, /**< F11 */ + F12 = 0x7B, /**< F12 */ + Home = 0x24, /**< Home */ + End = 0x23, /**< End */ + PageUp = 0x21, /**< Page up */ + PageDown = 0x22, /**< Page down */ + + Space = 0x20, /**< Space */ + Comma = 0xBC, /**< Comma */ + Period = 0xBE, /**< Period */ + Minus = 0xBD, /**< Minus */ + Plus = 0xBB, /**< Plus */ + + Zero = '0', /**< Zero */ + One = '1', /**< One */ + Two = '2', /**< Two */ + Three = '3', /**< Three */ + Four = '4', /**< Four */ + Five = '5', /**< Five */ + Six = '6', /**< Six */ + Seven = '7', /**< Seven */ + Eight = '8', /**< Eight */ + Nine = '9', /**< Nine */ + + A = 'A', /**< Letter A */ + B = 'B', /**< Letter B */ + C = 'C', /**< Letter C */ + D = 'D', /**< Letter D */ + E = 'E', /**< Letter E */ + F = 'F', /**< Letter F */ + G = 'G', /**< Letter G */ + H = 'H', /**< Letter H */ + I = 'I', /**< Letter I */ + J = 'J', /**< Letter J */ + K = 'K', /**< Letter K */ + L = 'L', /**< Letter L */ + M = 'M', /**< Letter M */ + N = 'N', /**< Letter N */ + O = 'O', /**< Letter O */ + P = 'P', /**< Letter P */ + Q = 'Q', /**< Letter Q */ + R = 'R', /**< Letter R */ + S = 'S', /**< Letter S */ + T = 'T', /**< Letter T */ + U = 'U', /**< Letter U */ + V = 'V', /**< Letter V */ + W = 'W', /**< Letter W */ + X = 'X', /**< Letter X */ + Y = 'Y', /**< Letter Y */ + Z = 'Z' /**< Letter Z */ + }; + + protected: + /** + * @brief Key press event + * @param key Key pressed + * @param modifiers Active modifiers + * @param position Cursor position (not implemented) + * + * Called when an key is pressed. Default implementation does nothing. + */ + virtual void keyPressEvent(Key key, Modifiers modifiers, const Math::Vector2& position); + + /** + * @brief Key release event + * @param key Key released + * @param modifiers Active modifiers + * @param position Cursor position (not implemented) + */ + virtual void keyReleaseEvent(Key key, Modifiers modifiers, const Math::Vector2& position); /*@}*/ @@ -125,6 +251,8 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient { void DidChangeView(const pp::View& view) override; + bool HandleInputEvent(const pp::InputEvent& event) override; + static void swapCallback(void* applicationInstance, std::int32_t); pp::Graphics3D* graphics; @@ -160,7 +288,9 @@ namespace Implementation { @brief Entry point for NaCl application @param application Application class name -See NaClApplication for more information. +See NaClApplication and @ref portability-applications for more information. +When no other application header is included this macro is also aliased to +`MAGNUM_APPLICATION_MAIN()`. */ /* look at that insane placement of __attribute__. WTF. */ #define MAGNUM_NACLAPPLICATION_MAIN(application) \ @@ -170,6 +300,18 @@ See NaClApplication for more information. } \ } +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_APPLICATION_MAIN +#define MAGNUM_APPLICATION_MAIN(className) MAGNUM_NACLAPPLICATION_MAIN(className) +#else +#undef MAGNUM_APPLICATION_MAIN +#endif +#endif + +/* Implementations for inline functions with unused parameters */ +inline void NaClApplication::keyPressEvent(Key, Modifiers, const Math::Vector2&) {} +inline void NaClApplication::keyReleaseEvent(Key, Modifiers, const Math::Vector2&) {} + }} #endif diff --git a/src/Platform/Sdl2Application.cpp b/src/Platform/Sdl2Application.cpp index 00dfaee4d..4f6091493 100644 --- a/src/Platform/Sdl2Application.cpp +++ b/src/Platform/Sdl2Application.cpp @@ -83,12 +83,26 @@ int Sdl2Application::exec() { break; } break; case SDL_KEYDOWN: - keyPressEvent(static_cast(event.key.keysym.sym), Modifiers(), {}); + case SDL_KEYUP: { + /* + * Fix up the modifiers -- we want >= operator to work + * properly on Shift, Ctrl, Alt, but SDL generates + * different event for left / right keys, thus + * (modifiers >= Shift) would pass only if both left and + * right were pressed, which is usually not what the + * developers wants. + */ + Modifiers modifiers(static_cast(event.key.keysym.mod)); + if(modifiers & Modifier::Shift) modifiers |= Modifier::Shift; + if(modifiers & Modifier::Ctrl) modifiers |= Modifier::Ctrl; + if(modifiers & Modifier::Alt) modifiers |= Modifier::Alt; + + if(event.type == SDL_KEYDOWN) + keyPressEvent(static_cast(event.key.keysym.sym), modifiers, {}); + else + keyReleaseEvent(static_cast(event.key.keysym.sym), modifiers, {}); break; - case SDL_KEYUP: - keyReleaseEvent(static_cast(event.key.keysym.sym), Modifiers(), {}); - break; - case SDL_MOUSEBUTTONDOWN: + } case SDL_MOUSEBUTTONDOWN: mousePressEvent(static_cast(event.button.button), Modifiers(), {event.button.x, event.button.y}); break; case SDL_MOUSEBUTTONUP: diff --git a/src/Platform/Sdl2Application.h b/src/Platform/Sdl2Application.h index 033fc804f..59b978420 100644 --- a/src/Platform/Sdl2Application.h +++ b/src/Platform/Sdl2Application.h @@ -42,16 +42,13 @@ Supports keyboard and mouse handling. @section Sdl2Application-usage Usage You need to implement at least drawEvent() and viewportEvent() to be able to -draw on the screen. The subclass can be then used directly in `main()`, for -example: +draw on the screen. The subclass can be then used directly in `main()` - see +convenience macro MAGNUM_SDL2APPLICATION_MAIN(). @code class MyApplication: public Magnum::Platform::Sdl2Application { // implement required methods... }; -int main(int argc, char** argv) { - MyApplication c(argc, argv); - return c.exec(); -} +MAGNUM_SDL2APPLICATION_MAIN(MyApplication) @endcode */ class Sdl2Application { @@ -99,21 +96,29 @@ class Sdl2Application { /*@}*/ /** @{ @name Keyboard handling */ + public: /** * @brief %Modifier * - * @see Modifiers, keyPressEvent(), keyReleaseEvent(), - * mousePressEvent(), mouseReleaseEvent(), mouseMotionEvent() + * @see Modifiers, keyPressEvent(), keyReleaseEvent() */ - enum class Modifier: unsigned int {}; + enum class Modifier: Uint16 { + Shift = KMOD_SHIFT, /**< Shift */ + Ctrl = KMOD_CTRL, /**< Ctrl */ + Alt = KMOD_ALT, /**< Alt */ + AltGr = KMOD_MODE, /**< AltGr */ + + CapsLock = KMOD_CAPS, /**< Caps lock */ + NumLock = KMOD_NUM /**< Num lock */ + }; /** * @brief Set of modifiers * * @see keyPressEvent(), keyReleaseEvent() */ - typedef Corrade::Containers::EnumSet Modifiers; + typedef Corrade::Containers::EnumSet Modifiers; /** * @brief Key @@ -121,28 +126,92 @@ class Sdl2Application { * @see keyPressEvent(), keyReleaseEvent() */ enum class Key: SDL_Keycode { - Up = SDLK_UP, /**< Up arrow */ - Down = SDLK_DOWN, /**< Down arrow */ - Left = SDLK_LEFT, /**< Left arrow */ - Right = SDLK_RIGHT, /**< Right arrow */ - Plus = SDLK_PLUS, /**< Plus */ - Minus = SDLK_MINUS /**< Minus */ + Enter = SDLK_RETURN, /**< Enter */ + Esc = SDLK_ESCAPE, /**< Escape */ + + Up = SDLK_UP, /**< Up arrow */ + Down = SDLK_DOWN, /**< Down arrow */ + Left = SDLK_LEFT, /**< Left arrow */ + Right = SDLK_RIGHT, /**< Right arrow */ + F1 = SDLK_F1, /**< F1 */ + F2 = SDLK_F2, /**< F2 */ + F3 = SDLK_F3, /**< F3 */ + F4 = SDLK_F4, /**< F4 */ + F5 = SDLK_F5, /**< F5 */ + F6 = SDLK_F6, /**< F6 */ + F7 = SDLK_F7, /**< F7 */ + F8 = SDLK_F8, /**< F8 */ + F9 = SDLK_F9, /**< F9 */ + F10 = SDLK_F10, /**< F10 */ + F11 = SDLK_F11, /**< F11 */ + F12 = SDLK_F12, /**< F12 */ + Home = SDLK_HOME, /**< Home */ + End = SDLK_END, /**< End */ + PageUp = SDLK_PAGEUP, /**< Page up */ + PageDown = SDLK_PAGEDOWN, /**< Page down */ + + Space = SDLK_SPACE, /**< Space */ + Comma = SDLK_COMMA, /**< Comma */ + Period = SDLK_PERIOD, /**< Period */ + Minus = SDLK_MINUS, /**< Minus */ + Plus = SDLK_PLUS, /**< Plus */ + Slash = SDLK_SLASH, /**< Slash */ + Percent = SDLK_PERCENT, /**< Percent */ + Equal = SDLK_EQUALS, /**< Equal */ + + Zero = SDLK_0, /**< Zero */ + One = SDLK_1, /**< One */ + Two = SDLK_2, /**< Two */ + Three = SDLK_3, /**< Three */ + Four = SDLK_4, /**< Four */ + Five = SDLK_5, /**< Five */ + Six = SDLK_6, /**< Six */ + Seven = SDLK_7, /**< Seven */ + Eight = SDLK_8, /**< Eight */ + Nine = SDLK_9, /**< Nine */ + + A = SDLK_a, /**< Letter A */ + B = SDLK_b, /**< Letter B */ + C = SDLK_c, /**< Letter C */ + D = SDLK_d, /**< Letter D */ + E = SDLK_e, /**< Letter E */ + F = SDLK_f, /**< Letter F */ + G = SDLK_g, /**< Letter G */ + H = SDLK_h, /**< Letter H */ + I = SDLK_i, /**< Letter I */ + J = SDLK_j, /**< Letter J */ + K = SDLK_k, /**< Letter K */ + L = SDLK_l, /**< Letter L */ + M = SDLK_m, /**< Letter M */ + N = SDLK_n, /**< Letter N */ + O = SDLK_o, /**< Letter O */ + P = SDLK_p, /**< Letter P */ + Q = SDLK_q, /**< Letter Q */ + R = SDLK_r, /**< Letter R */ + S = SDLK_s, /**< Letter S */ + T = SDLK_t, /**< Letter T */ + U = SDLK_u, /**< Letter U */ + V = SDLK_v, /**< Letter V */ + W = SDLK_w, /**< Letter W */ + X = SDLK_x, /**< Letter X */ + Y = SDLK_y, /**< Letter Y */ + Z = SDLK_z /**< Letter Z */ }; protected: /** * @brief Key press event * @param key Key pressed - * @param modifiers Active modifiers (not yet implemented) - * @param position Cursor position (not yet implemented) + * @param modifiers Active modifiers + * @param position Cursor position (not implemented) */ virtual void keyPressEvent(Key key, Modifiers modifiers, const Math::Vector2& position); /** * @brief Key release event * @param key Key released - * @param modifiers Active modifiers (not yet implemented) - * @param position Cursor position (not yet implemented) + * @param modifiers Active modifiers + * @param position Cursor position (not implemented) */ virtual void keyReleaseEvent(Key key, Modifiers modifiers, const Math::Vector2& position); @@ -178,7 +247,7 @@ class Sdl2Application { /** * @brief Mouse press event * @param button Button pressed - * @param modifiers Active modifiers (not yet implemented) + * @param modifiers Active modifiers (not implemented) * @param position Cursor position * * Called when mouse button is pressed. Default implementation does @@ -189,7 +258,7 @@ class Sdl2Application { /** * @brief Mouse release event * @param button Button released - * @param modifiers Active modifiers (not yet implemented) + * @param modifiers Active modifiers (not implemented) * @param position Cursor position * * Called when mouse button is released. Default implementation does @@ -199,7 +268,7 @@ class Sdl2Application { /** * @brief Mouse motion event - * @param modifiers Active modifiers (not yet implemented) + * @param modifiers Active modifiers (not implemented) * @param position Mouse position relative to the window * * Called when mouse is moved. Default implementation does nothing. @@ -217,6 +286,34 @@ class Sdl2Application { bool _redraw; }; +/** @hideinitializer +@param className Class name + +Can be used as equivalent to the following code to achieve better portability, +see @ref portability-applications for more information. +@code +int main(int argc, char** argv) { + className app(argc, argv); + return app.exec(); +} +@endcode +When no other application header is included this macro is also aliased to +`MAGNUM_APPLICATION_MAIN()`. +*/ +#define MAGNUM_SDL2APPLICATION_MAIN(className) \ + int main(int argc, char** argv) { \ + className app(argc, argv); \ + return app.exec(); \ + } + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_APPLICATION_MAIN +#define MAGNUM_APPLICATION_MAIN(className) MAGNUM_SDL2APPLICATION_MAIN(className) +#else +#undef MAGNUM_APPLICATION_MAIN +#endif +#endif + CORRADE_ENUMSET_OPERATORS(Sdl2Application::Modifiers) /* Implementations for inline functions with unused parameters */ diff --git a/src/Platform/XEglApplication.h b/src/Platform/XEglApplication.h index 490b16353..7fdcfe1f4 100644 --- a/src/Platform/XEglApplication.h +++ b/src/Platform/XEglApplication.h @@ -32,16 +32,13 @@ Uses EglContextHandler. @section XEglApplication-usage Usage You need to implement at least drawEvent() and viewportEvent() to be able to -draw on the screen. The subclass can be then used directly in `main()`, for -example: +draw on the screen. The subclass can be then used directly in `main()` - see +convenience macro MAGNUM_XAPPLICATION_MAIN(). @code class MyApplication: public Magnum::Platform::XEglApplication { // implement required methods... }; -int main(int argc, char** argv) { - MyApplication c(argc, argv); - return c.exec(); -} +MAGNUM_XAPPLICATION_MAIN(MyApplication) @endcode */ class XEglApplication: public AbstractXApplication {