Replace RenderWindow with swapchains

This commit is contained in:
SirLynix
2023-01-21 12:02:34 +01:00
committed by Jérôme Leclercq
parent 8db1c04568
commit 18851c9185
66 changed files with 1404 additions and 2048 deletions

View File

@@ -3,12 +3,25 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/AppWindowingComponent.hpp>
#include <Nazara/Core/ApplicationBase.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
void AppWindowingComponent::Update(Time elapsedTime)
{
// SDL_PollEvent
Window::ProcessEvents();
for (auto it = m_windows.begin(); it != m_windows.end();)
{
Window& window = **it;
if (!window.IsOpen(true))
it = m_windows.erase(it);
else
++it;
}
if (m_quitOnLastWindowClosed && m_windows.empty())
GetApp().Quit();
}
}

View File

@@ -34,16 +34,11 @@ namespace Nz
{
switch (sdlButton)
{
case SDL_BUTTON_LEFT:
return Mouse::Left;
case SDL_BUTTON_MIDDLE:
return Mouse::Middle;
case SDL_BUTTON_RIGHT:
return Mouse::Right;
case SDL_BUTTON_X1:
return Mouse::XButton1;
case SDL_BUTTON_X2:
return Mouse::XButton2;
case SDL_BUTTON_LEFT: return Mouse::Left;
case SDL_BUTTON_MIDDLE: return Mouse::Middle;
case SDL_BUTTON_RIGHT: return Mouse::Right;
case SDL_BUTTON_X1: return Mouse::XButton1;
case SDL_BUTTON_X2: return Mouse::XButton2;
default:
NazaraAssert(false, "Unkown mouse button");
return Mouse::Left;
@@ -54,30 +49,16 @@ namespace Nz
WindowImpl::WindowImpl(Window* parent) :
m_cursor(nullptr),
m_handle(nullptr),
//m_callback(0),
m_style(0),
m_maxSize(-1),
m_minSize(-1),
m_parent(parent),
m_keyRepeat(true),
m_mouseInside(false),
m_smoothScrolling(false),
m_scrolling(0)
m_eventListener(false),
m_ignoreNextMouseMove(false),
m_lastEditEventLength(0)
{
m_cursor = SDL_GetDefaultCursor();
}
bool WindowImpl::Create(const VideoMode& mode, const std::string& title, WindowStyleFlags style)
{
bool async = (style & WindowStyle::Threaded) != 0;
if (async)
{
NazaraError("SDL2 backend doesn't support asyn window for now");
return false;
}
bool fullscreen = (style & WindowStyle::Fullscreen) != 0;
Uint32 winStyle = 0;
@@ -88,7 +69,6 @@ namespace Nz
if (fullscreen)
winStyle |= SDL_WINDOW_FULLSCREEN;
// Testé une seconde fois car sa valeur peut changer
if (fullscreen)
{
x = 0;
@@ -105,72 +85,106 @@ namespace Nz
if (style & WindowStyle::Resizable)
winStyle |= SDL_WINDOW_RESIZABLE;
if (style & WindowStyle::Max)
winStyle |= SDL_WINDOW_MAXIMIZED;
m_eventListener = true;
m_ownsWindow = true;
m_sizemove = false;
m_style = style;
m_handle = SDL_CreateWindow(title.c_str(), x, y, width, height, winStyle);
if (!m_handle)
{
NazaraError("Failed to create window: " + Error::GetLastSystemError());
return false;
}
PrepareWindow(fullscreen);
SDL_AddEventWatch(HandleEvent, this);
m_windowId = SDL_GetWindowID(m_handle);
SetEventListener(true);
return true;
}
bool WindowImpl::Create(void* handle)
bool WindowImpl::Create(WindowHandle handle)
{
m_handle = SDL_CreateWindowFrom(handle);
void* systemHandle = nullptr;
switch (handle.type)
{
case WindowBackend::Invalid:
{
NazaraError("unsupported creation from a Wayland handle");
return false;
}
case WindowBackend::Wayland:
{
NazaraError("unsupported creation from a Wayland handle");
return false;
}
case WindowBackend::Cocoa: systemHandle = handle.cocoa.window; break;
case WindowBackend::X11: systemHandle = (void*) handle.x11.window; break;
case WindowBackend::Windows: systemHandle = handle.windows.window; break;
}
m_ownsWindow = false;
m_handle = SDL_CreateWindowFrom(systemHandle);
if (!m_handle)
{
NazaraError("Invalid handle");
return false;
}
m_eventListener = false;
m_ownsWindow = false;
m_sizemove = false;
SDL_GetWindowPosition(m_handle, &m_position.x, &m_position.y);
int width;
int height;
SDL_GetWindowSize(m_handle, &width, &height);
m_size.Set(width, height);
m_windowId = SDL_GetWindowID(m_handle);
SetEventListener(true);
return true;
}
void WindowImpl::Destroy()
{
if (m_ownsWindow && m_handle)
SetEventListener(false);
if (m_handle)
{
SDL_DelEventWatch(HandleEvent, this);
SDL_DestroyWindow(m_handle);
if (m_ownsWindow)
SDL_DestroyWindow(m_handle);
m_handle = nullptr;
}
else
SetEventListener(false);
}
void WindowImpl::EnableKeyRepeat(bool enable)
Vector2i WindowImpl::FetchPosition() const
{
m_keyRepeat = enable;
int x, y;
SDL_GetWindowPosition(m_handle, &x, &y);
return { x, y };
}
void WindowImpl::EnableSmoothScrolling(bool enable)
Vector2ui WindowImpl::FetchSize() const
{
m_smoothScrolling = enable;
int width, height;
SDL_GetWindowSize(m_handle, &width, &height);
return { SafeCast<unsigned int>(width), SafeCast<unsigned int>(height) };
}
WindowStyleFlags WindowImpl::FetchStyle() const
{
UInt32 windowFlags = SDL_GetWindowFlags(m_handle);
WindowStyleFlags styleFlags;
if (windowFlags & SDL_WINDOW_RESIZABLE)
styleFlags |= WindowStyle::Resizable;
if ((windowFlags & SDL_WINDOW_BORDERLESS) == 0)
styleFlags |= WindowStyle::Titlebar | WindowStyle::Closable;
if (windowFlags & SDL_WINDOW_FULLSCREEN)
styleFlags |= WindowStyle::Fullscreen;
return styleFlags;
}
std::string WindowImpl::FetchTitle() const
{
return SDL_GetWindowTitle(m_handle);
}
SDL_Window* WindowImpl::GetHandle() const
@@ -178,21 +192,6 @@ namespace Nz
return m_handle;
}
Vector2i WindowImpl::GetPosition() const
{
return m_position;
}
Vector2ui WindowImpl::GetSize() const
{
return m_size;
}
WindowStyleFlags WindowImpl::GetStyle() const
{
return m_style;
}
WindowHandle WindowImpl::GetSystemHandle() const
{
SDL_SysWMinfo wmInfo;
@@ -253,22 +252,14 @@ namespace Nz
return handle;
}
std::string WindowImpl::GetTitle() const
{
return SDL_GetWindowTitle(m_handle);
}
bool WindowImpl::HasFocus() const
{
return (SDL_GetWindowFlags(m_handle) & SDL_WINDOW_INPUT_FOCUS) != 0;
}
void WindowImpl::IgnoreNextMouseEvent(int mouseX, int mouseY)
void WindowImpl::IgnoreNextMouseEvent(int /*mouseX*/, int /*mouseY*/)
{
m_ignoreNextMouseMove = true;
// Petite astuce ... probablement foireuse dans certains cas :ahde:
m_mousePos.x = mouseX;
m_mousePos.y = mouseY;
}
bool WindowImpl::IsMinimized() const
@@ -297,27 +288,7 @@ namespace Nz
}
}
void WindowImpl::ProcessEvents(bool block)
{
if (m_ownsWindow)
SDL_PumpEvents();
/*if (m_ownsWindow)
{
if (block)
WaitMessage();
MSG message;
while (PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessageW(&message);
}
}*/
}
int WindowImpl::HandleEvent(void *userdata, SDL_Event* event)
int WindowImpl::HandleEvent(void* userdata, SDL_Event* event)
{
try
{
@@ -327,7 +298,7 @@ namespace Nz
{
case SDL_WINDOWEVENT:
{
if (SDL_GetWindowID(window->m_handle) != event->window.windowID)
if (window->m_windowId != event->window.windowID)
return 0;
WindowEvent windowEvent;
@@ -337,20 +308,16 @@ namespace Nz
windowEvent.type = WindowEventType::Quit;
break;
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
windowEvent.type = WindowEventType::Resized;
windowEvent.size.width = static_cast<unsigned int>(std::max(0, event->window.data1));
windowEvent.size.height = static_cast<unsigned int>(std::max(0, event->window.data2));
window->m_size.Set(windowEvent.size.width, windowEvent.size.height);
break;
case SDL_WINDOWEVENT_MOVED:
windowEvent.type = WindowEventType::Moved;
windowEvent.position.x = event->window.data1;
windowEvent.position.y = event->window.data2;
window->m_position.Set(event->window.data1, event->window.data2);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
@@ -364,23 +331,35 @@ namespace Nz
case SDL_WINDOWEVENT_ENTER:
windowEvent.type = WindowEventType::MouseEntered;
window->RefreshCursor();
break;
case SDL_WINDOWEVENT_LEAVE:
windowEvent.type = WindowEventType::MouseLeft;
break;
case SDL_WINDOWEVENT_MINIMIZED:
windowEvent.type = WindowEventType::Minimized;
break;
case SDL_WINDOWEVENT_RESTORED:
windowEvent.type = WindowEventType::Restored;
break;
default:
return 0;
}
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEMOTION:
{
if (SDL_GetWindowID(window->m_handle) != event->motion.windowID)
if (window->m_windowId != event->motion.windowID)
return 0;
if (window->m_ignoreNextMouseMove /*&& event->motion.x == window->m_mousePos.x && event->motion.y == window->m_mousePos.y*/)
if (window->m_ignoreNextMouseMove)
{
window->m_ignoreNextMouseMove = false;
return 0;
@@ -393,13 +372,13 @@ namespace Nz
windowEvent.mouseMove.deltaX = event->motion.xrel;
windowEvent.mouseMove.deltaY = event->motion.yrel;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEBUTTONDOWN:
{
if (SDL_GetWindowID(window->m_handle) != event->button.windowID)
if (window->m_windowId != event->button.windowID)
return 0;
WindowEvent windowEvent;
@@ -409,13 +388,13 @@ namespace Nz
windowEvent.mouseButton.y = event->button.y;
windowEvent.mouseButton.clickCount = event->button.clicks;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEBUTTONUP:
{
if (SDL_GetWindowID(window->m_handle) != event->button.windowID)
if (window->m_windowId != event->button.windowID)
return 0;
WindowEvent windowEvent;
@@ -424,25 +403,28 @@ namespace Nz
windowEvent.mouseButton.x = event->button.x;
windowEvent.mouseButton.y = event->button.y;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEWHEEL:
{
if (SDL_GetWindowID(window->m_handle) != event->wheel.windowID)
if (window->m_windowId != event->wheel.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::MouseWheelMoved;
windowEvent.mouseWheel.delta = event->wheel.y;
windowEvent.mouseWheel.delta = event->wheel.preciseY;
windowEvent.mouseWheel.x = event->wheel.mouseX;
windowEvent.mouseWheel.y = event->wheel.mouseY;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_KEYDOWN:
if (SDL_GetWindowID(window->m_handle) != event->key.windowID)
{
if (window->m_windowId != event->key.windowID)
return 0;
WindowEvent windowEvent;
@@ -455,7 +437,7 @@ namespace Nz
windowEvent.key.system = (event->key.keysym.mod & KMOD_GUI) != 0;
windowEvent.key.virtualKey = SDLHelper::FromSDL(event->key.keysym.sym);
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
// implements X11/Win32 APIs behavior for Enter and Backspace
switch (windowEvent.key.virtualKey)
@@ -470,7 +452,7 @@ namespace Nz
windowEvent.text.character = U'\n';
windowEvent.text.repeated = event->key.repeat != 0;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
@@ -479,7 +461,7 @@ namespace Nz
windowEvent.text.character = U'\b';
windowEvent.text.repeated = event->key.repeat != 0;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
default:
@@ -487,12 +469,14 @@ namespace Nz
}
break;
}
case SDL_KEYUP:
{
if (SDL_GetWindowID(window->m_handle) != event->key.windowID)
if (window->m_windowId != event->key.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::KeyReleased;
windowEvent.key.alt = (event->key.keysym.mod & KMOD_ALT) != 0;
windowEvent.key.control = (event->key.keysym.mod & KMOD_CTRL) != 0;
@@ -502,15 +486,16 @@ namespace Nz
windowEvent.key.system = (event->key.keysym.mod & KMOD_GUI) != 0;
windowEvent.key.virtualKey = SDLHelper::FromSDL(event->key.keysym.sym);
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_TEXTINPUT:
{
if (SDL_GetWindowID(window->m_handle) != event->text.windowID)
if (window->m_windowId != event->text.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::TextEntered;
windowEvent.text.repeated = false;
@@ -519,7 +504,7 @@ namespace Nz
{
windowEvent.text.character = *it;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
}
while (*it++);
@@ -528,9 +513,10 @@ namespace Nz
case SDL_TEXTEDITING:
{
if (SDL_GetWindowID(window->m_handle) != event->edit.windowID)
if (window->m_windowId != event->edit.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::TextEdited;
windowEvent.edit.length = event->edit.length;
window->m_lastEditEventLength = windowEvent.edit.length;
@@ -540,7 +526,7 @@ namespace Nz
windowEvent.edit.text[i] = event->edit.text[i];
}
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
}
@@ -557,7 +543,7 @@ namespace Nz
return 0;
}
void WindowImpl::SetCursor(const Cursor& cursor)
void WindowImpl::UpdateCursor(const Cursor& cursor)
{
m_cursor = cursor.m_impl->GetCursor();
@@ -565,73 +551,57 @@ namespace Nz
RefreshCursor();
}
void WindowImpl::SetEventListener(bool listener)
{
if (m_ownsWindow)
return;
if (listener)
SDL_AddEventWatch(HandleEvent, this);
else
SDL_DelEventWatch(HandleEvent, this);
}
void WindowImpl::SetFocus()
void WindowImpl::RaiseFocus()
{
SDL_RaiseWindow(m_handle);
}
void WindowImpl::SetIcon(const Icon& icon)
void WindowImpl::UpdateIcon(const Icon& icon)
{
SDL_SetWindowIcon(m_handle, icon.m_impl->GetIcon());
}
void WindowImpl::SetMaximumSize(int width, int height)
void WindowImpl::UpdateMaximumSize(int width, int height)
{
SDL_SetWindowMaximumSize(m_handle, width, height);
}
void WindowImpl::SetMinimumSize(int width, int height)
void WindowImpl::UpdateMinimumSize(int width, int height)
{
SDL_SetWindowMinimumSize(m_handle, width, height);
}
void WindowImpl::SetPosition(int x, int y)
void WindowImpl::UpdatePosition(int x, int y)
{
SDL_SetWindowPosition(m_handle, x, y);
}
void WindowImpl::SetSize(unsigned int width, unsigned int height)
void WindowImpl::UpdateSize(unsigned int width, unsigned int height)
{
m_size.Set(width, height);
SDL_SetWindowSize(m_handle, width, height);
}
void WindowImpl::SetStayOnTop(bool stayOnTop)
void WindowImpl::UpdateStayOnTop(bool stayOnTop)
{
NazaraDebug("Stay on top isn't supported by SDL2 backend for now");
SDL_SetWindowAlwaysOnTop(m_handle, (stayOnTop) ? SDL_TRUE : SDL_FALSE);
}
void WindowImpl::SetTitle(const std::string& title)
void WindowImpl::UpdateTitle(const std::string& title)
{
SDL_SetWindowTitle(m_handle, title.c_str());
}
void WindowImpl::SetVisible(bool visible)
void WindowImpl::Show(bool visible)
{
visible ? SDL_ShowWindow(m_handle) : SDL_HideWindow(m_handle);
if (visible)
SDL_ShowWindow(m_handle);
else
SDL_HideWindow(m_handle);
}
void WindowImpl::PrepareWindow(bool fullscreen)
void WindowImpl::ProcessEvents()
{
(void)fullscreen; // ignore param warning
SDL_GetWindowPosition(m_handle, &m_position.x, &m_position.y);
int width, height;
SDL_GetWindowSize(m_handle, &width, &height);
m_size.Set(width, height);
SDL_PumpEvents();
}
bool WindowImpl::Initialize()
@@ -650,27 +620,18 @@ namespace Nz
SDL_Quit();
}
// not implemented for now, wait for mainloop friendly input
//void WindowImpl::WindowThread(SDL_Window* handle, /*DWORD styleEx,*/ const String& title, /*DWORD style,*/ bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition)
//{
// SDL_Window& winHandle = *handle;
/*winHandle = CreateWindowExW(styleEx, className, title.GetWideString().data(), style, dimensions.x, dimensions.y, dimensions.width, dimensions.height, nullptr, nullptr, GetModuleHandle(nullptr), window);
void WindowImpl::SetEventListener(bool listener)
{
if (m_eventListener == listener)
return;
if (winHandle)
window->PrepareWindow(fullscreen);
if (listener)
SDL_AddEventWatch(HandleEvent, this);
else
SDL_DelEventWatch(HandleEvent, this);
mutex->Lock();
condition->Signal();
mutex->Unlock(); // mutex and condition may be destroyed after this line
if (!winHandle)
return;
while (window->m_threadActive)
window->ProcessEvents(true);
DestroyWindow(winHandle);*/
//}
m_eventListener = listener;
}
}
#if defined(NAZARA_PLATFORM_WINDOWS)

View File

@@ -35,19 +35,17 @@ namespace Nz
~WindowImpl() = default;
bool Create(const VideoMode& mode, const std::string& title, WindowStyleFlags style);
bool Create(void* handle);
bool Create(WindowHandle handle);
void Destroy();
void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable);
Vector2i FetchPosition() const;
Vector2ui FetchSize() const;
WindowStyleFlags FetchStyle() const;
std::string FetchTitle() const;
SDL_Window* GetHandle() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
WindowStyleFlags GetStyle() const;
WindowHandle GetSystemHandle() const;
std::string GetTitle() const;
bool HasFocus() const;
@@ -56,52 +54,40 @@ namespace Nz
bool IsMinimized() const;
bool IsVisible() const;
void RaiseFocus();
void RefreshCursor();
void ProcessEvents(bool block);
void UpdateCursor(const Cursor& cursor);
void UpdateIcon(const Icon& icon);
void UpdateMaximumSize(int width, int height);
void UpdateMinimumSize(int width, int height);
void UpdatePosition(int x, int y);
void UpdateSize(unsigned int width, unsigned int height);
void UpdateStayOnTop(bool stayOnTop);
void UpdateTitle(const std::string& title);
void SetCursor(const Cursor& cursor);
void SetEventListener(bool listener);
void SetFocus();
void SetIcon(const Icon& icon);
void SetMaximumSize(int width, int height);
void SetMinimumSize(int width, int height);
void SetPosition(int x, int y);
void SetSize(unsigned int width, unsigned int height);
void SetStayOnTop(bool stayOnTop);
void SetTitle(const std::string& title);
void SetVisible(bool visible);
void Show(bool visible);
WindowImpl& operator=(const WindowImpl&) = delete;
WindowImpl& operator=(WindowImpl&&) = delete; ///TODO?
static void ProcessEvents();
static bool Initialize();
static void Uninitialize();
private:
void SetEventListener(bool listener);
static int SDLCALL HandleEvent(void* userdata, SDL_Event* event);
void PrepareWindow(bool fullscreen);
int m_lastEditEventLength = 0;
UInt32 m_windowId;
SDL_Cursor* m_cursor;
SDL_Window* m_handle;
WindowStyleFlags m_style;
Vector2i m_maxSize;
Vector2i m_minSize;
Vector2i m_mousePos;
Vector2i m_position;
Vector2ui m_size;
Window* m_parent;
bool m_eventListener;
bool m_ignoreNextMouseMove = false;
bool m_keyRepeat;
bool m_mouseInside;
bool m_ignoreNextMouseMove;
bool m_ownsWindow;
bool m_sizemove;
bool m_smoothScrolling;
bool m_threadActive;
short m_scrolling;
int m_lastEditEventLength;
};
}

View File

@@ -12,33 +12,22 @@
namespace Nz
{
namespace NAZARA_ANONYMOUS_NAMESPACE
{
Window* s_fullscreenWindow = nullptr;
}
Window::Window() :
m_impl(nullptr),
m_asyncWindow(false),
m_closeOnQuit(true),
m_eventPolling(false),
m_waitForEvent(false)
{
ConnectSlots();
}
Window::Window(Window&& window) :
m_events(std::move(window.m_events)),
m_pendingEvents(std::move(window.m_pendingEvents)),
Window::Window(Window&& window) noexcept :
m_cursorController(std::move(window.m_cursorController)),
m_cursor(std::move(window.m_cursor)),
m_eventHandler(std::move(window.m_eventHandler)),
m_icon(std::move(window.m_icon)),
m_asyncWindow(window.m_asyncWindow),
m_closed(window.m_asyncWindow),
m_closed(window.m_closed),
m_closeOnQuit(window.m_closeOnQuit),
m_eventPolling(window.m_eventPolling),
m_ownsWindow(window.m_asyncWindow),
m_ownsWindow(window.m_ownsWindow),
m_waitForEvent(window.m_waitForEvent)
{
window.DisconnectSlots();
@@ -52,214 +41,136 @@ namespace Nz
bool Window::Create(VideoMode mode, const std::string& title, WindowStyleFlags style)
{
NAZARA_USE_ANONYMOUS_NAMESPACE
// If the window is already open, we keep its position
bool opened = IsOpen();
Vector2i position;
if (opened)
position = m_impl->GetPosition();
position = m_position;
Destroy();
// Inspired by the code of the SFML by Laurent Gomila (and its team)
if (style & WindowStyle::Fullscreen)
{
if (s_fullscreenWindow)
{
NazaraError("Window " + PointerToString(s_fullscreenWindow) + " already in fullscreen mode");
style &= ~WindowStyle::Fullscreen;
}
else
{
if (!mode.IsFullscreenValid())
{
NazaraWarning("Video mode is not fullscreen valid");
mode = VideoMode::GetFullscreenModes()[0];
}
s_fullscreenWindow = this;
}
}
else if (style & WindowStyle::Closable || style & WindowStyle::Resizable)
if (style & WindowStyle::Closable || style & WindowStyle::Resizable)
style |= WindowStyle::Titlebar;
m_asyncWindow = (style & WindowStyle::Threaded) != 0;
std::unique_ptr<WindowImpl> impl = std::make_unique<WindowImpl>(this);
if (!impl->Create(mode, title, style))
m_impl = std::make_unique<WindowImpl>(this);
if (!m_impl->Create(mode, title, style))
{
NazaraError("Failed to create window implementation");
return false;
}
m_impl = impl.release();
CallOnExit destroyOnFailure([this] () { Destroy(); });
m_closed = false;
m_ownsWindow = true;
if (!OnWindowCreated())
{
NazaraError("Failed to initialize window extension");
return false;
}
m_position = m_impl->FetchPosition();
m_size = m_impl->FetchSize();
// Default parameters
m_impl->EnableKeyRepeat(true);
m_impl->EnableSmoothScrolling(false);
m_impl->SetMaximumSize(-1, -1);
m_impl->SetMinimumSize(-1, -1);
m_impl->SetVisible(true);
m_impl->UpdateMaximumSize(-1, -1);
m_impl->UpdateMinimumSize(-1, -1);
m_impl->Show(true);
if (opened)
m_impl->SetPosition(position.x, position.y);
OnWindowResized();
m_impl->UpdatePosition(position.x, position.y);
destroyOnFailure.Reset();
m_eventHandler.Dispatch({ WindowEventType::Created });
return true;
}
bool Window::Create(void* handle)
bool Window::Create(WindowHandle handle)
{
Destroy();
m_asyncWindow = false;
m_impl = new WindowImpl(this);
m_impl = std::make_unique<WindowImpl>(this);
if (!m_impl->Create(handle))
{
NazaraError("Unable to create window implementation");
delete m_impl;
m_impl = nullptr;
m_impl.reset();
return false;
}
m_position = m_impl->FetchPosition();
m_size = m_impl->FetchSize();
m_closed = false;
m_ownsWindow = false;
if (!OnWindowCreated())
{
NazaraError("Failed to initialize window's derivate");
delete m_impl;
m_impl = nullptr;
return false;
}
m_eventHandler.Dispatch({ WindowEventType::Created });
return true;
}
void Window::Destroy()
{
NAZARA_USE_ANONYMOUS_NAMESPACE
m_cursor.reset();
if (m_impl)
{
OnWindowDestroy();
m_eventHandler.Dispatch({ WindowEventType::Destruction });
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
if (s_fullscreenWindow == this)
s_fullscreenWindow = nullptr;
m_impl.reset();
}
}
void Window::EnableKeyRepeat(bool enable)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return;
}
#endif
m_impl->EnableKeyRepeat(enable);
}
void Window::EnableSmoothScrolling(bool enable)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return;
}
#endif
m_impl->EnableSmoothScrolling(enable);
m_cursor.reset();
}
Vector2i Window::GetPosition() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return Vector2i::Zero();
}
#endif
return m_impl->GetPosition();
NazaraAssert(m_impl, "Window not created");
return m_position;
}
Vector2ui Window::GetSize() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return Vector2ui::Zero();
}
#endif
return m_impl->GetSize();
NazaraAssert(m_impl, "Window not created");
return m_size;
}
WindowStyleFlags Window::GetStyle() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return 0;
}
#endif
return m_impl->GetStyle();
}
WindowHandle Window::GetSystemHandle() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return {};
}
#endif
return m_impl->GetSystemHandle();
NazaraAssert(m_impl, "Window not created");
return m_impl->FetchStyle();
}
std::string Window::GetTitle() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return {};
}
#endif
NazaraAssert(m_impl, "Window not created");
return m_impl->FetchTitle();
}
return m_impl->GetTitle();
void Window::HandleEvent(const WindowEvent& event)
{
m_eventHandler.Dispatch(event);
switch (event.type)
{
case WindowEventType::Moved:
{
m_position = { event.position.x, event.position.y };
break;
}
case WindowEventType::Quit:
{
if (m_closeOnQuit)
Close();
break;
}
case WindowEventType::Resized:
{
m_size = { event.size.width, event.size.height };
break;
}
default:
break;
}
}
bool Window::HasFocus() const
@@ -301,76 +212,13 @@ namespace Nz
return m_impl->IsVisible();
}
bool Window::PollEvent(WindowEvent* event)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return false;
}
#endif
if (!m_asyncWindow)
m_impl->ProcessEvents(false);
if (!m_events.empty())
{
if (event)
*event = m_events.front();
m_events.pop();
return true;
}
return false;
}
void Window::ProcessEvents(bool block)
{
NazaraAssert(m_impl, "Window not created");
NazaraUnused(block);
if (!m_asyncWindow)
m_impl->ProcessEvents(block);
else
{
std::lock_guard<std::mutex> eventLock(m_eventMutex);
for (const WindowEvent& event : m_pendingEvents)
HandleEvent(event);
m_pendingEvents.clear();
}
}
void Window::SetCursor(std::shared_ptr<Cursor> cursor)
{
NazaraAssert(m_impl, "Window not created");
NazaraAssert(cursor && cursor->IsValid(), "Invalid cursor");
m_cursor = std::move(cursor);
m_impl->SetCursor(*m_cursor);
}
void Window::SetEventListener(bool listener)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return;
}
#endif
m_impl->SetEventListener(listener);
if (!listener)
{
// Empty the event queue
while (!m_events.empty())
m_events.pop();
}
m_impl->UpdateCursor(*m_cursor);
}
void Window::SetFocus()
@@ -383,7 +231,7 @@ namespace Nz
}
#endif
m_impl->SetFocus();
m_impl->RaiseFocus();
}
void Window::SetIcon(std::shared_ptr<Icon> icon)
@@ -392,7 +240,7 @@ namespace Nz
NazaraAssert(icon, "Invalid icon");
m_icon = std::move(icon);
m_impl->SetIcon(*m_icon);
m_impl->UpdateIcon(*m_icon);
}
void Window::SetMaximumSize(const Vector2i& maxSize)
@@ -405,7 +253,7 @@ namespace Nz
}
#endif
m_impl->SetMaximumSize(maxSize.x, maxSize.y);
m_impl->UpdateMaximumSize(maxSize.x, maxSize.y);
}
void Window::SetMaximumSize(int width, int height)
@@ -418,7 +266,7 @@ namespace Nz
}
#endif
m_impl->SetMaximumSize(width, height);
m_impl->UpdateMaximumSize(width, height);
}
void Window::SetMinimumSize(const Vector2i& minSize)
@@ -431,7 +279,7 @@ namespace Nz
}
#endif
m_impl->SetMinimumSize(minSize.x, minSize.y);
m_impl->UpdateMinimumSize(minSize.x, minSize.y);
}
void Window::SetMinimumSize(int width, int height)
@@ -444,7 +292,7 @@ namespace Nz
}
#endif
m_impl->SetMinimumSize(width, height);
m_impl->UpdateMinimumSize(width, height);
}
void Window::SetPosition(const Vector2i& position)
@@ -457,7 +305,7 @@ namespace Nz
}
#endif
m_impl->SetPosition(position.x, position.y);
m_impl->UpdatePosition(position.x, position.y);
}
void Window::SetPosition(int x, int y)
@@ -470,7 +318,7 @@ namespace Nz
}
#endif
m_impl->SetPosition(x, y);
m_impl->UpdatePosition(x, y);
}
void Window::SetSize(const Vector2i& size)
@@ -483,7 +331,7 @@ namespace Nz
}
#endif
m_impl->SetSize(size.x, size.y);
m_impl->UpdateSize(size.x, size.y);
}
void Window::SetSize(unsigned int width, unsigned int height)
@@ -496,7 +344,7 @@ namespace Nz
}
#endif
m_impl->SetSize(width, height);
m_impl->UpdateSize(width, height);
}
void Window::SetStayOnTop(bool stayOnTop)
@@ -509,7 +357,7 @@ namespace Nz
}
#endif
m_impl->SetStayOnTop(stayOnTop);
m_impl->UpdateStayOnTop(stayOnTop);
}
void Window::SetTitle(const std::string& title)
@@ -522,7 +370,7 @@ namespace Nz
}
#endif
m_impl->SetTitle(title);
m_impl->UpdateTitle(title);
}
void Window::SetVisible(bool visible)
@@ -535,76 +383,18 @@ namespace Nz
}
#endif
m_impl->SetVisible(visible);
m_impl->Show(visible);
}
bool Window::WaitEvent(WindowEvent* event)
Window& Window::operator=(Window&& window) noexcept
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return false;
}
#endif
if (!m_asyncWindow)
{
while (m_events.empty())
m_impl->ProcessEvents(true);
if (event)
*event = m_events.front();
m_events.pop();
return true;
}
else
{
std::lock_guard<std::mutex> lock(m_eventMutex);
if (m_events.empty())
{
m_waitForEvent = true;
{
m_eventMutex.unlock();
std::unique_lock<std::mutex> eventConditionLock(m_eventConditionMutex);
m_eventCondition.wait(eventConditionLock);
m_eventMutex.lock();
}
m_waitForEvent = false;
}
if (!m_events.empty())
{
if (event)
*event = m_events.front();
m_events.pop();
return true;
}
return false;
}
}
Window& Window::operator=(Window&& window)
{
m_events = std::move(window.m_events);
m_pendingEvents = std::move(window.m_pendingEvents);
m_cursorController = std::move(window.m_cursorController);
m_cursor = std::move(window.m_cursor);
m_eventHandler = std::move(window.m_eventHandler);
m_icon = std::move(window.m_icon);
m_asyncWindow = window.m_asyncWindow;
m_closed = window.m_asyncWindow;
m_closed = window.m_closed;
m_closeOnQuit = window.m_closeOnQuit;
m_eventPolling = window.m_eventPolling;
m_ownsWindow = window.m_asyncWindow;
m_ownsWindow = window.m_ownsWindow;
m_waitForEvent = window.m_waitForEvent;
window.DisconnectSlots();
@@ -613,22 +403,14 @@ namespace Nz
return *this;
}
void* Window::GetHandle()
void Window::ProcessEvents()
{
return (m_impl) ? m_impl->GetHandle() : nullptr;
WindowImpl::ProcessEvents();
}
bool Window::OnWindowCreated()
{
return true;
}
void Window::OnWindowDestroy()
{
}
void Window::OnWindowResized()
WindowHandle Window::GetHandle() const
{
return (m_impl) ? m_impl->GetSystemHandle() : WindowHandle{};
}
void Window::ConnectSlots()
@@ -658,34 +440,6 @@ namespace Nz
m_impl->IgnoreNextMouseEvent(mouseX, mouseY);
}
void Window::HandleEvent(const WindowEvent& event)
{
if (m_eventPolling)
m_events.push(event);
m_eventHandler.Dispatch(event);
switch (event.type)
{
case WindowEventType::MouseEntered:
m_impl->RefreshCursor();
break;
case WindowEventType::Resized:
OnWindowResized();
break;
case WindowEventType::Quit:
if (m_closeOnQuit)
Close();
break;
default:
break;
}
}
bool Window::Initialize()
{
return WindowImpl::Initialize();