fix bug: exiting fullscreen mode makes the window smaller
This commit is contained in:
parent
ef8db9023c
commit
ae247dd676
|
|
@ -39,4 +39,10 @@ WindowClosedEvent::WindowClosedEvent()
|
|||
{
|
||||
}
|
||||
|
||||
WindowFullscreenEvent::WindowFullscreenEvent()
|
||||
: WindowEvent(KGE_EVENT(WindowFullscreenEvent))
|
||||
, fullscreen(false)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -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<WindowEvent>
|
|||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ public:
|
|||
|
||||
virtual HRESULT SetDpi(float dpi) = 0;
|
||||
|
||||
virtual HRESULT SetFullscreenState(bool fullscreen) = 0;
|
||||
|
||||
virtual void DiscardResources() = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue