diff --git a/doc/changelog.dox b/doc/changelog.dox index a039e463a..8b66c23ce 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -203,6 +203,18 @@ See also: @ref Platform::WindowlessGlxApplication, @ref Platform::WindowlessWglApplication and @ref Platform::WindowlessWindowsEglApplication (see [mosra/magnum#](https://github.com/mosra/magnum/pull/433)) +- Added @ref Platform::GlfwApplication::Configuration::WindowFlag::Borderless +- Added @ref Platform::Sdl2Application::Configuration::WindowFlag::FullscreenDesktop, + @ref Platform::Sdl2Application::Configuration::WindowFlag::AlwaysOnTop "AlwaysOnTop", + @ref Platform::Sdl2Application::Configuration::WindowFlag::SkipTaskbar "SkipTaskbar", + @ref Platform::Sdl2Application::Configuration::WindowFlag::Utility "Utility", + @ref Platform::Sdl2Application::Configuration::WindowFlag::Tooltip "Tooltip" + and @ref Platform::Sdl2Application::Configuration::WindowFlag::PopupMenu "PopupMenu" +- Added @ref Platform::Sdl2Application::Configuration::addWindowFlags() and + @ref Platform::Sdl2Application::Configuration::clearWindowFlags() "clearWindowFlags()" + for consistency with similar functions in + @ref Platform::Sdl2Application::GLConfiguration; same done for + @ref Platform::GlfwApplication as well @subsubsection changelog-latest-new-primitives Primitives library @@ -518,6 +530,10 @@ See also: @cpp Platform::Sdl2Application::Configuration::isMouseLocked() @ce is deprecated in favor of the new @ref Platform::Sdl2Application::setCursor() together with @ref Platform::Sdl2Application::Cursor::HiddenLocked +- @cpp Platform::GlfwApplication::Configuration::WindowFlag::Floating @ce is + deprecated in favor of a more descriptive + @ref Platform::GlfwApplication::Configuration::WindowFlag::AlwaysOnTop, + which is also consistent with @ref Platform::Sdl2Application - @cpp Audio::AbstractImporter::Features @ce, @cpp Text::AbstractFont::Features @ce, @cpp Text::AbstractFontConverter::Features @ce, diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 6d30f2233..9ffd0e0f7 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -327,12 +327,13 @@ bool GlfwApplication::tryCreate(const Configuration& configuration) { glfwWindowHint(GLFW_AUTO_ICONIFY, configuration.windowFlags() >= Configuration::WindowFlag::AutoIconify); } else { const Configuration::WindowFlags& flags = configuration.windowFlags(); + glfwWindowHint(GLFW_DECORATED, !(flags >= Configuration::WindowFlag::Borderless)); glfwWindowHint(GLFW_RESIZABLE, flags >= Configuration::WindowFlag::Resizable); glfwWindowHint(GLFW_VISIBLE, !(flags >= Configuration::WindowFlag::Hidden)); #ifdef GLFW_MAXIMIZED glfwWindowHint(GLFW_MAXIMIZED, flags >= Configuration::WindowFlag::Maximized); #endif - glfwWindowHint(GLFW_FLOATING, flags >= Configuration::WindowFlag::Floating); + glfwWindowHint(GLFW_FLOATING, flags >= Configuration::WindowFlag::AlwaysOnTop); } glfwWindowHint(GLFW_FOCUSED, configuration.windowFlags() >= Configuration::WindowFlag::Focused); @@ -402,12 +403,13 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf glfwWindowHint(GLFW_AUTO_ICONIFY, configuration.windowFlags() >= Configuration::WindowFlag::AutoIconify); } else { const Configuration::WindowFlags& flags = configuration.windowFlags(); + glfwWindowHint(GLFW_DECORATED, !(flags >= Configuration::WindowFlag::Borderless)); glfwWindowHint(GLFW_RESIZABLE, flags >= Configuration::WindowFlag::Resizable); glfwWindowHint(GLFW_VISIBLE, !(flags >= Configuration::WindowFlag::Hidden)); #ifdef GLFW_MAXIMIZED glfwWindowHint(GLFW_MAXIMIZED, flags >= Configuration::WindowFlag::Maximized); #endif - glfwWindowHint(GLFW_FLOATING, flags >= Configuration::WindowFlag::Floating); + glfwWindowHint(GLFW_FLOATING, flags >= Configuration::WindowFlag::AlwaysOnTop); } glfwWindowHint(GLFW_FOCUSED, configuration.windowFlags() >= Configuration::WindowFlag::Focused); diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index f1bedd58d..38df4548b 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -1016,8 +1016,15 @@ class GlfwApplication::Configuration { */ enum class WindowFlag: UnsignedShort { Fullscreen = 1 << 0, /**< Fullscreen window */ - Resizable = 1 << 1, /**< Resizable window */ - Hidden = 1 << 2, /**< Hidden window */ + + /** + * No window decoration + * @m_since_latest + */ + Borderless = 1 << 1, + + Resizable = 1 << 2, /**< Resizable window */ + Hidden = 1 << 3, /**< Hidden window */ #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_MAXIMIZED) /** @@ -1025,19 +1032,37 @@ class GlfwApplication::Configuration { * * @note Supported since GLFW 3.2. */ - Maximized = 1 << 3, + Maximized = 1 << 4, #endif - Minimized = 1 << 4, /**< Minimized window */ - Floating = 1 << 5, /**< Window floating above others, top-most */ + Minimized = 1 << 5, /**< Minimized window */ + + /** + * Always on top + * @m_since_latest + */ + AlwaysOnTop = 1 << 6, + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * Always on top + * @deprecated Use @ref WindowFlag::AlwaysOnTop instead. + */ + Floating CORRADE_DEPRECATED_ENUM("use AlwaysOnTop instead") = AlwaysOnTop, + #endif /** * Automatically iconify (minimize) if fullscreen window loses * input focus */ - AutoIconify = 1 << 6, + AutoIconify = 1 << 7, - Focused = 1 << 7, /**< Window has input focus */ + /** + * Window has input focus + * + * @todo there's also GLFW_FOCUS_ON_SHOW, what's the difference? + */ + Focused = 1 << 8, #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_NO_API) /** @@ -1050,7 +1075,7 @@ class GlfwApplication::Configuration { * * @note Supported since GLFW 3.2. */ - Contextless = 1 << 8 + Contextless = 1 << 9 #endif }; @@ -1242,6 +1267,35 @@ class GlfwApplication::Configuration { return *this; } + /** + * @brief Add window flags + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setWindowFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearWindowFlags() + */ + Configuration& addWindowFlags(WindowFlags flags) { + _windowFlags |= flags; + return *this; + } + + /** + * @brief Clear window flags + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setWindowFlags(), ANDs the inverse of @p flags with + * existing instead of replacing them. Useful for removing default + * flags. + * @see @ref addWindowFlags() + */ + Configuration& clearWindowFlags(WindowFlags flags) { + _windowFlags &= ~flags; + return *this; + } + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Cursor mode diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 115d7ce0d..539d70c22 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1534,6 +1534,14 @@ class Sdl2Application::Configuration { */ Fullscreen = SDL_WINDOW_FULLSCREEN, + /** + * Fullscreen window at the current desktop resolution + * @m_since_latest + * + * @note Not available on @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". + */ + FullscreenDesktop = SDL_WINDOW_FULLSCREEN_DESKTOP, + /** * No window decoration. On iOS this hides the menu bar. * @@ -1579,8 +1587,66 @@ class Sdl2Application::Configuration { * Window with mouse locked * * @note Not available on @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". + * @todo SDL_WINDOW_MOUSE_CAPTURE, also what all those do? isn't it + * redundant / better handled with cursor APIs? */ MouseLocked = SDL_WINDOW_INPUT_GRABBED, + + /** @todo SDL_WINDOW_INPUT_FOCUS, SDL_WINDOW_MOUSE_FOCUS, GLFW has + GLFW_FOCUSED (exposed as Focused) and GLFW_FOCUS_ON_SHOW (not + exposed) -- what's the relation? How to make these compatible? */ + + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2005 || defined(DOXYGEN_GENERATING_OUTPUT) + /** + * Always on top + * @m_since_latest + * + * @note Available since SDL 2.0.5, not available on + * @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". According to + * SDL docs works only on X11. + */ + AlwaysOnTop = SDL_WINDOW_ALWAYS_ON_TOP, + + /** + * Don't add the window to taskbar + * @m_since_latest + * + * @note Available since SDL 2.0.5, not available on + * @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". According to + * SDL docs works only on X11. + */ + SkipTaskbar = SDL_WINDOW_SKIP_TASKBAR, + + /** + * Window should be treated as a utility window + * @m_since_latest + * + * @note Available since SDL 2.0.5, not available on + * @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". According to + * SDL docs works only on X11. + */ + Utility = SDL_WINDOW_UTILITY, + + /** + * Window should be treated as a tooltip + * @m_since_latest + * + * @note Available since SDL 2.0.5, not available on + * @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". According to + * SDL docs works only on X11. + */ + Tooltip = SDL_WINDOW_TOOLTIP, + + /** + * Window should be treated as a popup menu + * @m_since_latest + * + * @note Available since SDL 2.0.5, not available on + * @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". According to + * SDL docs works only on X11. + */ + PopupMenu = SDL_WINDOW_POPUP_MENU, + #endif #endif /** @@ -1800,6 +1866,35 @@ class Sdl2Application::Configuration { return *this; } + /** + * @brief Add window flags + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setWindowFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearWindowFlags() + */ + Configuration& addWindowFlags(WindowFlags flags) { + _windowFlags |= flags; + return *this; + } + + /** + * @brief Clear window flags + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setWindowFlags(), ANDs the inverse of @p flags with + * existing instead of replacing them. Useful for removing default + * flags. + * @see @ref addWindowFlags() + */ + Configuration& clearWindowFlags(WindowFlags flags) { + _windowFlags &= ~flags; + return *this; + } + private: #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_IOS) std::string _title; diff --git a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp index da1c37d17..c47bb7a46 100644 --- a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp @@ -106,6 +106,8 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: args.addOption("dpi-scaling").setHelp("dpi-scaling", "DPI scaled passed via Configuration instead of --magnum-dpi-scaling, to test app overrides") .addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") + .addBooleanOption("borderless").setHelp("borderless", "no window decoration") + .addBooleanOption("always-on-top").setHelp("always-on-top", "always on top") .parse(arguments.argc, arguments.argv); if(args.isSet("exit-immediately")) { @@ -117,6 +119,10 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: conf.setWindowFlags(Configuration::WindowFlag::Resizable); if(!args.value("dpi-scaling").empty()) conf.setSize({800, 600}, args.value("dpi-scaling")); + if(args.isSet("borderless")) + conf.addWindowFlags(Configuration::WindowFlag::Borderless); + if(args.isSet("always-on-top")) + conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop); create(conf); /* For testing resize events */ diff --git a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp index 1b6d4cc65..5fa394616 100644 --- a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp +++ b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp @@ -151,6 +151,12 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: args.addOption("dpi-scaling").setHelp("dpi-scaling", "DPI scaled passed via Configuration instead of --magnum-dpi-scaling, to test app overrides") .addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") + #ifndef CORRADE_TARGET_EMSCRIPTEN + .addBooleanOption("borderless").setHelp("borderless", "no window decoration") + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2005 + .addBooleanOption("always-on-top").setHelp("always-on-top", "always on top") + #endif + #endif .parse(arguments.argc, arguments.argv); if(args.isSet("exit-immediately")) { @@ -162,6 +168,14 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: conf.setWindowFlags(Configuration::WindowFlag::Resizable); if(!args.value("dpi-scaling").empty()) conf.setSize({800, 600}, args.value("dpi-scaling")); + #ifndef CORRADE_TARGET_EMSCRIPTEN + if(args.isSet("borderless")) + conf.addWindowFlags(Configuration::WindowFlag::Borderless); + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2005 + if(args.isSet("always-on-top")) + conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop); + #endif + #endif create(conf); /* For testing resize events */