This commit is contained in:
liuhaibo.2020 2020-05-15 16:31:17 +08:00
commit d7c7cb9841
8 changed files with 113 additions and 154 deletions

View File

@ -39,4 +39,10 @@ WindowClosedEvent::WindowClosedEvent()
{ {
} }
WindowFullscreenEvent::WindowFullscreenEvent()
: WindowEvent(KGE_EVENT(WindowFullscreenEvent))
, fullscreen(false)
{
}
} // namespace kiwano } // namespace kiwano

View File

@ -29,6 +29,7 @@ KGE_DECLARE_SMART_PTR(WindowResizedEvent);
KGE_DECLARE_SMART_PTR(WindowFocusChangedEvent); KGE_DECLARE_SMART_PTR(WindowFocusChangedEvent);
KGE_DECLARE_SMART_PTR(WindowTitleChangedEvent); KGE_DECLARE_SMART_PTR(WindowTitleChangedEvent);
KGE_DECLARE_SMART_PTR(WindowClosedEvent); KGE_DECLARE_SMART_PTR(WindowClosedEvent);
KGE_DECLARE_SMART_PTR(WindowFullscreenEvent);
/** /**
* \addtogroup Events * \addtogroup Events
@ -93,6 +94,16 @@ public:
WindowClosedEvent(); WindowClosedEvent();
}; };
/// \~chinese
/// @brief 窗口切换全屏事件
class KGE_API WindowFullscreenEvent : public WindowEvent
{
public:
bool fullscreen;
WindowFullscreenEvent();
};
/** @} */ /** @} */
template <> template <>
@ -102,8 +113,8 @@ struct IsEventType<WindowEvent>
{ {
return evt->GetType() == KGE_EVENT(WindowMovedEvent) || evt->GetType() == KGE_EVENT(WindowResizedEvent) return evt->GetType() == KGE_EVENT(WindowMovedEvent) || evt->GetType() == KGE_EVENT(WindowResizedEvent)
|| evt->GetType() == KGE_EVENT(WindowFocusChangedEvent) || evt->GetType() == KGE_EVENT(WindowFocusChangedEvent)
|| evt->GetType() == KGE_EVENT(WindowTitleChangedEvent) || evt->GetType() == KGE_EVENT(WindowTitleChangedEvent) || evt->GetType() == KGE_EVENT(WindowClosedEvent)
|| evt->GetType() == KGE_EVENT(WindowClosedEvent); || evt->GetType() == KGE_EVENT(WindowFullscreenEvent);
} }
}; };

View File

@ -26,6 +26,7 @@ namespace kiwano
Window::Window() Window::Window()
: handle_(nullptr) : handle_(nullptr)
, should_close_(false) , should_close_(false)
, is_fullscreen_(false)
, width_(0) , width_(0)
, height_(0) , height_(0)
{ {
@ -88,9 +89,4 @@ void Window::PushEvent(EventPtr evt)
event_queue_.push(evt); event_queue_.push(evt);
} }
void Window::Destroy()
{
should_close_ = true;
}
} // namespace kiwano } // namespace kiwano

View File

@ -132,8 +132,6 @@ public:
* \~chinese * \~chinese
* @brief * @brief
* @param fullscreen * @param fullscreen
* @param width
* @param height
*/ */
virtual void SetFullscreen(bool fullscreen) = 0; virtual void SetFullscreen(bool fullscreen) = 0;
@ -147,8 +145,7 @@ public:
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @return \n * @return ,
*
*/ */
EventPtr PollEvent(); EventPtr PollEvent();
@ -177,12 +174,6 @@ public:
*/ */
void SetShouldClose(bool should); void SetShouldClose(bool should);
/**
* \~chinese
* @brief
*/
virtual void Destroy();
protected: protected:
Window(); Window();
@ -190,6 +181,7 @@ protected:
protected: protected:
bool should_close_; bool should_close_;
bool is_fullscreen_;
uint32_t width_; uint32_t width_;
uint32_t height_; uint32_t height_;
WindowHandle handle_; WindowHandle handle_;

View File

@ -59,8 +59,6 @@ public:
void SetCursor(CursorType cursor) override; void SetCursor(CursorType cursor) override;
void Destroy() override;
void PumpEvents() override; void PumpEvents() override;
DWORD GetStyle() const; DWORD GetStyle() const;
@ -75,7 +73,6 @@ public:
private: private:
bool resizable_; bool resizable_;
bool is_fullscreen_;
CursorType mouse_cursor_; CursorType mouse_cursor_;
String device_name_; String device_name_;
@ -136,36 +133,10 @@ void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_wi
*win_height = screenh; *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 } // namespace
WindowWin32Impl::WindowWin32Impl() WindowWin32Impl::WindowWin32Impl()
: is_fullscreen_(false) : resizable_(false)
, resizable_(false)
, mouse_cursor_(CursorType::Arrow) , mouse_cursor_(CursorType::Arrow)
, key_map_{} , key_map_{}
{ {
@ -213,7 +184,11 @@ WindowWin32Impl::WindowWin32Impl()
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, 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; int left = -1, top = -1;
resizable_ = resizable; if (fullscreen)
is_fullscreen_ = fullscreen;
if (is_fullscreen_)
{ {
top = monitor_info_ex.rcMonitor.top; top = monitor_info_ex.rcMonitor.top;
left = monitor_info_ex.rcMonitor.left; 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; 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); left, top, width, height, nullptr, nullptr, hinst, nullptr);
if (handle_ == 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"); KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Create window failed");
} }
width_ = width; width_ = width;
height_ = height; height_ = height;
resizable_ = resizable;
// disable imm // disable imm
::ImmAssociateContext(handle_, nullptr); ::ImmAssociateContext(handle_, nullptr);
@ -306,7 +279,7 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height,
if (is_fullscreen_) 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) void WindowWin32Impl::SetTitle(const String& title)
{ {
if (handle_) KGE_ASSERT(handle_);
{ ::SetWindowTextA(handle_, title.c_str());
::SetWindowTextA(handle_, title.c_str());
}
} }
void WindowWin32Impl::SetIcon(uint32_t icon_resource) void WindowWin32Impl::SetIcon(uint32_t icon_resource)
{ {
if (handle_) KGE_ASSERT(handle_);
{
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); HINSTANCE hinstance = ::GetModuleHandle(nullptr);
::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon); 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) 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 screenw = uint32_t(info.rcWork.right - info.rcWork.left);
uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top); uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top);
RECT rc = { 0, 0, LONG(width), LONG(height) }; RECT rc = { 0, 0, LONG(width), LONG(height) };
::AdjustWindowRect(&rc, GetStyle(), false); ::AdjustWindowRect(&rc, GetStyle(), false);
width = rc.right - rc.left; width = rc.right - rc.left;
height = rc.bottom - rc.top; height = rc.bottom - rc.top;
int left = screenw > width ? ((screenw - width) / 2) : 0; int left = screenw > width ? ((screenw - width) / 2) : 0;
int top = screenh > height ? ((screenh - height) / 2) : 0; int top = screenh > height ? ((screenh - height) / 2) : 0;
::SetWindowPos(handle_, 0, left, top, width, height, SWP_NOZORDER | SWP_NOACTIVATE); ::SetWindowPos(handle_, 0, left, top, width, height, SWP_NOZORDER | SWP_NOACTIVATE);
} }
else else
{ {
// move window to (0, 0) before display switch MONITORINFOEXA info = GetMoniterInfoEx(handle_);
::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE); ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, 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);
}
} }
} }
@ -383,39 +345,32 @@ void WindowWin32Impl::SetFullscreen(bool fullscreen)
{ {
is_fullscreen_ = fullscreen; is_fullscreen_ = fullscreen;
uint32_t width = GetWidth();
uint32_t height = GetHeight();
if (is_fullscreen_) if (is_fullscreen_)
{ {
// move window to (0, 0) before display switch // Reset window style
::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE);
ChangeFullScreenResolution(width, height, device_name_.c_str());
MONITORINFOEXA info = GetMoniterInfoEx(handle_);
::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle()); ::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); SWP_NOACTIVATE);
} }
else else
{ {
RestoreResolution(device_name_.c_str()); // Reset window style
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;
::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle()); ::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); ::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; mouse_cursor_ = cursor;
} }
void WindowWin32Impl::Destroy() void WindowWin32Impl::SetActive(bool actived)
{ {
if (!handle_)
return;
if (is_fullscreen_) if (is_fullscreen_)
RestoreResolution(device_name_.c_str());
if (handle_)
{ {
::DestroyWindow(handle_); // Hide window when it is not active
handle_ = nullptr; 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 DWORD WindowWin32Impl::GetStyle() const
@ -476,31 +439,6 @@ void WindowWin32Impl::UpdateCursor()
::SetCursor(::LoadCursor(nullptr, win32_cursor)); ::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) LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam)
{ {
switch (msg) switch (msg)

View File

@ -65,17 +65,19 @@ inline bool SdkLayersAvailable()
struct D3D10DeviceResources : public ID3D10DeviceResources struct D3D10DeviceResources : public ID3D10DeviceResources
{ {
public: 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: public:
unsigned long STDMETHODCALLTYPE AddRef(); unsigned long STDMETHODCALLTYPE AddRef();
@ -396,6 +398,11 @@ HRESULT D3D10DeviceResources::SetDpi(float dpi)
return S_OK; return S_OK;
} }
HRESULT D3D10DeviceResources::SetFullscreenState(bool fullscreen)
{
return dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr);
}
STDMETHODIMP_(unsigned long) D3D10DeviceResources::AddRef() STDMETHODIMP_(unsigned long) D3D10DeviceResources::AddRef()
{ {
return InterlockedIncrement(&ref_count_); return InterlockedIncrement(&ref_count_);

View File

@ -64,6 +64,8 @@ public:
HRESULT SetDpi(float dpi) override; HRESULT SetDpi(float dpi) override;
HRESULT SetFullscreenState(bool fullscreen) override;
void DiscardResources() override; void DiscardResources() override;
public: public:
@ -416,6 +418,11 @@ HRESULT D3D11DeviceResources::SetDpi(float dpi)
return S_OK; return S_OK;
} }
HRESULT D3D11DeviceResources::SetFullscreenState(bool fullscreen)
{
return dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr);
}
STDMETHODIMP_(unsigned long) D3D11DeviceResources::AddRef() STDMETHODIMP_(unsigned long) D3D11DeviceResources::AddRef()
{ {
return InterlockedIncrement(&ref_count_); return InterlockedIncrement(&ref_count_);

View File

@ -37,6 +37,8 @@ public:
virtual HRESULT SetDpi(float dpi) = 0; virtual HRESULT SetDpi(float dpi) = 0;
virtual HRESULT SetFullscreenState(bool fullscreen) = 0;
virtual void DiscardResources() = 0; virtual void DiscardResources() = 0;
}; };