diff --git a/src/kiwano/core/event/WindowEvent.cpp b/src/kiwano/core/event/WindowEvent.cpp index 37cafb2b..2ab6ab75 100644 --- a/src/kiwano/core/event/WindowEvent.cpp +++ b/src/kiwano/core/event/WindowEvent.cpp @@ -39,4 +39,10 @@ WindowClosedEvent::WindowClosedEvent() { } +WindowFullscreenEvent::WindowFullscreenEvent() + : WindowEvent(KGE_EVENT(WindowFullscreenEvent)) + , fullscreen(false) +{ +} + } // namespace kiwano diff --git a/src/kiwano/core/event/WindowEvent.h b/src/kiwano/core/event/WindowEvent.h index 26a28e0d..96e5cfb2 100644 --- a/src/kiwano/core/event/WindowEvent.h +++ b/src/kiwano/core/event/WindowEvent.h @@ -29,6 +29,7 @@ KGE_DECLARE_SMART_PTR(WindowResizedEvent); KGE_DECLARE_SMART_PTR(WindowFocusChangedEvent); KGE_DECLARE_SMART_PTR(WindowTitleChangedEvent); KGE_DECLARE_SMART_PTR(WindowClosedEvent); +KGE_DECLARE_SMART_PTR(WindowFullscreenEvent); /** * \addtogroup Events @@ -93,6 +94,16 @@ public: WindowClosedEvent(); }; +/// \~chinese +/// @brief 窗口切换全屏事件 +class KGE_API WindowFullscreenEvent : public WindowEvent +{ +public: + bool fullscreen; + + WindowFullscreenEvent(); +}; + /** @} */ template <> @@ -102,8 +113,8 @@ struct IsEventType { return evt->GetType() == KGE_EVENT(WindowMovedEvent) || evt->GetType() == KGE_EVENT(WindowResizedEvent) || evt->GetType() == KGE_EVENT(WindowFocusChangedEvent) - || evt->GetType() == KGE_EVENT(WindowTitleChangedEvent) - || evt->GetType() == KGE_EVENT(WindowClosedEvent); + || evt->GetType() == KGE_EVENT(WindowTitleChangedEvent) || evt->GetType() == KGE_EVENT(WindowClosedEvent) + || evt->GetType() == KGE_EVENT(WindowFullscreenEvent); } }; diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp index e784c7cb..be976cb4 100644 --- a/src/kiwano/platform/Window.cpp +++ b/src/kiwano/platform/Window.cpp @@ -26,6 +26,7 @@ namespace kiwano Window::Window() : handle_(nullptr) , should_close_(false) + , is_fullscreen_(false) , width_(0) , height_(0) { @@ -88,9 +89,4 @@ void Window::PushEvent(EventPtr evt) event_queue_.push(evt); } -void Window::Destroy() -{ - should_close_ = true; -} - } // namespace kiwano diff --git a/src/kiwano/platform/Window.h b/src/kiwano/platform/Window.h index c4b24208..ac1aa963 100644 --- a/src/kiwano/platform/Window.h +++ b/src/kiwano/platform/Window.h @@ -132,8 +132,6 @@ public: * \~chinese * @brief 设置全屏模式 * @param fullscreen 是否全屏 - * @param width 窗口宽度 - * @param height 窗口高度 */ virtual void SetFullscreen(bool fullscreen) = 0; @@ -147,8 +145,7 @@ public: /** * \~chinese * @brief 轮询窗口事件 - * @return 返回事件队列中的第一个事件并将其从队列中移除\n - * 若事件队列为空则返回空指针 + * @return 返回事件队列中的第一个事件并将其从队列中移除, 若队列为空则返回空指针 */ EventPtr PollEvent(); @@ -177,12 +174,6 @@ public: */ void SetShouldClose(bool should); - /** - * \~chinese - * @brief 销毁窗口 - */ - virtual void Destroy(); - protected: Window(); @@ -190,6 +181,7 @@ protected: protected: bool should_close_; + bool is_fullscreen_; uint32_t width_; uint32_t height_; WindowHandle handle_; diff --git a/src/kiwano/platform/win32/WindowImpl.cpp b/src/kiwano/platform/win32/WindowImpl.cpp index 9f7c8e05..6a238585 100644 --- a/src/kiwano/platform/win32/WindowImpl.cpp +++ b/src/kiwano/platform/win32/WindowImpl.cpp @@ -59,8 +59,6 @@ public: void SetCursor(CursorType cursor) override; - void Destroy() override; - void PumpEvents() override; DWORD GetStyle() const; @@ -75,7 +73,6 @@ public: private: bool resizable_; - bool is_fullscreen_; CursorType mouse_cursor_; String device_name_; @@ -136,36 +133,10 @@ void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_wi *win_height = screenh; } -void ChangeFullScreenResolution(uint32_t width, uint32_t height, const CHAR* device_name) -{ - DEVMODEA mode; - - memset(&mode, 0, sizeof(mode)); - mode.dmSize = sizeof(mode); - mode.dmPelsWidth = width; - mode.dmPelsHeight = height; - mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; - - LONG ret = ::ChangeDisplaySettingsExA(device_name, &mode, NULL, CDS_FULLSCREEN, NULL); - if (ret != DISP_CHANGE_SUCCESSFUL) - { - KGE_ERROR("ChangeDisplaySettings failed with error code %d", ret); - } -} - -void RestoreResolution(const CHAR* device_name) -{ - LONG ret = ::ChangeDisplaySettingsExA(device_name, NULL, NULL, 0, NULL); - if (ret != DISP_CHANGE_SUCCESSFUL) - { - KGE_ERROR("ChangeDisplaySettings failed with error code %d", ret); - } -} } // namespace WindowWin32Impl::WindowWin32Impl() - : is_fullscreen_(false) - , resizable_(false) + : resizable_(false) , mouse_cursor_(CursorType::Arrow) , key_map_{} { @@ -213,7 +184,11 @@ WindowWin32Impl::WindowWin32Impl() WindowWin32Impl::~WindowWin32Impl() { - this->Destroy(); + if (handle_) + { + ::DestroyWindow(handle_); + handle_ = nullptr; + } } void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, @@ -255,10 +230,7 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, int left = -1, top = -1; - resizable_ = resizable; - is_fullscreen_ = fullscreen; - - if (is_fullscreen_) + if (fullscreen) { top = monitor_info_ex.rcMonitor.top; left = monitor_info_ex.rcMonitor.left; @@ -283,7 +255,7 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, height = win_height; } - handle_ = ::CreateWindowExA(is_fullscreen_ ? WS_EX_TOPMOST : 0, "KiwanoAppWnd", title.c_str(), GetStyle(), + handle_ = ::CreateWindowExA(fullscreen ? WS_EX_TOPMOST : 0, "KiwanoAppWnd", title.c_str(), GetStyle(), left, top, width, height, nullptr, nullptr, hinst, nullptr); if (handle_ == nullptr) @@ -292,8 +264,9 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Create window failed"); } - width_ = width; - height_ = height; + width_ = width; + height_ = height; + resizable_ = resizable; // disable imm ::ImmAssociateContext(handle_, nullptr); @@ -306,7 +279,7 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, if (is_fullscreen_) { - ChangeFullScreenResolution(width, height, device_name_.c_str()); + SetFullscreen(true); } } @@ -322,58 +295,47 @@ void WindowWin32Impl::PumpEvents() void WindowWin32Impl::SetTitle(const String& title) { - if (handle_) - { - ::SetWindowTextA(handle_, title.c_str()); - } + KGE_ASSERT(handle_); + ::SetWindowTextA(handle_, title.c_str()); } void WindowWin32Impl::SetIcon(uint32_t icon_resource) { - if (handle_) - { - HINSTANCE hinstance = ::GetModuleHandle(nullptr); - HICON icon = (HICON)::LoadImage(hinstance, MAKEINTRESOURCE(icon_resource), IMAGE_ICON, 0, 0, - LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + KGE_ASSERT(handle_); - ::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon); - ::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon); - } + HINSTANCE hinstance = ::GetModuleHandle(nullptr); + HICON icon = (HICON)::LoadImage(hinstance, MAKEINTRESOURCE(icon_resource), IMAGE_ICON, 0, 0, + LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + + ::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon); + ::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon); } void WindowWin32Impl::Resize(uint32_t width, uint32_t height) { - if (handle_) + KGE_ASSERT(handle_); + if (!is_fullscreen_) { - if (!is_fullscreen_) - { - MONITORINFOEXA info = GetMoniterInfoEx(handle_); + MONITORINFOEXA info = GetMoniterInfoEx(handle_); - uint32_t screenw = uint32_t(info.rcWork.right - info.rcWork.left); - uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top); + uint32_t screenw = uint32_t(info.rcWork.right - info.rcWork.left); + uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top); - RECT rc = { 0, 0, LONG(width), LONG(height) }; - ::AdjustWindowRect(&rc, GetStyle(), false); + RECT rc = { 0, 0, LONG(width), LONG(height) }; + ::AdjustWindowRect(&rc, GetStyle(), false); - width = rc.right - rc.left; - height = rc.bottom - rc.top; + width = rc.right - rc.left; + height = rc.bottom - rc.top; - int left = screenw > width ? ((screenw - width) / 2) : 0; - int top = screenh > height ? ((screenh - height) / 2) : 0; + int left = screenw > width ? ((screenw - width) / 2) : 0; + int top = screenh > height ? ((screenh - height) / 2) : 0; - ::SetWindowPos(handle_, 0, left, top, width, height, SWP_NOZORDER | SWP_NOACTIVATE); - } - else - { - // move window to (0, 0) before display switch - ::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE); - - ChangeFullScreenResolution(width, height, device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, - SWP_NOACTIVATE); - } + ::SetWindowPos(handle_, 0, left, top, width, height, SWP_NOZORDER | SWP_NOACTIVATE); + } + else + { + MONITORINFOEXA info = GetMoniterInfoEx(handle_); + ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, SWP_NOACTIVATE); } } @@ -383,39 +345,32 @@ void WindowWin32Impl::SetFullscreen(bool fullscreen) { is_fullscreen_ = fullscreen; - uint32_t width = GetWidth(); - uint32_t height = GetHeight(); - if (is_fullscreen_) { - // move window to (0, 0) before display switch - ::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE); - - ChangeFullScreenResolution(width, height, device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - + // Reset window style ::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle()); - ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, + + // Top the window + MONITORINFOEXA info = GetMoniterInfoEx(handle_); + ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width_, height_, SWP_NOACTIVATE); } else { - RestoreResolution(device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - - uint32_t screenw = uint32_t(info.rcWork.right - info.rcWork.left); - uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top); - - int left = screenw > width ? ((screenw - width) / 2) : 0; - int top = screenh > height ? ((screenh - height) / 2) : 0; - + // Reset window style ::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle()); - ::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, width, height, SWP_DRAWFRAME | SWP_FRAMECHANGED); + + // Unpin the window + ::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); } ::ShowWindow(handle_, SW_SHOWNORMAL); + + // Send event + WindowFullscreenEventPtr evt = new WindowFullscreenEvent; + evt->fullscreen = is_fullscreen_; + PushEvent(evt); } } @@ -424,18 +379,26 @@ void WindowWin32Impl::SetCursor(CursorType cursor) mouse_cursor_ = cursor; } -void WindowWin32Impl::Destroy() +void WindowWin32Impl::SetActive(bool actived) { + if (!handle_) + return; + if (is_fullscreen_) - RestoreResolution(device_name_.c_str()); - - if (handle_) { - ::DestroyWindow(handle_); - handle_ = nullptr; + // Hide window when it is not active + if (actived) + { + MONITORINFOEXA info = GetMoniterInfoEx(handle_); + ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width_, height_, + SWP_NOACTIVATE); + } + else + { + ::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + ::ShowWindow(handle_, SW_MINIMIZE); + } } - - Window::Destroy(); } DWORD WindowWin32Impl::GetStyle() const @@ -476,31 +439,6 @@ void WindowWin32Impl::UpdateCursor() ::SetCursor(::LoadCursor(nullptr, win32_cursor)); } -void WindowWin32Impl::SetActive(bool actived) -{ - if (!handle_) - return; - - if (is_fullscreen_) - { - if (actived) - { - ChangeFullScreenResolution(GetWidth(), GetHeight(), device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, GetWidth(), GetHeight(), - SWP_NOACTIVATE); - } - else - { - RestoreResolution(device_name_.c_str()); - - ::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - ::ShowWindow(handle_, SW_MINIMIZE); - } - } -} - LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) { switch (msg) diff --git a/src/kiwano/render/DirectX/D3D10DeviceResources.cpp b/src/kiwano/render/DirectX/D3D10DeviceResources.cpp index 70c4b74b..662cbb90 100644 --- a/src/kiwano/render/DirectX/D3D10DeviceResources.cpp +++ b/src/kiwano/render/DirectX/D3D10DeviceResources.cpp @@ -65,17 +65,19 @@ inline bool SdkLayersAvailable() struct D3D10DeviceResources : public ID3D10DeviceResources { public: - HRESULT Present(bool vsync); + HRESULT Present(bool vsync) override; - void ClearRenderTarget(Color& clear_color); + void ClearRenderTarget(Color& clear_color) override; - HRESULT HandleDeviceLost(); + HRESULT HandleDeviceLost() override; - HRESULT SetLogicalSize(Size logical_size); + HRESULT SetLogicalSize(Size logical_size) override; - HRESULT SetDpi(float dpi); + HRESULT SetDpi(float dpi) override; - void DiscardResources(); + HRESULT SetFullscreenState(bool fullscreen) override; + + void DiscardResources() override; public: unsigned long STDMETHODCALLTYPE AddRef(); @@ -396,6 +398,11 @@ HRESULT D3D10DeviceResources::SetDpi(float dpi) return S_OK; } +HRESULT D3D10DeviceResources::SetFullscreenState(bool fullscreen) +{ + return dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr); +} + STDMETHODIMP_(unsigned long) D3D10DeviceResources::AddRef() { return InterlockedIncrement(&ref_count_); diff --git a/src/kiwano/render/DirectX/D3D11DeviceResources.cpp b/src/kiwano/render/DirectX/D3D11DeviceResources.cpp index a78790d3..fe0b7b12 100644 --- a/src/kiwano/render/DirectX/D3D11DeviceResources.cpp +++ b/src/kiwano/render/DirectX/D3D11DeviceResources.cpp @@ -64,6 +64,8 @@ public: HRESULT SetDpi(float dpi) override; + HRESULT SetFullscreenState(bool fullscreen) override; + void DiscardResources() override; public: @@ -416,6 +418,11 @@ HRESULT D3D11DeviceResources::SetDpi(float dpi) return S_OK; } +HRESULT D3D11DeviceResources::SetFullscreenState(bool fullscreen) +{ + return dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr); +} + STDMETHODIMP_(unsigned long) D3D11DeviceResources::AddRef() { return InterlockedIncrement(&ref_count_); diff --git a/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h b/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h index 5cdde8b1..421376a0 100644 --- a/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h +++ b/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h @@ -37,6 +37,8 @@ public: virtual HRESULT SetDpi(float dpi) = 0; + virtual HRESULT SetFullscreenState(bool fullscreen) = 0; + virtual void DiscardResources() = 0; };