Switch from Nz prefix to namespace Nz for linux
Former-commit-id: 64eeaf3c633254b04910ebd4576fd9e910002be0
This commit is contained in:
parent
752518ef14
commit
37586e7283
|
|
@ -116,6 +116,7 @@
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__linux__) || defined(__unix__)
|
#elif defined(__linux__) || defined(__unix__)
|
||||||
#define NAZARA_PLATFORM_LINUX
|
#define NAZARA_PLATFORM_LINUX
|
||||||
|
#define NAZARA_PLATFORM_GLX
|
||||||
#define NAZARA_PLATFORM_POSIX
|
#define NAZARA_PLATFORM_POSIX
|
||||||
#define NAZARA_PLATFORM_X11
|
#define NAZARA_PLATFORM_X11
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@
|
||||||
#include <GL3/glext.h>
|
#include <GL3/glext.h>
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <GL3/wglext.h>
|
#include <GL3/wglext.h>
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_GLX)
|
||||||
namespace GLX
|
namespace GLX
|
||||||
{
|
{
|
||||||
#include <GL3/glx.h>
|
#include <GL/glx.h> // Defined in a namespace to avoid conflict
|
||||||
}
|
}
|
||||||
#include <GL3/glxext.h>
|
#include <GL3/glxext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -329,7 +329,7 @@ NAZARA_RENDERER_API extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAtt
|
||||||
NAZARA_RENDERER_API extern PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
|
NAZARA_RENDERER_API extern PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
|
||||||
NAZARA_RENDERER_API extern PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT;
|
NAZARA_RENDERER_API extern PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT;
|
||||||
NAZARA_RENDERER_API extern PFNWGLSWAPINTERVALEXTPROC wglSwapInterval;
|
NAZARA_RENDERER_API extern PFNWGLSWAPINTERVALEXTPROC wglSwapInterval;
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_GLX)
|
||||||
NAZARA_RENDERER_API extern GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
|
NAZARA_RENDERER_API extern GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
|
||||||
NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
|
NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
|
||||||
NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA;
|
NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA;
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,16 @@
|
||||||
#define NAZARA_WINDOWHANDLE_HPP
|
#define NAZARA_WINDOWHANDLE_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#if defined(NAZARA_PLATFORM_X11)
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
// http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx
|
// http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx
|
||||||
typedef void* WindowHandle;
|
typedef void* WindowHandle;
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_X11)
|
||||||
#include <xcb/xcb.h>
|
|
||||||
// http://en.wikipedia.org/wiki/Xlib#Data_types
|
// http://en.wikipedia.org/wiki/Xlib#Data_types
|
||||||
using WindowHandle = xcb_window_t;
|
using WindowHandle = xcb_window_t;
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@
|
||||||
|
|
||||||
void* operator new(std::size_t size)
|
void* operator new(std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, false);
|
return Nz::MemoryManager::Allocate(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](std::size_t size)
|
void* operator new[](std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, true);
|
return Nz::MemoryManager::Allocate(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* pointer) noexcept
|
void operator delete(void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, false);
|
Nz::MemoryManager::Free(pointer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* pointer) noexcept
|
void operator delete[](void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, true);
|
Nz::MemoryManager::Free(pointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_AUDIO_MANAGE_MEMORY
|
#endif // NAZARA_AUDIO_MANAGE_MEMORY
|
||||||
|
|
|
||||||
|
|
@ -8,21 +8,24 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
bool NzClockImplInitializeHighPrecision()
|
namespace Nz
|
||||||
{
|
{
|
||||||
return true; // No initialization needed
|
bool ClockImplInitializeHighPrecision()
|
||||||
}
|
{
|
||||||
|
return true; // No initialization needed
|
||||||
|
}
|
||||||
|
|
||||||
nzUInt64 NzClockImplGetMicroseconds()
|
UInt64 ClockImplGetElapsedMicroseconds()
|
||||||
{
|
{
|
||||||
timeval clock;
|
timeval clock;
|
||||||
gettimeofday(&clock, nullptr);
|
gettimeofday(&clock, nullptr);
|
||||||
return static_cast<nzUInt64>(clock.tv_sec*1000000 + clock.tv_usec);
|
return static_cast<UInt64>(clock.tv_sec*1000000 + clock.tv_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
nzUInt64 NzClockImplGetMilliseconds()
|
UInt64 ClockImplGetElapsedMilliseconds()
|
||||||
{
|
{
|
||||||
timeval clock;
|
timeval clock;
|
||||||
gettimeofday(&clock, nullptr);
|
gettimeofday(&clock, nullptr);
|
||||||
return static_cast<nzUInt64>(clock.tv_sec*1000 + (clock.tv_usec/1000));
|
return static_cast<UInt64>(clock.tv_sec*1000 + (clock.tv_usec/1000));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,11 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
|
||||||
bool NzClockImplInitializeHighPrecision();
|
namespace Nz
|
||||||
nzUInt64 NzClockImplGetMicroseconds();
|
{
|
||||||
nzUInt64 NzClockImplGetMilliseconds();
|
bool ClockImplInitializeHighPrecision();
|
||||||
|
UInt64 ClockImplGetElapsedMicroseconds();
|
||||||
|
UInt64 ClockImplGetElapsedMilliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_CLOCKIMPL_POSIX_HPP
|
#endif // NAZARA_CLOCKIMPL_POSIX_HPP
|
||||||
|
|
|
||||||
|
|
@ -6,42 +6,45 @@
|
||||||
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
NzConditionVariableImpl::NzConditionVariableImpl()
|
namespace Nz
|
||||||
{
|
{
|
||||||
pthread_cond_init(&m_cv, nullptr);
|
ConditionVariableImpl::ConditionVariableImpl()
|
||||||
}
|
{
|
||||||
|
pthread_cond_init(&m_cv, nullptr);
|
||||||
NzConditionVariableImpl::~NzConditionVariableImpl()
|
}
|
||||||
{
|
|
||||||
pthread_cond_destroy(&m_cv);
|
ConditionVariableImpl::~ConditionVariableImpl()
|
||||||
}
|
{
|
||||||
|
pthread_cond_destroy(&m_cv);
|
||||||
void NzConditionVariableImpl::Signal()
|
}
|
||||||
{
|
|
||||||
pthread_cond_signal(&m_cv);
|
void ConditionVariableImpl::Signal()
|
||||||
}
|
{
|
||||||
|
pthread_cond_signal(&m_cv);
|
||||||
void NzConditionVariableImpl::SignalAll()
|
}
|
||||||
{
|
|
||||||
pthread_cond_broadcast(&m_cv);
|
void ConditionVariableImpl::SignalAll()
|
||||||
}
|
{
|
||||||
|
pthread_cond_broadcast(&m_cv);
|
||||||
void NzConditionVariableImpl::Wait(NzMutexImpl* mutex)
|
}
|
||||||
{
|
|
||||||
pthread_cond_wait(&m_cv, &mutex->m_handle);
|
void ConditionVariableImpl::Wait(MutexImpl* mutex)
|
||||||
}
|
{
|
||||||
|
pthread_cond_wait(&m_cv, &mutex->m_handle);
|
||||||
bool NzConditionVariableImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout)
|
}
|
||||||
{
|
|
||||||
// get the current time
|
bool ConditionVariableImpl::Wait(MutexImpl* mutex, UInt32 timeout)
|
||||||
timeval tv;
|
{
|
||||||
gettimeofday(&tv, nullptr);
|
// get the current time
|
||||||
|
timeval tv;
|
||||||
// construct the time limit (current time + time to wait)
|
gettimeofday(&tv, nullptr);
|
||||||
timespec ti;
|
|
||||||
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
|
// construct the time limit (current time + time to wait)
|
||||||
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
timespec ti;
|
||||||
ti.tv_nsec %= 1000000000;
|
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
|
||||||
|
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
||||||
return pthread_cond_timedwait(&m_cv,&mutex->m_handle, &ti) != 0;
|
ti.tv_nsec %= 1000000000;
|
||||||
|
|
||||||
|
return pthread_cond_timedwait(&m_cv,&mutex->m_handle, &ti) != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,25 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
class NzMutexImpl;
|
namespace Nz
|
||||||
|
|
||||||
class NzConditionVariableImpl
|
|
||||||
{
|
{
|
||||||
public:
|
class MutexImpl;
|
||||||
NzConditionVariableImpl();
|
|
||||||
~NzConditionVariableImpl();
|
|
||||||
|
|
||||||
void Signal();
|
class ConditionVariableImpl
|
||||||
void SignalAll();
|
{
|
||||||
|
public:
|
||||||
|
ConditionVariableImpl();
|
||||||
|
~ConditionVariableImpl();
|
||||||
|
|
||||||
void Wait(NzMutexImpl* mutex);
|
void Signal();
|
||||||
bool Wait(NzMutexImpl* mutex, nzUInt32 timeout);
|
void SignalAll();
|
||||||
|
|
||||||
private:
|
void Wait(MutexImpl* mutex);
|
||||||
pthread_cond_t m_cv;
|
bool Wait(MutexImpl* mutex, UInt32 timeout);
|
||||||
};
|
|
||||||
|
private:
|
||||||
|
pthread_cond_t m_cv;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP
|
#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -9,95 +9,98 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
NzDirectoryImpl::NzDirectoryImpl(const NzDirectory* parent)
|
namespace Nz
|
||||||
{
|
{
|
||||||
NazaraUnused(parent);
|
DirectoryImpl::DirectoryImpl(const Directory* parent)
|
||||||
}
|
{
|
||||||
|
NazaraUnused(parent);
|
||||||
|
}
|
||||||
|
|
||||||
void NzDirectoryImpl::Close()
|
void DirectoryImpl::Close()
|
||||||
{
|
{
|
||||||
closedir(m_handle);
|
closedir(m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzString NzDirectoryImpl::GetResultName() const
|
String DirectoryImpl::GetResultName() const
|
||||||
{
|
{
|
||||||
return m_result->d_name;
|
return m_result->d_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
nzUInt64 NzDirectoryImpl::GetResultSize() const
|
UInt64 DirectoryImpl::GetResultSize() const
|
||||||
{
|
{
|
||||||
struct stat64 resulststat;
|
struct stat64 resulststat;
|
||||||
stat64(m_result->d_name, &resulststat);
|
stat64(m_result->d_name, &resulststat);
|
||||||
|
|
||||||
return static_cast<nzUInt64>(resulststat.st_size);
|
return static_cast<UInt64>(resulststat.st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzDirectoryImpl::IsResultDirectory() const
|
bool DirectoryImpl::IsResultDirectory() const
|
||||||
{
|
{
|
||||||
struct stat64 filestats;
|
struct stat64 filestats;
|
||||||
if (stat64(m_result->d_name, &filestats) == -1) // error
|
if (stat64(m_result->d_name, &filestats) == -1) // error
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return S_ISDIR(filestats.st_mode);
|
return S_ISDIR(filestats.st_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DirectoryImpl::NextResult()
|
||||||
|
{
|
||||||
|
if ((m_result = readdir64(m_handle)))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (errno != ENOENT)
|
||||||
|
NazaraError("Unable to get next result: " + Error::GetLastSystemError());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirectoryImpl::Open(const String& dirPath)
|
||||||
|
{
|
||||||
|
m_handle = opendir(dirPath.GetConstBuffer());
|
||||||
|
if (!m_handle)
|
||||||
|
{
|
||||||
|
NazaraError("Unable to open directory: " + Error::GetLastSystemError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NzDirectoryImpl::NextResult()
|
|
||||||
{
|
|
||||||
if ((m_result = readdir64(m_handle)))
|
|
||||||
return true;
|
return true;
|
||||||
else
|
|
||||||
{
|
|
||||||
if (errno != ENOENT)
|
|
||||||
NazaraError("Unable to get next result: " + NzError::GetLastSystemError());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzDirectoryImpl::Open(const NzString& dirPath)
|
|
||||||
{
|
|
||||||
m_handle = opendir(dirPath.GetConstBuffer());
|
|
||||||
if (!m_handle)
|
|
||||||
{
|
|
||||||
NazaraError("Unable to open directory: " + NzError::GetLastSystemError());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
bool DirectoryImpl::Create(const String& dirPath)
|
||||||
}
|
{
|
||||||
|
mode_t permissions; // TODO: check permissions
|
||||||
bool NzDirectoryImpl::Create(const NzString& dirPath)
|
|
||||||
{
|
return mkdir(dirPath.GetConstBuffer(), permissions) != -1;;
|
||||||
mode_t permissions; // TODO: check permissions
|
}
|
||||||
|
|
||||||
return mkdir(dirPath.GetConstBuffer(), permissions) != -1;;
|
bool DirectoryImpl::Exists(const String& dirPath)
|
||||||
}
|
{
|
||||||
|
struct stat64 filestats;
|
||||||
bool NzDirectoryImpl::Exists(const NzString& dirPath)
|
if (stat64(dirPath.GetConstBuffer(), &filestats) == -1) // error
|
||||||
{
|
return false;
|
||||||
struct stat64 filestats;
|
|
||||||
if (stat64(dirPath.GetConstBuffer(), &filestats) == -1) // error
|
return S_ISDIR(filestats.st_mode) || S_ISREG(filestats.st_mode);
|
||||||
return false;
|
}
|
||||||
|
|
||||||
return S_ISDIR(filestats.st_mode) || S_ISREG(filestats.st_mode);
|
String DirectoryImpl::GetCurrent()
|
||||||
}
|
{
|
||||||
|
String currentPath;
|
||||||
NzString NzDirectoryImpl::GetCurrent()
|
|
||||||
{
|
char path[MAXPATHLEN];
|
||||||
NzString currentPath;
|
if (getcwd(path, MAXPATHLEN))
|
||||||
|
currentPath = path;
|
||||||
char path[MAXPATHLEN];
|
else
|
||||||
if (getcwd(path, MAXPATHLEN))
|
NazaraError("Unable to get current directory: " + Error::GetLastSystemError()); // Bug: initialisation -> if no path for log !
|
||||||
currentPath = path;
|
|
||||||
else
|
return currentPath;
|
||||||
NazaraError("Unable to get current directory: " + NzError::GetLastSystemError()); // Bug: initialisation -> if no path for log !
|
}
|
||||||
|
|
||||||
return currentPath;
|
bool DirectoryImpl::Remove(const String& dirPath)
|
||||||
}
|
{
|
||||||
|
bool success = rmdir(dirPath.GetConstBuffer()) != -1;
|
||||||
bool NzDirectoryImpl::Remove(const NzString& dirPath)
|
|
||||||
{
|
return success;
|
||||||
bool success = rmdir(dirPath.GetConstBuffer()) != -1;
|
}
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,40 +8,47 @@
|
||||||
#define NAZARA_DIRECTORYIMPL_HPP
|
#define NAZARA_DIRECTORYIMPL_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/NonCopyable.hpp>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
class NzDirectory;
|
namespace Nz
|
||||||
class NzString;
|
|
||||||
|
|
||||||
class NzDirectoryImpl : NzNonCopyable
|
|
||||||
{
|
{
|
||||||
public:
|
class Directory;
|
||||||
NzDirectoryImpl(const NzDirectory* parent);
|
class String;
|
||||||
~NzDirectoryImpl() = default;
|
|
||||||
|
|
||||||
void Close();
|
class DirectoryImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DirectoryImpl(const Directory* parent);
|
||||||
|
DirectoryImpl(const DirectoryImpl&) = delete;
|
||||||
|
DirectoryImpl(DirectoryImpl&&) = delete; ///TODO
|
||||||
|
~DirectoryImpl() = default;
|
||||||
|
|
||||||
NzString GetResultName() const;
|
void Close();
|
||||||
nzUInt64 GetResultSize() const;
|
|
||||||
|
|
||||||
bool IsResultDirectory() const;
|
String GetResultName() const;
|
||||||
|
UInt64 GetResultSize() const;
|
||||||
|
|
||||||
bool NextResult();
|
bool IsResultDirectory() const;
|
||||||
|
|
||||||
bool Open(const NzString& dirPath);
|
bool NextResult();
|
||||||
|
|
||||||
static bool Create(const NzString& dirPath);
|
bool Open(const String& dirPath);
|
||||||
static bool Exists(const NzString& dirPath);
|
|
||||||
static NzString GetCurrent();
|
|
||||||
static bool Remove(const NzString& dirPath);
|
|
||||||
|
|
||||||
private:
|
DirectoryImpl& operator=(const DirectoryImpl&) = delete;
|
||||||
DIR* m_handle;
|
DirectoryImpl& operator=(DirectoryImpl&&) = delete; ///TODO
|
||||||
dirent64* m_result;
|
|
||||||
};
|
static bool Create(const String& dirPath);
|
||||||
|
static bool Exists(const String& dirPath);
|
||||||
|
static String GetCurrent();
|
||||||
|
static bool Remove(const String& dirPath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DIR* m_handle;
|
||||||
|
dirent64* m_result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_DIRECTORYIMPL_HPP
|
#endif // NAZARA_DIRECTORYIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -8,55 +8,58 @@
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
NzDynLibImpl::NzDynLibImpl(NzDynLib* parent)
|
namespace Nz
|
||||||
{
|
{
|
||||||
NazaraUnused(parent);
|
DynLibImpl::DynLibImpl(DynLib* parent)
|
||||||
}
|
|
||||||
|
|
||||||
NzDynLibFunc NzDynLibImpl::GetSymbol(const NzString& symbol, NzString* errorMessage) const
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Il n'est pas standard de cast un pointeur d'objet vers un pointeur de fonction.
|
|
||||||
Nous devons donc utiliser des techniques diaboliques venant du malin lui-même.. :D
|
|
||||||
Au moins ce n'est pas aussi terrible qu'un const_cast
|
|
||||||
-Lynix
|
|
||||||
*/
|
|
||||||
union
|
|
||||||
{
|
{
|
||||||
NzDynLibFunc func;
|
NazaraUnused(parent);
|
||||||
void* pointer;
|
}
|
||||||
} converter;
|
|
||||||
|
|
||||||
dlerror(); // Clear error flag
|
DynLibFunc DynLibImpl::GetSymbol(const String& symbol, String* errorMessage) const
|
||||||
|
|
||||||
converter.pointer = dlsym(m_handle, symbol.GetConstBuffer());
|
|
||||||
if (!converter.pointer)
|
|
||||||
*errorMessage = dlerror();
|
|
||||||
|
|
||||||
return converter.func;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzDynLibImpl::Load(const NzString& libraryPath, NzString* errorMessage)
|
|
||||||
{
|
|
||||||
NzString path = libraryPath;
|
|
||||||
|
|
||||||
unsigned int pos = path.FindLast(".so");
|
|
||||||
if (pos == NzString::npos || (path.GetLength() > pos+3 && path[pos+3] != '.'))
|
|
||||||
path += ".so";
|
|
||||||
|
|
||||||
dlerror(); // Clear error flag
|
|
||||||
m_handle = dlopen(path.GetConstBuffer(), RTLD_LAZY | RTLD_GLOBAL);
|
|
||||||
|
|
||||||
if (m_handle)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
*errorMessage = dlerror();
|
/*
|
||||||
return false;
|
Il n'est pas standard de cast un pointeur d'objet vers un pointeur de fonction.
|
||||||
|
Nous devons donc utiliser des techniques diaboliques venant du malin lui-même.. :D
|
||||||
|
Au moins ce n'est pas aussi terrible qu'un const_cast
|
||||||
|
-Lynix
|
||||||
|
*/
|
||||||
|
union
|
||||||
|
{
|
||||||
|
DynLibFunc func;
|
||||||
|
void* pointer;
|
||||||
|
} converter;
|
||||||
|
|
||||||
|
dlerror(); // Clear error flag
|
||||||
|
|
||||||
|
converter.pointer = dlsym(m_handle, symbol.GetConstBuffer());
|
||||||
|
if (!converter.pointer)
|
||||||
|
*errorMessage = dlerror();
|
||||||
|
|
||||||
|
return converter.func;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynLibImpl::Load(const String& libraryPath, String* errorMessage)
|
||||||
|
{
|
||||||
|
String path = libraryPath;
|
||||||
|
|
||||||
|
unsigned int pos = path.FindLast(".so");
|
||||||
|
if (pos == String::npos || (path.GetLength() > pos+3 && path[pos+3] != '.'))
|
||||||
|
path += ".so";
|
||||||
|
|
||||||
|
dlerror(); // Clear error flag
|
||||||
|
m_handle = dlopen(path.GetConstBuffer(), RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
|
||||||
|
if (m_handle)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*errorMessage = dlerror();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynLibImpl::Unload()
|
||||||
|
{
|
||||||
|
dlclose(m_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzDynLibImpl::Unload()
|
|
||||||
{
|
|
||||||
dlclose(m_handle);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,25 @@
|
||||||
#define NAZARA_DYNLIBIMPL_HPP
|
#define NAZARA_DYNLIBIMPL_HPP
|
||||||
|
|
||||||
#include <Nazara/Core/DynLib.hpp>
|
#include <Nazara/Core/DynLib.hpp>
|
||||||
#include <Nazara/Core/NonCopyable.hpp>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
class NzString;
|
namespace Nz
|
||||||
|
|
||||||
class NzDynLibImpl : NzNonCopyable
|
|
||||||
{
|
{
|
||||||
public:
|
class String;
|
||||||
NzDynLibImpl(NzDynLib* m_parent);
|
|
||||||
~NzDynLibImpl() = default;
|
|
||||||
|
|
||||||
NzDynLibFunc GetSymbol(const NzString& symbol, NzString* errorMessage) const;
|
class DynLibImpl
|
||||||
bool Load(const NzString& libraryPath, NzString* errorMessage);
|
{
|
||||||
void Unload();
|
public:
|
||||||
|
DynLibImpl(DynLib* m_parent);
|
||||||
|
~DynLibImpl() = default;
|
||||||
|
|
||||||
private:
|
DynLibFunc GetSymbol(const String& symbol, String* errorMessage) const;
|
||||||
void* m_handle;
|
bool Load(const String& libraryPath, String* errorMessage);
|
||||||
};
|
void Unload();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* m_handle;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_DYNLIBIMPL_HPP
|
#endif // NAZARA_DYNLIBIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -7,236 +7,239 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
NzFileImpl::NzFileImpl(const NzFile* parent) :
|
namespace Nz
|
||||||
m_endOfFile(false),
|
|
||||||
m_endOfFileUpdated(true)
|
|
||||||
{
|
{
|
||||||
NazaraUnused(parent);
|
FileImpl::FileImpl(const File* parent) :
|
||||||
}
|
m_endOfFile(false),
|
||||||
|
m_endOfFileUpdated(true)
|
||||||
void NzFileImpl::Close()
|
|
||||||
{
|
|
||||||
close(m_fileDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzFileImpl::EndOfFile() const
|
|
||||||
{
|
|
||||||
if (!m_endOfFileUpdated)
|
|
||||||
{
|
{
|
||||||
struct stat64 fileSize;
|
NazaraUnused(parent);
|
||||||
if (fstat64(m_fileDescriptor, &fileSize) == -1)
|
|
||||||
fileSize.st_size = 0;
|
|
||||||
|
|
||||||
m_endOfFile = (GetCursorPos() >= static_cast<nzUInt64>(fileSize.st_size));
|
|
||||||
m_endOfFileUpdated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_endOfFile;
|
void FileImpl::Close()
|
||||||
}
|
|
||||||
|
|
||||||
void NzFileImpl::Flush()
|
|
||||||
{
|
|
||||||
if (fsync(m_fileDescriptor) == -1)
|
|
||||||
NazaraError("Unable to flush file: " + NzError::GetLastSystemError());
|
|
||||||
}
|
|
||||||
|
|
||||||
nzUInt64 NzFileImpl::GetCursorPos() const
|
|
||||||
{
|
|
||||||
off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
|
|
||||||
return static_cast<nzUInt64>(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
|
|
||||||
{
|
|
||||||
int flags;
|
|
||||||
mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
|
||||||
|
|
||||||
if (mode & nzOpenMode_ReadOnly)
|
|
||||||
flags = O_RDONLY;
|
|
||||||
else if (mode & nzOpenMode_ReadWrite)
|
|
||||||
{
|
{
|
||||||
flags = O_CREAT | O_RDWR;
|
close(m_fileDescriptor);
|
||||||
|
|
||||||
if (mode & nzOpenMode_Append)
|
|
||||||
flags |= O_APPEND;
|
|
||||||
|
|
||||||
if (mode & nzOpenMode_Truncate)
|
|
||||||
flags |= O_TRUNC;
|
|
||||||
}
|
|
||||||
else if (mode & nzOpenMode_WriteOnly)
|
|
||||||
{
|
|
||||||
flags = O_CREAT | O_WRONLY;
|
|
||||||
|
|
||||||
if (mode & nzOpenMode_Append)
|
|
||||||
flags |= O_APPEND;
|
|
||||||
|
|
||||||
if (mode & nzOpenMode_Truncate)
|
|
||||||
flags |= O_TRUNC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
///TODO: lock
|
|
||||||
// if ((mode & nzOpenMode_Lock) == 0)
|
|
||||||
// shareMode |= FILE_SHARE_WRITE;
|
|
||||||
|
|
||||||
m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
|
|
||||||
return m_fileDescriptor != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t NzFileImpl::Read(void* buffer, std::size_t size)
|
|
||||||
{
|
|
||||||
ssize_t bytes;
|
|
||||||
if ((bytes = read(m_fileDescriptor, buffer, size)) != -1)
|
|
||||||
{
|
|
||||||
m_endOfFile = (static_cast<std::size_t>(bytes) != size);
|
|
||||||
m_endOfFileUpdated = true;
|
|
||||||
|
|
||||||
return static_cast<std::size_t>(bytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzFileImpl::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
|
|
||||||
{
|
|
||||||
int moveMethod;
|
|
||||||
switch (pos)
|
|
||||||
{
|
|
||||||
case nzCursorPosition_AtBegin:
|
|
||||||
moveMethod = SEEK_SET;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzCursorPosition_AtCurrent:
|
|
||||||
moveMethod = SEEK_CUR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzCursorPosition_AtEnd:
|
|
||||||
moveMethod = SEEK_END;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
NazaraInternalError("Cursor position not handled (0x" + NzString::Number(pos, 16) + ')');
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_endOfFileUpdated = false;
|
bool FileImpl::EndOfFile() const
|
||||||
|
|
||||||
return lseek64(m_fileDescriptor, offset, moveMethod) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t NzFileImpl::Write(const void* buffer, std::size_t size)
|
|
||||||
{
|
|
||||||
lockf64(m_fileDescriptor, F_LOCK, size);
|
|
||||||
ssize_t written = write(m_fileDescriptor, buffer, size);
|
|
||||||
lockf64(m_fileDescriptor, F_ULOCK, size);
|
|
||||||
|
|
||||||
m_endOfFileUpdated = false;
|
|
||||||
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzFileImpl::Copy(const NzString& sourcePath, const NzString& targetPath)
|
|
||||||
{
|
|
||||||
int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
|
|
||||||
if (fd1 == -1)
|
|
||||||
{
|
{
|
||||||
NazaraError("Fail to open input file (" + sourcePath + "): " + NzError::GetLastSystemError());
|
if (!m_endOfFileUpdated)
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mode_t permissions; // TODO : get permission from first file
|
|
||||||
int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
|
|
||||||
if (fd2 == -1)
|
|
||||||
{
|
|
||||||
NazaraError("Fail to open output file (" + targetPath + "): " + NzError::GetLastSystemError()); // TODO: more info ?
|
|
||||||
close(fd1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buffer[512];
|
|
||||||
ssize_t bytes;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
bytes = read(fd1,buffer,512);
|
|
||||||
if (bytes == -1)
|
|
||||||
{
|
{
|
||||||
close(fd1);
|
struct stat64 fileSize;
|
||||||
close(fd2);
|
if (fstat64(m_fileDescriptor, &fileSize) == -1)
|
||||||
NazaraError("An error occured from copy : " + NzError::GetLastSystemError());
|
fileSize.st_size = 0;
|
||||||
|
|
||||||
|
m_endOfFile = (GetCursorPos() >= static_cast<UInt64>(fileSize.st_size));
|
||||||
|
m_endOfFileUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_endOfFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileImpl::Flush()
|
||||||
|
{
|
||||||
|
if (fsync(m_fileDescriptor) == -1)
|
||||||
|
NazaraError("Unable to flush file: " + Error::GetLastSystemError());
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 FileImpl::GetCursorPos() const
|
||||||
|
{
|
||||||
|
off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
|
||||||
|
return static_cast<UInt64>(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileImpl::Open(const String& filePath, unsigned int mode)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||||
|
|
||||||
|
if (mode & OpenMode_ReadOnly)
|
||||||
|
flags = O_RDONLY;
|
||||||
|
else if (mode & OpenMode_ReadWrite)
|
||||||
|
{
|
||||||
|
flags = O_CREAT | O_RDWR;
|
||||||
|
|
||||||
|
if (mode & OpenMode_Append)
|
||||||
|
flags |= O_APPEND;
|
||||||
|
|
||||||
|
if (mode & OpenMode_Truncate)
|
||||||
|
flags |= O_TRUNC;
|
||||||
|
}
|
||||||
|
else if (mode & OpenMode_WriteOnly)
|
||||||
|
{
|
||||||
|
flags = O_CREAT | O_WRONLY;
|
||||||
|
|
||||||
|
if (mode & OpenMode_Append)
|
||||||
|
flags |= O_APPEND;
|
||||||
|
|
||||||
|
if (mode & OpenMode_Truncate)
|
||||||
|
flags |= O_TRUNC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
///TODO: lock
|
||||||
|
// if ((mode & OpenMode_Lock) == 0)
|
||||||
|
// shareMode |= FILE_SHARE_WRITE;
|
||||||
|
|
||||||
|
m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
|
||||||
|
return m_fileDescriptor != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t FileImpl::Read(void* buffer, std::size_t size)
|
||||||
|
{
|
||||||
|
ssize_t bytes;
|
||||||
|
if ((bytes = read(m_fileDescriptor, buffer, size)) != -1)
|
||||||
|
{
|
||||||
|
m_endOfFile = (static_cast<std::size_t>(bytes) != size);
|
||||||
|
m_endOfFileUpdated = true;
|
||||||
|
|
||||||
|
return static_cast<std::size_t>(bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileImpl::SetCursorPos(CursorPosition pos, Int64 offset)
|
||||||
|
{
|
||||||
|
int moveMethod;
|
||||||
|
switch (pos)
|
||||||
|
{
|
||||||
|
case CursorPosition_AtBegin:
|
||||||
|
moveMethod = SEEK_SET;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CursorPosition_AtCurrent:
|
||||||
|
moveMethod = SEEK_CUR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CursorPosition_AtEnd:
|
||||||
|
moveMethod = SEEK_END;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_endOfFileUpdated = false;
|
||||||
|
|
||||||
|
return lseek64(m_fileDescriptor, offset, moveMethod) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t FileImpl::Write(const void* buffer, std::size_t size)
|
||||||
|
{
|
||||||
|
lockf64(m_fileDescriptor, F_LOCK, size);
|
||||||
|
ssize_t written = write(m_fileDescriptor, buffer, size);
|
||||||
|
lockf64(m_fileDescriptor, F_ULOCK, size);
|
||||||
|
|
||||||
|
m_endOfFileUpdated = false;
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
|
||||||
|
{
|
||||||
|
int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
|
||||||
|
if (fd1 == -1)
|
||||||
|
{
|
||||||
|
NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
write(fd2,buffer,bytes);
|
|
||||||
}
|
|
||||||
while (bytes == 512);
|
|
||||||
|
|
||||||
close(fd1);
|
mode_t permissions; // TODO : get permission from first file
|
||||||
close(fd2);
|
int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
|
||||||
return true;
|
if (fd2 == -1)
|
||||||
}
|
{
|
||||||
|
NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ?
|
||||||
|
close(fd1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NzFileImpl::Delete(const NzString& filePath)
|
char buffer[512];
|
||||||
{
|
ssize_t bytes;
|
||||||
bool success = unlink(filePath.GetConstBuffer()) != -1;
|
do
|
||||||
|
{
|
||||||
|
bytes = read(fd1,buffer,512);
|
||||||
|
if (bytes == -1)
|
||||||
|
{
|
||||||
|
close(fd1);
|
||||||
|
close(fd2);
|
||||||
|
NazaraError("An error occured from copy : " + Error::GetLastSystemError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write(fd2,buffer,bytes);
|
||||||
|
}
|
||||||
|
while (bytes == 512);
|
||||||
|
|
||||||
if (success)
|
close(fd1);
|
||||||
|
close(fd2);
|
||||||
return true;
|
return true;
|
||||||
else
|
}
|
||||||
|
|
||||||
|
bool FileImpl::Delete(const String& filePath)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to delete file (" + filePath + "): " + NzError::GetLastSystemError());
|
bool success = unlink(filePath.GetConstBuffer()) != -1;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileImpl::Exists(const String& filePath)
|
||||||
|
{
|
||||||
|
const char* path = filePath.GetConstBuffer();
|
||||||
|
if (access(path, F_OK) != -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool NzFileImpl::Exists(const NzString& filePath)
|
time_t FileImpl::GetCreationTime(const String& filePath)
|
||||||
{
|
|
||||||
const char* path = filePath.GetConstBuffer();
|
|
||||||
if (access(path, F_OK) != -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t NzFileImpl::GetCreationTime(const NzString& filePath)
|
|
||||||
{
|
|
||||||
NazaraWarning("Posix has no creation time information");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t NzFileImpl::GetLastAccessTime(const NzString& filePath)
|
|
||||||
{
|
|
||||||
struct stat64 stats;
|
|
||||||
stat64(filePath.GetConstBuffer(), &stats);
|
|
||||||
|
|
||||||
return stats.st_atime;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t NzFileImpl::GetLastWriteTime(const NzString& filePath)
|
|
||||||
{
|
|
||||||
struct stat64 stats;
|
|
||||||
stat64(filePath.GetConstBuffer(), &stats);
|
|
||||||
|
|
||||||
return stats.st_mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
nzUInt64 NzFileImpl::GetSize(const NzString& filePath)
|
|
||||||
{
|
|
||||||
struct stat64 stats;
|
|
||||||
stat64(filePath.GetConstBuffer(), &stats);
|
|
||||||
|
|
||||||
return static_cast<nzUInt64>(stats.st_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzFileImpl::Rename(const NzString& sourcePath, const NzString& targetPath)
|
|
||||||
{
|
|
||||||
bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
NazaraError("Unable to rename file: " + NzError::GetLastSystemError());
|
NazaraWarning("Posix has no creation time information");
|
||||||
return false;
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t FileImpl::GetLastAccessTime(const String& filePath)
|
||||||
|
{
|
||||||
|
struct stat64 stats;
|
||||||
|
stat64(filePath.GetConstBuffer(), &stats);
|
||||||
|
|
||||||
|
return stats.st_atime;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t FileImpl::GetLastWriteTime(const String& filePath)
|
||||||
|
{
|
||||||
|
struct stat64 stats;
|
||||||
|
stat64(filePath.GetConstBuffer(), &stats);
|
||||||
|
|
||||||
|
return stats.st_mtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 FileImpl::GetSize(const String& filePath)
|
||||||
|
{
|
||||||
|
struct stat64 stats;
|
||||||
|
stat64(filePath.GetConstBuffer(), &stats);
|
||||||
|
|
||||||
|
return static_cast<UInt64>(stats.st_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
|
||||||
|
{
|
||||||
|
bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NazaraError("Unable to rename file: " + Error::GetLastSystemError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,44 +13,51 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/File.hpp>
|
#include <Nazara/Core/File.hpp>
|
||||||
#include <Nazara/Core/NonCopyable.hpp>
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
class NzFile;
|
namespace Nz
|
||||||
class NzString;
|
|
||||||
|
|
||||||
class NzFileImpl : NzNonCopyable
|
|
||||||
{
|
{
|
||||||
public:
|
class File;
|
||||||
NzFileImpl(const NzFile* parent);
|
class String;
|
||||||
~NzFileImpl() = default;
|
|
||||||
|
|
||||||
void Close();
|
class FileImpl
|
||||||
bool EndOfFile() const;
|
{
|
||||||
void Flush();
|
public:
|
||||||
nzUInt64 GetCursorPos() const;
|
FileImpl(const File* parent);
|
||||||
bool Open(const NzString& filePath, unsigned int mode);
|
FileImpl(const FileImpl&) = delete;
|
||||||
std::size_t Read(void* buffer, std::size_t size);
|
FileImpl(FileImpl&&) = delete; ///TODO
|
||||||
bool SetCursorPos(nzCursorPosition pos, nzInt64 offset);
|
~FileImpl() = default;
|
||||||
std::size_t Write(const void* buffer, std::size_t size);
|
|
||||||
|
|
||||||
static bool Copy(const NzString& sourcePath, const NzString& targetPath);
|
void Close();
|
||||||
static bool Delete(const NzString& filePath);
|
bool EndOfFile() const;
|
||||||
static bool Exists(const NzString& filePath);
|
void Flush();
|
||||||
static time_t GetCreationTime(const NzString& filePath);
|
UInt64 GetCursorPos() const;
|
||||||
static time_t GetLastAccessTime(const NzString& filePath);
|
bool Open(const String& filePath, unsigned int mode);
|
||||||
static time_t GetLastWriteTime(const NzString& filePath);
|
std::size_t Read(void* buffer, std::size_t size);
|
||||||
static nzUInt64 GetSize(const NzString& filePath);
|
bool SetCursorPos(CursorPosition pos, Int64 offset);
|
||||||
static bool Rename(const NzString& sourcePath, const NzString& targetPath);
|
std::size_t Write(const void* buffer, std::size_t size);
|
||||||
|
|
||||||
private:
|
FileImpl& operator=(const FileImpl&) = delete;
|
||||||
int m_fileDescriptor;
|
FileImpl& operator=(FileImpl&&) = delete; ///TODO
|
||||||
mutable bool m_endOfFile;
|
|
||||||
mutable bool m_endOfFileUpdated;
|
static bool Copy(const String& sourcePath, const String& targetPath);
|
||||||
};
|
static bool Delete(const String& filePath);
|
||||||
|
static bool Exists(const String& filePath);
|
||||||
|
static time_t GetCreationTime(const String& filePath);
|
||||||
|
static time_t GetLastAccessTime(const String& filePath);
|
||||||
|
static time_t GetLastWriteTime(const String& filePath);
|
||||||
|
static UInt64 GetSize(const String& filePath);
|
||||||
|
static bool Rename(const String& sourcePath, const String& targetPath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_fileDescriptor;
|
||||||
|
mutable bool m_endOfFile;
|
||||||
|
mutable bool m_endOfFileUpdated;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_FILEIMPL_HPP
|
#endif // NAZARA_FILEIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -6,58 +6,61 @@
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
void NzHardwareInfoImpl::Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4])
|
namespace Nz
|
||||||
{
|
{
|
||||||
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
|
void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4])
|
||||||
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
|
{
|
||||||
asm volatile ("cpuid" // Besoin d'être volatile ?
|
|
||||||
: "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
|
|
||||||
: "a" (functionId), "c" (subFunctionId)); // input
|
|
||||||
#else
|
|
||||||
NazaraInternalError("Cpuid has been called although it is not supported");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int NzHardwareInfoImpl::GetProcessorCount()
|
|
||||||
{
|
|
||||||
// Plus simple (et plus portable) que de passer par le CPUID
|
|
||||||
return sysconf(_SC_NPROCESSORS_CONF);
|
|
||||||
}
|
|
||||||
|
|
||||||
nzUInt64 NzHardwareInfoImpl::GetTotalMemory()
|
|
||||||
{
|
|
||||||
nzUInt64 pages = sysconf(_SC_PHYS_PAGES);
|
|
||||||
nzUInt64 page_size = sysconf(_SC_PAGE_SIZE);
|
|
||||||
|
|
||||||
return pages * page_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzHardwareInfoImpl::IsCpuidSupported()
|
|
||||||
{
|
|
||||||
#ifdef NAZARA_PLATFORM_x64
|
|
||||||
return true; // Toujours supporté sur un processeur 64 bits
|
|
||||||
#else
|
|
||||||
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
|
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
|
||||||
int supported;
|
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
|
||||||
asm volatile (" pushfl\n"
|
asm volatile ("cpuid" // Besoin d'être volatile ?
|
||||||
" pop %%eax\n"
|
: "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
|
||||||
" mov %%eax, %%ecx\n"
|
: "a" (functionId), "c" (subFunctionId)); // input
|
||||||
" xor $0x200000, %%eax\n"
|
|
||||||
" push %%eax\n"
|
|
||||||
" popfl\n"
|
|
||||||
" pushfl\n"
|
|
||||||
" pop %%eax\n"
|
|
||||||
" xor %%ecx, %%eax\n"
|
|
||||||
" mov %%eax, %0\n"
|
|
||||||
" push %%ecx\n"
|
|
||||||
" popfl"
|
|
||||||
: "=m" (supported) // output
|
|
||||||
: // input
|
|
||||||
: "eax", "ecx", "memory"); // clobbered register
|
|
||||||
|
|
||||||
return supported != 0;
|
|
||||||
#else
|
#else
|
||||||
return false;
|
NazaraInternalError("Cpuid has been called although it is not supported");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
unsigned int HardwareInfoImpl::GetProcessorCount()
|
||||||
|
{
|
||||||
|
// Plus simple (et plus portable) que de passer par le CPUID
|
||||||
|
return sysconf(_SC_NPROCESSORS_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 HardwareInfoImpl::GetTotalMemory()
|
||||||
|
{
|
||||||
|
UInt64 pages = sysconf(_SC_PHYS_PAGES);
|
||||||
|
UInt64 page_size = sysconf(_SC_PAGE_SIZE);
|
||||||
|
|
||||||
|
return pages * page_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HardwareInfoImpl::IsCpuidSupported()
|
||||||
|
{
|
||||||
|
#ifdef NAZARA_PLATFORM_x64
|
||||||
|
return true; // Toujours supporté sur un processeur 64 bits
|
||||||
|
#else
|
||||||
|
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
|
||||||
|
int supported;
|
||||||
|
asm volatile (" pushfl\n"
|
||||||
|
" pop %%eax\n"
|
||||||
|
" mov %%eax, %%ecx\n"
|
||||||
|
" xor $0x200000, %%eax\n"
|
||||||
|
" push %%eax\n"
|
||||||
|
" popfl\n"
|
||||||
|
" pushfl\n"
|
||||||
|
" pop %%eax\n"
|
||||||
|
" xor %%ecx, %%eax\n"
|
||||||
|
" mov %%eax, %0\n"
|
||||||
|
" push %%ecx\n"
|
||||||
|
" popfl"
|
||||||
|
: "=m" (supported) // output
|
||||||
|
: // input
|
||||||
|
: "eax", "ecx", "memory"); // clobbered register
|
||||||
|
|
||||||
|
return supported != 0;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,16 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
class NzHardwareInfoImpl
|
namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
class HardwareInfoImpl
|
||||||
static void Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4]);
|
{
|
||||||
static unsigned int GetProcessorCount();
|
public:
|
||||||
static nzUInt64 GetTotalMemory();
|
static void Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4]);
|
||||||
static bool IsCpuidSupported();
|
static unsigned int GetProcessorCount();
|
||||||
};
|
static UInt64 GetTotalMemory();
|
||||||
|
static bool IsCpuidSupported();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_HARDWAREINFOIMPL_POSIX_HPP
|
#endif // NAZARA_HARDWAREINFOIMPL_POSIX_HPP
|
||||||
|
|
|
||||||
|
|
@ -5,31 +5,34 @@
|
||||||
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
NzMutexImpl::NzMutexImpl()
|
namespace Nz
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t attr;
|
MutexImpl::MutexImpl()
|
||||||
pthread_mutexattr_init(&attr);
|
{
|
||||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
pthread_mutexattr_t attr;
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
|
||||||
pthread_mutex_init(&m_handle, &attr);
|
pthread_mutex_init(&m_handle, &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzMutexImpl::~NzMutexImpl()
|
MutexImpl::~MutexImpl()
|
||||||
{
|
{
|
||||||
pthread_mutex_destroy(&m_handle);
|
pthread_mutex_destroy(&m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzMutexImpl::Lock()
|
void MutexImpl::Lock()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&m_handle);
|
pthread_mutex_lock(&m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzMutexImpl::TryLock()
|
bool MutexImpl::TryLock()
|
||||||
{
|
{
|
||||||
return pthread_mutex_trylock(&m_handle) == 0;
|
return pthread_mutex_trylock(&m_handle) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzMutexImpl::Unlock()
|
void MutexImpl::Unlock()
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&m_handle);
|
pthread_mutex_unlock(&m_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,23 @@
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
class NzMutexImpl
|
namespace Nz
|
||||||
{
|
{
|
||||||
friend class NzConditionVariableImpl;
|
class MutexImpl
|
||||||
|
{
|
||||||
|
friend class ConditionVariableImpl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NzMutexImpl();
|
MutexImpl();
|
||||||
~NzMutexImpl();
|
~MutexImpl();
|
||||||
|
|
||||||
void Lock();
|
void Lock();
|
||||||
bool TryLock();
|
bool TryLock();
|
||||||
void Unlock();
|
void Unlock();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pthread_mutex_t m_handle;
|
pthread_mutex_t m_handle;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_MUTEXIMPL_HPP
|
#endif // NAZARA_MUTEXIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -9,63 +9,66 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
NzSemaphoreImpl::NzSemaphoreImpl(unsigned int count)
|
namespace Nz
|
||||||
{
|
{
|
||||||
if(sem_init(&m_semaphore, 0, count) != 0)
|
SemaphoreImpl::SemaphoreImpl(unsigned int count)
|
||||||
NazaraError("Failed to create semaphore: " + NzError::GetLastSystemError());
|
|
||||||
}
|
|
||||||
|
|
||||||
NzSemaphoreImpl::~NzSemaphoreImpl()
|
|
||||||
{
|
|
||||||
sem_destroy(&m_semaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int NzSemaphoreImpl::GetCount() const
|
|
||||||
{
|
|
||||||
int count=0;
|
|
||||||
sem_getvalue(const_cast<sem_t*>(&m_semaphore), &count);
|
|
||||||
return static_cast<unsigned int>(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzSemaphoreImpl::Post()
|
|
||||||
{
|
|
||||||
#if NAZARA_CORE_SAFE
|
|
||||||
if (sem_post(&m_semaphore)==-1)
|
|
||||||
NazaraError("Failed to release semaphore: " + NzError::GetLastSystemError());
|
|
||||||
#else
|
|
||||||
sem_post(&m_semaphore);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzSemaphoreImpl::Wait()
|
|
||||||
{
|
|
||||||
#if NAZARA_CORE_SAFE
|
|
||||||
if (sem_wait(&m_semaphore) == -1 )
|
|
||||||
NazaraError("Failed to wait for semaphore: " + NzError::GetLastSystemError());
|
|
||||||
#else
|
|
||||||
sem_wait(&m_semaphore);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzSemaphoreImpl::Wait(nzUInt32 timeout)
|
|
||||||
{
|
|
||||||
timeval tv;
|
|
||||||
gettimeofday(&tv, nullptr);
|
|
||||||
|
|
||||||
timespec ti;
|
|
||||||
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
|
|
||||||
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
|
||||||
ti.tv_nsec %= 1000000000;
|
|
||||||
|
|
||||||
#if NAZARA_CORE_SAFE
|
|
||||||
if (sem_timedwait(&m_semaphore, &ti) != 0)
|
|
||||||
{
|
{
|
||||||
NazaraError("Failed to wait for semaphore: " + NzError::GetLastSystemError());
|
if(sem_init(&m_semaphore, 0, count) != 0)
|
||||||
return false;
|
NazaraError("Failed to create semaphore: " + Error::GetLastSystemError());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
SemaphoreImpl::~SemaphoreImpl()
|
||||||
#else
|
{
|
||||||
return sem_timedwait(&m_semaphore, &ti) != 0;
|
sem_destroy(&m_semaphore);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
unsigned int SemaphoreImpl::GetCount() const
|
||||||
|
{
|
||||||
|
int count=0;
|
||||||
|
sem_getvalue(const_cast<sem_t*>(&m_semaphore), &count);
|
||||||
|
return static_cast<unsigned int>(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SemaphoreImpl::Post()
|
||||||
|
{
|
||||||
|
#if NAZARA_CORE_SAFE
|
||||||
|
if (sem_post(&m_semaphore)==-1)
|
||||||
|
NazaraError("Failed to release semaphore: " + Error::GetLastSystemError());
|
||||||
|
#else
|
||||||
|
sem_post(&m_semaphore);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SemaphoreImpl::Wait()
|
||||||
|
{
|
||||||
|
#if NAZARA_CORE_SAFE
|
||||||
|
if (sem_wait(&m_semaphore) == -1 )
|
||||||
|
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||||
|
#else
|
||||||
|
sem_wait(&m_semaphore);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemaphoreImpl::Wait(UInt32 timeout)
|
||||||
|
{
|
||||||
|
timeval tv;
|
||||||
|
gettimeofday(&tv, nullptr);
|
||||||
|
|
||||||
|
timespec ti;
|
||||||
|
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
|
||||||
|
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
||||||
|
ti.tv_nsec %= 1000000000;
|
||||||
|
|
||||||
|
#if NAZARA_CORE_SAFE
|
||||||
|
if (sem_timedwait(&m_semaphore, &ti) != 0)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return sem_timedwait(&m_semaphore, &ti) != 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,22 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
class NzSemaphoreImpl
|
namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
class SemaphoreImpl
|
||||||
NzSemaphoreImpl(unsigned int count);
|
{
|
||||||
~NzSemaphoreImpl();
|
public:
|
||||||
|
SemaphoreImpl(unsigned int count);
|
||||||
|
~SemaphoreImpl();
|
||||||
|
|
||||||
unsigned int GetCount() const;
|
unsigned int GetCount() const;
|
||||||
void Post();
|
void Post();
|
||||||
void Wait();
|
void Wait();
|
||||||
bool Wait(nzUInt32 timeout);
|
bool Wait(UInt32 timeout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sem_t m_semaphore;
|
sem_t m_semaphore;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_SEMAPHOREIMPL_HPP
|
#endif // NAZARA_SEMAPHOREIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -7,186 +7,189 @@
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
bool NzTaskSchedulerImpl::Initialize(unsigned int workerCount)
|
namespace Nz
|
||||||
{
|
{
|
||||||
if (IsInitialized())
|
bool TaskSchedulerImpl::Initialize(unsigned int workerCount)
|
||||||
return true; // Déjà initialisé
|
|
||||||
|
|
||||||
#if NAZARA_CORE_SAFE
|
|
||||||
if (workerCount == 0)
|
|
||||||
{
|
{
|
||||||
NazaraError("Invalid worker count ! (0)");
|
if (IsInitialized())
|
||||||
return false;
|
return true; // Déjà initialisé
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s_workerCount = workerCount;
|
#if NAZARA_CORE_SAFE
|
||||||
s_isDone = false;
|
if (workerCount == 0)
|
||||||
s_isWaiting = false;
|
|
||||||
s_shouldFinish = false;
|
|
||||||
|
|
||||||
s_threads.reset(new pthread_t[workerCount]);
|
|
||||||
|
|
||||||
// On initialise les conditions variables, mutex et barrière.
|
|
||||||
pthread_cond_init(&s_cvEmpty, nullptr);
|
|
||||||
pthread_cond_init(&s_cvNotEmpty, nullptr);
|
|
||||||
pthread_mutex_init(&s_mutexQueue, nullptr);
|
|
||||||
pthread_barrier_init(&s_barrier, nullptr, workerCount + 1);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
|
||||||
{
|
|
||||||
// Le thread va se lancer, attendre que tous se créent et attendre d'être réveillé.
|
|
||||||
pthread_create(&s_threads[i], nullptr, WorkerProc, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_barrier_wait(&s_barrier); // On attend que les enfants soient bien créés.
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzTaskSchedulerImpl::IsInitialized()
|
|
||||||
{
|
|
||||||
return s_workerCount > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzTaskSchedulerImpl::Run(NzFunctor** tasks, unsigned int count)
|
|
||||||
{
|
|
||||||
// On s'assure que des tâches ne sont pas déjà en cours
|
|
||||||
Wait();
|
|
||||||
|
|
||||||
pthread_mutex_lock(&s_mutexQueue);
|
|
||||||
s_isDone = false;
|
|
||||||
|
|
||||||
while (count--)
|
|
||||||
s_tasks.push(*tasks++);
|
|
||||||
|
|
||||||
pthread_cond_signal(&s_cvNotEmpty);
|
|
||||||
pthread_mutex_unlock(&s_mutexQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzTaskSchedulerImpl::Uninitialize()
|
|
||||||
{
|
|
||||||
#ifdef NAZARA_CORE_SAFE
|
|
||||||
if (s_workerCount == 0)
|
|
||||||
{
|
|
||||||
NazaraError("Task scheduler is not initialized");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// On réveille les threads pour qu'ils sortent de la boucle et terminent.
|
|
||||||
pthread_mutex_lock(&s_mutexQueue);
|
|
||||||
// On commence par vider la queue et demander qu'ils s'arrêtent.
|
|
||||||
std::queue<NzFunctor*> emptyQueue;
|
|
||||||
std::swap(s_tasks, emptyQueue);
|
|
||||||
s_shouldFinish = true;
|
|
||||||
pthread_cond_broadcast(&s_cvNotEmpty);
|
|
||||||
pthread_mutex_unlock(&s_mutexQueue);
|
|
||||||
|
|
||||||
// On attend que chaque thread se termine
|
|
||||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
|
||||||
pthread_join(s_threads[i], nullptr);
|
|
||||||
|
|
||||||
// Et on libère les ressources
|
|
||||||
pthread_barrier_destroy(&s_barrier);
|
|
||||||
pthread_cond_destroy(&s_cvEmpty);
|
|
||||||
pthread_cond_destroy(&s_cvNotEmpty);
|
|
||||||
pthread_mutex_destroy(&s_mutexQueue);
|
|
||||||
|
|
||||||
s_workerCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzTaskSchedulerImpl::WaitForTasks()
|
|
||||||
{
|
|
||||||
#ifdef NAZARA_CORE_SAFE
|
|
||||||
if (s_workerCount == 0)
|
|
||||||
{
|
|
||||||
NazaraError("Task scheduler is not initialized");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
NzFunctor* NzTaskSchedulerImpl::PopQueue()
|
|
||||||
{
|
|
||||||
NzFunctor* task = nullptr;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&s_mutexQueue);
|
|
||||||
|
|
||||||
if (!s_tasks.empty())
|
|
||||||
{
|
|
||||||
task = s_tasks.front();
|
|
||||||
s_tasks.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&s_mutexQueue);
|
|
||||||
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzTaskSchedulerImpl::Wait()
|
|
||||||
{
|
|
||||||
if (s_isDone)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&s_mutexQueue);
|
|
||||||
s_isWaiting = true;
|
|
||||||
pthread_cond_broadcast(&s_cvNotEmpty);
|
|
||||||
pthread_cond_wait(&s_cvEmpty, &s_mutexQueue);
|
|
||||||
pthread_mutex_unlock(&s_mutexQueue);
|
|
||||||
|
|
||||||
s_isDone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* NzTaskSchedulerImpl::WorkerProc(void* /*userdata*/)
|
|
||||||
{
|
|
||||||
// On s'assure que tous les threads soient correctement lancés.
|
|
||||||
pthread_barrier_wait(&s_barrier);
|
|
||||||
|
|
||||||
// On quitte s'il doit terminer.
|
|
||||||
while (!s_shouldFinish)
|
|
||||||
{
|
|
||||||
NzFunctor* task = PopQueue();
|
|
||||||
|
|
||||||
if (task)
|
|
||||||
{
|
{
|
||||||
// On exécute la tâche avant de la supprimer
|
NazaraError("Invalid worker count ! (0)");
|
||||||
task->Run();
|
return false;
|
||||||
delete task;
|
|
||||||
}
|
}
|
||||||
else
|
#endif
|
||||||
|
|
||||||
|
s_workerCount = workerCount;
|
||||||
|
s_isDone = false;
|
||||||
|
s_isWaiting = false;
|
||||||
|
s_shouldFinish = false;
|
||||||
|
|
||||||
|
s_threads.reset(new pthread_t[workerCount]);
|
||||||
|
|
||||||
|
// On initialise les conditions variables, mutex et barrière.
|
||||||
|
pthread_cond_init(&s_cvEmpty, nullptr);
|
||||||
|
pthread_cond_init(&s_cvNotEmpty, nullptr);
|
||||||
|
pthread_mutex_init(&s_mutexQueue, nullptr);
|
||||||
|
pthread_barrier_init(&s_barrier, nullptr, workerCount + 1);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&s_mutexQueue);
|
// Le thread va se lancer, attendre que tous se créent et attendre d'être réveillé.
|
||||||
if (s_tasks.empty())
|
pthread_create(&s_threads[i], nullptr, WorkerProc, nullptr);
|
||||||
s_isDone = true;
|
}
|
||||||
|
|
||||||
while (!(!s_tasks.empty() || s_isWaiting || s_shouldFinish))
|
pthread_barrier_wait(&s_barrier); // On attend que les enfants soient bien créés.
|
||||||
pthread_cond_wait(&s_cvNotEmpty, &s_mutexQueue);
|
|
||||||
|
|
||||||
if (s_tasks.empty() && s_isWaiting)
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskSchedulerImpl::IsInitialized()
|
||||||
|
{
|
||||||
|
return s_workerCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskSchedulerImpl::Run(Functor** tasks, unsigned int count)
|
||||||
|
{
|
||||||
|
// On s'assure que des tâches ne sont pas déjà en cours
|
||||||
|
Wait();
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_mutexQueue);
|
||||||
|
s_isDone = false;
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
s_tasks.push(*tasks++);
|
||||||
|
|
||||||
|
pthread_cond_signal(&s_cvNotEmpty);
|
||||||
|
pthread_mutex_unlock(&s_mutexQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskSchedulerImpl::Uninitialize()
|
||||||
|
{
|
||||||
|
#ifdef NAZARA_CORE_SAFE
|
||||||
|
if (s_workerCount == 0)
|
||||||
|
{
|
||||||
|
NazaraError("Task scheduler is not initialized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// On réveille les threads pour qu'ils sortent de la boucle et terminent.
|
||||||
|
pthread_mutex_lock(&s_mutexQueue);
|
||||||
|
// On commence par vider la queue et demander qu'ils s'arrêtent.
|
||||||
|
std::queue<Functor*> emptyQueue;
|
||||||
|
std::swap(s_tasks, emptyQueue);
|
||||||
|
s_shouldFinish = true;
|
||||||
|
pthread_cond_broadcast(&s_cvNotEmpty);
|
||||||
|
pthread_mutex_unlock(&s_mutexQueue);
|
||||||
|
|
||||||
|
// On attend que chaque thread se termine
|
||||||
|
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||||
|
pthread_join(s_threads[i], nullptr);
|
||||||
|
|
||||||
|
// Et on libère les ressources
|
||||||
|
pthread_barrier_destroy(&s_barrier);
|
||||||
|
pthread_cond_destroy(&s_cvEmpty);
|
||||||
|
pthread_cond_destroy(&s_cvNotEmpty);
|
||||||
|
pthread_mutex_destroy(&s_mutexQueue);
|
||||||
|
|
||||||
|
s_workerCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskSchedulerImpl::WaitForTasks()
|
||||||
|
{
|
||||||
|
#ifdef NAZARA_CORE_SAFE
|
||||||
|
if (s_workerCount == 0)
|
||||||
|
{
|
||||||
|
NazaraError("Task scheduler is not initialized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
Functor* TaskSchedulerImpl::PopQueue()
|
||||||
|
{
|
||||||
|
Functor* task = nullptr;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_mutexQueue);
|
||||||
|
|
||||||
|
if (!s_tasks.empty())
|
||||||
|
{
|
||||||
|
task = s_tasks.front();
|
||||||
|
s_tasks.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&s_mutexQueue);
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskSchedulerImpl::Wait()
|
||||||
|
{
|
||||||
|
if (s_isDone)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_mutexQueue);
|
||||||
|
s_isWaiting = true;
|
||||||
|
pthread_cond_broadcast(&s_cvNotEmpty);
|
||||||
|
pthread_cond_wait(&s_cvEmpty, &s_mutexQueue);
|
||||||
|
pthread_mutex_unlock(&s_mutexQueue);
|
||||||
|
|
||||||
|
s_isDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* TaskSchedulerImpl::WorkerProc(void* /*userdata*/)
|
||||||
|
{
|
||||||
|
// On s'assure que tous les threads soient correctement lancés.
|
||||||
|
pthread_barrier_wait(&s_barrier);
|
||||||
|
|
||||||
|
// On quitte s'il doit terminer.
|
||||||
|
while (!s_shouldFinish)
|
||||||
|
{
|
||||||
|
Functor* task = PopQueue();
|
||||||
|
|
||||||
|
if (task)
|
||||||
{
|
{
|
||||||
// On prévient le thread qui attend que les tâches soient effectuées.
|
// On exécute la tâche avant de la supprimer
|
||||||
s_isWaiting = false;
|
task->Run();
|
||||||
pthread_cond_signal(&s_cvEmpty);
|
delete task;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&s_mutexQueue);
|
||||||
|
if (s_tasks.empty())
|
||||||
|
s_isDone = true;
|
||||||
|
|
||||||
pthread_mutex_unlock(&s_mutexQueue);
|
while (!(!s_tasks.empty() || s_isWaiting || s_shouldFinish))
|
||||||
|
pthread_cond_wait(&s_cvNotEmpty, &s_mutexQueue);
|
||||||
|
|
||||||
|
if (s_tasks.empty() && s_isWaiting)
|
||||||
|
{
|
||||||
|
// On prévient le thread qui attend que les tâches soient effectuées.
|
||||||
|
s_isWaiting = false;
|
||||||
|
pthread_cond_signal(&s_cvEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&s_mutexQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
std::queue<Functor*> TaskSchedulerImpl::s_tasks;
|
||||||
|
std::unique_ptr<pthread_t[]> TaskSchedulerImpl::s_threads;
|
||||||
|
std::atomic<bool> TaskSchedulerImpl::s_isDone;
|
||||||
|
std::atomic<bool> TaskSchedulerImpl::s_isWaiting;
|
||||||
|
std::atomic<bool> TaskSchedulerImpl::s_shouldFinish;
|
||||||
|
unsigned int TaskSchedulerImpl::s_workerCount;
|
||||||
|
|
||||||
|
pthread_mutex_t TaskSchedulerImpl::s_mutexQueue;
|
||||||
|
pthread_cond_t TaskSchedulerImpl::s_cvEmpty;
|
||||||
|
pthread_cond_t TaskSchedulerImpl::s_cvNotEmpty;
|
||||||
|
pthread_barrier_t TaskSchedulerImpl::s_barrier;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::queue<NzFunctor*> NzTaskSchedulerImpl::s_tasks;
|
|
||||||
std::unique_ptr<pthread_t[]> NzTaskSchedulerImpl::s_threads;
|
|
||||||
std::atomic<bool> NzTaskSchedulerImpl::s_isDone;
|
|
||||||
std::atomic<bool> NzTaskSchedulerImpl::s_isWaiting;
|
|
||||||
std::atomic<bool> NzTaskSchedulerImpl::s_shouldFinish;
|
|
||||||
unsigned int NzTaskSchedulerImpl::s_workerCount;
|
|
||||||
|
|
||||||
pthread_mutex_t NzTaskSchedulerImpl::s_mutexQueue;
|
|
||||||
pthread_cond_t NzTaskSchedulerImpl::s_cvEmpty;
|
|
||||||
pthread_cond_t NzTaskSchedulerImpl::s_cvNotEmpty;
|
|
||||||
pthread_barrier_t NzTaskSchedulerImpl::s_barrier;
|
|
||||||
|
|
|
||||||
|
|
@ -14,34 +14,37 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
class NzTaskSchedulerImpl
|
namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
class TaskSchedulerImpl
|
||||||
NzTaskSchedulerImpl() = delete;
|
{
|
||||||
~NzTaskSchedulerImpl() = delete;
|
public:
|
||||||
|
TaskSchedulerImpl() = delete;
|
||||||
|
~TaskSchedulerImpl() = delete;
|
||||||
|
|
||||||
static bool Initialize(unsigned int workerCount);
|
static bool Initialize(unsigned int workerCount);
|
||||||
static bool IsInitialized();
|
static bool IsInitialized();
|
||||||
static void Run(NzFunctor** tasks, unsigned int count);
|
static void Run(Functor** tasks, unsigned int count);
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
static void WaitForTasks();
|
static void WaitForTasks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static NzFunctor* PopQueue();
|
static Functor* PopQueue();
|
||||||
static void Wait();
|
static void Wait();
|
||||||
static void* WorkerProc(void* userdata);
|
static void* WorkerProc(void* userdata);
|
||||||
|
|
||||||
static std::queue<NzFunctor*> s_tasks;
|
static std::queue<Functor*> s_tasks;
|
||||||
static std::unique_ptr<pthread_t[]> s_threads;
|
static std::unique_ptr<pthread_t[]> s_threads;
|
||||||
static std::atomic<bool> s_isDone;
|
static std::atomic<bool> s_isDone;
|
||||||
static std::atomic<bool> s_isWaiting;
|
static std::atomic<bool> s_isWaiting;
|
||||||
static std::atomic<bool> s_shouldFinish;
|
static std::atomic<bool> s_shouldFinish;
|
||||||
static unsigned int s_workerCount;
|
static unsigned int s_workerCount;
|
||||||
|
|
||||||
static pthread_mutex_t s_mutexQueue;
|
static pthread_mutex_t s_mutexQueue;
|
||||||
static pthread_cond_t s_cvEmpty;
|
static pthread_cond_t s_cvEmpty;
|
||||||
static pthread_cond_t s_cvNotEmpty;
|
static pthread_cond_t s_cvNotEmpty;
|
||||||
static pthread_barrier_t s_barrier;
|
static pthread_barrier_t s_barrier;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_TASKSCHEDULERIMPL_HPP
|
#endif // NAZARA_TASKSCHEDULERIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -9,64 +9,67 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
NzThreadImpl::NzThreadImpl(NzFunctor* functor)
|
namespace Nz
|
||||||
{
|
{
|
||||||
int error = pthread_create(&m_handle, nullptr, &NzThreadImpl::ThreadProc, functor);
|
ThreadImpl::ThreadImpl(Functor* functor)
|
||||||
if (error != 0)
|
{
|
||||||
NazaraInternalError("Failed to create thread: " + NzError::GetLastSystemError());
|
int error = pthread_create(&m_handle, nullptr, &ThreadImpl::ThreadProc, functor);
|
||||||
}
|
if (error != 0)
|
||||||
|
NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());
|
||||||
void NzThreadImpl::Detach()
|
}
|
||||||
{
|
|
||||||
pthread_detach(m_handle);
|
void ThreadImpl::Detach()
|
||||||
}
|
{
|
||||||
|
pthread_detach(m_handle);
|
||||||
void NzThreadImpl::Join()
|
}
|
||||||
{
|
|
||||||
pthread_join(m_handle, nullptr);
|
void ThreadImpl::Join()
|
||||||
}
|
{
|
||||||
|
pthread_join(m_handle, nullptr);
|
||||||
void* NzThreadImpl::ThreadProc(void* userdata)
|
}
|
||||||
{
|
|
||||||
NzFunctor* func = static_cast<NzFunctor*>(userdata);
|
void* ThreadImpl::ThreadProc(void* userdata)
|
||||||
func->Run();
|
{
|
||||||
delete func;
|
Functor* func = static_cast<Functor*>(userdata);
|
||||||
|
func->Run();
|
||||||
return nullptr;
|
delete func;
|
||||||
}
|
|
||||||
|
return nullptr;
|
||||||
void NzThreadImpl::Sleep(nzUInt32 time)
|
}
|
||||||
{
|
|
||||||
// code from SFML2 Unix SleepImpl.cpp source https://github.com/LaurentGomila/SFML/blob/master/src/SFML/System/Unix/SleepImpl.cpp
|
void ThreadImpl::Sleep(UInt32 time)
|
||||||
|
{
|
||||||
// usleep is not reliable enough (it might block the
|
// code from SFML2 Unix SleepImpl.cpp source https://github.com/LaurentGomila/SFML/blob/master/src/SFML/System/Unix/SleepImpl.cpp
|
||||||
// whole process instead of just the current thread)
|
|
||||||
// so we must use pthread_cond_timedwait instead
|
// usleep is not reliable enough (it might block the
|
||||||
|
// whole process instead of just the current thread)
|
||||||
// this implementation is inspired from Qt
|
// so we must use pthread_cond_timedwait instead
|
||||||
|
|
||||||
// get the current time
|
// this implementation is inspired from Qt
|
||||||
timeval tv;
|
|
||||||
gettimeofday(&tv, nullptr);
|
// get the current time
|
||||||
|
timeval tv;
|
||||||
// construct the time limit (current time + time to wait)
|
gettimeofday(&tv, nullptr);
|
||||||
timespec ti;
|
|
||||||
ti.tv_nsec = (tv.tv_usec + (time % 1000)) * 1000;
|
// construct the time limit (current time + time to wait)
|
||||||
ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000);
|
timespec ti;
|
||||||
ti.tv_nsec %= 1000000000;
|
ti.tv_nsec = (tv.tv_usec + (time % 1000)) * 1000;
|
||||||
|
ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000);
|
||||||
// create a mutex and thread condition
|
ti.tv_nsec %= 1000000000;
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_mutex_init(&mutex, nullptr);
|
// create a mutex and thread condition
|
||||||
pthread_cond_t condition;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_init(&condition, nullptr);
|
pthread_mutex_init(&mutex, nullptr);
|
||||||
|
pthread_cond_t condition;
|
||||||
// wait...
|
pthread_cond_init(&condition, nullptr);
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
pthread_cond_timedwait(&condition, &mutex, &ti);
|
// wait...
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
|
pthread_cond_timedwait(&condition, &mutex, &ti);
|
||||||
// destroy the mutex and condition
|
pthread_mutex_unlock(&mutex);
|
||||||
pthread_cond_destroy(&condition);
|
|
||||||
pthread_mutex_destroy(&mutex);
|
// destroy the mutex and condition
|
||||||
|
pthread_cond_destroy(&condition);
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,25 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
struct NzFunctor;
|
namespace Nz
|
||||||
|
|
||||||
class NzThreadImpl
|
|
||||||
{
|
{
|
||||||
public:
|
struct Functor;
|
||||||
NzThreadImpl(NzFunctor* threadFunc);
|
|
||||||
|
|
||||||
void Detach();
|
class ThreadImpl
|
||||||
void Join();
|
{
|
||||||
|
public:
|
||||||
|
ThreadImpl(Functor* threadFunc);
|
||||||
|
|
||||||
static void Sleep(nzUInt32 time);
|
void Detach();
|
||||||
|
void Join();
|
||||||
|
|
||||||
private:
|
static void Sleep(UInt32 time);
|
||||||
static void* ThreadProc(void* userdata);
|
|
||||||
|
|
||||||
pthread_t m_handle;
|
private:
|
||||||
};
|
static void* ThreadProc(void* userdata);
|
||||||
|
|
||||||
|
pthread_t m_handle;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_THREADIMPL_HPP
|
#endif // NAZARA_THREADIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@
|
||||||
|
|
||||||
void* operator new(std::size_t size)
|
void* operator new(std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, false);
|
return Nz::MemoryManager::Allocate(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](std::size_t size)
|
void* operator new[](std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, true);
|
return Nz::MemoryManager::Allocate(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* pointer) noexcept
|
void operator delete(void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, false);
|
Nz::MemoryManager::Free(pointer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* pointer) noexcept
|
void operator delete[](void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, true);
|
Nz::MemoryManager::Free(pointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_GRAPHICS_MANAGE_MEMORY
|
#endif // NAZARA_GRAPHICS_MANAGE_MEMORY
|
||||||
|
|
|
||||||
|
|
@ -689,7 +689,7 @@ namespace Nz
|
||||||
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
|
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
|
||||||
if (shaderUniforms->hasLightUniforms)
|
if (shaderUniforms->hasLightUniforms)
|
||||||
{
|
{
|
||||||
lightCount = std::min(m_renderQueue.directionalLights.size(), NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
lightCount = std::min(m_renderQueue.directionalLights.size(), static_cast<decltype(m_renderQueue.directionalLights.size())>(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < lightCount; ++i)
|
for (unsigned int i = 0; i < lightCount; ++i)
|
||||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset * i);
|
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset * i);
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@
|
||||||
|
|
||||||
void* operator new(std::size_t size)
|
void* operator new(std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, false);
|
return Nz::MemoryManager::Allocate(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](std::size_t size)
|
void* operator new[](std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, true);
|
return Nz::MemoryManager::Allocate(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* pointer) noexcept
|
void operator delete(void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, false);
|
Nz::MemoryManager::Free(pointer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* pointer) noexcept
|
void operator delete[](void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, true);
|
Nz::MemoryManager::Free(pointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_LUA_MANAGE_MEMORY
|
#endif // NAZARA_LUA_MANAGE_MEMORY
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@
|
||||||
|
|
||||||
void* operator new(std::size_t size)
|
void* operator new(std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, false);
|
return Nz::MemoryManager::Allocate(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](std::size_t size)
|
void* operator new[](std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, true);
|
return Nz::MemoryManager::Allocate(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* pointer) noexcept
|
void operator delete(void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, false);
|
Nz::MemoryManager::Free(pointer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* pointer) noexcept
|
void operator delete[](void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, true);
|
Nz::MemoryManager::Free(pointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_NOISE_MANAGE_MEMORY
|
#endif // NAZARA_NOISE_MANAGE_MEMORY
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@
|
||||||
|
|
||||||
void* operator new(std::size_t size)
|
void* operator new(std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, false);
|
return Nz::MemoryManager::Allocate(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](std::size_t size)
|
void* operator new[](std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, true);
|
return Nz::MemoryManager::Allocate(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* pointer) noexcept
|
void operator delete(void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, false);
|
Nz::MemoryManager::Free(pointer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* pointer) noexcept
|
void operator delete[](void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, true);
|
Nz::MemoryManager::Free(pointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_PHYSICS_MANAGE_MEMORY
|
#endif // NAZARA_PHYSICS_MANAGE_MEMORY
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
|
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_GLX)
|
||||||
#include <Nazara/Renderer/GLX/ContextImpl.hpp>
|
#include <Nazara/Renderer/GLX/ContextImpl.hpp>
|
||||||
#define CALLBACK
|
#define CALLBACK
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@
|
||||||
|
|
||||||
void* operator new(std::size_t size)
|
void* operator new(std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, false);
|
return Nz::MemoryManager::Allocate(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](std::size_t size)
|
void* operator new[](std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, true);
|
return Nz::MemoryManager::Allocate(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* pointer) noexcept
|
void operator delete(void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, false);
|
Nz::MemoryManager::Free(pointer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* pointer) noexcept
|
void operator delete[](void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, true);
|
Nz::MemoryManager::Free(pointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_RENDERER_MANAGE_MEMORY
|
#endif // NAZARA_RENDERER_MANAGE_MEMORY
|
||||||
|
|
|
||||||
|
|
@ -12,286 +12,289 @@
|
||||||
|
|
||||||
using namespace GLX;
|
using namespace GLX;
|
||||||
|
|
||||||
namespace
|
namespace Nz
|
||||||
{
|
{
|
||||||
Display* m_display;
|
namespace
|
||||||
int m_sharedDisplay = 0;
|
|
||||||
|
|
||||||
bool ctxErrorOccurred = false;
|
|
||||||
int ctxErrorHandler( Display* /*dpy*/, XErrorEvent* /*ev*/ )
|
|
||||||
{
|
{
|
||||||
ctxErrorOccurred = true;
|
Display* m_display;
|
||||||
return 0;
|
int m_sharedDisplay = 0;
|
||||||
|
|
||||||
|
bool ctxErrorOccurred = false;
|
||||||
|
int ctxErrorHandler( Display* /*dpy*/, XErrorEvent* /*ev*/ )
|
||||||
|
{
|
||||||
|
ctxErrorOccurred = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
NzContextImpl::NzContextImpl() :
|
ContextImpl::ContextImpl() :
|
||||||
m_colormap(0),
|
m_colormap(0),
|
||||||
m_context(0),
|
m_context(0),
|
||||||
m_window(0),
|
m_window(0),
|
||||||
m_ownsWindow(false)
|
m_ownsWindow(false)
|
||||||
{
|
|
||||||
if (m_sharedDisplay == 0)
|
|
||||||
m_display = XOpenDisplay(nullptr);
|
|
||||||
|
|
||||||
++m_sharedDisplay;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzContextImpl::~NzContextImpl()
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
|
|
||||||
if (--m_sharedDisplay == 0)
|
|
||||||
{
|
{
|
||||||
XCloseDisplay(m_display);
|
if (m_sharedDisplay == 0)
|
||||||
m_display = nullptr;
|
m_display = XOpenDisplay(nullptr);
|
||||||
|
|
||||||
|
++m_sharedDisplay;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool NzContextImpl::Activate()
|
ContextImpl::~ContextImpl()
|
||||||
{
|
|
||||||
return glXMakeCurrent(m_display, m_window, m_context) == true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzContextImpl::Create(NzContextParameters& parameters)
|
|
||||||
{
|
|
||||||
// En cas d'exception, la ressource sera quand même libérée
|
|
||||||
NzCallOnExit onExit([this] ()
|
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
});
|
|
||||||
|
|
||||||
// Get a matching FB config
|
if (--m_sharedDisplay == 0)
|
||||||
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;
|
XCloseDisplay(m_display);
|
||||||
glXGetFBConfigAttrib(m_display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
|
m_display = nullptr;
|
||||||
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];
|
bool ContextImpl::Activate()
|
||||||
|
|
||||||
// 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 glXMakeCurrent(m_display, m_window, m_context) == true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If context is shared by multiple windows
|
bool ContextImpl::Create(ContextParameters& parameters)
|
||||||
if (parameters.window)
|
|
||||||
{
|
{
|
||||||
m_window = parameters.window;
|
// En cas d'exception, la ressource sera quand même libérée
|
||||||
m_ownsWindow = false;
|
CallOnExit onExit([this] ()
|
||||||
}
|
|
||||||
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");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_window = XCreateWindow(
|
int fbcount;
|
||||||
m_display,
|
GLXFBConfig* fbc = glXChooseFBConfig(m_display, XDefaultScreen(m_display), visual_attribs, &fbcount);
|
||||||
XRootWindow(
|
if (!fbc)
|
||||||
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,
|
NazaraError("Failed to retrieve a framebuffer config");
|
||||||
GLX_CONTEXT_MINOR_VERSION_ARB, minor,
|
return false;
|
||||||
GLX_CONTEXT_PROFILE_MASK_ARB, profile,
|
}
|
||||||
GLX_CONTEXT_FLAGS_ARB, debug,
|
|
||||||
None, None
|
|
||||||
};
|
|
||||||
|
|
||||||
m_context = glXCreateContextAttribs(
|
// Pick the FB config/visual with the most samples per pixel
|
||||||
m_display,
|
int best_fbc = -1;
|
||||||
bestFbc,
|
int worst_fbc = -1;
|
||||||
parameters.shared ? parameters.shareContext->m_impl->m_context : 0,
|
int best_num_samp = -1;
|
||||||
True,
|
int worst_num_samp = 999;
|
||||||
context_attribs
|
|
||||||
);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync to ensure any errors generated are processed.
|
void ContextImpl::Destroy()
|
||||||
XSync(m_display, False);
|
|
||||||
XSetErrorHandler(oldHandler);
|
|
||||||
if (ctxErrorOccurred || !m_context)
|
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create context, check the version");
|
// Destroy the context
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExit.Reset();
|
void ContextImpl::EnableVerticalSync(bool enabled)
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzContextImpl::Destroy()
|
|
||||||
{
|
|
||||||
// Destroy the context
|
|
||||||
if (m_context)
|
|
||||||
{
|
{
|
||||||
if (glXGetCurrentContext() == m_context)
|
if (glXSwapIntervalEXT)
|
||||||
glXMakeCurrent(m_display, None, nullptr);
|
glXSwapIntervalEXT(m_display, glXGetCurrentDrawable(), enabled ? 1 : 0);
|
||||||
glXDestroyContext(m_display, m_context);
|
else if (NzglXSwapIntervalMESA)
|
||||||
m_context = nullptr;
|
NzglXSwapIntervalMESA(enabled ? 1 : 0);
|
||||||
|
else if (glXSwapIntervalSGI)
|
||||||
|
glXSwapIntervalSGI(enabled ? 1 : 0);
|
||||||
|
else
|
||||||
|
NazaraError("Vertical sync not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the window if we own it
|
void ContextImpl::SwapBuffers()
|
||||||
if (m_ownsWindow && m_window)
|
|
||||||
{
|
{
|
||||||
XFreeColormap(m_display, m_colormap);
|
if (m_window)
|
||||||
XDestroyWindow(m_display, m_window);
|
glXSwapBuffers(m_display, m_window);
|
||||||
m_ownsWindow = false;
|
}
|
||||||
m_window = 0;
|
|
||||||
XFlush(m_display);
|
bool ContextImpl::Desactivate()
|
||||||
|
{
|
||||||
|
return glXMakeCurrent(m_display, None, nullptr) == true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzContextImpl::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 NzContextImpl::SwapBuffers()
|
|
||||||
{
|
|
||||||
if (m_window)
|
|
||||||
glXSwapBuffers(m_display, m_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzContextImpl::Desactivate()
|
|
||||||
{
|
|
||||||
return glXMakeCurrent(m_display, None, nullptr) == true;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -9,31 +9,34 @@
|
||||||
|
|
||||||
#include <Nazara/Renderer/OpenGL.hpp>
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
|
|
||||||
class NzContextParameters;
|
namespace Nz
|
||||||
|
|
||||||
class NzContextImpl
|
|
||||||
{
|
{
|
||||||
public:
|
class ContextParameters;
|
||||||
NzContextImpl();
|
|
||||||
~NzContextImpl();
|
|
||||||
|
|
||||||
bool Activate();
|
class ContextImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ContextImpl();
|
||||||
|
~ContextImpl();
|
||||||
|
|
||||||
bool Create(NzContextParameters& parameters);
|
bool Activate();
|
||||||
|
|
||||||
void Destroy();
|
bool Create(ContextParameters& parameters);
|
||||||
|
|
||||||
void EnableVerticalSync(bool enabled);
|
void Destroy();
|
||||||
|
|
||||||
void SwapBuffers();
|
void EnableVerticalSync(bool enabled);
|
||||||
|
|
||||||
static bool Desactivate();
|
void SwapBuffers();
|
||||||
|
|
||||||
private:
|
static bool Desactivate();
|
||||||
GLX::Colormap m_colormap;
|
|
||||||
GLX::GLXContext m_context;
|
private:
|
||||||
GLX::Window m_window;
|
GLX::Colormap m_colormap;
|
||||||
bool m_ownsWindow;
|
GLX::GLXContext m_context;
|
||||||
};
|
GLX::Window m_window;
|
||||||
|
bool m_ownsWindow;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_CONTEXTIMPL_HPP
|
#endif // NAZARA_CONTEXTIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@
|
||||||
#include <Nazara/Math/Algorithm.hpp>
|
#include <Nazara/Math/Algorithm.hpp>
|
||||||
#include <Nazara/Renderer/Context.hpp>
|
#include <Nazara/Renderer/Context.hpp>
|
||||||
#include <Nazara/Renderer/RenderTarget.hpp>
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
|
#if defined(NAZARA_PLATFORM_GLX)
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
#endif // NAZARA_PLATFORM_GLX
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -30,7 +33,7 @@ namespace Nz
|
||||||
OpenGLFunc entry = reinterpret_cast<OpenGLFunc>(wglGetProcAddress(name));
|
OpenGLFunc entry = reinterpret_cast<OpenGLFunc>(wglGetProcAddress(name));
|
||||||
if (!entry) // wglGetProcAddress ne fonctionne pas sur les fonctions OpenGL <= 1.1
|
if (!entry) // wglGetProcAddress ne fonctionne pas sur les fonctions OpenGL <= 1.1
|
||||||
entry = reinterpret_cast<OpenGLFunc>(GetProcAddress(openGLlibrary, name));
|
entry = reinterpret_cast<OpenGLFunc>(GetProcAddress(openGLlibrary, name));
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_GLX)
|
||||||
OpenGLFunc entry = reinterpret_cast<OpenGLFunc>(GLX::glXGetProcAddress(reinterpret_cast<const unsigned char*>(name)));
|
OpenGLFunc entry = reinterpret_cast<OpenGLFunc>(GLX::glXGetProcAddress(reinterpret_cast<const unsigned char*>(name)));
|
||||||
#else
|
#else
|
||||||
#error OS not handled
|
#error OS not handled
|
||||||
|
|
@ -716,6 +719,15 @@ namespace Nz
|
||||||
if (s_initialized)
|
if (s_initialized)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#if defined(NAZARA_PLATFORM_GLX)
|
||||||
|
Initializer<X11> display;
|
||||||
|
if (!display)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to load display library");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!LoadLibrary())
|
if (!LoadLibrary())
|
||||||
{
|
{
|
||||||
NazaraError("Failed to load OpenGL library");
|
NazaraError("Failed to load OpenGL library");
|
||||||
|
|
@ -1004,7 +1016,7 @@ namespace Nz
|
||||||
wglGetExtensionsStringARB = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(LoadEntry("wglGetExtensionsStringARB", false));
|
wglGetExtensionsStringARB = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(LoadEntry("wglGetExtensionsStringARB", false));
|
||||||
wglGetExtensionsStringEXT = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGEXTPROC>(LoadEntry("wglGetExtensionsStringEXT", false));
|
wglGetExtensionsStringEXT = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGEXTPROC>(LoadEntry("wglGetExtensionsStringEXT", false));
|
||||||
wglSwapInterval = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(LoadEntry("wglSwapIntervalEXT", false));
|
wglSwapInterval = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(LoadEntry("wglSwapIntervalEXT", false));
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_GLX)
|
||||||
glXSwapIntervalEXT = reinterpret_cast<GLX::PFNGLXSWAPINTERVALEXTPROC>(LoadEntry("glXSwapIntervalEXT", false));
|
glXSwapIntervalEXT = reinterpret_cast<GLX::PFNGLXSWAPINTERVALEXTPROC>(LoadEntry("glXSwapIntervalEXT", false));
|
||||||
NzglXSwapIntervalMESA = reinterpret_cast<GLX::PFNGLXSWAPINTERVALMESAPROC>(LoadEntry("glXSwapIntervalMESA", false));
|
NzglXSwapIntervalMESA = reinterpret_cast<GLX::PFNGLXSWAPINTERVALMESAPROC>(LoadEntry("glXSwapIntervalMESA", false));
|
||||||
glXSwapIntervalSGI = reinterpret_cast<GLX::PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
|
glXSwapIntervalSGI = reinterpret_cast<GLX::PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
|
||||||
|
|
@ -2242,9 +2254,9 @@ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
|
||||||
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr;
|
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr;
|
||||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr;
|
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr;
|
||||||
PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr;
|
PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr;
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_GLX)
|
||||||
GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr;
|
GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr;
|
||||||
GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
|
GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
|
||||||
GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA = nullptr;
|
GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA = nullptr;
|
||||||
GLX::PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
|
GLX::PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@
|
||||||
|
|
||||||
void* operator new(std::size_t size)
|
void* operator new(std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, false);
|
return Nz::MemoryManager::Allocate(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](std::size_t size)
|
void* operator new[](std::size_t size)
|
||||||
{
|
{
|
||||||
return NzMemoryManager::Allocate(size, true);
|
return Nz::MemoryManager::Allocate(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* pointer) noexcept
|
void operator delete(void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, false);
|
Nz::MemoryManager::Free(pointer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* pointer) noexcept
|
void operator delete[](void* pointer) noexcept
|
||||||
{
|
{
|
||||||
NzMemoryManager::Free(pointer, true);
|
Nz::MemoryManager::Free(pointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_UTILITY_MANAGE_MEMORY
|
#endif // NAZARA_UTILITY_MANAGE_MEMORY
|
||||||
|
|
|
||||||
|
|
@ -12,150 +12,153 @@
|
||||||
#include <xcb/xcb_renderutil.h>
|
#include <xcb/xcb_renderutil.h>
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
bool NzCursorImpl::Create(const NzImage& cursor, int hotSpotX, int hotSpotY)
|
namespace Nz
|
||||||
{
|
{
|
||||||
NzImage cursorImage(cursor); // Vive le COW
|
bool CursorImpl::Create(const Image& cursor, int hotSpotX, int hotSpotY)
|
||||||
if (!cursorImage.Convert(nzPixelFormat_BGRA8))
|
|
||||||
{
|
{
|
||||||
NazaraError("Failed to convert cursor to BGRA8");
|
Image cursorImage(cursor); // Vive le COW
|
||||||
return false;
|
if (!cursorImage.Convert(Nz::PixelFormatType_BGRA8))
|
||||||
}
|
{
|
||||||
|
NazaraError("Failed to convert cursor to BGRA8");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto width = cursorImage.GetWidth();
|
auto width = cursorImage.GetWidth();
|
||||||
auto height = cursorImage.GetHeight();
|
auto height = cursorImage.GetHeight();
|
||||||
|
|
||||||
NzScopedXCBConnection connection;
|
ScopedXCBConnection connection;
|
||||||
|
|
||||||
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
|
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
|
||||||
|
|
||||||
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
ScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
NzScopedXCB<xcb_render_query_pict_formats_reply_t> formatsReply = xcb_render_query_pict_formats_reply(
|
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;
|
|
||||||
|
|
||||||
NzCallOnExit onExit([&](){
|
|
||||||
xcb_image_destroy(xi);
|
|
||||||
if (pic != XCB_NONE)
|
|
||||||
xcb_render_free_picture(connection, pic);
|
|
||||||
});
|
|
||||||
|
|
||||||
NzXCBPixmap 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,
|
connection,
|
||||||
pic,
|
xcb_render_query_pict_formats(connection),
|
||||||
pix,
|
&error);
|
||||||
fmt->id,
|
|
||||||
0,
|
|
||||||
nullptr
|
|
||||||
)))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to create render picture for cursor");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzXCBGContext gc(connection);
|
if (!formatsReply || error)
|
||||||
if (!gc.Create(pix, 0, nullptr))
|
{
|
||||||
{
|
NazaraError("Failed to get pict formats");
|
||||||
NazaraError("Failed to create gcontext for cursor");
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!X11::CheckCookie(
|
xcb_render_pictforminfo_t* fmt = xcb_render_util_find_standard_format(
|
||||||
connection,
|
formatsReply.get(),
|
||||||
xcb_image_put(
|
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,
|
connection,
|
||||||
pix,
|
xcb_render_create_picture(
|
||||||
gc,
|
connection,
|
||||||
xi,
|
pic,
|
||||||
0, 0,
|
pix,
|
||||||
0
|
fmt->id,
|
||||||
)))
|
0,
|
||||||
{
|
nullptr
|
||||||
NazaraError("Failed to put image for cursor");
|
)))
|
||||||
return false;
|
{
|
||||||
}
|
NazaraError("Failed to create render picture for cursor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_cursor = xcb_generate_id(connection);
|
XCBGContext gc(connection);
|
||||||
if (!X11::CheckCookie(
|
if (!gc.Create(pix, 0, nullptr))
|
||||||
connection,
|
{
|
||||||
xcb_render_create_cursor(
|
NazaraError("Failed to create gcontext for cursor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!X11::CheckCookie(
|
||||||
connection,
|
connection,
|
||||||
m_cursor,
|
xcb_image_put(
|
||||||
pic,
|
connection,
|
||||||
hotSpotX, hotSpotY
|
pix,
|
||||||
)))
|
gc,
|
||||||
{
|
xi,
|
||||||
NazaraError("Failed to create cursor");
|
0, 0,
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
void CursorImpl::Destroy()
|
||||||
}
|
{
|
||||||
|
ScopedXCBConnection connection;
|
||||||
|
|
||||||
void NzCursorImpl::Destroy()
|
xcb_free_cursor(connection, m_cursor);
|
||||||
{
|
m_cursor = 0;
|
||||||
NzScopedXCBConnection connection;
|
}
|
||||||
|
|
||||||
xcb_free_cursor(connection, m_cursor);
|
xcb_cursor_t CursorImpl::GetCursor()
|
||||||
m_cursor = 0;
|
{
|
||||||
}
|
return m_cursor;
|
||||||
|
}
|
||||||
xcb_cursor_t NzCursorImpl::GetCursor()
|
|
||||||
{
|
|
||||||
return m_cursor;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,20 +7,24 @@
|
||||||
#ifndef NAZARA_CURSORIMPL_HPP
|
#ifndef NAZARA_CURSORIMPL_HPP
|
||||||
#define NAZARA_CURSORIMPL_HPP
|
#define NAZARA_CURSORIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <xcb/xcb_cursor.h>
|
#include <xcb/xcb_cursor.h>
|
||||||
|
|
||||||
class NzImage;
|
namespace Nz
|
||||||
|
|
||||||
class NzCursorImpl
|
|
||||||
{
|
{
|
||||||
public:
|
class Image;
|
||||||
bool Create(const NzImage& image, int hotSpotX, int hotSpotY);
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
xcb_cursor_t GetCursor();
|
class CursorImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Create(const Image& image, int hotSpotX, int hotSpotY);
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
private:
|
xcb_cursor_t GetCursor();
|
||||||
xcb_cursor_t m_cursor;
|
|
||||||
};
|
private:
|
||||||
|
xcb_cursor_t m_cursor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_CURSORIMPL_HPP
|
#endif // NAZARA_CURSORIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -4,32 +4,34 @@
|
||||||
|
|
||||||
#include <Nazara/Utility/X11/Display.hpp>
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Core/Log.hpp>
|
||||||
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
namespace
|
namespace Nz
|
||||||
{
|
{
|
||||||
// The shared display and its reference counter
|
namespace
|
||||||
xcb_connection_t* sharedConnection = nullptr;
|
|
||||||
int screen_nbr = 0;
|
|
||||||
unsigned int referenceCountConnection = 0;
|
|
||||||
|
|
||||||
xcb_key_symbols_t* sharedkeySymbol;
|
|
||||||
unsigned int referenceCountKeySymbol = 0;
|
|
||||||
|
|
||||||
xcb_ewmh_connection_t* sharedEwmhConnection;
|
|
||||||
unsigned int referenceCountEwmhConnection = 0;
|
|
||||||
|
|
||||||
using AtomMap = std::map<std::string, xcb_atom_t>;
|
|
||||||
AtomMap atoms;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace X11
|
|
||||||
{
|
|
||||||
bool CheckCookie(xcb_connection_t* connection, xcb_void_cookie_t cookie)
|
|
||||||
{
|
{
|
||||||
NzScopedXCB<xcb_generic_error_t> error(xcb_request_check(
|
// 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,
|
connection,
|
||||||
cookie
|
cookie
|
||||||
));
|
));
|
||||||
|
|
@ -40,36 +42,36 @@ namespace X11
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloseConnection(xcb_connection_t* connection)
|
void X11::CloseConnection(xcb_connection_t* connection)
|
||||||
{
|
{
|
||||||
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
--referenceCountConnection;
|
--referenceCountConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloseEWMHConnection(xcb_ewmh_connection_t* ewmh_connection)
|
void X11::CloseEWMHConnection(xcb_ewmh_connection_t* ewmh_connection)
|
||||||
{
|
{
|
||||||
NazaraAssert(ewmh_connection == sharedEwmhConnection, "The model is meant for one connection to X11 server");
|
NazaraAssert(ewmh_connection == sharedEwmhConnection, "The model is meant for one connection to X11 server");
|
||||||
--referenceCountEwmhConnection;
|
--referenceCountEwmhConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_atom_t GetAtom(const std::string& name, bool onlyIfExists)
|
xcb_atom_t X11::GetAtom(const String& name, bool onlyIfExists)
|
||||||
{
|
{
|
||||||
AtomMap::const_iterator iter = atoms.find(name);
|
AtomMap::const_iterator iter = atoms.find(name);
|
||||||
|
|
||||||
if (iter != atoms.end())
|
if (iter != atoms.end())
|
||||||
return iter->second;
|
return iter->second;
|
||||||
|
|
||||||
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
ScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
|
|
||||||
xcb_connection_t* connection = OpenConnection();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
|
|
||||||
NzScopedXCB<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(
|
ScopedXCB<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(
|
||||||
connection,
|
connection,
|
||||||
xcb_intern_atom(
|
xcb_intern_atom(
|
||||||
connection,
|
connection,
|
||||||
onlyIfExists,
|
onlyIfExists,
|
||||||
name.size(),
|
name.GetSize(),
|
||||||
name.c_str()
|
name.GetConstBuffer()
|
||||||
),
|
),
|
||||||
&error
|
&error
|
||||||
));
|
));
|
||||||
|
|
@ -87,8 +89,16 @@ namespace X11
|
||||||
return reply->atom;
|
return reply->atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize()
|
bool X11::Initialize()
|
||||||
{
|
{
|
||||||
|
if (IsInitialized())
|
||||||
|
{
|
||||||
|
s_moduleReferenceCounter++;
|
||||||
|
return true; // Déjà initialisé
|
||||||
|
}
|
||||||
|
|
||||||
|
s_moduleReferenceCounter++;
|
||||||
|
|
||||||
NazaraAssert(referenceCountConnection == 0, "Initialize should be called before anything");
|
NazaraAssert(referenceCountConnection == 0, "Initialize should be called before anything");
|
||||||
NazaraAssert(referenceCountKeySymbol == 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");
|
NazaraAssert(referenceCountEwmhConnection == 0, "Initialize should be called before anything");
|
||||||
|
|
@ -125,9 +135,17 @@ namespace X11
|
||||||
|
|
||||||
OpenEWMHConnection(sharedConnection);
|
OpenEWMHConnection(sharedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NazaraNotice("Initialized: Utility module");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_key_symbols_t* XCBKeySymbolsAlloc(xcb_connection_t* connection)
|
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");
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
|
||||||
|
|
@ -135,20 +153,20 @@ namespace X11
|
||||||
return sharedkeySymbol;
|
return sharedkeySymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols)
|
void X11::XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols)
|
||||||
{
|
{
|
||||||
NazaraAssert(keySymbols == sharedkeySymbol, "The model is meant for one connection to X11 server");
|
NazaraAssert(keySymbols == sharedkeySymbol, "The model is meant for one connection to X11 server");
|
||||||
|
|
||||||
--referenceCountKeySymbol;
|
--referenceCountKeySymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_connection_t* OpenConnection()
|
xcb_connection_t* X11::OpenConnection()
|
||||||
{
|
{
|
||||||
++referenceCountConnection;
|
++referenceCountConnection;
|
||||||
return sharedConnection;
|
return sharedConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_ewmh_connection_t* OpenEWMHConnection(xcb_connection_t* connection)
|
xcb_ewmh_connection_t* X11::OpenEWMHConnection(xcb_connection_t* connection)
|
||||||
{
|
{
|
||||||
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
|
||||||
|
|
@ -156,8 +174,19 @@ namespace X11
|
||||||
return sharedEwmhConnection;
|
return sharedEwmhConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Uninitialize()
|
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");
|
NazaraAssert(referenceCountEwmhConnection == 1, "Uninitialize should be called after anything or a close is missing");
|
||||||
CloseEWMHConnection(sharedEwmhConnection);
|
CloseEWMHConnection(sharedEwmhConnection);
|
||||||
|
|
@ -179,9 +208,11 @@ namespace X11
|
||||||
|
|
||||||
xcb_disconnect(sharedConnection);
|
xcb_disconnect(sharedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NazaraNotice("Uninitialized: Display module");
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection)
|
xcb_window_t X11::XCBDefaultRootWindow(xcb_connection_t* connection)
|
||||||
{
|
{
|
||||||
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
xcb_screen_t* screen = XCBDefaultScreen(connection);
|
xcb_screen_t* screen = XCBDefaultScreen(connection);
|
||||||
|
|
@ -190,19 +221,19 @@ namespace X11
|
||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection)
|
xcb_screen_t* X11::XCBDefaultScreen(xcb_connection_t* connection)
|
||||||
{
|
{
|
||||||
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
return XCBScreenOfDisplay(connection, screen_nbr);
|
return XCBScreenOfDisplay(connection, screen_nbr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int XCBScreen(xcb_connection_t* connection)
|
int X11::XCBScreen(xcb_connection_t* connection)
|
||||||
{
|
{
|
||||||
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
return screen_nbr;
|
return screen_nbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr)
|
xcb_screen_t* X11::XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr)
|
||||||
{
|
{
|
||||||
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
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));
|
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
|
||||||
|
|
@ -215,4 +246,6 @@ namespace X11
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int X11::s_moduleReferenceCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,35 +7,47 @@
|
||||||
#ifndef NAZARA_X11DISPLAY_HPP
|
#ifndef NAZARA_X11DISPLAY_HPP
|
||||||
#define NAZARA_X11DISPLAY_HPP
|
#define NAZARA_X11DISPLAY_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Utility/WindowHandle.hpp>
|
#include <Nazara/Utility/WindowHandle.hpp>
|
||||||
#include <Nazara/Utility/X11/ScopedXCB.hpp>
|
#include <Nazara/Utility/X11/ScopedXCB.hpp>
|
||||||
#include <xcb/xcb_ewmh.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
typedef struct _XCBKeySymbols xcb_key_symbols_t;
|
typedef struct _XCBKeySymbols xcb_key_symbols_t;
|
||||||
|
|
||||||
namespace X11
|
namespace Nz
|
||||||
{
|
{
|
||||||
bool CheckCookie(xcb_connection_t* connection, xcb_void_cookie_t cookie);
|
class String;
|
||||||
void CloseConnection(xcb_connection_t* connection);
|
|
||||||
void CloseEWMHConnection(xcb_ewmh_connection_t* ewmh_connection);
|
|
||||||
|
|
||||||
xcb_atom_t GetAtom(const std::string& name, bool onlyIfExists = false);
|
class X11
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
X11() = delete;
|
||||||
|
~X11() = delete;
|
||||||
|
|
||||||
void Initialize();
|
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);
|
||||||
|
|
||||||
xcb_key_symbols_t* XCBKeySymbolsAlloc(xcb_connection_t* connection);
|
static xcb_atom_t GetAtom(const String& name, bool onlyIfExists = false);
|
||||||
void XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols);
|
|
||||||
|
|
||||||
xcb_connection_t* OpenConnection();
|
static bool Initialize();
|
||||||
xcb_ewmh_connection_t* OpenEWMHConnection(xcb_connection_t* connection);
|
static bool IsInitialized();
|
||||||
|
|
||||||
void Uninitialize();
|
static xcb_key_symbols_t* XCBKeySymbolsAlloc(xcb_connection_t* connection);
|
||||||
|
static void XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols);
|
||||||
|
|
||||||
xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection);
|
static xcb_connection_t* OpenConnection();
|
||||||
xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection);
|
static xcb_ewmh_connection_t* OpenEWMHConnection(xcb_connection_t* connection);
|
||||||
int XCBScreen(xcb_connection_t* connection);
|
|
||||||
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr);
|
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
|
#endif // NAZARA_X11DISPLAY_HPP
|
||||||
|
|
|
||||||
|
|
@ -10,125 +10,128 @@
|
||||||
#include <Nazara/Utility/X11/Display.hpp>
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
NzIconImpl::NzIconImpl()
|
namespace Nz
|
||||||
{
|
{
|
||||||
NzScopedXCBConnection connection;
|
IconImpl::IconImpl()
|
||||||
|
|
||||||
m_iconPixmap.Connect(connection);
|
|
||||||
m_maskPixmap.Connect(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzIconImpl::Create(const NzImage& icon)
|
|
||||||
{
|
|
||||||
NzImage iconImage(icon); // Vive le COW
|
|
||||||
if (!iconImage.Convert(nzPixelFormat_BGRA8))
|
|
||||||
{
|
{
|
||||||
NazaraError("Failed to convert icon to BGRA8");
|
ScopedXCBConnection connection;
|
||||||
return false;
|
|
||||||
|
m_iconPixmap.Connect(connection);
|
||||||
|
m_maskPixmap.Connect(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto width = iconImage.GetWidth();
|
bool IconImpl::Create(const Image& icon)
|
||||||
auto height = iconImage.GetHeight();
|
|
||||||
|
|
||||||
NzScopedXCBConnection 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");
|
Image iconImage(icon); // Vive le COW
|
||||||
return false;
|
if (!iconImage.Convert(Nz::PixelFormatType_BGRA8))
|
||||||
}
|
|
||||||
|
|
||||||
NzCallOnExit onExit([this](){
|
|
||||||
Destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
NzXCBGContext 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<nzUInt8> 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)
|
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)
|
||||||
{
|
{
|
||||||
if (i * 8 + k < width)
|
for (std::size_t k = 0; k < 8; ++k)
|
||||||
{
|
{
|
||||||
nzUInt8 opacity = (iconImage.GetConstPixels()[(i * 8 + k + j * width) * 4 + 3] > 0) ? 1 : 0;
|
if (i * 8 + k < width)
|
||||||
maskPixels[i + j * pitch] |= (opacity << k);
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_maskPixmap.CreatePixmapFromBitmapData(
|
void IconImpl::Destroy()
|
||||||
X11::XCBDefaultRootWindow(connection),
|
|
||||||
reinterpret_cast<uint8_t*>(&maskPixels[0]),
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
nullptr))
|
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create mask pixmap for icon");
|
m_iconPixmap.Destroy();
|
||||||
return false;
|
m_maskPixmap.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
onExit.Reset();
|
xcb_pixmap_t IconImpl::GetIcon()
|
||||||
|
{
|
||||||
|
return m_iconPixmap;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
xcb_pixmap_t IconImpl::GetMask()
|
||||||
}
|
{
|
||||||
|
return m_maskPixmap;
|
||||||
void NzIconImpl::Destroy()
|
}
|
||||||
{
|
|
||||||
m_iconPixmap.Destroy();
|
|
||||||
m_maskPixmap.Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_pixmap_t NzIconImpl::GetIcon()
|
|
||||||
{
|
|
||||||
return m_iconPixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_pixmap_t NzIconImpl::GetMask()
|
|
||||||
{
|
|
||||||
return m_maskPixmap;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,28 @@
|
||||||
#ifndef NAZARA_ICONIMPL_HPP
|
#ifndef NAZARA_ICONIMPL_HPP
|
||||||
#define NAZARA_ICONIMPL_HPP
|
#define NAZARA_ICONIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Utility/X11/ScopedXCB.hpp>
|
#include <Nazara/Utility/X11/ScopedXCB.hpp>
|
||||||
|
|
||||||
class NzImage;
|
namespace Nz
|
||||||
|
|
||||||
class NzIconImpl
|
|
||||||
{
|
{
|
||||||
public:
|
class Image;
|
||||||
NzIconImpl();
|
|
||||||
|
|
||||||
bool Create(const NzImage& image);
|
class IconImpl
|
||||||
void Destroy();
|
{
|
||||||
|
public:
|
||||||
|
IconImpl();
|
||||||
|
|
||||||
xcb_pixmap_t GetIcon();
|
bool Create(const Image& image);
|
||||||
xcb_pixmap_t GetMask();
|
void Destroy();
|
||||||
|
|
||||||
private:
|
xcb_pixmap_t GetIcon();
|
||||||
NzXCBPixmap m_iconPixmap;
|
xcb_pixmap_t GetMask();
|
||||||
NzXCBPixmap m_maskPixmap;
|
|
||||||
};
|
private:
|
||||||
|
XCBPixmap m_iconPixmap;
|
||||||
|
XCBPixmap m_maskPixmap;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NAZARA_ICONIMPL_HPP
|
#endif // NAZARA_ICONIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -12,215 +12,186 @@
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
namespace
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
KeySym GetKeySym(NzKeyboard::Key key)
|
|
||||||
{
|
{
|
||||||
// X11 keysym correspondant
|
KeySym GetKeySym(Keyboard::Key key)
|
||||||
KeySym keysym = 0;
|
|
||||||
switch (key)
|
|
||||||
{
|
{
|
||||||
// Lettres
|
// X11 keysym correspondant
|
||||||
case NzKeyboard::A: keysym = XK_A; break;
|
KeySym keysym = 0;
|
||||||
case NzKeyboard::B: keysym = XK_B; break;
|
switch (key)
|
||||||
case NzKeyboard::C: keysym = XK_C; break;
|
{
|
||||||
case NzKeyboard::D: keysym = XK_D; break;
|
// Lettres
|
||||||
case NzKeyboard::E: keysym = XK_E; break;
|
case Keyboard::A: keysym = XK_A; break;
|
||||||
case NzKeyboard::F: keysym = XK_F; break;
|
case Keyboard::B: keysym = XK_B; break;
|
||||||
case NzKeyboard::G: keysym = XK_G; break;
|
case Keyboard::C: keysym = XK_C; break;
|
||||||
case NzKeyboard::H: keysym = XK_H; break;
|
case Keyboard::D: keysym = XK_D; break;
|
||||||
case NzKeyboard::I: keysym = XK_I; break;
|
case Keyboard::E: keysym = XK_E; break;
|
||||||
case NzKeyboard::J: keysym = XK_J; break;
|
case Keyboard::F: keysym = XK_F; break;
|
||||||
case NzKeyboard::K: keysym = XK_K; break;
|
case Keyboard::G: keysym = XK_G; break;
|
||||||
case NzKeyboard::L: keysym = XK_L; break;
|
case Keyboard::H: keysym = XK_H; break;
|
||||||
case NzKeyboard::M: keysym = XK_M; break;
|
case Keyboard::I: keysym = XK_I; break;
|
||||||
case NzKeyboard::N: keysym = XK_N; break;
|
case Keyboard::J: keysym = XK_J; break;
|
||||||
case NzKeyboard::O: keysym = XK_O; break;
|
case Keyboard::K: keysym = XK_K; break;
|
||||||
case NzKeyboard::P: keysym = XK_P; break;
|
case Keyboard::L: keysym = XK_L; break;
|
||||||
case NzKeyboard::Q: keysym = XK_Q; break;
|
case Keyboard::M: keysym = XK_M; break;
|
||||||
case NzKeyboard::R: keysym = XK_R; break;
|
case Keyboard::N: keysym = XK_N; break;
|
||||||
case NzKeyboard::S: keysym = XK_S; break;
|
case Keyboard::O: keysym = XK_O; break;
|
||||||
case NzKeyboard::T: keysym = XK_T; break;
|
case Keyboard::P: keysym = XK_P; break;
|
||||||
case NzKeyboard::U: keysym = XK_U; break;
|
case Keyboard::Q: keysym = XK_Q; break;
|
||||||
case NzKeyboard::V: keysym = XK_V; break;
|
case Keyboard::R: keysym = XK_R; break;
|
||||||
case NzKeyboard::W: keysym = XK_W; break;
|
case Keyboard::S: keysym = XK_S; break;
|
||||||
case NzKeyboard::X: keysym = XK_X; break;
|
case Keyboard::T: keysym = XK_T; break;
|
||||||
case NzKeyboard::Y: keysym = XK_Y; break;
|
case Keyboard::U: keysym = XK_U; break;
|
||||||
case NzKeyboard::Z: keysym = XK_Z; 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
|
// Touches de fonction
|
||||||
case NzKeyboard::F1: keysym = XK_F1; break;
|
case Keyboard::F1: keysym = XK_F1; break;
|
||||||
case NzKeyboard::F2: keysym = XK_F2; break;
|
case Keyboard::F2: keysym = XK_F2; break;
|
||||||
case NzKeyboard::F3: keysym = XK_F3; break;
|
case Keyboard::F3: keysym = XK_F3; break;
|
||||||
case NzKeyboard::F4: keysym = XK_F4; break;
|
case Keyboard::F4: keysym = XK_F4; break;
|
||||||
case NzKeyboard::F5: keysym = XK_F5; break;
|
case Keyboard::F5: keysym = XK_F5; break;
|
||||||
case NzKeyboard::F6: keysym = XK_F6; break;
|
case Keyboard::F6: keysym = XK_F6; break;
|
||||||
case NzKeyboard::F7: keysym = XK_F7; break;
|
case Keyboard::F7: keysym = XK_F7; break;
|
||||||
case NzKeyboard::F8: keysym = XK_F8; break;
|
case Keyboard::F8: keysym = XK_F8; break;
|
||||||
case NzKeyboard::F9: keysym = XK_F9; break;
|
case Keyboard::F9: keysym = XK_F9; break;
|
||||||
case NzKeyboard::F10: keysym = XK_F10; break;
|
case Keyboard::F10: keysym = XK_F10; break;
|
||||||
case NzKeyboard::F11: keysym = XK_F11; break;
|
case Keyboard::F11: keysym = XK_F11; break;
|
||||||
case NzKeyboard::F12: keysym = XK_F12; break;
|
case Keyboard::F12: keysym = XK_F12; break;
|
||||||
case NzKeyboard::F13: keysym = XK_F13; break;
|
case Keyboard::F13: keysym = XK_F13; break;
|
||||||
case NzKeyboard::F14: keysym = XK_F14; break;
|
case Keyboard::F14: keysym = XK_F14; break;
|
||||||
case NzKeyboard::F15: keysym = XK_F15; break;
|
case Keyboard::F15: keysym = XK_F15; break;
|
||||||
|
|
||||||
// Flèches directionnelles
|
// Flèches directionnelles
|
||||||
case NzKeyboard::Down: keysym = XK_Down; break;
|
case Keyboard::Down: keysym = XK_Down; break;
|
||||||
case NzKeyboard::Left: keysym = XK_Left; break;
|
case Keyboard::Left: keysym = XK_Left; break;
|
||||||
case NzKeyboard::Right: keysym = XK_Right; break;
|
case Keyboard::Right: keysym = XK_Right; break;
|
||||||
case NzKeyboard::Up: keysym = XK_Up; break;
|
case Keyboard::Up: keysym = XK_Up; break;
|
||||||
|
|
||||||
// Pavé numérique
|
// Pavé numérique
|
||||||
case NzKeyboard::Add: keysym = XK_KP_Add; break;
|
case Keyboard::Add: keysym = XK_KP_Add; break;
|
||||||
case NzKeyboard::Decimal: keysym = XK_KP_Decimal; break;
|
case Keyboard::Decimal: keysym = XK_KP_Decimal; break;
|
||||||
case NzKeyboard::Divide: keysym = XK_KP_Divide; break;
|
case Keyboard::Divide: keysym = XK_KP_Divide; break;
|
||||||
case NzKeyboard::Multiply: keysym = XK_KP_Multiply; break;
|
case Keyboard::Multiply: keysym = XK_KP_Multiply; break;
|
||||||
case NzKeyboard::Numpad0: keysym = XK_KP_0; break;
|
case Keyboard::Numpad0: keysym = XK_KP_0; break;
|
||||||
case NzKeyboard::Numpad1: keysym = XK_KP_1; break;
|
case Keyboard::Numpad1: keysym = XK_KP_1; break;
|
||||||
case NzKeyboard::Numpad2: keysym = XK_KP_2; break;
|
case Keyboard::Numpad2: keysym = XK_KP_2; break;
|
||||||
case NzKeyboard::Numpad3: keysym = XK_KP_3; break;
|
case Keyboard::Numpad3: keysym = XK_KP_3; break;
|
||||||
case NzKeyboard::Numpad4: keysym = XK_KP_4; break;
|
case Keyboard::Numpad4: keysym = XK_KP_4; break;
|
||||||
case NzKeyboard::Numpad5: keysym = XK_KP_5; break;
|
case Keyboard::Numpad5: keysym = XK_KP_5; break;
|
||||||
case NzKeyboard::Numpad6: keysym = XK_KP_6; break;
|
case Keyboard::Numpad6: keysym = XK_KP_6; break;
|
||||||
case NzKeyboard::Numpad7: keysym = XK_KP_7; break;
|
case Keyboard::Numpad7: keysym = XK_KP_7; break;
|
||||||
case NzKeyboard::Numpad8: keysym = XK_KP_8; break;
|
case Keyboard::Numpad8: keysym = XK_KP_8; break;
|
||||||
case NzKeyboard::Numpad9: keysym = XK_KP_9; break;
|
case Keyboard::Numpad9: keysym = XK_KP_9; break;
|
||||||
case NzKeyboard::Subtract: keysym = XK_KP_Subtract; break;
|
case Keyboard::Subtract: keysym = XK_KP_Subtract; break;
|
||||||
|
|
||||||
// Divers
|
// Divers
|
||||||
case NzKeyboard::Backslash: keysym = XK_backslash; break;
|
case Keyboard::Backslash: keysym = XK_backslash; break;
|
||||||
case NzKeyboard::Backspace: keysym = XK_BackSpace; break;
|
case Keyboard::Backspace: keysym = XK_BackSpace; break;
|
||||||
case NzKeyboard::Clear: keysym = XK_Clear; break;
|
case Keyboard::Clear: keysym = XK_Clear; break;
|
||||||
case NzKeyboard::Comma: keysym = XK_comma; break;
|
case Keyboard::Comma: keysym = XK_comma; break;
|
||||||
case NzKeyboard::Dash: keysym = XK_minus; break;
|
case Keyboard::Dash: keysym = XK_minus; break;
|
||||||
case NzKeyboard::Delete: keysym = XK_Delete; break;
|
case Keyboard::Delete: keysym = XK_Delete; break;
|
||||||
case NzKeyboard::End: keysym = XK_End; break;
|
case Keyboard::End: keysym = XK_End; break;
|
||||||
case NzKeyboard::Equal: keysym = XK_equal; break;
|
case Keyboard::Equal: keysym = XK_equal; break;
|
||||||
case NzKeyboard::Escape: keysym = XK_Escape; break;
|
case Keyboard::Escape: keysym = XK_Escape; break;
|
||||||
case NzKeyboard::Home: keysym = XK_Home; break;
|
case Keyboard::Home: keysym = XK_Home; break;
|
||||||
case NzKeyboard::Insert: keysym = XK_Insert; break;
|
case Keyboard::Insert: keysym = XK_Insert; break;
|
||||||
case NzKeyboard::LAlt: keysym = XK_Alt_L; break;
|
case Keyboard::LAlt: keysym = XK_Alt_L; break;
|
||||||
case NzKeyboard::LBracket: keysym = XK_bracketleft; break;
|
case Keyboard::LBracket: keysym = XK_bracketleft; break;
|
||||||
case NzKeyboard::LControl: keysym = XK_Control_L; break;
|
case Keyboard::LControl: keysym = XK_Control_L; break;
|
||||||
case NzKeyboard::LShift: keysym = XK_Shift_L; break;
|
case Keyboard::LShift: keysym = XK_Shift_L; break;
|
||||||
case NzKeyboard::LSystem: keysym = XK_Super_L; break;
|
case Keyboard::LSystem: keysym = XK_Super_L; break;
|
||||||
case NzKeyboard::Num0: keysym = XK_0; break;
|
case Keyboard::Num0: keysym = XK_0; break;
|
||||||
case NzKeyboard::Num1: keysym = XK_1; break;
|
case Keyboard::Num1: keysym = XK_1; break;
|
||||||
case NzKeyboard::Num2: keysym = XK_2; break;
|
case Keyboard::Num2: keysym = XK_2; break;
|
||||||
case NzKeyboard::Num3: keysym = XK_3; break;
|
case Keyboard::Num3: keysym = XK_3; break;
|
||||||
case NzKeyboard::Num4: keysym = XK_4; break;
|
case Keyboard::Num4: keysym = XK_4; break;
|
||||||
case NzKeyboard::Num5: keysym = XK_5; break;
|
case Keyboard::Num5: keysym = XK_5; break;
|
||||||
case NzKeyboard::Num6: keysym = XK_6; break;
|
case Keyboard::Num6: keysym = XK_6; break;
|
||||||
case NzKeyboard::Num7: keysym = XK_7; break;
|
case Keyboard::Num7: keysym = XK_7; break;
|
||||||
case NzKeyboard::Num8: keysym = XK_8; break;
|
case Keyboard::Num8: keysym = XK_8; break;
|
||||||
case NzKeyboard::Num9: keysym = XK_9; break;
|
case Keyboard::Num9: keysym = XK_9; break;
|
||||||
case NzKeyboard::PageDown: keysym = XK_Page_Down; break;
|
case Keyboard::PageDown: keysym = XK_Page_Down; break;
|
||||||
case NzKeyboard::PageUp: keysym = XK_Page_Up; break;
|
case Keyboard::PageUp: keysym = XK_Page_Up; break;
|
||||||
case NzKeyboard::Pause: keysym = XK_Pause; break;
|
case Keyboard::Pause: keysym = XK_Pause; break;
|
||||||
case NzKeyboard::Period: keysym = XK_period; break;
|
case Keyboard::Period: keysym = XK_period; break;
|
||||||
case NzKeyboard::Print: keysym = XK_Print; break;
|
case Keyboard::Print: keysym = XK_Print; break;
|
||||||
case NzKeyboard::PrintScreen: keysym = XK_Sys_Req; break;
|
case Keyboard::PrintScreen: keysym = XK_Sys_Req; break;
|
||||||
case NzKeyboard::Quote: keysym = XK_quotedbl; break;
|
case Keyboard::Quote: keysym = XK_quotedbl; break;
|
||||||
case NzKeyboard::RAlt: keysym = XK_Alt_R; break;
|
case Keyboard::RAlt: keysym = XK_Alt_R; break;
|
||||||
case NzKeyboard::RBracket: keysym = XK_bracketright; break;
|
case Keyboard::RBracket: keysym = XK_bracketright; break;
|
||||||
case NzKeyboard::RControl: keysym = XK_Control_R; break;
|
case Keyboard::RControl: keysym = XK_Control_R; break;
|
||||||
case NzKeyboard::Return: keysym = XK_Return; break;
|
case Keyboard::Return: keysym = XK_Return; break;
|
||||||
case NzKeyboard::RShift: keysym = XK_Shift_R; break;
|
case Keyboard::RShift: keysym = XK_Shift_R; break;
|
||||||
case NzKeyboard::RSystem: keysym = XK_Super_R; break;
|
case Keyboard::RSystem: keysym = XK_Super_R; break;
|
||||||
case NzKeyboard::Semicolon: keysym = XK_semicolon; break;
|
case Keyboard::Semicolon: keysym = XK_semicolon; break;
|
||||||
case NzKeyboard::Slash: keysym = XK_slash; break;
|
case Keyboard::Slash: keysym = XK_slash; break;
|
||||||
case NzKeyboard::Space: keysym = XK_space; break;
|
case Keyboard::Space: keysym = XK_space; break;
|
||||||
case NzKeyboard::Tab: keysym = XK_Tab; break;
|
case Keyboard::Tab: keysym = XK_Tab; break;
|
||||||
case NzKeyboard::Tilde: keysym = XK_grave; break;
|
case Keyboard::Tilde: keysym = XK_grave; break;
|
||||||
|
|
||||||
// Touches navigateur
|
// Touches navigateur
|
||||||
case NzKeyboard::Browser_Back: keysym = XF86XK_Back; break;
|
case Keyboard::Browser_Back: keysym = XF86XK_Back; break;
|
||||||
case NzKeyboard::Browser_Favorites: keysym = XF86XK_Favorites; break;
|
case Keyboard::Browser_Favorites: keysym = XF86XK_Favorites; break;
|
||||||
case NzKeyboard::Browser_Forward: keysym = XF86XK_Forward; break;
|
case Keyboard::Browser_Forward: keysym = XF86XK_Forward; break;
|
||||||
case NzKeyboard::Browser_Home: keysym = XF86XK_HomePage; break;
|
case Keyboard::Browser_Home: keysym = XF86XK_HomePage; break;
|
||||||
case NzKeyboard::Browser_Refresh: keysym = XF86XK_Refresh; break;
|
case Keyboard::Browser_Refresh: keysym = XF86XK_Refresh; break;
|
||||||
case NzKeyboard::Browser_Search: keysym = XF86XK_Search; break;
|
case Keyboard::Browser_Search: keysym = XF86XK_Search; break;
|
||||||
case NzKeyboard::Browser_Stop: keysym = XF86XK_Stop; break;
|
case Keyboard::Browser_Stop: keysym = XF86XK_Stop; break;
|
||||||
|
|
||||||
// Touches de contrôle
|
// Touches de contrôle
|
||||||
case NzKeyboard::Media_Next: keysym = XF86XK_AudioNext; break;
|
case Keyboard::Media_Next: keysym = XF86XK_AudioNext; break;
|
||||||
case NzKeyboard::Media_Play: keysym = XF86XK_AudioPlay; break;
|
case Keyboard::Media_Play: keysym = XF86XK_AudioPlay; break;
|
||||||
case NzKeyboard::Media_Previous: keysym = XF86XK_AudioPrev; break;
|
case Keyboard::Media_Previous: keysym = XF86XK_AudioPrev; break;
|
||||||
case NzKeyboard::Media_Stop: keysym = XF86XK_AudioStop; break;
|
case Keyboard::Media_Stop: keysym = XF86XK_AudioStop; break;
|
||||||
|
|
||||||
// Touches de contrôle du volume
|
// Touches de contrôle du volume
|
||||||
case NzKeyboard::Volume_Down: keysym = XF86XK_AudioLowerVolume; break;
|
case Keyboard::Volume_Down: keysym = XF86XK_AudioLowerVolume; break;
|
||||||
case NzKeyboard::Volume_Mute: keysym = XF86XK_AudioMute; break;
|
case Keyboard::Volume_Mute: keysym = XF86XK_AudioMute; break;
|
||||||
case NzKeyboard::Volume_Up: keysym = XF86XK_AudioRaiseVolume; break;
|
case Keyboard::Volume_Up: keysym = XF86XK_AudioRaiseVolume; break;
|
||||||
|
|
||||||
// Touches à verrouillage
|
// Touches à verrouillage
|
||||||
case NzKeyboard::CapsLock: keysym = XK_Caps_Lock; break;
|
case Keyboard::CapsLock: keysym = XK_Caps_Lock; break;
|
||||||
case NzKeyboard::NumLock: keysym = XK_Num_Lock; break;
|
case Keyboard::NumLock: keysym = XK_Num_Lock; break;
|
||||||
case NzKeyboard::ScrollLock: keysym = XK_Scroll_Lock; break;
|
case Keyboard::ScrollLock: keysym = XK_Scroll_Lock; break;
|
||||||
|
|
||||||
default: 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity checks
|
|
||||||
if (key < 0 || key >= NzKeyboard::Count || keysym == 0)
|
|
||||||
NazaraWarning("Key " + NzString::Number(key) + " is not handled in NzKeyboard");
|
|
||||||
|
|
||||||
return keysym;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NzString NzEventImpl::GetKeyName(NzKeyboard::Key key)
|
|
||||||
{
|
|
||||||
KeySym keySym = GetKeySym(key);
|
|
||||||
|
|
||||||
// XKeysymToString returns a static area.
|
|
||||||
return XKeysymToString(keySym);
|
|
||||||
}
|
|
||||||
|
|
||||||
NzVector2i NzEventImpl::GetMousePosition()
|
|
||||||
{
|
|
||||||
NzScopedXCBConnection connection;
|
|
||||||
|
|
||||||
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
|
||||||
|
|
||||||
NzScopedXCB<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 NzVector2i(-1, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NzVector2i(pointer->root_x, pointer->root_y);
|
String EventImpl::GetKeyName(Keyboard::Key key)
|
||||||
}
|
|
||||||
|
|
||||||
NzVector2i NzEventImpl::GetMousePosition(const NzWindow& relativeTo)
|
|
||||||
{
|
|
||||||
NzWindowHandle handle = relativeTo.GetHandle();
|
|
||||||
if (handle)
|
|
||||||
{
|
{
|
||||||
// Open a connection with the X server
|
KeySym keySym = GetKeySym(key);
|
||||||
NzScopedXCBConnection connection;
|
|
||||||
|
|
||||||
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
// XKeysymToString returns a static area.
|
||||||
|
return XKeysymToString(keySym);
|
||||||
|
}
|
||||||
|
|
||||||
NzScopedXCB<xcb_query_pointer_reply_t> pointer(
|
Vector2i EventImpl::GetMousePosition()
|
||||||
|
{
|
||||||
|
ScopedXCBConnection connection;
|
||||||
|
|
||||||
|
ScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
|
|
||||||
|
ScopedXCB<xcb_query_pointer_reply_t> pointer(
|
||||||
xcb_query_pointer_reply(
|
xcb_query_pointer_reply(
|
||||||
connection,
|
connection,
|
||||||
xcb_query_pointer(
|
xcb_query_pointer(
|
||||||
connection,
|
connection,
|
||||||
handle
|
X11::XCBDefaultRootWindow(connection)
|
||||||
),
|
),
|
||||||
&error
|
&error
|
||||||
)
|
)
|
||||||
|
|
@ -229,143 +200,174 @@ NzVector2i NzEventImpl::GetMousePosition(const NzWindow& relativeTo)
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to query pointer");
|
NazaraError("Failed to query pointer");
|
||||||
return NzVector2i(-1, -1);
|
return Vector2i(-1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NzVector2i(pointer->win_x, pointer->win_y);
|
return Vector2i(pointer->root_x, pointer->root_y);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
Vector2i EventImpl::GetMousePosition(const Window& relativeTo)
|
||||||
{
|
{
|
||||||
NazaraError("No window handle");
|
WindowHandle handle = relativeTo.GetHandle();
|
||||||
return NzVector2i(-1, -1);
|
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 NzEventImpl::IsKeyPressed(NzKeyboard::Key key)
|
bool EventImpl::IsKeyPressed(Keyboard::Key key)
|
||||||
{
|
|
||||||
NzScopedXCBConnection connection;
|
|
||||||
|
|
||||||
xcb_keysym_t keySym = GetKeySym(key);
|
|
||||||
|
|
||||||
xcb_key_symbols_t* keySymbols = X11::XCBKeySymbolsAlloc(connection);
|
|
||||||
if (!keySymbols)
|
|
||||||
{
|
{
|
||||||
NazaraError("Failed to alloc key symbols");
|
ScopedXCBConnection connection;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzScopedXCB<xcb_keycode_t> keyCode = xcb_key_symbols_get_keycode(keySymbols, keySym);
|
xcb_keysym_t keySym = GetKeySym(key);
|
||||||
if (!keyCode)
|
|
||||||
{
|
|
||||||
NazaraError("Failed to get key code");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
X11::XCBKeySymbolsFree(keySymbols);
|
|
||||||
|
|
||||||
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
xcb_key_symbols_t* keySymbols = X11::XCBKeySymbolsAlloc(connection);
|
||||||
|
if (!keySymbols)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to alloc key symbols");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the whole keyboard state
|
ScopedXCB<xcb_keycode_t> keyCode = xcb_key_symbols_get_keycode(keySymbols, keySym);
|
||||||
NzScopedXCB<xcb_query_keymap_reply_t> keymap(
|
if (!keyCode)
|
||||||
xcb_query_keymap_reply(
|
{
|
||||||
connection,
|
NazaraError("Failed to get key code");
|
||||||
xcb_query_keymap(connection),
|
return false;
|
||||||
&error
|
}
|
||||||
)
|
X11::XCBKeySymbolsFree(keySymbols);
|
||||||
);
|
|
||||||
|
|
||||||
if (error)
|
ScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
{
|
|
||||||
NazaraError("Failed to query keymap");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check our keycode
|
// Get the whole keyboard state
|
||||||
return (keymap->keys[*keyCode.get() / 8] & (1 << (*keyCode.get() % 8))) != 0;
|
ScopedXCB<xcb_query_keymap_reply_t> keymap(
|
||||||
}
|
xcb_query_keymap_reply(
|
||||||
|
|
||||||
bool NzEventImpl::IsMouseButtonPressed(NzMouse::Button button)
|
|
||||||
{
|
|
||||||
NzScopedXCBConnection connection;
|
|
||||||
|
|
||||||
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
|
||||||
|
|
||||||
// Get pointer mask
|
|
||||||
NzScopedXCB<xcb_query_pointer_reply_t> pointer(
|
|
||||||
xcb_query_pointer_reply(
|
|
||||||
connection,
|
|
||||||
xcb_query_pointer(
|
|
||||||
connection,
|
connection,
|
||||||
X11::XCBDefaultRootWindow(connection)
|
xcb_query_keymap(connection),
|
||||||
),
|
&error
|
||||||
&error
|
)
|
||||||
)
|
);
|
||||||
);
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to query keymap");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check our keycode
|
||||||
|
return (keymap->keys[*keyCode.get() / 8] & (1 << (*keyCode.get() % 8))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EventImpl::IsMouseButtonPressed(Mouse::Button button)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to query pointer");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t buttons = pointer->mask;
|
void EventImpl::SetMousePosition(int x, int y)
|
||||||
|
|
||||||
switch (button)
|
|
||||||
{
|
{
|
||||||
case NzMouse::Left: return buttons & XCB_BUTTON_MASK_1;
|
ScopedXCBConnection connection;
|
||||||
case NzMouse::Right: return buttons & XCB_BUTTON_MASK_3;
|
|
||||||
case NzMouse::Middle: return buttons & XCB_BUTTON_MASK_2;
|
|
||||||
case NzMouse::XButton1: return false; // not supported by X
|
|
||||||
case NzMouse::XButton2: return false; // not supported by X
|
|
||||||
}
|
|
||||||
|
|
||||||
NazaraError("Mouse button not supported.");
|
xcb_window_t root = X11::XCBDefaultRootWindow(connection);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzEventImpl::SetMousePosition(int x, int y)
|
|
||||||
{
|
|
||||||
NzScopedXCBConnection 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 NzEventImpl::SetMousePosition(int x, int y, const NzWindow& relativeTo)
|
|
||||||
{
|
|
||||||
NzScopedXCBConnection connection;
|
|
||||||
|
|
||||||
NzWindowHandle handle = relativeTo.GetHandle();
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
if (!X11::CheckCookie(
|
if (!X11::CheckCookie(
|
||||||
connection,
|
connection,
|
||||||
xcb_warp_pointer(
|
xcb_warp_pointer(
|
||||||
connection,
|
connection,
|
||||||
None, // Source window
|
None, // Source window
|
||||||
handle, // Destination window
|
root, // Destination window
|
||||||
0, 0, // Source position
|
0, 0, // Source position
|
||||||
0, 0, // Source size
|
0, 0, // Source size
|
||||||
x, y // Destination position
|
x, y // Destination position
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
NazaraError("Failed to set mouse position relative to window");
|
NazaraError("Failed to set mouse position");
|
||||||
|
|
||||||
xcb_flush(connection);
|
xcb_flush(connection);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
NazaraError("No window handle");
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,25 @@
|
||||||
#ifndef NAZARA_INPUTIMPL_HPP
|
#ifndef NAZARA_INPUTIMPL_HPP
|
||||||
#define NAZARA_INPUTIMPL_HPP
|
#define NAZARA_INPUTIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Utility/Keyboard.hpp>
|
#include <Nazara/Utility/Keyboard.hpp>
|
||||||
#include <Nazara/Utility/Mouse.hpp>
|
#include <Nazara/Utility/Mouse.hpp>
|
||||||
|
|
||||||
class NzEventImpl
|
namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
class EventImpl
|
||||||
static NzString GetKeyName(NzKeyboard::Key key);
|
{
|
||||||
static NzVector2i GetMousePosition();
|
public:
|
||||||
static NzVector2i GetMousePosition(const NzWindow& relativeTo);
|
static String GetKeyName(Keyboard::Key key);
|
||||||
static bool IsKeyPressed(NzKeyboard::Key key);
|
static Vector2i GetMousePosition();
|
||||||
static bool IsMouseButtonPressed(NzMouse::Button button);
|
static Vector2i GetMousePosition(const Window& relativeTo);
|
||||||
static void SetMousePosition(int x, int y);
|
static bool IsKeyPressed(Keyboard::Key key);
|
||||||
static void SetMousePosition(int x, int y, const NzWindow& relativeTo);
|
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
|
#endif // NAZARA_INPUTIMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -8,189 +8,192 @@
|
||||||
#include <xcb/xcb_image.h>
|
#include <xcb/xcb_image.h>
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
/***********************************************
|
namespace Nz
|
||||||
NzScopedXCBConnection
|
|
||||||
***********************************************/
|
|
||||||
|
|
||||||
NzScopedXCBConnection::NzScopedXCBConnection() :
|
|
||||||
m_connection(nullptr)
|
|
||||||
{
|
{
|
||||||
m_connection = X11::OpenConnection();
|
/***********************************************
|
||||||
}
|
ScopedXCBConnection
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
NzScopedXCBConnection::~NzScopedXCBConnection()
|
ScopedXCBConnection::ScopedXCBConnection() :
|
||||||
{
|
m_connection(nullptr)
|
||||||
X11::CloseConnection(m_connection);
|
{
|
||||||
}
|
m_connection = X11::OpenConnection();
|
||||||
|
}
|
||||||
|
|
||||||
NzScopedXCBConnection::operator xcb_connection_t*() const
|
ScopedXCBConnection::~ScopedXCBConnection()
|
||||||
{
|
{
|
||||||
return m_connection;
|
X11::CloseConnection(m_connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************
|
ScopedXCBConnection::operator xcb_connection_t*() const
|
||||||
NzScopedXCBEWMHConnection
|
{
|
||||||
***********************************************/
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
NzScopedXCBEWMHConnection::NzScopedXCBEWMHConnection(xcb_connection_t* connection) :
|
/***********************************************
|
||||||
m_ewmhConnection(nullptr)
|
ScopedXCBEWMHConnection
|
||||||
{
|
***********************************************/
|
||||||
m_ewmhConnection = X11::OpenEWMHConnection(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
NzScopedXCBEWMHConnection::~NzScopedXCBEWMHConnection()
|
ScopedXCBEWMHConnection::ScopedXCBEWMHConnection(xcb_connection_t* connection) :
|
||||||
{
|
m_ewmhConnection(nullptr)
|
||||||
X11::CloseEWMHConnection(m_ewmhConnection);
|
{
|
||||||
}
|
m_ewmhConnection = X11::OpenEWMHConnection(connection);
|
||||||
|
}
|
||||||
|
|
||||||
xcb_ewmh_connection_t* NzScopedXCBEWMHConnection::operator ->() const
|
ScopedXCBEWMHConnection::~ScopedXCBEWMHConnection()
|
||||||
{
|
{
|
||||||
return m_ewmhConnection;
|
X11::CloseEWMHConnection(m_ewmhConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzScopedXCBEWMHConnection::operator xcb_ewmh_connection_t*() const
|
xcb_ewmh_connection_t* ScopedXCBEWMHConnection::operator ->() const
|
||||||
{
|
{
|
||||||
return m_ewmhConnection;
|
return m_ewmhConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************
|
ScopedXCBEWMHConnection::operator xcb_ewmh_connection_t*() const
|
||||||
NzXCBGContext
|
{
|
||||||
***********************************************/
|
return m_ewmhConnection;
|
||||||
|
}
|
||||||
|
|
||||||
NzXCBGContext::NzXCBGContext(xcb_connection_t* connection) :
|
/***********************************************
|
||||||
m_connection(connection),
|
XCBGContext
|
||||||
m_gcontext(XCB_NONE)
|
***********************************************/
|
||||||
{
|
|
||||||
NazaraAssert(connection, "Connection must have been established");
|
|
||||||
}
|
|
||||||
|
|
||||||
NzXCBGContext::~NzXCBGContext()
|
XCBGContext::XCBGContext(xcb_connection_t* connection) :
|
||||||
{
|
m_connection(connection),
|
||||||
Destroy();
|
m_gcontext(XCB_NONE)
|
||||||
}
|
{
|
||||||
|
NazaraAssert(connection, "Connection must have been established");
|
||||||
|
}
|
||||||
|
|
||||||
bool NzXCBGContext::Create(xcb_drawable_t drawable, uint32_t value_mask, const uint32_t* value_list)
|
XCBGContext::~XCBGContext()
|
||||||
{
|
{
|
||||||
NazaraAssert(m_gcontext == XCB_NONE, "Context must have been destroyed before or just created");
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
m_gcontext = xcb_generate_id(m_connection);
|
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");
|
||||||
|
|
||||||
return X11::CheckCookie(
|
m_gcontext = xcb_generate_id(m_connection);
|
||||||
m_connection,
|
|
||||||
xcb_create_gc(
|
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,
|
m_connection,
|
||||||
m_gcontext,
|
|
||||||
drawable,
|
|
||||||
value_mask,
|
|
||||||
value_list
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzXCBGContext::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzXCBGContext::operator xcb_gcontext_t() const
|
|
||||||
{
|
|
||||||
return m_gcontext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************
|
|
||||||
NzXCBPixmap
|
|
||||||
***********************************************/
|
|
||||||
|
|
||||||
NzXCBPixmap::NzXCBPixmap() :
|
|
||||||
m_connection(nullptr),
|
|
||||||
m_pixmap(XCB_NONE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NzXCBPixmap::NzXCBPixmap(xcb_connection_t* connection) :
|
|
||||||
m_connection(connection),
|
|
||||||
m_pixmap(XCB_NONE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NzXCBPixmap::~NzXCBPixmap()
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzXCBPixmap::Connect(xcb_connection_t* connection)
|
|
||||||
{
|
|
||||||
NazaraAssert(connection && !m_connection, "Connection must be established");
|
|
||||||
|
|
||||||
m_connection = connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzXCBPixmap::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,
|
drawable,
|
||||||
|
data,
|
||||||
width,
|
width,
|
||||||
height
|
height,
|
||||||
));
|
depth,
|
||||||
}
|
fg,
|
||||||
|
bg,
|
||||||
|
gcp
|
||||||
|
);
|
||||||
|
|
||||||
bool NzXCBPixmap::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)
|
return m_pixmap != XCB_NONE;
|
||||||
{
|
}
|
||||||
NazaraAssert(m_pixmap == XCB_NONE, "Pixmap must have been destroyed before or just created");
|
|
||||||
|
|
||||||
m_pixmap = xcb_create_pixmap_from_bitmap_data(
|
void XCBPixmap::Destroy()
|
||||||
m_connection,
|
{
|
||||||
drawable,
|
if (m_pixmap == XCB_NONE)
|
||||||
data,
|
return;
|
||||||
width,
|
|
||||||
height,
|
|
||||||
depth,
|
|
||||||
fg,
|
|
||||||
bg,
|
|
||||||
gcp
|
|
||||||
);
|
|
||||||
|
|
||||||
return m_pixmap != XCB_NONE;
|
if (!X11::CheckCookie(
|
||||||
}
|
|
||||||
|
|
||||||
void NzXCBPixmap::Destroy()
|
|
||||||
{
|
|
||||||
if (m_pixmap == XCB_NONE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!X11::CheckCookie(
|
|
||||||
m_connection,
|
|
||||||
xcb_free_pixmap(
|
|
||||||
m_connection,
|
m_connection,
|
||||||
m_pixmap
|
xcb_free_pixmap(
|
||||||
))
|
m_connection,
|
||||||
)
|
m_pixmap
|
||||||
NazaraError("Failed to free pixmap");
|
))
|
||||||
|
)
|
||||||
|
NazaraError("Failed to free pixmap");
|
||||||
|
|
||||||
m_pixmap = XCB_NONE;
|
m_pixmap = XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzXCBPixmap::operator xcb_pixmap_t() const
|
XCBPixmap::operator xcb_pixmap_t() const
|
||||||
{
|
{
|
||||||
return m_pixmap;
|
return m_pixmap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,88 +7,93 @@
|
||||||
#ifndef NAZARA_SCOPEDXCB_HPP
|
#ifndef NAZARA_SCOPEDXCB_HPP
|
||||||
#define NAZARA_SCOPEDXCB_HPP
|
#define NAZARA_SCOPEDXCB_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_ewmh.h>
|
#include <xcb/xcb_ewmh.h>
|
||||||
|
|
||||||
class NzScopedXCBConnection
|
namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
class ScopedXCBConnection
|
||||||
NzScopedXCBConnection();
|
{
|
||||||
~NzScopedXCBConnection();
|
public:
|
||||||
|
ScopedXCBConnection();
|
||||||
|
~ScopedXCBConnection();
|
||||||
|
|
||||||
operator xcb_connection_t*() const;
|
operator xcb_connection_t*() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
xcb_connection_t* m_connection;
|
xcb_connection_t* m_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NzScopedXCBEWMHConnection
|
class ScopedXCBEWMHConnection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzScopedXCBEWMHConnection(xcb_connection_t* connection);
|
ScopedXCBEWMHConnection(xcb_connection_t* connection);
|
||||||
~NzScopedXCBEWMHConnection();
|
~ScopedXCBEWMHConnection();
|
||||||
|
|
||||||
xcb_ewmh_connection_t* operator ->() const;
|
xcb_ewmh_connection_t* operator ->() const;
|
||||||
|
|
||||||
operator xcb_ewmh_connection_t*() const;
|
operator xcb_ewmh_connection_t*() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
xcb_ewmh_connection_t* m_ewmhConnection;
|
xcb_ewmh_connection_t* m_ewmhConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class NzScopedXCB
|
class ScopedXCB
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzScopedXCB(T* pointer);
|
ScopedXCB(T* pointer);
|
||||||
~NzScopedXCB();
|
~ScopedXCB();
|
||||||
|
|
||||||
T* operator ->() const;
|
T* operator ->() const;
|
||||||
T** operator &();
|
T** operator &();
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
|
||||||
T* get() const;
|
T* get() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* m_pointer;
|
T* m_pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NzXCBGContext
|
class XCBGContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzXCBGContext(xcb_connection_t* connection);
|
XCBGContext(xcb_connection_t* connection);
|
||||||
~NzXCBGContext();
|
~XCBGContext();
|
||||||
|
|
||||||
bool Create(xcb_drawable_t drawable, uint32_t value_mask, const uint32_t* value_list);
|
bool Create(xcb_drawable_t drawable, uint32_t value_mask, const uint32_t* value_list);
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
operator xcb_gcontext_t() const;
|
operator xcb_gcontext_t() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
xcb_connection_t* m_connection;
|
xcb_connection_t* m_connection;
|
||||||
xcb_gcontext_t m_gcontext;
|
xcb_gcontext_t m_gcontext;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NzXCBPixmap
|
class XCBPixmap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzXCBPixmap();
|
XCBPixmap();
|
||||||
NzXCBPixmap(xcb_connection_t* connection);
|
XCBPixmap(xcb_connection_t* connection);
|
||||||
~NzXCBPixmap();
|
~XCBPixmap();
|
||||||
|
|
||||||
void Connect(xcb_connection_t* connection);
|
void Connect(xcb_connection_t* connection);
|
||||||
bool Create(uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height);
|
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);
|
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();
|
void Destroy();
|
||||||
|
|
||||||
operator xcb_pixmap_t() const;
|
operator xcb_pixmap_t() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
xcb_connection_t* m_connection;
|
xcb_connection_t* m_connection;
|
||||||
xcb_pixmap_t m_pixmap;
|
xcb_pixmap_t m_pixmap;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#include <Nazara/Utility/X11/ScopedXCB.inl>
|
#include <Nazara/Utility/X11/ScopedXCB.inl>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,156 +10,159 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
NzVideoMode NzVideoModeImpl::GetDesktopMode()
|
namespace Nz
|
||||||
{
|
{
|
||||||
NzVideoMode desktopMode;
|
VideoMode VideoModeImpl::GetDesktopMode()
|
||||||
|
|
||||||
NzScopedXCBConnection connection;
|
|
||||||
|
|
||||||
// Retrieve the default screen
|
|
||||||
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
|
|
||||||
|
|
||||||
NzScopedXCB<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
|
VideoMode desktopMode;
|
||||||
NazaraError("Failed to use the RandR extension while trying to get the desktop video mode");
|
|
||||||
return desktopMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load RandR and check its version
|
ScopedXCBConnection connection;
|
||||||
NzScopedXCB<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
|
|
||||||
connection,
|
|
||||||
xcb_randr_query_version(
|
|
||||||
connection,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
),
|
|
||||||
&error
|
|
||||||
));
|
|
||||||
|
|
||||||
if (error)
|
// Retrieve the default screen
|
||||||
{
|
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
|
||||||
NazaraError("Failed to load the RandR extension while trying to get the desktop video mode");
|
|
||||||
return desktopMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current configuration
|
ScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
NzScopedXCB<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)
|
// Check if the RandR extension is present
|
||||||
{
|
const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);
|
||||||
// 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
|
if (!randrExt || !randrExt->present)
|
||||||
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 = NzVideoMode(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 NzVideoModeImpl::GetFullscreenModes(std::vector<NzVideoMode>& modes)
|
|
||||||
{
|
|
||||||
NzScopedXCBConnection connection;
|
|
||||||
|
|
||||||
// Retrieve the default screen
|
|
||||||
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
|
|
||||||
|
|
||||||
NzScopedXCB<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
|
|
||||||
NzScopedXCB<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
|
|
||||||
NzScopedXCB<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)
|
// 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))
|
||||||
{
|
{
|
||||||
// Convert to VideoMode
|
for (int j = 0; j < config->nSizes; ++j)
|
||||||
NzVideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
|
{
|
||||||
|
// Convert to VideoMode
|
||||||
|
VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
|
||||||
|
|
||||||
if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
|
if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
|
||||||
config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
|
config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
|
||||||
std::swap(mode.width, mode.height);
|
std::swap(mode.width, mode.height);
|
||||||
|
|
||||||
// Add it only if it is not already in the array
|
// Add it only if it is not already in the array
|
||||||
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
|
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
|
||||||
modes.push_back(mode);
|
modes.push_back(mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,17 @@
|
||||||
#ifndef NAZARA_VIDEOMODEIMPL_HPP
|
#ifndef NAZARA_VIDEOMODEIMPL_HPP
|
||||||
#define NAZARA_VIDEOMODEIMPL_HPP
|
#define NAZARA_VIDEOMODEIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Utility/VideoMode.hpp>
|
#include <Nazara/Utility/VideoMode.hpp>
|
||||||
|
|
||||||
class NzVideoModeImpl
|
namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
class VideoModeImpl
|
||||||
static NzVideoMode GetDesktopMode();
|
{
|
||||||
static void GetFullscreenModes(std::vector<NzVideoMode>& modes);
|
public:
|
||||||
};
|
static VideoMode GetDesktopMode();
|
||||||
|
static void GetFullscreenModes(std::vector<VideoMode>& modes);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NNAZARA_VIDEOMODEIMPL_HPP
|
#endif // NNAZARA_VIDEOMODEIMPL_HPP
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,118 +9,127 @@
|
||||||
#ifndef NAZARA_WINDOWIMPL_HPP
|
#ifndef NAZARA_WINDOWIMPL_HPP
|
||||||
#define NAZARA_WINDOWIMPL_HPP
|
#define NAZARA_WINDOWIMPL_HPP
|
||||||
|
|
||||||
#include <Nazara/Core/NonCopyable.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/Thread.hpp>
|
#include <Nazara/Core/Thread.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Utility/Enums.hpp>
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
#include <Nazara/Utility/Keyboard.hpp>
|
#include <Nazara/Utility/Keyboard.hpp>
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <Nazara/Utility/X11/Display.hpp>
|
|
||||||
|
|
||||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
namespace Nz
|
||||||
class NzConditionVariable;
|
|
||||||
class NzMutex;
|
|
||||||
#endif
|
|
||||||
class NzCursor;
|
|
||||||
class NzIcon;
|
|
||||||
class NzVideoMode;
|
|
||||||
class NzWindow;
|
|
||||||
|
|
||||||
class NzWindowImpl : NzNonCopyable
|
|
||||||
{
|
{
|
||||||
public:
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
NzWindowImpl(NzWindow* parent);
|
class ConditionVariable;
|
||||||
~NzWindowImpl();
|
class Mutex;
|
||||||
|
#endif
|
||||||
|
class Cursor;
|
||||||
|
class Icon;
|
||||||
|
class VideoMode;
|
||||||
|
class Window;
|
||||||
|
|
||||||
bool Create(const NzVideoMode& mode, const NzString& title, nzUInt32 style);
|
class WindowImpl
|
||||||
bool Create(NzWindowHandle handle);
|
{
|
||||||
|
public:
|
||||||
|
WindowImpl(Window* parent);
|
||||||
|
WindowImpl(const WindowImpl&) = delete;
|
||||||
|
WindowImpl(WindowImpl&&) = delete; ///TODO?
|
||||||
|
~WindowImpl();
|
||||||
|
|
||||||
void Destroy();
|
bool Create(const VideoMode& mode, const String& title, UInt32 style);
|
||||||
|
bool Create(WindowHandle handle);
|
||||||
|
|
||||||
void EnableKeyRepeat(bool enable);
|
void Destroy();
|
||||||
void EnableSmoothScrolling(bool enable);
|
|
||||||
|
|
||||||
NzWindowHandle GetHandle() const;
|
void EnableKeyRepeat(bool enable);
|
||||||
unsigned int GetHeight() const;
|
void EnableSmoothScrolling(bool enable);
|
||||||
NzVector2i GetPosition() const;
|
|
||||||
NzVector2ui GetSize() const;
|
|
||||||
nzUInt32 GetStyle() const;
|
|
||||||
NzString GetTitle() const;
|
|
||||||
unsigned int GetWidth() const;
|
|
||||||
|
|
||||||
bool HasFocus() const;
|
WindowHandle GetHandle() const;
|
||||||
|
unsigned int GetHeight() const;
|
||||||
|
Vector2i GetPosition() const;
|
||||||
|
Vector2ui GetSize() const;
|
||||||
|
UInt32 GetStyle() const;
|
||||||
|
String GetTitle() const;
|
||||||
|
unsigned int GetWidth() const;
|
||||||
|
|
||||||
void IgnoreNextMouseEvent(int mouseX, int mouseY);
|
bool HasFocus() const;
|
||||||
|
|
||||||
bool IsMinimized() const;
|
void IgnoreNextMouseEvent(int mouseX, int mouseY);
|
||||||
bool IsVisible() const;
|
|
||||||
|
|
||||||
void ProcessEvents(bool block);
|
bool IsMinimized() const;
|
||||||
|
bool IsVisible() const;
|
||||||
|
|
||||||
void SetCursor(nzWindowCursor cursor);
|
void ProcessEvents(bool block);
|
||||||
void SetCursor(const NzCursor& cursor);
|
|
||||||
void SetEventListener(bool listener);
|
|
||||||
void SetFocus();
|
|
||||||
void SetIcon(const NzIcon& 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 NzString& title);
|
|
||||||
void SetVisible(bool visible);
|
|
||||||
|
|
||||||
static bool Initialize();
|
void SetCursor(WindowCursor cursor);
|
||||||
static void Uninitialize();
|
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);
|
||||||
|
|
||||||
private:
|
WindowImpl& operator=(const WindowImpl&) = delete;
|
||||||
|
WindowImpl& operator=(WindowImpl&&) = delete; ///TODO?
|
||||||
|
|
||||||
void CleanUp();
|
static bool Initialize();
|
||||||
xcb_keysym_t ConvertKeyCodeToKeySym(xcb_keycode_t keycode, uint16_t state);
|
static void Uninitialize();
|
||||||
NzKeyboard::Key ConvertVirtualKey(xcb_keysym_t symbol);
|
|
||||||
const char* ConvertWindowCursorToXName(nzWindowCursor cursor);
|
|
||||||
void CommonInitialize();
|
|
||||||
|
|
||||||
void ProcessEvent(xcb_generic_event_t* windowEvent);
|
private:
|
||||||
|
|
||||||
void ResetVideoMode();
|
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);
|
||||||
|
void CommonInitialize();
|
||||||
|
|
||||||
void SetCursor(xcb_cursor_t cursor);
|
void ProcessEvent(xcb_generic_event_t* windowEvent);
|
||||||
void SetMotifHints();
|
|
||||||
void SetVideoMode(const NzVideoMode& mode);
|
|
||||||
void SwitchToFullscreen();
|
|
||||||
|
|
||||||
bool UpdateNormalHints();
|
void ResetVideoMode();
|
||||||
void UpdateEventQueue(xcb_generic_event_t* event);
|
|
||||||
|
|
||||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
void SetCursor(xcb_cursor_t cursor);
|
||||||
static void WindowThread(NzWindowImpl* window, NzMutex* mutex, NzConditionVariable* condition);
|
void SetMotifHints();
|
||||||
#endif
|
void SetVideoMode(const VideoMode& mode);
|
||||||
|
void SwitchToFullscreen();
|
||||||
|
|
||||||
xcb_window_t m_window;
|
bool UpdateNormalHints();
|
||||||
xcb_screen_t* m_screen;
|
void UpdateEventQueue(xcb_generic_event_t* event);
|
||||||
xcb_randr_get_screen_info_reply_t m_oldVideoMode;
|
|
||||||
xcb_size_hints_t m_size_hints;
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
nzUInt32 m_style;
|
static void WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
|
||||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
#endif
|
||||||
NzThread m_thread;
|
|
||||||
#endif
|
xcb_window_t m_window;
|
||||||
NzWindow* m_parent;
|
xcb_screen_t* m_screen;
|
||||||
bool m_eventListener;
|
xcb_randr_get_screen_info_reply_t m_oldVideoMode;
|
||||||
bool m_ownsWindow;
|
xcb_size_hints_t m_size_hints;
|
||||||
bool m_smoothScrolling;
|
UInt32 m_style;
|
||||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
bool m_threadActive;
|
Thread m_thread;
|
||||||
#endif
|
#endif
|
||||||
short m_scrolling;
|
Window* m_parent;
|
||||||
NzVector2i m_mousePos;
|
bool m_eventListener;
|
||||||
bool m_keyRepeat;
|
bool m_ownsWindow;
|
||||||
|
bool m_smoothScrolling;
|
||||||
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
|
bool m_threadActive;
|
||||||
|
#endif
|
||||||
|
short m_scrolling;
|
||||||
|
Vector2i m_mousePos;
|
||||||
|
bool m_keyRepeat;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
xcb_generic_event_t* curr = nullptr;
|
||||||
|
xcb_generic_event_t* next = nullptr;
|
||||||
|
} m_eventQueue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
xcb_generic_event_t* curr = nullptr;
|
|
||||||
xcb_generic_event_t* next = nullptr;
|
|
||||||
} m_eventQueue;
|
|
||||||
};
|
|
||||||
#endif // NAZARA_WINDOWIMPL_HPP
|
#endif // NAZARA_WINDOWIMPL_HPP
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue