Replace platform backends by SDL

This commit is contained in:
Lynix
2020-05-27 17:47:52 +02:00
parent c071f52d8f
commit b0c72a6101
132 changed files with 38933 additions and 6374 deletions

View File

@@ -3,17 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Cursor.hpp>
#if defined(NAZARA_PLATFORM_SDL2)
#include <Nazara/Platform/SDL2/CursorImpl.hpp>
#elif defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Platform/Win32/CursorImpl.hpp>
#elif defined(NAZARA_PLATFORM_X11)
#include <Nazara/Platform/X11/CursorImpl.hpp>
#else
#error Lack of implementation: Cursor
#endif
#include <Nazara/Platform/SDL2/CursorImpl.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz

View File

@@ -3,17 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Icon.hpp>
#if defined(NAZARA_PLATFORM_SDL2)
#include <Nazara/Platform/SDL2/IconImpl.hpp>
#elif defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Platform/Win32/IconImpl.hpp>
#elif defined(NAZARA_PLATFORM_X11)
#include <Nazara/Platform/X11/IconImpl.hpp>
#else
#error Lack of implementation: Icon
#endif
#include <Nazara/Platform/SDL2/IconImpl.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz

View File

@@ -3,17 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Keyboard.hpp>
#if defined(NAZARA_PLATFORM_SDL2)
#include <Nazara/Platform/SDL2/InputImpl.hpp>
#elif defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Platform/Win32/InputImpl.hpp>
#elif defined(NAZARA_PLATFORM_X11)
#include <Nazara/Platform/X11/InputImpl.hpp>
#else
#error Lack of implementation: Keyboard
#endif
#include <Nazara/Platform/SDL2/InputImpl.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz

View File

@@ -4,17 +4,7 @@
#include <Nazara/Platform/Mouse.hpp>
#include <Nazara/Platform/Window.hpp>
#if defined(NAZARA_PLATFORM_SDL2)
#include <Nazara/Platform/SDL2/InputImpl.hpp>
#elif defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Platform/Win32/InputImpl.hpp>
#elif defined(NAZARA_PLATFORM_X11)
#include <Nazara/Platform/X11/InputImpl.hpp>
#else
#error Lack of implementation: Mouse
#endif
#include <Nazara/Platform/SDL2/InputImpl.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz

View File

@@ -5,17 +5,7 @@
#include <Nazara/Platform/VideoMode.hpp>
#include <algorithm>
#include <functional>
#if defined(NAZARA_PLATFORM_SDL2)
#include <Nazara/Platform/SDL2/VideoModeImpl.hpp>
#elif defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Platform/Win32/VideoModeImpl.hpp>
#elif defined(NAZARA_PLATFORM_X11)
#include <Nazara/Platform/X11/VideoModeImpl.hpp>
#else
#error Lack of implementation: Window
#endif
#include <Nazara/Platform/SDL2/VideoModeImpl.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz

View File

@@ -1,106 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Win32/CursorImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
bool CursorImpl::Create(const Image& cursor, int hotSpotX, int hotSpotY)
{
Image windowsCursor(cursor);
if (!windowsCursor.Convert(PixelFormatType_BGRA8))
{
NazaraError("Failed to convert cursor to BGRA8");
return false;
}
HBITMAP bitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 32, windowsCursor.GetConstPixels());
HBITMAP monoBitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 1, nullptr);
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx
ICONINFO iconInfo;
iconInfo.fIcon = FALSE;
iconInfo.xHotspot = hotSpotX;
iconInfo.yHotspot = hotSpotY;
iconInfo.hbmMask = monoBitmap;
iconInfo.hbmColor = bitmap;
m_icon = CreateIconIndirect(&iconInfo);
DeleteObject(bitmap);
DeleteObject(monoBitmap);
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_None)
m_cursor = static_cast<HCURSOR>(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()
{
if (m_icon)
DestroyIcon(m_icon);
}
HCURSOR CursorImpl::GetCursor()
{
return m_cursor;
}
bool CursorImpl::Initialize()
{
return true;
}
void CursorImpl::Uninitialize()
{
}
std::array<LPTSTR, SystemCursor_Max + 1> 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");
}

View File

@@ -1,42 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CURSORIMPL_HPP
#define NAZARA_CURSORIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Platform/Enums.hpp>
#include <array>
#include <windows.h>
namespace Nz
{
class Image;
class CursorImpl
{
friend class Cursor;
public:
bool Create(const Image& image, int hotSpotX, int hotSpotY);
bool Create(SystemCursor cursor);
void Destroy();
HCURSOR GetCursor();
private:
static bool Initialize();
static void Uninitialize();
HCURSOR m_cursor = nullptr;
HICON m_icon = nullptr;
static std::array<LPTSTR, SystemCursor_Max + 1> s_systemCursorIds;
};
}
#endif // NAZARA_CURSORIMPL_HPP

View File

@@ -1,53 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Win32/IconImpl.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
bool IconImpl::Create(const Image& icon)
{
Image windowsIcon(icon); // Vive le COW
if (!windowsIcon.Convert(PixelFormatType_BGRA8))
{
NazaraError("Failed to convert icon to BGRA8");
return false;
}
HBITMAP bitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 32, windowsIcon.GetConstPixels());
HBITMAP monoBitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 1, nullptr);
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.hbmMask = monoBitmap;
iconInfo.hbmColor = bitmap;
m_icon = CreateIconIndirect(&iconInfo);
DeleteObject(bitmap);
DeleteObject(monoBitmap);
if (!m_icon)
{
NazaraError("Failed to create icon: " + Error::GetLastSystemError());
return false;
}
return true;
}
void IconImpl::Destroy()
{
DestroyIcon(m_icon);
}
HICON IconImpl::GetIcon()
{
return m_icon;
}
}

View File

@@ -1,30 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ICONIMPL_HPP
#define NAZARA_ICONIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <windows.h>
namespace Nz
{
class Image;
class IconImpl
{
public:
bool Create(const Image& image);
void Destroy();
HICON GetIcon();
private:
HICON m_icon = nullptr;
};
}
#endif // NAZARA_ICONIMPL_HPP

View File

@@ -1,298 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Platform/Debug.hpp>
#include <Nazara/Platform/Win32/InputImpl.hpp>
#include <Nazara/Platform/Window.hpp>
#include <windows.h>
namespace Nz
{
namespace
{
int vKeys[Keyboard::Count] = {
// Lettres
0x41, // Key::A
0x42, // Key::B
0x43, // Key::C
0x44, // Key::D
0x45, // Key::E
0x46, // Key::F
0x47, // Key::G
0x48, // Key::H
0x49, // Key::I
0x4A, // Key::J
0x4B, // Key::K
0x4C, // Key::L
0x4D, // Key::M
0x4E, // Key::N
0x4F, // Key::O
0x50, // Key::P
0x51, // Key::Q
0x52, // Key::R
0x53, // Key::S
0x54, // Key::T
0x55, // Key::U
0x56, // Key::V
0x57, // Key::W
0x58, // Key::X
0x59, // Key::Y
0x5A, // Key::Z
// Touches de fonction
VK_F1, // Key::F1
VK_F2, // Key::F2
VK_F3, // Key::F3
VK_F4, // Key::F4
VK_F5, // Key::F5
VK_F6, // Key::F6
VK_F7, // Key::F7
VK_F8, // Key::F8
VK_F9, // Key::F9
VK_F10, // Key::F10
VK_F11, // Key::F11
VK_F12, // Key::F12
VK_F13, // Key::F13
VK_F14, // Key::F14
VK_F15, // Key::F15
// Flèches directionnelles
VK_DOWN, // Key::Down
VK_LEFT, // Key::Left
VK_RIGHT, // Key::Right
VK_UP, // Key::Up
// Pavé numérique
VK_ADD, // Key::Add
VK_DECIMAL, // Key::Decimal
VK_DIVIDE, // Key::Divide
VK_MULTIPLY, // Key::Multiply
VK_RETURN, // Key::Multiply
VK_NUMPAD0, // Key::Numpad0
VK_NUMPAD1, // Key::Numpad1
VK_NUMPAD2, // Key::Numpad2
VK_NUMPAD3, // Key::Numpad3
VK_NUMPAD4, // Key::Numpad4
VK_NUMPAD5, // Key::Numpad5
VK_NUMPAD6, // Key::Numpad6
VK_NUMPAD7, // Key::Numpad7
VK_NUMPAD8, // Key::Numpad8
VK_NUMPAD9, // Key::Numpad9
VK_SUBTRACT, // Key::Subtract
// Diverss
VK_OEM_5, // Key::Backslash
VK_BACK, // Key::Backspace
VK_CLEAR, // Key::Clear
VK_OEM_COMMA, // Key::Comma,
VK_OEM_MINUS, // Key::Dash
VK_DELETE, // Key::Delete
VK_END, // Key::End
VK_OEM_PLUS, // Key::Equal
VK_ESCAPE, // Key::Escape
VK_HOME, // Key::Home
VK_INSERT, // Key::Insert
VK_LMENU, // Key::LAlt
VK_OEM_4, // Key::LBracket
VK_LCONTROL, // Key::LControl
VK_LSHIFT, // Key::LShift
VK_LWIN, // Key::LSystem
0x30, // Key::Num0
0x31, // Key::Num1
0x32, // Key::Num2
0x33, // Key::Num3
0x34, // Key::Num4
0x35, // Key::Num5
0x36, // Key::Num6
0x37, // Key::Num7
0x38, // Key::Num8
0x39, // Key::Num9
VK_NEXT, // Key::PageDown
VK_PRIOR, // Key::PageUp
VK_PAUSE, // Key::Pause
VK_OEM_PERIOD, // Key::Period
VK_PRINT, // Key::Print
VK_SNAPSHOT, // Key::PrintScreen
VK_OEM_7, // Key::Quote
VK_RMENU, // Key::RAlt
VK_OEM_6, // Key::RBracket
VK_RCONTROL, // Key::RControl
VK_RETURN, // Key::Return
VK_RSHIFT, // Key::RShift
VK_RWIN, // Key::RSystem
VK_OEM_1, // Key::Semicolon
VK_OEM_2, // Key::Slash
VK_SPACE, // Key::Space
VK_TAB, // Key::Tab
VK_OEM_3, // Key::Tilde
VK_APPS, // Key::Menu
VK_OEM_102, // Key::ISOBackslash102
// Touches navigateur
VK_BROWSER_BACK, // Key::Browser_Back
VK_BROWSER_FAVORITES, // Key::Browser_Favorites
VK_BROWSER_FORWARD, // Key::Browser_Forward
VK_BROWSER_HOME, // Key::Browser_Home
VK_BROWSER_REFRESH, // Key::Browser_Refresh
VK_BROWSER_SEARCH, // Key::Browser_Search
VK_BROWSER_STOP, // Key::Browser_Stop
// Touches de contrôle
VK_MEDIA_NEXT_TRACK, // Key::Media_Next,
VK_MEDIA_PLAY_PAUSE, // Key::Media_PlayPause,
VK_MEDIA_PREV_TRACK, // Key::Media_Previous,
VK_MEDIA_STOP, // Key::Media_Stop,
// Touches de contrôle du volume
VK_VOLUME_DOWN, // Key::Volume_Down
VK_VOLUME_MUTE, // Key::Volume_Mute
VK_VOLUME_UP, // Key::Volume_Up
// Touches à verrouillage
VK_CAPITAL, // Key::CapsLock
VK_NUMLOCK, // Key::NumLock
VK_SCROLL // Key::ScrollLock
};
}
String EventImpl::GetKeyName(Keyboard::Key key)
{
// http://www.ffuts.org/blog/mapvirtualkey-getkeynametext-and-a-story-of-how-to/
int vk = vKeys[key];
unsigned int code = MapVirtualKeyW(vk, 0) << 16;
///FIXME: Liste complète ?
switch (vk)
{
case VK_ATTN:
case VK_DOWN:
case VK_DECIMAL:
case VK_DELETE:
case VK_DIVIDE:
case VK_END:
case VK_HOME:
case VK_INSERT:
case VK_LEFT:
case VK_LWIN:
case VK_OEM_1:
case VK_OEM_2:
case VK_OEM_3:
case VK_OEM_4:
case VK_OEM_5:
case VK_OEM_6:
case VK_OEM_7:
case VK_OEM_CLEAR:
case VK_OEM_COMMA:
case VK_OEM_MINUS:
case VK_OEM_PERIOD:
case VK_OEM_PLUS:
case VK_PAUSE:
case VK_NEXT:
case VK_NUMLOCK:
case VK_PRIOR:
case VK_RIGHT:
case VK_RWIN:
case VK_UP:
case VK_RETURN: // TODO check
code |= 0x1000000; // 24ème bit pour l'extension
break;
}
wchar_t keyName[20]; // Je ne pense pas que ça dépassera 20 caractères
if (!GetKeyNameTextW(code, &keyName[0], 20))
return "Unknown";
return String::Unicode(keyName);
}
Vector2i EventImpl::GetMousePosition()
{
POINT pos;
GetCursorPos(&pos);
return Vector2i(pos.x, pos.y);
}
Vector2i EventImpl::GetMousePosition(const Window& relativeTo)
{
HWND handle = static_cast<HWND>(relativeTo.GetHandle());
if (handle)
{
POINT pos;
GetCursorPos(&pos);
ScreenToClient(handle, &pos);
return Vector2i(pos.x, pos.y);
}
else
{
NazaraError("Invalid window handle");
// Attention que (-1, -1) est une position tout à fait valide et ne doit pas servir de test
return Vector2i(-1, -1);
}
}
bool EventImpl::IsKeyPressed(Keyboard::Key key)
{
switch (key)
{
case Keyboard::CapsLock:
case Keyboard::NumLock:
case Keyboard::ScrollLock:
return GetKeyState(vKeys[key]) != 0;
default:
return (GetAsyncKeyState(vKeys[key]) & 0x8000) != 0;
}
}
bool EventImpl::IsMouseButtonPressed(Mouse::Button button)
{
static int vButtons[Mouse::Max + 1] = {
VK_LBUTTON, // Button::Left
VK_MBUTTON, // Button::Middle
VK_RBUTTON, // Button::Right
VK_XBUTTON1, // Button::XButton1
VK_XBUTTON2 // Button::XButton2
};
// Gestion de l'inversement des boutons de la souris
if (GetSystemMetrics(SM_SWAPBUTTON))
switch (button)
{
case Mouse::Left:
button = Mouse::Right;
break;
case Mouse::Right:
button = Mouse::Left;
break;
default:
break;
}
return (GetAsyncKeyState(vButtons[button]) & 0x8000) != 0;
}
void EventImpl::SetMousePosition(int x, int y)
{
SetCursorPos(x, y);
}
void EventImpl::SetMousePosition(int x, int y, const Window& relativeTo)
{
HWND handle = static_cast<HWND>(relativeTo.GetHandle());
if (handle)
{
POINT pos = {x, y};
ClientToScreen(handle, &pos);
SetCursorPos(pos.x, pos.y);
}
else
NazaraError("Invalid window handle");
}
}

View File

@@ -1,30 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_INPUTIMPL_HPP
#define NAZARA_INPUTIMPL_HPP
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Platform/Keyboard.hpp>
#include <Nazara/Platform/Mouse.hpp>
namespace Nz
{
class EventImpl
{
public:
static String GetKeyName(Keyboard::Key key);
static Vector2i GetMousePosition();
static Vector2i GetMousePosition(const Window& relativeTo);
static bool IsKeyPressed(Keyboard::Key key);
static bool IsMouseButtonPressed(Mouse::Button button);
static void SetMousePosition(int x, int y);
static void SetMousePosition(int x, int y, const Window& relativeTo);
};
}
#endif // NAZARA_INPUTIMPL_HPP

View File

@@ -1,35 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Win32/VideoModeImpl.hpp>
#include <Nazara/Platform/VideoMode.hpp>
#include <algorithm>
#include <windows.h>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
VideoMode VideoModeImpl::GetDesktopMode()
{
DEVMODE mode;
mode.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &mode);
return VideoMode(mode.dmPelsWidth, mode.dmPelsHeight, static_cast<UInt8>(mode.dmBitsPerPel));
}
void VideoModeImpl::GetFullscreenModes(std::vector<VideoMode>& modes)
{
DEVMODE win32Mode;
win32Mode.dmSize = sizeof(DEVMODE);
for (unsigned int i = 0; EnumDisplaySettings(nullptr, i, &win32Mode); ++i)
{
VideoMode mode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, static_cast<UInt8>(win32Mode.dmBitsPerPel));
// Il existe plusieurs modes avec ces trois caractéristques identiques
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
modes.push_back(mode);
}
}
}

View File

@@ -1,22 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VIDEOMODEIMPL_HPP
#define NAZARA_VIDEOMODEIMPL_HPP
#include <Nazara/Platform/VideoMode.hpp>
namespace Nz
{
class VideoModeImpl
{
public:
static VideoMode GetDesktopMode();
static void GetFullscreenModes(std::vector<VideoMode>& modes);
};
}
#endif // NNAZARA_VIDEOMODEIMPL_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -1,116 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Interface inspirée de la SFML par Laurent Gomila
#pragma once
#ifndef NAZARA_WINDOWIMPL_HPP
#define NAZARA_WINDOWIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Platform/Config.hpp>
#include <Nazara/Platform/Keyboard.hpp>
#include <Nazara/Platform/Mouse.hpp>
#include <Nazara/Platform/VideoMode.hpp>
#include <Nazara/Platform/Window.hpp>
#include <windows.h>
namespace Nz
{
class ConditionVariable;
class Mutex;
class Window;
#undef IsMinimized // Conflits with windows.h redefinition
class WindowImpl
{
public:
WindowImpl(Window* parent);
WindowImpl(const WindowImpl&) = delete;
WindowImpl(WindowImpl&&) = delete; ///TODO?
~WindowImpl() = default;
bool Create(const VideoMode& mode, const String& title, WindowStyleFlags style);
bool Create(WindowHandle handle);
void Destroy();
void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable);
WindowHandle GetHandle() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
WindowStyleFlags GetStyle() const;
String GetTitle() const;
bool HasFocus() const;
void IgnoreNextMouseEvent(int mouseX, int mouseY);
bool IsMinimized() const;
bool IsVisible() const;
void RefreshCursor();
void ProcessEvents(bool block);
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 String& title);
void SetVisible(bool visible);
WindowImpl& operator=(const WindowImpl&) = delete;
WindowImpl& operator=(WindowImpl&&) = delete; ///TODO?
static bool Initialize();
static void Uninitialize();
private:
bool HandleMessage(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
void PrepareWindow(bool fullscreen);
static bool SetProcessDpiAware();
static Keyboard::Key ConvertVirtualKey(WPARAM key, LPARAM flags);
static LRESULT CALLBACK MessageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
static UInt32 RetrieveStyle(HWND window);
static void WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
HCURSOR m_cursor;
HWND m_handle;
LONG_PTR m_callback;
WindowStyleFlags m_style;
Vector2i m_maxSize;
Vector2i m_minSize;
Vector2i m_mousePos;
Vector2i m_position;
Vector2ui m_size;
Thread m_thread;
Window* m_parent;
bool m_eventListener;
bool m_keyRepeat;
bool m_mouseInside;
bool m_ownsWindow;
bool m_sizemove;
bool m_smoothScrolling;
bool m_threadActive;
short m_scrolling;
};
}
#endif // NAZARA_WINDOWIMPL_HPP

View File

@@ -8,17 +8,7 @@
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Platform/Cursor.hpp>
#include <Nazara/Platform/Icon.hpp>
#if defined(NAZARA_PLATFORM_SDL2)
#include <Nazara/Platform/SDL2/WindowImpl.hpp>
#elif defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Platform/Win32/WindowImpl.hpp>
#elif defined(NAZARA_PLATFORM_X11)
#include <Nazara/Platform/X11/WindowImpl.hpp>
#else
#error Lack of implementation: Window
#endif
#include <Nazara/Platform/Debug.hpp>
namespace Nz

View File

@@ -1,270 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/X11/CursorImpl.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Platform/X11/Display.hpp>
#include <Nazara/Platform/X11/ScopedXCB.hpp>
#include <xcb/xcb_image.h>
// Some older versions of xcb/util-renderutil (notably the one available on Travis CI) use `template` as an argument name
// This is a fixed bug (https://cgit.freedesktop.org/xcb/util-renderutil/commit/?id=8d15acc45a47dc4c922eee5b99885db42bc62c17) but until Travis-CI
// has upgraded their Ubuntu version, I'm forced to use this ugly trick.
#define template ptemplate
extern "C"
{
#include <xcb/xcb_renderutil.h>
}
#undef template
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
bool CursorImpl::Create(const Image& cursor, int hotSpotX, int hotSpotY)
{
Image cursorImage(cursor); // Vive le COW
if (!cursorImage.Convert(Nz::PixelFormatType_BGRA8))
{
NazaraError("Failed to convert cursor to BGRA8");
return false;
}
auto width = cursorImage.GetWidth();
auto height = cursorImage.GetHeight();
ScopedXCBConnection connection;
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
ScopedXCB<xcb_generic_error_t> error(nullptr);
ScopedXCB<xcb_render_query_pict_formats_reply_t> formatsReply = xcb_render_query_pict_formats_reply(
connection,
xcb_render_query_pict_formats(connection),
&error);
if (!formatsReply || error)
{
NazaraError("Failed to get pict formats");
return false;
}
xcb_render_pictforminfo_t* fmt = xcb_render_util_find_standard_format(
formatsReply.get(),
XCB_PICT_STANDARD_ARGB_32);
if (!fmt)
{
NazaraError("Failed to find format PICT_STANDARD_ARGB_32");
return false;
}
xcb_image_t* xi = xcb_image_create(
width, height,
XCB_IMAGE_FORMAT_Z_PIXMAP,
32, 32, 32, 32,
XCB_IMAGE_ORDER_LSB_FIRST,
XCB_IMAGE_ORDER_MSB_FIRST,
0, 0, 0);
if (!xi)
{
NazaraError("Failed to create image for cursor");
return false;
}
std::unique_ptr<uint8_t[]> data(new uint8_t[xi->stride * height]);
if (!data)
{
xcb_image_destroy(xi);
NazaraError("Failed to allocate memory for cursor image");
return false;
}
xi->data = data.get();
std::copy(cursorImage.GetConstPixels(), cursorImage.GetConstPixels() + cursorImage.GetBytesPerPixel() * width * height, xi->data);
xcb_render_picture_t pic = XCB_NONE;
CallOnExit onExit([&](){
xcb_image_destroy(xi);
if (pic != XCB_NONE)
xcb_render_free_picture(connection, pic);
});
XCBPixmap pix(connection);
if (!pix.Create(32, screen->root, width, height))
{
NazaraError("Failed to create pixmap for cursor");
return false;
}
pic = xcb_generate_id(connection);
if (!X11::CheckCookie(
connection,
xcb_render_create_picture(
connection,
pic,
pix,
fmt->id,
0,
nullptr
)))
{
NazaraError("Failed to create render picture for cursor");
return false;
}
XCBGContext gc(connection);
if (!gc.Create(pix, 0, nullptr))
{
NazaraError("Failed to create gcontext for cursor");
return false;
}
if (!X11::CheckCookie(
connection,
xcb_image_put(
connection,
pix,
gc,
xi,
0, 0,
0
)))
{
NazaraError("Failed to put image for cursor");
return false;
}
m_cursor = xcb_generate_id(connection);
if (!X11::CheckCookie(
connection,
xcb_render_create_cursor(
connection,
m_cursor,
pic,
hotSpotX, hotSpotY
)))
{
NazaraError("Failed to create cursor");
return false;
}
return true;
}
bool CursorImpl::Create(SystemCursor cursor)
{
ScopedXCBConnection connection;
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
const char* cursorName = s_systemCursorIds[cursor];
if (cursorName)
{
if (xcb_cursor_context_new(connection, screen, &m_cursorContext) >= 0)
m_cursor = xcb_cursor_load_cursor(m_cursorContext, cursorName);
else
{
NazaraError("Failed to create cursor context");
return false;
}
}
else
m_cursor = s_hiddenCursor;
return true;
}
void CursorImpl::Destroy()
{
ScopedXCBConnection connection;
xcb_free_cursor(connection, m_cursor);
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;
}
s_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,
s_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;
}
}
xcb_cursor_t CursorImpl::s_hiddenCursor = 0;
std::array<const char*, SystemCursor_Max + 1> 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");
}

View File

@@ -1,43 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CURSORIMPL_HPP
#define NAZARA_CURSORIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Platform/Enums.hpp>
#include <xcb/xcb_cursor.h>
#include <array>
namespace Nz
{
class Image;
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:
static bool Initialize();
static void Uninitialize();
xcb_cursor_t m_cursor = 0;
xcb_cursor_context_t* m_cursorContext = nullptr;
static xcb_cursor_t s_hiddenCursor;
static std::array<const char*, SystemCursor_Max + 1> s_systemCursorIds;
};
}
#endif // NAZARA_CURSORIMPL_HPP

View File

@@ -1,247 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/X11/Display.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Platform/X11/ScopedXCB.hpp>
#include <xcb/xcb_keysyms.h>
#include <map>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
namespace
{
// The shared display and its reference counter
xcb_connection_t* sharedConnection = nullptr;
int screen_nbr = 0;
unsigned int referenceCountConnection = 0;
xcb_key_symbols_t* sharedkeySymbol = nullptr;
unsigned int referenceCountKeySymbol = 0;
xcb_ewmh_connection_t* sharedEwmhConnection = nullptr;
unsigned int referenceCountEwmhConnection = 0;
using AtomMap = std::map<String, xcb_atom_t>;
AtomMap atoms;
}
bool X11::CheckCookie(xcb_connection_t* connection, xcb_void_cookie_t cookie)
{
ScopedXCB<xcb_generic_error_t> error(xcb_request_check(
connection,
cookie
));
if (error)
return false;
else
return true;
}
void X11::CloseConnection(xcb_connection_t* connection)
{
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
--referenceCountConnection;
}
void X11::CloseEWMHConnection(xcb_ewmh_connection_t* ewmh_connection)
{
NazaraAssert(ewmh_connection == sharedEwmhConnection, "The model is meant for one connection to X11 server");
--referenceCountEwmhConnection;
}
xcb_atom_t X11::GetAtom(const String& name, bool onlyIfExists)
{
AtomMap::const_iterator iter = atoms.find(name);
if (iter != atoms.end())
return iter->second;
ScopedXCB<xcb_generic_error_t> error(nullptr);
xcb_connection_t* connection = OpenConnection();
ScopedXCB<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(
connection,
xcb_intern_atom(
connection,
onlyIfExists,
name.GetSize(),
name.GetConstBuffer()
),
&error
));
CloseConnection(connection);
if (error || !reply)
{
NazaraError("Failed to get " + name + " atom.");
return XCB_ATOM_NONE;
}
atoms[name] = reply->atom;
return reply->atom;
}
bool X11::Initialize()
{
if (IsInitialized())
{
s_moduleReferenceCounter++;
return true; // Déjà initialisé
}
s_moduleReferenceCounter++;
NazaraAssert(referenceCountConnection == 0, "Initialize should be called before anything");
NazaraAssert(referenceCountKeySymbol == 0, "Initialize should be called before anything");
NazaraAssert(referenceCountEwmhConnection == 0, "Initialize should be called before anything");
{
sharedConnection = xcb_connect(nullptr, &screen_nbr);
// Opening display failed: The best we can do at the moment is to output a meaningful error message
if (!sharedConnection || xcb_connection_has_error(sharedConnection))
{
NazaraError("Failed to open xcb connection");
return false;
}
OpenConnection();
}
{
sharedkeySymbol = xcb_key_symbols_alloc(sharedConnection);
XCBKeySymbolsAlloc(sharedConnection);
}
{
sharedEwmhConnection = new xcb_ewmh_connection_t;
xcb_intern_atom_cookie_t* ewmh_cookie = xcb_ewmh_init_atoms(sharedConnection, sharedEwmhConnection);
if(!xcb_ewmh_init_atoms_replies(sharedEwmhConnection, ewmh_cookie, nullptr))
{
NazaraError("Could not initialize EWMH Connection");
sharedEwmhConnection = nullptr;
}
OpenEWMHConnection(sharedConnection);
}
return true;
}
bool X11::IsInitialized()
{
return s_moduleReferenceCounter != 0;
}
xcb_key_symbols_t* X11::XCBKeySymbolsAlloc(xcb_connection_t* connection)
{
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
++referenceCountKeySymbol;
return sharedkeySymbol;
}
void X11::XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols)
{
NazaraAssert(keySymbols == sharedkeySymbol, "The model is meant for one connection to X11 server");
--referenceCountKeySymbol;
}
xcb_connection_t* X11::OpenConnection()
{
++referenceCountConnection;
return sharedConnection;
}
xcb_ewmh_connection_t* X11::OpenEWMHConnection(xcb_connection_t* connection)
{
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
++referenceCountEwmhConnection;
return sharedEwmhConnection;
}
void X11::Uninitialize()
{
if (s_moduleReferenceCounter != 1)
{
// Le module est soit encore utilisé, soit pas initialisé
if (s_moduleReferenceCounter > 1)
s_moduleReferenceCounter--;
return;
}
s_moduleReferenceCounter = 0;
{
NazaraAssert(referenceCountEwmhConnection == 1, "Uninitialize should be called after anything or a close is missing");
CloseEWMHConnection(sharedEwmhConnection);
xcb_ewmh_connection_wipe(sharedEwmhConnection);
delete sharedEwmhConnection;
}
{
NazaraAssert(referenceCountKeySymbol == 1, "Uninitialize should be called after anything or a free is missing");
XCBKeySymbolsFree(sharedkeySymbol);
xcb_key_symbols_free(sharedkeySymbol);
}
{
NazaraAssert(referenceCountConnection == 1, "Uninitialize should be called after anything or a close is missing");
CloseConnection(sharedConnection);
xcb_disconnect(sharedConnection);
}
}
xcb_window_t X11::XCBDefaultRootWindow(xcb_connection_t* connection)
{
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
xcb_screen_t* screen = XCBDefaultScreen(connection);
if (screen)
return screen->root;
return XCB_NONE;
}
xcb_screen_t* X11::XCBDefaultScreen(xcb_connection_t* connection)
{
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
return XCBScreenOfDisplay(connection, screen_nbr);
}
int X11::XCBScreen(xcb_connection_t* connection)
{
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
return screen_nbr;
}
xcb_screen_t* X11::XCBScreenOfDisplay(xcb_connection_t* connection, int screenIndex)
{
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
for (; iter.rem; --screenIndex, xcb_screen_next (&iter))
{
if (screenIndex == 0)
return iter.data;
}
return nullptr;
}
unsigned int X11::s_moduleReferenceCounter = 0;
}

View File

@@ -1,54 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_X11DISPLAY_HPP
#define NAZARA_X11DISPLAY_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Platform/Config.hpp>
#include <xcb/xcb.h>
#include <xcb/xcb_ewmh.h>
typedef struct _XCBKeySymbols xcb_key_symbols_t;
namespace Nz
{
class String;
class NAZARA_PLATFORM_API X11
{
public:
X11() = delete;
~X11() = delete;
static bool CheckCookie(xcb_connection_t* connection, xcb_void_cookie_t cookie);
static void CloseConnection(xcb_connection_t* connection);
static void CloseEWMHConnection(xcb_ewmh_connection_t* ewmh_connection);
static xcb_atom_t GetAtom(const String& name, bool onlyIfExists = false);
static bool Initialize();
static bool IsInitialized();
static xcb_key_symbols_t* XCBKeySymbolsAlloc(xcb_connection_t* connection);
static void XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols);
static xcb_connection_t* OpenConnection();
static xcb_ewmh_connection_t* OpenEWMHConnection(xcb_connection_t* connection);
static void Uninitialize();
static xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection);
static xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection);
static int XCBScreen(xcb_connection_t* connection);
static xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr);
private:
static unsigned int s_moduleReferenceCounter;
};
}
#endif // NAZARA_X11DISPLAY_HPP

View File

@@ -1,136 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/X11/IconImpl.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Platform/X11/Display.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
IconImpl::IconImpl()
{
ScopedXCBConnection connection;
m_iconPixmap.Connect(connection);
m_maskPixmap.Connect(connection);
}
bool IconImpl::Create(const Image& icon)
{
Image iconImage(icon); // Vive le COW
if (!iconImage.Convert(Nz::PixelFormatType_BGRA8))
{
NazaraError("Failed to convert icon to BGRA8");
return false;
}
auto width = iconImage.GetWidth();
auto height = iconImage.GetHeight();
ScopedXCBConnection connection;
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
if (!m_iconPixmap.Create(
screen->root_depth,
screen->root,
width,
height))
{
NazaraError("Failed to create icon pixmap");
return false;
}
CallOnExit onExit([this](){
Destroy();
});
XCBGContext iconGC(connection);
if (!iconGC.Create(
m_iconPixmap,
0,
nullptr))
{
NazaraError("Failed to create icon gc");
return false;
}
if (!X11::CheckCookie(
connection,
xcb_put_image(
connection,
XCB_IMAGE_FORMAT_Z_PIXMAP,
m_iconPixmap,
iconGC,
width,
height,
0,
0,
0,
screen->root_depth,
width * height * 4,
iconImage.GetConstPixels()
)))
{
NazaraError("Failed to put image for icon");
return false;
}
// Create the mask pixmap (must have 1 bit depth)
std::size_t pitch = (width + 7) / 8;
static std::vector<UInt8> maskPixels(pitch * height, 0);
for (std::size_t j = 0; j < height; ++j)
{
for (std::size_t i = 0; i < pitch; ++i)
{
for (std::size_t k = 0; k < 8; ++k)
{
if (i * 8 + k < width)
{
UInt8 opacity = (iconImage.GetConstPixels()[(i * 8 + k + j * width) * 4 + 3] > 0) ? 1 : 0;
maskPixels[i + j * pitch] |= (opacity << k);
}
}
}
}
if (!m_maskPixmap.CreatePixmapFromBitmapData(
X11::XCBDefaultRootWindow(connection),
reinterpret_cast<uint8_t*>(&maskPixels[0]),
width,
height,
1,
0,
1,
nullptr))
{
NazaraError("Failed to create mask pixmap for icon");
return false;
}
onExit.Reset();
return true;
}
void IconImpl::Destroy()
{
m_iconPixmap.Destroy();
m_maskPixmap.Destroy();
}
xcb_pixmap_t IconImpl::GetIcon()
{
return m_iconPixmap;
}
xcb_pixmap_t IconImpl::GetMask()
{
return m_maskPixmap;
}
}

View File

@@ -1,34 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ICONIMPL_HPP
#define NAZARA_ICONIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Platform/X11/ScopedXCB.hpp>
namespace Nz
{
class Image;
class IconImpl
{
public:
IconImpl();
bool Create(const Image& image);
void Destroy();
xcb_pixmap_t GetIcon();
xcb_pixmap_t GetMask();
private:
XCBPixmap m_iconPixmap;
XCBPixmap m_maskPixmap;
};
}
#endif // NAZARA_ICONIMPL_HPP

View File

@@ -1,393 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/X11/InputImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Platform/Window.hpp>
#include <Nazara/Platform/X11/Display.hpp>
#include <Nazara/Platform/X11/ScopedXCB.hpp>
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
#include <X11/Xlib.h>
#include <xcb/xcb_keysyms.h>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
namespace
{
KeySym GetKeySym(Keyboard::Key key)
{
// X11 keysym correspondant
KeySym keysym = 0;
switch (key)
{
// Lettres
case Keyboard::A: keysym = XK_a; break;
case Keyboard::B: keysym = XK_b; break;
case Keyboard::C: keysym = XK_c; break;
case Keyboard::D: keysym = XK_d; break;
case Keyboard::E: keysym = XK_e; break;
case Keyboard::F: keysym = XK_f; break;
case Keyboard::G: keysym = XK_g; break;
case Keyboard::H: keysym = XK_h; break;
case Keyboard::I: keysym = XK_i; break;
case Keyboard::J: keysym = XK_j; break;
case Keyboard::K: keysym = XK_k; break;
case Keyboard::L: keysym = XK_l; break;
case Keyboard::M: keysym = XK_m; break;
case Keyboard::N: keysym = XK_n; break;
case Keyboard::O: keysym = XK_o; break;
case Keyboard::P: keysym = XK_p; break;
case Keyboard::Q: keysym = XK_q; break;
case Keyboard::R: keysym = XK_r; break;
case Keyboard::S: keysym = XK_s; break;
case Keyboard::T: keysym = XK_t; break;
case Keyboard::U: keysym = XK_u; break;
case Keyboard::V: keysym = XK_v; break;
case Keyboard::W: keysym = XK_w; break;
case Keyboard::X: keysym = XK_x; break;
case Keyboard::Y: keysym = XK_y; break;
case Keyboard::Z: keysym = XK_z; break;
// Touches de fonction
case Keyboard::F1: keysym = XK_F1; break;
case Keyboard::F2: keysym = XK_F2; break;
case Keyboard::F3: keysym = XK_F3; break;
case Keyboard::F4: keysym = XK_F4; break;
case Keyboard::F5: keysym = XK_F5; break;
case Keyboard::F6: keysym = XK_F6; break;
case Keyboard::F7: keysym = XK_F7; break;
case Keyboard::F8: keysym = XK_F8; break;
case Keyboard::F9: keysym = XK_F9; break;
case Keyboard::F10: keysym = XK_F10; break;
case Keyboard::F11: keysym = XK_F11; break;
case Keyboard::F12: keysym = XK_F12; break;
case Keyboard::F13: keysym = XK_F13; break;
case Keyboard::F14: keysym = XK_F14; break;
case Keyboard::F15: keysym = XK_F15; break;
// Flèches directionnelles
case Keyboard::Down: keysym = XK_Down; break;
case Keyboard::Left: keysym = XK_Left; break;
case Keyboard::Right: keysym = XK_Right; break;
case Keyboard::Up: keysym = XK_Up; break;
// Pavé numérique
case Keyboard::Add: keysym = XK_KP_Add; break;
case Keyboard::Decimal: keysym = XK_KP_Decimal; break;
case Keyboard::Divide: keysym = XK_KP_Divide; break;
case Keyboard::Multiply: keysym = XK_KP_Multiply; break;
case Keyboard::NumpadReturn: keysym = XK_KP_Enter; break;
case Keyboard::Numpad0: keysym = XK_KP_0; break;
case Keyboard::Numpad1: keysym = XK_KP_1; break;
case Keyboard::Numpad2: keysym = XK_KP_2; break;
case Keyboard::Numpad3: keysym = XK_KP_3; break;
case Keyboard::Numpad4: keysym = XK_KP_4; break;
case Keyboard::Numpad5: keysym = XK_KP_5; break;
case Keyboard::Numpad6: keysym = XK_KP_6; break;
case Keyboard::Numpad7: keysym = XK_KP_7; break;
case Keyboard::Numpad8: keysym = XK_KP_8; break;
case Keyboard::Numpad9: keysym = XK_KP_9; break;
case Keyboard::Subtract: keysym = XK_KP_Subtract; break;
// Divers
case Keyboard::Backslash: keysym = XK_backslash; break;
case Keyboard::Backspace: keysym = XK_BackSpace; break;
case Keyboard::Clear: keysym = XK_Clear; break;
case Keyboard::Comma: keysym = XK_comma; break;
case Keyboard::Dash: keysym = XK_minus; break;
case Keyboard::Delete: keysym = XK_Delete; break;
case Keyboard::End: keysym = XK_End; break;
case Keyboard::Equal: keysym = XK_equal; break;
case Keyboard::Escape: keysym = XK_Escape; break;
case Keyboard::Home: keysym = XK_Home; break;
case Keyboard::Insert: keysym = XK_Insert; break;
case Keyboard::LAlt: keysym = XK_Alt_L; break;
case Keyboard::LBracket: keysym = XK_bracketleft; break;
case Keyboard::LControl: keysym = XK_Control_L; break;
case Keyboard::LShift: keysym = XK_Shift_L; break;
case Keyboard::LSystem: keysym = XK_Super_L; break;
case Keyboard::Num0: keysym = XK_0; break;
case Keyboard::Num1: keysym = XK_1; break;
case Keyboard::Num2: keysym = XK_2; break;
case Keyboard::Num3: keysym = XK_3; break;
case Keyboard::Num4: keysym = XK_4; break;
case Keyboard::Num5: keysym = XK_5; break;
case Keyboard::Num6: keysym = XK_6; break;
case Keyboard::Num7: keysym = XK_7; break;
case Keyboard::Num8: keysym = XK_8; break;
case Keyboard::Num9: keysym = XK_9; break;
case Keyboard::PageDown: keysym = XK_Page_Down; break;
case Keyboard::PageUp: keysym = XK_Page_Up; break;
case Keyboard::Pause: keysym = XK_Pause; break;
case Keyboard::Period: keysym = XK_period; break;
case Keyboard::Print: keysym = XK_Print; break;
case Keyboard::PrintScreen: keysym = XK_Sys_Req; break;
case Keyboard::Quote: keysym = XK_quotedbl; break;
case Keyboard::RAlt: keysym = XK_Alt_R; break;
case Keyboard::RBracket: keysym = XK_bracketright; break;
case Keyboard::RControl: keysym = XK_Control_R; break;
case Keyboard::Return: keysym = XK_Return; break;
case Keyboard::RShift: keysym = XK_Shift_R; break;
case Keyboard::RSystem: keysym = XK_Super_R; break;
case Keyboard::Semicolon: keysym = XK_semicolon; break;
case Keyboard::Slash: keysym = XK_slash; break;
case Keyboard::Space: keysym = XK_space; break;
case Keyboard::Tab: keysym = XK_Tab; break;
case Keyboard::Tilde: keysym = XK_grave; break;
case Keyboard::Menu: keysym = XK_Menu; break;
case Keyboard::ISOBackslash102: keysym = XK_less; break;
// Touches navigateur
case Keyboard::Browser_Back: keysym = XF86XK_Back; break;
case Keyboard::Browser_Favorites: keysym = XF86XK_Favorites; break;
case Keyboard::Browser_Forward: keysym = XF86XK_Forward; break;
case Keyboard::Browser_Home: keysym = XF86XK_HomePage; break;
case Keyboard::Browser_Refresh: keysym = XF86XK_Refresh; break;
case Keyboard::Browser_Search: keysym = XF86XK_Search; break;
case Keyboard::Browser_Stop: keysym = XF86XK_Stop; break;
// Touches de contrôle
case Keyboard::Media_Next: keysym = XF86XK_AudioNext; break;
case Keyboard::Media_Play: keysym = XF86XK_AudioPlay; break;
case Keyboard::Media_Previous: keysym = XF86XK_AudioPrev; break;
case Keyboard::Media_Stop: keysym = XF86XK_AudioStop; break;
// Touches de contrôle du volume
case Keyboard::Volume_Down: keysym = XF86XK_AudioLowerVolume; break;
case Keyboard::Volume_Mute: keysym = XF86XK_AudioMute; break;
case Keyboard::Volume_Up: keysym = XF86XK_AudioRaiseVolume; break;
// Touches à verrouillage
case Keyboard::CapsLock: keysym = XK_Caps_Lock; break;
case Keyboard::NumLock: keysym = XK_Num_Lock; break;
case Keyboard::ScrollLock: keysym = XK_Scroll_Lock; break;
default: break;
}
// Sanity checks
if (key < 0 || key >= Keyboard::Count || keysym == 0)
NazaraWarning("Key " + String::Number(key) + " is not handled in Keyboard");
return keysym;
}
}
String EventImpl::GetKeyName(Keyboard::Key key)
{
KeySym keySym = GetKeySym(key);
// XKeysymToString returns a static area.
return XKeysymToString(keySym);
}
Vector2i EventImpl::GetMousePosition()
{
ScopedXCBConnection connection;
ScopedXCB<xcb_generic_error_t> error(nullptr);
ScopedXCB<xcb_query_pointer_reply_t> pointer(
xcb_query_pointer_reply(
connection,
xcb_query_pointer(
connection,
X11::XCBDefaultRootWindow(connection)
),
&error
)
);
if (error)
{
NazaraError("Failed to query pointer");
return Vector2i(-1, -1);
}
return Vector2i(pointer->root_x, pointer->root_y);
}
Vector2i EventImpl::GetMousePosition(const Window& relativeTo)
{
WindowHandle handle = relativeTo.GetHandle();
if (handle)
{
// Open a connection with the X server
ScopedXCBConnection connection;
ScopedXCB<xcb_generic_error_t> error(nullptr);
ScopedXCB<xcb_query_pointer_reply_t> pointer(
xcb_query_pointer_reply(
connection,
xcb_query_pointer(
connection,
handle
),
&error
)
);
if (error)
{
NazaraError("Failed to query pointer");
return Vector2i(-1, -1);
}
return Vector2i(pointer->win_x, pointer->win_y);
}
else
{
NazaraError("No window handle");
return Vector2i(-1, -1);
}
}
bool EventImpl::IsKeyPressed(Keyboard::Key key)
{
ScopedXCBConnection connection;
xcb_keysym_t keySym = GetKeySym(key);
xcb_keycode_t realKeyCode = XCB_NO_SYMBOL;
xcb_key_symbols_t* keySymbols = X11::XCBKeySymbolsAlloc(connection);
if (!keySymbols)
{
NazaraError("Failed to alloc key symbols");
return false;
}
ScopedXCB<xcb_keycode_t> keyCode = xcb_key_symbols_get_keycode(keySymbols, keySym);
if (!keyCode)
{
NazaraError("Failed to get key code");
return false;
}
// One keysym is associated with multiple key codes, we have to find the matching one ...
int i = 0;
while (keyCode.get()[i] != XCB_NO_SYMBOL)
{
xcb_keycode_t toTry = keyCode.get()[i];
if (keySym == xcb_key_symbols_get_keysym(keySymbols, toTry, 0))
{
realKeyCode = toTry;
break;
}
++i;
}
X11::XCBKeySymbolsFree(keySymbols);
ScopedXCB<xcb_generic_error_t> error(nullptr);
// Get the whole keyboard state
ScopedXCB<xcb_query_keymap_reply_t> keymap(
xcb_query_keymap_reply(
connection,
xcb_query_keymap(connection),
&error
)
);
if (error)
{
NazaraError("Failed to query keymap");
return false;
}
// Check our keycode
return (keymap->keys[realKeyCode / 8] & (1 << (realKeyCode % 8))) != 0;
}
bool EventImpl::IsMouseButtonPressed(Mouse::Button button)
{
ScopedXCBConnection connection;
ScopedXCB<xcb_generic_error_t> error(nullptr);
// Get pointer mask
ScopedXCB<xcb_query_pointer_reply_t> pointer(
xcb_query_pointer_reply(
connection,
xcb_query_pointer(
connection,
X11::XCBDefaultRootWindow(connection)
),
&error
)
);
if (error)
{
NazaraError("Failed to query pointer");
return false;
}
uint16_t buttons = pointer->mask;
switch (button)
{
case Mouse::Left: return buttons & XCB_BUTTON_MASK_1;
case Mouse::Right: return buttons & XCB_BUTTON_MASK_3;
case Mouse::Middle: return buttons & XCB_BUTTON_MASK_2;
case Mouse::XButton1: return false; // not supported by X
case Mouse::XButton2: return false; // not supported by X
}
NazaraError("Mouse button not supported.");
return false;
}
void EventImpl::SetMousePosition(int x, int y)
{
ScopedXCBConnection connection;
xcb_window_t root = X11::XCBDefaultRootWindow(connection);
if (!X11::CheckCookie(
connection,
xcb_warp_pointer(
connection,
None, // Source window
root, // Destination window
0, 0, // Source position
0, 0, // Source size
x, y // Destination position
))
)
NazaraError("Failed to set mouse position");
xcb_flush(connection);
}
void EventImpl::SetMousePosition(int x, int y, const Window& relativeTo)
{
ScopedXCBConnection connection;
WindowHandle handle = relativeTo.GetHandle();
if (handle)
{
if (!X11::CheckCookie(
connection,
xcb_warp_pointer(
connection,
None, // Source window
handle, // Destination window
0, 0, // Source position
0, 0, // Source size
x, y // Destination position
))
)
NazaraError("Failed to set mouse position relative to window");
xcb_flush(connection);
}
else
NazaraError("No window handle");
}
}

View File

@@ -1,31 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_INPUTIMPL_HPP
#define NAZARA_INPUTIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Platform/Keyboard.hpp>
#include <Nazara/Platform/Mouse.hpp>
namespace Nz
{
class EventImpl
{
public:
static String GetKeyName(Keyboard::Key key);
static Vector2i GetMousePosition();
static Vector2i GetMousePosition(const Window& relativeTo);
static bool IsKeyPressed(Keyboard::Key key);
static bool IsMouseButtonPressed(Mouse::Button button);
static void SetMousePosition(int x, int y);
static void SetMousePosition(int x, int y, const Window& relativeTo);
};
}
#endif // NAZARA_INPUTIMPL_HPP

View File

@@ -1,199 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/X11/ScopedXCB.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Platform/X11/Display.hpp>
#include <xcb/xcb_image.h>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
/***********************************************
ScopedXCBConnection
***********************************************/
ScopedXCBConnection::ScopedXCBConnection() :
m_connection(nullptr)
{
m_connection = X11::OpenConnection();
}
ScopedXCBConnection::~ScopedXCBConnection()
{
X11::CloseConnection(m_connection);
}
ScopedXCBConnection::operator xcb_connection_t*() const
{
return m_connection;
}
/***********************************************
ScopedXCBEWMHConnection
***********************************************/
ScopedXCBEWMHConnection::ScopedXCBEWMHConnection(xcb_connection_t* connection) :
m_ewmhConnection(nullptr)
{
m_ewmhConnection = X11::OpenEWMHConnection(connection);
}
ScopedXCBEWMHConnection::~ScopedXCBEWMHConnection()
{
X11::CloseEWMHConnection(m_ewmhConnection);
}
xcb_ewmh_connection_t* ScopedXCBEWMHConnection::operator ->() const
{
return m_ewmhConnection;
}
ScopedXCBEWMHConnection::operator xcb_ewmh_connection_t*() const
{
return m_ewmhConnection;
}
/***********************************************
XCBGContext
***********************************************/
XCBGContext::XCBGContext(xcb_connection_t* connection) :
m_connection(connection),
m_gcontext(XCB_NONE)
{
NazaraAssert(connection, "Connection must have been established");
}
XCBGContext::~XCBGContext()
{
Destroy();
}
bool XCBGContext::Create(xcb_drawable_t drawable, uint32_t value_mask, const uint32_t* value_list)
{
NazaraAssert(m_gcontext == XCB_NONE, "Context must have been destroyed before or just created");
m_gcontext = xcb_generate_id(m_connection);
return X11::CheckCookie(
m_connection,
xcb_create_gc(
m_connection,
m_gcontext,
drawable,
value_mask,
value_list
));
}
void XCBGContext::Destroy()
{
if (m_gcontext == XCB_NONE)
return;
if (!X11::CheckCookie(
m_connection,
xcb_free_gc(
m_connection,
m_gcontext
))
)
NazaraError("Failed to free gcontext");
m_gcontext = XCB_NONE;
}
XCBGContext::operator xcb_gcontext_t() const
{
return m_gcontext;
}
/***********************************************
XCBPixmap
***********************************************/
XCBPixmap::XCBPixmap() :
m_connection(nullptr),
m_pixmap(XCB_NONE)
{
}
XCBPixmap::XCBPixmap(xcb_connection_t* connection) :
m_connection(connection),
m_pixmap(XCB_NONE)
{
}
XCBPixmap::~XCBPixmap()
{
Destroy();
}
void XCBPixmap::Connect(xcb_connection_t* connection)
{
NazaraAssert(connection && !m_connection, "Connection must be established");
m_connection = connection;
}
bool XCBPixmap::Create(uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height)
{
NazaraAssert(m_pixmap == XCB_NONE, "Pixmap must have been destroyed before or just created");
m_pixmap = xcb_generate_id(m_connection);
return X11::CheckCookie(
m_connection,
xcb_create_pixmap(
m_connection,
depth,
m_pixmap,
drawable,
width,
height
));
}
bool XCBPixmap::CreatePixmapFromBitmapData(xcb_drawable_t drawable, uint8_t* data, uint32_t width, uint32_t height, uint32_t depth, uint32_t fg, uint32_t bg, xcb_gcontext_t* gcp)
{
NazaraAssert(m_pixmap == XCB_NONE, "Pixmap must have been destroyed before or just created");
m_pixmap = xcb_create_pixmap_from_bitmap_data(
m_connection,
drawable,
data,
width,
height,
depth,
fg,
bg,
gcp
);
return m_pixmap != XCB_NONE;
}
void XCBPixmap::Destroy()
{
if (m_pixmap == XCB_NONE)
return;
if (!X11::CheckCookie(
m_connection,
xcb_free_pixmap(
m_connection,
m_pixmap
))
)
NazaraError("Failed to free pixmap");
m_pixmap = XCB_NONE;
}
XCBPixmap::operator xcb_pixmap_t() const
{
return m_pixmap;
}
}

View File

@@ -1,101 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SCOPEDXCB_HPP
#define NAZARA_SCOPEDXCB_HPP
#include <Nazara/Prerequisites.hpp>
#include <xcb/xcb.h>
#include <xcb/xcb_ewmh.h>
#include <cstdlib>
namespace Nz
{
class ScopedXCBConnection
{
public:
ScopedXCBConnection();
~ScopedXCBConnection();
operator xcb_connection_t*() const;
private:
xcb_connection_t* m_connection;
};
class ScopedXCBEWMHConnection
{
public:
ScopedXCBEWMHConnection(xcb_connection_t* connection);
~ScopedXCBEWMHConnection();
xcb_ewmh_connection_t* operator ->() const;
operator xcb_ewmh_connection_t*() const;
private:
xcb_ewmh_connection_t* m_ewmhConnection;
};
template <typename T>
class ScopedXCB
{
public:
ScopedXCB(T* pointer);
~ScopedXCB();
T* operator ->() const;
T** operator &();
operator bool() const;
T* get() const;
private:
T* m_pointer;
};
class XCBGContext
{
public:
XCBGContext(xcb_connection_t* connection);
~XCBGContext();
bool Create(xcb_drawable_t drawable, uint32_t value_mask, const uint32_t* value_list);
void Destroy();
operator xcb_gcontext_t() const;
private:
xcb_connection_t* m_connection;
xcb_gcontext_t m_gcontext;
};
class XCBPixmap
{
public:
XCBPixmap();
XCBPixmap(xcb_connection_t* connection);
~XCBPixmap();
void Connect(xcb_connection_t* connection);
bool Create(uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height);
bool CreatePixmapFromBitmapData(xcb_drawable_t drawable, uint8_t* data, uint32_t width, uint32_t height, uint32_t depth, uint32_t fg, uint32_t bg, xcb_gcontext_t* gcp);
void Destroy();
operator xcb_pixmap_t() const;
private:
xcb_connection_t* m_connection;
xcb_pixmap_t m_pixmap;
};
}
#include <Nazara/Platform/X11/ScopedXCB.inl>
#endif // NAZARA_SCOPEDXCB_HPP

View File

@@ -1,46 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
template <typename T>
ScopedXCB<T>::ScopedXCB(T* pointer) :
m_pointer(pointer)
{
}
template <typename T>
ScopedXCB<T>::~ScopedXCB()
{
std::free(m_pointer);
}
template <typename T>
T* ScopedXCB<T>::operator ->() const
{
return m_pointer;
}
template <typename T>
T** ScopedXCB<T>::operator &()
{
return &m_pointer;
}
template <typename T>
ScopedXCB<T>::operator bool() const
{
return m_pointer != nullptr;
}
template <typename T>
T* ScopedXCB<T>::get() const
{
return m_pointer;
}
}
#include <Nazara/Platform/DebugOff.hpp>

View File

@@ -1,170 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/X11/VideoModeImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Platform/VideoMode.hpp>
#include <Nazara/Platform/X11/Display.hpp>
#include <Nazara/Platform/X11/ScopedXCB.hpp>
#include <xcb/randr.h>
#include <algorithm>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
VideoMode VideoModeImpl::GetDesktopMode()
{
VideoMode desktopMode;
ScopedXCBConnection connection;
// Retrieve the default screen
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
ScopedXCB<xcb_generic_error_t> error(nullptr);
// Check if the RandR extension is present
const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);
if (!randrExt || !randrExt->present)
{
// Randr extension is not supported: we cannot get the video modes
NazaraError("Failed to use the RandR extension while trying to get the desktop video mode");
return desktopMode;
}
// Load RandR and check its version
ScopedXCB<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
connection,
xcb_randr_query_version(
connection,
1,
1
),
&error
));
if (error)
{
NazaraError("Failed to load the RandR extension while trying to get the desktop video mode");
return desktopMode;
}
// Get the current configuration
ScopedXCB<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
connection,
xcb_randr_get_screen_info(
connection,
screen->root
),
&error
));
if (error)
{
// Failed to get the screen configuration
NazaraError("Failed to retrieve the screen configuration while trying to get the desktop video mode");
return desktopMode;
}
// Get the current video mode
xcb_randr_mode_t currentMode = config->sizeID;
// Get the available screen sizes
int nbSizes = xcb_randr_get_screen_info_sizes_length(config.get());
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
if (sizes && (nbSizes > 0))
{
desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth);
if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
std::swap(desktopMode.width, desktopMode.height);
}
else
{
NazaraError("Failed to retrieve any screen sizes while trying to get the desktop video mode");
}
return desktopMode;
}
void VideoModeImpl::GetFullscreenModes(std::vector<VideoMode>& modes)
{
ScopedXCBConnection connection;
// Retrieve the default screen
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
ScopedXCB<xcb_generic_error_t> error(nullptr);
const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);
if (!randrExt || !randrExt->present)
{
// Randr extension is not supported: we cannot get the video modes
NazaraError("Failed to use the RandR extension while trying to get the supported video modes");
return;
}
// Load RandR and check its version
ScopedXCB<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
connection,
xcb_randr_query_version(
connection,
1,
1
),
&error
));
if (error)
{
NazaraError("Failed to load the RandR extension while trying to get the supported video modes");
return;
}
// Get the current configuration
ScopedXCB<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
connection,
xcb_randr_get_screen_info(
connection,
screen->root
),
&error
));
if (error)
{
// Failed to get the screen configuration
NazaraError("Failed to retrieve the screen configuration while trying to get the supported video modes");
return;
}
// Get the available screen sizes
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
if (sizes && (config->nSizes > 0))
{
// Get the list of supported depths
xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
// Combine depths and sizes to fill the array of supported modes
for (; iter.rem; xcb_depth_next(&iter))
{
for (int j = 0; j < config->nSizes; ++j)
{
// Convert to VideoMode
VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
std::swap(mode.width, mode.height);
// Add it only if it is not already in the array
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
modes.push_back(mode);
}
}
}
}
}

View File

@@ -1,23 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VIDEOMODEIMPL_HPP
#define NAZARA_VIDEOMODEIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Platform/VideoMode.hpp>
namespace Nz
{
class VideoModeImpl
{
public:
static VideoMode GetDesktopMode();
static void GetFullscreenModes(std::vector<VideoMode>& modes);
};
}
#endif // NNAZARA_VIDEOMODEIMPL_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -1,127 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Interface inspirée de la SFML par Laurent Gomila
#pragma once
#ifndef NAZARA_WINDOWIMPL_HPP
#define NAZARA_WINDOWIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Platform/Enums.hpp>
#include <Nazara/Platform/Keyboard.hpp>
#include <Nazara/Platform/WindowHandle.hpp>
#include <xcb/randr.h>
#include <xcb/xcb_icccm.h>
namespace Nz
{
class ConditionVariable;
class Mutex;
class Cursor;
class Icon;
class VideoMode;
class Window;
class WindowImpl
{
public:
WindowImpl(Window* parent);
WindowImpl(const WindowImpl&) = delete;
WindowImpl(WindowImpl&&) = delete; ///TODO?
~WindowImpl();
bool Create(const VideoMode& mode, const String& title, WindowStyleFlags style);
bool Create(WindowHandle handle);
void Destroy();
void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable);
WindowHandle GetHandle() const;
unsigned int GetHeight() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
WindowStyleFlags GetStyle() const;
String GetTitle() const;
unsigned int GetWidth() const;
bool HasFocus() const;
void IgnoreNextMouseEvent(int mouseX, int mouseY);
bool IsMinimized() const;
bool IsVisible() const;
void RefreshCursor();
void ProcessEvents(bool block);
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 String& title);
void SetVisible(bool visible);
WindowImpl& operator=(const WindowImpl&) = delete;
WindowImpl& operator=(WindowImpl&&) = delete; ///TODO?
static bool Initialize();
static void Uninitialize();
private:
void CleanUp();
xcb_keysym_t ConvertKeyCodeToKeySym(xcb_keycode_t keycode, uint16_t state);
Keyboard::Key ConvertVirtualKey(xcb_keysym_t symbol);
void CommonInitialize();
char32_t GetRepresentation(xcb_keysym_t keysym) const;
void ProcessEvent(xcb_generic_event_t* windowEvent);
void ResetVideoMode();
void SetMotifHints();
void SetVideoMode(const VideoMode& mode);
void SwitchToFullscreen();
bool UpdateNormalHints();
void UpdateEventQueue(xcb_generic_event_t* event);
static void WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
xcb_window_t m_window;
xcb_screen_t* m_screen;
xcb_randr_get_screen_info_reply_t m_oldVideoMode;
xcb_size_hints_t m_size_hints;
Thread m_thread;
WindowStyleFlags m_style;
Window* m_parent;
bool m_eventListener;
bool m_ownsWindow;
bool m_smoothScrolling;
bool m_threadActive;
Vector2i m_mousePos;
bool m_keyRepeat;
struct
{
xcb_generic_event_t* curr = nullptr;
xcb_generic_event_t* next = nullptr;
} m_eventQueue;
};
}
#endif // NAZARA_WINDOWIMPL_HPP

View File

@@ -12,19 +12,10 @@
#include <memory>
#include <vector>
#if defined(NAZARA_PLATFORM_SDL2)
#include <Nazara/Renderer/SDL2/ContextImpl.hpp>
#include <Nazara/Renderer/SDL2/ContextImpl.hpp>
#if defined(NAZARA_PLATFORM_LINUX)
#define CALLBACK
#endif
#elif defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
#elif defined(NAZARA_PLATFORM_GLX)
#include <Nazara/Renderer/GLX/ContextImpl.hpp>
#if defined(NAZARA_PLATFORM_LINUX)
#define CALLBACK
#else
#error Lack of implementation: Context
#endif
#include <Nazara/Renderer/Debug.hpp>

View File

@@ -1,300 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
#include <Nazara/Renderer/GLX/ContextImpl.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Debug.hpp>
using namespace GLX;
namespace Nz
{
namespace
{
Display* m_display;
int m_sharedDisplay = 0;
bool ctxErrorOccurred = false;
int ctxErrorHandler( Display* /*dpy*/, XErrorEvent* /*ev*/ )
{
ctxErrorOccurred = true;
return 0;
}
}
ContextImpl::ContextImpl() :
m_colormap(0),
m_context(0),
m_window(0),
m_ownsWindow(false)
{
if (m_sharedDisplay == 0)
m_display = XOpenDisplay(nullptr);
++m_sharedDisplay;
}
ContextImpl::~ContextImpl()
{
Destroy();
if (--m_sharedDisplay == 0)
{
XCloseDisplay(m_display);
m_display = nullptr;
}
}
bool ContextImpl::Activate() const
{
return glXMakeCurrent(m_display, m_window, m_context) == true;
}
bool ContextImpl::Create(ContextParameters& parameters)
{
// En cas d'exception, la ressource sera quand même libérée
CallOnExit onExit([this] ()
{
Destroy();
});
// Get a matching FB config
static int visual_attribs[] =
{
GLX_X_RENDERABLE, True,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_BUFFER_SIZE, parameters.bitsPerPixel,
GLX_ALPHA_SIZE, (parameters.bitsPerPixel == 32) ? 8 : 0,
GLX_DEPTH_SIZE, parameters.depthBits,
GLX_STENCIL_SIZE, parameters.stencilBits,
GLX_DOUBLEBUFFER, True,
GLX_SAMPLE_BUFFERS, (parameters.antialiasingLevel > 0) ? True : False,
GLX_SAMPLES, parameters.antialiasingLevel,
None
};
int glx_major = 0;
int glx_minor = 0;
// FBConfigs were added in GLX version 1.3.
if (!glXQueryVersion(m_display, &glx_major, &glx_minor) || ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1))
{
NazaraError("Invalid GLX version, version > 1.3 is required.");
return false;
}
int fbcount;
GLXFBConfig* fbc = glXChooseFBConfig(m_display, XDefaultScreen(m_display), visual_attribs, &fbcount);
if (!fbc)
{
NazaraError("Failed to retrieve a framebuffer config");
return false;
}
// Pick the FB config/visual with the most samples per pixel
int best_fbc = -1;
int worst_fbc = -1;
int best_num_samp = -1;
int worst_num_samp = 999;
for (int i = 0; i < fbcount; ++i)
{
XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, fbc[i]);
if (vi)
{
int samp_buf = 0, samples = 0;
glXGetFBConfigAttrib(m_display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
glXGetFBConfigAttrib(m_display, fbc[i], GLX_SAMPLES , &samples );
if ((best_fbc < 0) || (samp_buf && (samples > best_num_samp)))
{
best_fbc = i;
best_num_samp = samples;
}
if ((worst_fbc < 0) || !samp_buf || (samples < worst_num_samp))
{
worst_fbc = i;
worst_num_samp = samples;
}
}
XFree(vi);
}
GLXFBConfig bestFbc = fbc[best_fbc];
// Be sure to free the FBConfig list allocated by glXChooseFBConfig()
XFree(fbc);
// Get a visual
XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, bestFbc);
if (!vi)
{
NazaraError("Failed to get best VisualInfo");
return false;
}
// If context is shared by multiple windows
if (parameters.window)
{
m_window = parameters.window;
m_ownsWindow = false;
}
else
{
XSetWindowAttributes swa;
swa.colormap = m_colormap = XCreateColormap(
m_display,
XRootWindow(
m_display,
vi->screen),
vi->visual,
AllocNone
);
swa.background_pixmap = None;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
if (!m_colormap)
{
NazaraError("Failed to create colormap for context");
return false;
}
m_window = XCreateWindow(
m_display,
XRootWindow(
m_display,
vi->screen),
0, 0, // X, Y
1, 1, // W H
0,
vi->depth,
InputOutput,
vi->visual,
CWBorderPixel | CWColormap | CWEventMask,
&swa
);
m_ownsWindow = true;
}
if (!m_window)
{
NazaraError("Failed to create window");
return false;
}
// Done with the visual info data
XFree(vi);
// Install an X error handler so the application won't exit if GL 3.0
// context allocation fails.
//
// Note this error handler is global. All display connections in all threads
// of a process use the same error handler, so be sure to guard against other
// threads issuing X commands while this code is running.
ctxErrorOccurred = false;
int (*oldHandler)(Display*, XErrorEvent*) =
XSetErrorHandler(&ctxErrorHandler);
// Check for the GLX_ARB_create_context extension string and the function.
// If either is not present, use GLX 1.3 context creation method.
if (!glXCreateContextAttribs)
{
NazaraWarning("glXCreateContextAttribs() not found. Using old-style GLX context");
m_context = glXCreateNewContext(m_display, bestFbc, GLX_RGBA_TYPE, parameters.shared ? parameters.shareContext->m_impl->m_context : 0, True);
}
// If it does, try to get a GL 3.0 context!
else
{
int profile = parameters.compatibilityProfile ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
int debug = parameters.debugMode ? GLX_CONTEXT_DEBUG_BIT_ARB : 0;
int major = 3;//parameters.majorVersion;
int minor = 3;//parameters.minorVersion;
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, major,
GLX_CONTEXT_MINOR_VERSION_ARB, minor,
GLX_CONTEXT_PROFILE_MASK_ARB, profile,
GLX_CONTEXT_FLAGS_ARB, debug,
None, None
};
m_context = glXCreateContextAttribs(
m_display,
bestFbc,
parameters.shared ? parameters.shareContext->m_impl->m_context : 0,
True,
context_attribs
);
}
// Sync to ensure any errors generated are processed.
XSync(m_display, False);
XSetErrorHandler(oldHandler);
if (ctxErrorOccurred || !m_context)
{
NazaraError("Failed to create context, check the version");
return false;
}
onExit.Reset();
return true;
}
void ContextImpl::Destroy()
{
// Destroy the context
if (m_context)
{
if (glXGetCurrentContext() == m_context)
glXMakeCurrent(m_display, None, nullptr);
glXDestroyContext(m_display, m_context);
m_context = nullptr;
}
// Destroy the window if we own it
if (m_ownsWindow && m_window)
{
XFreeColormap(m_display, m_colormap);
XDestroyWindow(m_display, m_window);
m_ownsWindow = false;
m_window = 0;
XFlush(m_display);
}
}
void ContextImpl::EnableVerticalSync(bool enabled)
{
if (glXSwapIntervalEXT)
glXSwapIntervalEXT(m_display, glXGetCurrentDrawable(), enabled ? 1 : 0);
else if (NzglXSwapIntervalMESA)
NzglXSwapIntervalMESA(enabled ? 1 : 0);
else if (glXSwapIntervalSGI)
glXSwapIntervalSGI(enabled ? 1 : 0);
else
NazaraError("Vertical sync not supported");
}
void ContextImpl::SwapBuffers()
{
if (m_window)
glXSwapBuffers(m_display, m_window);
}
bool ContextImpl::Desactivate()
{
return glXMakeCurrent(m_display, None, nullptr) == true;
}
}

View File

@@ -1,42 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CONTEXTIMPL_HPP
#define NAZARA_CONTEXTIMPL_HPP
#include <Nazara/Renderer/OpenGL.hpp>
namespace Nz
{
struct ContextParameters;
class ContextImpl
{
public:
ContextImpl();
~ContextImpl();
bool Activate() const;
bool Create(ContextParameters& parameters);
void Destroy();
void EnableVerticalSync(bool enabled);
void SwapBuffers();
static bool Desactivate();
private:
GLX::Colormap m_colormap;
GLX::GLXContext m_context;
GLX::Window m_window;
bool m_ownsWindow;
};
}
#endif // NAZARA_CONTEXTIMPL_HPP

View File

@@ -9,11 +9,7 @@
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#if defined(NAZARA_PLATFORM_SDL2)
#include <SDL2/SDL_video.h>
#elif defined(NAZARA_PLATFORM_GLX)
#include <Nazara/Platform/X11/Display.hpp>
#endif // NAZARA_PLATFORM_GLX
#include <Nazara/Renderer/Debug.hpp>
#include <set>
#include <sstream>
@@ -30,17 +26,7 @@ namespace Nz
OpenGLFunc LoadEntry(const char* name, bool launchException = true)
{
#if defined(NAZARA_PLATFORM_SDL2)
OpenGLFunc entry = reinterpret_cast<OpenGLFunc>(SDL_GL_GetProcAddress(name));
#elif defined(NAZARA_PLATFORM_WINDOWS)
OpenGLFunc entry = reinterpret_cast<OpenGLFunc>(wglGetProcAddress(name));
if (!entry) // wglGetProcAddress ne fonctionne pas sur les fonctions OpenGL <= 1.1
entry = reinterpret_cast<OpenGLFunc>(GetProcAddress(openGLlibrary, name));
#elif defined(NAZARA_PLATFORM_GLX)
OpenGLFunc entry = reinterpret_cast<OpenGLFunc>(GLX::glXGetProcAddress(reinterpret_cast<const unsigned char*>(name)));
#else
#error OS not handled
#endif
if (!entry && launchException)
{
@@ -55,31 +41,19 @@ namespace Nz
bool LoadLibrary()
{
#if defined(NAZARA_PLATFORM_SDL2)
if (SDL_GL_LoadLibrary(nullptr) != 0)
{
NazaraError(SDL_GetError());
return false;
}
return true;
#elif defined(NAZARA_PLATFORM_WINDOWS)
openGLlibrary = ::LoadLibraryA("opengl32.dll");
return openGLlibrary != nullptr;
#else
return true;
#endif
}
void UnloadLibrary()
{
#if defined(NAZARA_PLATFORM_SDL2)
SDL_GL_UnloadLibrary();
#elif defined(NAZARA_PLATFORM_WINDOWS)
FreeLibrary(openGLlibrary);
#endif
}
enum GarbageResourceType
@@ -742,20 +716,9 @@ namespace Nz
if (s_initialized)
return true;
#if defined(NAZARA_PLATFORM_SDL2)
if (SDL_VideoInit(NULL) != 0)
NazaraError(SDL_GetError());
#elif defined(NAZARA_PLATFORM_GLX)
Initializer<X11> display;
if (!display)
{
NazaraError("Failed to load display library");
return false;
}
#endif
if (!LoadLibrary())
{
NazaraError("Failed to load OpenGL library");
@@ -783,11 +746,6 @@ namespace Nz
/****************************Chargement OpenGL****************************/
///FIXME: I'm really thinking this is a mistake and GLX has no need to be initialized differently (Lynix)
#if defined(NAZARA_PLATFORM_LINUX) && not defined(NAZARA_PLATFORM_SDL2)
glXCreateContextAttribs = reinterpret_cast<GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC>(LoadEntry("glXCreateContextAttribsARB", false));
#endif
Context loadContext;
if (!loadContext.Create(parameters))
{
@@ -795,13 +753,6 @@ namespace Nz
return false;
}
#if defined(NAZARA_PLATFORM_WINDOWS) && not defined(NAZARA_PLATFORM_SDL2)
wglCreateContextAttribs = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(LoadEntry("wglCreateContextAttribsARB", false));
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(LoadEntry("wglChoosePixelFormatARB", false));
if (!wglChoosePixelFormat)
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATEXTPROC>(LoadEntry("wglChoosePixelFormatEXT", false));
#endif
// Récupération de la version d'OpenGL et du GLSL
// Ce code se base sur le fait que la carte graphique renverra un contexte de compatibilité avec la plus haute version supportée
// Ce qui semble vrai chez AMD, NVidia et Intel, mais j'aimerai une preuve que ça sera toujours le cas...
@@ -1047,16 +998,6 @@ namespace Nz
glInvalidateBufferData = reinterpret_cast<PFNGLINVALIDATEBUFFERDATAPROC>(LoadEntry("glInvalidateBufferData", false));
glVertexAttribLPointer = reinterpret_cast<PFNGLVERTEXATTRIBLPOINTERPROC>(LoadEntry("glVertexAttribLPointer", false));
#if defined(NAZARA_PLATFORM_WINDOWS)
wglGetExtensionsStringARB = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(LoadEntry("wglGetExtensionsStringARB", false));
wglGetExtensionsStringEXT = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGEXTPROC>(LoadEntry("wglGetExtensionsStringEXT", false));
wglSwapInterval = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(LoadEntry("wglSwapIntervalEXT", false));
#elif defined(NAZARA_PLATFORM_GLX)
glXSwapIntervalEXT = reinterpret_cast<GLX::PFNGLXSWAPINTERVALEXTPROC>(LoadEntry("glXSwapIntervalEXT", false));
NzglXSwapIntervalMESA = reinterpret_cast<GLX::PFNGLXSWAPINTERVALMESAPROC>(LoadEntry("glXSwapIntervalMESA", false));
glXSwapIntervalSGI = reinterpret_cast<GLX::PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
#endif
if (!glGetStringi || !LoadExtensions3())
{
NazaraWarning("Failed to load OpenGL 3 extension system, falling back to OpenGL 2 extension system...");
@@ -1065,21 +1006,6 @@ namespace Nz
NazaraWarning("Failed to load extension system");
}
#if defined(NAZARA_PLATFORM_WINDOWS) && !defined(NAZARA_PLATFORM_SDL2)
{
bool loaded;
if (wglGetExtensionsStringARB)
loaded = LoadExtensionsString(reinterpret_cast<const char*>(wglGetExtensionsStringARB(wglGetCurrentDC())));
else if (wglGetExtensionsStringEXT)
loaded = LoadExtensionsString(reinterpret_cast<const char*>(wglGetExtensionsStringEXT()));
else
loaded = false;
if (!loaded)
NazaraWarning("Failed to load wgl extension string");
}
#endif
// AnisotropicFilter
s_openGLextensions[OpenGLExtension_AnisotropicFilter] = IsSupported("GL_EXT_texture_filter_anisotropic");
@@ -1248,11 +1174,7 @@ namespace Nz
bool OpenGL::IsSupported(const String& string)
{
#ifdef NAZARA_PLATFORM_SDL2
return SDL_GL_ExtensionSupported(string.GetConstBuffer());
#else
return s_openGLextensionSet.find(string) != s_openGLextensionSet.end();
#endif
}
void OpenGL::SetBuffer(BufferType type, GLuint id)
@@ -2306,18 +2228,4 @@ namespace Nz
PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = nullptr;
PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer = nullptr;
PFNGLVIEWPORTPROC glViewport = nullptr;
#if defined(NAZARA_PLATFORM_WINDOWS)
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat = nullptr;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr;
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr;
PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr;
#elif defined(NAZARA_PLATFORM_GLX)
GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr;
GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA = nullptr;
GLX::PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
#endif
}

View File

@@ -1,248 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <cstring>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
ContextImpl::ContextImpl()
{
}
bool ContextImpl::Activate() const
{
return wglMakeCurrent(m_deviceContext, m_context) == TRUE;
}
bool ContextImpl::Create(ContextParameters& parameters)
{
if (parameters.window)
{
m_window = static_cast<HWND>(parameters.window);
m_ownsWindow = false;
}
else
{
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
if (!m_window)
{
NazaraError("Failed to create window");
return false;
}
ShowWindow(m_window, SW_HIDE);
m_ownsWindow = true;
}
// En cas d'exception, la ressource sera quand même libérée
CallOnExit onExit([this] ()
{
Destroy();
});
m_deviceContext = GetDC(m_window);
if (!m_deviceContext)
{
NazaraError("Failed to get device context");
return false;
}
int pixelFormat = 0;
if (parameters.antialiasingLevel > 0)
{
if (wglChoosePixelFormat)
{
bool valid;
UINT numFormats;
int attributes[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel,
WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0,
WGL_DEPTH_BITS_ARB, parameters.depthBits,
WGL_STENCIL_BITS_ARB, parameters.stencilBits,
WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, parameters.antialiasingLevel,
0, 0
};
do
{
valid = (wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats) == TRUE);
}
while ((!valid || numFormats == 0) && --attributes[19] > 0);
if (!valid)
{
NazaraWarning("Could not find a format matching requirements, disabling antialiasing...");
pixelFormat = 0;
}
parameters.antialiasingLevel = attributes[19];
}
else
{
NazaraWarning("Antialiasing is not supported");
parameters.antialiasingLevel = 0;
}
}
PIXELFORMATDESCRIPTOR descriptor;
ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR));
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
descriptor.nVersion = 1;
if (pixelFormat == 0)
{
descriptor.cColorBits = parameters.bitsPerPixel;
descriptor.cDepthBits = parameters.depthBits;
descriptor.cStencilBits = parameters.stencilBits;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
descriptor.iPixelType = PFD_TYPE_RGBA;
if (parameters.bitsPerPixel == 32)
descriptor.cAlphaBits = 8;
if (parameters.doubleBuffered)
descriptor.dwFlags |= PFD_DOUBLEBUFFER;
pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
if (pixelFormat == 0)
{
NazaraError("Failed to choose pixel format");
return false;
}
}
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
{
NazaraError("Failed to set pixel format");
return false;
}
// Arrivé ici, le format de pixel est choisi, nous récupérons donc les paramètres réels du futur contexte
if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0)
{
parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
parameters.depthBits = descriptor.cDepthBits;
parameters.stencilBits = descriptor.cDepthBits;
}
else
NazaraWarning("Failed to get context's parameters");
HGLRC shareContext = (parameters.shared) ? static_cast<ContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr;
m_context = nullptr;
if (wglCreateContextAttribs)
{
int attributes[4*2+1];
int* attrib = attributes;
*attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
*attrib++ = parameters.majorVersion;
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
*attrib++ = parameters.minorVersion;
if (parameters.majorVersion >= 3)
{
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
*attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
// Les contextes forward-compatible ne sont plus utilisés pour cette raison :
// http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile
}
if (parameters.debugMode)
{
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
*attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB;
}
*attrib++ = 0;
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
}
if (!m_context)
{
m_context = wglCreateContext(m_deviceContext);
if (shareContext)
{
// wglShareLists n'est pas thread-safe (source: SFML)
static Mutex mutex;
LockGuard lock(mutex);
if (!wglShareLists(shareContext, m_context))
NazaraWarning("Failed to share the context: " + Error::GetLastSystemError());
}
}
if (!m_context)
{
NazaraError("Failed to create context");
return false;
}
onExit.Reset();
return true;
}
void ContextImpl::Destroy()
{
if (m_context)
{
if (wglGetCurrentContext() == m_context)
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(m_context);
m_context = nullptr;
}
if (m_deviceContext)
{
ReleaseDC(m_window, m_deviceContext);
m_deviceContext = nullptr;
}
if (m_ownsWindow)
{
DestroyWindow(m_window);
m_window = nullptr;
}
}
void ContextImpl::EnableVerticalSync(bool enabled)
{
if (wglSwapInterval)
wglSwapInterval(enabled ? 1 : 0);
else
NazaraError("Vertical sync not supported");
}
void ContextImpl::SwapBuffers()
{
::SwapBuffers(m_deviceContext);
}
bool ContextImpl::Desactivate()
{
return wglMakeCurrent(nullptr, nullptr) == TRUE;
}
}

View File

@@ -1,41 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CONTEXTIMPL_HPP
#define NAZARA_CONTEXTIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
#include <windows.h>
namespace Nz
{
class ContextImpl
{
public:
ContextImpl();
bool Activate() const;
bool Create(ContextParameters& parameters);
void Destroy();
void EnableVerticalSync(bool enabled);
void SwapBuffers();
static bool Desactivate();
private:
HDC m_deviceContext;
HGLRC m_context;
HWND m_window;
bool m_ownsWindow;
};
}
#endif // NAZARA_CONTEXTIMPL_HPP