Merge branch 'NDK' into NDK-ShadowMapping
Former-commit-id: 150a4149d50af6971fd5798c080f0c55e009a55b
This commit is contained in:
commit
1ffd2b724f
|
|
@ -15,8 +15,8 @@ MODULE.OsFiles.Windows = {
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE.OsFiles.Posix = {
|
MODULE.OsFiles.Posix = {
|
||||||
"../src/Nazara/Renderer/Posix/**.hpp",
|
"../src/Nazara/Renderer/GLX/**.hpp",
|
||||||
"../src/Nazara/Renderer/Posix/**.cpp"
|
"../src/Nazara/Renderer/GLX/**.cpp"
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE.OsLibraries.Windows = {
|
MODULE.OsLibraries.Windows = {
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ MODULE.OsFiles.Windows = {
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE.OsFiles.Posix = {
|
MODULE.OsFiles.Posix = {
|
||||||
"../src/Nazara/Utility/Posix/**.hpp",
|
"../src/Nazara/Utility/X11/**.hpp",
|
||||||
"../src/Nazara/Utility/Posix/**.cpp"
|
"../src/Nazara/Utility/X11/**.cpp"
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE.OsLibraries.Windows = {
|
MODULE.OsLibraries.Windows = {
|
||||||
|
|
|
||||||
|
|
@ -180,10 +180,10 @@ class NAZARA_CORE_API NzString : public NzHashable
|
||||||
const char* end() const;
|
const char* end() const;
|
||||||
void push_front(char c);
|
void push_front(char c);
|
||||||
void push_back(char c);
|
void push_back(char c);
|
||||||
/*char* rbegin();
|
//char* rbegin();
|
||||||
const char* rbegin() const;
|
//const char* rbegin() const;
|
||||||
char* rend();
|
//char* rend();
|
||||||
const char* rend() const;*/
|
//const char* rend() const;
|
||||||
|
|
||||||
typedef const char& const_reference;
|
typedef const char& const_reference;
|
||||||
typedef char* iterator;
|
typedef char* iterator;
|
||||||
|
|
|
||||||
|
|
@ -114,9 +114,10 @@
|
||||||
#define _WIN32_WINNT NAZARA_WINNT
|
#define _WIN32_WINNT NAZARA_WINNT
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__) || defined(__unix__)
|
||||||
#define NAZARA_PLATFORM_LINUX
|
#define NAZARA_PLATFORM_LINUX
|
||||||
#define NAZARA_PLATFORM_POSIX
|
#define NAZARA_PLATFORM_POSIX
|
||||||
|
#define NAZARA_PLATFORM_X11
|
||||||
|
|
||||||
#define NAZARA_EXPORT __attribute__((visibility ("default")))
|
#define NAZARA_EXPORT __attribute__((visibility ("default")))
|
||||||
#define NAZARA_IMPORT __attribute__((visibility ("default")))
|
#define NAZARA_IMPORT __attribute__((visibility ("default")))
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,20 @@ class NAZARA_RENDERER_API NzContext : public NzRefCounted
|
||||||
~NzContext();
|
~NzContext();
|
||||||
|
|
||||||
bool Create(const NzContextParameters& parameters = NzContextParameters());
|
bool Create(const NzContextParameters& parameters = NzContextParameters());
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
void EnableVerticalSync(bool enabled);
|
||||||
|
|
||||||
const NzContextParameters& GetParameters() const;
|
const NzContextParameters& GetParameters() const;
|
||||||
|
|
||||||
bool IsActive() const;
|
bool IsActive() const;
|
||||||
|
|
||||||
bool SetActive(bool active) const;
|
bool SetActive(bool active) const;
|
||||||
void SwapBuffers();
|
void SwapBuffers();
|
||||||
|
|
||||||
static bool EnsureContext();
|
static bool EnsureContext();
|
||||||
|
|
||||||
static const NzContext* GetCurrent();
|
static const NzContext* GetCurrent();
|
||||||
static const NzContext* GetReference();
|
static const NzContext* GetReference();
|
||||||
static const NzContext* GetThreadContext();
|
static const NzContext* GetThreadContext();
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@
|
||||||
#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_LINUX)
|
||||||
|
namespace GLX
|
||||||
|
{
|
||||||
|
#include <GL3/glx.h>
|
||||||
|
}
|
||||||
#include <GL3/glxext.h>
|
#include <GL3/glxext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -332,8 +336,10 @@ NAZARA_RENDERER_API extern PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStr
|
||||||
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_LINUX)
|
||||||
NAZARA_RENDERER_API extern PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
|
NAZARA_RENDERER_API extern GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
|
||||||
NAZARA_RENDERER_API extern PFNGLXSWAPINTERVALSGIPROC glXSwapInterval;
|
NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
|
||||||
|
NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA;
|
||||||
|
NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // NAZARA_RENDERER_OPENGL
|
#endif // NAZARA_RENDERER_OPENGL
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@
|
||||||
// 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* NzWindowHandle;
|
typedef void* NzWindowHandle;
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||||
|
#include <xcb/xcb.h>
|
||||||
// http://en.wikipedia.org/wiki/Xlib#Data_types
|
// http://en.wikipedia.org/wiki/Xlib#Data_types
|
||||||
typedef unsigned long NzWindowHandle;
|
using NzWindowHandle = xcb_window_t;
|
||||||
#else
|
#else
|
||||||
#error Lack of implementation: WindowHandle
|
#error Lack of implementation: WindowHandle
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3847,10 +3847,10 @@ NzString NzString::Number(unsigned long long number, nzUInt8 radix)
|
||||||
|
|
||||||
NzString NzString::Pointer(const void* ptr)
|
NzString NzString::Pointer(const void* ptr)
|
||||||
{
|
{
|
||||||
const unsigned int size = sizeof(void*)*2 + 2;
|
const unsigned int capacity = sizeof(void*)*2 + 2;
|
||||||
|
|
||||||
auto str = std::make_shared<SharedString>(size);
|
auto str = std::make_shared<SharedString>(capacity);
|
||||||
std::sprintf(str->string.get(), "0x%p", ptr);
|
str->size = std::sprintf(str->string.get(), "0x%p", ptr);
|
||||||
|
|
||||||
return NzString(std::move(str));
|
return NzString(std::move(str));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ NzStringStream& NzStringStream::operator<<(const NzString& string)
|
||||||
NzStringStream& NzStringStream::operator<<(const void* ptr)
|
NzStringStream& NzStringStream::operator<<(const void* ptr)
|
||||||
{
|
{
|
||||||
m_strings.push_back(NzString::Pointer(ptr));
|
m_strings.push_back(NzString::Pointer(ptr));
|
||||||
m_bufferSize += sizeof(void*)*2;
|
m_bufferSize += m_strings.back().GetSize();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// This file is part of the "Nazara Engine - Graphics module"
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Graphics/ColorBackGround.hpp>
|
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@
|
||||||
#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_LINUX)
|
||||||
#include <Nazara/Renderer/Linux/ContextImpl.hpp>
|
#include <Nazara/Renderer/GLX/ContextImpl.hpp>
|
||||||
|
#define CALLBACK
|
||||||
#else
|
#else
|
||||||
#error Lack of implementation: Context
|
#error Lack of implementation: Context
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -194,6 +195,19 @@ void NzContext::Destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzContext::EnableVerticalSync(bool enabled)
|
||||||
|
{
|
||||||
|
#ifdef NAZARA_RENDERER_SAFE
|
||||||
|
if (!m_impl)
|
||||||
|
{
|
||||||
|
NazaraError("No context has been created");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_impl->EnableVerticalSync(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
const NzContextParameters& NzContext::GetParameters() const
|
const NzContextParameters& NzContext::GetParameters() const
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_RENDERER_SAFE
|
#ifdef NAZARA_RENDERER_SAFE
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,297 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/GLX/ContextImpl.hpp>
|
||||||
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Renderer/Context.hpp>
|
||||||
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
|
using namespace GLX;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
Display* m_display;
|
||||||
|
int m_sharedDisplay = 0;
|
||||||
|
|
||||||
|
bool ctxErrorOccurred = false;
|
||||||
|
int ctxErrorHandler( Display* /*dpy*/, XErrorEvent* /*ev*/ )
|
||||||
|
{
|
||||||
|
ctxErrorOccurred = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NzContextImpl::NzContextImpl() :
|
||||||
|
m_colormap(0),
|
||||||
|
m_context(0),
|
||||||
|
m_window(0),
|
||||||
|
m_ownsWindow(false)
|
||||||
|
{
|
||||||
|
if (m_sharedDisplay == 0)
|
||||||
|
m_display = XOpenDisplay(nullptr);
|
||||||
|
|
||||||
|
++m_sharedDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzContextImpl::~NzContextImpl()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
if (--m_sharedDisplay == 0)
|
||||||
|
{
|
||||||
|
XCloseDisplay(m_display);
|
||||||
|
m_display = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzContextImpl::Activate()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get a matching FB config
|
||||||
|
static int visual_attribs[] =
|
||||||
|
{
|
||||||
|
GLX_X_RENDERABLE, True,
|
||||||
|
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||||
|
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||||
|
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
||||||
|
GLX_BUFFER_SIZE, parameters.bitsPerPixel,
|
||||||
|
GLX_ALPHA_SIZE, (parameters.bitsPerPixel == 32) ? 8 : 0,
|
||||||
|
GLX_DEPTH_SIZE, parameters.depthBits,
|
||||||
|
GLX_STENCIL_SIZE, parameters.stencilBits,
|
||||||
|
GLX_DOUBLEBUFFER, True,
|
||||||
|
GLX_SAMPLE_BUFFERS, (parameters.antialiasingLevel > 0) ? True : False,
|
||||||
|
GLX_SAMPLES, parameters.antialiasingLevel,
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
int glx_major = 0;
|
||||||
|
int glx_minor = 0;
|
||||||
|
// FBConfigs were added in GLX version 1.3.
|
||||||
|
if (!glXQueryVersion(m_display, &glx_major, &glx_minor) || ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1))
|
||||||
|
{
|
||||||
|
NazaraError("Invalid GLX version, version > 1.3 is required.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fbcount;
|
||||||
|
GLXFBConfig* fbc = glXChooseFBConfig(m_display, XDefaultScreen(m_display), visual_attribs, &fbcount);
|
||||||
|
if (!fbc)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to retrieve a framebuffer config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick the FB config/visual with the most samples per pixel
|
||||||
|
int best_fbc = -1;
|
||||||
|
int worst_fbc = -1;
|
||||||
|
int best_num_samp = -1;
|
||||||
|
int worst_num_samp = 999;
|
||||||
|
|
||||||
|
for (int i = 0; i < fbcount; ++i)
|
||||||
|
{
|
||||||
|
XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, fbc[i]);
|
||||||
|
|
||||||
|
if (vi)
|
||||||
|
{
|
||||||
|
int samp_buf = 0, samples = 0;
|
||||||
|
glXGetFBConfigAttrib(m_display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
|
||||||
|
glXGetFBConfigAttrib(m_display, fbc[i], GLX_SAMPLES , &samples );
|
||||||
|
|
||||||
|
if ((best_fbc < 0) || (samp_buf && (samples > best_num_samp)))
|
||||||
|
{
|
||||||
|
best_fbc = i;
|
||||||
|
best_num_samp = samples;
|
||||||
|
}
|
||||||
|
if ((worst_fbc < 0) || !samp_buf || (samples < worst_num_samp))
|
||||||
|
{
|
||||||
|
worst_fbc = i;
|
||||||
|
worst_num_samp = samples;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(vi);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLXFBConfig bestFbc = fbc[best_fbc];
|
||||||
|
|
||||||
|
// Be sure to free the FBConfig list allocated by glXChooseFBConfig()
|
||||||
|
XFree(fbc);
|
||||||
|
|
||||||
|
// Get a visual
|
||||||
|
XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, bestFbc);
|
||||||
|
if (!vi)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to get best VisualInfo");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If context is shared by multiple windows
|
||||||
|
if (parameters.window)
|
||||||
|
{
|
||||||
|
m_window = parameters.window;
|
||||||
|
m_ownsWindow = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XSetWindowAttributes swa;
|
||||||
|
swa.colormap = m_colormap = XCreateColormap(
|
||||||
|
m_display,
|
||||||
|
XRootWindow(
|
||||||
|
m_display,
|
||||||
|
vi->screen),
|
||||||
|
vi->visual,
|
||||||
|
AllocNone
|
||||||
|
);
|
||||||
|
|
||||||
|
swa.background_pixmap = None;
|
||||||
|
swa.border_pixel = 0;
|
||||||
|
swa.event_mask = StructureNotifyMask;
|
||||||
|
|
||||||
|
if (!m_colormap)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create colormap for context");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_window = XCreateWindow(
|
||||||
|
m_display,
|
||||||
|
XRootWindow(
|
||||||
|
m_display,
|
||||||
|
vi->screen),
|
||||||
|
0, 0, // X, Y
|
||||||
|
1, 1, // W H
|
||||||
|
0,
|
||||||
|
vi->depth,
|
||||||
|
InputOutput,
|
||||||
|
vi->visual,
|
||||||
|
CWBorderPixel | CWColormap | CWEventMask,
|
||||||
|
&swa
|
||||||
|
);
|
||||||
|
|
||||||
|
m_ownsWindow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_window)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create window");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done with the visual info data
|
||||||
|
XFree(vi);
|
||||||
|
|
||||||
|
// Install an X error handler so the application won't exit if GL 3.0
|
||||||
|
// context allocation fails.
|
||||||
|
//
|
||||||
|
// Note this error handler is global. All display connections in all threads
|
||||||
|
// of a process use the same error handler, so be sure to guard against other
|
||||||
|
// threads issuing X commands while this code is running.
|
||||||
|
ctxErrorOccurred = false;
|
||||||
|
int (*oldHandler)(Display*, XErrorEvent*) =
|
||||||
|
XSetErrorHandler(&ctxErrorHandler);
|
||||||
|
|
||||||
|
// Check for the GLX_ARB_create_context extension string and the function.
|
||||||
|
// If either is not present, use GLX 1.3 context creation method.
|
||||||
|
if (!glXCreateContextAttribs)
|
||||||
|
{
|
||||||
|
NazaraWarning("glXCreateContextAttribs() not found. Using old-style GLX context");
|
||||||
|
m_context = glXCreateNewContext(m_display, bestFbc, GLX_RGBA_TYPE, parameters.shared ? parameters.shareContext->m_impl->m_context : 0, True);
|
||||||
|
}
|
||||||
|
// If it does, try to get a GL 3.0 context!
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int profile = parameters.compatibilityProfile ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
int debug = parameters.debugMode ? GLX_CONTEXT_DEBUG_BIT_ARB : 0;
|
||||||
|
|
||||||
|
int major = 3;//parameters.majorVersion;
|
||||||
|
int minor = 3;//parameters.minorVersion;
|
||||||
|
|
||||||
|
int context_attribs[] =
|
||||||
|
{
|
||||||
|
GLX_CONTEXT_MAJOR_VERSION_ARB, major,
|
||||||
|
GLX_CONTEXT_MINOR_VERSION_ARB, minor,
|
||||||
|
GLX_CONTEXT_PROFILE_MASK_ARB, profile,
|
||||||
|
GLX_CONTEXT_FLAGS_ARB, debug,
|
||||||
|
None, None
|
||||||
|
};
|
||||||
|
|
||||||
|
m_context = glXCreateContextAttribs(
|
||||||
|
m_display,
|
||||||
|
bestFbc,
|
||||||
|
parameters.shared ? parameters.shareContext->m_impl->m_context : 0,
|
||||||
|
True,
|
||||||
|
context_attribs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync to ensure any errors generated are processed.
|
||||||
|
XSync(m_display, False);
|
||||||
|
XSetErrorHandler(oldHandler);
|
||||||
|
if (ctxErrorOccurred || !m_context)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create context, check the version");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onExit.Reset();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzContextImpl::Destroy()
|
||||||
|
{
|
||||||
|
// Destroy the context
|
||||||
|
if (m_context)
|
||||||
|
{
|
||||||
|
if (glXGetCurrentContext() == m_context)
|
||||||
|
glXMakeCurrent(m_display, None, nullptr);
|
||||||
|
glXDestroyContext(m_display, m_context);
|
||||||
|
m_context = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the window if we own it
|
||||||
|
if (m_ownsWindow && m_window)
|
||||||
|
{
|
||||||
|
XFreeColormap(m_display, m_colormap);
|
||||||
|
XDestroyWindow(m_display, m_window);
|
||||||
|
m_ownsWindow = false;
|
||||||
|
m_window = 0;
|
||||||
|
XFlush(m_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine".
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_CONTEXTIMPL_HPP
|
||||||
|
#define NAZARA_CONTEXTIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
|
|
||||||
|
class NzContextParameters;
|
||||||
|
|
||||||
|
class NzContextImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzContextImpl();
|
||||||
|
~NzContextImpl();
|
||||||
|
|
||||||
|
bool Activate();
|
||||||
|
|
||||||
|
bool Create(NzContextParameters& parameters);
|
||||||
|
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
void EnableVerticalSync(bool enabled);
|
||||||
|
|
||||||
|
void SwapBuffers();
|
||||||
|
|
||||||
|
static bool Desactivate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLX::Colormap m_colormap;
|
||||||
|
GLX::GLXContext m_context;
|
||||||
|
GLX::Window m_window;
|
||||||
|
bool m_ownsWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_CONTEXTIMPL_HPP
|
||||||
|
|
@ -29,7 +29,7 @@ namespace
|
||||||
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<NzOpenGLFunc>(GetProcAddress(openGLlibrary, name));
|
entry = reinterpret_cast<NzOpenGLFunc>(GetProcAddress(openGLlibrary, name));
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||||
NzOpenGLFunc entry = reinterpret_cast<NzOpenGLFunc>(glXGetProcAddress(name));
|
NzOpenGLFunc entry = reinterpret_cast<NzOpenGLFunc>(GLX::glXGetProcAddress(reinterpret_cast<const unsigned char*>(name)));
|
||||||
#else
|
#else
|
||||||
#error OS not handled
|
#error OS not handled
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -741,6 +741,11 @@ bool NzOpenGL::Initialize()
|
||||||
|
|
||||||
/****************************Chargement OpenGL****************************/
|
/****************************Chargement OpenGL****************************/
|
||||||
|
|
||||||
|
///FIXME: I'm really thinking this is a mistake and GLX has no need to be initialized differently (Lynix)
|
||||||
|
#if defined(NAZARA_PLATFORM_LINUX)
|
||||||
|
glXCreateContextAttribs = reinterpret_cast<GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC>(LoadEntry("glXCreateContextAttribsARB", false));
|
||||||
|
#endif
|
||||||
|
|
||||||
NzContext loadContext;
|
NzContext loadContext;
|
||||||
if (!loadContext.Create(parameters))
|
if (!loadContext.Create(parameters))
|
||||||
{
|
{
|
||||||
|
|
@ -753,8 +758,6 @@ bool NzOpenGL::Initialize()
|
||||||
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(LoadEntry("wglChoosePixelFormatARB", false));
|
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(LoadEntry("wglChoosePixelFormatARB", false));
|
||||||
if (!wglChoosePixelFormat)
|
if (!wglChoosePixelFormat)
|
||||||
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATEXTPROC>(LoadEntry("wglChoosePixelFormatEXT", false));
|
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATEXTPROC>(LoadEntry("wglChoosePixelFormatEXT", false));
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
|
||||||
glXCreateContextAttribs = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(LoadEntry("glXCreateContextAttribsARB", false));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Récupération de la version d'OpenGL et du GLSL
|
// Récupération de la version d'OpenGL et du GLSL
|
||||||
|
|
@ -976,7 +979,9 @@ bool NzOpenGL::Initialize()
|
||||||
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_LINUX)
|
||||||
glXSwapInterval = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
|
glXSwapIntervalEXT = reinterpret_cast<GLX::PFNGLXSWAPINTERVALEXTPROC>(LoadEntry("glXSwapIntervalEXT", false));
|
||||||
|
NzglXSwapIntervalMESA = reinterpret_cast<GLX::PFNGLXSWAPINTERVALMESAPROC>(LoadEntry("glXSwapIntervalMESA", false));
|
||||||
|
glXSwapIntervalSGI = reinterpret_cast<GLX::PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!glGetStringi || !LoadExtensions3())
|
if (!glGetStringi || !LoadExtensions3())
|
||||||
|
|
@ -2399,6 +2404,8 @@ PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr;
|
||||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr;
|
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr;
|
||||||
PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr;
|
PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr;
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr;
|
GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr;
|
||||||
PFNGLXSWAPINTERVALSGIPROC glXSwapInterval = nullptr;
|
GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
|
||||||
|
GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA = nullptr;
|
||||||
|
GLX::PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,15 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
|
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) :
|
||||||
|
NzRenderTarget(), NzWindow()
|
||||||
{
|
{
|
||||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||||
Create(mode, title, style, parameters);
|
Create(mode, title, style, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters)
|
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters) :
|
||||||
|
NzRenderTarget(), NzWindow()
|
||||||
{
|
{
|
||||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||||
Create(handle, parameters);
|
Create(handle, parameters);
|
||||||
|
|
@ -149,30 +151,13 @@ void NzRenderWindow::EnableVerticalSync(bool enabled)
|
||||||
{
|
{
|
||||||
if (m_context)
|
if (m_context)
|
||||||
{
|
{
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
|
||||||
if (!m_context->SetActive(true))
|
if (!m_context->SetActive(true))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to activate context");
|
NazaraError("Failed to activate context");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wglSwapInterval)
|
m_context->EnableVerticalSync(enabled);
|
||||||
wglSwapInterval(enabled ? 1 : 0);
|
|
||||||
else
|
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
|
||||||
if (!m_context->SetActive(true))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to activate context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glXSwapInterval)
|
|
||||||
glXSwapInterval(enabled ? 1 : 0);
|
|
||||||
else
|
|
||||||
#else
|
|
||||||
#error Vertical Sync is not supported on this platform
|
|
||||||
#endif
|
|
||||||
NazaraError("Vertical Sync is not supported on this platform");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
NazaraError("No context");
|
NazaraError("No context");
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,14 @@ void NzContextImpl::Destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzContextImpl::EnableVerticalSync(bool enabled)
|
||||||
|
{
|
||||||
|
if (wglSwapInterval)
|
||||||
|
wglSwapInterval(enabled ? 1 : 0);
|
||||||
|
else
|
||||||
|
NazaraError("Vertical sync not supported");
|
||||||
|
}
|
||||||
|
|
||||||
void NzContextImpl::SwapBuffers()
|
void NzContextImpl::SwapBuffers()
|
||||||
{
|
{
|
||||||
::SwapBuffers(m_deviceContext);
|
::SwapBuffers(m_deviceContext);
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,13 @@ class NzContextImpl
|
||||||
NzContextImpl();
|
NzContextImpl();
|
||||||
|
|
||||||
bool Activate();
|
bool Activate();
|
||||||
|
|
||||||
bool Create(NzContextParameters& parameters);
|
bool Create(NzContextParameters& parameters);
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
void EnableVerticalSync(bool enabled);
|
||||||
|
|
||||||
void SwapBuffers();
|
void SwapBuffers();
|
||||||
|
|
||||||
static bool Desactivate();
|
static bool Desactivate();
|
||||||
|
|
|
||||||
|
|
@ -247,18 +247,18 @@ namespace
|
||||||
m_misses = 0;
|
m_misses = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMissCount()
|
int GetMissCount() const
|
||||||
{
|
{
|
||||||
return m_misses;
|
return m_misses;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetVertex(int which)
|
int GetVertex(int which) const
|
||||||
{
|
{
|
||||||
return m_cache[which];
|
return m_cache[which];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int FindVertex(int v)
|
int FindVertex(int v) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 32; ++i)
|
for (int i = 0; i < 32; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -328,9 +328,9 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float CalculateVertexScore(unsigned int vertex)
|
float CalculateVertexScore(unsigned int vertex) const
|
||||||
{
|
{
|
||||||
VertexCacheData *v = &m_vertices[vertex];
|
const VertexCacheData* v = &m_vertices[vertex];
|
||||||
if (v->remaining_valence <= 0)
|
if (v->remaining_valence <= 0)
|
||||||
// No tri needs this vertex!
|
// No tri needs this vertex!
|
||||||
return -1.0f;
|
return -1.0f;
|
||||||
|
|
@ -572,7 +572,7 @@ namespace
|
||||||
if (vert < 0)
|
if (vert < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
VertexCacheData *v = &m_vertices[vert];
|
const VertexCacheData* v = &m_vertices[vert];
|
||||||
|
|
||||||
// iterate through all *active* triangles of this vertex
|
// iterate through all *active* triangles of this vertex
|
||||||
for (int j = 0; j < v->remaining_valence; j++)
|
for (int j = 0; j < v->remaining_valence; j++)
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <Nazara/Utility/Win32/CursorImpl.hpp>
|
#include <Nazara/Utility/Win32/CursorImpl.hpp>
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_X11)
|
||||||
#include <Nazara/Utility/Linux/CursorImpl.hpp>
|
#include <Nazara/Utility/X11/CursorImpl.hpp>
|
||||||
#else
|
#else
|
||||||
#error Lack of implementation: Cursor
|
#error Lack of implementation: Cursor
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <Nazara/Utility/Win32/IconImpl.hpp>
|
#include <Nazara/Utility/Win32/IconImpl.hpp>
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_X11)
|
||||||
#include <Nazara/Utility/Linux/IconImpl.hpp>
|
#include <Nazara/Utility/X11/IconImpl.hpp>
|
||||||
#else
|
#else
|
||||||
#error Lack of implementation: Icon
|
#error Lack of implementation: Icon
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <Nazara/Utility/Win32/InputImpl.hpp>
|
#include <Nazara/Utility/Win32/InputImpl.hpp>
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_X11)
|
||||||
#include <Nazara/Utility/Linux/InputImpl.hpp>
|
#include <Nazara/Utility/X11/InputImpl.hpp>
|
||||||
#else
|
#else
|
||||||
#error Lack of implementation: Keyboard
|
#error Lack of implementation: Keyboard
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <Nazara/Utility/Win32/InputImpl.hpp>
|
#include <Nazara/Utility/Win32/InputImpl.hpp>
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_X11)
|
||||||
#include <Nazara/Utility/Linux/InputImpl.hpp>
|
#include <Nazara/Utility/X11/InputImpl.hpp>
|
||||||
#else
|
#else
|
||||||
#error Lack of implementation: Mouse
|
#error Lack of implementation: Mouse
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,17 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Utility/VideoMode.hpp>
|
#include <Nazara/Utility/VideoMode.hpp>
|
||||||
#include <Nazara/Utility/VideoModeImpl.hpp>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
|
#include <Nazara/Utility/Win32/VideoModeImpl.hpp>
|
||||||
|
#elif defined(NAZARA_PLATFORM_X11)
|
||||||
|
#include <Nazara/Utility/X11/VideoModeImpl.hpp>
|
||||||
|
#else
|
||||||
|
#error Lack of implementation: Window
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
NzVideoMode::NzVideoMode() :
|
NzVideoMode::NzVideoMode() :
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// This file is part of the "Nazara Engine - Utility module"
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Utility/VideoModeImpl.hpp>
|
#include <Nazara/Utility/Win32/VideoModeImpl.hpp>
|
||||||
#include <Nazara/Utility/VideoMode.hpp>
|
#include <Nazara/Utility/VideoMode.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_VIDEOMODEIMPL_HPP
|
||||||
|
#define NAZARA_VIDEOMODEIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Utility/VideoMode.hpp>
|
||||||
|
|
||||||
|
class NzVideoModeImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static NzVideoMode GetDesktopMode();
|
||||||
|
static void GetFullscreenModes(std::vector<NzVideoMode>& modes);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NNAZARA_VIDEOMODEIMPL_HPP
|
||||||
|
|
@ -13,8 +13,8 @@
|
||||||
|
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <Nazara/Utility/Win32/WindowImpl.hpp>
|
#include <Nazara/Utility/Win32/WindowImpl.hpp>
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
#elif defined(NAZARA_PLATFORM_X11)
|
||||||
#include <Nazara/Utility/Linux/WindowImpl.hpp>
|
#include <Nazara/Utility/X11/WindowImpl.hpp>
|
||||||
#else
|
#else
|
||||||
#error Lack of implementation: Window
|
#error Lack of implementation: Window
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/CursorImpl.hpp>
|
||||||
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Utility/Image.hpp>
|
||||||
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
#include <xcb/xcb_image.h>
|
||||||
|
#include <xcb/xcb_renderutil.h>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
bool NzCursorImpl::Create(const NzImage& cursor, int hotSpotX, int hotSpotY)
|
||||||
|
{
|
||||||
|
NzImage cursorImage(cursor); // Vive le COW
|
||||||
|
if (!cursorImage.Convert(nzPixelFormat_BGRA8))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to convert cursor to BGRA8");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto width = cursorImage.GetWidth();
|
||||||
|
auto height = cursorImage.GetHeight();
|
||||||
|
|
||||||
|
NzScopedXCBConnection connection;
|
||||||
|
|
||||||
|
xcb_screen_t* screen = X11::XCBDefaultScreen(connection);
|
||||||
|
|
||||||
|
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
|
NzScopedXCB<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,
|
||||||
|
pic,
|
||||||
|
pix,
|
||||||
|
fmt->id,
|
||||||
|
0,
|
||||||
|
nullptr
|
||||||
|
)))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create render picture for cursor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzXCBGContext gc(connection);
|
||||||
|
if (!gc.Create(pix, 0, nullptr))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create gcontext for cursor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!X11::CheckCookie(
|
||||||
|
connection,
|
||||||
|
xcb_image_put(
|
||||||
|
connection,
|
||||||
|
pix,
|
||||||
|
gc,
|
||||||
|
xi,
|
||||||
|
0, 0,
|
||||||
|
0
|
||||||
|
)))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to put image for cursor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cursor = xcb_generate_id(connection);
|
||||||
|
if (!X11::CheckCookie(
|
||||||
|
connection,
|
||||||
|
xcb_render_create_cursor(
|
||||||
|
connection,
|
||||||
|
m_cursor,
|
||||||
|
pic,
|
||||||
|
hotSpotX, hotSpotY
|
||||||
|
)))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create cursor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzCursorImpl::Destroy()
|
||||||
|
{
|
||||||
|
NzScopedXCBConnection connection;
|
||||||
|
|
||||||
|
xcb_free_cursor(connection, m_cursor);
|
||||||
|
m_cursor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_cursor_t NzCursorImpl::GetCursor()
|
||||||
|
{
|
||||||
|
return m_cursor;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_CURSORIMPL_HPP
|
||||||
|
#define NAZARA_CURSORIMPL_HPP
|
||||||
|
|
||||||
|
#include <xcb/xcb_cursor.h>
|
||||||
|
|
||||||
|
class NzImage;
|
||||||
|
|
||||||
|
class NzCursorImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Create(const NzImage& image, int hotSpotX, int hotSpotY);
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
xcb_cursor_t GetCursor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
xcb_cursor_t m_cursor;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_CURSORIMPL_HPP
|
||||||
|
|
@ -0,0 +1,218 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
#include <map>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// The shared display and its reference counter
|
||||||
|
xcb_connection_t* sharedConnection = nullptr;
|
||||||
|
int screen_nbr = 0;
|
||||||
|
unsigned int referenceCountConnection = 0;
|
||||||
|
|
||||||
|
xcb_key_symbols_t* sharedkeySymbol;
|
||||||
|
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(
|
||||||
|
connection,
|
||||||
|
cookie
|
||||||
|
));
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseConnection(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
--referenceCountConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseEWMHConnection(xcb_ewmh_connection_t* ewmh_connection)
|
||||||
|
{
|
||||||
|
NazaraAssert(ewmh_connection == sharedEwmhConnection, "The model is meant for one connection to X11 server");
|
||||||
|
--referenceCountEwmhConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_atom_t GetAtom(const std::string& name, bool onlyIfExists)
|
||||||
|
{
|
||||||
|
AtomMap::const_iterator iter = atoms.find(name);
|
||||||
|
|
||||||
|
if (iter != atoms.end())
|
||||||
|
return iter->second;
|
||||||
|
|
||||||
|
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
|
|
||||||
|
xcb_connection_t* connection = OpenConnection();
|
||||||
|
|
||||||
|
NzScopedXCB<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(
|
||||||
|
connection,
|
||||||
|
xcb_intern_atom(
|
||||||
|
connection,
|
||||||
|
onlyIfExists,
|
||||||
|
name.size(),
|
||||||
|
name.c_str()
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
));
|
||||||
|
|
||||||
|
CloseConnection(connection);
|
||||||
|
|
||||||
|
if (error || !reply)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to get " + name + " atom.");
|
||||||
|
return XCB_ATOM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
atoms[name] = reply->atom;
|
||||||
|
|
||||||
|
return reply->atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
NazaraAssert(referenceCountConnection == 0, "Initialize should be called before anything");
|
||||||
|
NazaraAssert(referenceCountKeySymbol == 0, "Initialize should be called before anything");
|
||||||
|
NazaraAssert(referenceCountEwmhConnection == 0, "Initialize should be called before anything");
|
||||||
|
|
||||||
|
{
|
||||||
|
sharedConnection = xcb_connect(nullptr, &screen_nbr);
|
||||||
|
|
||||||
|
// Opening display failed: The best we can do at the moment is to output a meaningful error message
|
||||||
|
// and cause an abnormal program termination
|
||||||
|
if (!sharedConnection || xcb_connection_has_error(sharedConnection))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to open xcb connection");
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
sharedkeySymbol = xcb_key_symbols_alloc(sharedConnection);
|
||||||
|
|
||||||
|
XCBKeySymbolsAlloc(sharedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
sharedEwmhConnection = new xcb_ewmh_connection_t;
|
||||||
|
xcb_intern_atom_cookie_t* ewmh_cookie = xcb_ewmh_init_atoms(sharedConnection, sharedEwmhConnection);
|
||||||
|
|
||||||
|
if(!xcb_ewmh_init_atoms_replies(sharedEwmhConnection, ewmh_cookie, nullptr))
|
||||||
|
{
|
||||||
|
NazaraError("Could not initialize EWMH Connection");
|
||||||
|
sharedEwmhConnection = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenEWMHConnection(sharedConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_key_symbols_t* XCBKeySymbolsAlloc(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
|
||||||
|
++referenceCountKeySymbol;
|
||||||
|
return sharedkeySymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols)
|
||||||
|
{
|
||||||
|
NazaraAssert(keySymbols == sharedkeySymbol, "The model is meant for one connection to X11 server");
|
||||||
|
|
||||||
|
--referenceCountKeySymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_connection_t* OpenConnection()
|
||||||
|
{
|
||||||
|
++referenceCountConnection;
|
||||||
|
return sharedConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_ewmh_connection_t* OpenEWMHConnection(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
|
||||||
|
++referenceCountEwmhConnection;
|
||||||
|
return sharedEwmhConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uninitialize()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
NazaraAssert(referenceCountEwmhConnection == 1, "Uninitialize should be called after anything or a close is missing");
|
||||||
|
CloseEWMHConnection(sharedEwmhConnection);
|
||||||
|
|
||||||
|
xcb_ewmh_connection_wipe(sharedEwmhConnection);
|
||||||
|
delete sharedEwmhConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
NazaraAssert(referenceCountKeySymbol == 1, "Uninitialize should be called after anything or a free is missing");
|
||||||
|
XCBKeySymbolsFree(sharedkeySymbol);
|
||||||
|
|
||||||
|
xcb_key_symbols_free(sharedkeySymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
NazaraAssert(referenceCountConnection == 1, "Uninitialize should be called after anything or a close is missing");
|
||||||
|
CloseConnection(sharedConnection);
|
||||||
|
|
||||||
|
xcb_disconnect(sharedConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
xcb_screen_t* screen = XCBDefaultScreen(connection);
|
||||||
|
if (screen)
|
||||||
|
return screen->root;
|
||||||
|
return XCB_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
return XCBScreenOfDisplay(connection, screen_nbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int XCBScreen(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
return screen_nbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection == sharedConnection, "The model is meant for one connection to X11 server");
|
||||||
|
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
|
||||||
|
|
||||||
|
for (; iter.rem; --screen_nbr, xcb_screen_next (&iter))
|
||||||
|
{
|
||||||
|
if (screen_nbr == 0)
|
||||||
|
return iter.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_X11DISPLAY_HPP
|
||||||
|
#define NAZARA_X11DISPLAY_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Utility/WindowHandle.hpp>
|
||||||
|
#include <Nazara/Utility/X11/ScopedXCB.hpp>
|
||||||
|
#include <xcb/xcb_ewmh.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
typedef struct _XCBKeySymbols xcb_key_symbols_t;
|
||||||
|
|
||||||
|
namespace X11
|
||||||
|
{
|
||||||
|
bool CheckCookie(xcb_connection_t* connection, xcb_void_cookie_t cookie);
|
||||||
|
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);
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
|
xcb_key_symbols_t* XCBKeySymbolsAlloc(xcb_connection_t* connection);
|
||||||
|
void XCBKeySymbolsFree(xcb_key_symbols_t* keySymbols);
|
||||||
|
|
||||||
|
xcb_connection_t* OpenConnection();
|
||||||
|
xcb_ewmh_connection_t* OpenEWMHConnection(xcb_connection_t* connection);
|
||||||
|
|
||||||
|
void Uninitialize();
|
||||||
|
|
||||||
|
xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection);
|
||||||
|
xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection);
|
||||||
|
int XCBScreen(xcb_connection_t* connection);
|
||||||
|
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NAZARA_X11DISPLAY_HPP
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/IconImpl.hpp>
|
||||||
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Utility/Image.hpp>
|
||||||
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
NzIconImpl::NzIconImpl()
|
||||||
|
{
|
||||||
|
NzScopedXCBConnection connection;
|
||||||
|
|
||||||
|
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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto width = iconImage.GetWidth();
|
||||||
|
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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (i * 8 + k < width)
|
||||||
|
{
|
||||||
|
nzUInt8 opacity = (iconImage.GetConstPixels()[(i * 8 + k + j * width) * 4 + 3] > 0) ? 1 : 0;
|
||||||
|
maskPixels[i + j * pitch] |= (opacity << k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_maskPixmap.CreatePixmapFromBitmapData(
|
||||||
|
X11::XCBDefaultRootWindow(connection),
|
||||||
|
reinterpret_cast<uint8_t*>(&maskPixels[0]),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
nullptr))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create mask pixmap for icon");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onExit.Reset();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzIconImpl::Destroy()
|
||||||
|
{
|
||||||
|
m_iconPixmap.Destroy();
|
||||||
|
m_maskPixmap.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_pixmap_t NzIconImpl::GetIcon()
|
||||||
|
{
|
||||||
|
return m_iconPixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_pixmap_t NzIconImpl::GetMask()
|
||||||
|
{
|
||||||
|
return m_maskPixmap;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_ICONIMPL_HPP
|
||||||
|
#define NAZARA_ICONIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/ScopedXCB.hpp>
|
||||||
|
|
||||||
|
class NzImage;
|
||||||
|
|
||||||
|
class NzIconImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzIconImpl();
|
||||||
|
|
||||||
|
bool Create(const NzImage& image);
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
xcb_pixmap_t GetIcon();
|
||||||
|
xcb_pixmap_t GetMask();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NzXCBPixmap m_iconPixmap;
|
||||||
|
NzXCBPixmap m_maskPixmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_ICONIMPL_HPP
|
||||||
|
|
@ -0,0 +1,371 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/InputImpl.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Utility/Window.hpp>
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include <X11/XF86keysym.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
KeySym GetKeySym(NzKeyboard::Key key)
|
||||||
|
{
|
||||||
|
// X11 keysym correspondant
|
||||||
|
KeySym keysym = 0;
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
// Lettres
|
||||||
|
case NzKeyboard::A: keysym = XK_A; break;
|
||||||
|
case NzKeyboard::B: keysym = XK_B; break;
|
||||||
|
case NzKeyboard::C: keysym = XK_C; break;
|
||||||
|
case NzKeyboard::D: keysym = XK_D; break;
|
||||||
|
case NzKeyboard::E: keysym = XK_E; break;
|
||||||
|
case NzKeyboard::F: keysym = XK_F; break;
|
||||||
|
case NzKeyboard::G: keysym = XK_G; break;
|
||||||
|
case NzKeyboard::H: keysym = XK_H; break;
|
||||||
|
case NzKeyboard::I: keysym = XK_I; break;
|
||||||
|
case NzKeyboard::J: keysym = XK_J; break;
|
||||||
|
case NzKeyboard::K: keysym = XK_K; break;
|
||||||
|
case NzKeyboard::L: keysym = XK_L; break;
|
||||||
|
case NzKeyboard::M: keysym = XK_M; break;
|
||||||
|
case NzKeyboard::N: keysym = XK_N; break;
|
||||||
|
case NzKeyboard::O: keysym = XK_O; break;
|
||||||
|
case NzKeyboard::P: keysym = XK_P; break;
|
||||||
|
case NzKeyboard::Q: keysym = XK_Q; break;
|
||||||
|
case NzKeyboard::R: keysym = XK_R; break;
|
||||||
|
case NzKeyboard::S: keysym = XK_S; break;
|
||||||
|
case NzKeyboard::T: keysym = XK_T; break;
|
||||||
|
case NzKeyboard::U: keysym = XK_U; break;
|
||||||
|
case NzKeyboard::V: keysym = XK_V; break;
|
||||||
|
case NzKeyboard::W: keysym = XK_W; break;
|
||||||
|
case NzKeyboard::X: keysym = XK_X; break;
|
||||||
|
case NzKeyboard::Y: keysym = XK_Y; break;
|
||||||
|
case NzKeyboard::Z: keysym = XK_Z; break;
|
||||||
|
|
||||||
|
// Touches de fonction
|
||||||
|
case NzKeyboard::F1: keysym = XK_F1; break;
|
||||||
|
case NzKeyboard::F2: keysym = XK_F2; break;
|
||||||
|
case NzKeyboard::F3: keysym = XK_F3; break;
|
||||||
|
case NzKeyboard::F4: keysym = XK_F4; break;
|
||||||
|
case NzKeyboard::F5: keysym = XK_F5; break;
|
||||||
|
case NzKeyboard::F6: keysym = XK_F6; break;
|
||||||
|
case NzKeyboard::F7: keysym = XK_F7; break;
|
||||||
|
case NzKeyboard::F8: keysym = XK_F8; break;
|
||||||
|
case NzKeyboard::F9: keysym = XK_F9; break;
|
||||||
|
case NzKeyboard::F10: keysym = XK_F10; break;
|
||||||
|
case NzKeyboard::F11: keysym = XK_F11; break;
|
||||||
|
case NzKeyboard::F12: keysym = XK_F12; break;
|
||||||
|
case NzKeyboard::F13: keysym = XK_F13; break;
|
||||||
|
case NzKeyboard::F14: keysym = XK_F14; break;
|
||||||
|
case NzKeyboard::F15: keysym = XK_F15; break;
|
||||||
|
|
||||||
|
// Flèches directionnelles
|
||||||
|
case NzKeyboard::Down: keysym = XK_Down; break;
|
||||||
|
case NzKeyboard::Left: keysym = XK_Left; break;
|
||||||
|
case NzKeyboard::Right: keysym = XK_Right; break;
|
||||||
|
case NzKeyboard::Up: keysym = XK_Up; break;
|
||||||
|
|
||||||
|
// Pavé numérique
|
||||||
|
case NzKeyboard::Add: keysym = XK_KP_Add; break;
|
||||||
|
case NzKeyboard::Decimal: keysym = XK_KP_Decimal; break;
|
||||||
|
case NzKeyboard::Divide: keysym = XK_KP_Divide; break;
|
||||||
|
case NzKeyboard::Multiply: keysym = XK_KP_Multiply; break;
|
||||||
|
case NzKeyboard::Numpad0: keysym = XK_KP_0; break;
|
||||||
|
case NzKeyboard::Numpad1: keysym = XK_KP_1; break;
|
||||||
|
case NzKeyboard::Numpad2: keysym = XK_KP_2; break;
|
||||||
|
case NzKeyboard::Numpad3: keysym = XK_KP_3; break;
|
||||||
|
case NzKeyboard::Numpad4: keysym = XK_KP_4; break;
|
||||||
|
case NzKeyboard::Numpad5: keysym = XK_KP_5; break;
|
||||||
|
case NzKeyboard::Numpad6: keysym = XK_KP_6; break;
|
||||||
|
case NzKeyboard::Numpad7: keysym = XK_KP_7; break;
|
||||||
|
case NzKeyboard::Numpad8: keysym = XK_KP_8; break;
|
||||||
|
case NzKeyboard::Numpad9: keysym = XK_KP_9; break;
|
||||||
|
case NzKeyboard::Subtract: keysym = XK_KP_Subtract; break;
|
||||||
|
|
||||||
|
// Divers
|
||||||
|
case NzKeyboard::Backslash: keysym = XK_backslash; break;
|
||||||
|
case NzKeyboard::Backspace: keysym = XK_BackSpace; break;
|
||||||
|
case NzKeyboard::Clear: keysym = XK_Clear; break;
|
||||||
|
case NzKeyboard::Comma: keysym = XK_comma; break;
|
||||||
|
case NzKeyboard::Dash: keysym = XK_minus; break;
|
||||||
|
case NzKeyboard::Delete: keysym = XK_Delete; break;
|
||||||
|
case NzKeyboard::End: keysym = XK_End; break;
|
||||||
|
case NzKeyboard::Equal: keysym = XK_equal; break;
|
||||||
|
case NzKeyboard::Escape: keysym = XK_Escape; break;
|
||||||
|
case NzKeyboard::Home: keysym = XK_Home; break;
|
||||||
|
case NzKeyboard::Insert: keysym = XK_Insert; break;
|
||||||
|
case NzKeyboard::LAlt: keysym = XK_Alt_L; break;
|
||||||
|
case NzKeyboard::LBracket: keysym = XK_bracketleft; break;
|
||||||
|
case NzKeyboard::LControl: keysym = XK_Control_L; break;
|
||||||
|
case NzKeyboard::LShift: keysym = XK_Shift_L; break;
|
||||||
|
case NzKeyboard::LSystem: keysym = XK_Super_L; break;
|
||||||
|
case NzKeyboard::Num0: keysym = XK_0; break;
|
||||||
|
case NzKeyboard::Num1: keysym = XK_1; break;
|
||||||
|
case NzKeyboard::Num2: keysym = XK_2; break;
|
||||||
|
case NzKeyboard::Num3: keysym = XK_3; break;
|
||||||
|
case NzKeyboard::Num4: keysym = XK_4; break;
|
||||||
|
case NzKeyboard::Num5: keysym = XK_5; break;
|
||||||
|
case NzKeyboard::Num6: keysym = XK_6; break;
|
||||||
|
case NzKeyboard::Num7: keysym = XK_7; break;
|
||||||
|
case NzKeyboard::Num8: keysym = XK_8; break;
|
||||||
|
case NzKeyboard::Num9: keysym = XK_9; break;
|
||||||
|
case NzKeyboard::PageDown: keysym = XK_Page_Down; break;
|
||||||
|
case NzKeyboard::PageUp: keysym = XK_Page_Up; break;
|
||||||
|
case NzKeyboard::Pause: keysym = XK_Pause; break;
|
||||||
|
case NzKeyboard::Period: keysym = XK_period; break;
|
||||||
|
case NzKeyboard::Print: keysym = XK_Print; break;
|
||||||
|
case NzKeyboard::PrintScreen: keysym = XK_Sys_Req; break;
|
||||||
|
case NzKeyboard::Quote: keysym = XK_quotedbl; break;
|
||||||
|
case NzKeyboard::RAlt: keysym = XK_Alt_R; break;
|
||||||
|
case NzKeyboard::RBracket: keysym = XK_bracketright; break;
|
||||||
|
case NzKeyboard::RControl: keysym = XK_Control_R; break;
|
||||||
|
case NzKeyboard::Return: keysym = XK_Return; break;
|
||||||
|
case NzKeyboard::RShift: keysym = XK_Shift_R; break;
|
||||||
|
case NzKeyboard::RSystem: keysym = XK_Super_R; break;
|
||||||
|
case NzKeyboard::Semicolon: keysym = XK_semicolon; break;
|
||||||
|
case NzKeyboard::Slash: keysym = XK_slash; break;
|
||||||
|
case NzKeyboard::Space: keysym = XK_space; break;
|
||||||
|
case NzKeyboard::Tab: keysym = XK_Tab; break;
|
||||||
|
case NzKeyboard::Tilde: keysym = XK_grave; break;
|
||||||
|
|
||||||
|
// Touches navigateur
|
||||||
|
case NzKeyboard::Browser_Back: keysym = XF86XK_Back; break;
|
||||||
|
case NzKeyboard::Browser_Favorites: keysym = XF86XK_Favorites; break;
|
||||||
|
case NzKeyboard::Browser_Forward: keysym = XF86XK_Forward; break;
|
||||||
|
case NzKeyboard::Browser_Home: keysym = XF86XK_HomePage; break;
|
||||||
|
case NzKeyboard::Browser_Refresh: keysym = XF86XK_Refresh; break;
|
||||||
|
case NzKeyboard::Browser_Search: keysym = XF86XK_Search; break;
|
||||||
|
case NzKeyboard::Browser_Stop: keysym = XF86XK_Stop; break;
|
||||||
|
|
||||||
|
// Touches de contrôle
|
||||||
|
case NzKeyboard::Media_Next: keysym = XF86XK_AudioNext; break;
|
||||||
|
case NzKeyboard::Media_Play: keysym = XF86XK_AudioPlay; break;
|
||||||
|
case NzKeyboard::Media_Previous: keysym = XF86XK_AudioPrev; break;
|
||||||
|
case NzKeyboard::Media_Stop: keysym = XF86XK_AudioStop; break;
|
||||||
|
|
||||||
|
// Touches de contrôle du volume
|
||||||
|
case NzKeyboard::Volume_Down: keysym = XF86XK_AudioLowerVolume; break;
|
||||||
|
case NzKeyboard::Volume_Mute: keysym = XF86XK_AudioMute; break;
|
||||||
|
case NzKeyboard::Volume_Up: keysym = XF86XK_AudioRaiseVolume; break;
|
||||||
|
|
||||||
|
// Touches à verrouillage
|
||||||
|
case NzKeyboard::CapsLock: keysym = XK_Caps_Lock; break;
|
||||||
|
case NzKeyboard::NumLock: keysym = XK_Num_Lock; break;
|
||||||
|
case NzKeyboard::ScrollLock: keysym = XK_Scroll_Lock; break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector2i NzEventImpl::GetMousePosition(const NzWindow& relativeTo)
|
||||||
|
{
|
||||||
|
NzWindowHandle handle = relativeTo.GetHandle();
|
||||||
|
if (handle)
|
||||||
|
{
|
||||||
|
// Open a connection with the X server
|
||||||
|
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,
|
||||||
|
handle
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to query pointer");
|
||||||
|
return NzVector2i(-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NzVector2i(pointer->win_x, pointer->win_y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NazaraError("No window handle");
|
||||||
|
return NzVector2i(-1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzEventImpl::IsKeyPressed(NzKeyboard::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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzScopedXCB<xcb_keycode_t> keyCode = xcb_key_symbols_get_keycode(keySymbols, keySym);
|
||||||
|
if (!keyCode)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to get key code");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
X11::XCBKeySymbolsFree(keySymbols);
|
||||||
|
|
||||||
|
NzScopedXCB<xcb_generic_error_t> error(nullptr);
|
||||||
|
|
||||||
|
// Get the whole keyboard state
|
||||||
|
NzScopedXCB<xcb_query_keymap_reply_t> keymap(
|
||||||
|
xcb_query_keymap_reply(
|
||||||
|
connection,
|
||||||
|
xcb_query_keymap(connection),
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to query keymap");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check our keycode
|
||||||
|
return (keymap->keys[*keyCode.get() / 8] & (1 << (*keyCode.get() % 8))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
X11::XCBDefaultRootWindow(connection)
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to query pointer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t buttons = pointer->mask;
|
||||||
|
|
||||||
|
switch (button)
|
||||||
|
{
|
||||||
|
case NzMouse::Left: return buttons & XCB_BUTTON_MASK_1;
|
||||||
|
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.");
|
||||||
|
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(
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_INPUTIMPL_HPP
|
||||||
|
#define NAZARA_INPUTIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/String.hpp>
|
||||||
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
|
#include <Nazara/Utility/Keyboard.hpp>
|
||||||
|
#include <Nazara/Utility/Mouse.hpp>
|
||||||
|
|
||||||
|
class NzEventImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static NzString GetKeyName(NzKeyboard::Key key);
|
||||||
|
static NzVector2i GetMousePosition();
|
||||||
|
static NzVector2i GetMousePosition(const NzWindow& relativeTo);
|
||||||
|
static bool IsKeyPressed(NzKeyboard::Key key);
|
||||||
|
static bool IsMouseButtonPressed(NzMouse::Button button);
|
||||||
|
static void SetMousePosition(int x, int y);
|
||||||
|
static void SetMousePosition(int x, int y, const NzWindow& relativeTo);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_INPUTIMPL_HPP
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/ScopedXCB.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
#include <xcb/xcb_image.h>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
NzScopedXCBConnection
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
|
NzScopedXCBConnection::NzScopedXCBConnection() :
|
||||||
|
m_connection(nullptr)
|
||||||
|
{
|
||||||
|
m_connection = X11::OpenConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzScopedXCBConnection::~NzScopedXCBConnection()
|
||||||
|
{
|
||||||
|
X11::CloseConnection(m_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzScopedXCBConnection::operator xcb_connection_t*() const
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
NzScopedXCBEWMHConnection
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
|
NzScopedXCBEWMHConnection::NzScopedXCBEWMHConnection(xcb_connection_t* connection) :
|
||||||
|
m_ewmhConnection(nullptr)
|
||||||
|
{
|
||||||
|
m_ewmhConnection = X11::OpenEWMHConnection(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzScopedXCBEWMHConnection::~NzScopedXCBEWMHConnection()
|
||||||
|
{
|
||||||
|
X11::CloseEWMHConnection(m_ewmhConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_ewmh_connection_t* NzScopedXCBEWMHConnection::operator ->() const
|
||||||
|
{
|
||||||
|
return m_ewmhConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzScopedXCBEWMHConnection::operator xcb_ewmh_connection_t*() const
|
||||||
|
{
|
||||||
|
return m_ewmhConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
NzXCBGContext
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
|
NzXCBGContext::NzXCBGContext(xcb_connection_t* connection) :
|
||||||
|
m_connection(connection),
|
||||||
|
m_gcontext(XCB_NONE)
|
||||||
|
{
|
||||||
|
NazaraAssert(connection, "Connection must have been established");
|
||||||
|
}
|
||||||
|
|
||||||
|
NzXCBGContext::~NzXCBGContext()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzXCBGContext::Create(xcb_drawable_t drawable, uint32_t value_mask, const uint32_t* value_list)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_gcontext == XCB_NONE, "Context must have been destroyed before or just created");
|
||||||
|
|
||||||
|
m_gcontext = xcb_generate_id(m_connection);
|
||||||
|
|
||||||
|
return X11::CheckCookie(
|
||||||
|
m_connection,
|
||||||
|
xcb_create_gc(
|
||||||
|
m_connection,
|
||||||
|
m_gcontext,
|
||||||
|
drawable,
|
||||||
|
value_mask,
|
||||||
|
value_list
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_pixmap == XCB_NONE, "Pixmap must have been destroyed before or just created");
|
||||||
|
|
||||||
|
m_pixmap = xcb_create_pixmap_from_bitmap_data(
|
||||||
|
m_connection,
|
||||||
|
drawable,
|
||||||
|
data,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
depth,
|
||||||
|
fg,
|
||||||
|
bg,
|
||||||
|
gcp
|
||||||
|
);
|
||||||
|
|
||||||
|
return m_pixmap != XCB_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzXCBPixmap::Destroy()
|
||||||
|
{
|
||||||
|
if (m_pixmap == XCB_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!X11::CheckCookie(
|
||||||
|
m_connection,
|
||||||
|
xcb_free_pixmap(
|
||||||
|
m_connection,
|
||||||
|
m_pixmap
|
||||||
|
))
|
||||||
|
)
|
||||||
|
NazaraError("Failed to free pixmap");
|
||||||
|
|
||||||
|
m_pixmap = XCB_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzXCBPixmap::operator xcb_pixmap_t() const
|
||||||
|
{
|
||||||
|
return m_pixmap;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_SCOPEDXCB_HPP
|
||||||
|
#define NAZARA_SCOPEDXCB_HPP
|
||||||
|
|
||||||
|
#include <xcb/xcb_ewmh.h>
|
||||||
|
|
||||||
|
class NzScopedXCBConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzScopedXCBConnection();
|
||||||
|
~NzScopedXCBConnection();
|
||||||
|
|
||||||
|
operator xcb_connection_t*() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
xcb_connection_t* m_connection;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NzScopedXCBEWMHConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzScopedXCBEWMHConnection(xcb_connection_t* connection);
|
||||||
|
~NzScopedXCBEWMHConnection();
|
||||||
|
|
||||||
|
xcb_ewmh_connection_t* operator ->() const;
|
||||||
|
|
||||||
|
operator xcb_ewmh_connection_t*() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
xcb_ewmh_connection_t* m_ewmhConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class NzScopedXCB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzScopedXCB(T* pointer);
|
||||||
|
~NzScopedXCB();
|
||||||
|
|
||||||
|
T* operator ->() const;
|
||||||
|
T** operator &();
|
||||||
|
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
T* get() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* m_pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NzXCBGContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzXCBGContext(xcb_connection_t* connection);
|
||||||
|
~NzXCBGContext();
|
||||||
|
|
||||||
|
bool Create(xcb_drawable_t drawable, uint32_t value_mask, const uint32_t* value_list);
|
||||||
|
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
operator xcb_gcontext_t() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
xcb_connection_t* m_connection;
|
||||||
|
xcb_gcontext_t m_gcontext;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NzXCBPixmap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzXCBPixmap();
|
||||||
|
NzXCBPixmap(xcb_connection_t* connection);
|
||||||
|
~NzXCBPixmap();
|
||||||
|
|
||||||
|
void Connect(xcb_connection_t* connection);
|
||||||
|
bool Create(uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height);
|
||||||
|
bool CreatePixmapFromBitmapData(xcb_drawable_t drawable, uint8_t* data, uint32_t width, uint32_t height, uint32_t depth, uint32_t fg, uint32_t bg, xcb_gcontext_t* gcp);
|
||||||
|
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
operator xcb_pixmap_t() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
xcb_connection_t* m_connection;
|
||||||
|
xcb_pixmap_t m_pixmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/ScopedXCB.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_SCOPEDXCB_HPP
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
NzScopedXCB<T>::NzScopedXCB(T* pointer) :
|
||||||
|
m_pointer(pointer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
NzScopedXCB<T>::~NzScopedXCB()
|
||||||
|
{
|
||||||
|
std::free(m_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* NzScopedXCB<T>::operator ->() const
|
||||||
|
{
|
||||||
|
return m_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T** NzScopedXCB<T>::operator &()
|
||||||
|
{
|
||||||
|
return &m_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
NzScopedXCB<T>::operator bool() const
|
||||||
|
{
|
||||||
|
return m_pointer != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* NzScopedXCB<T>::get() const
|
||||||
|
{
|
||||||
|
return m_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Utility/DebugOff.hpp>
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Utility/X11/VideoModeImpl.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Utility/VideoMode.hpp>
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
#include <xcb/randr.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
NzVideoMode NzVideoModeImpl::GetDesktopMode()
|
||||||
|
{
|
||||||
|
NzVideoMode desktopMode;
|
||||||
|
|
||||||
|
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
|
||||||
|
NazaraError("Failed to use the RandR extension while trying to get the desktop video mode");
|
||||||
|
return desktopMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 desktop video mode");
|
||||||
|
return desktopMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 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 = 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)
|
||||||
|
{
|
||||||
|
// Convert to VideoMode
|
||||||
|
NzVideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
|
||||||
|
|
||||||
|
if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
|
||||||
|
config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
|
||||||
|
std::swap(mode.width, mode.height);
|
||||||
|
|
||||||
|
// Add it only if it is not already in the array
|
||||||
|
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
|
||||||
|
modes.push_back(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_VIDEOMODEIMPL_HPP
|
||||||
|
#define NAZARA_VIDEOMODEIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Utility/VideoMode.hpp>
|
||||||
|
|
||||||
|
class NzVideoModeImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static NzVideoMode GetDesktopMode();
|
||||||
|
static void GetFullscreenModes(std::vector<NzVideoMode>& modes);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NNAZARA_VIDEOMODEIMPL_HPP
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,126 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
// Interface inspirée de la SFML par Laurent Gomila
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_WINDOWIMPL_HPP
|
||||||
|
#define NAZARA_WINDOWIMPL_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/NonCopyable.hpp>
|
||||||
|
#include <Nazara/Core/Thread.hpp>
|
||||||
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
|
#include <Nazara/Utility/Keyboard.hpp>
|
||||||
|
#include <xcb/randr.h>
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
|
#include <Nazara/Utility/X11/Display.hpp>
|
||||||
|
|
||||||
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
|
class NzConditionVariable;
|
||||||
|
class NzMutex;
|
||||||
|
#endif
|
||||||
|
class NzCursor;
|
||||||
|
class NzIcon;
|
||||||
|
class NzVideoMode;
|
||||||
|
class NzWindow;
|
||||||
|
|
||||||
|
class NzWindowImpl : NzNonCopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzWindowImpl(NzWindow* parent);
|
||||||
|
~NzWindowImpl();
|
||||||
|
|
||||||
|
bool Create(const NzVideoMode& mode, const NzString& title, nzUInt32 style);
|
||||||
|
bool Create(NzWindowHandle handle);
|
||||||
|
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
void EnableKeyRepeat(bool enable);
|
||||||
|
void EnableSmoothScrolling(bool enable);
|
||||||
|
|
||||||
|
NzWindowHandle GetHandle() const;
|
||||||
|
unsigned int GetHeight() const;
|
||||||
|
NzVector2i GetPosition() const;
|
||||||
|
NzVector2ui GetSize() const;
|
||||||
|
nzUInt32 GetStyle() const;
|
||||||
|
NzString GetTitle() const;
|
||||||
|
unsigned int GetWidth() const;
|
||||||
|
|
||||||
|
bool HasFocus() const;
|
||||||
|
|
||||||
|
void IgnoreNextMouseEvent(int mouseX, int mouseY);
|
||||||
|
|
||||||
|
bool IsMinimized() const;
|
||||||
|
bool IsVisible() const;
|
||||||
|
|
||||||
|
void ProcessEvents(bool block);
|
||||||
|
|
||||||
|
void SetCursor(nzWindowCursor cursor);
|
||||||
|
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();
|
||||||
|
static void Uninitialize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void CleanUp();
|
||||||
|
xcb_keysym_t ConvertKeyCodeToKeySym(xcb_keycode_t keycode, uint16_t state);
|
||||||
|
NzKeyboard::Key ConvertVirtualKey(xcb_keysym_t symbol);
|
||||||
|
const char* ConvertWindowCursorToXName(nzWindowCursor cursor);
|
||||||
|
void CommonInitialize();
|
||||||
|
|
||||||
|
void ProcessEvent(xcb_generic_event_t* windowEvent);
|
||||||
|
|
||||||
|
void ResetVideoMode();
|
||||||
|
|
||||||
|
void SetCursor(xcb_cursor_t cursor);
|
||||||
|
void SetMotifHints();
|
||||||
|
void SetVideoMode(const NzVideoMode& mode);
|
||||||
|
void SwitchToFullscreen();
|
||||||
|
|
||||||
|
bool UpdateNormalHints();
|
||||||
|
void UpdateEventQueue(xcb_generic_event_t* event);
|
||||||
|
|
||||||
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
|
static void WindowThread(NzWindowImpl* window, NzMutex* mutex, NzConditionVariable* condition);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xcb_window_t m_window;
|
||||||
|
xcb_screen_t* m_screen;
|
||||||
|
xcb_randr_get_screen_info_reply_t m_oldVideoMode;
|
||||||
|
xcb_size_hints_t m_size_hints;
|
||||||
|
nzUInt32 m_style;
|
||||||
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
|
NzThread m_thread;
|
||||||
|
#endif
|
||||||
|
NzWindow* m_parent;
|
||||||
|
bool m_eventListener;
|
||||||
|
bool m_ownsWindow;
|
||||||
|
bool m_smoothScrolling;
|
||||||
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
|
bool m_threadActive;
|
||||||
|
#endif
|
||||||
|
short m_scrolling;
|
||||||
|
NzVector2i m_mousePos;
|
||||||
|
bool m_keyRepeat;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
xcb_generic_event_t* curr = nullptr;
|
||||||
|
xcb_generic_event_t* next = nullptr;
|
||||||
|
} m_eventQueue;
|
||||||
|
};
|
||||||
|
#endif // NAZARA_WINDOWIMPL_HPP
|
||||||
|
|
@ -65,7 +65,7 @@ SCENARIO("StringStream", "[CORE][STRINGSTREAM]")
|
||||||
stringstream << NzString("3");
|
stringstream << NzString("3");
|
||||||
stringstream << static_cast<void*>(nullptr);
|
stringstream << static_cast<void*>(nullptr);
|
||||||
|
|
||||||
REQUIRE(stringstream.ToString() == (NzString("default3330x") + NzString(sizeof(void*) * 2, "0")));
|
REQUIRE(stringstream.ToString() == (NzString("default333") + NzString::Pointer(nullptr)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,9 @@ SCENARIO("EulerAngles", "[MATH][EULERANGLES]")
|
||||||
{
|
{
|
||||||
THEN("These results are expected")
|
THEN("These results are expected")
|
||||||
{
|
{
|
||||||
REQUIRE(NzEulerAnglesf(NzFromDegrees(45.f), 0.f, 0.f) == NzQuaternionf(0.923879504204f, 0.382683455944f, 0.f, 0.f).ToEulerAngles());
|
REQUIRE(NzEulerAngles<int>(NzFromDegrees(45.f), 0.f, 0.f) == NzEulerAngles<int>(NzQuaternionf(0.923879504204f, 0.382683455944f, 0.f, 0.f).ToEulerAngles()));
|
||||||
REQUIRE(NzEulerAnglesf(0.f, NzFromDegrees(45.f), 0.f) == NzQuaternionf(0.923879504204f, 0.f, 0.382683455944f, 0.f).ToEulerAngles());
|
REQUIRE(NzEulerAngles<int>(0.f, NzFromDegrees(45.f), 0.f) == NzEulerAngles<int>(NzQuaternionf(0.923879504204f, 0.f, 0.382683455944f, 0.f).ToEulerAngles()));
|
||||||
//REQUIRE(NzEulerAnglesf(0.f, 0.f, NzFromDegrees(45.f)) == NzQuaternionf(0.923879504204f, 0.f, 0.f, 0.382683455944f).ToEulerAngles());
|
REQUIRE(NzEulerAngles<int>(0.f, 0.f, NzFromDegrees(45.f)) == NzEulerAngles<int>(NzQuaternionf(0.923879504204f, 0.f, 0.f, 0.382683455944f).ToEulerAngles()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ SCENARIO("OrientedBox", "[MATH][ORIENTEDBOX]")
|
||||||
NzOrientedBoxf secondCenterAndUnit(NzOrientedBox<int>(NzVector3i::Zero(), NzVector3i::Unit()));
|
NzOrientedBoxf secondCenterAndUnit(NzOrientedBox<int>(NzVector3i::Zero(), NzVector3i::Unit()));
|
||||||
|
|
||||||
firstCenterAndUnit.Update(NzMatrix4f::Identity());
|
firstCenterAndUnit.Update(NzMatrix4f::Identity());
|
||||||
|
secondCenterAndUnit.Update(NzMatrix4f::Identity());
|
||||||
|
|
||||||
WHEN("We compare them")
|
WHEN("We compare them")
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,11 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]")
|
||||||
NzQuaternionf quaterionB(NzFromDegrees(45.f), NzVector3f::UnitZ());
|
NzQuaternionf quaterionB(NzFromDegrees(45.f), NzVector3f::UnitZ());
|
||||||
NzQuaternionf quaternionC = NzQuaternionf::Slerp(quaterionA, quaterionB, 0.5f);
|
NzQuaternionf quaternionC = NzQuaternionf::Slerp(quaterionA, quaterionB, 0.5f);
|
||||||
|
|
||||||
REQUIRE(quaternionC == NzQuaternionf(NzFromDegrees(22.5f), NzVector3f::UnitZ()));
|
NzQuaternionf unitZ225(NzFromDegrees(22.5f), NzVector3f::UnitZ());
|
||||||
|
REQUIRE(quaternionC.w == Approx(unitZ225.w));
|
||||||
|
REQUIRE(quaternionC.x == Approx(unitZ225.x));
|
||||||
|
REQUIRE(quaternionC.y == Approx(unitZ225.y));
|
||||||
|
REQUIRE(quaternionC.z == Approx(unitZ225.z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue