// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include #include #include #include #if defined(NAZARA_PLATFORM_WINDOWS) #include #elif defined(NAZARA_PLATFORM_X11) #include #else #error Lack of implementation: Window #endif #include namespace Nz { namespace { Window* fullscreenWindow = nullptr; } bool Window::Create(VideoMode mode, const String& title, UInt32 style) { // Si la fenêtre est déjà ouverte, nous conservons sa position bool opened = IsOpen(); Vector2i position; if (opened) position = m_impl->GetPosition(); Destroy(); // Inspiré du code de la SFML par Laurent Gomila if (style & WindowStyle_Fullscreen) { if (fullscreenWindow) { NazaraError("Window " + String::Pointer(fullscreenWindow) + " already in fullscreen mode"); style &= ~WindowStyle_Fullscreen; } else { if (!mode.IsFullscreenValid()) { NazaraWarning("Video mode is not fullscreen valid"); mode = VideoMode::GetFullscreenModes()[0]; } fullscreenWindow = this; } } else if (style & WindowStyle_Closable || style & WindowStyle_Resizable) style |= WindowStyle_Titlebar; std::unique_ptr impl = std::make_unique(this); if (!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; } // Paramètres par défaut m_impl->EnableKeyRepeat(true); m_impl->EnableSmoothScrolling(false); m_impl->SetCursor(WindowCursor_Default); m_impl->SetMaximumSize(-1, -1); m_impl->SetMinimumSize(-1, -1); m_impl->SetVisible(true); if (opened) m_impl->SetPosition(position.x, position.y); OnWindowResized(); destroyOnFailure.Reset(); return true; } bool Window::Create(WindowHandle handle) { Destroy(); m_impl = new WindowImpl(this); if (!m_impl->Create(handle)) { NazaraError("Unable to create window implementation"); delete m_impl; m_impl = nullptr; return false; } m_closed = false; m_ownsWindow = false; if (!OnWindowCreated()) { NazaraError("Failed to initialize window's derivate"); delete m_impl; m_impl = nullptr; return false; } return true; } void Window::Destroy() { if (m_impl) { OnWindowDestroy(); m_impl->Destroy(); delete m_impl; m_impl = nullptr; if (fullscreenWindow == this) fullscreenWindow = nullptr; } } void Window::EnableKeyRepeat(bool enable) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->EnableKeyRepeat(enable); } void Window::EnableSmoothScrolling(bool enable) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->EnableSmoothScrolling(enable); } WindowHandle Window::GetHandle() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return static_cast(0); } #endif return m_impl->GetHandle(); } unsigned int Window::GetHeight() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return 0; } #endif return m_impl->GetHeight(); } Vector2i Window::GetPosition() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return Vector2i::Zero(); } #endif return m_impl->GetPosition(); } Vector2ui Window::GetSize() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return Vector2ui::Zero(); } #endif return m_impl->GetSize(); } UInt32 Window::GetStyle() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return 0; } #endif return m_impl->GetStyle(); } String Window::GetTitle() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return String(); } #endif return m_impl->GetTitle(); } unsigned int Window::GetWidth() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return 0; } #endif return m_impl->GetWidth(); } bool Window::HasFocus() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return false; } #endif return m_impl->HasFocus(); } bool Window::IsMinimized() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return false; } #endif return m_impl->IsMinimized(); } bool Window::IsVisible() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return false; } #endif return m_impl->IsVisible(); } bool Window::PollEvent(WindowEvent* event) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return false; } #endif #if NAZARA_UTILITY_THREADED_WINDOW LockGuard lock(m_eventMutex); #else m_impl->ProcessEvents(false); #endif 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"); #if !NAZARA_UTILITY_THREADED_WINDOW m_impl->ProcessEvents(block); #endif } void Window::SetCursor(WindowCursor cursor) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetCursor(cursor); } void Window::SetCursor(const Cursor& cursor) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } if (!cursor.IsValid()) { NazaraError("Cursor is not valid"); return; } #endif m_impl->SetCursor(cursor); } void Window::SetEventListener(bool listener) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif #if NAZARA_UTILITY_THREADED_WINDOW m_impl->SetEventListener(listener); if (!listener) { // On vide la pile des évènements LockGuard lock(m_eventMutex); while (!m_events.empty()) m_events.pop(); } #else if (m_ownsWindow) { // Inutile de transmettre l'ordre dans ce cas-là if (!listener) NazaraError("A non-threaded window needs to listen to events"); } else m_impl->SetEventListener(listener); #endif } void Window::SetFocus() { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetFocus(); } void Window::SetIcon(const Icon& icon) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } if (!icon.IsValid()) { NazaraError("Icon is not valid"); return; } #endif m_impl->SetIcon(icon); } void Window::SetMaximumSize(const Vector2i& maxSize) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetMaximumSize(maxSize.x, maxSize.y); } void Window::SetMaximumSize(int width, int height) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetMaximumSize(width, height); } void Window::SetMinimumSize(const Vector2i& minSize) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetMinimumSize(minSize.x, minSize.y); } void Window::SetMinimumSize(int width, int height) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetMinimumSize(width, height); } void Window::SetPosition(const Vector2i& position) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetPosition(position.x, position.y); } void Window::SetPosition(int x, int y) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetPosition(x, y); } void Window::SetSize(const Vector2i& size) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetSize(size.x, size.y); } void Window::SetSize(unsigned int width, unsigned int height) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetSize(width, height); } void Window::SetStayOnTop(bool stayOnTop) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetStayOnTop(stayOnTop); } void Window::SetTitle(const String& title) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetTitle(title); } void Window::SetVisible(bool visible) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->SetVisible(visible); } bool Window::WaitEvent(WindowEvent* event) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return false; } #endif #if NAZARA_UTILITY_THREADED_WINDOW LockGuard lock(m_eventMutex); if (m_events.empty()) { m_waitForEvent = true; m_eventConditionMutex.Lock(); m_eventMutex.Unlock(); m_eventCondition.Wait(&m_eventConditionMutex); m_eventMutex.Lock(); m_eventConditionMutex.Unlock(); m_waitForEvent = false; } if (!m_events.empty()) { if (event) *event = m_events.front(); m_events.pop(); return true; } return false; #else while (m_events.empty()) m_impl->ProcessEvents(true); if (event) *event = m_events.front(); m_events.pop(); return true; #endif } bool Window::OnWindowCreated() { return true; } void Window::OnWindowDestroy() { } void Window::OnWindowResized() { } void Window::IgnoreNextMouseEvent(int mouseX, int mouseY) const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Window not created"); return; } #endif m_impl->IgnoreNextMouseEvent(mouseX, mouseY); } bool Window::Initialize() { return WindowImpl::Initialize(); } void Window::Uninitialize() { WindowImpl::Uninitialize(); } }