diff --git a/openVulkanoCpp/Base/UI/BaseWindow.hpp b/openVulkanoCpp/Base/UI/BaseWindow.hpp index b6291f0..8274058 100644 --- a/openVulkanoCpp/Base/UI/BaseWindow.hpp +++ b/openVulkanoCpp/Base/UI/BaseWindow.hpp @@ -5,11 +5,19 @@ namespace openVulkanoCpp { class BaseWindow : virtual public IWindow { + protected: const int windowId; + WindowConfiguration windowConfig; + public: BaseWindow() : windowId(CreateWindowId()) {} virtual ~BaseWindow() = default; + const WindowConfiguration& GetWindowConfiguration() override + { + return windowConfig; + } + void GetSize(int* width, int* height) override = 0; void GetSize(uint32_t* width, uint32_t* height) override @@ -72,6 +80,16 @@ namespace openVulkanoCpp return position; } + const std::string& GetTitle() override + { + return windowConfig.title; + } + + WindowMode GetWindowMode() override + { + return windowConfig.windowMode; + } + void SetPosition(int posX, int posY) override = 0; void SetPosition(glm::ivec2 pos) override { SetPosition(pos.x, pos.y); } diff --git a/openVulkanoCpp/Base/UI/IWindow.hpp b/openVulkanoCpp/Base/UI/IWindow.hpp index d7e0472..22a7181 100644 --- a/openVulkanoCpp/Base/UI/IWindow.hpp +++ b/openVulkanoCpp/Base/UI/IWindow.hpp @@ -11,13 +11,24 @@ namespace openVulkanoCpp { enum WindowMode { - WINDOWED, BORDERLESS, FULLSCREEN, BORDERLESS_FULLSCREEN + WINDOWED = 0, + BORDERLESS = 1, + FULLSCREEN = 2, + BORDERLESS_FULLSCREEN = 3 }; class IWindowHandler; class IVulkanWindow; class IOpenGlWindow; + struct WindowConfiguration + { + uint32_t width = 1280, height = 720; + int posX = 0, posY = 0; + std::string title = "Window Title"; + WindowMode windowMode = WINDOWED; + }; + class IWindow : public ITickable, public ICloseable { public: @@ -33,6 +44,7 @@ namespace openVulkanoCpp virtual void SetFullscreen() { SetWindowMode(FULLSCREEN); } virtual void SetWindowed() { SetWindowMode(WINDOWED); } + virtual const WindowConfiguration& GetWindowConfiguration() = 0; virtual uint32_t GetWidth() = 0; virtual uint32_t GetHeight() = 0; virtual void GetSize(int* width, int* height) = 0; diff --git a/openVulkanoCpp/Host/WindowGLFW.hpp b/openVulkanoCpp/Host/WindowGLFW.hpp index 8fc7c40..c65d616 100644 --- a/openVulkanoCpp/Host/WindowGLFW.hpp +++ b/openVulkanoCpp/Host/WindowGLFW.hpp @@ -9,19 +9,49 @@ namespace openVulkanoCpp { private: GLFWwindow* window = nullptr; - uint32_t width = 1280, height = 720; - std::string title = "Window Title"; - WindowMode windowMode = WINDOWED; IWindowHandler* handler = nullptr; public: WindowGLFW() = default; - virtual ~WindowGLFW() { if (window != nullptr) Close(); } + + virtual ~WindowGLFW() override + { + if (window != nullptr) Close(); + } protected: + GLFWmonitor* GetCurrentMonitor() const + { + int monitorCount = 0; + GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); + for(int i = 0; i < monitorCount; i++) + { + int posX, posY, sizeX, sizeY; + glfwGetMonitorWorkarea(monitors[i], &posX, &posY, &sizeX, &sizeY); + if (windowConfig.posX >= posX && windowConfig.posX < posX + sizeX && + windowConfig.posY >= posY && windowConfig.posY < posY + sizeY) + { + return monitors[i]; + } + } + return nullptr; + } + + GLFWmonitor* GetTargetMonitor() const + { + if(windowConfig.windowMode == FULLSCREEN) + { + // TODO add config to control used display + return GetPrimaryMonitor(); + } + return nullptr; + } + void Create() { - window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); + glfwWindowHint(GLFW_DECORATED, (~windowConfig.windowMode) & 1); + //TODO handle full screen resolutions + window = glfwCreateWindow(windowConfig.width, windowConfig.height, windowConfig.title.c_str(), GetTargetMonitor(), nullptr); if(!window) return; glfwSetWindowUserPointer(window, this); RegisterCallbacks(); @@ -109,23 +139,15 @@ namespace openVulkanoCpp void SetTitle(const std::string& title) override { - this->title = title; + windowConfig.title = title; glfwSetWindowTitle(window, title.c_str()); } - const std::string& GetTitle() override - { - return title; - } - void SetSize(uint32_t width, uint32_t height) override { - if (!window) - { - this->width = width; - this->height = height; - } - else + windowConfig.width = width; + windowConfig.height = height; + if (window) { glfwSetWindowSize(window, width, height); } @@ -133,7 +155,12 @@ namespace openVulkanoCpp void SetPosition(int posX, int posY) override { - glfwSetWindowPos(window, posX, posY); + windowConfig.posX = posX; + windowConfig.posY = posY; + if(window) + { + glfwSetWindowPos(window, posX, posY); + } } void SetSizeLimits(int minWidth, int minHeight, int maxWidth, int maxHeight) override @@ -152,9 +179,52 @@ namespace openVulkanoCpp void SetWindowMode(WindowMode windowMode) override { - if(windowMode == this->windowMode) return; //Nothing change here - //TODO - this->windowMode = windowMode; + if (windowMode == this->windowConfig.windowMode) return; // Nothing to change here + if (!window) return; // Window not yet created + this->windowConfig.windowMode = windowMode; + uint32_t sizeX = 0, sizeY = 0; + int posX = 0, posY = 0; + GLFWmonitor* monitor = nullptr; + glfwWindowHint(GLFW_DECORATED, (~windowMode) & 1); + if(windowMode == WINDOWED || windowMode == BORDERLESS) + { + sizeX = windowConfig.width; + sizeY = windowConfig.height; + posX = windowConfig.posX; + posY = windowConfig.posY; + monitor = nullptr; + if(windowMode == WINDOWED) + { + Logger::WINDOW->info("Switching to Windowed mode"); + } + else + { + Logger::WINDOW->info("Switching to Borderless Windowed mode"); + } + } + else + { // Fullscreen + GetPosition(&windowConfig.posX, &windowConfig.posY); // Backup current window position + monitor = GetCurrentMonitor(); + if (!monitor) monitor = GetPrimaryMonitor(); + if (!monitor) return; // We don't have a monitor to set the fullscreen window to + const GLFWvidmode* videoMode = glfwGetVideoMode(monitor ? monitor : GetPrimaryMonitor()); + sizeX = videoMode->width; + sizeY = videoMode->height; + if (windowMode == FULLSCREEN) + { + // TODO find video mode that best matches user settings + Logger::WINDOW->info("Switching to Fullscreen mode"); + } + else if (windowMode == BORDERLESS_FULLSCREEN) + { + int sX, sY; + glfwGetMonitorWorkarea(monitor, &posX, &posY, &sX, &sY); + monitor = nullptr; + Logger::WINDOW->info("Switching to Borderless Fullscreen mode"); + } + } + glfwSetWindowMonitor(this->window, monitor, posX, posY, sizeX, sizeY, GLFW_DONT_CARE); } void SetWindowHandler(IWindowHandler* handler) override @@ -173,11 +243,6 @@ namespace openVulkanoCpp } // Status getter - WindowMode GetWindowMode() override - { - return windowMode; - } - void GetSize(int* width, int* height) override { glfwGetWindowSize(window, width, height); @@ -240,6 +305,11 @@ namespace openVulkanoCpp void OnMove(const int posX, const int posY) { Logger::WINDOW->debug("Window (id: {0}) moved (x: {1}, y: {2})", GetWindowId(), posX, posY); + if (windowConfig.windowMode == WINDOWED || windowConfig.windowMode == BORDERLESS) + { // Don't save window position for fullscreen + windowConfig.posX = posX; + windowConfig.posY = posY; + } handler->OnWindowMove(this, posX, posY); } @@ -260,6 +330,18 @@ namespace openVulkanoCpp protected: virtual void OnKeyEvent(int key, int scanCode, int action, int mods) { + if (key == GLFW_KEY_ENTER && action == GLFW_PRESS && mods == GLFW_MOD_ALT) + { + WindowMode newMode = FULLSCREEN; + switch (windowConfig.windowMode) + { + case WINDOWED: newMode = FULLSCREEN; break; + case BORDERLESS: newMode = BORDERLESS_FULLSCREEN; break; + case FULLSCREEN: newMode = WINDOWED; break; + case BORDERLESS_FULLSCREEN: newMode = BORDERLESS; break; + } + SetWindowMode(newMode); + } switch (action) { case GLFW_PRESS: OnKeyPressed(key, mods); break;