From 954298dc1e02cfed288c4764acf46876301c870a Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Jan 2017 22:41:48 +0100 Subject: [PATCH 1/4] Utility/Cursor: Add GetImage() method --- include/Nazara/Utility/Cursor.hpp | 12 ++++++++---- include/Nazara/Utility/Cursor.inl | 31 +++++++++++++++++++++++++++++++ src/Nazara/Utility/Cursor.cpp | 17 ++--------------- 3 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 include/Nazara/Utility/Cursor.inl diff --git a/include/Nazara/Utility/Cursor.hpp b/include/Nazara/Utility/Cursor.hpp index b45fc6a1b..af2a160e1 100644 --- a/include/Nazara/Utility/Cursor.hpp +++ b/include/Nazara/Utility/Cursor.hpp @@ -10,29 +10,33 @@ #include #include #include +#include namespace Nz { class CursorImpl; - class Image; class NAZARA_UTILITY_API Cursor { friend class WindowImpl; public: - Cursor(); - ~Cursor(); + inline Cursor(); + inline ~Cursor(); bool Create(const Image& cursor, int hotSpotX = 0, int hotSpotY = 0); bool Create(const Image& cursor, const Vector2i& hotSpot); void Destroy(); - bool IsValid() const; + inline const Image& GetImage() const; + inline bool IsValid() const; private: + Image m_cursorImage; CursorImpl* m_impl; }; } +#include + #endif // NAZARA_CURSOR_HPP diff --git a/include/Nazara/Utility/Cursor.inl b/include/Nazara/Utility/Cursor.inl new file mode 100644 index 000000000..3073f297e --- /dev/null +++ b/include/Nazara/Utility/Cursor.inl @@ -0,0 +1,31 @@ +// 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 + +namespace Nz +{ + inline Cursor::Cursor() : + m_impl(nullptr) + { + } + + inline Cursor::~Cursor() + { + Destroy(); + } + + inline const Image& Cursor::GetImage() const + { + return m_cursorImage; + } + + inline bool Cursor::IsValid() const + { + return m_impl != nullptr; + } +} + +#include diff --git a/src/Nazara/Utility/Cursor.cpp b/src/Nazara/Utility/Cursor.cpp index deddbc753..9dafd36bc 100644 --- a/src/Nazara/Utility/Cursor.cpp +++ b/src/Nazara/Utility/Cursor.cpp @@ -16,16 +16,6 @@ namespace Nz { - Cursor::Cursor() : - m_impl(nullptr) - { - } - - Cursor::~Cursor() - { - Destroy(); - } - bool Cursor::Create(const Image& cursor, int hotSpotX, int hotSpotY) { Destroy(); @@ -40,6 +30,8 @@ namespace Nz return false; } + m_cursorImage = cursor; + return true; } @@ -58,9 +50,4 @@ namespace Nz m_impl = nullptr; } } - - bool Cursor::IsValid() const - { - return m_impl != nullptr; - } } From f406068c45ceac40080ee0fa880c143ee7cd87a5 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 16 Jan 2017 00:32:59 +0100 Subject: [PATCH 2/4] Utility: Rework cursors -Rename WindowCursor to SystemCursor -Merged Cursor class with SystemCursor enum --- examples/FirstScene/main.cpp | 2 +- examples/Particles/SpacebattleDemo.cpp | 2 +- include/Nazara/Utility/Cursor.hpp | 16 ++++- include/Nazara/Utility/Cursor.inl | 40 +++++++++++- include/Nazara/Utility/Enums.hpp | 50 +++++++-------- include/Nazara/Utility/Window.hpp | 1 - src/Nazara/Utility/Cursor.cpp | 39 +++++++++--- src/Nazara/Utility/Win32/CursorImpl.cpp | 56 +++++++++++++++- src/Nazara/Utility/Win32/CursorImpl.hpp | 14 +++- src/Nazara/Utility/Win32/WindowImpl.cpp | 46 ------------- src/Nazara/Utility/Win32/WindowImpl.hpp | 3 +- src/Nazara/Utility/Window.cpp | 30 +-------- src/Nazara/Utility/X11/CursorImpl.cpp | 82 +++++++++++++++++++++++- src/Nazara/Utility/X11/CursorImpl.hpp | 13 +++- src/Nazara/Utility/X11/WindowImpl.cpp | 85 ++----------------------- src/Nazara/Utility/X11/WindowImpl.hpp | 4 +- 16 files changed, 281 insertions(+), 202 deletions(-) diff --git a/examples/FirstScene/main.cpp b/examples/FirstScene/main.cpp index 863d3edea..b7e7d1198 100644 --- a/examples/FirstScene/main.cpp +++ b/examples/FirstScene/main.cpp @@ -251,7 +251,7 @@ int main() } // On fait disparaître le curseur de la souris - window.SetCursor(Nz::WindowCursor_None); + window.SetCursor(Nz::SystemCursor_None); // On lie la caméra à la fenêtre cameraComp.SetTarget(&window); diff --git a/examples/Particles/SpacebattleDemo.cpp b/examples/Particles/SpacebattleDemo.cpp index 8cc1558c6..7f2cd6b4c 100644 --- a/examples/Particles/SpacebattleDemo.cpp +++ b/examples/Particles/SpacebattleDemo.cpp @@ -644,7 +644,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm) m_turretReloadSound.LoadFromFile("resources/turretReload.wav"); //m_onMouseMoved.Connect(m_shared.target->GetEventHandler().OnMouseMoved, this, &SpacebattleExample::OnMouseMoved); - //m_shared.target->SetCursor(Nz::WindowCursor_None); + //m_shared.target->SetCursor(Nz::SystemCursor_None); ////////////////////////////////////////////////////////////////////////// diff --git a/include/Nazara/Utility/Cursor.hpp b/include/Nazara/Utility/Cursor.hpp index af2a160e1..ae8dd08b5 100644 --- a/include/Nazara/Utility/Cursor.hpp +++ b/include/Nazara/Utility/Cursor.hpp @@ -22,18 +22,32 @@ namespace Nz public: inline Cursor(); + inline Cursor(SystemCursor systemCursor); //< implicit conversion intended + Cursor(const Cursor&) = delete; + inline Cursor(Cursor&& cursor) noexcept; inline ~Cursor(); - bool Create(const Image& cursor, int hotSpotX = 0, int hotSpotY = 0); bool Create(const Image& cursor, const Vector2i& hotSpot); + bool Create(SystemCursor cursor); + void Destroy(); inline const Image& GetImage() const; + inline SystemCursor GetSystemCursor() const; + inline bool IsValid() const; + Cursor& operator=(const Cursor&) = delete; + inline Cursor& operator=(Cursor&& cursor); + private: + static bool Initialize(); + static void Uninitialize(); + Image m_cursorImage; + SystemCursor m_systemCursor; CursorImpl* m_impl; + bool m_usesSystemCursor; }; } diff --git a/include/Nazara/Utility/Cursor.inl b/include/Nazara/Utility/Cursor.inl index 3073f297e..dc0ce68db 100644 --- a/include/Nazara/Utility/Cursor.inl +++ b/include/Nazara/Utility/Cursor.inl @@ -3,15 +3,30 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz { inline Cursor::Cursor() : - m_impl(nullptr) + m_impl(nullptr), + m_usesSystemCursor(false) { } + inline Cursor::Cursor(SystemCursor systemCursor) : + Cursor() + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + Create(systemCursor); + } + + inline Cursor::Cursor(Cursor&& cursor) noexcept : + Cursor() + { + operator=(std::move(cursor)); + } + inline Cursor::~Cursor() { Destroy(); @@ -19,13 +34,36 @@ namespace Nz inline const Image& Cursor::GetImage() const { + NazaraAssert(IsValid(), "Invalid cursor"); + NazaraAssert(!m_usesSystemCursor, "System cursors have no image"); + return m_cursorImage; } + inline SystemCursor Cursor::GetSystemCursor() const + { + NazaraAssert(IsValid(), "Invalid cursor"); + NazaraAssert(m_usesSystemCursor, "Custom cursor uses an image"); + + return m_systemCursor; + } + inline bool Cursor::IsValid() const { return m_impl != nullptr; } + + inline Cursor& Cursor::operator=(Cursor&& cursor) + { + m_cursorImage = std::move(cursor.m_cursorImage); + m_systemCursor = cursor.m_systemCursor; + m_impl = cursor.m_impl; + m_usesSystemCursor = cursor.m_usesSystemCursor; + + cursor.m_impl = nullptr; + + return *this; + } } #include diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index fd9001d44..23c71d528 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -307,6 +307,31 @@ namespace Nz SamplerWrap_Max = SamplerWrap_Repeat }; + enum SystemCursor + { + SystemCursor_None, + SystemCursor_Default, + + SystemCursor_Crosshair, + SystemCursor_Hand, + SystemCursor_Help, + SystemCursor_Move, + SystemCursor_Pointer, + SystemCursor_Progress, + SystemCursor_ResizeE, + SystemCursor_ResizeN, + SystemCursor_ResizeNE, + SystemCursor_ResizeNW, + SystemCursor_ResizeS, + SystemCursor_ResizeSE, + SystemCursor_ResizeSW, + SystemCursor_ResizeW, + SystemCursor_Text, + SystemCursor_Wait, + + SystemCursor_Max = SystemCursor_Wait + }; + enum StencilOperation { StencilOperation_Decrement, @@ -393,31 +418,6 @@ namespace Nz VertexLayout_Max = VertexLayout_Matrix4 }; - enum WindowCursor - { - WindowCursor_None, - WindowCursor_Default, - - WindowCursor_Crosshair, - WindowCursor_Hand, - WindowCursor_Help, - WindowCursor_Move, - WindowCursor_Pointer, - WindowCursor_Progress, - WindowCursor_ResizeE, - WindowCursor_ResizeN, - WindowCursor_ResizeNE, - WindowCursor_ResizeNW, - WindowCursor_ResizeS, - WindowCursor_ResizeSE, - WindowCursor_ResizeSW, - WindowCursor_ResizeW, - WindowCursor_Text, - WindowCursor_Wait, - - WindowCursor_Max = WindowCursor_Wait - }; - enum WindowEventType { WindowEventType_GainedFocus, diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index 5ecabd8dd..3dbf9897b 100644 --- a/include/Nazara/Utility/Window.hpp +++ b/include/Nazara/Utility/Window.hpp @@ -79,7 +79,6 @@ namespace Nz void ProcessEvents(bool block = false); - void SetCursor(WindowCursor cursor); void SetCursor(const Cursor& cursor); void SetEventListener(bool listener); void SetFocus(); diff --git a/src/Nazara/Utility/Cursor.cpp b/src/Nazara/Utility/Cursor.cpp index 9dafd36bc..9b9af0fb9 100644 --- a/src/Nazara/Utility/Cursor.cpp +++ b/src/Nazara/Utility/Cursor.cpp @@ -16,28 +16,39 @@ namespace Nz { - bool Cursor::Create(const Image& cursor, int hotSpotX, int hotSpotY) + bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot) { Destroy(); - m_impl = new CursorImpl; - if (!m_impl->Create(cursor, hotSpotX, hotSpotY)) + std::unique_ptr impl(new CursorImpl); + if (!impl->Create(cursor, hotSpot.x, hotSpot.y)) { NazaraError("Failed to create cursor implementation"); - delete m_impl; - m_impl = nullptr; - return false; } m_cursorImage = cursor; + m_impl = impl.release(); return true; } - bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot) + inline bool Cursor::Create(SystemCursor cursor) { - return Create(cursor, hotSpot.x, hotSpot.y); + Destroy(); + + std::unique_ptr impl(new CursorImpl); + if (!impl->Create(cursor)) + { + NazaraError("Failed to create cursor implementation"); + return false; + } + + m_impl = impl.release(); + m_systemCursor = cursor; + m_usesSystemCursor = true; + + return true; } void Cursor::Destroy() @@ -49,5 +60,17 @@ namespace Nz delete m_impl; m_impl = nullptr; } + + m_usesSystemCursor = false; + } + + bool Cursor::Initialize() + { + return CursorImpl::Initialize(); + } + + void Cursor::Uninitialize() + { + CursorImpl::Uninitialize(); } } diff --git a/src/Nazara/Utility/Win32/CursorImpl.cpp b/src/Nazara/Utility/Win32/CursorImpl.cpp index eec8785bb..c4c43a6f1 100644 --- a/src/Nazara/Utility/Win32/CursorImpl.cpp +++ b/src/Nazara/Utility/Win32/CursorImpl.cpp @@ -30,27 +30,77 @@ namespace Nz iconInfo.hbmMask = monoBitmap; iconInfo.hbmColor = bitmap; - m_cursor = CreateIconIndirect(&iconInfo); + m_icon = CreateIconIndirect(&iconInfo); DeleteObject(bitmap); DeleteObject(monoBitmap); - if (!m_cursor) + if (!m_icon) { NazaraError("Failed to create cursor: " + Error::GetLastSystemError()); return false; } + m_cursor = m_icon; + + return true; + } + + bool CursorImpl::Create(SystemCursor cursor) + { + if (cursor != SystemCursor_Move) + m_cursor = static_cast(LoadImage(nullptr, s_systemCursorIds[cursor], IMAGE_CURSOR, 0, 0, LR_SHARED)); + else + m_cursor = nullptr; + + // No need to free the cursor if shared + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx + m_icon = nullptr; + return true; } void CursorImpl::Destroy() { - DestroyIcon(m_cursor); + if (m_icon) + DestroyIcon(m_icon); } HCURSOR CursorImpl::GetCursor() { return m_cursor; } + + bool CursorImpl::Initialize() + { + return true; + } + + void CursorImpl::Uninitialize() + { + } + + std::array CursorImpl::s_systemCursorIds = + { + IDC_CROSS, // SystemCursor_Crosshair + IDC_ARROW, // SystemCursor_Default + IDC_HAND, // SystemCursor_Hand + IDC_HELP, // SystemCursor_Help + IDC_SIZEALL, // SystemCursor_Move + nullptr, // SystemCursor_None + IDC_HAND, // SystemCursor_Pointer + IDC_APPSTARTING, // SystemCursor_Progress + IDC_SIZEWE, // SystemCursor_ResizeE + IDC_SIZENS, // SystemCursor_ResizeN + IDC_SIZENESW, // SystemCursor_ResizeNE + IDC_SIZENWSE, // SystemCursor_ResizeNW + IDC_SIZENS, // SystemCursor_ResizeS + IDC_SIZENWSE, // SystemCursor_ResizeSE + IDC_SIZENESW, // SystemCursor_ResizeSW + IDC_SIZEWE, // SystemCursor_ResizeW + IDC_IBEAM, // SystemCursor_Text + IDC_WAIT // SystemCursor_Wait + }; + + static_assert(SystemCursor_Max + 1 == 18, "System cursor array is incomplete"); } diff --git a/src/Nazara/Utility/Win32/CursorImpl.hpp b/src/Nazara/Utility/Win32/CursorImpl.hpp index 78662228e..c6899ed46 100644 --- a/src/Nazara/Utility/Win32/CursorImpl.hpp +++ b/src/Nazara/Utility/Win32/CursorImpl.hpp @@ -8,6 +8,8 @@ #define NAZARA_CURSORIMPL_HPP #include +#include +#include #include namespace Nz @@ -16,14 +18,24 @@ namespace Nz class CursorImpl { + friend class Cursor; + public: bool Create(const Image& image, int hotSpotX, int hotSpotY); + bool Create(SystemCursor cursor); + void Destroy(); HCURSOR GetCursor(); private: - HICON m_cursor = nullptr; + static bool Initialize(); + static void Uninitialize(); + + HCURSOR m_cursor = nullptr; + HICON m_icon = nullptr; + + static std::array s_systemCursorIds; }; } diff --git a/src/Nazara/Utility/Win32/WindowImpl.cpp b/src/Nazara/Utility/Win32/WindowImpl.cpp index e32caf95f..74f6fb62b 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.cpp +++ b/src/Nazara/Utility/Win32/WindowImpl.cpp @@ -4,8 +4,6 @@ // Un grand merci à Laurent Gomila pour la SFML qui m'aura bien aidé à réaliser cette implémentation -#define OEMRESOURCE - #include #include #include @@ -38,30 +36,6 @@ namespace Nz { namespace { - LPTSTR windowsCursors[] = - { - IDC_CROSS, // WindowCursor_Crosshair - IDC_ARROW, // WindowCursor_Default - IDC_HAND, // WindowCursor_Hand - IDC_HAND, // WindowCursor_Pointer - IDC_HELP, // WindowCursor_Help - IDC_SIZEALL, // WindowCursor_Move - nullptr, // WindowCursor_None - IDC_APPSTARTING, // WindowCursor_Progress - IDC_SIZENS, // WindowCursor_ResizeN - IDC_SIZENS, // WindowCursor_ResizeS - IDC_SIZENWSE, // WindowCursor_ResizeNW - IDC_SIZENWSE, // WindowCursor_ResizeSE - IDC_SIZENESW, // WindowCursor_ResizeNE - IDC_SIZENESW, // WindowCursor_ResizeSW - IDC_SIZEWE, // WindowCursor_ResizeE - IDC_SIZEWE, // WindowCursor_ResizeW - IDC_IBEAM, // WindowCursor_Text - IDC_WAIT // WindowCursor_Wait - }; - - static_assert(sizeof(windowsCursors)/sizeof(LPTSTR) == WindowCursor_Max+1, "Cursor type array is incomplete"); - const wchar_t* className = L"Nazara Window"; WindowImpl* fullscreenWindow = nullptr; } @@ -321,26 +295,6 @@ namespace Nz } } - void WindowImpl::SetCursor(WindowCursor cursor) - { - #ifdef NAZARA_DEBUG - if (cursor > WindowCursor_Max) - { - NazaraError("Window cursor out of enum"); - return; - } - #endif - - if (cursor != WindowCursor_None) - m_cursor = static_cast(LoadImage(nullptr, windowsCursors[cursor], IMAGE_CURSOR, 0, 0, LR_SHARED)); - else - m_cursor = nullptr; - - // Pas besoin de libérer le curseur par la suite s'il est partagé - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx - ::SetCursor(m_cursor); - } - void WindowImpl::SetCursor(const Cursor& cursor) { m_cursor = cursor.m_impl->GetCursor(); diff --git a/src/Nazara/Utility/Win32/WindowImpl.hpp b/src/Nazara/Utility/Win32/WindowImpl.hpp index ae08e42ad..36ba5d93b 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.hpp +++ b/src/Nazara/Utility/Win32/WindowImpl.hpp @@ -27,7 +27,7 @@ namespace Nz class Mutex; class Window; - #undef IsMinimized // Conflit avec la méthode du même nom + #undef IsMinimized // Conflits with windows.h redefinition class WindowImpl { @@ -62,7 +62,6 @@ namespace Nz void ProcessEvents(bool block); - void SetCursor(WindowCursor cursor); void SetCursor(const Cursor& cursor); void SetEventListener(bool listener); void SetFocus(); diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index 73c91168a..61ca49c80 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -90,7 +90,7 @@ namespace Nz // Paramètres par défaut m_impl->EnableKeyRepeat(true); m_impl->EnableSmoothScrolling(false); - m_impl->SetCursor(WindowCursor_Default); + m_impl->SetCursor(SystemCursor_Default); m_impl->SetMaximumSize(-1, -1); m_impl->SetMinimumSize(-1, -1); m_impl->SetVisible(true); @@ -350,34 +350,10 @@ namespace Nz } } - 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 + NazaraAssert(m_impl, "Window not created"); + NazaraAssert(cursor.IsValid(), "Invalid cursor"); m_impl->SetCursor(cursor); } diff --git a/src/Nazara/Utility/X11/CursorImpl.cpp b/src/Nazara/Utility/X11/CursorImpl.cpp index d09f51a1f..082825c50 100644 --- a/src/Nazara/Utility/X11/CursorImpl.cpp +++ b/src/Nazara/Utility/X11/CursorImpl.cpp @@ -159,16 +159,96 @@ namespace Nz return true; } + bool CursorImpl::Create(SystemCursor cursor) + { + ScopedXCBConnection connection; + + if (xcb_cursor_context_new(connection, m_screen, &m_cursorContext) >= 0) + m_cursor = xcb_cursor_load_cursor(ctx, s_systemCursorIds[cursor]); + + return true; + } + void CursorImpl::Destroy() { ScopedXCBConnection connection; xcb_free_cursor(connection, m_cursor); - m_cursor = 0; + if (m_cursorContext) + xcb_cursor_context_free(m_cursorContext); } xcb_cursor_t CursorImpl::GetCursor() { return m_cursor; } + + bool CursorImpl::Initialize() + { + ScopedXCBConnection connection; + XCBPixmap cursorPixmap(connection); + + xcb_window_t window = X11::XCBDefaultRootWindow(connection); + + if (!cursorPixmap.Create(1, window, 1, 1)) + { + NazaraError("Failed to create pixmap for hidden cursor"); + return false; + } + + hiddenCursor = xcb_generate_id(connection); + + // Create the cursor, using the pixmap as both the shape and the mask of the cursor + if (!X11::CheckCookie( + connection, xcb_create_cursor(connection, + hiddenCursor, + cursorPixmap, + cursorPixmap, + 0, 0, 0, // Foreground RGB color + 0, 0, 0, // Background RGB color + 0, // X + 0 // Y + ))) + { + NazaraError("Failed to create hidden cursor"); + return false; + } + + return true; + } + + void CursorImpl::Uninitialize() + { + if (s_hiddenCursor) + { + ScopedXCBConnection connection; + xcb_free_cursor(connection, s_hiddenCursor); + s_hiddenCursor = 0; + } + } + + std::array CursorImpl::s_systemCursorIds = + { + // http://gnome-look.org/content/preview.php?preview=1&id=128170&file1=128170-1.png&file2=&file3=&name=Dummy+X11+cursors&PHPSESSID=6 + "crosshair", // SystemCursor_Crosshair + "left_ptr", // SystemCursor_Default + "hand", // SystemCursor_Hand + "help", // SystemCursor_Help + "fleur", // SystemCursor_Move + nullptr, // SystemCursor_None + "hand", // SystemCursor_Pointer + "watch", // SystemCursor_Progress + "right_side", // SystemCursor_ResizeE + "top_side", // SystemCursor_ResizeN + "top_right_corner", // SystemCursor_ResizeNE + "top_left_corner", // SystemCursor_ResizeNW + "bottom_side", // SystemCursor_ResizeS + "bottom_right_corner", // SystemCursor_ResizeSE + "bottom_left_corner", // SystemCursor_ResizeSW + "left_side", // SystemCursor_ResizeW + "xterm", // SystemCursor_Text + "watch" // SystemCursor_Wait + }; + + static_assert(SystemCursor_Max + 1 == 18, "System cursor array is incomplete"); } diff --git a/src/Nazara/Utility/X11/CursorImpl.hpp b/src/Nazara/Utility/X11/CursorImpl.hpp index 41d91bcb1..b16cd4aa2 100644 --- a/src/Nazara/Utility/X11/CursorImpl.hpp +++ b/src/Nazara/Utility/X11/CursorImpl.hpp @@ -8,6 +8,7 @@ #define NAZARA_CURSORIMPL_HPP #include +#include #include namespace Nz @@ -16,14 +17,24 @@ namespace Nz class CursorImpl { + friend class Cursor; + public: bool Create(const Image& image, int hotSpotX, int hotSpotY); + bool Create(SystemCursor cursor); + void Destroy(); xcb_cursor_t GetCursor(); private: - xcb_cursor_t m_cursor; + static bool Initialize(); + static void Uninitialize(); + + xcb_cursor_t m_cursor = 0; + xcb_cursor_context_t* m_cursorContext = nullptr; + + static std::array s_systemCursorIds; }; } diff --git a/src/Nazara/Utility/X11/WindowImpl.cpp b/src/Nazara/Utility/X11/WindowImpl.cpp index 700b8c6ee..31f546b38 100644 --- a/src/Nazara/Utility/X11/WindowImpl.cpp +++ b/src/Nazara/Utility/X11/WindowImpl.cpp @@ -50,45 +50,7 @@ namespace Nz XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW; - xcb_cursor_t hiddenCursor = 0; - xcb_connection_t* connection = nullptr; - - void CreateHiddenCursor() - { - XCBPixmap cursorPixmap(connection); - - xcb_window_t window = X11::XCBDefaultRootWindow(connection); - - if (!cursorPixmap.Create( - 1, - window, - 1, - 1 - )) - { - NazaraError("Failed to create pixmap for hidden cursor"); - return; - } - - hiddenCursor = xcb_generate_id(connection); - - // Create the cursor, using the pixmap as both the shape and the mask of the cursor - if (!X11::CheckCookie( - connection, - xcb_create_cursor( - connection, - hiddenCursor, - cursorPixmap, - cursorPixmap, - 0, 0, 0, // Foreground RGB color - 0, 0, 0, // Background RGB color - 0, // X - 0 // Y - )) - ) - NazaraError("Failed to create hidden cursor"); - } } WindowImpl::WindowImpl(Window* parent) : @@ -452,34 +414,13 @@ namespace Nz } } - void WindowImpl::SetCursor(Nz::WindowCursor windowCursor) - { - if (windowCursor == Nz::WindowCursor_None) - SetCursor(hiddenCursor); - else - { - const char* name = ConvertWindowCursorToXName(windowCursor); - - xcb_cursor_context_t* ctx; - if (xcb_cursor_context_new(connection, m_screen, &ctx) >= 0) - { - xcb_cursor_t cursor = xcb_cursor_load_cursor(ctx, name); - SetCursor(cursor); - xcb_free_cursor(connection, cursor); - xcb_cursor_context_free(ctx); - } - } - } - void WindowImpl::SetCursor(const Cursor& cursor) { - if (!cursor.IsValid()) - { - NazaraError("Cursor is not valid"); - return; - } + xcb_cursor_t cursorImpl = cursor.m_impl->GetCursor(); + if (!X11::CheckCookie(connection, xcb_change_window_attributes(connection, m_window, XCB_CW_CURSOR, &cursor))) + NazaraError("Failed to change mouse cursor"); - SetCursor(cursor.m_impl->GetCursor()); + xcb_flush(connection); } void WindowImpl::SetEventListener(bool listener) @@ -998,7 +939,7 @@ namespace Nz } } - const char* WindowImpl::ConvertWindowCursorToXName(Nz::WindowCursor cursor) + const char* WindowImpl::ConvertWindowCursorToXName(SystemCursor cursor) { // http://gnome-look.org/content/preview.php?preview=1&id=128170&file1=128170-1.png&file2=&file3=&name=Dummy+X11+cursors&PHPSESSID=6 switch (cursor) @@ -1444,22 +1385,6 @@ namespace Nz } } - void WindowImpl::SetCursor(xcb_cursor_t cursor) - { - if (!X11::CheckCookie( - connection, - xcb_change_window_attributes( - connection, - m_window, - XCB_CW_CURSOR, - &cursor - )) - ) - NazaraError("Failed to change mouse cursor"); - - xcb_flush(connection); - } - void WindowImpl::SetMotifHints() { ScopedXCB error(nullptr); diff --git a/src/Nazara/Utility/X11/WindowImpl.hpp b/src/Nazara/Utility/X11/WindowImpl.hpp index 414140179..d56579561 100644 --- a/src/Nazara/Utility/X11/WindowImpl.hpp +++ b/src/Nazara/Utility/X11/WindowImpl.hpp @@ -60,7 +60,6 @@ namespace Nz void ProcessEvents(bool block); - void SetCursor(WindowCursor cursor); void SetCursor(const Cursor& cursor); void SetEventListener(bool listener); void SetFocus(); @@ -84,7 +83,7 @@ namespace Nz void CleanUp(); xcb_keysym_t ConvertKeyCodeToKeySym(xcb_keycode_t keycode, uint16_t state); Keyboard::Key ConvertVirtualKey(xcb_keysym_t symbol); - const char* ConvertWindowCursorToXName(WindowCursor cursor); + const char* ConvertWindowCursorToXName(SystemCursor cursor); void CommonInitialize(); char32_t GetRepresentation(xcb_keysym_t keysym) const; @@ -93,7 +92,6 @@ namespace Nz void ResetVideoMode(); - void SetCursor(xcb_cursor_t cursor); void SetMotifHints(); void SetVideoMode(const VideoMode& mode); void SwitchToFullscreen(); From 5b36ac1953b445745e0f4f730de218b01cea5602 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 16 Jan 2017 00:41:31 +0100 Subject: [PATCH 3/4] Utility: Fix Cursor missing initialization --- include/Nazara/Utility/Cursor.hpp | 1 + src/Nazara/Utility/Utility.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/include/Nazara/Utility/Cursor.hpp b/include/Nazara/Utility/Cursor.hpp index ae8dd08b5..7fe0b2831 100644 --- a/include/Nazara/Utility/Cursor.hpp +++ b/include/Nazara/Utility/Cursor.hpp @@ -18,6 +18,7 @@ namespace Nz class NAZARA_UTILITY_API Cursor { + friend class Utility; friend class WindowImpl; public: diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index 87b154157..3234869ad 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,13 @@ namespace Nz NazaraError("Failed to initialize window's system"); return false; } + + // Must be initialized after Window + if (!Cursor::Initialize()) + { + NazaraError("Failed to initialize cursors"); + return false; + } } // On enregistre les loaders pour les extensions @@ -180,7 +188,9 @@ namespace Nz Loaders::UnregisterSTBLoader(); Loaders::UnregisterSTBSaver(); + Cursor::Uninitialize(); //< Must be done before Window Window::Uninitialize(); + VertexDeclaration::Uninitialize(); Skeleton::Uninitialize(); PixelFormat::Uninitialize(); From 679f599c791be4d658d0e44174055b0424eb832c Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 16 Jan 2017 21:25:23 +0100 Subject: [PATCH 4/4] Sdk/Console: Fix crash --- SDK/src/NDK/Console.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/SDK/src/NDK/Console.cpp b/SDK/src/NDK/Console.cpp index 82d3d40af..1e49ec25f 100644 --- a/SDK/src/NDK/Console.cpp +++ b/SDK/src/NDK/Console.cpp @@ -192,9 +192,12 @@ namespace Ndk m_historyPosition = 1; } - Nz::String text = m_commandHistory[m_commandHistory.size() - m_historyPosition]; - m_inputDrawer.SetText(s_inputPrefix + text); - m_inputTextSprite->Update(m_inputDrawer); + if (!m_commandHistory.empty()) + { + Nz::String text = m_commandHistory[m_commandHistory.size() - m_historyPosition]; + m_inputDrawer.SetText(s_inputPrefix + text); + m_inputTextSprite->Update(m_inputDrawer); + } break; }