diff --git a/include/nbl/ui/IWindow.h b/include/nbl/ui/IWindow.h index 385f70d172..f691fed84d 100644 --- a/include/nbl/ui/IWindow.h +++ b/include/nbl/ui/IWindow.h @@ -21,25 +21,32 @@ class IWindow : public core::IReferenceCounted public: enum E_CREATE_FLAGS : uint32_t { + //! Implicitly adds ECF_BORDERLESS | ECF_ALWAYS_ON_TOP ECF_FULLSCREEN = 1u << 0, ECF_HIDDEN = 1u << 1, ECF_BORDERLESS = 1u << 2, - ECF_RESIZABLE = 1u << 3, - ECF_MINIMIZED = 1u << 4, - ECF_MAXIMIZED = 1u << 5, + //! Indicates whether window can be resized via UI + ECF_UI_RESIZABLE = 1u << 3, + //! Indicates whether window can be resized programmatically + ECF_PROGRAM_RESIZABLE = 1u << 4, + //! Opens the window in manimized mode + //! Implicitly adds ECF_UI_RESIZABLE + ECF_MINIMIZED = 1u << 5, + //! Opens the window in maximized mode + //! Implicitly adds ECF_UI_RESIZABLE + //! NOTE: Not working properly + ECF_MAXIMIZED = 1u << 6, //! Forces mouse to stay inside the window - ECF_MOUSE_CAPTURE = 1u << 6, + ECF_MOUSE_CAPTURE = 1u << 7, //! Indicates whether the window is active or not - ECF_INPUT_FOCUS = 1u << 7, + ECF_INPUT_FOCUS = 1u << 8, //! Indicates whether mouse is hovering over the window even if the window is not active - ECF_MOUSE_FOCUS = 1u << 8, - ECF_ALWAYS_ON_TOP = 1u << 9, + ECF_MOUSE_FOCUS = 1u << 9, + ECF_ALWAYS_ON_TOP = 1u << 10, //! If disabled, the maximize button is grayed out - ECF_CAN_MAXIMIZE = 1u << 10, + ECF_CAN_MAXIMIZE = 1u << 11, //! If disabled, the minimize button is grayed out - ECF_CAN_MINIMIZE = 1u << 11, - //! If disabled, the window can't be resized via the UI, only programmatically - ECF_CAN_RESIZE = 1u << 12, + ECF_CAN_MINIMIZE = 1u << 12, ECF_NONE = 0 }; @@ -173,18 +180,18 @@ class IWindow : public core::IReferenceCounted friend class IEventCallback; inline void setEventCallback(core::smart_refctd_ptr&& evCb) { m_cb = std::move(evCb); } - inline bool isFullscreen() { return (m_flags.value & ECF_FULLSCREEN); } - inline bool isHidden() { return (m_flags.value & ECF_HIDDEN); } - inline bool isBorderless() { return (m_flags.value & ECF_BORDERLESS); } - inline bool canProgrammaticallyResize() { return (m_flags.value & ECF_RESIZABLE); } - inline bool isMinimized() { return (m_flags.value & ECF_MINIMIZED); } - inline bool isMaximized() { return (m_flags.value & ECF_MAXIMIZED); } - inline bool hasMouseCaptured() { return (m_flags.value & ECF_MOUSE_CAPTURE); } - inline bool hasInputFocus() { return (m_flags.value & ECF_INPUT_FOCUS); } - inline bool hasMouseFocus() { return (m_flags.value & ECF_MOUSE_FOCUS); } - inline bool isAlwaysOnTop() { return (m_flags.value & ECF_ALWAYS_ON_TOP); } - inline bool isMaximizable() { return (m_flags.value & ECF_CAN_MAXIMIZE); } - inline bool isResizable() { return (m_flags.value & ECF_CAN_RESIZE); } + inline bool isFullscreen() { return (m_flags.value & ECF_FULLSCREEN); } + inline bool isHidden() { return (m_flags.value & ECF_HIDDEN); } + inline bool isBorderless() { return (m_flags.value & ECF_BORDERLESS); } + inline bool isUIResizable() { return (m_flags.value & ECF_UI_RESIZABLE); } + inline bool isProgrammaticallyResizable() { return (m_flags.value & ECF_PROGRAM_RESIZABLE); } + inline bool isMinimized() { return (m_flags.value & ECF_MINIMIZED); } + inline bool isMaximized() { return (m_flags.value & ECF_MAXIMIZED); } + inline bool hasMouseCaptured() { return (m_flags.value & ECF_MOUSE_CAPTURE); } + inline bool hasInputFocus() { return (m_flags.value & ECF_INPUT_FOCUS); } + inline bool hasMouseFocus() { return (m_flags.value & ECF_MOUSE_FOCUS); } + inline bool isAlwaysOnTop() { return (m_flags.value & ECF_ALWAYS_ON_TOP); } + inline bool isMaximizable() { return (m_flags.value & ECF_CAN_MAXIMIZE); } inline core::bitflag getFlags() { return m_flags; } diff --git a/include/nbl/ui/IWindowManager.h b/include/nbl/ui/IWindowManager.h index ffa83b525f..c29a3677cc 100644 --- a/include/nbl/ui/IWindowManager.h +++ b/include/nbl/ui/IWindowManager.h @@ -24,8 +24,7 @@ class NBL_API2 IWindowManager : public virtual core::IReferenceCounted inline bool setWindowSize(IWindow* window, const uint32_t width, const uint32_t height) { - auto cb = window->getEventCallback(); - if (window->getManager()!=this || !window->canProgrammaticallyResize()) + if (window->getManager()!=this || !window->isProgrammaticallyResizable()) return false; return setWindowSize_impl(window, width, height); @@ -33,8 +32,7 @@ class NBL_API2 IWindowManager : public virtual core::IReferenceCounted inline bool setWindowPosition(IWindow* window, const int32_t x, const int32_t y) { - auto cb = window->getEventCallback(); - if (window->getManager()!=this) + if (window->getManager() != this) return false; return setWindowPosition_impl(window, x, y); @@ -55,7 +53,6 @@ class NBL_API2 IWindowManager : public virtual core::IReferenceCounted inline bool show(IWindow* window) { - auto cb = window->getEventCallback(); if (window->getManager() != this || !window->isHidden()) return false; @@ -64,7 +61,6 @@ class NBL_API2 IWindowManager : public virtual core::IReferenceCounted inline bool hide(IWindow* window) { - auto cb = window->getEventCallback(); if (window->getManager() != this || window->isHidden()) return false; @@ -73,7 +69,6 @@ class NBL_API2 IWindowManager : public virtual core::IReferenceCounted inline bool maximize(IWindow* window) { - auto cb = window->getEventCallback(); if (window->getManager() != this || window->isMaximized()) return false; @@ -82,7 +77,6 @@ class NBL_API2 IWindowManager : public virtual core::IReferenceCounted inline bool minimize(IWindow* window) { - auto cb = window->getEventCallback(); if (window->getManager() != this || window->isMinimized()) return false; diff --git a/src/nbl/ui/CWindowManagerWin32.cpp b/src/nbl/ui/CWindowManagerWin32.cpp index 018613f670..601601d72c 100644 --- a/src/nbl/ui/CWindowManagerWin32.cpp +++ b/src/nbl/ui/CWindowManagerWin32.cpp @@ -29,46 +29,36 @@ IWindowManager::SDisplayInfo CWindowManagerWin32::getPrimaryDisplayInfo() const static inline DWORD getWindowStyle(const core::bitflag flags) { DWORD style = WS_POPUP; + // These are always set by GLFW + style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - if (!flags.hasFlags(IWindow::ECF_FULLSCREEN)) + if (!flags.hasFlags(IWindow::ECF_BORDERLESS)) { - if (!flags.hasFlags(IWindow::ECF_BORDERLESS)) - { - style |= WS_BORDER; - style |= (WS_SYSMENU | WS_CAPTION); - } - // ? not sure about those below - style |= WS_CLIPCHILDREN; - style |= WS_CLIPSIBLINGS; + style |= WS_BORDER | WS_CAPTION | WS_SYSMENU; } - if (flags.hasFlags(IWindow::ECF_MINIMIZED)) + if (flags.hasFlags(IWindow::ECF_UI_RESIZABLE)) { - style |= WS_MINIMIZE; + style |= WS_SIZEBOX; } if (flags.hasFlags(IWindow::ECF_MAXIMIZED)) { style |= WS_MAXIMIZE; } - if (flags.hasFlags(IWindow::ECF_ALWAYS_ON_TOP)) - { - style |= WS_EX_TOPMOST; - } - if (!flags.hasFlags(IWindow::ECF_HIDDEN)) + if (flags.hasFlags(IWindow::ECF_MINIMIZED)) { - style |= WS_VISIBLE; + style |= WS_MINIMIZE; } - style |= WS_OVERLAPPEDWINDOW; - if (!flags.hasFlags(IWindow::ECF_CAN_RESIZE)) + if (flags.hasFlags(IWindow::ECF_CAN_MAXIMIZE)) { - style &= ~WS_SIZEBOX; + style |= WS_MAXIMIZEBOX; } - if (!flags.hasFlags(IWindow::ECF_CAN_MAXIMIZE)) + if (flags.hasFlags(IWindow::ECF_CAN_MINIMIZE)) { - style &= ~WS_MAXIMIZEBOX; + style |= WS_MINIMIZEBOX; } - if (!flags.hasFlags(IWindow::ECF_CAN_MINIMIZE)) + if (!flags.hasFlags(IWindow::ECF_HIDDEN)) { - style &= ~WS_MINIMIZEBOX; + style |= WS_VISIBLE; } return style; @@ -76,12 +66,11 @@ static inline DWORD getWindowStyle(const core::bitflag core::smart_refctd_ptr CWindowManagerWin32::createWindow(IWindow::SCreationParams&& creationParams) { - // this could be common to all `createWindow` impl - if (creationParams.flags.hasFlags(IWindow::ECF_CAN_RESIZE) || creationParams.flags.hasFlags(IWindow::ECF_CAN_MAXIMIZE)) - creationParams.flags |= IWindow::ECF_RESIZABLE; // win32 minimize is weird, its a resize to 0,0 - if (creationParams.flags.hasFlags(IWindow::ECF_CAN_MINIMIZE)) - creationParams.flags |= IWindow::ECF_CAN_RESIZE; + if (creationParams.flags.hasFlags(IWindow::ECF_CAN_MAXIMIZE) || creationParams.flags.hasFlags(IWindow::ECF_CAN_MINIMIZE)) + creationParams.flags |= IWindow::ECF_UI_RESIZABLE; + if (creationParams.flags.hasFlags(IWindow::ECF_FULLSCREEN)) + creationParams.flags |= IWindow::ECF_BORDERLESS | IWindow::ECF_ALWAYS_ON_TOP; CAsyncQueue::future_t future; m_windowThreadManager.request(&future, SRequestParams_CreateWindow{ @@ -115,7 +104,7 @@ bool CWindowManagerWin32::setWindowSize_impl(IWindow* window, const uint32_t wid .nativeWindow = static_cast(window)->getNativeHandle(), .width = clientSize.right-clientSize.left, .height = clientSize.bottom-clientSize.top - }); + }); return true; } @@ -173,6 +162,15 @@ void CWindowManagerWin32::SRequestParams_CreateWindow::operator()(core::StorageT clientSize.right = clientSize.left + width; clientSize.bottom = clientSize.top + height; + if (flags.hasFlags(IWindow::ECF_FULLSCREEN)) { + HMONITOR monitor = MonitorFromPoint({ 0,0 }, MONITOR_DEFAULTTONEAREST); + MONITORINFO monitor_info; + monitor_info.cbSize = sizeof(monitor_info); + GetMonitorInfo(monitor, &monitor_info); + // We ignore the requested size cause they want full screen + clientSize = monitor_info.rcMonitor; + } + const DWORD style = getWindowStyle(flags); // TODO: @@ -192,9 +190,29 @@ void CWindowManagerWin32::SRequestParams_CreateWindow::operator()(core::StorageT NULL, NULL, hinstance, NULL ); - // + if (flags.hasFlags(IWindow::ECF_ALWAYS_ON_TOP)) { + SetWindowPos(nativeWindow, HWND_TOPMOST, clientSize.left, clientSize.top, realWidth, realHeight, 0); + } + + if (flags.hasFlags(IWindow::ECF_MOUSE_CAPTURE)) { + RECT clipRect; + GetClientRect(nativeWindow, &clipRect); + ClientToScreen(nativeWindow, (POINT*)&clipRect.left); + ClientToScreen(nativeWindow, (POINT*)&clipRect.right); + ClipCursor(&clipRect); + } + + int show_cmd = SW_SHOWNORMAL; + assert(!flags.hasFlags(IWindow::ECF_MINIMIZED | IWindow::ECF_MAXIMIZED)); + if (flags.hasFlags(IWindow::ECF_MINIMIZED)) { + show_cmd = SW_SHOWMINIMIZED; + } + if (flags.hasFlags(IWindow::ECF_MAXIMIZED)) { + show_cmd = SW_SHOWMAXIMIZED; + } + if (!flags.hasFlags(CWindowWin32::ECF_HIDDEN)) - ShowWindow(nativeWindow, SW_SHOWNORMAL); + ShowWindow(nativeWindow, show_cmd); UpdateWindow(nativeWindow); // fix ugly ATI driver bugs. Thanks to ariaci diff --git a/src/nbl/ui/CWindowWin32.h b/src/nbl/ui/CWindowWin32.h index fcb675900e..c1063adf6e 100644 --- a/src/nbl/ui/CWindowWin32.h +++ b/src/nbl/ui/CWindowWin32.h @@ -4,6 +4,7 @@ #include "nbl/ui/CWindowManagerWin32.h" #include "nbl/ui/CClipboardManagerWin32.h" +#include "nbl/ui/ICursorControl.h" #include #include