Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/ghost/intern')
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp11
-rw-r--r--intern/ghost/intern/GHOST_Context.cpp7
-rw-r--r--intern/ghost/intern/GHOST_Context.h12
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h79
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm814
-rw-r--r--intern/ghost/intern/GHOST_ContextD3D.cpp14
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.cpp106
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.h9
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp16
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h4
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp406
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerNULL.h26
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.cpp52
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp219
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.h33
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.cpp6
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.cpp7
-rw-r--r--intern/ghost/intern/GHOST_ISystem.cpp68
-rw-r--r--intern/ghost/intern/GHOST_IXrGraphicsBinding.h3
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.cpp31
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.h17
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerWin32.cpp6
-rw-r--r--intern/ghost/intern/GHOST_System.cpp15
-rw-r--r--intern/ghost/intern/GHOST_System.h12
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm9
-rw-r--r--intern/ghost/intern/GHOST_SystemHeadless.h166
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h122
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsUnix.cpp9
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp10
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp1588
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h22
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp829
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h52
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp179
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h4
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp5
-rw-r--r--intern/ghost/intern/GHOST_Window.h72
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h84
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp1
-rw-r--r--intern/ghost/intern/GHOST_WindowViewCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp71
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h14
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp115
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp301
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h2
-rw-r--r--intern/ghost/intern/GHOST_XrContext.cpp8
-rw-r--r--intern/ghost/intern/GHOST_XrGraphicsBinding.cpp124
-rw-r--r--intern/ghost/intern/GHOST_Xr_openxr_includes.h9
-rw-r--r--intern/ghost/intern/GHOST_utildefines.h29
58 files changed, 3135 insertions, 2696 deletions
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 65e7de707ec..710512881e8 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -30,6 +30,14 @@ GHOST_SystemHandle GHOST_CreateSystem(void)
return (GHOST_SystemHandle)system;
}
+GHOST_SystemHandle GHOST_CreateSystemBackground(void)
+{
+ GHOST_ISystem::createSystemBackground();
+ GHOST_ISystem *system = GHOST_ISystem::getSystem();
+
+ return (GHOST_SystemHandle)system;
+}
+
void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, GHOST_Debug debug)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -861,8 +869,7 @@ void GHOST_putClipboard(const char *buffer, bool selection)
bool GHOST_setConsoleWindowState(GHOST_TConsoleWindowState action)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
- /* FIXME: use `bool` instead of int for this value. */
- return (bool)system->setConsoleWindowState(action);
+ return system->setConsoleWindowState(action);
}
bool GHOST_UseNativePixels(void)
diff --git a/intern/ghost/intern/GHOST_Context.cpp b/intern/ghost/intern/GHOST_Context.cpp
index f4b3d08ffc5..aa379efbc1f 100644
--- a/intern/ghost/intern/GHOST_Context.cpp
+++ b/intern/ghost/intern/GHOST_Context.cpp
@@ -10,7 +10,7 @@
#include "GHOST_Context.h"
#ifdef _WIN32
-# include <GL/wglew.h> // only for symbolic constants, do not use API functions
+# include <epoxy/wgl.h>
# include <tchar.h>
#
# ifndef ERROR_PROFILE_DOES_NOT_MATCH_DEVICE
@@ -123,11 +123,6 @@ bool win32_chk(bool result, const char *file, int line, const char *text)
#endif // _WIN32
-void GHOST_Context::initContextGLEW()
-{
- GLEW_CHK(glewInit());
-}
-
void GHOST_Context::initClearGL()
{
glClearColor(0.294, 0.294, 0.294, 0.000);
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
index e707f1c3475..04d445e7f85 100644
--- a/intern/ghost/intern/GHOST_Context.h
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -11,7 +11,7 @@
#include "GHOST_IContext.h"
#include "GHOST_Types.h"
-#include "glew-mx.h"
+#include <epoxy/gl.h>
#include <cstdlib> // for NULL
@@ -36,19 +36,19 @@ class GHOST_Context : public GHOST_IContext {
* Swaps front and back buffers of a window.
* \return A boolean success indicator.
*/
- virtual GHOST_TSuccess swapBuffers() = 0;
+ virtual GHOST_TSuccess swapBuffers() override = 0;
/**
* Activates the drawing context of this window.
* \return A boolean success indicator.
*/
- virtual GHOST_TSuccess activateDrawingContext() = 0;
+ virtual GHOST_TSuccess activateDrawingContext() override = 0;
/**
* Release the drawing context of the calling thread.
* \return A boolean success indicator.
*/
- virtual GHOST_TSuccess releaseDrawingContext() = 0;
+ virtual GHOST_TSuccess releaseDrawingContext() override = 0;
/**
* Call immediately after new to initialize. If this fails then immediately delete the object.
@@ -130,14 +130,12 @@ class GHOST_Context : public GHOST_IContext {
* Gets the OpenGL frame-buffer associated with the OpenGL context
* \return The ID of an OpenGL frame-buffer object.
*/
- virtual unsigned int getDefaultFramebuffer()
+ virtual unsigned int getDefaultFramebuffer() override
{
return 0;
}
protected:
- void initContextGLEW();
-
bool m_stereoVisual;
/** Caller specified, not for internal use. */
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index badc3241107..130b926f25c 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -9,8 +9,13 @@
#include "GHOST_Context.h"
+#include <Cocoa/Cocoa.h>
+#include <Metal/Metal.h>
+#include <QuartzCore/QuartzCore.h>
+
@class CAMetalLayer;
@class MTLCommandQueue;
+@class MTLDevice;
@class MTLRenderPipelineState;
@class MTLTexture;
@class NSOpenGLContext;
@@ -36,62 +41,89 @@ class GHOST_ContextCGL : public GHOST_Context {
* Swaps front and back buffers of a window.
* \return A boolean success indicator.
*/
- GHOST_TSuccess swapBuffers();
+ GHOST_TSuccess swapBuffers() override;
/**
* Activates the drawing context of this window.
* \return A boolean success indicator.
*/
- GHOST_TSuccess activateDrawingContext();
+ GHOST_TSuccess activateDrawingContext() override;
/**
* Release the drawing context of the calling thread.
* \return A boolean success indicator.
*/
- GHOST_TSuccess releaseDrawingContext();
+ GHOST_TSuccess releaseDrawingContext() override;
- unsigned int getDefaultFramebuffer();
+ unsigned int getDefaultFramebuffer() override;
/**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
- GHOST_TSuccess initializeDrawingContext();
+ GHOST_TSuccess initializeDrawingContext() override;
/**
* Removes references to native handles from this context and then returns
* \return GHOST_kSuccess if it is OK for the parent to release the handles and
* GHOST_kFailure if releasing the handles will interfere with sharing
*/
- GHOST_TSuccess releaseNativeHandles();
+ GHOST_TSuccess releaseNativeHandles() override;
/**
* Sets the swap interval for #swapBuffers.
* \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
- GHOST_TSuccess setSwapInterval(int interval);
+ GHOST_TSuccess setSwapInterval(int interval) override;
/**
* Gets the current swap interval for #swapBuffers.
* \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
- GHOST_TSuccess getSwapInterval(int &);
+ GHOST_TSuccess getSwapInterval(int &) override;
/**
* Updates the drawing context of this window.
* Needed whenever the window is changed.
* \return Indication of success.
*/
- GHOST_TSuccess updateDrawingContext();
+ GHOST_TSuccess updateDrawingContext() override;
+
+ /**
+ * Returns a texture that Metal code can use as a render target. The current
+ * contents of this texture will be composited on top of the frame-buffer
+ * each time `swapBuffers` is called.
+ */
+ id<MTLTexture> metalOverlayTexture();
+
+ /**
+ * Return a pointer to the Metal command queue used by this context.
+ */
+ MTLCommandQueue *metalCommandQueue();
+
+ /**
+ * Return a pointer to the Metal device associated with this context.
+ */
+ MTLDevice *metalDevice();
+
+ /**
+ * Register present callback
+ */
+ void metalRegisterPresentCallback(void (*callback)(
+ MTLRenderPassDescriptor *, id<MTLRenderPipelineState>, id<MTLTexture>, id<CAMetalDrawable>));
private:
/** Metal state */
+ /* Set this flag to `true` when rendering with Metal API for Viewport.
+ * TODO(Metal): This should be assigned to externally. */
+ bool m_useMetalForRendering = false;
NSView *m_metalView;
CAMetalLayer *m_metalLayer;
MTLCommandQueue *m_metalCmdQueue;
MTLRenderPipelineState *m_metalRenderPipeline;
+ bool m_ownsMetalDevice;
/** OpenGL state, for GPUs that don't support Metal */
NSOpenGLView *m_openGLView;
@@ -103,10 +135,30 @@ class GHOST_ContextCGL : public GHOST_Context {
unsigned int m_defaultFramebuffer;
/** The virtualized default frame-buffer's texture. */
- MTLTexture *m_defaultFramebufferMetalTexture;
-
- bool m_coreProfile;
-
+ /**
+ * Texture that you can render into with Metal. The texture will be
+ * composited on top of `m_defaultFramebufferMetalTexture` whenever
+ * `swapBuffers` is called.
+ */
+ static const int METAL_SWAPCHAIN_SIZE = 3;
+ struct MTLSwapchainTexture {
+ id<MTLTexture> texture;
+ unsigned int index;
+ };
+ MTLSwapchainTexture m_defaultFramebufferMetalTexture[METAL_SWAPCHAIN_SIZE];
+ unsigned int current_swapchain_index = 0;
+
+ /* Present callback.
+ * We use this such that presentation can be controlled from within the Metal
+ * Context. This is required for optimal performance and clean control flow.
+ * Also helps ensure flickering does not occur by present being dependent
+ * on existing submissions. */
+ void (*contextPresentCallback)(MTLRenderPassDescriptor *,
+ id<MTLRenderPipelineState>,
+ id<MTLTexture>,
+ id<CAMetalDrawable>);
+
+ int mtl_SwapInterval;
const bool m_debug;
/** The first created OpenGL context (for sharing display lists) */
@@ -119,4 +171,5 @@ class GHOST_ContextCGL : public GHOST_Context {
void metalInitFramebuffer();
void metalUpdateFramebuffer();
void metalSwapBuffers();
+ void initClear();
};
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index dd800ef52a3..ff53ecdbbba 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -55,159 +55,291 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
m_openGLView(openGLView),
m_openGLContext(nil),
m_defaultFramebuffer(0),
- m_defaultFramebufferMetalTexture(nil),
m_debug(false)
{
-#if defined(WITH_GL_PROFILE_CORE)
- m_coreProfile = true;
-#else
- m_coreProfile = false;
-#endif
-
+ /* Initialize Metal Swap-chain. */
+ current_swapchain_index = 0;
+ for (int i = 0; i < METAL_SWAPCHAIN_SIZE; i++) {
+ m_defaultFramebufferMetalTexture[i].texture = nil;
+ m_defaultFramebufferMetalTexture[i].index = i;
+ }
if (m_metalView) {
+ m_ownsMetalDevice = false;
metalInit();
}
+ else {
+ /* Prepare offscreen GHOST Context Metal device. */
+ id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
+
+ if (m_debug) {
+ printf("Selected Metal Device: %s\n", [metalDevice.name UTF8String]);
+ }
+
+ m_ownsMetalDevice = true;
+ if (metalDevice) {
+ m_metalLayer = [[CAMetalLayer alloc] init];
+ [m_metalLayer setEdgeAntialiasingMask:0];
+ [m_metalLayer setMasksToBounds:NO];
+ [m_metalLayer setOpaque:YES];
+ [m_metalLayer setFramebufferOnly:YES];
+ [m_metalLayer setPresentsWithTransaction:NO];
+ [m_metalLayer removeAllAnimations];
+ [m_metalLayer setDevice:metalDevice];
+ m_metalLayer.allowsNextDrawableTimeout = NO;
+ metalInit();
+ }
+ else {
+ ghost_fatal_error_dialog(
+ "[ERROR] Failed to create Metal device for offscreen GHOST Context.\n");
+ }
+ }
+
+ /* Initialize swap-interval. */
+ mtl_SwapInterval = 60;
}
GHOST_ContextCGL::~GHOST_ContextCGL()
{
metalFree();
- if (m_openGLContext != nil) {
- if (m_openGLContext == [NSOpenGLContext currentContext]) {
- [NSOpenGLContext clearCurrentContext];
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ if (m_openGLContext != nil) {
+ if (m_openGLContext == [NSOpenGLContext currentContext]) {
+ [NSOpenGLContext clearCurrentContext];
- if (m_openGLView) {
- [m_openGLView clearGLContext];
+ if (m_openGLView) {
+ [m_openGLView clearGLContext];
+ }
}
- }
- if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
- assert(s_sharedCount > 0);
+ if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
- s_sharedCount--;
+ s_sharedCount--;
- if (s_sharedCount == 0)
- s_sharedOpenGLContext = nil;
+ if (s_sharedCount == 0)
+ s_sharedOpenGLContext = nil;
- [m_openGLContext release];
+ [m_openGLContext release];
+ }
+ }
+#endif
+ }
+
+ if (m_ownsMetalDevice) {
+ if (m_metalLayer) {
+ [m_metalLayer release];
+ m_metalLayer = nil;
}
}
}
GHOST_TSuccess GHOST_ContextCGL::swapBuffers()
{
- if (m_openGLContext != nil) {
- if (m_metalView) {
- metalSwapBuffers();
+ GHOST_TSuccess return_value = GHOST_kFailure;
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ if (m_openGLContext != nil) {
+ if (m_metalView) {
+ metalSwapBuffers();
+ }
+ else if (m_openGLView) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext flushBuffer];
+ [pool drain];
+ }
+ return_value = GHOST_kSuccess;
}
- else if (m_openGLView) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext flushBuffer];
- [pool drain];
+ else {
+ return_value = GHOST_kFailure;
}
- return GHOST_kSuccess;
+#endif
}
else {
- return GHOST_kFailure;
+ if (m_metalView) {
+ metalSwapBuffers();
+ }
+ return_value = GHOST_kSuccess;
}
+ return return_value;
}
GHOST_TSuccess GHOST_ContextCGL::setSwapInterval(int interval)
{
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext setValues:&interval forParameter:NSOpenGLCPSwapInterval];
- [pool drain];
- return GHOST_kSuccess;
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext setValues:&interval forParameter:NSOpenGLCPSwapInterval];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+#endif
}
else {
- return GHOST_kFailure;
+ mtl_SwapInterval = interval;
+ return GHOST_kSuccess;
}
}
GHOST_TSuccess GHOST_ContextCGL::getSwapInterval(int &intervalOut)
{
- if (m_openGLContext != nil) {
- GLint interval;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ if (m_openGLContext != nil) {
+ GLint interval;
- [m_openGLContext getValues:&interval forParameter:NSOpenGLCPSwapInterval];
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [pool drain];
+ [m_openGLContext getValues:&interval forParameter:NSOpenGLCPSwapInterval];
- intervalOut = static_cast<int>(interval);
+ [pool drain];
- return GHOST_kSuccess;
+ intervalOut = static_cast<int>(interval);
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+#endif
}
else {
- return GHOST_kFailure;
+ intervalOut = mtl_SwapInterval;
+ return GHOST_kSuccess;
}
}
GHOST_TSuccess GHOST_ContextCGL::activateDrawingContext()
{
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext makeCurrentContext];
- [pool drain];
- return GHOST_kSuccess;
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext makeCurrentContext];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+#endif
}
else {
- return GHOST_kFailure;
+ return GHOST_kSuccess;
}
}
GHOST_TSuccess GHOST_ContextCGL::releaseDrawingContext()
{
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [NSOpenGLContext clearCurrentContext];
- [pool drain];
- return GHOST_kSuccess;
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [NSOpenGLContext clearCurrentContext];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+#endif
}
else {
- return GHOST_kFailure;
+ return GHOST_kSuccess;
}
}
unsigned int GHOST_ContextCGL::getDefaultFramebuffer()
{
- return m_defaultFramebuffer;
+
+ if (!m_useMetalForRendering) {
+ return m_defaultFramebuffer;
+ }
+ /* NOTE(Metal): This is not valid. */
+ return 0;
}
GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
{
- if (m_openGLContext != nil) {
- if (m_metalView) {
- metalUpdateFramebuffer();
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ if (m_openGLContext != nil) {
+ if (m_metalView) {
+ metalUpdateFramebuffer();
+ }
+ else if (m_openGLView) {
+ @autoreleasepool {
+ [m_openGLContext update];
+ }
+ }
+
+ return GHOST_kSuccess;
}
- else if (m_openGLView) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext update];
- [pool drain];
+ else {
+ return GHOST_kFailure;
}
-
- return GHOST_kSuccess;
+#endif
}
else {
- return GHOST_kFailure;
+ if (m_metalView) {
+ metalUpdateFramebuffer();
+ return GHOST_kSuccess;
+ }
}
+ return GHOST_kFailure;
+}
+
+id<MTLTexture> GHOST_ContextCGL::metalOverlayTexture()
+{
+ /* Increment Swap-chain - Only needed if context is requesting a new texture */
+ current_swapchain_index = (current_swapchain_index + 1) % METAL_SWAPCHAIN_SIZE;
+
+ /* Ensure backing texture is ready for current swapchain index */
+ updateDrawingContext();
+
+ /* Return texture. */
+ return m_defaultFramebufferMetalTexture[current_swapchain_index].texture;
+}
+
+MTLCommandQueue *GHOST_ContextCGL::metalCommandQueue()
+{
+ return m_metalCmdQueue;
+}
+MTLDevice *GHOST_ContextCGL::metalDevice()
+{
+ id<MTLDevice> device = m_metalLayer.device;
+ return (MTLDevice *)device;
+}
+
+void GHOST_ContextCGL::metalRegisterPresentCallback(void (*callback)(
+ MTLRenderPassDescriptor *, id<MTLRenderPipelineState>, id<MTLTexture>, id<CAMetalDrawable>))
+{
+ this->contextPresentCallback = callback;
}
static void makeAttribList(std::vector<NSOpenGLPixelFormatAttribute> &attribs,
- bool coreProfile,
bool stereoVisual,
bool needAlpha,
- bool softwareGL)
+ bool softwareGL,
+ bool increasedSamplerLimit)
{
attribs.clear();
attribs.push_back(NSOpenGLPFAOpenGLProfile);
- attribs.push_back(coreProfile ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy);
+ attribs.push_back(NSOpenGLProfileVersion3_2Core);
- /* Pixel Format Attributes for the windowed NSOpenGLContext. */
+ /* Pixel Format Attributes for the windowed #NSOpenGLContext. */
attribs.push_back(NSOpenGLPFADoubleBuffer);
if (softwareGL) {
@@ -217,6 +349,12 @@ static void makeAttribList(std::vector<NSOpenGLPixelFormatAttribute> &attribs,
else {
attribs.push_back(NSOpenGLPFAAccelerated);
attribs.push_back(NSOpenGLPFANoRecovery);
+
+ /* Attempt to initialize device with extended sampler limit.
+ * Resolves EEVEE purple rendering artifacts on macOS. */
+ if (increasedSamplerLimit) {
+ attribs.push_back((NSOpenGLPixelFormatAttribute)400);
+ }
}
if (stereoVisual)
@@ -232,88 +370,143 @@ static void makeAttribList(std::vector<NSOpenGLPixelFormatAttribute> &attribs,
GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ @autoreleasepool {
#ifdef GHOST_OPENGL_ALPHA
- static const bool needAlpha = true;
+ static const bool needAlpha = true;
#else
- static const bool needAlpha = false;
+ static const bool needAlpha = false;
#endif
- /* Command-line argument would be better. */
- static bool softwareGL = getenv("BLENDER_SOFTWAREGL");
-
- std::vector<NSOpenGLPixelFormatAttribute> attribs;
- attribs.reserve(40);
- makeAttribList(attribs, m_coreProfile, m_stereoVisual, needAlpha, softwareGL);
+ /* Command-line argument would be better. */
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ /* Command-line argument would be better. */
+ static bool softwareGL = getenv("BLENDER_SOFTWAREGL");
+
+ NSOpenGLPixelFormat *pixelFormat = nil;
+ std::vector<NSOpenGLPixelFormatAttribute> attribs;
+ bool increasedSamplerLimit = false;
+
+ /* Attempt to initialize device with increased sampler limit.
+ * If this is unsupported and initialization fails, initialize GL Context as normal.
+ *
+ * NOTE: This is not available when using the SoftwareGL path, or for Intel-based
+ * platforms. */
+ if (!softwareGL) {
+ if (@available(macos 11.0, *)) {
+ increasedSamplerLimit = true;
+ }
+ }
+ const int max_ctx_attempts = increasedSamplerLimit ? 2 : 1;
+ for (int ctx_create_attempt = 0; ctx_create_attempt < max_ctx_attempts;
+ ctx_create_attempt++) {
+
+ attribs.clear();
+ attribs.reserve(40);
+ makeAttribList(attribs, m_stereoVisual, needAlpha, softwareGL, increasedSamplerLimit);
+
+ pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
+ if (pixelFormat == nil) {
+ /* If pixel format creation fails when testing increased sampler limit,
+ * attempt initialization again with feature disabled, otherwise, fail. */
+ if (increasedSamplerLimit) {
+ increasedSamplerLimit = false;
+ continue;
+ }
+ return GHOST_kFailure;
+ }
+
+ /* Attempt to create context. */
+ m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
+ shareContext:s_sharedOpenGLContext];
+ [pixelFormat release];
+
+ if (m_openGLContext == nil) {
+ /* If context creation fails when testing increased sampler limit,
+ * attempt re-creation with feature disabled. Otherwise, error. */
+ if (increasedSamplerLimit) {
+ increasedSamplerLimit = false;
+ continue;
+ }
+
+ /* Default context creation attempt failed. */
+ return GHOST_kFailure;
+ }
+
+ /* Created GL context successfully, activate. */
+ [m_openGLContext makeCurrentContext];
+
+ /* When increasing sampler limit, verify created context is a supported configuration. */
+ if (increasedSamplerLimit) {
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
+ const char *renderer = (const char *)glGetString(GL_RENDERER);
+
+ /* If generated context type is unsupported, release existing context and
+ * fallback to creating a normal context below. */
+ if (strstr(vendor, "Intel") || strstr(renderer, "Software")) {
+ [m_openGLContext release];
+ m_openGLContext = nil;
+ increasedSamplerLimit = false;
+ continue;
+ }
+ }
+ }
- NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
- if (pixelFormat == nil) {
- goto error;
- }
+ if (m_debug) {
+ GLint major = 0, minor = 0;
+ glGetIntegerv(GL_MAJOR_VERSION, &major);
+ glGetIntegerv(GL_MINOR_VERSION, &minor);
+ fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
+ fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
+ }
- m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
- shareContext:s_sharedOpenGLContext];
- [pixelFormat release];
+# ifdef GHOST_WAIT_FOR_VSYNC
+ {
+ GLint swapInt = 1;
+ /* Wait for vertical-sync, to avoid tearing artifacts. */
+ [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+ }
+# endif
+
+ if (m_metalView) {
+ if (m_defaultFramebuffer == 0) {
+ /* Create a virtual frame-buffer. */
+ [m_openGLContext makeCurrentContext];
+ metalInitFramebuffer();
+ initClearGL();
+ }
+ }
+ else if (m_openGLView) {
+ [m_openGLView setOpenGLContext:m_openGLContext];
+ [m_openGLContext setView:m_openGLView];
+ initClearGL();
+ }
- [m_openGLContext makeCurrentContext];
+ [m_openGLContext flushBuffer];
- if (m_debug) {
- GLint major = 0, minor = 0;
- glGetIntegerv(GL_MAJOR_VERSION, &major);
- glGetIntegerv(GL_MINOR_VERSION, &minor);
- fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
- fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
- }
+ if (s_sharedCount == 0)
+ s_sharedOpenGLContext = m_openGLContext;
-#ifdef GHOST_WAIT_FOR_VSYNC
- {
- GLint swapInt = 1;
- /* Wait for vertical-sync, to avoid tearing artifacts. */
- [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
- }
+ s_sharedCount++;
#endif
-
- initContextGLEW();
-
- if (m_metalView) {
- if (m_defaultFramebuffer == 0) {
- /* Create a virtual frame-buffer. */
- [m_openGLContext makeCurrentContext];
- metalInitFramebuffer();
- initClearGL();
+ }
+ else {
+ /* NOTE(Metal): Metal-only path. */
+ if (m_metalView) {
+ metalInitFramebuffer();
+ }
}
}
- else if (m_openGLView) {
- [m_openGLView setOpenGLContext:m_openGLContext];
- [m_openGLContext setView:m_openGLView];
- initClearGL();
- }
-
- [m_openGLContext flushBuffer];
-
- if (s_sharedCount == 0)
- s_sharedOpenGLContext = m_openGLContext;
-
- s_sharedCount++;
-
- [pool drain];
-
return GHOST_kSuccess;
-
-error:
-
- [pixelFormat release];
-
- [pool drain];
-
- return GHOST_kFailure;
}
GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()
{
+#if WITH_OPENGL
m_openGLContext = nil;
m_openGLView = nil;
+#endif
m_metalView = nil;
return GHOST_kSuccess;
@@ -363,10 +556,14 @@ void GHOST_ContextCGL::metalInit()
fragment float4 fragment_shader(Vertex v [[stage_in]],
texture2d<float> t [[texture(0)]]) {
- return t.sample(s, v.texCoord);
- }
- )msl";
+ /* Final blit should ensure alpha is 1.0. This resolves
+ * rendering artifacts for blitting of final backbuffer. */
+ float4 out_tex = t.sample(s, v.texCoord);
+ out_tex.a = 1.0;
+ return out_tex;
+ }
+ )msl";
MTLCompileOptions *options = [[[MTLCompileOptions alloc] init] autorelease];
options.languageVersion = MTLLanguageVersion1_1;
@@ -383,6 +580,8 @@ void GHOST_ContextCGL::metalInit()
desc.fragmentFunction = [library newFunctionWithName:@"fragment_shader"];
desc.vertexFunction = [library newFunctionWithName:@"vertex_shader"];
+ /* Ensure library is released. */
+ [library autorelease];
[desc.colorAttachments objectAtIndexedSubscript:0].pixelFormat = METAL_FRAMEBUFFERPIXEL_FORMAT;
@@ -393,6 +592,20 @@ void GHOST_ContextCGL::metalInit()
ghost_fatal_error_dialog(
"GHOST_ContextCGL::metalInit: newRenderPipelineStateWithDescriptor:error: failed!");
}
+
+ /* Create a render pipeline to composite things rendered with Metal on top
+ * of the frame-buffer contents. Uses the same vertex and fragment shader
+ * as the blit above, but with alpha blending enabled. */
+ desc.label = @"Metal Overlay";
+ desc.colorAttachments[0].blendingEnabled = YES;
+ desc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
+ desc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
+
+ if (error) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalInit: newRenderPipelineStateWithDescriptor:error: failed (when "
+ "creating the Metal overlay pipeline)!");
+ }
}
}
@@ -404,123 +617,206 @@ void GHOST_ContextCGL::metalFree()
if (m_metalRenderPipeline) {
[m_metalRenderPipeline release];
}
- if (m_defaultFramebufferMetalTexture) {
- [m_defaultFramebufferMetalTexture release];
+
+ for (int i = 0; i < METAL_SWAPCHAIN_SIZE; i++) {
+ if (m_defaultFramebufferMetalTexture[i].texture) {
+ [m_defaultFramebufferMetalTexture[i].texture release];
+ }
}
}
void GHOST_ContextCGL::metalInitFramebuffer()
{
- glGenFramebuffers(1, &m_defaultFramebuffer);
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ glGenFramebuffers(1, &m_defaultFramebuffer);
+#endif
+ }
updateDrawingContext();
- glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer);
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer);
+#endif
+ }
}
void GHOST_ContextCGL::metalUpdateFramebuffer()
{
- assert(m_defaultFramebuffer != 0);
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ assert(m_defaultFramebuffer != 0);
+#endif
+ }
NSRect bounds = [m_metalView bounds];
NSSize backingSize = [m_metalView convertSizeToBacking:bounds.size];
size_t width = (size_t)backingSize.width;
size_t height = (size_t)backingSize.height;
- {
- /* Test if there is anything to update */
- id<MTLTexture> tex = (id<MTLTexture>)m_defaultFramebufferMetalTexture;
- if (tex && tex.width == width && tex.height == height) {
- return;
+#if WITH_OPENGL
+ unsigned int glTex;
+ CVPixelBufferRef cvPixelBuffer = nil;
+ CVOpenGLTextureCacheRef cvGLTexCache = nil;
+ CVOpenGLTextureRef cvGLTex = nil;
+ CVMetalTextureCacheRef cvMetalTexCache = nil;
+ CVMetalTextureRef cvMetalTex = nil;
+#endif
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ /* OPENGL path */
+ {
+ /* Test if there is anything to update */
+ id<MTLTexture> tex = m_defaultFramebufferMetalTexture[current_swapchain_index].texture;
+ if (tex && tex.width == width && tex.height == height) {
+ return;
+ }
}
- }
- activateDrawingContext();
+ activateDrawingContext();
+
+ NSDictionary *cvPixelBufferProps = @{
+ (__bridge NSString *)kCVPixelBufferOpenGLCompatibilityKey : @YES,
+ (__bridge NSString *)kCVPixelBufferMetalCompatibilityKey : @YES,
+ };
+ CVReturn cvret = CVPixelBufferCreate(kCFAllocatorDefault,
+ width,
+ height,
+ METAL_CORE_VIDEO_PIXEL_FORMAT,
+ (__bridge CFDictionaryRef)cvPixelBufferProps,
+ &cvPixelBuffer);
+ if (cvret != kCVReturnSuccess) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalUpdateFramebuffer: CVPixelBufferCreate failed!");
+ }
- NSDictionary *cvPixelBufferProps = @{
- (__bridge NSString *)kCVPixelBufferOpenGLCompatibilityKey : @YES,
- (__bridge NSString *)kCVPixelBufferMetalCompatibilityKey : @YES,
- };
- CVPixelBufferRef cvPixelBuffer = nil;
- CVReturn cvret = CVPixelBufferCreate(kCFAllocatorDefault,
- width,
- height,
- METAL_CORE_VIDEO_PIXEL_FORMAT,
- (__bridge CFDictionaryRef)cvPixelBufferProps,
- &cvPixelBuffer);
- if (cvret != kCVReturnSuccess) {
- ghost_fatal_error_dialog(
- "GHOST_ContextCGL::metalUpdateFramebuffer: CVPixelBufferCreate failed!");
- }
-
- /* Create an OpenGL texture. */
- CVOpenGLTextureCacheRef cvGLTexCache = nil;
- cvret = CVOpenGLTextureCacheCreate(kCFAllocatorDefault,
- nil,
- m_openGLContext.CGLContextObj,
- m_openGLContext.pixelFormat.CGLPixelFormatObj,
- nil,
- &cvGLTexCache);
- if (cvret != kCVReturnSuccess) {
- ghost_fatal_error_dialog(
- "GHOST_ContextCGL::metalUpdateFramebuffer: CVOpenGLTextureCacheCreate failed!");
- }
+ /* Create an OpenGL texture. */
+ cvret = CVOpenGLTextureCacheCreate(kCFAllocatorDefault,
+ nil,
+ m_openGLContext.CGLContextObj,
+ m_openGLContext.pixelFormat.CGLPixelFormatObj,
+ nil,
+ &cvGLTexCache);
+ if (cvret != kCVReturnSuccess) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalUpdateFramebuffer: CVOpenGLTextureCacheCreate failed!");
+ }
- CVOpenGLTextureRef cvGLTex = nil;
- cvret = CVOpenGLTextureCacheCreateTextureFromImage(
- kCFAllocatorDefault, cvGLTexCache, cvPixelBuffer, nil, &cvGLTex);
- if (cvret != kCVReturnSuccess) {
- ghost_fatal_error_dialog(
- "GHOST_ContextCGL::metalUpdateFramebuffer: "
- "CVOpenGLTextureCacheCreateTextureFromImage failed!");
- }
+ cvret = CVOpenGLTextureCacheCreateTextureFromImage(
+ kCFAllocatorDefault, cvGLTexCache, cvPixelBuffer, nil, &cvGLTex);
+ if (cvret != kCVReturnSuccess) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalUpdateFramebuffer: "
+ "CVOpenGLTextureCacheCreateTextureFromImage failed!");
+ }
- unsigned int glTex;
- glTex = CVOpenGLTextureGetName(cvGLTex);
+ glTex = CVOpenGLTextureGetName(cvGLTex);
- /* Create a Metal texture. */
- CVMetalTextureCacheRef cvMetalTexCache = nil;
- cvret = CVMetalTextureCacheCreate(
- kCFAllocatorDefault, nil, m_metalLayer.device, nil, &cvMetalTexCache);
- if (cvret != kCVReturnSuccess) {
- ghost_fatal_error_dialog(
- "GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureCacheCreate failed!");
- }
+ /* Create a Metal texture. */
+ cvret = CVMetalTextureCacheCreate(
+ kCFAllocatorDefault, nil, m_metalLayer.device, nil, &cvMetalTexCache);
+ if (cvret != kCVReturnSuccess) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureCacheCreate failed!");
+ }
- CVMetalTextureRef cvMetalTex = nil;
- cvret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
- cvMetalTexCache,
- cvPixelBuffer,
- nil,
- METAL_FRAMEBUFFERPIXEL_FORMAT,
- width,
- height,
- 0,
- &cvMetalTex);
- if (cvret != kCVReturnSuccess) {
- ghost_fatal_error_dialog(
- "GHOST_ContextCGL::metalUpdateFramebuffer: "
- "CVMetalTextureCacheCreateTextureFromImage failed!");
- }
+ cvret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
+ cvMetalTexCache,
+ cvPixelBuffer,
+ nil,
+ METAL_FRAMEBUFFERPIXEL_FORMAT,
+ width,
+ height,
+ 0,
+ &cvMetalTex);
+ if (cvret != kCVReturnSuccess) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalUpdateFramebuffer: "
+ "CVMetalTextureCacheCreateTextureFromImage failed!");
+ }
+
+ id<MTLTexture> tex = CVMetalTextureGetTexture(cvMetalTex);
- MTLTexture *tex = (MTLTexture *)CVMetalTextureGetTexture(cvMetalTex);
+ if (!tex) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureGetTexture failed!");
+ }
- if (!tex) {
- ghost_fatal_error_dialog(
- "GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureGetTexture failed!");
+ [m_defaultFramebufferMetalTexture[current_swapchain_index].texture release];
+ m_defaultFramebufferMetalTexture[current_swapchain_index].texture = [tex retain];
+#endif
}
+ else {
+ /* NOTE(Metal): Metal API Path. */
+ if (m_defaultFramebufferMetalTexture[current_swapchain_index].texture &&
+ m_defaultFramebufferMetalTexture[current_swapchain_index].texture.width == width &&
+ m_defaultFramebufferMetalTexture[current_swapchain_index].texture.height == height) {
+ return;
+ }
- [m_defaultFramebufferMetalTexture release];
- m_defaultFramebufferMetalTexture = [tex retain];
+ /* Free old texture */
+ [m_defaultFramebufferMetalTexture[current_swapchain_index].texture release];
- glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, glTex, 0);
+ id<MTLDevice> device = m_metalLayer.device;
+ MTLTextureDescriptor *overlayDesc = [MTLTextureDescriptor
+ texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA16Float
+ width:width
+ height:height
+ mipmapped:NO];
+ overlayDesc.storageMode = MTLStorageModePrivate;
+ overlayDesc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
+
+ id<MTLTexture> overlayTex = [device newTextureWithDescriptor:overlayDesc];
+ if (!overlayTex) {
+ ghost_fatal_error_dialog(
+ "GHOST_ContextCGL::metalUpdateFramebuffer: failed to create Metal overlay texture!");
+ }
+ else {
+ overlayTex.label = [NSString
+ stringWithFormat:@"Metal Overlay for GHOST Context %p", this]; //@"";
- [m_metalLayer setDrawableSize:CGSizeMake((CGFloat)width, (CGFloat)height)];
+ // NSLog(@"Created new Metal Overlay (backbuffer) for context %p\n", this);
+ }
+
+ m_defaultFramebufferMetalTexture[current_swapchain_index].texture =
+ overlayTex; //[(MTLTexture *)overlayTex retain];
+
+ /* Clear texture on create */
+ id<MTLCommandBuffer> cmdBuffer = [m_metalCmdQueue commandBuffer];
+ MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
+ {
+ auto attachment = [passDescriptor.colorAttachments objectAtIndexedSubscript:0];
+ attachment.texture = m_defaultFramebufferMetalTexture[current_swapchain_index].texture;
+ attachment.loadAction = MTLLoadActionClear;
+ attachment.clearColor = MTLClearColorMake(0.294, 0.294, 0.294, 1.000);
+ attachment.storeAction = MTLStoreActionStore;
+ }
+ {
+ id<MTLRenderCommandEncoder> enc = [cmdBuffer
+ renderCommandEncoderWithDescriptor:passDescriptor];
+ [enc endEncoding];
+ }
+ [cmdBuffer commit];
+ }
- CVPixelBufferRelease(cvPixelBuffer);
- CVOpenGLTextureCacheRelease(cvGLTexCache);
- CVOpenGLTextureRelease(cvGLTex);
- CFRelease(cvMetalTexCache);
- CFRelease(cvMetalTex);
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, glTex, 0);
+#endif
+ }
+
+ [m_metalLayer setDrawableSize:CGSizeMake((CGFloat)width, (CGFloat)height)];
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ CVPixelBufferRelease(cvPixelBuffer);
+ CVOpenGLTextureCacheRelease(cvGLTexCache);
+ CVOpenGLTextureRelease(cvGLTex);
+ CFRelease(cvMetalTexCache);
+ CFRelease(cvMetalTex);
+#endif
+ }
}
void GHOST_ContextCGL::metalSwapBuffers()
@@ -529,40 +825,88 @@ void GHOST_ContextCGL::metalSwapBuffers()
@autoreleasepool {
/* clang-format on */
updateDrawingContext();
- glFlush();
- assert(m_defaultFramebufferMetalTexture != 0);
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ glFlush();
+ assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil);
+#endif
+ }
id<CAMetalDrawable> drawable = [m_metalLayer nextDrawable];
if (!drawable) {
return;
}
- id<MTLCommandBuffer> cmdBuffer = [m_metalCmdQueue commandBuffer];
-
MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
{
auto attachment = [passDescriptor.colorAttachments objectAtIndexedSubscript:0];
attachment.texture = drawable.texture;
- attachment.loadAction = MTLLoadActionDontCare;
+ attachment.loadAction = MTLLoadActionClear;
+ attachment.clearColor = MTLClearColorMake(1.0, 0.294, 0.294, 1.000);
attachment.storeAction = MTLStoreActionStore;
}
- id<MTLTexture> srcTexture = (id<MTLTexture>)m_defaultFramebufferMetalTexture;
+ if (!m_useMetalForRendering) {
+ id<MTLCommandBuffer> cmdBuffer = [m_metalCmdQueue commandBuffer];
+ {
+ assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil);
+ id<MTLRenderCommandEncoder> enc = [cmdBuffer
+ renderCommandEncoderWithDescriptor:passDescriptor];
+ [enc setRenderPipelineState:(id<MTLRenderPipelineState>)m_metalRenderPipeline];
+ [enc setFragmentTexture:m_defaultFramebufferMetalTexture[current_swapchain_index].texture
+ atIndex:0];
+ [enc drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3];
+ [enc endEncoding];
+ }
+
+ [cmdBuffer presentDrawable:drawable];
+
+ /* Submit command buffer */
+ [cmdBuffer commit];
+ }
+ else {
+ assert(contextPresentCallback);
+ assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil);
+ (*contextPresentCallback)(passDescriptor,
+ (id<MTLRenderPipelineState>)m_metalRenderPipeline,
+ m_defaultFramebufferMetalTexture[current_swapchain_index].texture,
+ drawable);
+ }
+ }
+}
+
+void GHOST_ContextCGL::initClear()
+{
+
+ if (!m_useMetalForRendering) {
+#if WITH_OPENGL
+ glClearColor(0.294, 0.294, 0.294, 0.000);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0.000, 0.000, 0.000, 0.000);
+#endif
+ }
+ else {
+#if WITH_METAL
+ // TODO (mg_gpusw_apple) this path is never taken, this is legacy left from inital integration
+ // of metal and gl, the whole file should be cleaned up and stripped of the legacy path
+ id<MTLCommandBuffer> cmdBuffer = [m_metalCmdQueue commandBuffer];
+ MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
+ {
+ auto attachment = [passDescriptor.colorAttachments objectAtIndexedSubscript:0];
+ attachment.texture = m_defaultFramebufferMetalTexture[current_swapchain_index].texture;
+ attachment.loadAction = MTLLoadActionClear;
+ attachment.clearColor = MTLClearColorMake(0.294, 0.294, 0.294, 1.000);
+ attachment.storeAction = MTLStoreActionStore;
+ }
+ // encoding
{
id<MTLRenderCommandEncoder> enc = [cmdBuffer
renderCommandEncoderWithDescriptor:passDescriptor];
-
- [enc setRenderPipelineState:(id<MTLRenderPipelineState>)m_metalRenderPipeline];
- [enc setFragmentTexture:srcTexture atIndex:0];
- [enc drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3];
-
[enc endEncoding];
}
-
- [cmdBuffer presentDrawable:drawable];
-
[cmdBuffer commit];
+#endif
}
}
diff --git a/intern/ghost/intern/GHOST_ContextD3D.cpp b/intern/ghost/intern/GHOST_ContextD3D.cpp
index ded76daa145..857323941ea 100644
--- a/intern/ghost/intern/GHOST_ContextD3D.cpp
+++ b/intern/ghost/intern/GHOST_ContextD3D.cpp
@@ -10,8 +10,7 @@
#include <iostream>
#include <string>
-#include <GL/glew.h>
-#include <GL/wglew.h>
+#include <epoxy/wgl.h>
#include "GHOST_ContextD3D.h"
#include "GHOST_ContextWGL.h" /* For shared drawing */
@@ -124,8 +123,6 @@ class GHOST_SharedOpenGLResource {
ID3D11RenderTargetView *render_target = nullptr)
: m_device(device), m_device_ctx(device_ctx), m_cur_width(width), m_cur_height(height)
{
- ID3D11Resource *backbuffer_res;
-
if (!render_target) {
D3D11_TEXTURE2D_DESC texDesc{};
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc{};
@@ -158,11 +155,12 @@ class GHOST_SharedOpenGLResource {
m_render_target = render_target;
if (m_render_target) {
+ ID3D11Resource *backbuffer_res = nullptr;
m_render_target->GetResource(&backbuffer_res);
- }
- if (backbuffer_res) {
- backbuffer_res->QueryInterface<ID3D11Texture2D>(&m_render_target_tex);
- backbuffer_res->Release();
+ if (backbuffer_res) {
+ backbuffer_res->QueryInterface<ID3D11Texture2D>(&m_render_target_tex);
+ backbuffer_res->Release();
+ }
}
if (!m_render_target || !m_render_target_tex) {
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
index 8c44dfe0158..ef13133d3a3 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -151,19 +151,6 @@ static bool egl_chk(bool result,
# define EGL_CHK(x) egl_chk(x)
#endif
-static inline bool bindAPI(EGLenum api)
-{
- if (EGLEW_VERSION_1_2) {
- return (EGL_CHK(eglBindAPI(api)) == EGL_TRUE);
- }
-
- return false;
-}
-
-#ifdef WITH_GL_ANGLE
-HMODULE GHOST_ContextEGL::s_d3dcompiler = nullptr;
-#endif
-
EGLContext GHOST_ContextEGL::s_gl_sharedContext = EGL_NO_CONTEXT;
EGLint GHOST_ContextEGL::s_gl_sharedCount = 0;
@@ -256,7 +243,7 @@ GHOST_TSuccess GHOST_ContextEGL::swapBuffers()
GHOST_TSuccess GHOST_ContextEGL::setSwapInterval(int interval)
{
- if (EGLEW_VERSION_1_1) {
+ if (epoxy_egl_version(m_display) >= 11) {
if (EGL_CHK(::eglSwapInterval(m_display, interval))) {
m_swap_interval = interval;
@@ -313,26 +300,13 @@ GHOST_TSuccess GHOST_ContextEGL::releaseDrawingContext()
return GHOST_kFailure;
}
-bool GHOST_ContextEGL::initContextEGLEW()
+inline bool GHOST_ContextEGL::bindAPI(EGLenum api)
{
- /* We have to manually get this function before we can call eglewInit, since
- * it requires a display argument. glewInit() does the same, but we only want
- * to initialize EGLEW here. */
- eglGetDisplay = (PFNEGLGETDISPLAYPROC)eglGetProcAddress("eglGetDisplay");
- if (eglGetDisplay == nullptr) {
- return false;
- }
-
- if (!EGL_CHK((m_display = ::eglGetDisplay(m_nativeDisplay)) != EGL_NO_DISPLAY)) {
- return false;
- }
-
- if (GLEW_CHK(eglewInit(m_display)) != GLEW_OK) {
- fprintf(stderr, "Warning! EGLEW failed to initialize properly.\n");
- return false;
+ if (epoxy_egl_version(m_display) >= 12) {
+ return (EGL_CHK(eglBindAPI(api)) == EGL_TRUE);
}
- return true;
+ return false;
}
static const std::string &api_string(EGLenum api)
@@ -355,34 +329,41 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
}
m_stereoVisual = false; /* It doesn't matter what the Window wants. */
- if (!initContextEGLEW()) {
- return GHOST_kFailure;
- }
-
-#ifdef WITH_GL_ANGLE
- /* `d3dcompiler_XX.dll` needs to be loaded before ANGLE will work. */
- if (s_d3dcompiler == nullptr) {
- s_d3dcompiler = LoadLibrary(D3DCOMPILER);
-
- WIN32_CHK(s_d3dcompiler != nullptr);
-
- if (s_d3dcompiler == nullptr) {
- fprintf(stderr, "LoadLibrary(\"" D3DCOMPILER "\") failed!\n");
- return GHOST_kFailure;
- }
- }
-#endif
-
EGLDisplay prev_display = eglGetCurrentDisplay();
EGLSurface prev_draw = eglGetCurrentSurface(EGL_DRAW);
EGLSurface prev_read = eglGetCurrentSurface(EGL_READ);
EGLContext prev_context = eglGetCurrentContext();
- EGLint egl_major, egl_minor;
+ EGLint egl_major = 0, egl_minor = 0;
- if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor))) {
+ if (!EGL_CHK((m_display = ::eglGetDisplay(m_nativeDisplay)) != EGL_NO_DISPLAY)) {
goto error;
}
+
+ if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor)) ||
+ (egl_major == 0 && egl_minor == 0)) {
+ /* We failed to create a regular render window, retry and see if we can create a headless
+ * render context. */
+ ::eglTerminate(m_display);
+
+ const char *egl_extension_st = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ assert(egl_extension_st != nullptr);
+ assert(strstr(egl_extension_st, "EGL_MESA_platform_surfaceless") != nullptr);
+ if (egl_extension_st == nullptr ||
+ strstr(egl_extension_st, "EGL_MESA_platform_surfaceless") == nullptr) {
+ goto error;
+ }
+
+ m_display = eglGetPlatformDisplayEXT(
+ EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, nullptr);
+
+ if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor))) {
+ goto error;
+ }
+ /* Because the first eglInitialize will print an error to the terminal, print a "success"
+ * message here to let the user know that we successfully recovered from the error. */
+ fprintf(stderr, "\nManaged to successfully fallback to surfaceless EGL rendering!\n\n");
+ }
#ifdef WITH_GHOST_DEBUG
fprintf(stderr, "EGL Version %d.%d\n", egl_major, egl_minor);
#endif
@@ -398,7 +379,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
attrib_list.reserve(20);
- if (m_api == EGL_OPENGL_ES_API && EGLEW_VERSION_1_2) {
+ if (m_api == EGL_OPENGL_ES_API && epoxy_egl_version(m_display) >= 12) {
/* According to the spec it seems that you are required to set EGL_RENDERABLE_TYPE,
* but some implementations (ANGLE) do not seem to care. */
@@ -421,9 +402,11 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
m_contextMinorVersion);
}
- if (!((m_contextMajorVersion == 1) || (m_contextMajorVersion == 2 && EGLEW_VERSION_1_3) ||
- (m_contextMajorVersion == 3 && /*EGLEW_VERSION_1_4 &&*/ EGLEW_KHR_create_context) ||
- (m_contextMajorVersion == 3 && EGLEW_VERSION_1_5))) {
+ if (!((m_contextMajorVersion == 1) ||
+ (m_contextMajorVersion == 2 && epoxy_egl_version(m_display) >= 13) ||
+ (m_contextMajorVersion == 3 &&
+ epoxy_has_egl_extension(m_display, "KHR_create_context")) ||
+ (m_contextMajorVersion == 3 && epoxy_egl_version(m_display) >= 15))) {
fprintf(stderr,
"Warning! May not be able to create a version %d.%d ES context with version %d.%d "
"of EGL\n",
@@ -488,7 +471,8 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
}
attrib_list.clear();
- if (EGLEW_VERSION_1_5 || EGLEW_KHR_create_context) {
+ if (epoxy_egl_version(m_display) >= 15 ||
+ epoxy_has_egl_extension(m_display, "KHR_create_context")) {
if (m_api == EGL_OPENGL_API || m_api == EGL_OPENGL_ES_API) {
if (m_contextMajorVersion != 0) {
attrib_list.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
@@ -530,7 +514,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
}
}
- if (m_api == EGL_OPENGL_API || EGLEW_VERSION_1_5) {
+ if (m_api == EGL_OPENGL_API || epoxy_egl_version(m_display) >= 15) {
if (m_contextResetNotificationStrategy != 0) {
attrib_list.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
attrib_list.push_back(m_contextResetNotificationStrategy);
@@ -598,10 +582,10 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
goto error;
}
- initContextGLEW();
-
- initClearGL();
- ::eglSwapBuffers(m_display, m_surface);
+ if (m_nativeWindow != 0) {
+ initClearGL();
+ ::eglSwapBuffers(m_display, m_surface);
+ }
return GHOST_kSuccess;
diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h
index 3250dc94978..3ccd34f0338 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.h
+++ b/intern/ghost/intern/GHOST_ContextEGL.h
@@ -10,7 +10,8 @@
#include "GHOST_Context.h"
#include "GHOST_System.h"
-#include <GL/eglew.h>
+#include <epoxy/egl.h>
+#include <epoxy/gl.h>
#ifndef GHOST_OPENGL_EGL_CONTEXT_FLAGS
# define GHOST_OPENGL_EGL_CONTEXT_FLAGS 0
@@ -96,7 +97,7 @@ class GHOST_ContextEGL : public GHOST_Context {
EGLContext getContext() const;
private:
- bool initContextEGLEW();
+ bool bindAPI(EGLenum api);
const GHOST_System *const m_system;
@@ -129,8 +130,4 @@ class GHOST_ContextEGL : public GHOST_Context {
static EGLContext s_vg_sharedContext;
static EGLint s_vg_sharedCount;
-
-#ifdef WITH_GL_ANGLE
- static HMODULE s_d3dcompiler;
-#endif
};
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
index b4a076e4598..ed1c874c236 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.cpp
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -95,11 +95,6 @@ GHOST_TSuccess GHOST_ContextGLX::releaseDrawingContext()
return ::glXMakeCurrent(m_display, None, nullptr) ? GHOST_kSuccess : GHOST_kFailure;
}
-void GHOST_ContextGLX::initContextGLXEW()
-{
- initContextGLEW();
-}
-
GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
{
GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
@@ -278,18 +273,11 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
glXMakeCurrent(m_display, m_window, m_context);
- /* Seems that this has to be called after #glXMakeCurrent,
- * which means we cannot use `glX` extensions until after we create a context. */
- initContextGLXEW();
-
if (m_window) {
initClearGL();
::glXSwapBuffers(m_display, m_window);
}
- /* re initialize to get the extensions properly */
- initContextGLXEW();
-
version = glGetString(GL_VERSION);
if (!version || version[0] < '3' || ((version[0] == '3') && (version[2] < '3'))) {
@@ -318,7 +306,7 @@ GHOST_TSuccess GHOST_ContextGLX::releaseNativeHandles()
GHOST_TSuccess GHOST_ContextGLX::setSwapInterval(int interval)
{
- if (!GLXEW_EXT_swap_control) {
+ if (!epoxy_has_glx_extension(m_display, DefaultScreen(m_display), "GLX_EXT_swap_control")) {
::glXSwapIntervalEXT(m_display, m_window, interval);
return GHOST_kSuccess;
}
@@ -327,7 +315,7 @@ GHOST_TSuccess GHOST_ContextGLX::setSwapInterval(int interval)
GHOST_TSuccess GHOST_ContextGLX::getSwapInterval(int &intervalOut)
{
- if (GLXEW_EXT_swap_control) {
+ if (epoxy_has_glx_extension(m_display, DefaultScreen(m_display), "GLX_EXT_swap_control")) {
unsigned int interval = 0;
::glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &interval);
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
index c6184bbd3da..d526e6b1b32 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.h
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -9,7 +9,7 @@
#include "GHOST_Context.h"
-#include <GL/glxew.h>
+#include <epoxy/glx.h>
#ifndef GHOST_OPENGL_GLX_CONTEXT_FLAGS
/* leave as convenience define for the future */
@@ -89,8 +89,6 @@ class GHOST_ContextGLX : public GHOST_Context {
GHOST_TSuccess getSwapInterval(int &intervalOut);
private:
- void initContextGLXEW();
-
Display *m_display;
GLXFBConfig m_fbconfig;
Window m_window;
diff --git a/intern/ghost/intern/GHOST_ContextSDL.cpp b/intern/ghost/intern/GHOST_ContextSDL.cpp
index 5b02fe1c1e6..63b5927895d 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.cpp
+++ b/intern/ghost/intern/GHOST_ContextSDL.cpp
@@ -138,8 +138,6 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
success = (SDL_GL_MakeCurrent(m_window, m_context) < 0) ? GHOST_kFailure : GHOST_kSuccess;
- initContextGLEW();
-
initClearGL();
SDL_GL_SwapWindow(m_window);
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
index 7417358e9ae..d3c190a13b1 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -87,7 +87,7 @@ GHOST_TSuccess GHOST_ContextWGL::swapBuffers()
GHOST_TSuccess GHOST_ContextWGL::setSwapInterval(int interval)
{
- if (WGLEW_EXT_swap_control)
+ if (epoxy_has_wgl_extension(m_hDC, "WGL_EXT_swap_control"))
return WIN32_CHK(::wglSwapIntervalEXT(interval)) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
else
return GHOST_kFailure;
@@ -95,7 +95,7 @@ GHOST_TSuccess GHOST_ContextWGL::setSwapInterval(int interval)
GHOST_TSuccess GHOST_ContextWGL::getSwapInterval(int &intervalOut)
{
- if (WGLEW_EXT_swap_control) {
+ if (epoxy_has_wgl_extension(m_hDC, "WGL_EXT_swap_control")) {
intervalOut = ::wglGetSwapIntervalEXT();
return GHOST_kSuccess;
}
@@ -266,89 +266,6 @@ static HWND clone_window(HWND hWnd, LPVOID lpParam)
return hwndCloned;
}
-void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
-{
- HWND dummyHWND = NULL;
-
- HDC dummyHDC = NULL;
- HGLRC dummyHGLRC = NULL;
-
- HDC prevHDC;
- HGLRC prevHGLRC;
-
- int iPixelFormat;
-
- SetLastError(NO_ERROR);
-
- prevHDC = ::wglGetCurrentDC();
- WIN32_CHK(GetLastError() == NO_ERROR);
-
- prevHGLRC = ::wglGetCurrentContext();
- WIN32_CHK(GetLastError() == NO_ERROR);
-
- iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
-
- if (iPixelFormat == 0)
- goto finalize;
-
- PIXELFORMATDESCRIPTOR chosenPFD;
- if (!WIN32_CHK(
- ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
- goto finalize;
-
- if (m_hWnd) {
- dummyHWND = clone_window(m_hWnd, NULL);
-
- if (dummyHWND == NULL)
- goto finalize;
-
- dummyHDC = GetDC(dummyHWND);
- }
-
- if (!WIN32_CHK(dummyHDC != NULL))
- goto finalize;
-
- if (!WIN32_CHK(::SetPixelFormat(dummyHDC, iPixelFormat, &chosenPFD)))
- goto finalize;
-
- dummyHGLRC = ::wglCreateContext(dummyHDC);
-
- if (!WIN32_CHK(dummyHGLRC != NULL))
- goto finalize;
-
- if (!WIN32_CHK(::wglMakeCurrent(dummyHDC, dummyHGLRC)))
- goto finalize;
-
- if (GLEW_CHK(glewInit()) != GLEW_OK) {
- fprintf(stderr, "Warning! Dummy GLEW/WGLEW failed to initialize properly.\n");
- }
-
- /* The following are not technically WGLEW, but they also require a context to work. */
-
-#ifndef NDEBUG
- free((void *)m_dummyRenderer);
- free((void *)m_dummyVendor);
- free((void *)m_dummyVersion);
-
- m_dummyRenderer = _strdup(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
- m_dummyVendor = _strdup(reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
- m_dummyVersion = _strdup(reinterpret_cast<const char *>(glGetString(GL_VERSION)));
-#endif
-
-finalize:
- WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
-
- if (dummyHGLRC != NULL)
- WIN32_CHK(::wglDeleteContext(dummyHGLRC));
-
- if (dummyHWND != NULL) {
- if (dummyHDC != NULL)
- WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC));
-
- WIN32_CHK(::DestroyWindow(dummyHWND));
- }
-}
-
static void makeAttribList(std::vector<int> &out, bool stereoVisual, bool needAlpha)
{
out.clear();
@@ -385,6 +302,130 @@ static void makeAttribList(std::vector<int> &out, bool stereoVisual, bool needAl
out.push_back(0);
}
+/* Temporary context used to create the actual context. We need ARB pixel format
+ * and context extensions, which are only available within a context. */
+struct DummyContextWGL {
+ HWND dummyHWND = NULL;
+
+ HDC dummyHDC = NULL;
+ HGLRC dummyHGLRC = NULL;
+
+ HDC prevHDC = NULL;
+ HGLRC prevHGLRC = NULL;
+
+ int dummyPixelFormat = 0;
+
+ PIXELFORMATDESCRIPTOR preferredPFD;
+
+ bool has_WGL_ARB_pixel_format = false;
+ bool has_WGL_ARB_create_context = false;
+ bool has_WGL_ARB_create_context_profile = false;
+ bool has_WGL_ARB_create_context_robustness = false;
+
+ DummyContextWGL(HDC hDC, HWND hWnd, bool stereoVisual, bool needAlpha)
+ {
+ preferredPFD = {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size */
+ 1, /* version */
+ (DWORD)(PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW |
+ PFD_DOUBLEBUFFER | /* support double-buffering */
+ (stereoVisual ? PFD_STEREO : 0) | /* support stereo */
+ (
+#ifdef WIN32_COMPOSITING
+ /* Support composition for transparent background. */
+ needAlpha ? PFD_SUPPORT_COMPOSITION :
+#endif
+ 0)),
+ PFD_TYPE_RGBA, /* color type */
+ (BYTE)(needAlpha ? 32 : 24), /* preferred color depth */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* color bits (ignored) */
+ (BYTE)(needAlpha ? 8 : 0), /* alpha buffer */
+ 0, /* alpha shift (ignored) */
+ 0, /* no accumulation buffer */
+ 0,
+ 0,
+ 0,
+ 0, /* accum bits (ignored) */
+ 0, /* depth buffer */
+ 0, /* stencil buffer */
+ 0, /* no auxiliary buffers */
+ PFD_MAIN_PLANE, /* main layer */
+ 0, /* reserved */
+ 0,
+ 0,
+ 0 /* layer, visible, and damage masks (ignored) */
+ };
+
+ SetLastError(NO_ERROR);
+
+ prevHDC = ::wglGetCurrentDC();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ prevHGLRC = ::wglGetCurrentContext();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ dummyPixelFormat = choose_pixel_format_legacy(hDC, preferredPFD);
+
+ if (dummyPixelFormat == 0)
+ return;
+
+ PIXELFORMATDESCRIPTOR chosenPFD;
+ if (!WIN32_CHK(::DescribePixelFormat(
+ hDC, dummyPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
+ return;
+
+ if (hWnd) {
+ dummyHWND = clone_window(hWnd, NULL);
+
+ if (dummyHWND == NULL)
+ return;
+
+ dummyHDC = GetDC(dummyHWND);
+ }
+
+ if (!WIN32_CHK(dummyHDC != NULL))
+ return;
+
+ if (!WIN32_CHK(::SetPixelFormat(dummyHDC, dummyPixelFormat, &chosenPFD)))
+ return;
+
+ dummyHGLRC = ::wglCreateContext(dummyHDC);
+
+ if (!WIN32_CHK(dummyHGLRC != NULL))
+ return;
+
+ if (!WIN32_CHK(::wglMakeCurrent(dummyHDC, dummyHGLRC)))
+ return;
+
+ has_WGL_ARB_pixel_format = epoxy_has_wgl_extension(hDC, "WGL_ARB_pixel_format");
+ has_WGL_ARB_create_context = epoxy_has_wgl_extension(hDC, "WGL_ARB_create_context");
+ has_WGL_ARB_create_context_profile = epoxy_has_wgl_extension(hDC,
+ "WGL_ARB_create_context_profile");
+ has_WGL_ARB_create_context_robustness = epoxy_has_wgl_extension(
+ hDC, "WGL_ARB_create_context_robustness");
+ }
+
+ ~DummyContextWGL()
+ {
+ WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
+
+ if (dummyHGLRC != NULL)
+ WIN32_CHK(::wglDeleteContext(dummyHGLRC));
+
+ if (dummyHWND != NULL) {
+ if (dummyHDC != NULL)
+ WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC));
+
+ WIN32_CHK(::DestroyWindow(dummyHWND));
+ }
+ }
+};
+
int GHOST_ContextWGL::_choose_pixel_format_arb_1(bool stereoVisual, bool needAlpha)
{
std::vector<int> iAttributes;
@@ -454,58 +495,6 @@ int GHOST_ContextWGL::choose_pixel_format_arb(bool stereoVisual, bool needAlpha)
return iPixelFormat;
}
-int GHOST_ContextWGL::choose_pixel_format(bool stereoVisual, bool needAlpha)
-{
- PIXELFORMATDESCRIPTOR preferredPFD = {
- sizeof(PIXELFORMATDESCRIPTOR), /* size */
- 1, /* version */
- (DWORD)(PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW |
- PFD_DOUBLEBUFFER | /* support double-buffering */
- (stereoVisual ? PFD_STEREO : 0) | /* support stereo */
- (
-#ifdef WIN32_COMPOSITING
- /* Support composition for transparent background. */
- needAlpha ? PFD_SUPPORT_COMPOSITION :
-#endif
- 0)),
- PFD_TYPE_RGBA, /* color type */
- (BYTE)(needAlpha ? 32 : 24), /* preferred color depth */
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, /* color bits (ignored) */
- (BYTE)(needAlpha ? 8 : 0), /* alpha buffer */
- 0, /* alpha shift (ignored) */
- 0, /* no accumulation buffer */
- 0,
- 0,
- 0,
- 0, /* accum bits (ignored) */
- 0, /* depth buffer */
- 0, /* stencil buffer */
- 0, /* no auxiliary buffers */
- PFD_MAIN_PLANE, /* main layer */
- 0, /* reserved */
- 0,
- 0,
- 0 /* layer, visible, and damage masks (ignored) */
- };
-
- initContextWGLEW(preferredPFD);
-
- int iPixelFormat = 0;
-
- if (WGLEW_ARB_pixel_format)
- iPixelFormat = choose_pixel_format_arb(stereoVisual, needAlpha);
-
- if (iPixelFormat == 0)
- iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
-
- return iPixelFormat;
-}
-
#ifndef NDEBUG
static void reportContextString(const char *name, const char *dummy, const char *context)
{
@@ -526,107 +515,96 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
HDC prevHDC = ::wglGetCurrentDC();
WIN32_CHK(GetLastError() == NO_ERROR);
- if (!WGLEW_ARB_create_context || ::GetPixelFormat(m_hDC) == 0) {
+ {
const bool needAlpha = m_alphaBackground;
- int iPixelFormat;
- int lastPFD;
-
- PIXELFORMATDESCRIPTOR chosenPFD;
-
- iPixelFormat = choose_pixel_format(m_stereoVisual, needAlpha);
+ DummyContextWGL dummy(m_hDC, m_hWnd, m_stereoVisual, needAlpha);
- if (iPixelFormat == 0) {
- goto error;
- }
+ if (!dummy.has_WGL_ARB_create_context || ::GetPixelFormat(m_hDC) == 0) {
+ int iPixelFormat = 0;
- lastPFD = ::DescribePixelFormat(
- m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
-
- if (!WIN32_CHK(lastPFD != 0)) {
- goto error;
- }
+ if (dummy.has_WGL_ARB_pixel_format)
+ iPixelFormat = choose_pixel_format_arb(m_stereoVisual, needAlpha);
- if (needAlpha && chosenPFD.cAlphaBits == 0)
- fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
+ if (iPixelFormat == 0)
+ iPixelFormat = choose_pixel_format_legacy(m_hDC, dummy.preferredPFD);
- if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
- goto error;
- }
- }
+ if (iPixelFormat == 0) {
+ goto error;
+ }
- if (WGLEW_ARB_create_context) {
- int profileBitCore = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
- int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ PIXELFORMATDESCRIPTOR chosenPFD;
+ int lastPFD = ::DescribePixelFormat(
+ m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
-#ifdef WITH_GLEW_ES
- int profileBitES = m_contextProfileMask & WGL_CONTEXT_ES_PROFILE_BIT_EXT;
-#endif
+ if (!WIN32_CHK(lastPFD != 0)) {
+ goto error;
+ }
- if (!WGLEW_ARB_create_context_profile && profileBitCore)
- fprintf(stderr, "Warning! OpenGL core profile not available.\n");
+ if (needAlpha && chosenPFD.cAlphaBits == 0)
+ fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
- if (!WGLEW_ARB_create_context_profile && profileBitCompat)
- fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
+ if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
+ goto error;
+ }
+ }
-#ifdef WITH_GLEW_ES
- if (!WGLEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
- fprintf(stderr, "Warning! OpenGL ES profile not available.\n");
+ if (dummy.has_WGL_ARB_create_context) {
+ int profileBitCore = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
- if (!WGLEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
- fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
-#endif
+ if (!dummy.has_WGL_ARB_create_context_profile && profileBitCore)
+ fprintf(stderr, "Warning! OpenGL core profile not available.\n");
- int profileMask = 0;
+ if (!dummy.has_WGL_ARB_create_context_profile && profileBitCompat)
+ fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
- if (WGLEW_ARB_create_context_profile && profileBitCore)
- profileMask |= profileBitCore;
+ int profileMask = 0;
- if (WGLEW_ARB_create_context_profile && profileBitCompat)
- profileMask |= profileBitCompat;
+ if (dummy.has_WGL_ARB_create_context_profile && profileBitCore)
+ profileMask |= profileBitCore;
-#ifdef WITH_GLEW_ES
- if (WGLEW_EXT_create_context_es_profile && profileBitES)
- profileMask |= profileBitES;
-#endif
+ if (dummy.has_WGL_ARB_create_context_profile && profileBitCompat)
+ profileMask |= profileBitCompat;
- if (profileMask != m_contextProfileMask)
- fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
+ if (profileMask != m_contextProfileMask)
+ fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
- std::vector<int> iAttributes;
+ std::vector<int> iAttributes;
- if (profileMask) {
- iAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
- iAttributes.push_back(profileMask);
- }
-
- if (m_contextMajorVersion != 0) {
- iAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
- iAttributes.push_back(m_contextMajorVersion);
- }
+ if (profileMask) {
+ iAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
+ iAttributes.push_back(profileMask);
+ }
- if (m_contextMinorVersion != 0) {
- iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
- iAttributes.push_back(m_contextMinorVersion);
- }
+ if (m_contextMajorVersion != 0) {
+ iAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+ iAttributes.push_back(m_contextMajorVersion);
+ }
- if (m_contextFlags != 0) {
- iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
- iAttributes.push_back(m_contextFlags);
- }
+ if (m_contextMinorVersion != 0) {
+ iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ iAttributes.push_back(m_contextMinorVersion);
+ }
- if (m_contextResetNotificationStrategy != 0) {
- if (WGLEW_ARB_create_context_robustness) {
- iAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
- iAttributes.push_back(m_contextResetNotificationStrategy);
+ if (m_contextFlags != 0) {
+ iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
+ iAttributes.push_back(m_contextFlags);
}
- else {
- fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
+
+ if (m_contextResetNotificationStrategy != 0) {
+ if (dummy.has_WGL_ARB_create_context_robustness) {
+ iAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ iAttributes.push_back(m_contextResetNotificationStrategy);
+ }
+ else {
+ fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
+ }
}
- }
- iAttributes.push_back(0);
+ iAttributes.push_back(0);
- m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
+ m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
+ }
}
/* Silence warnings interpreted as errors by users when trying to get
@@ -651,8 +629,6 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
goto error;
}
- initContextGLEW();
-
if (is_crappy_intel_card()) {
/* Some Intel cards with context 4.1 or 4.2
* don't have the point sprite enabled by default.
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
index ca0bf70b128..c02c0616422 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.h
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -11,7 +11,7 @@
#include "GHOST_Context.h"
-#include <GL/wglew.h>
+#include <epoxy/wgl.h>
#ifndef GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
# define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY 0
@@ -86,12 +86,9 @@ class GHOST_ContextWGL : public GHOST_Context {
GHOST_TSuccess getSwapInterval(int &intervalOut);
private:
- int choose_pixel_format(bool stereoVisual, bool needAlpha);
int choose_pixel_format_arb(bool stereoVisual, bool needAlpha);
int _choose_pixel_format_arb_1(bool stereoVisual, bool needAlpha);
- void initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD);
-
HWND m_hWnd;
HDC m_hDC;
diff --git a/intern/ghost/intern/GHOST_DisplayManagerNULL.h b/intern/ghost/intern/GHOST_DisplayManagerNULL.h
index ba72dcbe8dd..dbef4fafd8f 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerNULL.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerNULL.h
@@ -8,38 +8,38 @@
#pragma once
#include "GHOST_DisplayManager.h"
-#include "GHOST_SystemNULL.h"
+#include "GHOST_SystemHeadless.h"
-class GHOST_SystemNULL;
+class GHOST_SystemHeadless;
class GHOST_DisplayManagerNULL : public GHOST_DisplayManager {
public:
- GHOST_DisplayManagerNULL(GHOST_SystemNULL *system) : GHOST_DisplayManager(), m_system(system)
+ GHOST_DisplayManagerNULL() : GHOST_DisplayManager()
{ /* nop */
}
- GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const
+ GHOST_TSuccess getNumDisplays(uint8_t & /*numDisplays*/) const override
{
return GHOST_kFailure;
}
- GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const
+ GHOST_TSuccess getNumDisplaySettings(uint8_t /*display*/,
+ int32_t & /*numSettings*/) const override
{
return GHOST_kFailure;
}
- GHOST_TSuccess getDisplaySetting(uint8_t display,
- int32_t index,
- GHOST_DisplaySetting &setting) const
+ GHOST_TSuccess getDisplaySetting(uint8_t /*display*/,
+ int32_t /*index*/,
+ GHOST_DisplaySetting & /*setting*/) const override
{
return GHOST_kFailure;
}
- GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const
+ GHOST_TSuccess getCurrentDisplaySetting(uint8_t display,
+ GHOST_DisplaySetting &setting) const override
{
return getDisplaySetting(display, int32_t(0), setting);
}
- GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting)
+ GHOST_TSuccess setCurrentDisplaySetting(uint8_t /*display*/,
+ const GHOST_DisplaySetting & /*setting*/) override
{
return GHOST_kSuccess;
}
-
- private:
- GHOST_SystemNULL *m_system;
};
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
index 3d8920d7c52..ee79792bb7e 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
@@ -11,8 +11,9 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-// We do not support multiple monitors at the moment
+/* We do not support multiple monitors at the moment. */
#define COMPILE_MULTIMON_STUBS
+
#include <multimon.h>
GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void)
@@ -31,16 +32,15 @@ static BOOL get_dd(DWORD d, DISPLAY_DEVICE *dd)
return ::EnumDisplayDevices(NULL, d, dd, 0);
}
-/*
- * When you call EnumDisplaySettings with iModeNum set to zero, the operating system
- * initializes and caches information about the display device. When you call
- * EnumDisplaySettings with iModeNum set to a non-zero value, the function returns
- * the information that was cached the last time the function was called with iModeNum
- * set to zero.
- */
GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(uint8_t display,
int32_t &numSettings) const
{
+ /* When you call #EnumDisplaySettings with #iModeNum set to zero, the operating system
+ * initializes and caches information about the display device.
+ * When you call #EnumDisplaySettings with #iModeNum set to a non-zero value,
+ * the function returns the information that was cached the last time the
+ * function was called with #iModeNum set to zero. */
+
DISPLAY_DEVICE display_device;
if (!get_dd(display, &display_device))
return GHOST_kFailure;
@@ -70,21 +70,20 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(uint8_t display,
dm.dmPelsHeight,
dm.dmBitsPerPel,
dm.dmDisplayFrequency);
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
setting.xPixels = dm.dmPelsWidth;
setting.yPixels = dm.dmPelsHeight;
setting.bpp = dm.dmBitsPerPel;
- /* When you call the EnumDisplaySettings function, the dmDisplayFrequency member
+ /* When you call the #EnumDisplaySettings function, the #dmDisplayFrequency member
* may return with the value 0 or 1. These values represent the display hardware's
* default refresh rate. This default rate is typically set by switches on a display
* card or computer motherboard, or by a configuration program that does not use
- * Win32 display functions such as ChangeDisplaySettings.
- */
- /* First, we tried to explicitly set the frequency to 60 if EnumDisplaySettings
+ * Win32 display functions such as #ChangeDisplaySettings. */
+
+ /* First, we tried to explicitly set the frequency to 60 if #EnumDisplaySettings
* returned 0 or 1 but this doesn't work since later on an exact match will
* be searched. And this will never happen if we change it to 60. Now we rely
- * on the default h/w setting.
- */
+ * on the default hardware setting. */
setting.frequency = dm.dmDisplayFrequency;
success = GHOST_kSuccess;
}
@@ -117,22 +116,23 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
break;
}
}
- /*
- * dm.dmBitsPerPel = match.bpp;
- * dm.dmPelsWidth = match.xPixels;
- * dm.dmPelsHeight = match.yPixels;
- * dm.dmDisplayFrequency = match.frequency;
- * dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
- * dm.dmSize = sizeof(DEVMODE);
- * dm.dmDriverExtra = 0;
- */
+#if 0
+ dm.dmBitsPerPel = match.bpp;
+ dm.dmPelsWidth = match.xPixels;
+ dm.dmPelsHeight = match.yPixels;
+ dm.dmDisplayFrequency = match.frequency;
+ dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
+ dm.dmSize = sizeof(DEVMODE);
+ dm.dmDriverExtra = 0;
+#endif
+
#ifdef WITH_GHOST_DEBUG
printf("display change: Requested settings:\n");
printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel);
printf(" dmPelsWidth=%d\n", dm.dmPelsWidth);
printf(" dmPelsHeight=%d\n", dm.dmPelsHeight);
printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency);
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
#ifdef WITH_GHOST_DEBUG
@@ -166,6 +166,6 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
printf("display change: Return value invalid\n");
break;
}
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
return status == DISP_CHANGE_SUCCESSFUL ? GHOST_kSuccess : GHOST_kFailure;
}
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
index a82a31e7386..2831f2ee8ad 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -13,9 +13,9 @@
#include "utfconv.h"
#ifdef WITH_GHOST_DEBUG
-// utility
+/* utility */
void printLastError(void);
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system)
: m_window(window), m_system(system)
@@ -32,22 +32,21 @@ GHOST_DropTargetWin32::~GHOST_DropTargetWin32()
/*
* IUnknown::QueryInterface
*/
-HRESULT __stdcall GHOST_DropTargetWin32::QueryInterface(REFIID riid, void **ppvObj)
+HRESULT __stdcall GHOST_DropTargetWin32::QueryInterface(REFIID riid, void **ppv_obj)
{
- if (!ppvObj)
+ if (!ppv_obj) {
return E_INVALIDARG;
- *ppvObj = NULL;
+ }
+ *ppv_obj = NULL;
if (riid == IID_IUnknown || riid == IID_IDropTarget) {
AddRef();
- *ppvObj = (void *)this;
+ *ppv_obj = (void *)this;
return S_OK;
}
- else {
- *ppvObj = NULL;
- return E_NOINTERFACE;
- }
+ *ppv_obj = NULL;
+ return E_NOINTERFACE;
}
/*
@@ -78,16 +77,16 @@ ULONG __stdcall GHOST_DropTargetWin32::Release(void)
/*
* Implementation of IDropTarget::DragEnter
*/
-HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject *pDataObject,
- DWORD grfKeyState,
+HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject *p_data_object,
+ DWORD grf_key_state,
POINTL pt,
- DWORD *pdwEffect)
+ DWORD *pdw_effect)
{
- // we accept all drop by default
+ /* We accept all drop by default. */
m_window->setAcceptDragOperation(true);
- *pdwEffect = DROPEFFECT_NONE;
+ *pdw_effect = DROPEFFECT_NONE;
- m_draggedObjectType = getGhostType(pDataObject);
+ m_draggedObjectType = getGhostType(p_data_object);
m_system->pushDragDropEvent(
GHOST_kEventDraggingEntered, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
return S_OK;
@@ -96,15 +95,17 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject *pDataObject,
/*
* Implementation of IDropTarget::DragOver
*/
-HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
+HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD grf_key_state,
+ POINTL pt,
+ DWORD *pdw_effect)
{
if (m_window->canAcceptDragOperation()) {
- *pdwEffect = allowedDropEffect(*pdwEffect);
+ *pdw_effect = allowedDropEffect(*pdw_effect);
}
else {
- *pdwEffect = DROPEFFECT_NONE;
- // XXX Uncomment to test drop. Drop will not be called if pdwEffect == DROPEFFECT_NONE.
- // *pdwEffect = DROPEFFECT_COPY;
+ *pdw_effect = DROPEFFECT_NONE;
+ /* XXX Uncomment to test drop. Drop will not be called if `pdw_effect == DROPEFFECT_NONE`. */
+ // *pdw_effect = DROPEFFECT_COPY;
}
m_system->pushDragDropEvent(
GHOST_kEventDraggingUpdated, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
@@ -123,25 +124,25 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragLeave(void)
}
/* Implementation of IDropTarget::Drop
- * This function will not be called if pdwEffect is set to DROPEFFECT_NONE in
+ * This function will not be called if pdw_effect is set to DROPEFFECT_NONE in
* the implementation of IDropTarget::DragOver
*/
-HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject *pDataObject,
- DWORD grfKeyState,
+HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject *p_data_object,
+ DWORD grf_key_state,
POINTL pt,
- DWORD *pdwEffect)
+ DWORD *pdw_effect)
{
- void *data = getGhostData(pDataObject);
+ void *data = getGhostData(p_data_object);
if (m_window->canAcceptDragOperation()) {
- *pdwEffect = allowedDropEffect(*pdwEffect);
+ *pdw_effect = allowedDropEffect(*pdw_effect);
}
else {
- *pdwEffect = DROPEFFECT_NONE;
+ *pdw_effect = DROPEFFECT_NONE;
}
- if (data)
+ if (data) {
m_system->pushDragDropEvent(
GHOST_kEventDraggingDropDone, m_draggedObjectType, m_window, pt.x, pt.y, data);
-
+ }
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
return S_OK;
}
@@ -150,150 +151,132 @@ HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject *pDataObject,
* Helpers
*/
-DWORD GHOST_DropTargetWin32::allowedDropEffect(DWORD dwAllowed)
+DWORD GHOST_DropTargetWin32::allowedDropEffect(DWORD dw_allowed)
{
- DWORD dwEffect = DROPEFFECT_NONE;
- if (dwAllowed & DROPEFFECT_COPY)
- dwEffect = DROPEFFECT_COPY;
-
- return dwEffect;
+ DWORD dw_effect = DROPEFFECT_NONE;
+ if (dw_allowed & DROPEFFECT_COPY) {
+ dw_effect = DROPEFFECT_COPY;
+ }
+ return dw_effect;
}
-GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject *pDataObject)
+GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject *p_data_object)
{
/* Text
* NOTE: Unicode text is available as CF_TEXT too, the system can do the
* conversion, but we do the conversion our self with #WC_NO_BEST_FIT_CHARS.
*/
FORMATETC fmtetc = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
- if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
+ if (p_data_object->QueryGetData(&fmtetc) == S_OK) {
return GHOST_kDragnDropTypeString;
}
- // Filesnames
+ /* Files-names. */
fmtetc.cfFormat = CF_HDROP;
- if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
+ if (p_data_object->QueryGetData(&fmtetc) == S_OK) {
return GHOST_kDragnDropTypeFilenames;
}
return GHOST_kDragnDropTypeUnknown;
}
-void *GHOST_DropTargetWin32::getGhostData(IDataObject *pDataObject)
+void *GHOST_DropTargetWin32::getGhostData(IDataObject *p_data_object)
{
- GHOST_TDragnDropTypes type = getGhostType(pDataObject);
+ GHOST_TDragnDropTypes type = getGhostType(p_data_object);
switch (type) {
case GHOST_kDragnDropTypeFilenames:
- return getDropDataAsFilenames(pDataObject);
- break;
+ return getDropDataAsFilenames(p_data_object);
case GHOST_kDragnDropTypeString:
- return getDropDataAsString(pDataObject);
- break;
+ return getDropDataAsString(p_data_object);
case GHOST_kDragnDropTypeBitmap:
- // return getDropDataAsBitmap(pDataObject);
+ // return getDropDataAsBitmap(p_data_object);
break;
default:
#ifdef WITH_GHOST_DEBUG
::printf("\nGHOST_kDragnDropTypeUnknown");
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
return NULL;
- break;
}
return NULL;
}
-void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *pDataObject)
+void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *p_data_object)
{
- UINT totfiles, nvalid = 0;
- WCHAR fpath[MAX_PATH];
- char *temp_path;
- GHOST_TStringArray *strArray = NULL;
+ GHOST_TStringArray *str_array = NULL;
FORMATETC fmtetc = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
- STGMEDIUM stgmed;
- HDROP hdrop;
-
- // Check if dataobject supplies the format we want.
- // Double checking here, first in getGhostType.
- if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
- if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK) {
- hdrop = (HDROP)::GlobalLock(stgmed.hGlobal);
-
- totfiles = ::DragQueryFileW(hdrop, -1, NULL, 0);
- if (!totfiles) {
- ::GlobalUnlock(stgmed.hGlobal);
- return NULL;
- }
- strArray = (GHOST_TStringArray *)::malloc(sizeof(GHOST_TStringArray));
- strArray->count = 0;
- strArray->strings = (uint8_t **)::malloc(totfiles * sizeof(uint8_t *));
-
- for (UINT nfile = 0; nfile < totfiles; nfile++) {
- if (::DragQueryFileW(hdrop, nfile, fpath, MAX_PATH) > 0) {
- if (!(temp_path = alloc_utf_8_from_16(fpath, 0))) {
- continue;
+ /* Check if data-object supplies the format we want.
+ * Double checking here, first in #getGhostType. */
+ if (p_data_object->QueryGetData(&fmtetc) == S_OK) {
+ STGMEDIUM stgmed;
+ if (p_data_object->GetData(&fmtetc, &stgmed) == S_OK) {
+ const HDROP hdrop = (HDROP)::GlobalLock(stgmed.hGlobal);
+
+ const UINT totfiles = ::DragQueryFileW(hdrop, -1, NULL, 0);
+ if (totfiles) {
+ str_array = (GHOST_TStringArray *)::malloc(sizeof(GHOST_TStringArray));
+ str_array->count = 0;
+ str_array->strings = (uint8_t **)::malloc(totfiles * sizeof(uint8_t *));
+
+ for (UINT nfile = 0; nfile < totfiles; nfile++) {
+ WCHAR fpath[MAX_PATH];
+ if (::DragQueryFileW(hdrop, nfile, fpath, MAX_PATH) > 0) {
+ char *temp_path;
+ if (!(temp_path = alloc_utf_8_from_16(fpath, 0))) {
+ /* Just ignore paths that could not be converted verbatim. */
+ continue;
+ }
+ str_array->strings[str_array->count++] = (uint8_t *)temp_path;
}
- // Just ignore paths that could not be converted verbatim.
-
- strArray->strings[nvalid] = (uint8_t *)temp_path;
- strArray->count = nvalid + 1;
- nvalid++;
}
}
- // Free up memory.
+ /* Free up memory. */
::GlobalUnlock(stgmed.hGlobal);
::ReleaseStgMedium(&stgmed);
-
- return strArray;
}
}
- return NULL;
+ return str_array;
}
-void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject)
+void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *p_data_object)
{
char *tmp_string;
FORMATETC fmtetc = {CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM stgmed;
- // Try unicode first.
- // Check if dataobject supplies the format we want.
- if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
- if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK) {
+ /* Try unicode first.
+ * Check if data-object supplies the format we want. */
+ if (p_data_object->QueryGetData(&fmtetc) == S_OK) {
+ if (p_data_object->GetData(&fmtetc, &stgmed) == S_OK) {
LPCWSTR wstr = (LPCWSTR)::GlobalLock(stgmed.hGlobal);
- if (!(tmp_string = alloc_utf_8_from_16((wchar_t *)wstr, 0))) {
- ::GlobalUnlock(stgmed.hGlobal);
- return NULL;
- }
- // Free memory
+
+ tmp_string = alloc_utf_8_from_16((wchar_t *)wstr, 0);
+
+ /* Free memory. */
::GlobalUnlock(stgmed.hGlobal);
::ReleaseStgMedium(&stgmed);
+
#ifdef WITH_GHOST_DEBUG
- ::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n",
- tmp_string);
-#endif // WITH_GHOST_DEBUG
+ if (tmp_string) {
+ ::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n",
+ tmp_string);
+ }
+#endif /* WITH_GHOST_DEBUG */
return tmp_string;
}
}
fmtetc.cfFormat = CF_TEXT;
- if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
- if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK) {
+ if (p_data_object->QueryGetData(&fmtetc) == S_OK) {
+ if (p_data_object->GetData(&fmtetc, &stgmed) == S_OK) {
char *str = (char *)::GlobalLock(stgmed.hGlobal);
tmp_string = (char *)::malloc(::strlen(str) + 1);
- if (!tmp_string) {
- ::GlobalUnlock(stgmed.hGlobal);
- return NULL;
- }
-
- if (!::strcpy(tmp_string, str)) {
- ::free(tmp_string);
- ::GlobalUnlock(stgmed.hGlobal);
- return NULL;
+ if (tmp_string) {
+ ::strcpy(tmp_string, str);
}
- // Free memory
+ /* Free memory. */
::GlobalUnlock(stgmed.hGlobal);
::ReleaseStgMedium(&stgmed);
@@ -307,13 +290,13 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject)
int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
{
int size;
- out = NULL; // caller should free if != NULL
+ out = NULL; /* caller should free if != NULL */
- // Get the required size.
- size = ::WideCharToMultiByte(CP_ACP, // System Default Codepage
- 0x00000400, // WC_NO_BEST_FIT_CHARS
+ /* Get the required size. */
+ size = ::WideCharToMultiByte(CP_ACP, /* System Default Codepage */
+ 0x00000400, /* WC_NO_BEST_FIT_CHARS */
in,
- -1, //-1 null terminated, makes output null terminated too.
+ -1, /* -1 null terminated, makes output null terminated too. */
NULL,
0,
NULL,
@@ -322,7 +305,7 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
if (!size) {
#ifdef WITH_GHOST_DEBUG
::printLastError();
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
return 0;
}
@@ -337,7 +320,7 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
if (!size) {
#ifdef WITH_GHOST_DEBUG
::printLastError();
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
::free(out);
out = NULL;
}
@@ -362,4 +345,4 @@ void printLastError(void)
LocalFree(s);
}
}
-#endif // WITH_GHOST_DEBUG
+#endif /* WITH_GHOST_DEBUG */
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h
index 2f628e81b56..03e5492fcb1 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.h
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.h
@@ -21,7 +21,7 @@ class GHOST_DropTargetWin32 : public IDropTarget {
* inherited, directly or indirectly, from IUnknown. Therefore, the three
* methods in IUnknown are the first entries in the VTable for every interface.
*/
- HRESULT __stdcall QueryInterface(REFIID riid, void **ppvObj);
+ HRESULT __stdcall QueryInterface(REFIID riid, void **ppv_obj);
ULONG __stdcall AddRef(void);
ULONG __stdcall Release(void);
@@ -44,13 +44,16 @@ class GHOST_DropTargetWin32 : public IDropTarget {
* RevokeDragDrop functions.
*/
- HRESULT __stdcall DragEnter(IDataObject *pDataObject,
- DWORD grfKeyState,
+ HRESULT __stdcall DragEnter(IDataObject *p_data_object,
+ DWORD grf_key_state,
POINTL pt,
- DWORD *pdwEffect);
- HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
+ DWORD *pdw_effect);
+ HRESULT __stdcall DragOver(DWORD grf_key_state, POINTL pt, DWORD *pdw_effect);
HRESULT __stdcall DragLeave(void);
- HRESULT __stdcall Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
+ HRESULT __stdcall Drop(IDataObject *p_data_object,
+ DWORD grf_key_state,
+ POINTL pt,
+ DWORD *pdw_effect);
/**
* Constructor
@@ -76,36 +79,36 @@ class GHOST_DropTargetWin32 : public IDropTarget {
* \param dwAllowed: Drop sources allowed drop effect.
* \return The allowed drop effect.
*/
- DWORD allowedDropEffect(DWORD dwAllowed);
+ DWORD allowedDropEffect(DWORD dw_allowed);
/**
* Query DataObject for the data types it supports.
- * \param pDataObject: Pointer to the DataObject.
+ * \param p_data_object: Pointer to the DataObject.
* \return GHOST data type.
*/
- GHOST_TDragnDropTypes getGhostType(IDataObject *pDataObject);
+ GHOST_TDragnDropTypes getGhostType(IDataObject *p_data_object);
/**
* Get data to pass in event.
* It checks the type and calls specific functions for each type.
- * \param pDataObject: Pointer to the DataObject.
+ * \param p_data_object: Pointer to the DataObject.
* \return Pointer to data.
*/
- void *getGhostData(IDataObject *pDataObject);
+ void *getGhostData(IDataObject *p_data_object);
/**
* Allocate data as file array to pass in event.
- * \param pDataObject: Pointer to the DataObject.
+ * \param p_data_object: Pointer to the DataObject.
* \return Pointer to data.
*/
- void *getDropDataAsFilenames(IDataObject *pDataObject);
+ void *getDropDataAsFilenames(IDataObject *p_data_object);
/**
* Allocate data as string to pass in event.
- * \param pDataObject: Pointer to the DataObject.
+ * \param p_data_object: Pointer to the DataObject.
* \return Pointer to data.
*/
- void *getDropDataAsString(IDataObject *pDataObject);
+ void *getDropDataAsString(IDataObject *p_data_object);
/**
* Convert Unicode to ANSI, replacing uncomfortable chars with '?'.
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp
index 4da3c7c996d..1403639a36f 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp
@@ -114,7 +114,7 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr
/* Count total number of file paths in buffer. */
for (int i = 0; i <= dropBufferSize; i++) {
- if (dropBuffer[i] == 0 || dropBuffer[i] == '\n' || dropBuffer[i] == '\r') {
+ if (ELEM(dropBuffer[i], 0, '\n', '\r')) {
if (curLength) {
totPaths++;
curLength = 0;
@@ -131,7 +131,7 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr
curLength = 0;
for (int i = 0; i <= dropBufferSize; i++) {
- if (dropBuffer[i] == 0 || dropBuffer[i] == '\n' || dropBuffer[i] == '\r') {
+ if (ELEM(dropBuffer[i], 0, '\n', '\r')) {
if (curLength) {
char *curPath = (char *)malloc(curLength + 1);
char *decodedPath;
@@ -182,7 +182,7 @@ void *GHOST_DropTargetX11::getGhostData(Atom dropType,
data = decodedPath;
}
}
- else if (dropType == dndTypePlainText || dropType == dndTypeOctetStream) {
+ else if (ELEM(dropType, dndTypePlainText, dndTypeOctetStream)) {
m_draggedObjectType = GHOST_kDragnDropTypeString;
data = tmpBuffer;
needsFree = false;
diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp
index 2620bcc075d..7c20cd701b0 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.cpp
+++ b/intern/ghost/intern/GHOST_EventPrinter.cpp
@@ -220,8 +220,11 @@ void GHOST_EventPrinter::getKeyString(GHOST_TKey key, char str[32]) const
case GHOST_kKeyRightAlt:
tstr = "RightAlt";
break;
- case GHOST_kKeyOS:
- tstr = "OS";
+ case GHOST_kKeyLeftOS:
+ tstr = "LeftOS";
+ break;
+ case GHOST_kKeyRightOS:
+ tstr = "RightOS";
break;
case GHOST_kKeyApp:
tstr = "App";
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
index 4f6a9531077..13eccf661f5 100644
--- a/intern/ghost/intern/GHOST_ISystem.cpp
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -9,14 +9,14 @@
* Copyright (C) 2001 NaN Technologies B.V.
*/
+#include <stdexcept>
+
#include "GHOST_ISystem.h"
+#include "GHOST_SystemHeadless.h"
-#if defined(WITH_HEADLESS)
-# include "GHOST_SystemNULL.h"
-#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
+#if defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
# include "GHOST_SystemWayland.h"
# include "GHOST_SystemX11.h"
-# include <stdexcept>
#elif defined(WITH_GHOST_X11)
# include "GHOST_SystemX11.h"
#elif defined(WITH_GHOST_WAYLAND)
@@ -49,26 +49,50 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
#endif
#if defined(WITH_HEADLESS)
- m_system = new GHOST_SystemNULL();
+ /* Pass. */
#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
/* Special case, try Wayland, fall back to X11. */
try {
m_system = has_wayland_libraries ? new GHOST_SystemWayland() : nullptr;
}
catch (const std::runtime_error &) {
- /* fallback to X11. */
delete m_system;
m_system = nullptr;
}
if (!m_system) {
- m_system = new GHOST_SystemX11();
+ /* Try to fallback to X11. */
+ try {
+ m_system = new GHOST_SystemX11();
+ }
+ catch (const std::runtime_error &) {
+ delete m_system;
+ m_system = nullptr;
+ }
}
#elif defined(WITH_GHOST_X11)
- m_system = new GHOST_SystemX11();
+ try {
+ m_system = new GHOST_SystemX11();
+ }
+ catch (const std::runtime_error &) {
+ delete m_system;
+ m_system = nullptr;
+ }
#elif defined(WITH_GHOST_WAYLAND)
- m_system = has_wayland_libraries ? new GHOST_SystemWayland() : nullptr;
+ try {
+ m_system = has_wayland_libraries ? new GHOST_SystemWayland() : nullptr;
+ }
+ catch (const std::runtime_error &) {
+ delete m_system;
+ m_system = nullptr;
+ }
#elif defined(WITH_GHOST_SDL)
- m_system = new GHOST_SystemSDL();
+ try {
+ m_system = new GHOST_SystemSDL();
+ }
+ catch (const std::runtime_error &) {
+ delete m_system;
+ m_system = nullptr;
+ }
#elif defined(WIN32)
m_system = new GHOST_SystemWin32();
#elif defined(__APPLE__)
@@ -85,6 +109,30 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
return success;
}
+GHOST_TSuccess GHOST_ISystem::createSystemBackground()
+{
+ GHOST_TSuccess success;
+ if (!m_system) {
+#if !defined(WITH_HEADLESS)
+ /* Try to create a off-screen render surface with the graphical systems. */
+ success = createSystem();
+ if (success) {
+ return success;
+ }
+ /* Try to fallback to headless mode if all else fails. */
+#endif
+ m_system = new GHOST_SystemHeadless();
+ success = m_system != nullptr ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ if (success) {
+ success = m_system->init();
+ }
+ return success;
+}
+
GHOST_TSuccess GHOST_ISystem::disposeSystem()
{
GHOST_TSuccess success = GHOST_kSuccess;
diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
index 1246aa19a99..152b6b68026 100644
--- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
+++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
@@ -17,11 +17,8 @@ class GHOST_IXrGraphicsBinding {
public:
union {
#if defined(WITH_GHOST_X11)
-# if defined(WITH_GL_EGL)
XrGraphicsBindingEGLMNDX egl;
-# else
XrGraphicsBindingOpenGLXlibKHR glx;
-# endif
#elif defined(WIN32)
XrGraphicsBindingOpenGLWin32KHR wgl;
XrGraphicsBindingD3D11KHR d3d11;
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
index c3fcd7214ca..0a62359cd77 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.cpp
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -512,4 +512,4 @@ void GHOST_ImeWin32::UpdateInfo(HWND window_handle)
}
}
-#endif // WITH_INPUT_IME
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index 0ae2bbc59e9..85c8ed7b4bd 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -351,4 +351,4 @@ class GHOST_ImeWin32 {
bool is_first, is_enable;
};
-#endif // WITH_INPUT_IME
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.cpp b/intern/ghost/intern/GHOST_ModifierKeys.cpp
index d31dc8f0770..5ecbae77f46 100644
--- a/intern/ghost/intern/GHOST_ModifierKeys.cpp
+++ b/intern/ghost/intern/GHOST_ModifierKeys.cpp
@@ -10,6 +10,7 @@
*/
#include "GHOST_ModifierKeys.h"
+#include "GHOST_Debug.h"
GHOST_ModifierKeys::GHOST_ModifierKeys()
{
@@ -42,11 +43,15 @@ GHOST_TKey GHOST_ModifierKeys::getModifierKeyCode(GHOST_TModifierKey mask)
case GHOST_kModifierKeyRightControl:
key = GHOST_kKeyRightControl;
break;
- case GHOST_kModifierKeyOS:
- key = GHOST_kKeyOS;
+ case GHOST_kModifierKeyLeftOS:
+ key = GHOST_kKeyLeftOS;
+ break;
+ case GHOST_kModifierKeyRightOS:
+ key = GHOST_kKeyRightOS;
break;
default:
- // Should not happen
+ /* Should not happen. */
+ GHOST_ASSERT(0, "Invalid key!");
key = GHOST_kKeyUnknown;
break;
}
@@ -68,9 +73,12 @@ bool GHOST_ModifierKeys::get(GHOST_TModifierKey mask) const
return m_LeftControl;
case GHOST_kModifierKeyRightControl:
return m_RightControl;
- case GHOST_kModifierKeyOS:
- return m_OS;
+ case GHOST_kModifierKeyLeftOS:
+ return m_LeftOS;
+ case GHOST_kModifierKeyRightOS:
+ return m_RightOS;
default:
+ GHOST_ASSERT(0, "Invalid key!");
return false;
}
}
@@ -96,10 +104,14 @@ void GHOST_ModifierKeys::set(GHOST_TModifierKey mask, bool down)
case GHOST_kModifierKeyRightControl:
m_RightControl = down;
break;
- case GHOST_kModifierKeyOS:
- m_OS = down;
+ case GHOST_kModifierKeyLeftOS:
+ m_LeftOS = down;
+ break;
+ case GHOST_kModifierKeyRightOS:
+ m_RightOS = down;
break;
default:
+ GHOST_ASSERT(0, "Invalid key!");
break;
}
}
@@ -112,7 +124,8 @@ void GHOST_ModifierKeys::clear()
m_RightAlt = false;
m_LeftControl = false;
m_RightControl = false;
- m_OS = false;
+ m_LeftOS = false;
+ m_RightOS = false;
}
bool GHOST_ModifierKeys::equals(const GHOST_ModifierKeys &keys) const
@@ -120,5 +133,5 @@ bool GHOST_ModifierKeys::equals(const GHOST_ModifierKeys &keys) const
return (m_LeftShift == keys.m_LeftShift) && (m_RightShift == keys.m_RightShift) &&
(m_LeftAlt == keys.m_LeftAlt) && (m_RightAlt == keys.m_RightAlt) &&
(m_LeftControl == keys.m_LeftControl) && (m_RightControl == keys.m_RightControl) &&
- (m_OS == keys.m_OS);
+ (m_LeftOS == keys.m_LeftOS) && (m_RightOS == keys.m_RightOS);
}
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h
index ce1bf3df2ae..e2afc879411 100644
--- a/intern/ghost/intern/GHOST_ModifierKeys.h
+++ b/intern/ghost/intern/GHOST_ModifierKeys.h
@@ -55,18 +55,19 @@ struct GHOST_ModifierKeys {
*/
bool equals(const GHOST_ModifierKeys &keys) const;
- /** Bitfield that stores the appropriate key state. */
+ /** Bit-field that stores the appropriate key state. */
uint8_t m_LeftShift : 1;
- /** Bitfield that stores the appropriate key state. */
+ /** Bit-field that stores the appropriate key state. */
uint8_t m_RightShift : 1;
- /** Bitfield that stores the appropriate key state. */
+ /** Bit-field that stores the appropriate key state. */
uint8_t m_LeftAlt : 1;
- /** Bitfield that stores the appropriate key state. */
+ /** Bit-field that stores the appropriate key state. */
uint8_t m_RightAlt : 1;
- /** Bitfield that stores the appropriate key state. */
+ /** Bit-field that stores the appropriate key state. */
uint8_t m_LeftControl : 1;
- /** Bitfield that stores the appropriate key state. */
+ /** Bit-field that stores the appropriate key state. */
uint8_t m_RightControl : 1;
- /** Bitfield that stores the appropriate key state. */
- uint8_t m_OS : 1;
+ /** Bit-field that stores the appropriate key state. */
+ uint8_t m_LeftOS : 1;
+ uint8_t m_RightOS : 1;
};
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
index 36202278ea1..43f31cb2368 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
@@ -7,10 +7,10 @@ GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System &sys) : GHOST_NDOFMa
/* pass */
}
-// whether multi-axis functionality is available (via the OS or driver)
-// does not imply that a device is plugged in or being used
+/* Whether multi-axis functionality is available (via the OS or driver)
+ * does not imply that a device is plugged in or being used. */
bool GHOST_NDOFManagerWin32::available()
{
- // always available since RawInput is built into Windows
+ /* Always available since RawInput is built into Windows. */
return true;
}
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index cf04287af9f..714565568dc 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -8,7 +8,7 @@
#include "GHOST_System.h"
#include <chrono>
-#include <cstdio> /* just for printf */
+#include <cstdio> /* Just for #printf. */
#include "GHOST_DisplayManager.h"
#include "GHOST_EventManager.h"
@@ -110,8 +110,7 @@ bool GHOST_System::validWindow(GHOST_IWindow *window)
GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting &setting,
GHOST_IWindow **window,
- const bool stereoVisual,
- const bool alphaBackground)
+ const bool stereoVisual)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager");
@@ -125,8 +124,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting &setting
setting);
if (success == GHOST_kSuccess) {
// GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
- success = createFullScreenWindow(
- (GHOST_Window **)window, setting, stereoVisual, alphaBackground);
+ success = createFullScreenWindow((GHOST_Window **)window, setting, stereoVisual);
if (success == GHOST_kSuccess) {
m_windowManager->beginFullScreen(*window, stereoVisual);
}
@@ -373,18 +371,13 @@ GHOST_TSuccess GHOST_System::exit()
GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
const GHOST_DisplaySetting &settings,
- const bool stereoVisual,
- const bool alphaBackground)
+ const bool stereoVisual)
{
GHOST_GLSettings glSettings = {0};
if (stereoVisual) {
glSettings.flags |= GHOST_glStereoVisual;
}
- if (alphaBackground) {
- glSettings.flags |= GHOST_glAlphaBackground;
- }
-
/* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger than the viewport. */
GHOST_ASSERT(m_displayManager,
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index d5558be3444..83f8cb254ce 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -120,11 +120,10 @@ class GHOST_System : public GHOST_ISystem {
*/
GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting &setting,
GHOST_IWindow **window,
- const bool stereoVisual,
- const bool alphaBackground);
+ const bool stereoVisual);
/**
- * Updates the resolution while in fullscreen mode.
+ * Updates the resolution while in full-screen mode.
* \param setting: The new setting of the display.
* \param window: Window displayed in full screen.
*
@@ -370,14 +369,13 @@ class GHOST_System : public GHOST_ISystem {
virtual GHOST_TSuccess exit();
/**
- * Creates a fullscreen window.
+ * Creates a full-screen window.
* \param window: The window created.
* \return Indication of success.
*/
GHOST_TSuccess createFullScreenWindow(GHOST_Window **window,
const GHOST_DisplaySetting &settings,
- const bool stereoVisual,
- const bool alphaBackground = 0);
+ const bool stereoVisual);
/** The display manager (platform dependent). */
GHOST_DisplayManager *m_displayManager;
@@ -401,7 +399,7 @@ class GHOST_System : public GHOST_ISystem {
GHOST_EventPrinter *m_eventPrinter;
#endif // WITH_GHOST_DEBUG
- /** Settings of the display before the display went fullscreen. */
+ /** Settings of the display before the display went full-screen. */
GHOST_DisplaySetting m_preFullScreenSetting;
/** Which tablet API to use. */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 8b6dfb4efed..dbb41c7fddf 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -79,7 +79,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param state: The state of the window when opened.
* \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
- * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
+ * \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
* \return The new window (or 0 if creation failed).
*/
@@ -236,9 +236,9 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* \see GHOST_ISystem
*/
- int setConsoleWindowState(GHOST_TConsoleWindowState action)
+ bool setConsoleWindowState(GHOST_TConsoleWindowState action)
{
- return 0;
+ return false;
}
/**
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index c247ef3daa0..fe5992343ab 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -856,7 +856,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(int32_t x, int32_t y)
GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys &keys) const
{
- keys.set(GHOST_kModifierKeyOS, (m_modifierMask & NSEventModifierFlagCommand) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftOS, (m_modifierMask & NSEventModifierFlagCommand) ? true : false);
keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSEventModifierFlagOption) ? true : false);
keys.set(GHOST_kModifierKeyLeftShift,
(m_modifierMask & NSEventModifierFlagShift) ? true : false);
@@ -1020,7 +1020,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
(modifiers & NSEventModifierFlagCommand) ? GHOST_kEventKeyDown :
GHOST_kEventKeyUp,
window,
- GHOST_kKeyOS,
+ GHOST_kKeyLeftOS,
false));
}
@@ -1123,6 +1123,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
case GHOST_kEventDraggingEntered:
case GHOST_kEventDraggingUpdated:
case GHOST_kEventDraggingExited:
+ window->clientToScreenIntern(mouseX, mouseY, mouseX, mouseY);
pushEvent(new GHOST_EventDragnDrop(
getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, NULL));
break;
@@ -1331,6 +1332,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
return GHOST_kFailure;
break;
}
+
+ window->clientToScreenIntern(mouseX, mouseY, mouseX, mouseY);
pushEvent(new GHOST_EventDragnDrop(
getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, eventData));
@@ -1898,7 +1901,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
[event timestamp] * 1000,
(modifiers & NSEventModifierFlagCommand) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp,
window,
- GHOST_kKeyOS,
+ GHOST_kKeyLeftOS,
false));
}
diff --git a/intern/ghost/intern/GHOST_SystemHeadless.h b/intern/ghost/intern/GHOST_SystemHeadless.h
new file mode 100644
index 00000000000..b02a82fc9eb
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemHeadless.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup GHOST
+ * Declaration of GHOST_SystemHeadless class.
+ */
+
+#pragma once
+
+#include "../GHOST_Types.h"
+#include "GHOST_DisplayManagerNULL.h"
+#include "GHOST_System.h"
+#include "GHOST_WindowNULL.h"
+
+#ifdef __linux__
+# include "GHOST_ContextEGL.h"
+#endif
+#include "GHOST_ContextNone.h"
+
+class GHOST_WindowNULL;
+
+class GHOST_SystemHeadless : public GHOST_System {
+ public:
+ GHOST_SystemHeadless() : GHOST_System()
+ { /* nop */
+ }
+ ~GHOST_SystemHeadless() override = default;
+
+ bool processEvents(bool /*waitForEvent*/) override
+ {
+ return false;
+ }
+ bool setConsoleWindowState(GHOST_TConsoleWindowState /*action*/) override
+ {
+ return 0;
+ }
+ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys & /*keys*/) const override
+ {
+ return GHOST_kSuccess;
+ }
+ GHOST_TSuccess getButtons(GHOST_Buttons & /*buttons*/) const override
+ {
+ return GHOST_kSuccess;
+ }
+ char *getClipboard(bool /*selection*/) const override
+ {
+ return nullptr;
+ }
+ void putClipboard(const char * /*buffer*/, bool /*selection*/) const override
+ { /* nop */
+ }
+ uint64_t getMilliSeconds() const override
+ {
+ return 0;
+ }
+ uint8_t getNumDisplays() const override
+ {
+ return uint8_t(1);
+ }
+ GHOST_TSuccess getCursorPosition(int32_t & /*x*/, int32_t & /*y*/) const override
+ {
+ return GHOST_kFailure;
+ }
+ GHOST_TSuccess setCursorPosition(int32_t /*x*/, int32_t /*y*/) override
+ {
+ return GHOST_kFailure;
+ }
+ void getMainDisplayDimensions(uint32_t & /*width*/, uint32_t & /*height*/) const override
+ { /* nop */
+ }
+ void getAllDisplayDimensions(uint32_t & /*width*/, uint32_t & /*height*/) const override
+ { /* nop */
+ }
+ GHOST_IContext *createOffscreenContext(GHOST_GLSettings /*glSettings*/) override
+ {
+#ifdef __linux__
+ GHOST_Context *context;
+ for (int minor = 6; minor >= 0; --minor) {
+ context = new GHOST_ContextEGL((GHOST_System *)this,
+ false,
+ EGLNativeWindowType(0),
+ EGLNativeDisplayType(EGL_DEFAULT_DISPLAY),
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 4,
+ minor,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ delete context;
+ context = nullptr;
+ }
+
+ context = new GHOST_ContextEGL((GHOST_System *)this,
+ false,
+ EGLNativeWindowType(0),
+ EGLNativeDisplayType(EGL_DEFAULT_DISPLAY),
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3,
+ 3,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+
+ if (context->initializeDrawingContext() != GHOST_kSuccess) {
+ delete context;
+ context = nullptr;
+ }
+ return context;
+#else
+ return nullptr;
+#endif
+ }
+ GHOST_TSuccess disposeContext(GHOST_IContext *context) override
+ {
+ delete context;
+
+ return GHOST_kSuccess;
+ }
+
+ GHOST_TSuccess init() override
+ {
+ GHOST_TSuccess success = GHOST_System::init();
+
+ if (success) {
+ m_displayManager = new GHOST_DisplayManagerNULL();
+
+ if (m_displayManager) {
+ return GHOST_kSuccess;
+ }
+ }
+
+ return GHOST_kFailure;
+ }
+
+ GHOST_IWindow *createWindow(const char *title,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ GHOST_GLSettings glSettings,
+ const bool /*exclusive*/,
+ const bool /*is_dialog*/,
+ const GHOST_IWindow *parentWindow) override
+ {
+ return new GHOST_WindowNULL(title,
+ left,
+ top,
+ width,
+ height,
+ state,
+ parentWindow,
+ type,
+ ((glSettings.flags & GHOST_glStereoVisual) != 0));
+ }
+
+ GHOST_IWindow *getWindowUnderCursor(int32_t /*x*/, int32_t /*y*/) override
+ {
+ return nullptr;
+ }
+};
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
deleted file mode 100644
index 644eb1ba0a5..00000000000
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/** \file
- * \ingroup GHOST
- * Declaration of GHOST_SystemNULL class.
- */
-
-#pragma once
-
-#include "../GHOST_Types.h"
-#include "GHOST_DisplayManagerNULL.h"
-#include "GHOST_System.h"
-#include "GHOST_WindowNULL.h"
-
-class GHOST_WindowNULL;
-
-class GHOST_SystemNULL : public GHOST_System {
- public:
- GHOST_SystemNULL() : GHOST_System()
- { /* nop */
- }
- ~GHOST_SystemNULL()
- { /* nop */
- }
- bool processEvents(bool waitForEvent)
- {
- return false;
- }
- int setConsoleWindowState(GHOST_TConsoleWindowState action)
- {
- return 0;
- }
- GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const
- {
- return GHOST_kSuccess;
- }
- GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const
- {
- return GHOST_kSuccess;
- }
- char *getClipboard(bool selection) const
- {
- return nullptr;
- }
- void putClipboard(const char *buffer, bool selection) const
- { /* nop */
- }
- uint64_t getMilliSeconds() const
- {
- return 0;
- }
- uint8_t getNumDisplays() const
- {
- return uint8_t(1);
- }
- GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const
- {
- return GHOST_kFailure;
- }
- GHOST_TSuccess setCursorPosition(int32_t x, int32_t y)
- {
- return GHOST_kFailure;
- }
- void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
- { /* nop */
- }
- void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
- { /* nop */
- }
- GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings)
- {
- return nullptr;
- }
- GHOST_TSuccess disposeContext(GHOST_IContext *context)
- {
- return GHOST_kFailure;
- }
-
- GHOST_TSuccess init()
- {
- GHOST_TSuccess success = GHOST_System::init();
-
- if (success) {
- m_displayManager = new GHOST_DisplayManagerNULL(this);
-
- if (m_displayManager) {
- return GHOST_kSuccess;
- }
- }
-
- return GHOST_kFailure;
- }
-
- GHOST_IWindow *createWindow(const char *title,
- int32_t left,
- int32_t top,
- uint32_t width,
- uint32_t height,
- GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
- GHOST_GLSettings glSettings,
- const bool exclusive,
- const bool is_dialog,
- const GHOST_IWindow *parentWindow)
- {
- return new GHOST_WindowNULL(this,
- title,
- left,
- top,
- width,
- height,
- state,
- parentWindow,
- type,
- ((glSettings.flags & GHOST_glStereoVisual) != 0));
- }
-
- GHOST_IWindow *getWindowUnderCursor(int32_t x, int32_t y)
- {
- return nullptr;
- }
-};
diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
index 41babc5d312..7e1d3d868c6 100644
--- a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
@@ -5,22 +5,17 @@
* \ingroup GHOST
*/
-#include <cstdio>
#include <sstream>
#include "GHOST_SystemPathsUnix.h"
#include "GHOST_Debug.h"
-// For timing
-
+/* For timing. */
#include <sys/time.h>
#include <unistd.h>
-#include <cstdio> /* for fprintf only */
-#include <cstdlib> /* for exit */
-
-#include <pwd.h> /* for get home without use getenv() */
+#include <pwd.h> /* For get home without use `getenv()`. */
#include <string>
using std::string;
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index d912b57f049..76770e735fa 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -5,6 +5,7 @@
*/
#include <cassert>
+#include <stdexcept>
#include "GHOST_ContextSDL.h"
#include "GHOST_SystemSDL.h"
@@ -20,7 +21,7 @@
GHOST_SystemSDL::GHOST_SystemSDL() : GHOST_System()
{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
- printf("Error initializing SDL: %s\n", SDL_GetError());
+ throw std::runtime_error("Error initializing SDL: " + std::string(SDL_GetError()));
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
@@ -160,7 +161,8 @@ GHOST_TSuccess GHOST_SystemSDL::getModifierKeys(GHOST_ModifierKeys &keys) const
keys.set(GHOST_kModifierKeyRightControl, (mod & KMOD_RCTRL) != 0);
keys.set(GHOST_kModifierKeyLeftAlt, (mod & KMOD_LALT) != 0);
keys.set(GHOST_kModifierKeyRightAlt, (mod & KMOD_RALT) != 0);
- keys.set(GHOST_kModifierKeyOS, (mod & (KMOD_LGUI | KMOD_RGUI)) != 0);
+ keys.set(GHOST_kModifierKeyLeftOS, (mod & KMOD_LGUI) != 0);
+ keys.set(GHOST_kModifierKeyRightOS, (mod & KMOD_RGUI) != 0);
return GHOST_kSuccess;
}
@@ -218,8 +220,8 @@ static GHOST_TKey convertSDLKey(SDL_Scancode key)
GXMAP(type, SDL_SCANCODE_RCTRL, GHOST_kKeyRightControl);
GXMAP(type, SDL_SCANCODE_LALT, GHOST_kKeyLeftAlt);
GXMAP(type, SDL_SCANCODE_RALT, GHOST_kKeyRightAlt);
- GXMAP(type, SDL_SCANCODE_LGUI, GHOST_kKeyOS);
- GXMAP(type, SDL_SCANCODE_RGUI, GHOST_kKeyOS);
+ GXMAP(type, SDL_SCANCODE_LGUI, GHOST_kKeyLeftOS);
+ GXMAP(type, SDL_SCANCODE_RGUI, GHOST_kKeyRightOS);
GXMAP(type, SDL_SCANCODE_APPLICATION, GHOST_kKeyApp);
GXMAP(type, SDL_SCANCODE_INSERT, GHOST_kKeyInsert);
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index aefea5eda34..bee277ba674 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -33,9 +33,9 @@ class GHOST_SystemSDL : public GHOST_System {
bool processEvents(bool waitForEvent);
- int setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
+ bool setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
{
- return 0;
+ return false;
}
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const;
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 18d91d43057..dd82d435397 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -19,12 +19,14 @@
#include "GHOST_ContextEGL.h"
+#ifdef WITH_INPUT_NDOF
+# include "GHOST_NDOFManagerUnix.h"
+#endif
+
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
# include <wayland_dynload_API.h> /* For `ghost_wl_dynload_libraries`. */
#endif
-#include <EGL/egl.h>
-
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
# include <wayland_dynload_egl.h>
#endif
@@ -62,7 +64,7 @@
/* Logging, use `ghost.wl.*` prefix. */
#include "CLG_log.h"
-static void keyboard_handle_key_repeat_cancel(struct input_t *input);
+static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
static void output_handle_done(void *data, struct wl_output *wl_output);
@@ -84,10 +86,6 @@ static void output_handle_done(void *data, struct wl_output *wl_output);
static bool use_gnome_confine_hack = false;
#endif
-#define XKB_STATE_MODS_ALL \
- (enum xkb_state_component)(XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | \
- XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE)
-
/* -------------------------------------------------------------------- */
/** \name Inline Event Codes
*
@@ -125,6 +123,69 @@ static bool use_gnome_confine_hack = false;
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Modifier Table
+ *
+ * Convenient access to modifier key values, allow looping over modifier keys.
+ * \{ */
+
+enum {
+ MOD_INDEX_SHIFT = 0,
+ MOD_INDEX_ALT = 1,
+ MOD_INDEX_CTRL = 2,
+ MOD_INDEX_OS = 3,
+};
+#define MOD_INDEX_NUM (MOD_INDEX_OS + 1)
+
+struct GWL_ModifierInfo {
+ /** Only for printing messages. */
+ const char *display_name;
+ const char *xkb_id;
+ GHOST_TKey key_l, key_r;
+ GHOST_TModifierKey mod_l, mod_r;
+};
+
+static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = {
+ [MOD_INDEX_SHIFT] =
+ {
+ .display_name = "Shift",
+ .xkb_id = XKB_MOD_NAME_SHIFT,
+ .key_l = GHOST_kKeyLeftShift,
+ .key_r = GHOST_kKeyRightShift,
+ .mod_l = GHOST_kModifierKeyLeftShift,
+ .mod_r = GHOST_kModifierKeyRightShift,
+ },
+ [MOD_INDEX_ALT] =
+ {
+ .display_name = "Alt",
+ .xkb_id = XKB_MOD_NAME_ALT,
+ .key_l = GHOST_kKeyLeftAlt,
+ .key_r = GHOST_kKeyRightAlt,
+ .mod_l = GHOST_kModifierKeyLeftAlt,
+ .mod_r = GHOST_kModifierKeyRightAlt,
+ },
+ [MOD_INDEX_CTRL] =
+ {
+ .display_name = "Control",
+ .xkb_id = XKB_MOD_NAME_CTRL,
+ .key_l = GHOST_kKeyLeftControl,
+ .key_r = GHOST_kKeyRightControl,
+ .mod_l = GHOST_kModifierKeyLeftControl,
+ .mod_r = GHOST_kModifierKeyRightControl,
+ },
+ [MOD_INDEX_OS] =
+ {
+ .display_name = "OS",
+ .xkb_id = XKB_MOD_NAME_LOGO,
+ .key_l = GHOST_kKeyLeftOS,
+ .key_r = GHOST_kKeyRightOS,
+ .mod_l = GHOST_kModifierKeyLeftOS,
+ .mod_r = GHOST_kModifierKeyRightOS,
+ },
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Private Types & Defines
* \{ */
@@ -134,7 +195,7 @@ static bool use_gnome_confine_hack = false;
*/
#define EVDEV_OFFSET 8
-struct cursor_t {
+struct GWL_Cursor {
bool visible = false;
/**
* When false, hide the hardware cursor, while the cursor is still considered to be `visible`,
@@ -161,28 +222,28 @@ struct cursor_t {
* WAYLAND exposes tools via #zwp_tablet_tool_v2.
* Since are no API's to access properties of the tool, store the values here.
*/
-struct tablet_tool_input_t {
- struct input_t *input = nullptr;
- struct wl_surface *cursor_surface = nullptr;
- /** Used to delay clearing tablet focused surface until the frame is handled. */
+struct GWL_TabletTool {
+ struct GWL_Seat *seat = nullptr;
+ struct wl_surface *wl_surface_cursor = nullptr;
+ /** Used to delay clearing tablet focused wl_surface until the frame is handled. */
bool proximity = false;
GHOST_TabletData data = GHOST_TABLET_DATA_NONE;
};
-struct data_offer_t {
+struct GWL_DataOffer {
std::unordered_set<std::string> types;
uint32_t source_actions = 0;
uint32_t dnd_action = 0;
struct wl_data_offer *id = nullptr;
std::atomic<bool> in_use = false;
struct {
- /** Compatible with #input_t.xy coordinates. */
+ /** Compatible with #GWL_Seat.xy coordinates. */
wl_fixed_t xy[2] = {0, 0};
} dnd;
};
-struct data_source_t {
+struct GWL_DataSource {
struct wl_data_source *data_source = nullptr;
char *buffer_out = nullptr;
};
@@ -192,11 +253,11 @@ struct data_source_t {
*
* \note it's important not to store the target window here
* as it can be closed while the key is repeating,
- * instead use the focused keyboard from #intput_t which is cleared when windows are closed.
+ * instead use the focused keyboard from #GWL_Seat which is cleared when windows are closed.
* Therefor keyboard events must always check the window has not been cleared.
*/
-struct key_repeat_payload_t {
- struct input_t *input = nullptr;
+struct GWL_KeyRepeatPlayload {
+ struct GWL_Seat *seat = nullptr;
xkb_keycode_t key_code;
@@ -210,7 +271,7 @@ struct key_repeat_payload_t {
};
/** Internal variables used to track grab-state. */
-struct input_grab_state_t {
+struct GWL_SeatStateGrab {
bool use_lock = false;
bool use_confine = false;
};
@@ -218,7 +279,7 @@ struct input_grab_state_t {
/**
* State of the pointing device (tablet or mouse).
*/
-struct input_state_pointer_t {
+struct GWL_SeatStatePointer {
/**
* High precision coordinates.
*
@@ -227,15 +288,15 @@ struct input_state_pointer_t {
* \code{.cc}
* const wl_fixed_t scale = win->scale();
* const int event_xy[2] = {
- * wl_fixed_to_int(scale * input_state->xy[0]),
- * wl_fixed_to_int(scale * input_state->xy[1]),
+ * wl_fixed_to_int(scale * seat_state_pointer->xy[0]),
+ * wl_fixed_to_int(scale * seat_state_pointer->xy[1]),
* };
* \endcode
*/
wl_fixed_t xy[2] = {0, 0};
/** Outputs on which the cursor is visible. */
- std::unordered_set<const output_t *> outputs;
+ std::unordered_set<const GWL_Output *> outputs;
int theme_scale = 1;
@@ -243,7 +304,7 @@ struct input_state_pointer_t {
uint32_t serial = 0;
/**
- * The surface last used with this pointing device
+ * The wl_surface last used with this pointing device
* (events with this pointing device will be sent here).
*/
struct wl_surface *wl_surface = nullptr;
@@ -252,20 +313,29 @@ struct input_state_pointer_t {
};
/**
- * State of the keyboard.
+ * State of the keyboard (in #GWL_Seat).
*/
-struct input_state_keyboard_t {
+struct GWL_SeatStateKeyboard {
/** The serial of the last used pointer or tablet. */
uint32_t serial = 0;
/**
- * The surface last used with this pointing device
+ * The wl_surface last used with this pointing device
* (events with this pointing device will be sent here).
*/
struct wl_surface *wl_surface = nullptr;
};
-struct input_t {
+/**
+ * Store held keys (only modifiers), could store other keys in the future.
+ *
+ * Needed as #GWL_Seat.xkb_state doesn't store which modifier keys are held.
+ */
+struct WGL_KeyboardDepressedState {
+ int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0};
+};
+
+struct GWL_Seat {
GHOST_SystemWayland *system = nullptr;
std::string name;
@@ -280,12 +350,12 @@ struct input_t {
/** Use to check if the last cursor input was tablet or pointer. */
uint32_t cursor_source_serial = 0;
- input_state_pointer_t pointer;
+ GWL_SeatStatePointer pointer;
/** Mostly this can be interchanged with `pointer` however it can't be locked/confined. */
- input_state_pointer_t tablet;
+ GWL_SeatStatePointer tablet;
- input_state_keyboard_t keyboard;
+ GWL_SeatStateKeyboard keyboard;
#ifdef USE_GNOME_CONFINE_HACK
bool use_pointer_software_confine = false;
@@ -293,7 +363,7 @@ struct input_t {
/** The cursor location (in pixel-space) when hidden grab started (#GHOST_kGrabHide). */
wl_fixed_t grab_lock_xy[2] = {0, 0};
- struct cursor_t cursor;
+ struct GWL_Cursor cursor;
struct zwp_relative_pointer_v1 *relative_pointer = nullptr;
struct zwp_locked_pointer_v1 *locked_pointer = nullptr;
@@ -312,19 +382,15 @@ struct input_t {
*/
struct xkb_state *xkb_state_empty_with_numlock = nullptr;
+ /** Keys held matching `xkb_state`. */
+ struct WGL_KeyboardDepressedState key_depressed;
+
/**
* Cache result of `xkb_keymap_mod_get_index`
* so every time a modifier is accessed a string lookup isn't required.
* Be sure to check for #XKB_MOD_INVALID before using.
*/
- struct {
- xkb_mod_index_t shift; /* #XKB_MOD_NAME_SHIFT */
- xkb_mod_index_t caps; /* #XKB_MOD_NAME_CAPS */
- xkb_mod_index_t ctrl; /* #XKB_MOD_NAME_CTRL */
- xkb_mod_index_t alt; /* #XKB_MOD_NAME_ALT */
- xkb_mod_index_t num; /* #XKB_MOD_NAME_NUM */
- xkb_mod_index_t logo; /* #XKB_MOD_NAME_LOGO */
- } xkb_keymap_mod_index;
+ xkb_mod_index_t xkb_keymap_mod_index[MOD_INDEX_NUM];
struct {
/** Key repetition in character per second. */
@@ -335,25 +401,25 @@ struct input_t {
GHOST_ITimerTask *timer = nullptr;
} key_repeat;
- struct wl_surface *focus_dnd = nullptr;
+ struct wl_surface *wl_surface_focus_dnd = nullptr;
struct wl_data_device *data_device = nullptr;
/** Drag & Drop. */
- struct data_offer_t *data_offer_dnd = nullptr;
+ struct GWL_DataOffer *data_offer_dnd = nullptr;
std::mutex data_offer_dnd_mutex;
/** Copy & Paste. */
- struct data_offer_t *data_offer_copy_paste = nullptr;
+ struct GWL_DataOffer *data_offer_copy_paste = nullptr;
std::mutex data_offer_copy_paste_mutex;
- struct data_source_t *data_source = nullptr;
+ struct GWL_DataSource *data_source = nullptr;
std::mutex data_source_mutex;
/** Last device that was active. */
uint32_t data_source_serial = 0;
};
-struct display_t {
+struct GWL_Display {
GHOST_SystemWayland *system = nullptr;
struct wl_display *display = nullptr;
@@ -368,8 +434,8 @@ struct display_t {
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
struct wl_shm *shm = nullptr;
- std::vector<output_t *> outputs;
- std::vector<input_t *> inputs;
+ std::vector<GWL_Output *> outputs;
+ std::vector<GWL_Seat *> seats;
struct wl_data_device_manager *data_device_manager = nullptr;
struct zwp_tablet_manager_v2 *tablet_manager = nullptr;
@@ -407,31 +473,31 @@ static void ghost_wayland_log_handler(const char *msg, va_list arg)
}
}
-static input_state_pointer_t *input_state_pointer_active(input_t *input)
+static GWL_SeatStatePointer *seat_state_pointer_active(GWL_Seat *seat)
{
- if (input->pointer.serial == input->cursor_source_serial) {
- return &input->pointer;
+ if (seat->pointer.serial == seat->cursor_source_serial) {
+ return &seat->pointer;
}
- if (input->tablet.serial == input->cursor_source_serial) {
- return &input->tablet;
+ if (seat->tablet.serial == seat->cursor_source_serial) {
+ return &seat->tablet;
}
return nullptr;
}
-static input_state_pointer_t *input_state_pointer_from_cursor_surface(input_t *input,
- const wl_surface *wl_surface)
+static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *seat,
+ const wl_surface *wl_surface)
{
if (ghost_wl_surface_own_cursor_pointer(wl_surface)) {
- return &input->pointer;
+ return &seat->pointer;
}
if (ghost_wl_surface_own_cursor_tablet(wl_surface)) {
- return &input->tablet;
+ return &seat->tablet;
}
GHOST_ASSERT(0, "Surface found without pointer/tablet tag");
return nullptr;
}
-static void display_destroy(display_t *d)
+static void display_destroy(GWL_Display *d)
{
if (d->data_device_manager) {
wl_data_device_manager_destroy(d->data_device_manager);
@@ -441,77 +507,77 @@ static void display_destroy(display_t *d)
zwp_tablet_manager_v2_destroy(d->tablet_manager);
}
- for (output_t *output : d->outputs) {
+ for (GWL_Output *output : d->outputs) {
wl_output_destroy(output->wl_output);
delete output;
}
- for (input_t *input : d->inputs) {
+ for (GWL_Seat *seat : d->seats) {
/* First handle members that require locking.
* While highly unlikely, it's possible they are being used while this function runs. */
{
- std::lock_guard lock{input->data_source_mutex};
- if (input->data_source) {
- free(input->data_source->buffer_out);
- if (input->data_source->data_source) {
- wl_data_source_destroy(input->data_source->data_source);
+ std::lock_guard lock{seat->data_source_mutex};
+ if (seat->data_source) {
+ free(seat->data_source->buffer_out);
+ if (seat->data_source->data_source) {
+ wl_data_source_destroy(seat->data_source->data_source);
}
- delete input->data_source;
+ delete seat->data_source;
}
}
{
- std::lock_guard lock{input->data_offer_dnd_mutex};
- if (input->data_offer_dnd) {
- wl_data_offer_destroy(input->data_offer_dnd->id);
- delete input->data_offer_dnd;
+ std::lock_guard lock{seat->data_offer_dnd_mutex};
+ if (seat->data_offer_dnd) {
+ wl_data_offer_destroy(seat->data_offer_dnd->id);
+ delete seat->data_offer_dnd;
}
}
{
- std::lock_guard lock{input->data_offer_copy_paste_mutex};
- if (input->data_offer_copy_paste) {
- wl_data_offer_destroy(input->data_offer_copy_paste->id);
- delete input->data_offer_copy_paste;
+ std::lock_guard lock{seat->data_offer_copy_paste_mutex};
+ if (seat->data_offer_copy_paste) {
+ wl_data_offer_destroy(seat->data_offer_copy_paste->id);
+ delete seat->data_offer_copy_paste;
}
}
- if (input->data_device) {
- wl_data_device_release(input->data_device);
+ if (seat->data_device) {
+ wl_data_device_release(seat->data_device);
}
- if (input->cursor.custom_data) {
- munmap(input->cursor.custom_data, input->cursor.custom_data_size);
+ if (seat->cursor.custom_data) {
+ munmap(seat->cursor.custom_data, seat->cursor.custom_data_size);
}
- if (input->wl_pointer) {
- if (input->cursor.wl_surface) {
- wl_surface_destroy(input->cursor.wl_surface);
+ if (seat->wl_pointer) {
+ if (seat->cursor.wl_surface) {
+ wl_surface_destroy(seat->cursor.wl_surface);
}
- if (input->cursor.wl_theme) {
- wl_cursor_theme_destroy(input->cursor.wl_theme);
+ if (seat->cursor.wl_theme) {
+ wl_cursor_theme_destroy(seat->cursor.wl_theme);
}
- if (input->wl_pointer) {
- wl_pointer_destroy(input->wl_pointer);
+ if (seat->wl_pointer) {
+ wl_pointer_destroy(seat->wl_pointer);
}
}
- if (input->wl_keyboard) {
- if (input->key_repeat.timer) {
- keyboard_handle_key_repeat_cancel(input);
+ if (seat->wl_keyboard) {
+ if (seat->key_repeat.timer) {
+ keyboard_handle_key_repeat_cancel(seat);
}
- wl_keyboard_destroy(input->wl_keyboard);
+ wl_keyboard_destroy(seat->wl_keyboard);
}
/* Un-referencing checks for NULL case. */
- xkb_state_unref(input->xkb_state);
- xkb_state_unref(input->xkb_state_empty);
- xkb_state_unref(input->xkb_state_empty_with_numlock);
+ xkb_state_unref(seat->xkb_state);
+ xkb_state_unref(seat->xkb_state_empty);
+ xkb_state_unref(seat->xkb_state_empty_with_numlock);
- xkb_context_unref(input->xkb_context);
+ xkb_context_unref(seat->xkb_context);
- wl_seat_destroy(input->wl_seat);
- delete input;
+ wl_seat_destroy(seat->wl_seat);
+ delete seat;
}
if (d->shm) {
@@ -611,8 +677,8 @@ static GHOST_TKey xkb_map_gkey(const xkb_keysym_t sym)
GXMAP(gkey, XKB_KEY_Control_R, GHOST_kKeyRightControl);
GXMAP(gkey, XKB_KEY_Alt_L, GHOST_kKeyLeftAlt);
GXMAP(gkey, XKB_KEY_Alt_R, GHOST_kKeyRightAlt);
- GXMAP(gkey, XKB_KEY_Super_L, GHOST_kKeyOS);
- GXMAP(gkey, XKB_KEY_Super_R, GHOST_kKeyOS);
+ GXMAP(gkey, XKB_KEY_Super_L, GHOST_kKeyLeftOS);
+ GXMAP(gkey, XKB_KEY_Super_R, GHOST_kKeyRightOS);
GXMAP(gkey, XKB_KEY_Menu, GHOST_kKeyApp);
GXMAP(gkey, XKB_KEY_Caps_Lock, GHOST_kKeyCapsLock);
@@ -860,6 +926,78 @@ static wl_buffer *ghost_wl_buffer_create_for_image(struct wl_shm *shm,
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Private Keyboard Depressed Key Tracking
+ *
+ * Don't track physical key-codes because there may be multiple keyboards connected.
+ * Instead, count the number of #GHOST_kKey are pressed.
+ * This may seem susceptible to bugs with sticky-keys however XKB works this way internally.
+ * \{ */
+
+static CLG_LogRef LOG_WL_KEYBOARD_DEPRESSED_STATE = {"ghost.wl.keyboard.depressed"};
+#define LOG (&LOG_WL_KEYBOARD_DEPRESSED_STATE)
+
+static void keyboard_depressed_state_reset(GWL_Seat *seat)
+{
+ for (int i = 0; i < GHOST_KEY_MODIFIER_NUM; i++) {
+ seat->key_depressed.mods[i] = 0;
+ }
+}
+
+static void keyboard_depressed_state_key_event(GWL_Seat *seat,
+ const GHOST_TKey gkey,
+ const GHOST_TEventType etype)
+{
+ if (GHOST_KEY_MODIFIER_CHECK(gkey)) {
+ const int index = GHOST_KEY_MODIFIER_TO_INDEX(gkey);
+ int16_t &value = seat->key_depressed.mods[index];
+ if (etype == GHOST_kEventKeyUp) {
+ value -= 1;
+ if (UNLIKELY(value < 0)) {
+ CLOG_WARN(LOG, "modifier (%d) has negative keys held (%d)!", index, value);
+ value = 0;
+ }
+ }
+ else {
+ value += 1;
+ }
+ }
+}
+
+static void keyboard_depressed_state_push_events_from_change(
+ GWL_Seat *seat, const WGL_KeyboardDepressedState &key_depressed_prev)
+{
+ GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface);
+ GHOST_SystemWayland *system = seat->system;
+
+ /* Separate key up and down into separate passes so key down events always come after key up.
+ * Do this so users of GHOST can use the last pressed or released modifier to check
+ * if the modifier is held instead of counting modifiers pressed as is done here,
+ * this isn't perfect but works well enough in practice. */
+ for (int i = 0; i < GHOST_KEY_MODIFIER_NUM; i++) {
+ for (int d = seat->key_depressed.mods[i] - key_depressed_prev.mods[i]; d < 0; d++) {
+ const GHOST_TKey gkey = GHOST_KEY_MODIFIER_FROM_INDEX(i);
+ seat->system->pushEvent(
+ new GHOST_EventKey(system->getMilliSeconds(), GHOST_kEventKeyUp, win, gkey, false));
+
+ CLOG_INFO(LOG, 2, "modifier (%d) up", i);
+ }
+ }
+
+ for (int i = 0; i < GHOST_KEY_MODIFIER_NUM; i++) {
+ for (int d = seat->key_depressed.mods[i] - key_depressed_prev.mods[i]; d > 0; d--) {
+ const GHOST_TKey gkey = GHOST_KEY_MODIFIER_FROM_INDEX(i);
+ seat->system->pushEvent(
+ new GHOST_EventKey(system->getMilliSeconds(), GHOST_kEventKeyDown, win, gkey, false));
+ CLOG_INFO(LOG, 2, "modifier (%d) down", i);
+ }
+ }
+}
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Listener (Relative Motion), #zwp_relative_pointer_v1_listener
*
* These callbacks are registered for Wayland interfaces and called when
@@ -870,19 +1008,19 @@ static CLG_LogRef LOG_WL_RELATIVE_POINTER = {"ghost.wl.handle.relative_pointer"}
#define LOG (&LOG_WL_RELATIVE_POINTER)
/**
- * The caller is responsible for setting the value of `input->xy`.
+ * The caller is responsible for setting the value of `seat->xy`.
*/
-static void relative_pointer_handle_relative_motion_impl(input_t *input,
+static void relative_pointer_handle_relative_motion_impl(GWL_Seat *seat,
GHOST_WindowWayland *win,
const wl_fixed_t xy[2])
{
const wl_fixed_t scale = win->scale();
- input->pointer.xy[0] = xy[0];
- input->pointer.xy[1] = xy[1];
+ seat->pointer.xy[0] = xy[0];
+ seat->pointer.xy[1] = xy[1];
#ifdef USE_GNOME_CONFINE_HACK
- if (input->use_pointer_software_confine) {
+ if (seat->use_pointer_software_confine) {
GHOST_Rect bounds;
win->getClientBounds(bounds);
/* Needed or the cursor is considered outside the window and doesn't restore the location. */
@@ -893,15 +1031,15 @@ static void relative_pointer_handle_relative_motion_impl(input_t *input,
bounds.m_t = wl_fixed_from_int(bounds.m_t) / scale;
bounds.m_r = wl_fixed_from_int(bounds.m_r) / scale;
bounds.m_b = wl_fixed_from_int(bounds.m_b) / scale;
- bounds.clampPoint(UNPACK2(input->pointer.xy));
+ bounds.clampPoint(UNPACK2(seat->pointer.xy));
}
#endif
- input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- win,
- wl_fixed_to_int(scale * input->pointer.xy[0]),
- wl_fixed_to_int(scale * input->pointer.xy[1]),
- GHOST_TABLET_DATA_NONE));
+ seat->system->pushEvent(new GHOST_EventCursor(seat->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ win,
+ wl_fixed_to_int(scale * seat->pointer.xy[0]),
+ wl_fixed_to_int(scale * seat->pointer.xy[1]),
+ GHOST_TABLET_DATA_NONE));
}
static void relative_pointer_handle_relative_motion(
@@ -914,16 +1052,16 @@ static void relative_pointer_handle_relative_motion(
const wl_fixed_t /*dx_unaccel*/,
const wl_fixed_t /*dy_unaccel*/)
{
- input_t *input = static_cast<input_t *>(data);
- if (wl_surface *focus_surface = input->pointer.wl_surface) {
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
CLOG_INFO(LOG, 2, "relative_motion");
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
const wl_fixed_t xy_next[2] = {
- input->pointer.xy[0] + (dx / scale),
- input->pointer.xy[1] + (dy / scale),
+ seat->pointer.xy[0] + (dx / scale),
+ seat->pointer.xy[1] + (dy / scale),
};
- relative_pointer_handle_relative_motion_impl(input, win, xy_next);
+ relative_pointer_handle_relative_motion_impl(seat, win, xy_next);
}
else {
CLOG_INFO(LOG, 2, "relative_motion (skipped)");
@@ -945,26 +1083,26 @@ static const zwp_relative_pointer_v1_listener relative_pointer_listener = {
static CLG_LogRef LOG_WL_DATA_SOURCE = {"ghost.wl.handle.data_source"};
#define LOG (&LOG_WL_DATA_SOURCE)
-static void dnd_events(const input_t *const input, const GHOST_TEventType event)
+static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event)
{
- /* NOTE: `input->data_offer_dnd_mutex` must already be locked. */
- if (wl_surface *focus_surface = input->focus_dnd) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
+ /* NOTE: `seat->data_offer_dnd_mutex` must already be locked. */
+ if (wl_surface *wl_surface_focus = seat->wl_surface_focus_dnd) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
const int event_xy[2] = {
- wl_fixed_to_int(scale * input->data_offer_dnd->dnd.xy[0]),
- wl_fixed_to_int(scale * input->data_offer_dnd->dnd.xy[1]),
+ wl_fixed_to_int(scale * seat->data_offer_dnd->dnd.xy[0]),
+ wl_fixed_to_int(scale * seat->data_offer_dnd->dnd.xy[1]),
};
- const uint64_t time = input->system->getMilliSeconds();
+ const uint64_t time = seat->system->getMilliSeconds();
for (const std::string &type : mime_preference_order) {
- input->system->pushEvent(new GHOST_EventDragnDrop(
+ seat->system->pushEvent(new GHOST_EventDragnDrop(
time, event, mime_dnd.at(type), win, UNPACK2(event_xy), nullptr));
}
}
}
-static std::string read_pipe(data_offer_t *data_offer,
+static std::string read_pipe(GWL_DataOffer *data_offer,
const std::string mime_receive,
std::mutex *mutex)
{
@@ -1011,12 +1149,12 @@ static void data_source_handle_send(void *data,
const char * /*mime_type*/,
const int32_t fd)
{
- input_t *input = static_cast<input_t *>(data);
- std::lock_guard lock{input->data_source_mutex};
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ std::lock_guard lock{seat->data_source_mutex};
CLOG_INFO(LOG, 2, "send");
- const char *const buffer = input->data_source->buffer_out;
+ const char *const buffer = seat->data_source->buffer_out;
if (write(fd, buffer, strlen(buffer)) < 0) {
GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl);
}
@@ -1094,7 +1232,7 @@ static void data_offer_handle_offer(void *data,
const char *mime_type)
{
CLOG_INFO(LOG, 2, "offer (mime_type=%s)", mime_type);
- static_cast<data_offer_t *>(data)->types.insert(mime_type);
+ static_cast<GWL_DataOffer *>(data)->types.insert(mime_type);
}
static void data_offer_handle_source_actions(void *data,
@@ -1102,7 +1240,7 @@ static void data_offer_handle_source_actions(void *data,
const uint32_t source_actions)
{
CLOG_INFO(LOG, 2, "source_actions (%u)", source_actions);
- static_cast<data_offer_t *>(data)->source_actions = source_actions;
+ static_cast<GWL_DataOffer *>(data)->source_actions = source_actions;
}
static void data_offer_handle_action(void *data,
@@ -1110,7 +1248,7 @@ static void data_offer_handle_action(void *data,
const uint32_t dnd_action)
{
CLOG_INFO(LOG, 2, "actions (%u)", dnd_action);
- static_cast<data_offer_t *>(data)->dnd_action = dnd_action;
+ static_cast<GWL_DataOffer *>(data)->dnd_action = dnd_action;
}
static const struct wl_data_offer_listener data_offer_listener = {
@@ -1136,7 +1274,7 @@ static void data_device_handle_data_offer(void * /*data*/,
{
CLOG_INFO(LOG, 2, "data_offer");
- data_offer_t *data_offer = new data_offer_t;
+ GWL_DataOffer *data_offer = new GWL_DataOffer;
data_offer->id = id;
wl_data_offer_add_listener(id, &data_offer_listener, data_offer);
}
@@ -1144,23 +1282,23 @@ static void data_device_handle_data_offer(void * /*data*/,
static void data_device_handle_enter(void *data,
struct wl_data_device * /*wl_data_device*/,
const uint32_t serial,
- struct wl_surface *surface,
+ struct wl_surface *wl_surface,
const wl_fixed_t x,
const wl_fixed_t y,
struct wl_data_offer *id)
{
- if (!ghost_wl_surface_own(surface)) {
+ if (!ghost_wl_surface_own(wl_surface)) {
CLOG_INFO(LOG, 2, "enter (skipped)");
return;
}
CLOG_INFO(LOG, 2, "enter");
- input_t *input = static_cast<input_t *>(data);
- std::lock_guard lock{input->data_offer_dnd_mutex};
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ std::lock_guard lock{seat->data_offer_dnd_mutex};
- delete input->data_offer_dnd;
- input->data_offer_dnd = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id));
- data_offer_t *data_offer = input->data_offer_dnd;
+ delete seat->data_offer_dnd;
+ seat->data_offer_dnd = static_cast<GWL_DataOffer *>(wl_data_offer_get_user_data(id));
+ GWL_DataOffer *data_offer = seat->data_offer_dnd;
data_offer->in_use.store(true);
data_offer->dnd.xy[0] = x;
@@ -1175,24 +1313,24 @@ static void data_device_handle_enter(void *data,
wl_data_offer_accept(id, serial, type.c_str());
}
- input->focus_dnd = surface;
- dnd_events(input, GHOST_kEventDraggingEntered);
+ seat->wl_surface_focus_dnd = wl_surface;
+ dnd_events(seat, GHOST_kEventDraggingEntered);
}
static void data_device_handle_leave(void *data, struct wl_data_device * /*wl_data_device*/)
{
- input_t *input = static_cast<input_t *>(data);
- std::lock_guard lock{input->data_offer_dnd_mutex};
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ std::lock_guard lock{seat->data_offer_dnd_mutex};
CLOG_INFO(LOG, 2, "leave");
- dnd_events(input, GHOST_kEventDraggingExited);
- input->focus_dnd = nullptr;
+ dnd_events(seat, GHOST_kEventDraggingExited);
+ seat->wl_surface_focus_dnd = nullptr;
- if (input->data_offer_dnd && !input->data_offer_dnd->in_use.load()) {
- wl_data_offer_destroy(input->data_offer_dnd->id);
- delete input->data_offer_dnd;
- input->data_offer_dnd = nullptr;
+ if (seat->data_offer_dnd && !seat->data_offer_dnd->in_use.load()) {
+ wl_data_offer_destroy(seat->data_offer_dnd->id);
+ delete seat->data_offer_dnd;
+ seat->data_offer_dnd = nullptr;
}
}
@@ -1202,23 +1340,23 @@ static void data_device_handle_motion(void *data,
const wl_fixed_t x,
const wl_fixed_t y)
{
- input_t *input = static_cast<input_t *>(data);
- std::lock_guard lock{input->data_offer_dnd_mutex};
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ std::lock_guard lock{seat->data_offer_dnd_mutex};
CLOG_INFO(LOG, 2, "motion");
- input->data_offer_dnd->dnd.xy[0] = x;
- input->data_offer_dnd->dnd.xy[1] = y;
+ seat->data_offer_dnd->dnd.xy[0] = x;
+ seat->data_offer_dnd->dnd.xy[1] = y;
- dnd_events(input, GHOST_kEventDraggingUpdated);
+ dnd_events(seat, GHOST_kEventDraggingUpdated);
}
static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_data_device*/)
{
- input_t *input = static_cast<input_t *>(data);
- std::lock_guard lock{input->data_offer_dnd_mutex};
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ std::lock_guard lock{seat->data_offer_dnd_mutex};
- data_offer_t *data_offer = input->data_offer_dnd;
+ GWL_DataOffer *data_offer = seat->data_offer_dnd;
const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(),
mime_preference_order.end(),
@@ -1227,9 +1365,9 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
CLOG_INFO(LOG, 2, "drop mime_recieve=%s", mime_receive.c_str());
- auto read_uris_fn = [](input_t *const input,
- data_offer_t *data_offer,
- wl_surface *surface,
+ auto read_uris_fn = [](GWL_Seat *const seat,
+ GWL_DataOffer *data_offer,
+ wl_surface *wl_surface,
const std::string mime_receive) {
const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)};
@@ -1241,13 +1379,13 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
wl_data_offer_finish(data_offer->id);
wl_data_offer_destroy(data_offer->id);
- if (input->data_offer_dnd == data_offer) {
- input->data_offer_dnd = nullptr;
+ if (seat->data_offer_dnd == data_offer) {
+ seat->data_offer_dnd = nullptr;
}
delete data_offer;
data_offer = nullptr;
- GHOST_SystemWayland *const system = input->system;
+ GHOST_SystemWayland *const system = seat->system;
if (mime_receive == mime_text_uri) {
static constexpr const char *file_proto = "file://";
@@ -1255,7 +1393,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
* So support both, once `\n` is found, strip the preceding `\r` if found. */
static constexpr const char *lf = "\n";
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface);
std::vector<std::string> uris;
size_t pos = 0;
@@ -1302,9 +1440,10 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
wl_display_roundtrip(system->display());
};
- /* Pass in `input->focus_dnd` instead of accessing it from `input` since the leave callback
- * (#data_device_handle_leave) will clear the value once this function starts. */
- std::thread read_thread(read_uris_fn, input, data_offer, input->focus_dnd, mime_receive);
+ /* Pass in `seat->wl_surface_focus_dnd` instead of accessing it from `seat` since the leave
+ * callback (#data_device_handle_leave) will clear the value once this function starts. */
+ std::thread read_thread(
+ read_uris_fn, seat, data_offer, seat->wl_surface_focus_dnd, mime_receive);
read_thread.detach();
}
@@ -1312,17 +1451,18 @@ static void data_device_handle_selection(void *data,
struct wl_data_device * /*wl_data_device*/,
struct wl_data_offer *id)
{
- input_t *input = static_cast<input_t *>(data);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- std::lock_guard lock{input->data_offer_copy_paste_mutex};
+ std::lock_guard lock{seat->data_offer_copy_paste_mutex};
- data_offer_t *data_offer = input->data_offer_copy_paste;
+ GWL_DataOffer *data_offer = seat->data_offer_copy_paste;
/* Delete old data offer. */
if (data_offer != nullptr) {
wl_data_offer_destroy(data_offer->id);
delete data_offer;
data_offer = nullptr;
+ seat->data_offer_copy_paste = nullptr;
}
if (id == nullptr) {
@@ -1332,14 +1472,14 @@ static void data_device_handle_selection(void *data,
CLOG_INFO(LOG, 2, "selection");
/* Get new data offer. */
- data_offer = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id));
- input->data_offer_copy_paste = data_offer;
+ data_offer = static_cast<GWL_DataOffer *>(wl_data_offer_get_user_data(id));
+ seat->data_offer_copy_paste = data_offer;
- auto read_selection_fn = [](input_t *input) {
- GHOST_SystemWayland *const system = input->system;
- input->data_offer_copy_paste_mutex.lock();
+ auto read_selection_fn = [](GWL_Seat *seat) {
+ GHOST_SystemWayland *const system = seat->system;
+ seat->data_offer_copy_paste_mutex.lock();
- data_offer_t *data_offer = input->data_offer_copy_paste;
+ GWL_DataOffer *data_offer = seat->data_offer_copy_paste;
std::string mime_receive;
for (const std::string type : {mime_text_utf8, mime_text_plain}) {
if (data_offer->types.count(type)) {
@@ -1348,7 +1488,7 @@ static void data_device_handle_selection(void *data,
}
}
const std::string data = read_pipe(
- data_offer, mime_receive, &input->data_offer_copy_paste_mutex);
+ data_offer, mime_receive, &seat->data_offer_copy_paste_mutex);
{
std::lock_guard lock{system_selection_mutex};
@@ -1356,7 +1496,7 @@ static void data_device_handle_selection(void *data,
}
};
- std::thread read_thread(read_selection_fn, input);
+ std::thread read_thread(read_selection_fn, seat);
read_thread.detach();
}
@@ -1384,7 +1524,7 @@ static void cursor_buffer_handle_release(void *data, struct wl_buffer *wl_buffer
{
CLOG_INFO(LOG, 2, "release");
- cursor_t *cursor = static_cast<cursor_t *>(data);
+ GWL_Cursor *cursor = static_cast<GWL_Cursor *>(data);
wl_buffer_destroy(wl_buffer);
if (wl_buffer == cursor->wl_buffer) {
@@ -1408,22 +1548,22 @@ static const struct wl_buffer_listener cursor_buffer_listener = {
static CLG_LogRef LOG_WL_CURSOR_SURFACE = {"ghost.wl.handle.cursor_surface"};
#define LOG (&LOG_WL_CURSOR_SURFACE)
-static bool update_cursor_scale(cursor_t &cursor,
+static bool update_cursor_scale(GWL_Cursor &cursor,
wl_shm *shm,
- input_state_pointer_t *input_state,
- wl_surface *cursor_surface)
+ GWL_SeatStatePointer *seat_state_pointer,
+ wl_surface *wl_cursor_surface)
{
int scale = 0;
- for (const output_t *output : input_state->outputs) {
+ for (const GWL_Output *output : seat_state_pointer->outputs) {
if (output->scale > scale) {
scale = output->scale;
}
}
- if (scale > 0 && input_state->theme_scale != scale) {
- input_state->theme_scale = scale;
+ if (scale > 0 && seat_state_pointer->theme_scale != scale) {
+ seat_state_pointer->theme_scale = scale;
if (!cursor.is_custom) {
- wl_surface_set_buffer_scale(cursor_surface, scale);
+ wl_surface_set_buffer_scale(wl_cursor_surface, scale);
}
wl_cursor_theme_destroy(cursor.wl_theme);
cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm);
@@ -1434,36 +1574,38 @@ static bool update_cursor_scale(cursor_t &cursor,
static void cursor_surface_handle_enter(void *data,
struct wl_surface *wl_surface,
- struct wl_output *output)
+ struct wl_output *wl_output)
{
- if (!ghost_wl_output_own(output)) {
+ if (!ghost_wl_output_own(wl_output)) {
CLOG_INFO(LOG, 2, "handle_enter (skipped)");
return;
}
CLOG_INFO(LOG, 2, "handle_enter");
- input_t *input = static_cast<input_t *>(data);
- input_state_pointer_t *input_state = input_state_pointer_from_cursor_surface(input, wl_surface);
- const output_t *reg_output = ghost_wl_output_user_data(output);
- input_state->outputs.insert(reg_output);
- update_cursor_scale(input->cursor, input->system->shm(), input_state, wl_surface);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_from_cursor_surface(seat,
+ wl_surface);
+ const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output);
+ seat_state_pointer->outputs.insert(reg_output);
+ update_cursor_scale(seat->cursor, seat->system->shm(), seat_state_pointer, wl_surface);
}
static void cursor_surface_handle_leave(void *data,
struct wl_surface *wl_surface,
- struct wl_output *output)
+ struct wl_output *wl_output)
{
- if (!(output && ghost_wl_output_own(output))) {
+ if (!(wl_output && ghost_wl_output_own(wl_output))) {
CLOG_INFO(LOG, 2, "handle_leave (skipped)");
return;
}
CLOG_INFO(LOG, 2, "handle_leave");
- input_t *input = static_cast<input_t *>(data);
- input_state_pointer_t *input_state = input_state_pointer_from_cursor_surface(input, wl_surface);
- const output_t *reg_output = ghost_wl_output_user_data(output);
- input_state->outputs.erase(reg_output);
- update_cursor_scale(input->cursor, input->system->shm(), input_state, wl_surface);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_from_cursor_surface(seat,
+ wl_surface);
+ const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output);
+ seat_state_pointer->outputs.erase(reg_output);
+ update_cursor_scale(seat->cursor, seat->system->shm(), seat_state_pointer, wl_surface);
}
static const struct wl_surface_listener cursor_surface_listener = {
@@ -1485,48 +1627,48 @@ static CLG_LogRef LOG_WL_POINTER = {"ghost.wl.handle.pointer"};
static void pointer_handle_enter(void *data,
struct wl_pointer * /*wl_pointer*/,
const uint32_t serial,
- struct wl_surface *surface,
+ struct wl_surface *wl_surface,
const wl_fixed_t surface_x,
const wl_fixed_t surface_y)
{
- if (!ghost_wl_surface_own(surface)) {
+ if (!ghost_wl_surface_own(wl_surface)) {
CLOG_INFO(LOG, 2, "enter (skipped)");
return;
}
CLOG_INFO(LOG, 2, "enter");
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface);
win->activate();
- input_t *input = static_cast<input_t *>(data);
- input->cursor_source_serial = serial;
- input->pointer.serial = serial;
- input->pointer.xy[0] = surface_x;
- input->pointer.xy[1] = surface_y;
- input->pointer.wl_surface = surface;
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->cursor_source_serial = serial;
+ seat->pointer.serial = serial;
+ seat->pointer.xy[0] = surface_x;
+ seat->pointer.xy[1] = surface_y;
+ seat->pointer.wl_surface = wl_surface;
win->setCursorShape(win->getCursorShape());
const wl_fixed_t scale = win->scale();
- input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- win,
- wl_fixed_to_int(scale * input->pointer.xy[0]),
- wl_fixed_to_int(scale * input->pointer.xy[1]),
- GHOST_TABLET_DATA_NONE));
+ seat->system->pushEvent(new GHOST_EventCursor(seat->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ win,
+ wl_fixed_to_int(scale * seat->pointer.xy[0]),
+ wl_fixed_to_int(scale * seat->pointer.xy[1]),
+ GHOST_TABLET_DATA_NONE));
}
static void pointer_handle_leave(void *data,
struct wl_pointer * /*wl_pointer*/,
const uint32_t /*serial*/,
- struct wl_surface *surface)
+ struct wl_surface *wl_surface)
{
/* First clear the `pointer.wl_surface`, since the window won't exist when closing the window. */
- static_cast<input_t *>(data)->pointer.wl_surface = nullptr;
- if (surface && ghost_wl_surface_own(surface)) {
+ static_cast<GWL_Seat *>(data)->pointer.wl_surface = nullptr;
+ if (wl_surface && ghost_wl_surface_own(wl_surface)) {
CLOG_INFO(LOG, 2, "leave");
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface);
win->deactivate();
}
else {
@@ -1540,20 +1682,20 @@ static void pointer_handle_motion(void *data,
const wl_fixed_t surface_x,
const wl_fixed_t surface_y)
{
- input_t *input = static_cast<input_t *>(data);
- input->pointer.xy[0] = surface_x;
- input->pointer.xy[1] = surface_y;
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->pointer.xy[0] = surface_x;
+ seat->pointer.xy[1] = surface_y;
- if (wl_surface *focus_surface = input->pointer.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
CLOG_INFO(LOG, 2, "motion");
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
- input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- win,
- wl_fixed_to_int(scale * input->pointer.xy[0]),
- wl_fixed_to_int(scale * input->pointer.xy[1]),
- GHOST_TABLET_DATA_NONE));
+ seat->system->pushEvent(new GHOST_EventCursor(seat->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ win,
+ wl_fixed_to_int(scale * seat->pointer.xy[0]),
+ wl_fixed_to_int(scale * seat->pointer.xy[1]),
+ GHOST_TABLET_DATA_NONE));
}
else {
CLOG_INFO(LOG, 2, "motion (skipped)");
@@ -1569,7 +1711,7 @@ static void pointer_handle_button(void *data,
{
CLOG_INFO(LOG, 2, "button (button=%u, state=%u)", button, state);
- input_t *input = static_cast<input_t *>(data);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
GHOST_TEventType etype = GHOST_kEventUnknown;
switch (state) {
case WL_POINTER_BUTTON_STATE_RELEASED:
@@ -1605,13 +1747,13 @@ static void pointer_handle_button(void *data,
break;
}
- input->data_source_serial = serial;
- input->pointer.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
+ seat->data_source_serial = serial;
+ seat->pointer.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
- if (wl_surface *focus_surface = input->pointer.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- input->system->pushEvent(new GHOST_EventButton(
- input->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE));
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ seat->system->pushEvent(new GHOST_EventButton(
+ seat->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE));
}
}
@@ -1648,15 +1790,15 @@ static void pointer_handle_axis_discrete(void *data,
{
CLOG_INFO(LOG, 2, "axis_discrete (axis=%u, discrete=%d)", axis, discrete);
- input_t *input = static_cast<input_t *>(data);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
return;
}
- if (wl_surface *focus_surface = input->pointer.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- input->system->pushEvent(new GHOST_EventWheel(
- input->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1));
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ seat->system->pushEvent(new GHOST_EventWheel(
+ seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1));
}
}
@@ -1689,9 +1831,9 @@ static void tablet_tool_handle_type(void *data,
{
CLOG_INFO(LOG, 2, "type (type=%u)", tool_type);
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
- tool_input->data.Active = tablet_tool_map_type((enum zwp_tablet_tool_v2_type)tool_type);
+ tablet_tool->data.Active = tablet_tool_map_type((enum zwp_tablet_tool_v2_type)tool_type);
}
static void tablet_tool_handle_hardware_serial(void * /*data*/,
@@ -1734,47 +1876,47 @@ static void tablet_tool_handle_removed(void *data, struct zwp_tablet_tool_v2 *zw
{
CLOG_INFO(LOG, 2, "removed");
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GWL_Seat *seat = tablet_tool->seat;
- if (tool_input->cursor_surface) {
- wl_surface_destroy(tool_input->cursor_surface);
+ if (tablet_tool->wl_surface_cursor) {
+ wl_surface_destroy(tablet_tool->wl_surface_cursor);
}
- input->tablet_tools.erase(zwp_tablet_tool_v2);
+ seat->tablet_tools.erase(zwp_tablet_tool_v2);
- delete tool_input;
+ delete tablet_tool;
}
static void tablet_tool_handle_proximity_in(void *data,
struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/,
const uint32_t serial,
struct zwp_tablet_v2 * /*tablet*/,
- struct wl_surface *surface)
+ struct wl_surface *wl_surface)
{
- if (!ghost_wl_surface_own(surface)) {
+ if (!ghost_wl_surface_own(wl_surface)) {
CLOG_INFO(LOG, 2, "proximity_in (skipped)");
return;
}
CLOG_INFO(LOG, 2, "proximity_in");
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- tool_input->proximity = true;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ tablet_tool->proximity = true;
- input_t *input = tool_input->input;
- input->cursor_source_serial = serial;
- input->tablet.wl_surface = surface;
- input->tablet.serial = serial;
+ GWL_Seat *seat = tablet_tool->seat;
+ seat->cursor_source_serial = serial;
+ seat->tablet.wl_surface = wl_surface;
+ seat->tablet.serial = serial;
- input->data_source_serial = serial;
+ seat->data_source_serial = serial;
/* Update #GHOST_TabletData. */
- GHOST_TabletData &td = tool_input->data;
+ GHOST_TabletData &td = tablet_tool->data;
/* Reset, to avoid using stale tilt/pressure. */
td.Xtilt = 0.0f;
td.Ytilt = 0.0f;
/* In case pressure isn't supported. */
td.Pressure = 1.0f;
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(input->tablet.wl_surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl_surface);
win->activate();
@@ -1784,10 +1926,10 @@ static void tablet_tool_handle_proximity_out(void *data,
struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/)
{
CLOG_INFO(LOG, 2, "proximity_out");
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- /* Defer clearing the surface until the frame is handled.
- * Without this, the frame can not access the surface. */
- tool_input->proximity = false;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ /* Defer clearing the wl_surface until the frame is handled.
+ * Without this, the frame can not access the wl_surface. */
+ tablet_tool->proximity = false;
}
static void tablet_tool_handle_down(void *data,
@@ -1796,18 +1938,18 @@ static void tablet_tool_handle_down(void *data,
{
CLOG_INFO(LOG, 2, "down");
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GWL_Seat *seat = tablet_tool->seat;
const GHOST_TButton ebutton = GHOST_kButtonMaskLeft;
const GHOST_TEventType etype = GHOST_kEventButtonDown;
- input->data_source_serial = serial;
- input->tablet.buttons.set(ebutton, true);
+ seat->data_source_serial = serial;
+ seat->tablet.buttons.set(ebutton, true);
- if (wl_surface *focus_surface = input->tablet.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- input->system->pushEvent(new GHOST_EventButton(
- input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data));
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ seat->system->pushEvent(new GHOST_EventButton(
+ seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data));
}
}
@@ -1815,17 +1957,17 @@ static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_
{
CLOG_INFO(LOG, 2, "up");
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GWL_Seat *seat = tablet_tool->seat;
const GHOST_TButton ebutton = GHOST_kButtonMaskLeft;
const GHOST_TEventType etype = GHOST_kEventButtonUp;
- input->tablet.buttons.set(ebutton, false);
+ seat->tablet.buttons.set(ebutton, false);
- if (wl_surface *focus_surface = input->tablet.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- input->system->pushEvent(new GHOST_EventButton(
- input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data));
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ seat->system->pushEvent(new GHOST_EventButton(
+ seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data));
}
}
@@ -1836,11 +1978,11 @@ static void tablet_tool_handle_motion(void *data,
{
CLOG_INFO(LOG, 2, "motion");
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GWL_Seat *seat = tablet_tool->seat;
- input->tablet.xy[0] = x;
- input->tablet.xy[1] = y;
+ seat->tablet.xy[0] = x;
+ seat->tablet.xy[1] = y;
/* NOTE: #tablet_tool_handle_frame generates the event (with updated pressure, tilt... etc). */
}
@@ -1852,8 +1994,8 @@ static void tablet_tool_handle_pressure(void *data,
const float pressure_unit = (float)pressure / 65535;
CLOG_INFO(LOG, 2, "pressure (%.4f)", pressure_unit);
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- GHOST_TabletData &td = tool_input->data;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GHOST_TabletData &td = tablet_tool->data;
td.Pressure = pressure_unit;
}
static void tablet_tool_handle_distance(void * /*data*/,
@@ -1874,8 +2016,8 @@ static void tablet_tool_handle_tilt(void *data,
(float)(wl_fixed_to_double(tilt_y) / 90.0),
};
CLOG_INFO(LOG, 2, "tilt (x=%.4f, y=%.4f)", UNPACK2(tilt_unit));
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- GHOST_TabletData &td = tool_input->data;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GHOST_TabletData &td = tablet_tool->data;
td.Xtilt = tilt_unit[0];
td.Ytilt = tilt_unit[1];
CLAMP(td.Xtilt, -1.0f, 1.0f);
@@ -1905,11 +2047,11 @@ static void tablet_tool_handle_wheel(void *data,
}
CLOG_INFO(LOG, 2, "wheel (clicks=%d)", clicks);
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
- if (wl_surface *focus_surface = input->tablet.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- input->system->pushEvent(new GHOST_EventWheel(input->system->getMilliSeconds(), win, clicks));
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GWL_Seat *seat = tablet_tool->seat;
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ seat->system->pushEvent(new GHOST_EventWheel(seat->system->getMilliSeconds(), win, clicks));
}
}
static void tablet_tool_handle_button(void *data,
@@ -1920,8 +2062,8 @@ static void tablet_tool_handle_button(void *data,
{
CLOG_INFO(LOG, 2, "button (button=%u, state=%u)", button, state);
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GWL_Seat *seat = tablet_tool->seat;
GHOST_TEventType etype = GHOST_kEventUnknown;
switch (state) {
@@ -1946,13 +2088,13 @@ static void tablet_tool_handle_button(void *data,
break;
}
- input->data_source_serial = serial;
- input->tablet.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
+ seat->data_source_serial = serial;
+ seat->tablet.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
- if (wl_surface *focus_surface = input->tablet.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- input->system->pushEvent(new GHOST_EventButton(
- input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data));
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ seat->system->pushEvent(new GHOST_EventButton(
+ seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data));
}
}
static void tablet_tool_handle_frame(void *data,
@@ -1961,26 +2103,26 @@ static void tablet_tool_handle_frame(void *data,
{
CLOG_INFO(LOG, 2, "frame");
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
+ GWL_Seat *seat = tablet_tool->seat;
/* No need to check the surfaces origin, it's already known to be owned by GHOST. */
- if (wl_surface *focus_surface = input->tablet.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
- input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- win,
- wl_fixed_to_int(scale * input->tablet.xy[0]),
- wl_fixed_to_int(scale * input->tablet.xy[1]),
- tool_input->data));
- if (tool_input->proximity == false) {
+ seat->system->pushEvent(new GHOST_EventCursor(seat->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ win,
+ wl_fixed_to_int(scale * seat->tablet.xy[0]),
+ wl_fixed_to_int(scale * seat->tablet.xy[1]),
+ tablet_tool->data));
+ if (tablet_tool->proximity == false) {
win->setCursorShape(win->getCursorShape());
}
}
- if (tool_input->proximity == false) {
- input->tablet.wl_surface = nullptr;
+ if (tablet_tool->proximity == false) {
+ seat->tablet.wl_surface = nullptr;
}
}
@@ -2030,19 +2172,19 @@ static void tablet_seat_handle_tool_added(void *data,
{
CLOG_INFO(LOG, 2, "tool_added (id=%p)", id);
- input_t *input = static_cast<input_t *>(data);
- tablet_tool_input_t *tool_input = new tablet_tool_input_t();
- tool_input->input = input;
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ GWL_TabletTool *tablet_tool = new GWL_TabletTool();
+ tablet_tool->seat = seat;
- /* Every tool has it's own cursor surface. */
- tool_input->cursor_surface = wl_compositor_create_surface(input->system->compositor());
- ghost_wl_surface_tag_cursor_tablet(tool_input->cursor_surface);
+ /* Every tool has it's own cursor wl_surface. */
+ tablet_tool->wl_surface_cursor = wl_compositor_create_surface(seat->system->compositor());
+ ghost_wl_surface_tag_cursor_tablet(tablet_tool->wl_surface_cursor);
- wl_surface_add_listener(tool_input->cursor_surface, &cursor_surface_listener, (void *)input);
+ wl_surface_add_listener(tablet_tool->wl_surface_cursor, &cursor_surface_listener, (void *)seat);
- zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listner, tool_input);
+ zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listner, tablet_tool);
- input->tablet_tools.insert(id);
+ seat->tablet_tools.insert(id);
}
static void tablet_seat_handle_pad_added(void * /*data*/,
@@ -2075,7 +2217,7 @@ static void keyboard_handle_keymap(void *data,
const int32_t fd,
const uint32_t size)
{
- input_t *input = static_cast<input_t *>(data);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
if ((!data) || (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)) {
CLOG_INFO(LOG, 2, "keymap (no data or wrong version)");
@@ -2090,7 +2232,7 @@ static void keyboard_handle_keymap(void *data,
}
struct xkb_keymap *keymap = xkb_keymap_new_from_string(
- input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
+ seat->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(map_str, size);
close(fd);
@@ -2102,31 +2244,31 @@ static void keyboard_handle_keymap(void *data,
CLOG_INFO(LOG, 2, "keymap");
/* In practice we can assume `xkb_state_new` always succeeds. */
- xkb_state_unref(input->xkb_state);
- input->xkb_state = xkb_state_new(keymap);
+ xkb_state_unref(seat->xkb_state);
+ seat->xkb_state = xkb_state_new(keymap);
- xkb_state_unref(input->xkb_state_empty);
- input->xkb_state_empty = xkb_state_new(keymap);
+ xkb_state_unref(seat->xkb_state_empty);
+ seat->xkb_state_empty = xkb_state_new(keymap);
- xkb_state_unref(input->xkb_state_empty_with_numlock);
- input->xkb_state_empty_with_numlock = nullptr;
+ xkb_state_unref(seat->xkb_state_empty_with_numlock);
+ seat->xkb_state_empty_with_numlock = nullptr;
{
const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock");
if (num != XKB_MOD_INVALID && mod2 != XKB_MOD_INVALID) {
- input->xkb_state_empty_with_numlock = xkb_state_new(keymap);
+ seat->xkb_state_empty_with_numlock = xkb_state_new(keymap);
xkb_state_update_mask(
- input->xkb_state_empty_with_numlock, (1 << mod2), 0, (1 << num), 0, 0, 0);
+ seat->xkb_state_empty_with_numlock, (1 << mod2), 0, (1 << num), 0, 0, 0);
}
}
- input->xkb_keymap_mod_index.shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
- input->xkb_keymap_mod_index.caps = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
- input->xkb_keymap_mod_index.ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
- input->xkb_keymap_mod_index.alt = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_ALT);
- input->xkb_keymap_mod_index.num = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
- input->xkb_keymap_mod_index.logo = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_LOGO);
+ for (int i = 0; i < MOD_INDEX_NUM; i++) {
+ const GWL_ModifierInfo &mod_info = g_modifier_info_table[i];
+ seat->xkb_keymap_mod_index[i] = xkb_keymap_mod_get_index(keymap, mod_info.xkb_id);
+ }
+
+ keyboard_depressed_state_reset(seat);
xkb_keymap_unref(keymap);
}
@@ -2134,92 +2276,65 @@ static void keyboard_handle_keymap(void *data,
/**
* Enter event.
*
- * Notification that this seat's keyboard focus is on a certain
- * surface.
+ * Notification that this seat's keyboard focus is on a certain wl_surface.
*/
static void keyboard_handle_enter(void *data,
struct wl_keyboard * /*wl_keyboard*/,
const uint32_t serial,
- struct wl_surface *surface,
+ struct wl_surface *wl_surface,
struct wl_array *keys)
{
- if (!ghost_wl_surface_own(surface)) {
+ if (!ghost_wl_surface_own(wl_surface)) {
CLOG_INFO(LOG, 2, "enter (skipped)");
return;
}
CLOG_INFO(LOG, 2, "enter");
- input_t *input = static_cast<input_t *>(data);
- input->keyboard.serial = serial;
- input->keyboard.wl_surface = surface;
-
- if (keys->size != 0) {
- /* If there are any keys held when activating the window,
- * modifiers will be compared against the input state,
- * only enabling modifiers that were previously disabled. */
-
- const xkb_mod_mask_t state = xkb_state_serialize_mods(input->xkb_state, XKB_STATE_MODS_ALL);
- uint32_t *key;
- WL_ARRAY_FOR_EACH (key, keys) {
- const xkb_keycode_t key_code = *key + EVDEV_OFFSET;
- const xkb_keysym_t sym = xkb_state_key_get_one_sym(input->xkb_state, key_code);
- GHOST_TKey gkey = GHOST_kKeyUnknown;
-
-#define MOD_TEST(state, mod) ((mod != XKB_MOD_INVALID) && (state & (1 << mod)))
-#define MOD_TEST_CASE(xkb_key, ghost_key, mod_index) \
- case xkb_key: \
- if (!MOD_TEST(state, input->xkb_keymap_mod_index.mod_index)) { \
- gkey = ghost_key; \
- } \
- break
-
- switch (sym) {
- MOD_TEST_CASE(XKB_KEY_Shift_L, GHOST_kKeyLeftShift, shift);
- MOD_TEST_CASE(XKB_KEY_Shift_R, GHOST_kKeyRightShift, shift);
- MOD_TEST_CASE(XKB_KEY_Control_L, GHOST_kKeyLeftControl, ctrl);
- MOD_TEST_CASE(XKB_KEY_Control_R, GHOST_kKeyRightControl, ctrl);
- MOD_TEST_CASE(XKB_KEY_Alt_L, GHOST_kKeyLeftAlt, alt);
- MOD_TEST_CASE(XKB_KEY_Alt_R, GHOST_kKeyRightAlt, alt);
- MOD_TEST_CASE(XKB_KEY_Super_L, GHOST_kKeyOS, logo);
- MOD_TEST_CASE(XKB_KEY_Super_R, GHOST_kKeyOS, logo);
- }
-
-#undef MOD_TEST
-#undef MOD_TEST_CASE
-
- if (gkey != GHOST_kKeyUnknown) {
- GHOST_IWindow *win = ghost_wl_surface_user_data(surface);
- GHOST_SystemWayland *system = input->system;
- input->system->pushEvent(
- new GHOST_EventKey(system->getMilliSeconds(), GHOST_kEventKeyDown, win, gkey, false));
- }
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->keyboard.serial = serial;
+ seat->keyboard.wl_surface = wl_surface;
+
+ /* If there are any keys held when activating the window,
+ * modifiers will be compared against the seat state,
+ * only enabling modifiers that were previously disabled. */
+ WGL_KeyboardDepressedState key_depressed_prev = seat->key_depressed;
+ keyboard_depressed_state_reset(seat);
+
+ uint32_t *key;
+ WL_ARRAY_FOR_EACH (key, keys) {
+ const xkb_keycode_t key_code = *key + EVDEV_OFFSET;
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym(seat->xkb_state, key_code);
+ const GHOST_TKey gkey = xkb_map_gkey_or_scan_code(sym, *key);
+ if (gkey != GHOST_kKeyUnknown) {
+ keyboard_depressed_state_key_event(seat, gkey, GHOST_kEventKeyDown);
}
}
+
+ keyboard_depressed_state_push_events_from_change(seat, key_depressed_prev);
}
/**
* Leave event.
*
- * Notification that this seat's keyboard focus is no longer on a
- * certain surface.
+ * Notification that this seat's keyboard focus is no longer on a certain wl_surface.
*/
static void keyboard_handle_leave(void *data,
struct wl_keyboard * /*wl_keyboard*/,
const uint32_t /*serial*/,
- struct wl_surface *surface)
+ struct wl_surface *wl_surface)
{
- if (!(surface && ghost_wl_surface_own(surface))) {
+ if (!(wl_surface && ghost_wl_surface_own(wl_surface))) {
CLOG_INFO(LOG, 2, "leave (skipped)");
return;
}
CLOG_INFO(LOG, 2, "leave");
- input_t *input = static_cast<input_t *>(data);
- input->keyboard.wl_surface = nullptr;
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->keyboard.wl_surface = nullptr;
/* Losing focus must stop repeating text. */
- if (input->key_repeat.timer) {
- keyboard_handle_key_repeat_cancel(input);
+ if (seat->key_repeat.timer) {
+ keyboard_handle_key_repeat_cancel(seat);
}
}
@@ -2253,12 +2368,12 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(
return sym;
}
-static void keyboard_handle_key_repeat_cancel(input_t *input)
+static void keyboard_handle_key_repeat_cancel(GWL_Seat *seat)
{
- GHOST_ASSERT(input->key_repeat.timer != nullptr, "Caller much check for timer");
- delete static_cast<key_repeat_payload_t *>(input->key_repeat.timer->getUserData());
- input->system->removeTimer(input->key_repeat.timer);
- input->key_repeat.timer = nullptr;
+ GHOST_ASSERT(seat->key_repeat.timer != nullptr, "Caller much check for timer");
+ delete static_cast<GWL_KeyRepeatPlayload *>(seat->key_repeat.timer->getUserData());
+ seat->system->removeTimer(seat->key_repeat.timer);
+ seat->key_repeat.timer = nullptr;
}
/**
@@ -2266,17 +2381,17 @@ static void keyboard_handle_key_repeat_cancel(input_t *input)
* \param use_delay: When false, use the interval
* (prevents pause when the setting changes while the key is held).
*/
-static void keyboard_handle_key_repeat_reset(input_t *input, const bool use_delay)
+static void keyboard_handle_key_repeat_reset(GWL_Seat *seat, const bool use_delay)
{
- GHOST_ASSERT(input->key_repeat.timer != nullptr, "Caller much check for timer");
- GHOST_SystemWayland *system = input->system;
- GHOST_ITimerTask *timer = input->key_repeat.timer;
+ GHOST_ASSERT(seat->key_repeat.timer != nullptr, "Caller much check for timer");
+ GHOST_SystemWayland *system = seat->system;
+ GHOST_ITimerTask *timer = seat->key_repeat.timer;
GHOST_TimerProcPtr key_repeat_fn = timer->getTimerProc();
- GHOST_TUserDataPtr payload = input->key_repeat.timer->getUserData();
- input->system->removeTimer(input->key_repeat.timer);
- const uint64_t time_step = 1000 / input->key_repeat.rate;
- const uint64_t time_start = use_delay ? input->key_repeat.delay : time_step;
- input->key_repeat.timer = system->installTimer(time_start, time_step, key_repeat_fn, payload);
+ GHOST_TUserDataPtr payload = seat->key_repeat.timer->getUserData();
+ seat->system->removeTimer(seat->key_repeat.timer);
+ const uint64_t time_step = 1000 / seat->key_repeat.rate;
+ const uint64_t time_start = use_delay ? seat->key_repeat.delay : time_step;
+ seat->key_repeat.timer = system->installTimer(time_start, time_step, key_repeat_fn, payload);
}
static void keyboard_handle_key(void *data,
@@ -2286,11 +2401,11 @@ static void keyboard_handle_key(void *data,
const uint32_t key,
const uint32_t state)
{
- input_t *input = static_cast<input_t *>(data);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
const xkb_keycode_t key_code = key + EVDEV_OFFSET;
const xkb_keysym_t sym = xkb_state_key_get_one_sym_without_modifiers(
- input->xkb_state_empty, input->xkb_state_empty_with_numlock, key_code);
+ seat->xkb_state_empty, seat->xkb_state_empty_with_numlock, key_code);
if (sym == XKB_KEY_NoSymbol) {
CLOG_INFO(LOG, 2, "key (no symbol, skipped)");
return;
@@ -2307,15 +2422,15 @@ static void keyboard_handle_key(void *data,
break;
}
- struct key_repeat_payload_t *key_repeat_payload = nullptr;
+ struct GWL_KeyRepeatPlayload *key_repeat_payload = nullptr;
/* Delete previous timer. */
- if (input->key_repeat.timer) {
+ if (seat->key_repeat.timer) {
enum { NOP = 1, RESET, CANCEL } timer_action = NOP;
- key_repeat_payload = static_cast<key_repeat_payload_t *>(
- input->key_repeat.timer->getUserData());
+ key_repeat_payload = static_cast<GWL_KeyRepeatPlayload *>(
+ seat->key_repeat.timer->getUserData());
- if (input->key_repeat.rate == 0) {
+ if (seat->key_repeat.rate == 0) {
/* Repeat was disabled (unlikely but possible). */
timer_action = CANCEL;
}
@@ -2323,7 +2438,7 @@ static void keyboard_handle_key(void *data,
/* Releasing the key that was held always cancels. */
timer_action = CANCEL;
}
- else if (xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key_code)) {
+ else if (xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb_state), key_code)) {
if (etype == GHOST_kEventKeyDown) {
/* Any other key-down always cancels (and may start it's own repeat timer). */
timer_action = CANCEL;
@@ -2346,16 +2461,16 @@ static void keyboard_handle_key(void *data,
}
case RESET: {
/* The payload will be added again. */
- input->system->removeTimer(input->key_repeat.timer);
- input->key_repeat.timer = nullptr;
+ seat->system->removeTimer(seat->key_repeat.timer);
+ seat->key_repeat.timer = nullptr;
break;
}
case CANCEL: {
delete key_repeat_payload;
key_repeat_payload = nullptr;
- input->system->removeTimer(input->key_repeat.timer);
- input->key_repeat.timer = nullptr;
+ seat->system->removeTimer(seat->key_repeat.timer);
+ seat->key_repeat.timer = nullptr;
break;
}
}
@@ -2364,24 +2479,26 @@ static void keyboard_handle_key(void *data,
const GHOST_TKey gkey = xkb_map_gkey_or_scan_code(sym, key);
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
if (etype == GHOST_kEventKeyDown) {
- xkb_state_key_get_utf8(input->xkb_state, key_code, utf8_buf, sizeof(utf8_buf));
+ xkb_state_key_get_utf8(seat->xkb_state, key_code, utf8_buf, sizeof(utf8_buf));
}
- input->data_source_serial = serial;
+ seat->data_source_serial = serial;
+
+ keyboard_depressed_state_key_event(seat, gkey, etype);
- if (wl_surface *focus_surface = input->keyboard.wl_surface) {
- GHOST_IWindow *win = ghost_wl_surface_user_data(focus_surface);
- input->system->pushEvent(
- new GHOST_EventKey(input->system->getMilliSeconds(), etype, win, gkey, false, utf8_buf));
+ if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface) {
+ GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus);
+ seat->system->pushEvent(
+ new GHOST_EventKey(seat->system->getMilliSeconds(), etype, win, gkey, false, utf8_buf));
}
/* An existing payload means the key repeat timer is reset and will be added again. */
if (key_repeat_payload == nullptr) {
/* Start timer for repeating key, if applicable. */
- if ((input->key_repeat.rate > 0) && (etype == GHOST_kEventKeyDown) &&
- xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key_code)) {
- key_repeat_payload = new key_repeat_payload_t({
- .input = input,
+ if ((seat->key_repeat.rate > 0) && (etype == GHOST_kEventKeyDown) &&
+ xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb_state), key_code)) {
+ key_repeat_payload = new GWL_KeyRepeatPlayload({
+ .seat = seat,
.key_code = key_code,
.key_data = {.gkey = gkey},
});
@@ -2390,16 +2507,16 @@ static void keyboard_handle_key(void *data,
if (key_repeat_payload) {
auto key_repeat_fn = [](GHOST_ITimerTask *task, uint64_t /*time*/) {
- struct key_repeat_payload_t *payload = static_cast<key_repeat_payload_t *>(
+ struct GWL_KeyRepeatPlayload *payload = static_cast<GWL_KeyRepeatPlayload *>(
task->getUserData());
- input_t *input = payload->input;
- if (wl_surface *focus_surface = input->keyboard.wl_surface) {
- GHOST_IWindow *win = ghost_wl_surface_user_data(focus_surface);
- GHOST_SystemWayland *system = input->system;
+ GWL_Seat *seat = payload->seat;
+ if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface) {
+ GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus);
+ GHOST_SystemWayland *system = seat->system;
/* Calculate this value every time in case modifier keys are pressed. */
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
- xkb_state_key_get_utf8(input->xkb_state, payload->key_code, utf8_buf, sizeof(utf8_buf));
+ xkb_state_key_get_utf8(seat->xkb_state, payload->key_code, utf8_buf, sizeof(utf8_buf));
system->pushEvent(new GHOST_EventKey(system->getMilliSeconds(),
GHOST_kEventKeyDown,
win,
@@ -2408,8 +2525,8 @@ static void keyboard_handle_key(void *data,
utf8_buf));
}
};
- input->key_repeat.timer = input->system->installTimer(
- input->key_repeat.delay, 1000 / input->key_repeat.rate, key_repeat_fn, key_repeat_payload);
+ seat->key_repeat.timer = seat->system->installTimer(
+ seat->key_repeat.delay, 1000 / seat->key_repeat.rate, key_repeat_fn, key_repeat_payload);
}
}
@@ -2429,13 +2546,13 @@ static void keyboard_handle_modifiers(void *data,
mods_locked,
group);
- input_t *input = static_cast<input_t *>(data);
- xkb_state_update_mask(input->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ xkb_state_update_mask(seat->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
/* A modifier changed so reset the timer,
* see comment in #keyboard_handle_key regarding this behavior. */
- if (input->key_repeat.timer) {
- keyboard_handle_key_repeat_reset(input, true);
+ if (seat->key_repeat.timer) {
+ keyboard_handle_key_repeat_reset(seat, true);
}
}
@@ -2446,13 +2563,13 @@ static void keyboard_repeat_handle_info(void *data,
{
CLOG_INFO(LOG, 2, "info (rate=%d, delay=%d)", rate, delay);
- input_t *input = static_cast<input_t *>(data);
- input->key_repeat.rate = rate;
- input->key_repeat.delay = delay;
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->key_repeat.rate = rate;
+ seat->key_repeat.delay = delay;
/* Unlikely possible this setting changes while repeating. */
- if (input->key_repeat.timer) {
- keyboard_handle_key_repeat_reset(input, false);
+ if (seat->key_repeat.timer) {
+ keyboard_handle_key_repeat_reset(seat, false);
}
}
@@ -2487,35 +2604,35 @@ static void seat_handle_capabilities(void *data,
(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0,
(capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0);
- input_t *input = static_cast<input_t *>(data);
- input->wl_pointer = nullptr;
- input->wl_keyboard = nullptr;
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->wl_pointer = nullptr;
+ seat->wl_keyboard = nullptr;
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
- input->wl_pointer = wl_seat_get_pointer(wl_seat);
- input->cursor.wl_surface = wl_compositor_create_surface(input->system->compositor());
- input->cursor.visible = true;
- input->cursor.wl_buffer = nullptr;
- if (!get_cursor_settings(input->cursor.theme_name, input->cursor.size)) {
- input->cursor.theme_name = std::string();
- input->cursor.size = default_cursor_size;
+ seat->wl_pointer = wl_seat_get_pointer(wl_seat);
+ seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->compositor());
+ seat->cursor.visible = true;
+ seat->cursor.wl_buffer = nullptr;
+ if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.size)) {
+ seat->cursor.theme_name = std::string();
+ seat->cursor.size = default_cursor_size;
}
- wl_pointer_add_listener(input->wl_pointer, &pointer_listener, data);
+ wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data);
- wl_surface_add_listener(input->cursor.wl_surface, &cursor_surface_listener, data);
- ghost_wl_surface_tag_cursor_pointer(input->cursor.wl_surface);
+ wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, data);
+ ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface);
}
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
- input->wl_keyboard = wl_seat_get_keyboard(wl_seat);
- wl_keyboard_add_listener(input->wl_keyboard, &keyboard_listener, data);
+ seat->wl_keyboard = wl_seat_get_keyboard(wl_seat);
+ wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data);
}
}
static void seat_handle_name(void *data, struct wl_seat * /*wl_seat*/, const char *name)
{
CLOG_INFO(LOG, 2, "name (name=\"%s\")", name);
- static_cast<input_t *>(data)->name = std::string(name);
+ static_cast<GWL_Seat *>(data)->name = std::string(name);
}
static const struct wl_seat_listener seat_listener = {
@@ -2541,7 +2658,7 @@ static void xdg_output_handle_logical_position(void *data,
{
CLOG_INFO(LOG, 2, "logical_position [%d, %d]", x, y);
- output_t *output = static_cast<output_t *>(data);
+ GWL_Output *output = static_cast<GWL_Output *>(data);
output->position_logical[0] = x;
output->position_logical[1] = y;
output->has_position_logical = true;
@@ -2554,7 +2671,7 @@ static void xdg_output_handle_logical_size(void *data,
{
CLOG_INFO(LOG, 2, "logical_size [%d, %d]", width, height);
- output_t *output = static_cast<output_t *>(data);
+ GWL_Output *output = static_cast<GWL_Output *>(data);
if (output->size_logical[0] != 0 && output->size_logical[1] != 0) {
/* Original comment from SDL. */
/* FIXME(@flibit): GNOME has a bug where the logical size does not account for
@@ -2586,7 +2703,7 @@ static void xdg_output_handle_done(void *data, struct zxdg_output_v1 * /*xdg_out
CLOG_INFO(LOG, 2, "done");
/* NOTE: `xdg-output.done` events are deprecated and only apply below version 3 of the protocol.
* `wl-output.done` event will be emitted in version 3 or higher. */
- output_t *output = static_cast<output_t *>(data);
+ GWL_Output *output = static_cast<GWL_Output *>(data);
if (zxdg_output_v1_get_version(output->xdg_output) < 3) {
output_handle_done(data, output->wl_output);
}
@@ -2645,7 +2762,7 @@ static void output_handle_geometry(void *data,
physical_width,
physical_height);
- output_t *output = static_cast<output_t *>(data);
+ GWL_Output *output = static_cast<GWL_Output *>(data);
output->transform = transform;
output->make = std::string(make);
output->model = std::string(model);
@@ -2666,7 +2783,7 @@ static void output_handle_mode(void *data,
}
CLOG_INFO(LOG, 2, "mode (size=[%d, %d], flags=%u)", width, height, flags);
- output_t *output = static_cast<output_t *>(data);
+ GWL_Output *output = static_cast<GWL_Output *>(data);
output->size_native[0] = width;
output->size_native[1] = height;
@@ -2690,7 +2807,7 @@ static void output_handle_done(void *data, struct wl_output * /*wl_output*/)
{
CLOG_INFO(LOG, 2, "done");
- output_t *output = static_cast<output_t *>(data);
+ GWL_Output *output = static_cast<GWL_Output *>(data);
int32_t size_native[2];
if (output->transform & WL_OUTPUT_TRANSFORM_90) {
size_native[0] = output->size_native[1];
@@ -2718,14 +2835,12 @@ static void output_handle_done(void *data, struct wl_output * /*wl_output*/)
static void output_handle_scale(void *data, struct wl_output * /*wl_output*/, const int32_t factor)
{
CLOG_INFO(LOG, 2, "scale");
- static_cast<output_t *>(data)->scale = factor;
+ static_cast<GWL_Output *>(data)->scale = factor;
if (window_manager) {
for (GHOST_IWindow *iwin : window_manager->getWindows()) {
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
win->outputs_changed_update_scale();
- /* TODO(@campbellbarton): support refreshing the UI when the DPI changes.
- * There are glitches when resizing the monitor which would be nice to solve. */
}
}
}
@@ -2747,7 +2862,7 @@ static const struct wl_output_listener output_listener = {
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
-static CLG_LogRef LOG_WL_XDG_WM_BASE = {"ghost.wl.handle.output"};
+static CLG_LogRef LOG_WL_XDG_WM_BASE = {"ghost.wl.handle.xdg_wm_base"};
# define LOG (&LOG_WL_XDG_WM_BASE)
static void shell_handle_ping(void * /*data*/,
@@ -2815,35 +2930,35 @@ static void global_handle_add(void *data,
/* Log last since it can be noted if the interface was handled or not. */
bool found = true;
- struct display_t *display = static_cast<struct display_t *>(data);
- if (!strcmp(interface, wl_compositor_interface.name)) {
+ struct GWL_Display *display = static_cast<struct GWL_Display *>(data);
+ if (STREQ(interface, wl_compositor_interface.name)) {
display->compositor = static_cast<wl_compositor *>(
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
}
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
/* Pass. */
#else
- else if (!strcmp(interface, xdg_wm_base_interface.name)) {
+ else if (STREQ(interface, xdg_wm_base_interface.name)) {
display->xdg_shell = static_cast<xdg_wm_base *>(
wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr);
}
- else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)) {
+ else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) {
display->xdg_decoration_manager = static_cast<zxdg_decoration_manager_v1 *>(
wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1));
}
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
- else if (!strcmp(interface, zxdg_output_manager_v1_interface.name)) {
+ else if (STREQ(interface, zxdg_output_manager_v1_interface.name)) {
display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2));
- for (output_t *output : display->outputs) {
+ for (GWL_Output *output : display->outputs) {
output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager,
output->wl_output);
zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
}
}
- else if (!strcmp(interface, wl_output_interface.name)) {
- output_t *output = new output_t;
+ else if (STREQ(interface, wl_output_interface.name)) {
+ GWL_Output *output = new GWL_Output;
output->wl_output = static_cast<wl_output *>(
wl_registry_bind(wl_registry, name, &wl_output_interface, 2));
ghost_wl_output_tag(output->wl_output);
@@ -2858,33 +2973,33 @@ static void global_handle_add(void *data,
zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
}
}
- else if (!strcmp(interface, wl_seat_interface.name)) {
- input_t *input = new input_t;
- input->system = display->system;
- input->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- input->data_source = new data_source_t;
- input->wl_seat = static_cast<wl_seat *>(
+ else if (STREQ(interface, wl_seat_interface.name)) {
+ GWL_Seat *seat = new GWL_Seat;
+ seat->system = display->system;
+ seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ seat->data_source = new GWL_DataSource;
+ seat->wl_seat = static_cast<wl_seat *>(
wl_registry_bind(wl_registry, name, &wl_seat_interface, 5));
- display->inputs.push_back(input);
- wl_seat_add_listener(input->wl_seat, &seat_listener, input);
+ display->seats.push_back(seat);
+ wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
}
- else if (!strcmp(interface, wl_shm_interface.name)) {
+ else if (STREQ(interface, wl_shm_interface.name)) {
display->shm = static_cast<wl_shm *>(
wl_registry_bind(wl_registry, name, &wl_shm_interface, 1));
}
- else if (!strcmp(interface, wl_data_device_manager_interface.name)) {
+ else if (STREQ(interface, wl_data_device_manager_interface.name)) {
display->data_device_manager = static_cast<wl_data_device_manager *>(
wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3));
}
- else if (!strcmp(interface, zwp_tablet_manager_v2_interface.name)) {
+ else if (STREQ(interface, zwp_tablet_manager_v2_interface.name)) {
display->tablet_manager = static_cast<zwp_tablet_manager_v2 *>(
wl_registry_bind(wl_registry, name, &zwp_tablet_manager_v2_interface, 1));
}
- else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) {
+ else if (STREQ(interface, zwp_relative_pointer_manager_v1_interface.name)) {
display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(
wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1));
}
- else if (!strcmp(interface, zwp_pointer_constraints_v1_interface.name)) {
+ else if (STREQ(interface, zwp_pointer_constraints_v1_interface.name)) {
display->pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>(
wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1));
}
@@ -2932,7 +3047,7 @@ static const struct wl_registry_listener registry_listener = {
* WAYLAND specific implementation of the #GHOST_System interface.
* \{ */
-GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t)
+GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display)
{
wl_log_set_handler_client(ghost_wayland_log_handler);
@@ -2968,18 +3083,17 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t)
/* Register data device per seat for IPC between Wayland clients. */
if (d->data_device_manager) {
- for (input_t *input : d->inputs) {
- input->data_device = wl_data_device_manager_get_data_device(d->data_device_manager,
- input->wl_seat);
- wl_data_device_add_listener(input->data_device, &data_device_listener, input);
+ for (GWL_Seat *seat : d->seats) {
+ seat->data_device = wl_data_device_manager_get_data_device(d->data_device_manager,
+ seat->wl_seat);
+ wl_data_device_add_listener(seat->data_device, &data_device_listener, seat);
}
}
if (d->tablet_manager) {
- for (input_t *input : d->inputs) {
- input->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(d->tablet_manager,
- input->wl_seat);
- zwp_tablet_seat_v2_add_listener(input->tablet_seat, &tablet_seat_listener, input);
+ for (GWL_Seat *seat : d->seats) {
+ seat->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(d->tablet_manager, seat->wl_seat);
+ zwp_tablet_seat_v2_add_listener(seat->tablet_seat, &tablet_seat_listener, seat);
}
}
}
@@ -2989,9 +3103,36 @@ GHOST_SystemWayland::~GHOST_SystemWayland()
display_destroy(d);
}
+GHOST_TSuccess GHOST_SystemWayland::init()
+{
+ GHOST_TSuccess success = GHOST_System::init();
+
+ if (success) {
+#ifdef WITH_INPUT_NDOF
+ m_ndofManager = new GHOST_NDOFManagerUnix(*this);
+#endif
+ return GHOST_kSuccess;
+ }
+
+ return GHOST_kFailure;
+}
+
bool GHOST_SystemWayland::processEvents(bool waitForEvent)
{
- const bool fired = getTimerManager()->fireTimers(getMilliSeconds());
+ bool any_processed = false;
+
+ if (getTimerManager()->fireTimers(getMilliSeconds())) {
+ any_processed = true;
+ }
+
+#ifdef WITH_INPUT_NDOF
+ if (static_cast<GHOST_NDOFManagerUnix *>(m_ndofManager)->processEvents()) {
+ /* As NDOF bypasses WAYLAND event handling,
+ * never wait for an event when an NDOF event was found. */
+ waitForEvent = false;
+ any_processed = true;
+ }
+#endif /* WITH_INPUT_NDOF */
if (waitForEvent) {
wl_display_dispatch(d->display);
@@ -3000,65 +3141,79 @@ bool GHOST_SystemWayland::processEvents(bool waitForEvent)
wl_display_roundtrip(d->display);
}
- return fired || (getEventManager()->getNumEvents() > 0);
+ if ((getEventManager()->getNumEvents() > 0)) {
+ any_processed = true;
+ }
+
+ return any_processed;
}
-int GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
+bool GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
{
- return 0;
+ return false;
}
GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- input_t *input = d->inputs[0];
-
- bool val;
-
- /* NOTE: XKB doesn't differentiate between left/right modifiers
- * for it's internal modifier state storage. */
- const xkb_mod_mask_t state = xkb_state_serialize_mods(input->xkb_state, XKB_STATE_MODS_ALL);
+ GWL_Seat *seat = d->seats[0];
-#define MOD_TEST(state, mod) ((mod != XKB_MOD_INVALID) && (state & (1 << mod)))
+ const xkb_mod_mask_t state = xkb_state_serialize_mods(seat->xkb_state, XKB_STATE_MODS_DEPRESSED);
- val = MOD_TEST(state, input->xkb_keymap_mod_index.shift);
- keys.set(GHOST_kModifierKeyLeftShift, val);
- keys.set(GHOST_kModifierKeyRightShift, val);
-
- val = MOD_TEST(state, input->xkb_keymap_mod_index.alt);
- keys.set(GHOST_kModifierKeyLeftAlt, val);
- keys.set(GHOST_kModifierKeyRightAlt, val);
-
- val = MOD_TEST(state, input->xkb_keymap_mod_index.ctrl);
- keys.set(GHOST_kModifierKeyLeftControl, val);
- keys.set(GHOST_kModifierKeyRightControl, val);
-
- val = MOD_TEST(state, input->xkb_keymap_mod_index.logo);
- keys.set(GHOST_kModifierKeyOS, val);
-
- val = MOD_TEST(state, input->xkb_keymap_mod_index.num);
- keys.set(GHOST_kModifierKeyNum, val);
+ /* Use local #WGL_KeyboardDepressedState to check which key is pressed.
+ * Use XKB as the source of truth, if there is any discrepancy. */
+ for (int i = 0; i < MOD_INDEX_NUM; i++) {
+ if (UNLIKELY(seat->xkb_keymap_mod_index[i] == XKB_MOD_INVALID)) {
+ continue;
+ }
+ const GWL_ModifierInfo &mod_info = g_modifier_info_table[i];
+ const bool val = (state & (1 << seat->xkb_keymap_mod_index[i])) != 0;
+ bool val_l = seat->key_depressed.mods[GHOST_KEY_MODIFIER_TO_INDEX(mod_info.key_l)] > 0;
+ bool val_r = seat->key_depressed.mods[GHOST_KEY_MODIFIER_TO_INDEX(mod_info.key_r)] > 0;
+
+ /* This shouldn't be needed, but guard against any possibility of modifiers being stuck.
+ * Warn so if this happens it can be investigated. */
+ if (val) {
+ if (UNLIKELY(!(val_l || val_r))) {
+ CLOG_WARN(&LOG_WL_KEYBOARD_DEPRESSED_STATE,
+ "modifier (%s) state is inconsistent (held keys do not match XKB)",
+ mod_info.display_name);
+ /* Picking the left is arbitrary. */
+ val_l = true;
+ }
+ }
+ else {
+ if (UNLIKELY(val_l || val_r)) {
+ CLOG_WARN(&LOG_WL_KEYBOARD_DEPRESSED_STATE,
+ "modifier (%s) state is inconsistent (released keys do not match XKB)",
+ mod_info.display_name);
+ val_l = false;
+ val_r = false;
+ }
+ }
-#undef MOD_TEST
+ keys.set(mod_info.mod_l, val_l);
+ keys.set(mod_info.mod_r, val_r);
+ }
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- input_t *input = d->inputs[0];
- input_state_pointer_t *input_state = input_state_pointer_active(input);
- if (!input_state) {
+ GWL_Seat *seat = d->seats[0];
+ GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat);
+ if (!seat_state_pointer) {
return GHOST_kFailure;
}
- buttons = input_state->buttons;
+ buttons = seat_state_pointer->buttons;
return GHOST_kSuccess;
}
@@ -3071,15 +3226,15 @@ char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const
void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const
{
- if (UNLIKELY(!d->data_device_manager || d->inputs.empty())) {
+ if (UNLIKELY(!d->data_device_manager || d->seats.empty())) {
return;
}
- input_t *input = d->inputs[0];
+ GWL_Seat *seat = d->seats[0];
- std::lock_guard lock{input->data_source_mutex};
+ std::lock_guard lock{seat->data_source_mutex};
- data_source_t *data_source = input->data_source;
+ GWL_DataSource *data_source = seat->data_source;
/* Copy buffer. */
free(data_source->buffer_out);
@@ -3089,15 +3244,15 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c
data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager);
- wl_data_source_add_listener(data_source->data_source, &data_source_listener, input);
+ wl_data_source_add_listener(data_source->data_source, &data_source_listener, seat);
for (const std::string &type : mime_send) {
wl_data_source_offer(data_source->data_source, type.c_str());
}
- if (input->data_device) {
+ if (seat->data_device) {
wl_data_device_set_selection(
- input->data_device, data_source->data_source, input->data_source_serial);
+ seat->data_device, data_source->data_source, seat->data_source_serial);
}
}
@@ -3107,18 +3262,18 @@ uint8_t GHOST_SystemWayland::getNumDisplays() const
}
static GHOST_TSuccess getCursorPositionClientRelative_impl(
- const input_state_pointer_t *input_state,
+ const GWL_SeatStatePointer *seat_state_pointer,
const GHOST_WindowWayland *win,
int32_t &x,
int32_t &y)
{
const wl_fixed_t scale = win->scale();
- x = wl_fixed_to_int(scale * input_state->xy[0]);
- y = wl_fixed_to_int(scale * input_state->xy[1]);
+ x = wl_fixed_to_int(scale * seat_state_pointer->xy[0]);
+ y = wl_fixed_to_int(scale * seat_state_pointer->xy[1]);
return GHOST_kSuccess;
}
-static GHOST_TSuccess setCursorPositionClientRelative_impl(input_t *input,
+static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat,
GHOST_WindowWayland *win,
const int32_t x,
const int32_t y)
@@ -3126,7 +3281,7 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(input_t *input,
/* NOTE: WAYLAND doesn't support warping the cursor.
* However when grab is enabled, we already simulate a cursor location
* so that can be set to a new location. */
- if (!input->relative_pointer) {
+ if (!seat->relative_pointer) {
return GHOST_kFailure;
}
const wl_fixed_t scale = win->scale();
@@ -3136,7 +3291,7 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(input_t *input,
};
/* As the cursor was "warped" generate an event at the new location. */
- relative_pointer_handle_relative_motion_impl(input, win, xy_next);
+ relative_pointer_handle_relative_motion_impl(seat, win, xy_next);
return GHOST_kSuccess;
}
@@ -3145,60 +3300,60 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPositionClientRelative(const GHOST_
int32_t &x,
int32_t &y) const
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- input_t *input = d->inputs[0];
- input_state_pointer_t *input_state = input_state_pointer_active(input);
- if (!input_state || !input_state->wl_surface) {
+ GWL_Seat *seat = d->seats[0];
+ GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat);
+ if (!seat_state_pointer || !seat_state_pointer->wl_surface) {
return GHOST_kFailure;
}
const GHOST_WindowWayland *win = static_cast<const GHOST_WindowWayland *>(window);
- return getCursorPositionClientRelative_impl(input_state, win, x, y);
+ return getCursorPositionClientRelative_impl(seat_state_pointer, win, x, y);
}
GHOST_TSuccess GHOST_SystemWayland::setCursorPositionClientRelative(GHOST_IWindow *window,
const int32_t x,
const int32_t y)
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- input_t *input = d->inputs[0];
+ GWL_Seat *seat = d->seats[0];
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(window);
- return setCursorPositionClientRelative_impl(input, win, x, y);
+ return setCursorPositionClientRelative_impl(seat, win, x, y);
}
GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- input_t *input = d->inputs[0];
- input_state_pointer_t *input_state = input_state_pointer_active(input);
- if (!input_state) {
+ GWL_Seat *seat = d->seats[0];
+ GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat);
+ if (!seat_state_pointer) {
return GHOST_kFailure;
}
- if (wl_surface *focus_surface = input_state->wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- return getCursorPositionClientRelative_impl(input_state, win, x, y);
+ if (wl_surface *wl_surface_focus = seat_state_pointer->wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ return getCursorPositionClientRelative_impl(seat_state_pointer, win, x, y);
}
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(const int32_t x, const int32_t y)
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- input_t *input = d->inputs[0];
+ GWL_Seat *seat = d->seats[0];
/* Intentionally different from `getCursorPosition` which supports both tablet & pointer.
* In the case of setting the cursor location, tablets don't support this. */
- if (wl_surface *focus_surface = input->pointer.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(focus_surface);
- return setCursorPositionClientRelative_impl(input, win, x, y);
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ return setCursorPositionClientRelative_impl(seat, win, x, y);
}
return GHOST_kFailure;
}
@@ -3218,7 +3373,7 @@ void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &hei
int32_t xy_min[2] = {INT32_MAX, INT32_MAX};
int32_t xy_max[2] = {INT32_MIN, INT32_MIN};
- for (const output_t *output : d->outputs) {
+ for (const GWL_Output *output : d->outputs) {
int32_t xy[2] = {0, 0};
if (output->has_position_logical) {
xy[0] = output->position_logical[0];
@@ -3363,32 +3518,32 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
* Show the buffer defined by #cursor_buffer_set without changing anything else,
* so #cursor_buffer_hide can be used to display it again.
*
- * The caller is responsible for setting `input->cursor.visible`.
+ * The caller is responsible for setting `seat->cursor.visible`.
*/
-static void cursor_buffer_show(const input_t *input)
+static void cursor_buffer_show(const GWL_Seat *seat)
{
- const cursor_t *c = &input->cursor;
+ const GWL_Cursor *c = &seat->cursor;
- if (input->wl_pointer) {
- const int scale = c->is_custom ? c->custom_scale : input->pointer.theme_scale;
+ if (seat->wl_pointer) {
+ const int scale = c->is_custom ? c->custom_scale : seat->pointer.theme_scale;
const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
- if (input->wl_pointer) {
+ if (seat->wl_pointer) {
wl_pointer_set_cursor(
- input->wl_pointer, input->pointer.serial, c->wl_surface, hotspot_x, hotspot_y);
+ seat->wl_pointer, seat->pointer.serial, c->wl_surface, hotspot_x, hotspot_y);
}
}
- if (!input->tablet_tools.empty()) {
- const int scale = c->is_custom ? c->custom_scale : input->tablet.theme_scale;
+ if (!seat->tablet_tools.empty()) {
+ const int scale = c->is_custom ? c->custom_scale : seat->tablet.theme_scale;
const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
- for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) {
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(
+ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
- input->tablet.serial,
- tool_input->cursor_surface,
+ seat->tablet.serial,
+ tablet_tool->wl_surface_cursor,
hotspot_x,
hotspot_y);
}
@@ -3399,13 +3554,13 @@ static void cursor_buffer_show(const input_t *input)
* Hide the buffer defined by #cursor_buffer_set without changing anything else,
* so #cursor_buffer_show can be used to display it again.
*
- * The caller is responsible for setting `input->cursor.visible`.
+ * The caller is responsible for setting `seat->cursor.visible`.
*/
-static void cursor_buffer_hide(const input_t *input)
+static void cursor_buffer_hide(const GWL_Seat *seat)
{
- wl_pointer_set_cursor(input->wl_pointer, input->pointer.serial, nullptr, 0, 0);
- for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) {
- zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, input->tablet.serial, nullptr, 0, 0);
+ wl_pointer_set_cursor(seat->wl_pointer, seat->pointer.serial, nullptr, 0, 0);
+ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
+ zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, seat->tablet.serial, nullptr, 0, 0);
}
}
@@ -3426,12 +3581,12 @@ static int cursor_buffer_compatible_scale_from_image(const struct wl_cursor_imag
return scale;
}
-static void cursor_buffer_set_surface_impl(const input_t *input,
+static void cursor_buffer_set_surface_impl(const GWL_Seat *seat,
wl_buffer *buffer,
struct wl_surface *wl_surface,
const int scale)
{
- const wl_cursor_image *wl_image = &input->cursor.wl_image;
+ const wl_cursor_image *wl_image = &seat->cursor.wl_image;
const int32_t image_size_x = int32_t(wl_image->width);
const int32_t image_size_y = int32_t(wl_image->height);
GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0,
@@ -3443,40 +3598,40 @@ static void cursor_buffer_set_surface_impl(const input_t *input,
wl_surface_commit(wl_surface);
}
-static void cursor_buffer_set(const input_t *input, wl_buffer *buffer)
+static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer)
{
- const cursor_t *c = &input->cursor;
- const wl_cursor_image *wl_image = &input->cursor.wl_image;
+ const GWL_Cursor *c = &seat->cursor;
+ const wl_cursor_image *wl_image = &seat->cursor.wl_image;
const bool visible = (c->visible && c->is_hardware);
/* This is a requirement of WAYLAND, when this isn't the case,
* it causes Blender's window to close intermittently. */
- if (input->wl_pointer) {
+ if (seat->wl_pointer) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : input->pointer.theme_scale);
+ wl_image, c->is_custom ? c->custom_scale : seat->pointer.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
- cursor_buffer_set_surface_impl(input, buffer, c->wl_surface, scale);
- wl_pointer_set_cursor(input->wl_pointer,
- input->pointer.serial,
+ cursor_buffer_set_surface_impl(seat, buffer, c->wl_surface, scale);
+ wl_pointer_set_cursor(seat->wl_pointer,
+ seat->pointer.serial,
visible ? c->wl_surface : nullptr,
hotspot_x,
hotspot_y);
}
/* Set the cursor for all tablet tools as well. */
- if (!input->tablet_tools.empty()) {
+ if (!seat->tablet_tools.empty()) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : input->tablet.theme_scale);
+ wl_image, c->is_custom ? c->custom_scale : seat->tablet.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
- for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) {
- tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(
+ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
+ GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
- cursor_buffer_set_surface_impl(input, buffer, tool_input->cursor_surface, scale);
+ cursor_buffer_set_surface_impl(seat, buffer, tablet_tool->wl_surface_cursor, scale);
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
- input->tablet.serial,
- visible ? tool_input->cursor_surface : nullptr,
+ seat->tablet.serial,
+ visible ? tablet_tool->wl_surface_cursor : nullptr,
hotspot_x,
hotspot_y);
}
@@ -3489,12 +3644,12 @@ enum eCursorSetMode {
CURSOR_VISIBLE_ONLY_SHOW,
};
-static void cursor_visible_set(input_t *input,
+static void cursor_visible_set(GWL_Seat *seat,
const bool visible,
const bool is_hardware,
const enum eCursorSetMode set_mode)
{
- cursor_t *cursor = &input->cursor;
+ GWL_Cursor *cursor = &seat->cursor;
const bool was_visible = cursor->is_hardware && cursor->visible;
const bool use_visible = is_hardware && visible;
@@ -3514,12 +3669,12 @@ static void cursor_visible_set(input_t *input,
if (use_visible) {
if (!was_visible) {
- cursor_buffer_show(input);
+ cursor_buffer_show(seat);
}
}
else {
if (was_visible) {
- cursor_buffer_hide(input);
+ cursor_buffer_hide(seat);
}
}
cursor->visible = visible;
@@ -3545,7 +3700,7 @@ static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_
GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor shape)
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
auto cursor_find = cursors.find(shape);
@@ -3553,13 +3708,12 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s
cursors.at(GHOST_kStandardCursorDefault) :
(*cursor_find).second;
- input_t *input = d->inputs[0];
- cursor_t *c = &input->cursor;
+ GWL_Seat *seat = d->seats[0];
+ GWL_Cursor *c = &seat->cursor;
if (!c->wl_theme) {
- /* The cursor surface hasn't entered an output yet. Initialize theme with scale 1. */
- c->wl_theme = wl_cursor_theme_load(
- c->theme_name.c_str(), c->size, d->inputs[0]->system->shm());
+ /* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
+ c->wl_theme = wl_cursor_theme_load(c->theme_name.c_str(), c->size, d->seats[0]->system->shm());
}
wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name);
@@ -3580,7 +3734,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s
c->wl_buffer = buffer;
c->wl_image = *image;
- cursor_buffer_set(input, buffer);
+ cursor_buffer_set(seat, buffer);
return GHOST_kSuccess;
}
@@ -3606,11 +3760,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
const int hotY,
const bool /*canInvertColor*/)
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- cursor_t *cursor = &d->inputs[0]->cursor;
+ GWL_Cursor *cursor = &d->seats[0]->cursor;
if (cursor->custom_data) {
munmap(cursor->custom_data, cursor->custom_data_size);
@@ -3666,14 +3820,14 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
cursor->wl_image.hotspot_x = uint32_t(hotX);
cursor->wl_image.hotspot_y = uint32_t(hotY);
- cursor_buffer_set(d->inputs[0], buffer);
+ cursor_buffer_set(d->seats[0], buffer);
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap)
{
- cursor_t *cursor = &d->inputs[0]->cursor;
+ GWL_Cursor *cursor = &d->seats[0]->cursor;
if (cursor->custom_data == nullptr) {
return GHOST_kFailure;
}
@@ -3694,12 +3848,12 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(const bool visible)
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
- input_t *input = d->inputs[0];
- cursor_visible_set(input, visible, input->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET);
+ GWL_Seat *seat = d->seats[0];
+ cursor_visible_set(seat, visible, seat->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET);
return GHOST_kSuccess;
}
@@ -3718,13 +3872,13 @@ bool GHOST_SystemWayland::supportsWindowPosition()
bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode)
{
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return false;
}
#ifdef USE_GNOME_CONFINE_HACK
- input_t *input = d->inputs[0];
- const bool use_software_confine = input->use_pointer_software_confine;
+ GWL_Seat *seat = d->seats[0];
+ const bool use_software_confine = seat->use_pointer_software_confine;
#else
const bool use_software_confine = false;
#endif
@@ -3734,7 +3888,7 @@ bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCurso
#ifdef USE_GNOME_CONFINE_HACK
static bool setCursorGrab_use_software_confine(const GHOST_TGrabCursorMode mode,
- wl_surface *surface)
+ wl_surface *wl_surface)
{
# ifndef USE_GNOME_CONFINE_HACK_ALWAYS_ON
if (use_gnome_confine_hack == false) {
@@ -3744,7 +3898,7 @@ static bool setCursorGrab_use_software_confine(const GHOST_TGrabCursorMode mode,
if (mode != GHOST_kGrabNormal) {
return false;
}
- const GHOST_WindowWayland *win = ghost_wl_surface_user_data(surface);
+ const GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface);
if (!win) {
return false;
}
@@ -3758,11 +3912,11 @@ static bool setCursorGrab_use_software_confine(const GHOST_TGrabCursorMode mode,
}
#endif
-static input_grab_state_t input_grab_state_from_mode(const GHOST_TGrabCursorMode mode,
- const bool use_software_confine)
+static GWL_SeatStateGrab seat_grab_state_from_mode(const GHOST_TGrabCursorMode mode,
+ const bool use_software_confine)
{
/* Initialize all members. */
- const struct input_grab_state_t grab_state = {
+ const struct GWL_SeatStateGrab grab_state = {
/* Warping happens to require software cursor which also hides. */
.use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine,
.use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false),
@@ -3781,44 +3935,45 @@ static const char *ghost_wl_surface_tag_id = "GHOST-window";
static const char *ghost_wl_surface_cursor_pointer_tag_id = "GHOST-cursor-pointer";
static const char *ghost_wl_surface_cursor_tablet_tag_id = "GHOST-cursor-tablet";
-bool ghost_wl_output_own(const struct wl_output *output)
+bool ghost_wl_output_own(const struct wl_output *wl_output)
{
- return wl_proxy_get_tag((struct wl_proxy *)output) == &ghost_wl_output_tag_id;
+ return wl_proxy_get_tag((struct wl_proxy *)wl_output) == &ghost_wl_output_tag_id;
}
-bool ghost_wl_surface_own(const struct wl_surface *surface)
+bool ghost_wl_surface_own(const struct wl_surface *wl_surface)
{
- return wl_proxy_get_tag((struct wl_proxy *)surface) == &ghost_wl_surface_tag_id;
+ return wl_proxy_get_tag((struct wl_proxy *)wl_surface) == &ghost_wl_surface_tag_id;
}
-bool ghost_wl_surface_own_cursor_pointer(const struct wl_surface *surface)
+bool ghost_wl_surface_own_cursor_pointer(const struct wl_surface *wl_surface)
{
- return wl_proxy_get_tag((struct wl_proxy *)surface) == &ghost_wl_surface_cursor_pointer_tag_id;
+ return wl_proxy_get_tag((struct wl_proxy *)wl_surface) ==
+ &ghost_wl_surface_cursor_pointer_tag_id;
}
-bool ghost_wl_surface_own_cursor_tablet(const struct wl_surface *surface)
+bool ghost_wl_surface_own_cursor_tablet(const struct wl_surface *wl_surface)
{
- return wl_proxy_get_tag((struct wl_proxy *)surface) == &ghost_wl_surface_cursor_tablet_tag_id;
+ return wl_proxy_get_tag((struct wl_proxy *)wl_surface) == &ghost_wl_surface_cursor_tablet_tag_id;
}
-void ghost_wl_output_tag(struct wl_output *output)
+void ghost_wl_output_tag(struct wl_output *wl_output)
{
- wl_proxy_set_tag((struct wl_proxy *)output, &ghost_wl_output_tag_id);
+ wl_proxy_set_tag((struct wl_proxy *)wl_output, &ghost_wl_output_tag_id);
}
-void ghost_wl_surface_tag(struct wl_surface *surface)
+void ghost_wl_surface_tag(struct wl_surface *wl_surface)
{
- wl_proxy_set_tag((struct wl_proxy *)surface, &ghost_wl_surface_tag_id);
+ wl_proxy_set_tag((struct wl_proxy *)wl_surface, &ghost_wl_surface_tag_id);
}
-void ghost_wl_surface_tag_cursor_pointer(struct wl_surface *surface)
+void ghost_wl_surface_tag_cursor_pointer(struct wl_surface *wl_surface)
{
- wl_proxy_set_tag((struct wl_proxy *)surface, &ghost_wl_surface_cursor_pointer_tag_id);
+ wl_proxy_set_tag((struct wl_proxy *)wl_surface, &ghost_wl_surface_cursor_pointer_tag_id);
}
-void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface)
+void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *wl_surface)
{
- wl_proxy_set_tag((struct wl_proxy *)surface, &ghost_wl_surface_cursor_tablet_tag_id);
+ wl_proxy_set_tag((struct wl_proxy *)wl_surface, &ghost_wl_surface_cursor_tablet_tag_id);
}
/** \} */
@@ -3860,7 +4015,7 @@ zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decoration_manager()
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
-const std::vector<output_t *> &GHOST_SystemWayland::outputs() const
+const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs() const
{
return d->outputs;
}
@@ -3876,19 +4031,20 @@ wl_shm *GHOST_SystemWayland::shm() const
/** \name Public WAYLAND Query Access
* \{ */
-struct output_t *ghost_wl_output_user_data(struct wl_output *wl_output)
+struct GWL_Output *ghost_wl_output_user_data(struct wl_output *wl_output)
{
GHOST_ASSERT(wl_output, "output must not be NULL");
GHOST_ASSERT(ghost_wl_output_own(wl_output), "output is not owned by GHOST");
- output_t *output = static_cast<output_t *>(wl_output_get_user_data(wl_output));
+ GWL_Output *output = static_cast<GWL_Output *>(wl_output_get_user_data(wl_output));
return output;
}
-GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *surface)
+GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface)
{
- GHOST_ASSERT(surface, "surface must not be NULL");
- GHOST_ASSERT(ghost_wl_surface_own(surface), "surface is not owned by GHOST");
- GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface));
+ GHOST_ASSERT(wl_surface, "wl_surface must not be NULL");
+ GHOST_ASSERT(ghost_wl_surface_own(wl_surface), "wl_surface is not owned by GHOST");
+ GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(wl_surface));
return win;
}
@@ -3905,20 +4061,20 @@ void GHOST_SystemWayland::selection_set(const std::string &selection)
this->selection = selection;
}
-void GHOST_SystemWayland::window_surface_unref(const wl_surface *surface)
+void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
{
#define SURFACE_CLEAR_PTR(surface_test) \
- if (surface_test == surface) { \
+ if (surface_test == wl_surface) { \
surface_test = nullptr; \
} \
((void)0);
/* Only clear window surfaces (not cursors, off-screen surfaces etc). */
- for (input_t *input : d->inputs) {
- SURFACE_CLEAR_PTR(input->pointer.wl_surface);
- SURFACE_CLEAR_PTR(input->tablet.wl_surface);
- SURFACE_CLEAR_PTR(input->keyboard.wl_surface);
- SURFACE_CLEAR_PTR(input->focus_dnd);
+ for (GWL_Seat *seat : d->seats) {
+ SURFACE_CLEAR_PTR(seat->pointer.wl_surface);
+ SURFACE_CLEAR_PTR(seat->tablet.wl_surface);
+ SURFACE_CLEAR_PTR(seat->keyboard.wl_surface);
+ SURFACE_CLEAR_PTR(seat->wl_surface_focus_dnd);
}
#undef SURFACE_CLEAR_PTR
}
@@ -3928,7 +4084,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
int32_t init_grab_xy[2],
const GHOST_Rect *wrap_bounds,
const GHOST_TAxisFlag wrap_axis,
- wl_surface *surface,
+ wl_surface *wl_surface,
const int scale)
{
/* Ignore, if the required protocols are not supported. */
@@ -3936,7 +4092,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
return GHOST_kFailure;
}
- if (UNLIKELY(d->inputs.empty())) {
+ if (UNLIKELY(d->seats.empty())) {
return GHOST_kFailure;
}
/* No change, success. */
@@ -3944,20 +4100,20 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
return GHOST_kSuccess;
}
- input_t *input = d->inputs[0];
+ GWL_Seat *seat = d->seats[0];
#ifdef USE_GNOME_CONFINE_HACK
- const bool was_software_confine = input->use_pointer_software_confine;
- const bool use_software_confine = setCursorGrab_use_software_confine(mode, surface);
+ const bool was_software_confine = seat->use_pointer_software_confine;
+ const bool use_software_confine = setCursorGrab_use_software_confine(mode, wl_surface);
#else
const bool was_software_confine = false;
const bool use_software_confine = false;
#endif
- const struct input_grab_state_t grab_state_prev = input_grab_state_from_mode(
- mode_current, was_software_confine);
- const struct input_grab_state_t grab_state_next = input_grab_state_from_mode(
- mode, use_software_confine);
+ const struct GWL_SeatStateGrab grab_state_prev = seat_grab_state_from_mode(mode_current,
+ was_software_confine);
+ const struct GWL_SeatStateGrab grab_state_next = seat_grab_state_from_mode(mode,
+ use_software_confine);
/* Check for wrap as #supportsCursorWarp isn't supported. */
const bool use_visible = !(ELEM(mode, GHOST_kGrabHide, GHOST_kGrabWrap) || use_software_confine);
@@ -3965,17 +4121,17 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
/* Only hide so the cursor is not made visible before it's location is restored.
* This function is called again at the end of this function which only shows. */
- cursor_visible_set(input, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_HIDE);
+ cursor_visible_set(seat, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_HIDE);
/* Switching from one grab mode to another,
* in this case disable the current locks as it makes logic confusing,
* postpone changing the cursor to avoid flickering. */
if (!grab_state_next.use_lock) {
- if (input->relative_pointer) {
- zwp_relative_pointer_v1_destroy(input->relative_pointer);
- input->relative_pointer = nullptr;
+ if (seat->relative_pointer) {
+ zwp_relative_pointer_v1_destroy(seat->relative_pointer);
+ seat->relative_pointer = nullptr;
}
- if (input->locked_pointer) {
+ if (seat->locked_pointer) {
/* Potentially add a motion event so the application has updated X/Y coordinates. */
int32_t xy_motion[2] = {0, 0};
bool xy_motion_create_event = false;
@@ -3984,7 +4140,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
if (mode_current == GHOST_kGrabWrap) {
/* Since this call is initiated by Blender, we can be sure the window wasn't closed
* by logic outside this function - as the window was needed to make this call. */
- int32_t xy_next[2] = {UNPACK2(input->pointer.xy)};
+ int32_t xy_next[2] = {UNPACK2(seat->pointer.xy)};
GHOST_Rect bounds_scale;
@@ -3996,26 +4152,26 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
bounds_scale.wrapPoint(UNPACK2(xy_next), 0, wrap_axis);
/* Push an event so the new location is registered. */
- if ((xy_next[0] != input->pointer.xy[0]) || (xy_next[1] != input->pointer.xy[1])) {
+ if ((xy_next[0] != seat->pointer.xy[0]) || (xy_next[1] != seat->pointer.xy[1])) {
xy_motion[0] = xy_next[0];
xy_motion[1] = xy_next[1];
xy_motion_create_event = true;
}
- input->pointer.xy[0] = xy_next[0];
- input->pointer.xy[1] = xy_next[1];
+ seat->pointer.xy[0] = xy_next[0];
+ seat->pointer.xy[1] = xy_next[1];
- zwp_locked_pointer_v1_set_cursor_position_hint(input->locked_pointer, UNPACK2(xy_next));
- wl_surface_commit(surface);
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next));
+ wl_surface_commit(wl_surface);
}
else if (mode_current == GHOST_kGrabHide) {
- if ((init_grab_xy[0] != input->grab_lock_xy[0]) ||
- (init_grab_xy[1] != input->grab_lock_xy[1])) {
+ if ((init_grab_xy[0] != seat->grab_lock_xy[0]) ||
+ (init_grab_xy[1] != seat->grab_lock_xy[1])) {
const wl_fixed_t xy_next[2] = {
wl_fixed_from_int(init_grab_xy[0]) / scale,
wl_fixed_from_int(init_grab_xy[1]) / scale,
};
- zwp_locked_pointer_v1_set_cursor_position_hint(input->locked_pointer, UNPACK2(xy_next));
- wl_surface_commit(surface);
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next));
+ wl_surface_commit(wl_surface);
/* NOTE(@campbellbarton): The new cursor position is a hint,
* it's possible the hint is ignored. It doesn't seem like there is a good way to
@@ -4028,31 +4184,31 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
#ifdef USE_GNOME_CONFINE_HACK
else if (mode_current == GHOST_kGrabNormal) {
if (was_software_confine) {
- zwp_locked_pointer_v1_set_cursor_position_hint(input->locked_pointer,
- UNPACK2(input->pointer.xy));
- wl_surface_commit(surface);
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer,
+ UNPACK2(seat->pointer.xy));
+ wl_surface_commit(wl_surface);
}
}
#endif
if (xy_motion_create_event) {
- input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- ghost_wl_surface_user_data(surface),
- wl_fixed_to_int(scale * xy_motion[0]),
- wl_fixed_to_int(scale * xy_motion[1]),
- GHOST_TABLET_DATA_NONE));
+ seat->system->pushEvent(new GHOST_EventCursor(seat->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ ghost_wl_surface_user_data(wl_surface),
+ wl_fixed_to_int(scale * xy_motion[0]),
+ wl_fixed_to_int(scale * xy_motion[1]),
+ GHOST_TABLET_DATA_NONE));
}
- zwp_locked_pointer_v1_destroy(input->locked_pointer);
- input->locked_pointer = nullptr;
+ zwp_locked_pointer_v1_destroy(seat->locked_pointer);
+ seat->locked_pointer = nullptr;
}
}
if (!grab_state_next.use_confine) {
- if (input->confined_pointer) {
- zwp_confined_pointer_v1_destroy(input->confined_pointer);
- input->confined_pointer = nullptr;
+ if (seat->confined_pointer) {
+ zwp_confined_pointer_v1_destroy(seat->confined_pointer);
+ seat->confined_pointer = nullptr;
}
}
@@ -4063,32 +4219,32 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
* possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates.
* An alternative could be to draw the cursor in software (and hide the real cursor),
* or just accept a locked cursor on WAYLAND. */
- input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
- d->relative_pointer_manager, input->wl_pointer);
+ seat->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
+ d->relative_pointer_manager, seat->wl_pointer);
zwp_relative_pointer_v1_add_listener(
- input->relative_pointer, &relative_pointer_listener, input);
- input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
+ seat->relative_pointer, &relative_pointer_listener, seat);
+ seat->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
d->pointer_constraints,
- surface,
- input->wl_pointer,
+ wl_surface,
+ seat->wl_pointer,
nullptr,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
}
if (mode == GHOST_kGrabHide) {
/* Set the initial position to detect any changes when un-grabbing,
* otherwise the unlocked cursor defaults to un-locking in-place. */
- init_grab_xy[0] = wl_fixed_to_int(scale * input->pointer.xy[0]);
- init_grab_xy[1] = wl_fixed_to_int(scale * input->pointer.xy[1]);
- input->grab_lock_xy[0] = init_grab_xy[0];
- input->grab_lock_xy[1] = init_grab_xy[1];
+ init_grab_xy[0] = wl_fixed_to_int(scale * seat->pointer.xy[0]);
+ init_grab_xy[1] = wl_fixed_to_int(scale * seat->pointer.xy[1]);
+ seat->grab_lock_xy[0] = init_grab_xy[0];
+ seat->grab_lock_xy[1] = init_grab_xy[1];
}
}
else if (grab_state_next.use_confine) {
if (!grab_state_prev.use_confine) {
- input->confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
+ seat->confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
d->pointer_constraints,
- surface,
- input->wl_pointer,
+ wl_surface,
+ seat->wl_pointer,
nullptr,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
}
@@ -4096,10 +4252,10 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
}
/* Only show so the cursor is made visible as the last step. */
- cursor_visible_set(input, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_SHOW);
+ cursor_visible_set(seat, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_SHOW);
#ifdef USE_GNOME_CONFINE_HACK
- input->use_pointer_software_confine = use_software_confine;
+ seat->use_pointer_software_confine = use_software_confine;
#endif
return GHOST_kSuccess;
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index bdf5f2fc273..caea7b0d748 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -31,11 +31,11 @@
class GHOST_WindowWayland;
-struct display_t;
+struct GWL_Display;
-bool ghost_wl_output_own(const struct wl_output *output);
-void ghost_wl_output_tag(struct wl_output *output);
-struct output_t *ghost_wl_output_user_data(struct wl_output *output);
+bool ghost_wl_output_own(const struct wl_output *wl_output);
+void ghost_wl_output_tag(struct wl_output *wl_output);
+struct GWL_Output *ghost_wl_output_user_data(struct wl_output *wl_output);
bool ghost_wl_surface_own(const struct wl_surface *surface);
void ghost_wl_surface_tag(struct wl_surface *surface);
@@ -55,7 +55,7 @@ void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface);
bool ghost_wl_dynload_libraries();
#endif
-struct output_t {
+struct GWL_Output {
struct wl_output *wl_output = nullptr;
struct zxdg_output_v1 *xdg_output = nullptr;
/** Dimensions in pixels. */
@@ -93,9 +93,11 @@ class GHOST_SystemWayland : public GHOST_System {
~GHOST_SystemWayland() override;
+ GHOST_TSuccess init();
+
bool processEvents(bool waitForEvent) override;
- int setConsoleWindowState(GHOST_TConsoleWindowState action) override;
+ bool setConsoleWindowState(GHOST_TConsoleWindowState action) override;
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override;
@@ -171,7 +173,7 @@ class GHOST_SystemWayland : public GHOST_System {
zxdg_decoration_manager_v1 *xdg_decoration_manager();
#endif
- const std::vector<output_t *> &outputs() const;
+ const std::vector<GWL_Output *> &outputs() const;
wl_shm *shm() const;
@@ -180,17 +182,17 @@ class GHOST_SystemWayland : public GHOST_System {
void selection_set(const std::string &selection);
/** Clear all references to this surface to prevent accessing NULL pointers. */
- void window_surface_unref(const wl_surface *surface);
+ void window_surface_unref(const wl_surface *wl_surface);
bool window_cursor_grab_set(const GHOST_TGrabCursorMode mode,
const GHOST_TGrabCursorMode mode_current,
int32_t init_grab_xy[2],
const GHOST_Rect *wrap_bounds,
GHOST_TAxisFlag wrap_axis,
- wl_surface *surface,
+ wl_surface *wl_surface,
int scale);
private:
- struct display_t *d;
+ struct GWL_Display *d;
std::string selection;
};
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 7c07ea6cd64..5c58f9a856c 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -42,47 +42,48 @@
# include "GHOST_NDOFManagerWin32.h"
#endif
-// Key code values not found in winuser.h
+/* Key code values not found in `winuser.h`. */
#ifndef VK_MINUS
# define VK_MINUS 0xBD
-#endif // VK_MINUS
+#endif /* VK_MINUS */
#ifndef VK_SEMICOLON
# define VK_SEMICOLON 0xBA
-#endif // VK_SEMICOLON
+#endif /* VK_SEMICOLON */
#ifndef VK_PERIOD
# define VK_PERIOD 0xBE
-#endif // VK_PERIOD
+#endif /* VK_PERIOD */
#ifndef VK_COMMA
# define VK_COMMA 0xBC
-#endif // VK_COMMA
+#endif /* VK_COMMA */
#ifndef VK_BACK_QUOTE
# define VK_BACK_QUOTE 0xC0
-#endif // VK_BACK_QUOTE
+#endif /* VK_BACK_QUOTE */
#ifndef VK_SLASH
# define VK_SLASH 0xBF
-#endif // VK_SLASH
+#endif /* VK_SLASH */
#ifndef VK_BACK_SLASH
# define VK_BACK_SLASH 0xDC
-#endif // VK_BACK_SLASH
+#endif /* VK_BACK_SLASH */
#ifndef VK_EQUALS
# define VK_EQUALS 0xBB
-#endif // VK_EQUALS
+#endif /* VK_EQUALS */
#ifndef VK_OPEN_BRACKET
# define VK_OPEN_BRACKET 0xDB
-#endif // VK_OPEN_BRACKET
+#endif /* VK_OPEN_BRACKET */
#ifndef VK_CLOSE_BRACKET
# define VK_CLOSE_BRACKET 0xDD
-#endif // VK_CLOSE_BRACKET
+#endif /* VK_CLOSE_BRACKET */
#ifndef VK_GR_LESS
# define VK_GR_LESS 0xE2
-#endif // VK_GR_LESS
+#endif /* VK_GR_LESS */
-/* Workaround for some laptop touchpads, some of which seems to
+/**
+ * Workaround for some laptop touch-pads, some of which seems to
* have driver issues which makes it so window function receives
- * the message, but PeekMessage doesn't pick those messages for
+ * the message, but #PeekMessage doesn't pick those messages for
* some reason.
*
- * We send a dummy WM_USER message to force PeekMessage to receive
+ * We send a dummy WM_USER message to force #PeekMessage to receive
* something, making it so blender's window manager sees the new
* messages coming in.
*/
@@ -101,22 +102,23 @@ static void initRawInput()
RAWINPUTDEVICE devices[DEVICE_COUNT];
memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE));
- // Initiates WM_INPUT messages from keyboard
- // That way GHOST can retrieve true keys
+ /* Initiates WM_INPUT messages from keyboard
+ * That way GHOST can retrieve true keys. */
devices[0].usUsagePage = 0x01;
devices[0].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
#ifdef WITH_INPUT_NDOF
- // multi-axis mouse (SpaceNavigator, etc.)
+ /* multi-axis mouse (SpaceNavigator, etc.). */
devices[1].usUsagePage = 0x01;
devices[1].usUsage = 0x08;
#endif
- if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE)))
- ; // yay!
- else
+ if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE))) {
+ /* Success. */
+ }
+ else {
GHOST_PRINTF("could not register for RawInput: %d\n", (int)GetLastError());
-
+ }
#undef DEVICE_COUNT
}
@@ -129,17 +131,17 @@ GHOST_SystemWin32::GHOST_SystemWin32()
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
m_displayManager->initialize();
- m_consoleStatus = 1;
+ m_consoleStatus = true;
- // Tell Windows we are per monitor DPI aware. This disables the default
- // blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI.
+ /* Tell Windows we are per monitor DPI aware. This disables the default
+ * blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI. */
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
- // Check if current keyboard layout uses AltGr and save keylayout ID for
- // specialized handling if keys like VK_OEM_*. I.e. french keylayout
- // generates VK_OEM_8 for their exclamation key (key left of right shift)
+ /* Check if current keyboard layout uses AltGr and save keylayout ID for
+ * specialized handling if keys like VK_OEM_*. I.e. french keylayout
+ * generates #VK_OEM_8 for their exclamation key (key left of right shift). */
this->handleKeyboardChange();
- // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
+ /* Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. */
OleInitialize(0);
#ifdef WITH_INPUT_NDOF
@@ -149,7 +151,7 @@ GHOST_SystemWin32::GHOST_SystemWin32()
GHOST_SystemWin32::~GHOST_SystemWin32()
{
- // Shutdown COM
+ /* Shutdown COM. */
OleUninitialize();
if (isStartedFromCommandPrompt()) {
@@ -159,7 +161,7 @@ GHOST_SystemWin32::~GHOST_SystemWin32()
uint64_t GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const
{
- // Calculate the time passed since system initialization.
+ /* Calculate the time passed since system initialization. */
__int64 delta = (perf_ticks - m_start) * 1000;
uint64_t t = (uint64_t)(delta / m_freq);
@@ -173,12 +175,12 @@ uint64_t GHOST_SystemWin32::tickCountToMillis(__int64 ticks) const
uint64_t GHOST_SystemWin32::getMilliSeconds() const
{
- // Hardware does not support high resolution timers. We will use GetTickCount instead then.
+ /* Hardware does not support high resolution timers. We will use GetTickCount instead then. */
if (!m_hasPerformanceCounter) {
return tickCountToMillis(::GetTickCount());
}
- // Retrieve current count
+ /* Retrieve current count */
__int64 count = 0;
::QueryPerformanceCounter((LARGE_INTEGER *)&count);
@@ -227,13 +229,13 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
state,
type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
- ((glSettings.flags & GHOST_glAlphaBackground) != 0),
+ false,
(GHOST_WindowWin32 *)parentWindow,
((glSettings.flags & GHOST_glDebugContext) != 0),
is_dialog);
if (window->getValid()) {
- // Store the pointer to the window
+ /* Store the pointer to the window */
m_windowManager->addWindow(window);
m_windowManager->setActiveWindow(window);
}
@@ -272,7 +274,7 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSet
HDC mHDC = GetDC(wnd);
HDC prev_hdc = wglGetCurrentDC();
HGLRC prev_context = wglGetCurrentContext();
-#if defined(WITH_GL_PROFILE_CORE)
+
for (int minor = 5; minor >= 0; --minor) {
context = new GHOST_ContextWGL(false,
true,
@@ -310,29 +312,6 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSet
return NULL;
}
-#elif defined(WITH_GL_PROFILE_COMPAT)
- // ask for 2.1 context, driver gives any GL version >= 2.1
- // (hopefully the latest compatibility profile)
- // 2.1 ignores the profile bit & is incompatible with core profile
- context = new GHOST_ContextWGL(false,
- true,
- NULL,
- NULL,
- 0, // no profile bit
- 2,
- 1,
- (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
-
- if (context->initializeDrawingContext()) {
- return context;
- }
- else {
- delete context;
- }
-#else
-# error // must specify either core or compat at build time
-#endif
finished:
wglMakeCurrent(prev_hdc, prev_context);
return context;
@@ -374,6 +353,7 @@ GHOST_ContextD3D *GHOST_SystemWin32::createOffscreenContextD3D()
context = new GHOST_ContextD3D(false, wnd);
if (context->initializeDrawingContext() == GHOST_kFailure) {
delete context;
+ context = nullptr;
}
return context;
@@ -418,10 +398,10 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
driveTrackpad();
- // Process all the events waiting for us
+ /* Process all the events waiting for us. */
while (::PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
- // TranslateMessage doesn't alter the message, and doesn't change our raw keyboard data.
- // Needed for MapVirtualKey or if we ever need to get chars from wm_ime_char or similar.
+ /* #TranslateMessage doesn't alter the message, and doesn't change our raw keyboard data.
+ * Needed for #MapVirtualKey or if we ever need to get chars from wm_ime_char or similar. */
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
hasEventHandled = true;
@@ -453,8 +433,9 @@ GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(int32_t &x, int32_t &y) cons
GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(int32_t x, int32_t y)
{
- if (!::GetActiveWindow())
+ if (!::GetActiveWindow()) {
return GHOST_kFailure;
+ }
return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
}
@@ -475,12 +456,11 @@ GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys &keys) cons
down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
keys.set(GHOST_kModifierKeyRightControl, down);
- bool lwindown = HIBYTE(::GetKeyState(VK_LWIN)) != 0;
- bool rwindown = HIBYTE(::GetKeyState(VK_RWIN)) != 0;
- if (lwindown || rwindown)
- keys.set(GHOST_kModifierKeyOS, true);
- else
- keys.set(GHOST_kModifierKeyOS, false);
+ down = HIBYTE(::GetKeyState(VK_LWIN)) != 0;
+ keys.set(GHOST_kModifierKeyLeftOS, down);
+ down = HIBYTE(::GetKeyState(VK_RWIN)) != 0;
+ keys.set(GHOST_kModifierKeyRightOS, down);
+
return GHOST_kSuccess;
}
@@ -512,7 +492,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
initRawInput();
m_lfstart = ::GetTickCount();
- // Determine whether this system has a high frequency performance counter. */
+ /* Determine whether this system has a high frequency performance counter. */
m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER *)&m_freq) == TRUE;
if (m_hasPerformanceCounter) {
GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n");
@@ -543,7 +523,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
wc.lpszMenuName = 0;
wc.lpszClassName = L"GHOST_WindowClass";
- // Use RegisterClassEx for setting small icon
+ /* Use #RegisterClassEx for setting small icon. */
if (::RegisterClassW(&wc) == 0) {
success = GHOST_kFailure;
}
@@ -557,76 +537,15 @@ GHOST_TSuccess GHOST_SystemWin32::exit()
return GHOST_System::exit();
}
-GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw,
- bool *r_keyDown,
- bool *r_is_repeated_modifier)
+GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw, bool *r_key_down)
{
- bool is_repeated_modifier = false;
-
- GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- GHOST_TKey key = GHOST_kKeyUnknown;
- GHOST_ModifierKeys modifiers;
- system->retrieveModifierKeys(modifiers);
-
- // RI_KEY_BREAK doesn't work for sticky keys release, so we also
- // check for the up message
+ /* #RI_KEY_BREAK doesn't work for sticky keys release, so we also check for the up message. */
unsigned int msg = raw.data.keyboard.Message;
- *r_keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK) && msg != WM_KEYUP && msg != WM_SYSKEYUP;
-
- key = this->convertKey(raw.data.keyboard.VKey,
- raw.data.keyboard.MakeCode,
- (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
-
- // extra handling of modifier keys: don't send repeats out from GHOST
- if (key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) {
- bool changed = false;
- GHOST_TModifierKey modifier;
- switch (key) {
- case GHOST_kKeyLeftShift: {
- changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != *r_keyDown);
- modifier = GHOST_kModifierKeyLeftShift;
- break;
- }
- case GHOST_kKeyRightShift: {
- changed = (modifiers.get(GHOST_kModifierKeyRightShift) != *r_keyDown);
- modifier = GHOST_kModifierKeyRightShift;
- break;
- }
- case GHOST_kKeyLeftControl: {
- changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != *r_keyDown);
- modifier = GHOST_kModifierKeyLeftControl;
- break;
- }
- case GHOST_kKeyRightControl: {
- changed = (modifiers.get(GHOST_kModifierKeyRightControl) != *r_keyDown);
- modifier = GHOST_kModifierKeyRightControl;
- break;
- }
- case GHOST_kKeyLeftAlt: {
- changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != *r_keyDown);
- modifier = GHOST_kModifierKeyLeftAlt;
- break;
- }
- case GHOST_kKeyRightAlt: {
- changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != *r_keyDown);
- modifier = GHOST_kModifierKeyRightAlt;
- break;
- }
- default:
- break;
- }
+ *r_key_down = !(raw.data.keyboard.Flags & RI_KEY_BREAK) && msg != WM_KEYUP && msg != WM_SYSKEYUP;
- if (changed) {
- modifiers.set(modifier, *r_keyDown);
- system->storeModifierKeys(modifiers);
- }
- else {
- is_repeated_modifier = true;
- }
- }
-
- *r_is_repeated_modifier = is_repeated_modifier;
- return key;
+ return this->convertKey(raw.data.keyboard.VKey,
+ raw.data.keyboard.MakeCode,
+ (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
}
/**
@@ -680,11 +599,11 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
GHOST_TKey key;
if ((vKey >= '0') && (vKey <= '9')) {
- // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
+ /* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39). */
key = (GHOST_TKey)(vKey - '0' + GHOST_kKey0);
}
else if ((vKey >= 'A') && (vKey <= 'Z')) {
- // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
+ /* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A). */
key = (GHOST_TKey)(vKey - 'A' + GHOST_kKeyA);
}
else if ((vKey >= VK_F1) && (vKey <= VK_F24)) {
@@ -829,8 +748,10 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
key = (extend) ? GHOST_kKeyRightAlt : GHOST_kKeyLeftAlt;
break;
case VK_LWIN:
+ key = GHOST_kKeyLeftOS;
+ break;
case VK_RWIN:
- key = GHOST_kKeyOS;
+ key = GHOST_kKeyRightOS;
break;
case VK_APPS:
key = GHOST_kKeyApp;
@@ -979,11 +900,11 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
mouseMoveHandled = true;
- break;
}
else {
WINTAB_PRINTF(" ... but no system button\n");
}
+ break;
}
case GHOST_kEventButtonUp: {
WINTAB_PRINTF("HWND %p Wintab button up", window->getHWND());
@@ -1058,7 +979,7 @@ void GHOST_SystemWin32::processPointerEvent(
}
switch (type) {
- case WM_POINTERUPDATE:
+ case WM_POINTERUPDATE: {
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
* Only contiguous move events are coalesced. */
for (uint32_t i = pointerInfo.size(); i-- > 0;) {
@@ -1073,7 +994,8 @@ void GHOST_SystemWin32::processPointerEvent(
/* Leave event unhandled so that system cursor is moved. */
break;
- case WM_POINTERDOWN:
+ }
+ case WM_POINTERDOWN: {
/* Move cursor to point of contact because GHOST_EventButton does not include position. */
system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
GHOST_kEventCursorMove,
@@ -1092,7 +1014,8 @@ void GHOST_SystemWin32::processPointerEvent(
eventHandled = true;
break;
- case WM_POINTERUP:
+ }
+ case WM_POINTERUP: {
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
GHOST_kEventButtonUp,
window,
@@ -1104,8 +1027,10 @@ void GHOST_SystemWin32::processPointerEvent(
eventHandled = true;
break;
- default:
+ }
+ default: {
break;
+ }
}
}
@@ -1122,6 +1047,12 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
system->getCursorPosition(x_screen, y_screen);
if (window->getCursorGrabModeIsWarp()) {
+ /* WORKAROUND:
+ * Sometimes Windows ignores `SetCursorPos()` or `SendInput()` calls or the mouse event is
+ * outdated. Identify these cases by checking if the cursor is not yet within bounds. */
+ static bool is_warping_x = false;
+ static bool is_warping_y = false;
+
int32_t x_new = x_screen;
int32_t y_new = y_screen;
int32_t x_accum, y_accum;
@@ -1138,29 +1069,41 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window->getCursorGrabAccum(x_accum, y_accum);
if (x_new != x_screen || y_new != y_screen) {
+ system->setCursorPosition(x_new, y_new); /* wrap */
+
+ /* Do not update the accum values if we are an outdated or failed pos-warp event. */
+ if (!is_warping_x) {
+ is_warping_x = x_new != x_screen;
+ if (is_warping_x) {
+ x_accum += (x_screen - x_new);
+ }
+ }
+
+ if (!is_warping_y) {
+ is_warping_y = y_new != y_screen;
+ if (is_warping_y) {
+ y_accum += (y_screen - y_new);
+ }
+ }
+ window->setCursorGrabAccum(x_accum, y_accum);
+
/* When wrapping we don't need to add an event because the setCursorPosition call will cause
* a new event after. */
- system->setCursorPosition(x_new, y_new); /* wrap */
- window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
- }
- else {
- return new GHOST_EventCursor(system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- window,
- x_screen + x_accum,
- y_screen + y_accum,
- GHOST_TABLET_DATA_NONE);
+ return NULL;
}
+
+ is_warping_x = false;
+ is_warping_y = false;
+ x_screen += x_accum;
+ y_screen += y_accum;
}
- else {
- return new GHOST_EventCursor(system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- window,
- x_screen,
- y_screen,
- GHOST_TABLET_DATA_NONE);
- }
- return NULL;
+
+ return new GHOST_EventCursor(system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ window,
+ x_screen,
+ y_screen,
+ GHOST_TABLET_DATA_NONE);
}
void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
@@ -1171,7 +1114,7 @@ void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wPar
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
if (acc * delta < 0) {
- // scroll direction reversed.
+ /* Scroll direction reversed. */
acc = 0;
}
acc += delta;
@@ -1187,48 +1130,55 @@ void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wPar
GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const &raw)
{
- bool keyDown = false;
- bool is_repeated_modifier = false;
+ const char vk = raw.data.keyboard.VKey;
+ bool key_down = false;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- GHOST_TKey key = system->hardKey(raw, &keyDown, &is_repeated_modifier);
+ GHOST_TKey key = system->hardKey(raw, &key_down);
GHOST_EventKey *event;
+ /* NOTE(@campbellbarton): key repeat in WIN32 also applies to modifier-keys.
+ * Check for this case and filter out modifier-repeat.
+ * Typically keyboard events are *not* filtered as part of GHOST's event handling.
+ * As other GHOST back-ends don't have the behavior, it's simplest not to send them through.
+ * Ideally it would be possible to check the key-map for keys that repeat but this doesn't look
+ * to be supported. */
+ bool is_repeat = false;
+ bool is_repeated_modifier = false;
+ if (key_down) {
+ if (system->m_keycode_last_repeat_key == vk) {
+ is_repeat = true;
+ is_repeated_modifier = GHOST_KEY_MODIFIER_CHECK(key);
+ }
+ system->m_keycode_last_repeat_key = vk;
+ }
+ else {
+ if (system->m_keycode_last_repeat_key == vk) {
+ system->m_keycode_last_repeat_key = 0;
+ }
+ }
+
/* We used to check `if (key != GHOST_kKeyUnknown)`, but since the message
* values `WM_SYSKEYUP`, `WM_KEYUP` and `WM_CHAR` are ignored, we capture
* those events here as well. */
if (!is_repeated_modifier) {
- char vk = raw.data.keyboard.VKey;
char utf8_char[6] = {0};
- char ascii = 0;
- bool is_repeat = false;
+ BYTE state[256];
+ const BOOL has_state = GetKeyboardState((PBYTE)state);
+ const bool ctrl_pressed = has_state && state[VK_CONTROL] & 0x80;
+ const bool alt_pressed = has_state && state[VK_MENU] & 0x80;
- /* Unlike on Linux, not all keys can send repeat events. E.g. modifier keys don't. */
- if (keyDown) {
- if (system->m_keycode_last_repeat_key == vk) {
- is_repeat = true;
- }
- system->m_keycode_last_repeat_key = vk;
- }
- else {
- if (system->m_keycode_last_repeat_key == vk) {
- system->m_keycode_last_repeat_key = 0;
- }
+ if (!key_down) {
+ /* Pass. */
}
-
- wchar_t utf16[3] = {0};
- BYTE state[256] = {0};
- int r;
- GetKeyboardState((PBYTE)state);
- bool ctrl_pressed = state[VK_CONTROL] & 0x80;
- bool alt_pressed = state[VK_MENU] & 0x80;
-
/* No text with control key pressed (Alt can be used to insert special characters though!). */
- if (ctrl_pressed && !alt_pressed) {
- utf8_char[0] = '\0';
+ else if (ctrl_pressed && !alt_pressed) {
+ /* Pass. */
}
- // Don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical
- // composition.
+ /* Don't call #ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical
+ * composition. */
else if (MapVirtualKeyW(vk, 2) != 0) {
+ wchar_t utf16[3] = {0};
+ int r;
/* TODO: #ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here).
* Could be up to 24 utf8 bytes. */
if ((r = ToUnicodeEx(
@@ -1243,28 +1193,25 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
}
}
- if (!keyDown) {
- utf8_char[0] = '\0';
- ascii = '\0';
- }
- else {
- ascii = utf8_char[0] & 0x80 ? '?' : utf8_char[0];
- }
-
#ifdef WITH_INPUT_IME
- if (window->getImeInput()->IsImeKeyEvent(ascii, key)) {
- return NULL;
+ if (key_down && ((utf8_char[0] & 0x80) == 0)) {
+ const char ascii = utf8_char[0];
+ if (window->getImeInput()->IsImeKeyEvent(ascii, key)) {
+ return NULL;
+ }
}
#endif /* WITH_INPUT_IME */
event = new GHOST_EventKey(system->getMilliSeconds(),
- keyDown ? GHOST_kEventKeyDown : GHOST_kEventKeyUp,
+ key_down ? GHOST_kEventKeyDown : GHOST_kEventKeyUp,
window,
key,
is_repeat,
utf8_char);
- // GHOST_PRINTF("%c\n", ascii); // we already get this info via EventPrinter
+#if 0 /* we already get this info via EventPrinter. */
+ GHOST_PRINTF("%c\n", ascii);
+#endif
}
else {
event = NULL;
@@ -1285,9 +1232,7 @@ GHOST_Event *GHOST_SystemWin32::processWindowSizeEvent(GHOST_WindowWin32 *window
system->dispatchEvents();
return NULL;
}
- else {
- return sizeEvent;
- }
+ return sizeEvent;
}
GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
@@ -1368,54 +1313,53 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
uint64_t now = getMilliSeconds();
static bool firstEvent = true;
- if (firstEvent) { // determine exactly which device is plugged in
+ if (firstEvent) { /* Determine exactly which device is plugged in. */
RID_DEVICE_INFO info;
unsigned infoSize = sizeof(RID_DEVICE_INFO);
info.cbSize = infoSize;
GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
- if (info.dwType == RIM_TYPEHID)
+ if (info.dwType == RIM_TYPEHID) {
m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
- else
+ }
+ else {
GHOST_PRINT("<!> not a HID device... mouse/kb perhaps?\n");
-
+ }
firstEvent = false;
}
- // The NDOF manager sends button changes immediately, and *pretends* to
- // send motion. Mark as 'sent' so motion will always get dispatched.
+ /* The NDOF manager sends button changes immediately, and *pretends* to
+ * send motion. Mark as 'sent' so motion will always get dispatched. */
eventSent = true;
BYTE const *data = raw.data.hid.bRawData;
BYTE packetType = data[0];
switch (packetType) {
- case 1: // translation
- {
+ case 1: { /* Translation. */
const short *axis = (short *)(data + 1);
- // massage into blender view coords (same goes for rotation)
+ /* Massage into blender view coords (same goes for rotation). */
const int t[3] = {axis[0], -axis[2], axis[1]};
m_ndofManager->updateTranslation(t, now);
if (raw.data.hid.dwSizeHid == 13) {
- // this report also includes rotation
+ /* This report also includes rotation. */
const int r[3] = {-axis[3], axis[5], -axis[4]};
m_ndofManager->updateRotation(r, now);
- // I've never gotten one of these, has anyone else?
+ /* I've never gotten one of these, has anyone else? */
GHOST_PRINT("ndof: combined T + R\n");
}
break;
}
- case 2: // rotation
- {
+ case 2: { /* Rotation. */
+
const short *axis = (short *)(data + 1);
const int r[3] = {-axis[0], axis[2], -axis[1]};
m_ndofManager->updateRotation(r, now);
break;
}
- case 3: // buttons
- {
+ case 3: { /* Buttons. */
int button_bits;
memcpy(&button_bits, data + 1, sizeof(button_bits));
m_ndofManager->updateButtons(button_bits, now);
@@ -1424,7 +1368,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
}
return eventSent;
}
-#endif // WITH_INPUT_NDOF
+#endif /* WITH_INPUT_NDOF */
void GHOST_SystemWin32::driveTrackpad()
{
@@ -1487,8 +1431,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
if (hwnd) {
if (msg == WM_NCCREATE) {
- // Tell Windows to automatically handle scaling of non-client areas
- // such as the caption bar. EnableNonClientDpiScaling was introduced in Windows 10
+ /* Tell Windows to automatically handle scaling of non-client areas
+ * such as the caption bar. #EnableNonClientDpiScaling was introduced in Windows 10. */
HMODULE m_user32 = ::LoadLibrary("User32.dll");
if (m_user32) {
GHOST_WIN32_EnableNonClientDpiScaling fpEnableNonClientDpiScaling =
@@ -1503,7 +1447,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
GHOST_WindowWin32 *window = (GHOST_WindowWin32 *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (window) {
switch (msg) {
- // we need to check if new key layout has AltGr
+ /* We need to check if new key layout has AltGr. */
case WM_INPUTLANGCHANGE: {
system->handleKeyboardChange();
#ifdef WITH_INPUT_IME
@@ -1512,9 +1456,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
#endif
break;
}
- ////////////////////////////////////////////////////////////////////////
- // Keyboard events, processed
- ////////////////////////////////////////////////////////////////////////
+ /* ==========================
+ * Keyboard events, processed
+ * ========================== */
case WM_INPUT: {
RAWINPUT raw;
RAWINPUT *raw_ptr = &raw;
@@ -1523,7 +1467,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER));
switch (raw.header.dwType) {
- case RIM_TYPEKEYBOARD:
+ case RIM_TYPEKEYBOARD: {
event = processKeyEvent(window, raw);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ");
@@ -1531,20 +1475,22 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
GHOST_PRINT(" key ignored\n");
}
break;
+ }
#ifdef WITH_INPUT_NDOF
- case RIM_TYPEHID:
+ case RIM_TYPEHID: {
if (system->processNDOF(raw)) {
eventHandled = true;
}
break;
+ }
#endif
}
break;
}
#ifdef WITH_INPUT_IME
- ////////////////////////////////////////////////////////////////////////
- // IME events, processed, read more in GHOST_IME.h
- ////////////////////////////////////////////////////////////////////////
+ /* =================================================
+ * IME events, processed, read more in `GHOST_IME.h`
+ * ================================================= */
case WM_IME_NOTIFY: {
/* Update conversion status when IME is changed or input mode is changed. */
if (wParam == IMN_SETOPENSTATUS || wParam == IMN_SETCONVERSIONMODE) {
@@ -1592,56 +1538,53 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
break;
}
#endif /* WITH_INPUT_IME */
- ////////////////////////////////////////////////////////////////////////
- // Keyboard events, ignored
- ////////////////////////////////////////////////////////////////////////
+ /* ========================
+ * Keyboard events, ignored
+ * ======================== */
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
- /* These functions were replaced by #WM_INPUT. */
+ /* These functions were replaced by #WM_INPUT. */
case WM_CHAR:
- /* The WM_CHAR message is posted to the window with the keyboard focus when
- * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
- * contains the character code of the key that was pressed.
- */
+ /* The #WM_CHAR message is posted to the window with the keyboard focus when
+ * a WM_KEYDOWN message is translated by the #TranslateMessage function.
+ * WM_CHAR contains the character code of the key that was pressed. */
case WM_DEADCHAR:
- /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
- * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR
+ /* The #WM_DEADCHAR message is posted to the window with the keyboard focus when a
+ * WM_KEYUP message is translated by the #TranslateMessage function. WM_DEADCHAR
* specifies a character code generated by a dead key. A dead key is a key that
* generates a character, such as the umlaut (double-dot), that is combined with
* another character to form a composite character. For example, the umlaut-O
* character (Ö) is generated by typing the dead key for the umlaut character, and
- * then typing the O key.
- */
+ * then typing the O key. */
break;
case WM_SYSDEADCHAR:
- /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when
- * a WM_SYSKEYDOWN message is translated by the TranslateMessage function.
- * WM_SYSDEADCHAR specifies the character code of a system dead key - that is,
- * a dead key that is pressed while holding down the alt key.
- */
- case WM_SYSCHAR:
- /* The WM_SYSCHAR message is sent to the window with the keyboard focus when
- * a WM_SYSCHAR message is translated by the TranslateMessage function.
+ /* The #WM_SYSDEADCHAR message is sent to the window with the keyboard focus when
+ * a WM_SYSKEYDOWN message is translated by the #TranslateMessage function.
+ * WM_SYSDEADCHAR specifies the character code of a system dead key - that is,
+ * a dead key that is pressed while holding down the alt key. */
+ case WM_SYSCHAR: {
+ /* #The WM_SYSCHAR message is sent to the window with the keyboard focus when
+ * a WM_SYSCHAR message is translated by the #TranslateMessage function.
* WM_SYSCHAR specifies the character code of a dead key - that is,
* a dead key that is pressed while holding down the alt key.
- * To prevent the sound, DefWindowProc must be avoided by return
- */
+ * To prevent the sound, #DefWindowProc must be avoided by return. */
break;
- case WM_SYSCOMMAND:
- /* The WM_SYSCOMMAND message is sent to the window when system commands such as
+ }
+ case WM_SYSCOMMAND: {
+ /* The #WM_SYSCOMMAND message is sent to the window when system commands such as
* maximize, minimize or close the window are triggered. Also it is sent when ALT
- * button is press for menu. To prevent this we must return preventing DefWindowProc.
+ * button is press for menu. To prevent this we must return preventing #DefWindowProc.
*
* Note that the four low-order bits of the wParam parameter are used internally by the
* OS. To obtain the correct result when testing the value of wParam, an application must
- * combine the value 0xFFF0 with the wParam value by using the bit-wise AND operator.
- */
+ * combine the value 0xFFF0 with the wParam value by using the bit-wise AND operator. */
switch (wParam & 0xFFF0) {
- case SC_KEYMENU:
+ case SC_KEYMENU: {
eventHandled = true;
break;
+ }
case SC_RESTORE: {
::ShowWindow(hwnd, SW_RESTORE);
window->setState(window->getState());
@@ -1672,9 +1615,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
}
break;
- ////////////////////////////////////////////////////////////////////////
- // Wintab events, processed
- ////////////////////////////////////////////////////////////////////////
+ }
+ /* ========================
+ * Wintab events, processed
+ * ======================== */
case WT_CSRCHANGE: {
WINTAB_PRINTF("HWND %p HCTX %p WT_CSRCHANGE\n", window->getHWND(), (void *)lParam);
GHOST_Wintab *wt = window->getWintab();
@@ -1726,44 +1670,53 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
eventHandled = true;
break;
}
- case WT_PACKET:
+ case WT_PACKET: {
processWintabEvent(window);
eventHandled = true;
break;
- ////////////////////////////////////////////////////////////////////////
- // Wintab events, debug
- ////////////////////////////////////////////////////////////////////////
- case WT_CTXOPEN:
+ }
+ /* ====================
+ * Wintab events, debug
+ * ==================== */
+ case WT_CTXOPEN: {
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXOPEN\n", window->getHWND(), (void *)wParam);
break;
- case WT_CTXCLOSE:
+ }
+ case WT_CTXCLOSE: {
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXCLOSE\n", window->getHWND(), (void *)wParam);
break;
- case WT_CTXUPDATE:
+ }
+ case WT_CTXUPDATE: {
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXUPDATE\n", window->getHWND(), (void *)wParam);
break;
- case WT_CTXOVERLAP:
+ }
+ case WT_CTXOVERLAP: {
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXOVERLAP", window->getHWND(), (void *)wParam);
switch (lParam) {
- case CXS_DISABLED:
+ case CXS_DISABLED: {
WINTAB_PRINTF(" CXS_DISABLED\n");
break;
- case CXS_OBSCURED:
+ }
+ case CXS_OBSCURED: {
WINTAB_PRINTF(" CXS_OBSCURED\n");
break;
- case CXS_ONTOP:
+ }
+ case CXS_ONTOP: {
WINTAB_PRINTF(" CXS_ONTOP\n");
break;
+ }
}
break;
- ////////////////////////////////////////////////////////////////////////
- // Pointer events, processed
- ////////////////////////////////////////////////////////////////////////
+ }
+ /* =========================
+ * Pointer events, processed
+ * ========================= */
case WM_POINTERUPDATE:
case WM_POINTERDOWN:
- case WM_POINTERUP:
+ case WM_POINTERUP: {
processPointerEvent(msg, window, wParam, lParam, eventHandled);
break;
+ }
case WM_POINTERLEAVE: {
uint32_t pointerId = GET_POINTERID_WPARAM(wParam);
POINTER_INFO pointerInfo;
@@ -1778,19 +1731,22 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
}
- ////////////////////////////////////////////////////////////////////////
- // Mouse events, processed
- ////////////////////////////////////////////////////////////////////////
- case WM_LBUTTONDOWN:
+ /* =======================
+ * Mouse events, processed
+ * ======================= */
+ case WM_LBUTTONDOWN: {
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
break;
- case WM_MBUTTONDOWN:
+ }
+ case WM_MBUTTONDOWN: {
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
break;
- case WM_RBUTTONDOWN:
+ }
+ case WM_RBUTTONDOWN: {
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
break;
- case WM_XBUTTONDOWN:
+ }
+ case WM_XBUTTONDOWN: {
if ((short)HIWORD(wParam) == XBUTTON1) {
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4);
}
@@ -1798,16 +1754,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5);
}
break;
- case WM_LBUTTONUP:
+ }
+ case WM_LBUTTONUP: {
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
break;
- case WM_MBUTTONUP:
+ }
+ case WM_MBUTTONUP: {
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
break;
- case WM_RBUTTONUP:
+ }
+ case WM_RBUTTONUP: {
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
break;
- case WM_XBUTTONUP:
+ }
+ case WM_XBUTTONUP: {
if ((short)HIWORD(wParam) == XBUTTON1) {
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4);
}
@@ -1815,7 +1775,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5);
}
break;
- case WM_MOUSEMOVE:
+ }
+ case WM_MOUSEMOVE: {
if (!window->m_mousePresent) {
WINTAB_PRINTF("HWND %p mouse enter\n", window->getHWND());
TRACKMOUSEEVENT tme = {sizeof(tme)};
@@ -1832,6 +1793,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
event = processCursorEvent(window);
break;
+ }
case WM_MOUSEWHEEL: {
/* The WM_MOUSEWHEEL message is sent to the focus window
* when the mouse wheel is rotated. The DefWindowProc
@@ -1847,7 +1809,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
#endif
break;
}
- case WM_SETCURSOR:
+ case WM_SETCURSOR: {
/* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
* to move within a window and mouse input is not captured.
* This means we have to set the cursor shape every time the mouse moves!
@@ -1855,16 +1817,17 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* arrow if it is not in the client area.
*/
if (LOWORD(lParam) == HTCLIENT) {
- // Load the current cursor
+ /* Load the current cursor. */
window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
- // Bypass call to DefWindowProc
+ /* Bypass call to #DefWindowProc. */
return 0;
}
else {
- // Outside of client area show standard cursor
+ /* Outside of client area show standard cursor. */
window->loadCursor(true, GHOST_kStandardCursorDefault);
}
break;
+ }
case WM_MOUSELEAVE: {
WINTAB_PRINTF("HWND %p mouse leave\n", window->getHWND());
window->m_mousePresent = false;
@@ -1877,26 +1840,27 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
}
- ////////////////////////////////////////////////////////////////////////
- // Mouse events, ignored
- ////////////////////////////////////////////////////////////////////////
- case WM_NCMOUSEMOVE:
- /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved
- * within the non-client area of the window. This message is posted to the window that
- * contains the cursor. If a window has captured the mouse, this message is not posted.
- */
- case WM_NCHITTEST:
+ /* =====================
+ * Mouse events, ignored
+ * ===================== */
+ case WM_NCMOUSEMOVE: {
+ /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved
+ * within the non-client area of the window. This message is posted to the window that
+ * contains the cursor. If a window has captured the mouse, this message is not posted.
+ */
+ }
+ case WM_NCHITTEST: {
/* The WM_NCHITTEST message is sent to a window when the cursor moves, or
* when a mouse button is pressed or released. If the mouse is not captured,
* the message is sent to the window beneath the cursor. Otherwise, the message
* is sent to the window that has captured the mouse.
*/
break;
-
- ////////////////////////////////////////////////////////////////////////
- // Window events, processed
- ////////////////////////////////////////////////////////////////////////
- case WM_CLOSE:
+ }
+ /* ========================
+ * Window events, processed
+ * ======================== */
+ case WM_CLOSE: {
/* The WM_CLOSE message is sent as a signal that a window
* or an application should terminate. Restore if minimized. */
if (IsIconic(hwnd)) {
@@ -1904,31 +1868,29 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
event = processWindowEvent(GHOST_kEventWindowClose, window);
break;
- case WM_ACTIVATE:
+ }
+ case WM_ACTIVATE: {
/* The WM_ACTIVATE message is sent to both the window being activated and the window
* being deactivated. If the windows use the same input queue, the message is sent
* synchronously, first to the window procedure of the top-level window being
* deactivated, then to the window procedure of the top-level window being activated.
* If the windows use different input queues, the message is sent asynchronously,
* so the window is activated immediately. */
- {
- GHOST_ModifierKeys modifiers;
- modifiers.clear();
- system->storeModifierKeys(modifiers);
- system->m_wheelDeltaAccum = 0;
- system->m_keycode_last_repeat_key = 0;
- event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate :
- GHOST_kEventWindowDeactivate,
- window);
- /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
- * will not be dispatched to OUR active window if we minimize one of OUR windows. */
- if (LOWORD(wParam) == WA_INACTIVE)
- window->lostMouseCapture();
-
- lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
- break;
+
+ system->m_wheelDeltaAccum = 0;
+ system->m_keycode_last_repeat_key = 0;
+ event = processWindowEvent(
+ LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
+ /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
+ * will not be dispatched to OUR active window if we minimize one of OUR windows. */
+ if (LOWORD(wParam) == WA_INACTIVE) {
+ window->lostMouseCapture();
}
- case WM_ENTERSIZEMOVE:
+
+ lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
+ break;
+ }
+ case WM_ENTERSIZEMOVE: {
/* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving
* or sizing modal loop. The window enters the moving or sizing modal loop when the user
* clicks the window's title bar or sizing border, or when the window passes the
@@ -1938,10 +1900,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
*/
window->m_inLiveResize = 1;
break;
- case WM_EXITSIZEMOVE:
+ }
+ case WM_EXITSIZEMOVE: {
window->m_inLiveResize = 0;
break;
- case WM_PAINT:
+ }
+ case WM_PAINT: {
/* An application sends the WM_PAINT message when the system or another application
* makes a request to paint a portion of an application's window. The message is sent
* when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage
@@ -1956,7 +1920,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
eventHandled = true;
}
break;
- case WM_GETMINMAXINFO:
+ }
+ case WM_GETMINMAXINFO: {
/* The WM_GETMINMAXINFO message is sent to a window when the size or
* position of the window is about to change. An application can use
* this message to override the window's default maximized size and
@@ -1965,10 +1930,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
processMinMaxInfo((MINMAXINFO *)lParam);
/* Let DefWindowProc handle it. */
break;
- case WM_SIZING:
+ }
+ case WM_SIZING: {
event = processWindowSizeEvent(window);
break;
- case WM_SIZE:
+ }
+ case WM_SIZE: {
/* The WM_SIZE message is sent to a window after its size has changed.
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
* WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
@@ -1977,15 +1944,17 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
*/
event = processWindowSizeEvent(window);
break;
- case WM_CAPTURECHANGED:
+ }
+ case WM_CAPTURECHANGED: {
window->lostMouseCapture();
break;
+ }
case WM_MOVING:
/* The WM_MOVING message is sent to a window that the user is moving. By processing
* this message, an application can monitor the size and position of the drag rectangle
* and, if needed, change its size or position.
*/
- case WM_MOVE:
+ case WM_MOVE: {
/* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
* WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
* to perform any move or size change processing during the WM_WINDOWPOSCHANGED
@@ -2001,33 +1970,33 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
- case WM_DPICHANGED:
+ }
+ case WM_DPICHANGED: {
/* The WM_DPICHANGED message is sent when the effective dots per inch (dpi) for a
* window has changed. The DPI is the scale factor for a window. There are multiple
* events that can cause the DPI to change such as when the window is moved to a monitor
- * with a different DPI.
- */
- {
- // The suggested new size and position of the window.
- RECT *const suggestedWindowRect = (RECT *)lParam;
+ * with a different DPI. */
- // Push DPI change event first
- system->pushEvent(processWindowEvent(GHOST_kEventWindowDPIHintChanged, window));
- system->dispatchEvents();
- eventHandled = true;
+ /* The suggested new size and position of the window. */
+ RECT *const suggestedWindowRect = (RECT *)lParam;
- // Then move and resize window
- SetWindowPos(hwnd,
- NULL,
- suggestedWindowRect->left,
- suggestedWindowRect->top,
- suggestedWindowRect->right - suggestedWindowRect->left,
- suggestedWindowRect->bottom - suggestedWindowRect->top,
- SWP_NOZORDER | SWP_NOACTIVATE);
+ /* Push DPI change event first. */
+ system->pushEvent(processWindowEvent(GHOST_kEventWindowDPIHintChanged, window));
+ system->dispatchEvents();
+ eventHandled = true;
- window->updateDPI();
- }
+ /* Then move and resize window. */
+ SetWindowPos(hwnd,
+ NULL,
+ suggestedWindowRect->left,
+ suggestedWindowRect->top,
+ suggestedWindowRect->right - suggestedWindowRect->left,
+ suggestedWindowRect->bottom - suggestedWindowRect->top,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+
+ window->updateDPI();
break;
+ }
case WM_DISPLAYCHANGE: {
GHOST_Wintab *wt = window->getWintab();
if (wt) {
@@ -2035,7 +2004,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
}
- case WM_KILLFOCUS:
+ case WM_KILLFOCUS: {
/* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard
* focus. We want to prevent this if a window is still active and it loses focus to
* nowhere. */
@@ -2043,73 +2012,73 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
::SetFocus(hwnd);
}
break;
- case WM_SETTINGCHANGE:
+ }
+ case WM_SETTINGCHANGE: {
/* Microsoft: "Note that some applications send this message with lParam set to NULL" */
if ((lParam != NULL) && (wcscmp(LPCWSTR(lParam), L"ImmersiveColorSet") == 0)) {
window->ThemeRefresh();
}
break;
- ////////////////////////////////////////////////////////////////////////
- // Window events, ignored
- ////////////////////////////////////////////////////////////////////////
+ }
+ /* ======================
+ * Window events, ignored
+ * ====================== */
case WM_WINDOWPOSCHANGED:
- /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
- * in the Z order has changed as a result of a call to the SetWindowPos function or
- * another window-management function.
- * The WM_SIZE and WM_MOVE messages are not sent if an application handles the
- * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
- * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
- * message without calling DefWindowProc.
- */
+ /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
+ * in the Z order has changed as a result of a call to the SetWindowPos function or
+ * another window-management function.
+ * The WM_SIZE and WM_MOVE messages are not sent if an application handles the
+ * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
+ * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
+ * message without calling DefWindowProc.
+ */
case WM_ERASEBKGND:
- /* An application sends the WM_ERASEBKGND message when the window background must be
- * erased (for example, when a window is resized). The message is sent to prepare an
- * invalidated portion of a window for painting.
- */
+ /* An application sends the WM_ERASEBKGND message when the window background must be
+ * erased (for example, when a window is resized). The message is sent to prepare an
+ * invalidated portion of a window for painting. */
case WM_NCPAINT:
- /* An application sends the WM_NCPAINT message to a window
- * when its frame must be painted. */
+ /* An application sends the WM_NCPAINT message to a window
+ * when its frame must be painted. */
case WM_NCACTIVATE:
- /* The WM_NCACTIVATE message is sent to a window when its non-client area needs to be
- * changed to indicate an active or inactive state. */
+ /* The WM_NCACTIVATE message is sent to a window when its non-client area needs to be
+ * changed to indicate an active or inactive state. */
case WM_DESTROY:
- /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the
- * window procedure of the window being destroyed after the window is removed from the
- * screen. This message is sent first to the window being destroyed and then to the child
- * windows (if any) as they are destroyed. During the processing of the message, it can
- * be assumed that all child windows still exist. */
- case WM_NCDESTROY:
+ /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the
+ * window procedure of the window being destroyed after the window is removed from the
+ * screen. This message is sent first to the window being destroyed and then to the child
+ * windows (if any) as they are destroyed. During the processing of the message, it can
+ * be assumed that all child windows still exist. */
+ case WM_NCDESTROY: {
/* The WM_NCDESTROY message informs a window that its non-client area is being
* destroyed. The DestroyWindow function sends the WM_NCDESTROY message to the window
* following the WM_DESTROY message. WM_DESTROY is used to free the allocated memory
* object associated with the window.
*/
break;
+ }
case WM_SHOWWINDOW:
- /* The WM_SHOWWINDOW message is sent to a window when the window is
- * about to be hidden or shown. */
+ /* The WM_SHOWWINDOW message is sent to a window when the window is
+ * about to be hidden or shown. */
case WM_WINDOWPOSCHANGING:
- /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in
- * the Z order is about to change as a result of a call to the SetWindowPos function or
- * another window-management function.
- */
- case WM_SETFOCUS:
+ /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in
+ * the Z order is about to change as a result of a call to the SetWindowPos function or
+ * another window-management function. */
+ case WM_SETFOCUS: {
/* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
break;
- ////////////////////////////////////////////////////////////////////////
- // Other events
- ////////////////////////////////////////////////////////////////////////
+ }
+ /* ============
+ * Other events
+ * ============ */
case WM_GETTEXT:
- /* An application sends a WM_GETTEXT message to copy the text that
- * corresponds to a window into a buffer provided by the caller.
- */
+ /* An application sends a WM_GETTEXT message to copy the text that
+ * corresponds to a window into a buffer provided by the caller. */
case WM_ACTIVATEAPP:
- /* The WM_ACTIVATEAPP message is sent when a window belonging to a
- * different application than the active window is about to be activated.
- * The message is sent to the application whose window is being activated
- * and to the application whose window is being deactivated.
- */
- case WM_TIMER:
+ /* The WM_ACTIVATEAPP message is sent when a window belonging to a
+ * different application than the active window is about to be activated.
+ * The message is sent to the application whose window is being activated
+ * and to the application whose window is being deactivated. */
+ case WM_TIMER: {
/* The WIN32 docs say:
* The WM_TIMER message is posted to the installing thread's message queue
* when a timer expires. You can process the message by providing a WM_TIMER
@@ -2117,19 +2086,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* call the TimerProc callback function specified in the call to the SetTimer
* function used to install the timer.
*
- * In GHOST, we let DefWindowProc call the timer callback.
- */
+ * In GHOST, we let DefWindowProc call the timer callback. */
break;
- case DM_POINTERHITTEST:
+ }
+ case DM_POINTERHITTEST: {
/* The DM_POINTERHITTEST message is sent to a window, when pointer input is first
* detected, in order to determine the most probable input target for Direct
* Manipulation. */
window->onPointerHitTest(wParam);
break;
+ }
}
}
else {
- // Event found for a window before the pointer to the class has been set.
+ /* Event found for a window before the pointer to the class has been set. */
GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n");
/* These are events we typically miss at this point:
* WM_GETMINMAXINFO 0x24
@@ -2141,7 +2111,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
}
else {
- // Events without valid hwnd
+ /* Events without valid `hwnd`. */
GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n");
}
@@ -2150,16 +2120,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
eventHandled = true;
}
- if (!eventHandled)
+ if (!eventHandled) {
lResult = ::DefWindowProcW(hwnd, msg, wParam, lParam);
+ }
return lResult;
}
char *GHOST_SystemWin32::getClipboard(bool selection) const
{
- char *temp_buff;
-
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) {
wchar_t *buffer;
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
@@ -2173,7 +2142,7 @@ char *GHOST_SystemWin32::getClipboard(bool selection) const
return NULL;
}
- temp_buff = alloc_utf_8_from_16(buffer, 0);
+ char *temp_buff = alloc_utf_8_from_16(buffer, 0);
/* Buffer mustn't be accessed after CloseClipboard
* it would like accessing free-d memory */
@@ -2182,7 +2151,7 @@ char *GHOST_SystemWin32::getClipboard(bool selection) const
return temp_buff;
}
- else if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
+ if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
char *buffer;
size_t len = 0;
HANDLE hData = GetClipboardData(CF_TEXT);
@@ -2197,7 +2166,7 @@ char *GHOST_SystemWin32::getClipboard(bool selection) const
}
len = strlen(buffer);
- temp_buff = (char *)malloc(len + 1);
+ char *temp_buff = (char *)malloc(len + 1);
strncpy(temp_buff, buffer, len);
temp_buff[len] = '\0';
@@ -2208,21 +2177,19 @@ char *GHOST_SystemWin32::getClipboard(bool selection) const
return temp_buff;
}
- else {
- return NULL;
- }
+ return nullptr;
}
void GHOST_SystemWin32::putClipboard(const char *buffer, bool selection) const
{
if (selection || !buffer) {
return;
- } // for copying the selection, used on X11
+ } /* For copying the selection, used on X11. */
if (OpenClipboard(NULL)) {
EmptyClipboard();
- // Get length of buffer including the terminating null
+ /* Get length of buffer including the terminating null. */
size_t len = count_utf_16_from_8(buffer);
HGLOBAL clipbuffer = GlobalAlloc(GMEM_MOVEABLE, sizeof(wchar_t) * len);
@@ -2279,7 +2246,7 @@ GHOST_TSuccess GHOST_SystemWin32::showMessageBox(const char *title,
case IDCONTINUE:
break;
default:
- break; // should never happen
+ break; /* Should never happen. */
}
free((void *)title_16);
@@ -2347,14 +2314,15 @@ static bool isStartedFromCommandPrompt()
}
/* When we're starting from a wrapper we need to compare with parent process ID. */
- if (pid != (start_from_launcher ? ppid : GetCurrentProcessId()))
+ if (pid != (start_from_launcher ? ppid : GetCurrentProcessId())) {
return true;
+ }
}
return false;
}
-int GHOST_SystemWin32::setConsoleWindowState(GHOST_TConsoleWindowState action)
+bool GHOST_SystemWin32::setConsoleWindowState(GHOST_TConsoleWindowState action)
{
HWND wnd = GetConsoleWindow();
@@ -2362,28 +2330,31 @@ int GHOST_SystemWin32::setConsoleWindowState(GHOST_TConsoleWindowState action)
case GHOST_kConsoleWindowStateHideForNonConsoleLaunch: {
if (!isStartedFromCommandPrompt()) {
ShowWindow(wnd, SW_HIDE);
- m_consoleStatus = 0;
+ m_consoleStatus = false;
}
break;
}
- case GHOST_kConsoleWindowStateHide:
+ case GHOST_kConsoleWindowStateHide: {
ShowWindow(wnd, SW_HIDE);
- m_consoleStatus = 0;
+ m_consoleStatus = false;
break;
- case GHOST_kConsoleWindowStateShow:
+ }
+ case GHOST_kConsoleWindowStateShow: {
ShowWindow(wnd, SW_SHOW);
if (!isStartedFromCommandPrompt()) {
DeleteMenu(GetSystemMenu(wnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
}
- m_consoleStatus = 1;
+ m_consoleStatus = true;
break;
- case GHOST_kConsoleWindowStateToggle:
+ }
+ case GHOST_kConsoleWindowStateToggle: {
ShowWindow(wnd, m_consoleStatus ? SW_HIDE : SW_SHOW);
m_consoleStatus = !m_consoleStatus;
if (m_consoleStatus && !isStartedFromCommandPrompt()) {
DeleteMenu(GetSystemMenu(wnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
}
break;
+ }
}
return m_consoleStatus;
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index b40f5e3fd75..f5cd0055b34 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -10,10 +10,10 @@
#ifndef WIN32
# error WIN32 only!
-#endif // WIN32
+#endif /* WIN32 */
#define WIN32_LEAN_AND_MEAN
-#include <ole2.h> // for drag-n-drop
+#include <ole2.h> /* For drag-n-drop. */
#include <windows.h>
#include "GHOST_System.h"
@@ -105,7 +105,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param state: The state of the window when opened.
* \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
- * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
+ * \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
* \return The new window (or 0 if creation failed).
*/
@@ -295,11 +295,10 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Catches raw WIN32 key codes from WM_INPUT in the wndproc.
* \param raw: RawInput structure with detailed info about the key event.
- * \param keyDown: Pointer flag that specify if a key is down.
- * \param vk: Pointer to virtual key.
+ * \param r_key_down: Set true when the key is pressed, otherwise false.
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- GHOST_TKey hardKey(RAWINPUT const &raw, bool *r_keyDown, bool *r_is_repeated_modifier);
+ GHOST_TKey hardKey(RAWINPUT const &raw, bool *r_key_down);
/**
* Creates mouse button event.
@@ -387,7 +386,7 @@ class GHOST_SystemWin32 : public GHOST_System {
static GHOST_Event *processImeEvent(GHOST_TEventType type,
GHOST_WindowWin32 *window,
GHOST_TEventImeData *data);
-#endif // WITH_INPUT_IME
+#endif /* WITH_INPUT_IME */
/**
* Handles minimum window size.
@@ -417,19 +416,6 @@ class GHOST_SystemWin32 : public GHOST_System {
void processTrackpad();
/**
- * Returns the local state of the modifier keys (from the message queue).
- * \param keys: The state of the keys.
- */
- inline void retrieveModifierKeys(GHOST_ModifierKeys &keys) const;
-
- /**
- * Stores the state of the modifier keys locally.
- * For internal use only!
- * param keys The new state of the modifier keys.
- */
- inline void storeModifierKeys(const GHOST_ModifierKeys &keys);
-
- /**
* Check current key layout for AltGr
*/
inline void handleKeyboardChange(void);
@@ -444,10 +430,8 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param action: console state
* \return current status (1 -visible, 0 - hidden)
*/
- int setConsoleWindowState(GHOST_TConsoleWindowState action);
+ bool setConsoleWindowState(GHOST_TConsoleWindowState action);
- /** The current state of the modifier keys. */
- GHOST_ModifierKeys m_modifierKeys;
/** The virtual-key code (VKey) of the last press event. Used to detect repeat events. */
unsigned short m_keycode_last_repeat_key;
/** State variable set at initialization. */
@@ -466,36 +450,26 @@ class GHOST_SystemWin32 : public GHOST_System {
HKL m_keylayout;
/** Console status. */
- int m_consoleStatus;
+ bool m_consoleStatus;
/** Wheel delta accumulator. */
int m_wheelDeltaAccum;
};
-inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys &keys) const
-{
- keys = m_modifierKeys;
-}
-
-inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys &keys)
-{
- m_modifierKeys = keys;
-}
-
inline void GHOST_SystemWin32::handleKeyboardChange(void)
{
- m_keylayout = GetKeyboardLayout(0); // get keylayout for current thread
+ m_keylayout = GetKeyboardLayout(0); /* Get keylayout for current thread. */
int i;
SHORT s;
- // save the language identifier.
+ /* Save the language identifier. */
m_langId = LOWORD(m_keylayout);
for (m_hasAltGr = false, i = 32; i < 256; ++i) {
s = VkKeyScanEx((char)i, m_keylayout);
- // s == -1 means no key that translates passed char code
- // high byte contains shift state. bit 2 ctrl pressed, bit 4 alt pressed
- // if both are pressed, we have AltGr keycombo on keylayout
+ /* `s == -1` means no key that translates passed char code high byte contains shift state.
+ * bit 2 Control pressed, bit 4 `Alt` pressed if both are pressed,
+ * we have `AltGr` key-combination on key-layout. */
if (s != -1 && (s & 0x600) == 0x600) {
m_hasAltGr = true;
break;
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 0494e462bfc..08ac0edb7ec 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -33,12 +33,8 @@
#include "GHOST_Debug.h"
-#if defined(WITH_GL_EGL)
-# include "GHOST_ContextEGL.h"
-# include <EGL/eglext.h>
-#else
-# include "GHOST_ContextGLX.h"
-#endif
+#include "GHOST_ContextEGL.h"
+#include "GHOST_ContextGLX.h"
#ifdef WITH_XF86KEYSYM
# include <X11/XF86keysym.h>
@@ -105,8 +101,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(nullptr), m_sta
m_display = XOpenDisplay(nullptr);
if (!m_display) {
- std::cerr << "Unable to open a display" << std::endl;
- abort(); /* was return before, but this would just mean it will crash later */
+ throw std::runtime_error("X11: Unable to open a display");
}
#ifdef USE_X11_ERROR_HANDLERS
@@ -235,10 +230,6 @@ GHOST_SystemX11::~GHOST_SystemX11()
clearXInputDevices();
#endif /* WITH_X11_XINPUT */
-#ifdef WITH_GL_EGL
- ::eglTerminate(::eglGetDisplay(m_display));
-#endif
-
if (m_xkb_descr) {
XkbFreeKeyboard(m_xkb_descr, XkbAllComponentsMask, true);
}
@@ -354,7 +345,6 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive,
- ((glSettings.flags & GHOST_glAlphaBackground) != 0),
(glSettings.flags & GHOST_glDebugContext) != 0);
if (window) {
@@ -375,6 +365,56 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
return window;
}
+#ifdef USE_EGL
+static GHOST_Context *create_egl_context(
+ GHOST_SystemX11 *system, Display *display, bool debug_context, int ver_major, int ver_minor)
+{
+ GHOST_Context *context;
+ context = new GHOST_ContextEGL(system,
+ false,
+ EGLNativeWindowType(nullptr),
+ EGLNativeDisplayType(display),
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ ver_major,
+ ver_minor,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS |
+ (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ delete context;
+
+ return nullptr;
+}
+#endif
+
+static GHOST_Context *create_glx_context(Display *display,
+ bool debug_context,
+ int ver_major,
+ int ver_minor)
+{
+ GHOST_Context *context;
+ context = new GHOST_ContextGLX(false,
+ (Window) nullptr,
+ display,
+ (GLXFBConfig) nullptr,
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ ver_major,
+ ver_minor,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS |
+ (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ delete context;
+
+ return nullptr;
+}
/**
* Create a new off-screen context.
* Never explicitly delete the context, use #disposeContext() instead.
@@ -394,98 +434,33 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
-#if defined(WITH_GL_PROFILE_CORE)
- {
- const char *version_major = (char *)glewGetString(GLEW_VERSION_MAJOR);
- if (version_major != nullptr && version_major[0] == '1') {
- fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
- abort();
- }
- }
-#endif
-
- const int profile_mask =
-#ifdef WITH_GL_EGL
-# if defined(WITH_GL_PROFILE_CORE)
- EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
-# elif defined(WITH_GL_PROFILE_COMPAT)
- EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
-# else
-# error // must specify either core or compat at build time
-# endif
-#else
-# if defined(WITH_GL_PROFILE_CORE)
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
-# elif defined(WITH_GL_PROFILE_COMPAT)
- GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
-# else
-# error // must specify either core or compat at build time
-# endif
-#endif
-
GHOST_Context *context;
+#ifdef USE_EGL
+ /* Try to initialize an EGL context. */
for (int minor = 5; minor >= 0; --minor) {
-#if defined(WITH_GL_EGL)
- context = new GHOST_ContextEGL(this,
- false,
- EGLNativeWindowType(nullptr),
- EGLNativeDisplayType(m_display),
- profile_mask,
- 4,
- minor,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS |
- (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
- context = new GHOST_ContextGLX(false,
- (Window) nullptr,
- m_display,
- (GLXFBConfig) nullptr,
- profile_mask,
- 4,
- minor,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS |
- (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#endif
-
- if (context->initializeDrawingContext()) {
+ context = create_egl_context(this, m_display, debug_context, 4, minor);
+ if (context != nullptr) {
return context;
}
- delete context;
+ }
+ context = create_egl_context(this, m_display, debug_context, 3, 3);
+ if (context != nullptr) {
+ return context;
}
-#if defined(WITH_GL_EGL)
- context = new GHOST_ContextEGL(this,
- false,
- EGLNativeWindowType(nullptr),
- EGLNativeDisplayType(m_display),
- profile_mask,
- 3,
- 3,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS |
- (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
- context = new GHOST_ContextGLX(false,
- (Window) nullptr,
- m_display,
- (GLXFBConfig) nullptr,
- profile_mask,
- 3,
- 3,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS |
- (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+ /* EGL initialization failed, try to fallback to a GLX context. */
#endif
-
- if (context->initializeDrawingContext()) {
+ for (int minor = 5; minor >= 0; --minor) {
+ context = create_glx_context(m_display, debug_context, 4, minor);
+ if (context != nullptr) {
+ return context;
+ }
+ }
+ context = create_glx_context(m_display, debug_context, 3, 3);
+ if (context != nullptr) {
return context;
}
- delete context;
return nullptr;
}
@@ -1090,7 +1065,8 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
case GHOST_kKeyLeftShift:
case GHOST_kKeyRightControl:
case GHOST_kKeyLeftControl:
- case GHOST_kKeyOS:
+ case GHOST_kKeyLeftOS:
+ case GHOST_kKeyRightOS:
case GHOST_kKey0:
case GHOST_kKey1:
case GHOST_kKey2:
@@ -1625,9 +1601,10 @@ GHOST_TSuccess GHOST_SystemX11::getModifierKeys(GHOST_ModifierKeys &keys) const
keys.set(GHOST_kModifierKeyLeftAlt, ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) != 0);
keys.set(GHOST_kModifierKeyRightAlt, ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) != 0);
/* super (windows) - only one GHOST-kModifierKeyOS, so mapping to either */
- keys.set(GHOST_kModifierKeyOS,
- (((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) ||
- ((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1)) != 0);
+ keys.set(GHOST_kModifierKeyLeftOS,
+ ((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) != 0);
+ keys.set(GHOST_kModifierKeyRightOS,
+ ((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1) != 0);
return GHOST_kSuccess;
}
@@ -1843,8 +1820,8 @@ static GHOST_TKey ghost_key_from_keysym(const KeySym key)
GXMAP(type, XK_Control_R, GHOST_kKeyRightControl);
GXMAP(type, XK_Alt_L, GHOST_kKeyLeftAlt);
GXMAP(type, XK_Alt_R, GHOST_kKeyRightAlt);
- GXMAP(type, XK_Super_L, GHOST_kKeyOS);
- GXMAP(type, XK_Super_R, GHOST_kKeyOS);
+ GXMAP(type, XK_Super_L, GHOST_kKeyLeftOS);
+ GXMAP(type, XK_Super_R, GHOST_kKeyRightOS);
GXMAP(type, XK_Insert, GHOST_kKeyInsert);
GXMAP(type, XK_Delete, GHOST_kKeyDelete);
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 7938aa2b646..33376d36a92 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -115,7 +115,7 @@ class GHOST_SystemX11 : public GHOST_System {
* \param state: The state of the window when opened.
* \param type: The type of drawing context installed in this window.
* \param stereoVisual: Create a stereo visual for quad buffered stereo.
- * \param exclusive: Use to show the window ontop and ignore others (used full*screen).
+ * \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
* \return The new window (or 0 if creation failed).
*/
@@ -253,7 +253,7 @@ class GHOST_SystemX11 : public GHOST_System {
/**
* \see GHOST_ISystem
*/
- int setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
+ bool setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
{
return 0;
}
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index db4d6c3bb71..da292a90869 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -92,6 +92,11 @@ GHOST_TSuccess GHOST_Window::getSwapInterval(int &intervalOut)
return m_context->getSwapInterval(intervalOut);
}
+GHOST_Context *GHOST_Window::getContext()
+{
+ return m_context;
+}
+
unsigned int GHOST_Window::getDefaultFramebuffer()
{
return (m_context) ? m_context->getDefaultFramebuffer() : 0;
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 5ff91c05b16..1c0991bba30 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -29,7 +29,7 @@ class GHOST_Window : public GHOST_IWindow {
* \param height: The height of the window.
* \param state: The state the window is initially opened with.
* \param wantStereoVisual: Stereo visual for quad buffered stereo.
- * \param exclusive: Use to show the window ontop and ignore others (used full-screen).
+ * \param exclusive: Use to show the window on top and ignore others (used full-screen).
*/
GHOST_Window(uint32_t width,
uint32_t height,
@@ -72,7 +72,7 @@ class GHOST_Window : public GHOST_IWindow {
* Returns indication as to whether the window is valid.
* \return The validity of the window.
*/
- virtual bool getValid() const
+ virtual bool getValid() const override
{
return m_context != NULL;
}
@@ -81,15 +81,15 @@ class GHOST_Window : public GHOST_IWindow {
* Returns the associated OS object/handle
* \return The associated OS object/handle
*/
- virtual void *getOSWindow() const;
+ virtual void *getOSWindow() const override;
/**
* Returns the current cursor shape.
* \return The current cursor shape.
*/
- inline GHOST_TStandardCursor getCursorShape() const;
+ inline GHOST_TStandardCursor getCursorShape() const override;
- inline bool isDialog() const
+ inline bool isDialog() const override
{
return false;
}
@@ -99,7 +99,7 @@ class GHOST_Window : public GHOST_IWindow {
* \param cursorShape: The new cursor shape type id.
* \return Indication of success.
*/
- GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
+ GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) override;
/**
* Set the shape of the cursor to a custom cursor.
@@ -115,15 +115,15 @@ class GHOST_Window : public GHOST_IWindow {
int sizey,
int hotX,
int hotY,
- bool canInvertColor);
+ bool canInvertColor) override;
- GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap);
+ GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap) override;
/**
* Returns the visibility state of the cursor.
* \return The visibility state of the cursor.
*/
- inline bool getCursorVisibility() const;
+ inline bool getCursorVisibility() const override;
inline GHOST_TGrabCursorMode getCursorGrabMode() const;
inline bool getCursorGrabModeIsWarp() const;
inline GHOST_TAxisFlag getCursorGrabAxis() const;
@@ -136,7 +136,7 @@ class GHOST_Window : public GHOST_IWindow {
* \param visible: The new visibility state of the cursor.
* \return Indication of success.
*/
- GHOST_TSuccess setCursorVisibility(bool visible);
+ GHOST_TSuccess setCursorVisibility(bool visible) override;
/**
* Sets the cursor grab.
@@ -146,28 +146,28 @@ class GHOST_Window : public GHOST_IWindow {
GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode,
GHOST_TAxisFlag wrap_axis,
GHOST_Rect *bounds,
- int32_t mouse_ungrab_xy[2]);
+ int32_t mouse_ungrab_xy[2]) override;
/**
* Gets the cursor grab region, if unset the window is used.
* reset when grab is disabled.
*/
- GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds);
+ GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) override;
void getCursorGrabState(GHOST_TGrabCursorMode &mode,
GHOST_TAxisFlag &axis_flag,
GHOST_Rect &bounds,
- bool &use_software_cursor);
+ bool &use_software_cursor) override;
/**
* Return true when a software cursor should be used.
*/
- bool getCursorGrabUseSoftwareDisplay();
+ bool getCursorGrabUseSoftwareDisplay() override;
/**
* Sets the progress bar value displayed in the window/application icon
* \param progress: The progress percentage (0.0 to 1.0).
*/
- virtual GHOST_TSuccess setProgressBar(float /*progress*/)
+ virtual GHOST_TSuccess setProgressBar(float /*progress*/) override
{
return GHOST_kFailure;
}
@@ -175,7 +175,7 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Hides the progress bar in the icon
*/
- virtual GHOST_TSuccess endProgressBar()
+ virtual GHOST_TSuccess endProgressBar() override
{
return GHOST_kFailure;
}
@@ -185,43 +185,43 @@ class GHOST_Window : public GHOST_IWindow {
* \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
- GHOST_TSuccess setSwapInterval(int interval);
+ GHOST_TSuccess setSwapInterval(int interval) override;
/**
* Gets the current swap interval for #swapBuffers.
* \return An integer.
*/
- GHOST_TSuccess getSwapInterval(int &intervalOut);
+ GHOST_TSuccess getSwapInterval(int &intervalOut) override;
/**
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
*/
- void setAcceptDragOperation(bool canAccept);
+ void setAcceptDragOperation(bool canAccept) override;
/**
* Returns acceptance of the dropped object
* Usually called by the "object dropped" event handling function
*/
- bool canAcceptDragOperation() const;
+ bool canAcceptDragOperation() const override;
/**
* Sets the window "modified" status, indicating unsaved changes
* \param isUnsavedChanges: Unsaved changes or not.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
+ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) override;
/**
* Gets the window "modified" status, indicating unsaved changes
* \return True if there are unsaved changes
*/
- virtual bool getModifiedState();
+ virtual bool getModifiedState() override;
/**
* Returns the type of drawing context used in this window.
* \return The current type of drawing context.
*/
- inline GHOST_TDrawingContextType getDrawingContextType();
+ inline GHOST_TDrawingContextType getDrawingContextType() override;
/**
* Tries to install a rendering context in this window.
@@ -230,19 +230,19 @@ class GHOST_Window : public GHOST_IWindow {
* \param type: The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
- GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
+ GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) override;
/**
* Swaps front and back buffers of a window.
* \return A boolean success indicator.
*/
- virtual GHOST_TSuccess swapBuffers();
+ virtual GHOST_TSuccess swapBuffers() override;
/**
* Activates the drawing context of this window.
* \return A boolean success indicator.
*/
- virtual GHOST_TSuccess activateDrawingContext();
+ virtual GHOST_TSuccess activateDrawingContext() override;
/**
* Updates the drawing context of this window. Needed
@@ -252,16 +252,22 @@ class GHOST_Window : public GHOST_IWindow {
GHOST_TSuccess updateDrawingContext();
/**
+ * Get the drawing context associated with this window.
+ *\return Pointer to the context object.
+ */
+ GHOST_Context *getContext();
+
+ /**
* Gets the OpenGL frame-buffer associated with the window's contents.
* \return The ID of an OpenGL frame-buffer object.
*/
- virtual unsigned int getDefaultFramebuffer();
+ virtual unsigned int getDefaultFramebuffer() override;
/**
* Returns the window user data.
* \return The window user data.
*/
- inline GHOST_TUserDataPtr getUserData() const
+ inline GHOST_TUserDataPtr getUserData() const override
{
return m_userData;
}
@@ -270,12 +276,12 @@ class GHOST_Window : public GHOST_IWindow {
* Changes the window user data.
* \param userData: The window user data.
*/
- void setUserData(const GHOST_TUserDataPtr userData)
+ void setUserData(const GHOST_TUserDataPtr userData) override
{
m_userData = userData;
}
- float getNativePixelSize(void)
+ float getNativePixelSize(void) override
{
if (m_nativePixelSize > 0.0f)
return m_nativePixelSize;
@@ -286,18 +292,18 @@ class GHOST_Window : public GHOST_IWindow {
* Returns the recommended DPI for this window.
* \return The recommended DPI for this window.
*/
- virtual inline uint16_t getDPIHint()
+ virtual inline uint16_t getDPIHint() override
{
return 96;
}
#ifdef WITH_INPUT_IME
- virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed)
+ virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) override
{
/* do nothing temporarily if not in windows */
}
- virtual void endIME()
+ virtual void endIME() override
{
/* do nothing temporarily if not in windows */
}
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index e7f5fdaa011..737fd64bdf0 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -719,7 +719,7 @@ void GHOST_WindowCocoa::setNativePixelSize(void)
}
/**
- * \note Fullscreen switch is not actual fullscreen with display capture.
+ * \note Full-screen switch is not actual fullscreen with display capture.
* As this capture removes all OS X window manager features.
*
* Instead, the menu bar and the dock are hidden, and the window is made border-less and enlarged.
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
index bf7a0f4ec61..a0a58fa82d8 100644
--- a/intern/ghost/intern/GHOST_WindowManager.h
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -113,13 +113,13 @@ class GHOST_WindowManager {
/** The list of windows managed */
std::vector<GHOST_IWindow *> m_windows;
- /** Window in fullscreen state. There can be only one of this which is not in or window list. */
+ /** Window in full-screen state. There can be only one of this which is not in or window list. */
GHOST_IWindow *m_fullScreenWindow;
/** The active window. */
GHOST_IWindow *m_activeWindow;
- /** Window that was active before entering fullscreen state. */
+ /** Window that was active before entering full-screen state. */
GHOST_IWindow *m_activeWindowBeforeFullScreen;
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index 01b50251d69..f9c0a593d5f 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -11,32 +11,31 @@
#include <map>
-class GHOST_SystemNULL;
+class GHOST_SystemHeadless;
class GHOST_WindowNULL : public GHOST_Window {
public:
- GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor)
+ GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor /*cursorShape*/) override
{
return GHOST_kSuccess;
}
- GHOST_WindowNULL(GHOST_SystemNULL *system,
- const char *title,
- int32_t left,
- int32_t top,
+ GHOST_WindowNULL(const char *title,
+ int32_t /*left*/,
+ int32_t /*top*/,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- const GHOST_IWindow *parentWindow,
- GHOST_TDrawingContextType type,
+ const GHOST_IWindow * /*parentWindow*/,
+ GHOST_TDrawingContextType /*type*/,
const bool stereoVisual)
- : GHOST_Window(width, height, state, stereoVisual, false), m_system(system)
+ : GHOST_Window(width, height, state, stereoVisual, false)
{
setTitle(title);
}
protected:
- GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type)
+ GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType /*type*/)
{
return GHOST_kSuccess;
}
@@ -44,114 +43,111 @@ class GHOST_WindowNULL : public GHOST_Window {
{
return GHOST_kSuccess;
}
- GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode)
+ GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode /*mode*/) override
{
return GHOST_kSuccess;
}
- GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape)
+ GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor /*shape*/) override
{
return GHOST_kSuccess;
}
- GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
- uint8_t *mask,
- int sizex,
- int sizey,
- int hotX,
- int hotY,
- bool canInvertColor)
+ GHOST_TSuccess setWindowCustomCursorShape(uint8_t * /*bitmap*/,
+ uint8_t * /*mask*/,
+ int /*sizex*/,
+ int /*sizey*/,
+ int /*hotX*/,
+ int /*hotY*/,
+ bool /*canInvertColor*/) override
{
return GHOST_kSuccess;
}
- bool getValid() const
+ bool getValid() const override
{
return true;
}
- void setTitle(const char *title)
+ void setTitle(const char * /*title*/) override
{ /* nothing */
}
- std::string getTitle() const
+ std::string getTitle() const override
{
return "untitled";
}
- void getWindowBounds(GHOST_Rect &bounds) const
+ void getWindowBounds(GHOST_Rect &bounds) const override
{
getClientBounds(bounds);
}
- void getClientBounds(GHOST_Rect &bounds) const
+ void getClientBounds(GHOST_Rect & /*bounds*/) const override
{ /* nothing */
}
- GHOST_TSuccess setClientWidth(uint32_t width)
+ GHOST_TSuccess setClientWidth(uint32_t /*width*/) override
{
return GHOST_kFailure;
}
- GHOST_TSuccess setClientHeight(uint32_t height)
+ GHOST_TSuccess setClientHeight(uint32_t /*height*/) override
{
return GHOST_kFailure;
}
- GHOST_TSuccess setClientSize(uint32_t width, uint32_t height)
+ GHOST_TSuccess setClientSize(uint32_t /*width*/, uint32_t /*height*/) override
{
return GHOST_kFailure;
}
- void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
+ void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
{
outX = inX;
outY = inY;
}
- void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
+ void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
{
outX = inX;
outY = inY;
}
- GHOST_TSuccess swapBuffers()
+ GHOST_TSuccess swapBuffers() override
{
return GHOST_kFailure;
}
- GHOST_TSuccess activateDrawingContext()
+ GHOST_TSuccess activateDrawingContext() override
{
return GHOST_kFailure;
}
- ~GHOST_WindowNULL()
- { /* nothing */
- }
- GHOST_TSuccess setWindowCursorVisibility(bool visible)
+ ~GHOST_WindowNULL() override = default;
+
+ GHOST_TSuccess setWindowCursorVisibility(bool /*visible*/) override
{
return GHOST_kSuccess;
}
- GHOST_TSuccess setState(GHOST_TWindowState state)
+ GHOST_TSuccess setState(GHOST_TWindowState /*state*/) override
{
return GHOST_kSuccess;
}
- GHOST_TWindowState getState() const
+ GHOST_TWindowState getState() const override
{
return GHOST_kWindowStateNormal;
}
- GHOST_TSuccess invalidate()
+ GHOST_TSuccess invalidate() override
{
return GHOST_kSuccess;
}
- GHOST_TSuccess setOrder(GHOST_TWindowOrder order)
+ GHOST_TSuccess setOrder(GHOST_TWindowOrder /*order*/) override
{
return GHOST_kSuccess;
}
- GHOST_TSuccess beginFullScreen() const
+ GHOST_TSuccess beginFullScreen() const override
{
return GHOST_kSuccess;
}
- GHOST_TSuccess endFullScreen() const
+ GHOST_TSuccess endFullScreen() const override
{
return GHOST_kSuccess;
}
private:
- GHOST_SystemNULL *m_system;
-
/**
* \param type: The type of rendering context create.
* \return Indication of success.
*/
- GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type)
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType /*type*/) override
{
return nullptr;
}
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index 09192d989e4..59dc80cf7e6 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -6,7 +6,6 @@
#include "GHOST_WindowSDL.h"
#include "SDL_mouse.h"
-#include "glew-mx.h"
#include "GHOST_ContextSDL.h"
diff --git a/intern/ghost/intern/GHOST_WindowViewCocoa.h b/intern/ghost/intern/GHOST_WindowViewCocoa.h
index 58c029620da..29653bd5ea2 100644
--- a/intern/ghost/intern/GHOST_WindowViewCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowViewCocoa.h
@@ -226,7 +226,7 @@
[super drawRect:rect];
systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
- /* For some cases like entering fullscreen we need to redraw immediately
+ /* For some cases like entering full-screen we need to redraw immediately
* so our window does not show blank during the animation */
if (associatedWindow->getImmediateDraw())
systemCocoa->dispatchEvents();
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index e303bd5b6aa..5f3cb3e3f3a 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -38,7 +38,7 @@ static constexpr size_t base_dpi = 96;
static GHOST_WindowManager *window_manager = nullptr;
-struct window_t {
+struct GWL_Window {
GHOST_WindowWayland *w = nullptr;
struct wl_surface *wl_surface = nullptr;
/**
@@ -47,7 +47,7 @@ struct window_t {
* This is an ordered set (whoever adds to this is responsible for keeping members unique).
* In practice this is rarely manipulated and is limited by the number of physical displays.
*/
- std::vector<output_t *> outputs;
+ std::vector<GWL_Output *> outputs;
/** The scale value written to #wl_surface_set_buffer_scale. */
int scale = 0;
@@ -87,7 +87,7 @@ struct window_t {
/**
* Return -1 if `output_a` has a scale smaller than `output_b`, 0 when there equal, otherwise 1.
*/
-static int output_scale_cmp(const output_t *output_a, const output_t *output_b)
+static int output_scale_cmp(const GWL_Output *output_a, const GWL_Output *output_b)
{
if (output_a->scale < output_b->scale) {
return -1;
@@ -112,12 +112,12 @@ static int output_scale_cmp(const output_t *output_a, const output_t *output_b)
return 0;
}
-static int outputs_max_scale_or_default(const std::vector<output_t *> &outputs,
+static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs,
const int32_t scale_default,
uint32_t *r_dpi)
{
- const output_t *output_max = nullptr;
- for (const output_t *reg_output : outputs) {
+ const GWL_Output *output_max = nullptr;
+ for (const GWL_Output *reg_output : outputs) {
if (!output_max || (output_scale_cmp(output_max, reg_output) == -1)) {
output_max = reg_output;
}
@@ -160,7 +160,7 @@ static void xdg_toplevel_handle_configure(void *data,
/* TODO: log `states`, not urgent. */
CLOG_INFO(LOG, 2, "configure (size=[%d, %d])", width, height);
- window_t *win = static_cast<window_t *>(data);
+ GWL_Window *win = static_cast<GWL_Window *>(data);
win->size_pending[0] = win->scale * width;
win->size_pending[1] = win->scale * height;
@@ -189,7 +189,7 @@ static void xdg_toplevel_handle_configure(void *data,
static void xdg_toplevel_handle_close(void *data, xdg_toplevel * /*xdg_toplevel*/)
{
CLOG_INFO(LOG, 2, "close");
- static_cast<window_t *>(data)->w->close();
+ static_cast<GWL_Window *>(data)->w->close();
}
static const xdg_toplevel_listener toplevel_listener = {
@@ -218,7 +218,7 @@ static void frame_handle_configure(struct libdecor_frame *frame,
{
CLOG_INFO(LOG, 2, "configure");
- window_t *win = static_cast<window_t *>(data);
+ GWL_Window *win = static_cast<GWL_Window *>(data);
int size_next[2];
enum libdecor_window_state window_state;
@@ -257,7 +257,7 @@ static void frame_handle_close(struct libdecor_frame * /*frame*/, void *data)
{
CLOG_INFO(LOG, 2, "close");
- static_cast<window_t *>(data)->w->close();
+ static_cast<GWL_Window *>(data)->w->close();
}
static void frame_handle_commit(struct libdecor_frame * /*frame*/, void *data)
@@ -265,8 +265,8 @@ static void frame_handle_commit(struct libdecor_frame * /*frame*/, void *data)
CLOG_INFO(LOG, 2, "commit");
/* We have to swap twice to keep any pop-up menus alive. */
- static_cast<window_t *>(data)->w->swapBuffers();
- static_cast<window_t *>(data)->w->swapBuffers();
+ static_cast<GWL_Window *>(data)->w->swapBuffers();
+ static_cast<GWL_Window *>(data)->w->swapBuffers();
}
static struct libdecor_frame_interface libdecor_frame_iface = {
@@ -296,7 +296,7 @@ static void xdg_toplevel_decoration_handle_configure(
const uint32_t mode)
{
CLOG_INFO(LOG, 2, "configure (mode=%u)", mode);
- static_cast<window_t *>(data)->decoration_mode = (zxdg_toplevel_decoration_v1_mode)mode;
+ static_cast<GWL_Window *>(data)->decoration_mode = (zxdg_toplevel_decoration_v1_mode)mode;
}
static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = {
@@ -322,7 +322,7 @@ static void xdg_surface_handle_configure(void *data,
xdg_surface *xdg_surface,
const uint32_t serial)
{
- window_t *win = static_cast<window_t *>(data);
+ GWL_Window *win = static_cast<GWL_Window *>(data);
if (win->xdg_surface != xdg_surface) {
CLOG_INFO(LOG, 2, "configure (skipped)");
@@ -369,15 +369,15 @@ static CLG_LogRef LOG_WL_SURFACE = {"ghost.wl.handle.surface"};
static void surface_handle_enter(void *data,
struct wl_surface * /*wl_surface*/,
- struct wl_output *output)
+ struct wl_output *wl_output)
{
- if (!ghost_wl_output_own(output)) {
+ if (!ghost_wl_output_own(wl_output)) {
CLOG_INFO(LOG, 2, "enter (skipped)");
return;
}
CLOG_INFO(LOG, 2, "enter");
- output_t *reg_output = ghost_wl_output_user_data(output);
+ GWL_Output *reg_output = ghost_wl_output_user_data(wl_output);
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(data);
if (win->outputs_enter(reg_output)) {
win->outputs_changed_update_scale();
@@ -386,15 +386,15 @@ static void surface_handle_enter(void *data,
static void surface_handle_leave(void *data,
struct wl_surface * /*wl_surface*/,
- struct wl_output *output)
+ struct wl_output *wl_output)
{
- if (!ghost_wl_output_own(output)) {
+ if (!ghost_wl_output_own(wl_output)) {
CLOG_INFO(LOG, 2, "leave (skipped)");
return;
}
CLOG_INFO(LOG, 2, "leave");
- output_t *reg_output = ghost_wl_output_user_data(output);
+ GWL_Output *reg_output = ghost_wl_output_user_data(wl_output);
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(data);
if (win->outputs_leave(reg_output)) {
win->outputs_changed_update_scale();
@@ -435,7 +435,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
const bool exclusive)
: GHOST_Window(width, height, state, stereoVisual, exclusive),
m_system(system),
- w(new window_t)
+ w(new GWL_Window)
{
/* Globally store pointer to window manager. */
if (!window_manager) {
@@ -877,12 +877,12 @@ int GHOST_WindowWayland::scale() const
return w->scale;
}
-wl_surface *GHOST_WindowWayland::surface() const
+wl_surface *GHOST_WindowWayland::wl_surface() const
{
return w->wl_surface;
}
-const std::vector<output_t *> &GHOST_WindowWayland::outputs()
+const std::vector<GWL_Output *> &GHOST_WindowWayland::outputs()
{
return w->outputs;
}
@@ -935,6 +935,9 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size()
* Functionality only used for the WAYLAND implementation.
* \{ */
+/**
+ * Return true when the windows scale or DPI changes.
+ */
bool GHOST_WindowWayland::outputs_changed_update_scale()
{
uint32_t dpi_next;
@@ -943,7 +946,7 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
return false;
}
- window_t *win = this->w;
+ GWL_Window *win = this->w;
const uint32_t dpi_curr = win->dpi;
const int scale_curr = win->scale;
bool changed = false;
@@ -963,26 +966,32 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
* use a multiplier for the default DPI as workaround. */
win->dpi = dpi_next;
changed = true;
+
+ /* As this is a low-level function, we might want adding this event to be optional,
+ * always add the event unless it causes issues. */
+ GHOST_System *system = (GHOST_System *)GHOST_ISystem::getSystem();
+ system->pushEvent(
+ new GHOST_Event(system->getMilliSeconds(), GHOST_kEventWindowDPIHintChanged, this));
}
return changed;
}
-bool GHOST_WindowWayland::outputs_enter(output_t *reg_output)
+bool GHOST_WindowWayland::outputs_enter(GWL_Output *output)
{
- std::vector<output_t *> &outputs = w->outputs;
- auto it = std::find(outputs.begin(), outputs.end(), reg_output);
+ std::vector<GWL_Output *> &outputs = w->outputs;
+ auto it = std::find(outputs.begin(), outputs.end(), output);
if (it != outputs.end()) {
return false;
}
- outputs.push_back(reg_output);
+ outputs.push_back(output);
return true;
}
-bool GHOST_WindowWayland::outputs_leave(output_t *reg_output)
+bool GHOST_WindowWayland::outputs_leave(GWL_Output *output)
{
- std::vector<output_t *> &outputs = w->outputs;
- auto it = std::find(outputs.begin(), outputs.end(), reg_output);
+ std::vector<GWL_Output *> &outputs = w->outputs;
+ auto it = std::find(outputs.begin(), outputs.end(), output);
if (it == outputs.end()) {
return false;
}
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index c754e4cd9e7..9b4c17ecd95 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -14,8 +14,8 @@
class GHOST_SystemWayland;
-struct output_t;
-struct window_t;
+struct GWL_Output;
+struct GWL_Window;
class GHOST_WindowWayland : public GHOST_Window {
public:
@@ -97,8 +97,8 @@ class GHOST_WindowWayland : public GHOST_Window {
uint16_t dpi() const;
int scale() const;
- struct wl_surface *surface() const;
- const std::vector<output_t *> &outputs();
+ struct wl_surface *wl_surface() const;
+ const std::vector<GWL_Output *> &outputs();
/* WAYLAND window-level functions. */
@@ -109,14 +109,14 @@ class GHOST_WindowWayland : public GHOST_Window {
/* WAYLAND utility functions. */
- bool outputs_enter(output_t *reg_output);
- bool outputs_leave(output_t *reg_output);
+ bool outputs_enter(GWL_Output *output);
+ bool outputs_leave(GWL_Output *output);
bool outputs_changed_update_scale();
private:
GHOST_SystemWayland *m_system;
- struct window_t *w;
+ struct GWL_Window *w;
std::string title;
/**
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 2e17454d24f..50ee9385e39 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -26,7 +26,7 @@
#ifndef GET_POINTERID_WPARAM
# define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam))
-#endif // GET_POINTERID_WPARAM
+#endif /* GET_POINTERID_WPARAM */
const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
const int GHOST_WindowWin32::s_maxTitleLength = 128;
@@ -93,18 +93,18 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
adjustWindowRectForClosestMonitor(&win_rect, style, extended_style);
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
- m_hWnd = ::CreateWindowExW(extended_style, // window extended style
- s_windowClassName, // pointer to registered class name
- title_16, // pointer to window name
- style, // window style
- win_rect.left, // horizontal position of window
- win_rect.top, // vertical position of window
- win_rect.right - win_rect.left, // window width
- win_rect.bottom - win_rect.top, // window height
- m_parentWindowHwnd, // handle to parent or owner window
- 0, // handle to menu or child-window identifier
- ::GetModuleHandle(0), // handle to application instance
- 0); // pointer to window-creation data
+ m_hWnd = ::CreateWindowExW(extended_style, /* window extended style */
+ s_windowClassName, /* pointer to registered class name */
+ title_16, /* pointer to window name */
+ style, /* window style */
+ win_rect.left, /* horizontal position of window */
+ win_rect.top, /* vertical position of window */
+ win_rect.right - win_rect.left, /* window width */
+ win_rect.bottom - win_rect.top, /* window height */
+ m_parentWindowHwnd, /* handle to parent or owner window */
+ 0, /* handle to menu or child-window identifier */
+ ::GetModuleHandle(0), /* handle to application instance */
+ 0); /* pointer to window-creation data */
free(title_16);
if (m_hWnd == NULL) {
@@ -197,7 +197,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
/* Force an initial paint of the window. */
::UpdateWindow(m_hWnd);
- /* Initialize Wintab. */
+ /* Initialize WINTAB. */
if (system->getTabletAPI() != GHOST_kTabletWinPointer) {
loadWintab(GHOST_kWindowStateMinimized != state);
}
@@ -221,7 +221,7 @@ void GHOST_WindowWin32::updateDirectManipulation()
void GHOST_WindowWin32::onPointerHitTest(WPARAM wParam)
{
- /* Only DM_POINTERHITTEST can be the first message of input sequence of touchpad input. */
+ /* Only #DM_POINTERHITTEST can be the first message of input sequence of touch-pad input. */
if (!m_directManipulationHelper) {
return;
@@ -280,9 +280,9 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
}
if (m_dropTarget) {
- // Disable DragDrop
+ /* Disable DragDrop. */
RevokeDragDrop(m_hWnd);
- // Release our reference of the DropTarget and it will delete itself eventually.
+ /* Release our reference of the DropTarget and it will delete itself eventually. */
m_dropTarget->Release();
m_dropTarget = NULL;
}
@@ -531,7 +531,8 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
break;
}
::SetWindowLongPtr(m_hWnd, GWL_STYLE, style);
- /* SetWindowLongPtr Docs: frame changes not visible until SetWindowPos with SWP_FRAMECHANGED. */
+ /* #SetWindowLongPtr Docs:
+ * Frame changes not visible until #SetWindowPos with #SWP_FRAMECHANGED. */
::SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
}
@@ -580,7 +581,6 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
if (type == GHOST_kDrawingContextTypeOpenGL) {
GHOST_Context *context;
-#if defined(WITH_GL_PROFILE_CORE)
/* - AMD and Intel give us exactly this version
* - NVIDIA gives at least this version <-- desired behavior
* So we ask for 4.5, 4.4 ... 3.3 in descending order
@@ -619,40 +619,14 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
}
return context;
-
-#elif defined(WITH_GL_PROFILE_COMPAT)
- // ask for 2.1 context, driver gives any GL version >= 2.1
- // (hopefully the latest compatibility profile)
- // 2.1 ignores the profile bit & is incompatible with core profile
- context = new GHOST_ContextWGL(m_wantStereoVisual,
- m_wantAlphaBackground,
- m_hWnd,
- m_hDC,
- 0, // no profile bit
- 2,
- 1,
- (m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
-
- if (context->initializeDrawingContext()) {
- return context;
- }
- else {
- delete context;
- }
-#else
-# error // must specify either core or compat at build time
-#endif
}
else if (type == GHOST_kDrawingContextTypeD3D) {
GHOST_Context *context;
context = new GHOST_ContextD3D(false, m_hWnd);
- if (context->initializeDrawingContext()) {
- return context;
- }
- else {
+ if (!context->initializeDrawingContext()) {
delete context;
+ context = nullptr;
}
return context;
@@ -705,7 +679,7 @@ void GHOST_WindowWin32::updateMouseCapture(GHOST_MouseCaptureEventWin32 event)
HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
{
- // Convert GHOST cursor to Windows OEM cursor
+ /* Convert GHOST cursor to Windows OEM cursor. */
HANDLE cursor = NULL;
HMODULE module = ::GetModuleHandle(0);
uint32_t flags = LR_SHARED | LR_DEFAULTSIZE;
@@ -763,36 +737,36 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
break;
case GHOST_kStandardCursorHelp:
cursor = ::LoadImage(NULL, IDC_HELP, IMAGE_CURSOR, cx, cy, flags);
- break; // Arrow and question mark
+ break; /* Arrow and question mark */
case GHOST_kStandardCursorWait:
cursor = ::LoadImage(NULL, IDC_WAIT, IMAGE_CURSOR, cx, cy, flags);
- break; // Hourglass
+ break; /* Hourglass */
case GHOST_kStandardCursorText:
cursor = ::LoadImage(NULL, IDC_IBEAM, IMAGE_CURSOR, cx, cy, flags);
- break; // I-beam
+ break; /* I-beam */
case GHOST_kStandardCursorCrosshair:
cursor = ::LoadImage(module, "cross_cursor", IMAGE_CURSOR, cx, cy, flags);
- break; // Standard Cross
+ break; /* Standard Cross */
case GHOST_kStandardCursorCrosshairA:
cursor = ::LoadImage(module, "crossA_cursor", IMAGE_CURSOR, cx, cy, flags);
- break; // Crosshair A
+ break; /* Crosshair A */
case GHOST_kStandardCursorCrosshairB:
cursor = ::LoadImage(module, "crossB_cursor", IMAGE_CURSOR, cx, cy, flags);
- break; // Diagonal Crosshair B
+ break; /* Diagonal Crosshair B */
case GHOST_kStandardCursorCrosshairC:
cursor = ::LoadImage(module, "crossC_cursor", IMAGE_CURSOR, cx, cy, flags);
- break; // Minimal Crosshair C
+ break; /* Minimal Crosshair C */
case GHOST_kStandardCursorBottomSide:
case GHOST_kStandardCursorUpDown:
cursor = ::LoadImage(module, "movens_cursor", IMAGE_CURSOR, cx, cy, flags);
- break; // Double-pointed arrow pointing north and south
+ break; /* Double-pointed arrow pointing north and south */
case GHOST_kStandardCursorLeftSide:
case GHOST_kStandardCursorLeftRight:
cursor = ::LoadImage(module, "moveew_cursor", IMAGE_CURSOR, cx, cy, flags);
- break; // Double-pointed arrow pointing west and east
+ break; /* Double-pointed arrow pointing west and east */
case GHOST_kStandardCursorTopSide:
cursor = ::LoadImage(NULL, IDC_UPARROW, IMAGE_CURSOR, cx, cy, flags);
- break; // Vertical arrow
+ break; /* Vertical arrow */
case GHOST_kStandardCursorTopLeftCorner:
cursor = ::LoadImage(NULL, IDC_SIZENWSE, IMAGE_CURSOR, cx, cy, flags);
break;
@@ -814,7 +788,7 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
case GHOST_kStandardCursorDestroy:
case GHOST_kStandardCursorStop:
cursor = ::LoadImage(module, "forbidden_cursor", IMAGE_CURSOR, cx, cy, flags);
- break; // Slashed circle
+ break; /* Slashed circle */
case GHOST_kStandardCursorDefault:
cursor = NULL;
break;
@@ -863,8 +837,9 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode
m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
setCursorGrabAccum(0, 0);
- if (mode == GHOST_kGrabHide)
+ if (mode == GHOST_kGrabHide) {
setWindowCursorVisibility(false);
+ }
}
updateMouseCapture(OperatorGrab);
}
@@ -874,9 +849,9 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode
setWindowCursorVisibility(true);
}
if (m_cursorGrab != GHOST_kGrabNormal) {
- /* use to generate a mouse move event, otherwise the last event
+ /* Use to generate a mouse move event, otherwise the last event
* blender gets can be outside the screen causing menus not to show
- * properly unless the user moves the mouse */
+ * properly unless the user moves the mouse. */
int32_t pos[2];
m_system->getCursorPosition(pos[0], pos[1]);
m_system->setCursorPosition(pos[0], pos[1]);
@@ -927,7 +902,7 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
for (uint32_t i = 0; i < outCount; i++) {
POINTER_INFO pointerApiInfo = pointerPenInfo[i].pointerInfo;
- // Obtain the basic information from the event
+ /* Obtain the basic information from the event. */
outPointerInfo[i].pointerId = pointerId;
outPointerInfo[i].isPrimary = isPrimary;
@@ -1069,8 +1044,9 @@ void GHOST_WindowWin32::ThemeRefresh()
&pcbData) == ERROR_SUCCESS) {
BOOL DarkMode = !lightMode;
- /* 20 == DWMWA_USE_IMMERSIVE_DARK_MODE in Windows 11 SDK. This value was undocumented for
- * Windows 10 versions 2004 and later, supported for Windows 11 Build 22000 and later. */
+ /* `20 == DWMWA_USE_IMMERSIVE_DARK_MODE` in Windows 11 SDK.
+ * This value was undocumented for Windows 10 versions 2004 and later,
+ * supported for Windows 11 Build 22000 and later. */
DwmSetWindowAttribute(this->m_hWnd, 20, &DarkMode, sizeof(DarkMode));
}
}
@@ -1126,8 +1102,9 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(
int x, y, cols;
cols = sizeX / 8; /* Number of whole bytes per row (width of bitmap/mask). */
- if (sizeX % 8)
+ if (sizeX % 8) {
cols++;
+ }
if (m_customCursor) {
DestroyCursor(m_customCursor);
@@ -1165,16 +1142,18 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(
GHOST_TSuccess GHOST_WindowWin32::setProgressBar(float progress)
{
/* #SetProgressValue sets state to #TBPF_NORMAL automatically. */
- if (m_Bar && S_OK == m_Bar->SetProgressValue(m_hWnd, 10000 * progress, 10000))
+ if (m_Bar && S_OK == m_Bar->SetProgressValue(m_hWnd, 10000 * progress, 10000)) {
return GHOST_kSuccess;
+ }
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
{
- if (m_Bar && S_OK == m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS))
+ if (m_Bar && S_OK == m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS)) {
return GHOST_kSuccess;
+ }
return GHOST_kFailure;
}
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 88731597caa..44071f0915e 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -10,7 +10,7 @@
#ifndef WIN32
# error WIN32 only!
-#endif // WIN32
+#endif /* WIN32 */
#include "GHOST_TaskbarWin32.h"
#include "GHOST_TrackpadWin32.h"
@@ -25,7 +25,7 @@
class GHOST_SystemWin32;
class GHOST_DropTargetWin32;
-// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions
+/* typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions. */
typedef UINT(API *GHOST_WIN32_GetDpiForWindow)(HWND);
typedef BOOL(API *GHOST_WIN32_AdjustWindowRectExForDpi)(
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 83c608435b0..113f453325d 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -10,9 +10,7 @@
#include <X11/Xmd.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
-#ifdef WITH_X11_ALPHA
-# include <X11/extensions/Xrender.h>
-#endif
+
#include "GHOST_Debug.h"
#include "GHOST_IconX11.h"
#include "GHOST_SystemX11.h"
@@ -23,12 +21,8 @@
# include "GHOST_DropTargetX11.h"
#endif
-#ifdef WITH_GL_EGL
-# include "GHOST_ContextEGL.h"
-# include <EGL/eglext.h>
-#else
-# include "GHOST_ContextGLX.h"
-#endif
+#include "GHOST_ContextEGL.h"
+#include "GHOST_ContextGLX.h"
/* for XIWarpPointer */
#ifdef WITH_X11_XINPUT
@@ -88,9 +82,7 @@ enum {
#define _NET_WM_STATE_ADD 1
// #define _NET_WM_STATE_TOGGLE 2 // UNUSED
-#ifdef WITH_GL_EGL
-
-static XVisualInfo *x11_visualinfo_from_egl(Display *display)
+static XVisualInfo *get_x11_visualinfo(Display *display)
{
int num_visuals;
XVisualInfo vinfo_template;
@@ -98,106 +90,6 @@ static XVisualInfo *x11_visualinfo_from_egl(Display *display)
return XGetVisualInfo(display, VisualScreenMask, &vinfo_template, &num_visuals);
}
-#else
-
-static XVisualInfo *x11_visualinfo_from_glx(Display *display,
- bool stereoVisual,
- bool needAlpha,
- GLXFBConfig *fbconfig)
-{
- int glx_major, glx_minor, glx_version; /* GLX version: major.minor */
- int glx_attribs[64];
-
- *fbconfig = nullptr;
-
- /* Set up the minimum attributes that we require and see if
- * X can find us a visual matching those requirements. */
-
- if (!glXQueryVersion(display, &glx_major, &glx_minor)) {
- fprintf(stderr,
- "%s:%d: X11 glXQueryVersion() failed, "
- "verify working openGL system!\n",
- __FILE__,
- __LINE__);
-
- return nullptr;
- }
- glx_version = glx_major * 100 + glx_minor;
-# ifndef WITH_X11_ALPHA
- (void)glx_version;
-# endif
-
-# ifdef WITH_X11_ALPHA
- if (needAlpha && glx_version >= 103 &&
- (glXChooseFBConfig || (glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddressARB(
- (const GLubyte *)"glXChooseFBConfig")) != nullptr) &&
- (glXGetVisualFromFBConfig ||
- (glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddressARB(
- (const GLubyte *)"glXGetVisualFromFBConfig")) != nullptr)) {
-
- GHOST_X11_GL_GetAttributes(glx_attribs, 64, stereoVisual, needAlpha, true);
-
- int nbfbconfig;
- GLXFBConfig *fbconfigs = glXChooseFBConfig(
- display, DefaultScreen(display), glx_attribs, &nbfbconfig);
-
- /* Any sample level or even zero, which means oversampling disabled, is good
- * but we need a valid visual to continue */
- if (nbfbconfig > 0) {
- /* take a frame buffer config that has alpha cap */
- for (int i = 0; i < nbfbconfig; i++) {
- XVisualInfo *visual = (XVisualInfo *)glXGetVisualFromFBConfig(display, fbconfigs[i]);
- if (!visual) {
- continue;
- }
- /* if we don't need a alpha background, the first config will do, otherwise
- * test the alphaMask as it won't necessarily be present */
- if (needAlpha) {
- XRenderPictFormat *pict_format = XRenderFindVisualFormat(display, visual->visual);
- if (!pict_format) {
- continue;
- }
- if (pict_format->direct.alphaMask <= 0) {
- continue;
- }
- }
-
- *fbconfig = fbconfigs[i];
- XFree(fbconfigs);
-
- return visual;
- }
-
- XFree(fbconfigs);
- }
- }
- else
-# endif
- {
- /* legacy, don't use extension */
- GHOST_X11_GL_GetAttributes(glx_attribs, 64, stereoVisual, needAlpha, false);
-
- XVisualInfo *visual = glXChooseVisual(display, DefaultScreen(display), glx_attribs);
-
- /* Any sample level or even zero, which means oversampling disabled, is good
- * but we need a valid visual to continue */
- if (visual != nullptr) {
- return visual;
- }
- }
-
- /* All options exhausted, cannot continue */
- fprintf(stderr,
- "%s:%d: X11 glXChooseVisual() failed, "
- "verify working openGL system!\n",
- __FILE__,
- __LINE__);
-
- return nullptr;
-}
-
-#endif // WITH_GL_EGL
-
GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
const char *title,
@@ -211,7 +103,6 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
const bool is_dialog,
const bool stereoVisual,
const bool exclusive,
- const bool alphaBackground,
const bool is_debug)
: GHOST_Window(width, height, state, stereoVisual, exclusive),
m_display(display),
@@ -235,13 +126,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
m_is_debug_context(is_debug)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
-#ifdef WITH_GL_EGL
- m_visualInfo = x11_visualinfo_from_egl(m_display);
- (void)alphaBackground;
-#else
- m_visualInfo = x11_visualinfo_from_glx(
- m_display, stereoVisual, alphaBackground, (GLXFBConfig *)&m_fbconfig);
-#endif
+ m_visualInfo = get_x11_visualinfo(m_display);
}
else {
XVisualInfo tmp = {nullptr};
@@ -332,7 +217,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
* So, m_post_init indicate that we need wait for the MapNotify
* event and then set the Window state to the m_post_state.
*/
- else if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
+ else if (!ELEM(state, GHOST_kWindowStateNormal, GHOST_kWindowStateMinimized)) {
m_post_init = True;
m_post_state = state;
}
@@ -1293,6 +1178,65 @@ GHOST_WindowX11::~GHOST_WindowX11()
}
}
+#ifdef USE_EGL
+static GHOST_Context *create_egl_context(GHOST_SystemX11 *system,
+ Window window,
+ Display *display,
+ bool want_stereo,
+ bool debug_context,
+ int ver_major,
+ int ver_minor)
+{
+ GHOST_Context *context;
+ context = new GHOST_ContextEGL(system,
+ want_stereo,
+ EGLNativeWindowType(window),
+ EGLNativeDisplayType(display),
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ ver_major,
+ ver_minor,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS |
+ (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ delete context;
+
+ return nullptr;
+}
+#endif
+
+static GHOST_Context *create_glx_context(Window window,
+ Display *display,
+ GLXFBConfig fbconfig,
+ bool want_stereo,
+ bool debug_context,
+ int ver_major,
+ int ver_minor)
+{
+ GHOST_Context *context;
+ context = new GHOST_ContextGLX(want_stereo,
+ window,
+ display,
+ fbconfig,
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ ver_major,
+ ver_minor,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS |
+ (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ delete context;
+
+ return nullptr;
+}
+
GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
@@ -1307,99 +1251,48 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
* - Try 3.3 core profile
* - No fall-backs. */
-#if defined(WITH_GL_PROFILE_CORE)
- {
- const char *version_major = (char *)glewGetString(GLEW_VERSION_MAJOR);
- if (version_major != nullptr && version_major[0] == '1') {
- fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
- abort();
- }
- }
-#endif
-
- const int profile_mask =
-#ifdef WITH_GL_EGL
-# if defined(WITH_GL_PROFILE_CORE)
- EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
-# elif defined(WITH_GL_PROFILE_COMPAT)
- EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
-# else
-# error // must specify either core or compat at build time
-# endif
-#else
-# if defined(WITH_GL_PROFILE_CORE)
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
-# elif defined(WITH_GL_PROFILE_COMPAT)
- GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
-# else
-# error // must specify either core or compat at build time
-# endif
-#endif
-
GHOST_Context *context;
+#ifdef USE_EGL
+ /* Try to initialize an EGL context. */
for (int minor = 5; minor >= 0; --minor) {
-#ifdef WITH_GL_EGL
- context = new GHOST_ContextEGL(
- this->m_system,
- m_wantStereoVisual,
- EGLNativeWindowType(m_window),
- EGLNativeDisplayType(m_display),
- profile_mask,
- 4,
- minor,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS |
- (m_is_debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
- context = new GHOST_ContextGLX(m_wantStereoVisual,
- m_window,
- m_display,
- (GLXFBConfig)m_fbconfig,
- profile_mask,
- 4,
- minor,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS |
- (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#endif
-
- if (context->initializeDrawingContext()) {
+ context = create_egl_context(
+ this->m_system, m_window, m_display, m_wantStereoVisual, m_is_debug_context, 4, minor);
+ if (context != nullptr) {
return context;
}
- delete context;
}
-#ifdef WITH_GL_EGL
- context = new GHOST_ContextEGL(this->m_system,
- m_wantStereoVisual,
- EGLNativeWindowType(m_window),
- EGLNativeDisplayType(m_display),
- profile_mask,
- 3,
- 3,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS |
- (m_is_debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
- context = new GHOST_ContextGLX(m_wantStereoVisual,
- m_window,
+ context = create_egl_context(
+ this->m_system, m_window, m_display, m_wantStereoVisual, m_is_debug_context, 3, 3);
+ if (context != nullptr) {
+ return context;
+ }
+
+ /* EGL initialization failed, try to fallback to a GLX context. */
+#endif
+ for (int minor = 5; minor >= 0; --minor) {
+ context = create_glx_context(m_window,
m_display,
(GLXFBConfig)m_fbconfig,
- profile_mask,
- 3,
- 3,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS |
- (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#endif
-
- if (context->initializeDrawingContext()) {
+ m_wantStereoVisual,
+ m_is_debug_context,
+ 4,
+ minor);
+ if (context != nullptr) {
+ return context;
+ }
+ }
+ context = create_glx_context(m_window,
+ m_display,
+ (GLXFBConfig)m_fbconfig,
+ m_wantStereoVisual,
+ m_is_debug_context,
+ 3,
+ 3);
+ if (context != nullptr) {
return context;
}
- delete context;
/* Ugly, but we get crashes unless a whole bunch of systems are patched. */
fprintf(stderr, "Error! Unsupported graphics card or driver.\n");
@@ -1712,7 +1605,7 @@ uint16_t GHOST_WindowX11::getDPIHint()
int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val);
if (success && type) {
- if (strcmp(type, "String") == 0) {
+ if (STREQ(type, "String")) {
return atoi((char *)val.addr);
}
}
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index ac4edd83549..c7a6b5e7357 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -47,7 +47,6 @@ class GHOST_WindowX11 : public GHOST_Window {
* \param parentWindow: Parent (embedder) window.
* \param type: The type of drawing context installed in this window.
* \param stereoVisual: Stereo visual for quad buffered stereo.
- * \param alphaBackground: Enable alpha blending of window with display background.
*/
GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
@@ -62,7 +61,6 @@ class GHOST_WindowX11 : public GHOST_Window {
const bool is_dialog = false,
const bool stereoVisual = false,
const bool exclusive = false,
- const bool alphaBackground = false,
const bool is_debug = false);
bool getValid() const;
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index 2ac3d9ec2a5..413e2670750 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -436,9 +436,11 @@ void GHOST_XrContext::getExtensionsToEnable(
r_ext_names.push_back(gpu_binding);
}
-#if defined(WITH_GHOST_X11) && defined(WITH_GL_EGL)
- assert(openxr_extension_is_available(m_oxr->extensions, XR_MNDX_EGL_ENABLE_EXTENSION_NAME));
- r_ext_names.push_back(XR_MNDX_EGL_ENABLE_EXTENSION_NAME);
+#if defined(WITH_GHOST_X11)
+ if (openxr_extension_is_available(m_oxr->extensions, XR_MNDX_EGL_ENABLE_EXTENSION_NAME)) {
+ /* Use EGL if that backend is available. */
+ r_ext_names.push_back(XR_MNDX_EGL_ENABLE_EXTENSION_NAME);
+ }
#endif
for (const std::string_view &ext : try_ext) {
diff --git a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
index aa230bf8deb..6a7eb25925a 100644
--- a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
+++ b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
@@ -8,17 +8,16 @@
#include <list>
#include <sstream>
-#if defined(WITH_GL_EGL)
+#if defined(WITH_GHOST_X11)
# include "GHOST_ContextEGL.h"
-# if defined(WITH_GHOST_X11)
-# include "GHOST_SystemX11.h"
-# endif
-# if defined(WITH_GHOST_WAYLAND)
-# include "GHOST_SystemWayland.h"
-# endif
-#elif defined(WITH_GHOST_X11)
# include "GHOST_ContextGLX.h"
-#elif defined(WIN32)
+# include "GHOST_SystemX11.h"
+#endif
+#if defined(WITH_GHOST_WAYLAND)
+# include "GHOST_ContextEGL.h"
+# include "GHOST_SystemWayland.h"
+#endif
+#if defined(WIN32)
# include "GHOST_ContextD3D.h"
# include "GHOST_ContextWGL.h"
# include "GHOST_SystemWin32.h"
@@ -61,19 +60,30 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
XrSystemId system_id,
std::string *r_requirement_info) const override
{
-#if defined(WITH_GL_EGL)
- GHOST_ContextEGL &ctx_gl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
-#elif defined(WITH_GHOST_X11)
- GHOST_ContextGLX &ctx_gl = static_cast<GHOST_ContextGLX &>(ghost_ctx);
-#else
+ int gl_major_version, gl_minor_version;
+#if defined(WIN32)
GHOST_ContextWGL &ctx_gl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
+ gl_major_version = ctx_gl.m_contextMajorVersion;
+ gl_minor_version = ctx_gl.m_contextMinorVersion;
+#elif defined(WITH_GHOST_X11) || defined(WITH_GHOST_WAYLAND)
+ if (dynamic_cast<GHOST_ContextEGL *>(&ghost_ctx)) {
+ GHOST_ContextEGL &ctx_gl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
+ gl_major_version = ctx_gl.m_contextMajorVersion;
+ gl_minor_version = ctx_gl.m_contextMinorVersion;
+ }
+# if defined(WITH_GHOST_X11)
+ else {
+ GHOST_ContextGLX &ctx_gl = static_cast<GHOST_ContextGLX &>(ghost_ctx);
+ gl_major_version = ctx_gl.m_contextMajorVersion;
+ gl_minor_version = ctx_gl.m_contextMinorVersion;
+ }
+# endif
#endif
static PFN_xrGetOpenGLGraphicsRequirementsKHR s_xrGetOpenGLGraphicsRequirementsKHR_fn =
nullptr;
// static XrInstance s_instance = XR_NULL_HANDLE;
XrGraphicsRequirementsOpenGLKHR gpu_requirements = {XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR};
- const XrVersion gl_version = XR_MAKE_VERSION(
- ctx_gl.m_contextMajorVersion, ctx_gl.m_contextMinorVersion, 0);
+ const XrVersion gl_version = XR_MAKE_VERSION(gl_major_version, gl_minor_version, 0);
/* Although it would seem reasonable that the proc address would not change if the instance was
* the same, in testing, repeated calls to #xrGetInstanceProcAddress() with the same instance
@@ -112,45 +122,67 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
void initFromGhostContext(GHOST_Context &ghost_ctx) override
{
-#if defined(WITH_GHOST_X11)
-# if defined(WITH_GL_EGL)
- GHOST_ContextEGL &ctx_egl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
-
- if (dynamic_cast<const GHOST_SystemX11 *const>(ctx_egl.m_system)) {
- oxr_binding.egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX;
- oxr_binding.egl.getProcAddress = eglGetProcAddress;
- oxr_binding.egl.display = ctx_egl.getDisplay();
- oxr_binding.egl.config = ctx_egl.getConfig();
- oxr_binding.egl.context = ctx_egl.getContext();
- }
+#if defined(WITH_GHOST_X11) || defined(WITH_GHOST_WAYLAND)
+ /* WAYLAND/X11 may be dynamically selected at load time but both may also be
+ * supported at compile time individually.
+ * Without `is_ctx_egl` & `is_wayland` preprocessor checks become an unmanageable soup. */
+ const bool is_ctx_egl = dynamic_cast<GHOST_ContextEGL *>(&ghost_ctx) != nullptr;
+ if (is_ctx_egl) {
+ GHOST_ContextEGL &ctx_egl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
+ const bool is_wayland = (
+# if defined(WITH_GHOST_WAYLAND)
+ dynamic_cast<const GHOST_SystemWayland *const>(ctx_egl.m_system) != nullptr
# else
- GHOST_ContextGLX &ctx_glx = static_cast<GHOST_ContextGLX &>(ghost_ctx);
- XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx.m_display, ctx_glx.m_fbconfig);
+ false
+# endif
+ );
+
+ if (is_wayland) {
+# if defined(WITH_GHOST_WAYLAND)
+ /* #GHOST_SystemWayland */
+ oxr_binding.wl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR;
+ oxr_binding.wl.display = (struct wl_display *)ctx_egl.m_nativeDisplay;
+# else
+ GHOST_ASSERT(false, "Unexpected State: logical error, unreachable!");
+# endif /* !WITH_GHOST_WAYLAND */
+ }
+ else { /* `!is_wayland` */
+# if defined(WITH_GHOST_X11)
+ /* #GHOST_SystemX11. */
+ oxr_binding.egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX;
+ oxr_binding.egl.getProcAddress = eglGetProcAddress;
+ oxr_binding.egl.display = ctx_egl.getDisplay();
+ oxr_binding.egl.config = ctx_egl.getConfig();
+ oxr_binding.egl.context = ctx_egl.getContext();
+# else
+ GHOST_ASSERT(false, "Unexpected State: built with only WAYLAND and no System found!");
+# endif /* !WITH_GHOST_X11 */
+ }
+ }
+ else { /* `!is_ctx_egl` */
+# if defined(WITH_GHOST_X11)
+ GHOST_ContextGLX &ctx_glx = static_cast<GHOST_ContextGLX &>(ghost_ctx);
+ XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx.m_display, ctx_glx.m_fbconfig);
- oxr_binding.glx.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
- oxr_binding.glx.xDisplay = ctx_glx.m_display;
- oxr_binding.glx.glxFBConfig = ctx_glx.m_fbconfig;
- oxr_binding.glx.glxDrawable = ctx_glx.m_window;
- oxr_binding.glx.glxContext = ctx_glx.m_context;
- oxr_binding.glx.visualid = visual_info->visualid;
+ oxr_binding.glx.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
+ oxr_binding.glx.xDisplay = ctx_glx.m_display;
+ oxr_binding.glx.glxFBConfig = ctx_glx.m_fbconfig;
+ oxr_binding.glx.glxDrawable = ctx_glx.m_window;
+ oxr_binding.glx.glxContext = ctx_glx.m_context;
+ oxr_binding.glx.visualid = visual_info->visualid;
- XFree(visual_info);
-# endif
+ XFree(visual_info);
+# else
+ GHOST_ASSERT(false, "Unexpected State: built without X11 and no EGL context is available!");
+# endif /* !WITH_GHOST_X11 */
+ }
#elif defined(WIN32)
GHOST_ContextWGL &ctx_wgl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
oxr_binding.wgl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
oxr_binding.wgl.hDC = ctx_wgl.m_hDC;
oxr_binding.wgl.hGLRC = ctx_wgl.m_hGLRC;
-#endif
-
-#if defined(WITH_GHOST_WAYLAND)
- GHOST_ContextEGL &ctx_wl_egl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
- if (dynamic_cast<const GHOST_SystemWayland *const>(ctx_wl_egl.m_system)) {
- oxr_binding.wl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR;
- oxr_binding.wl.display = (struct wl_display *)ctx_wl_egl.m_nativeDisplay;
- }
-#endif
+#endif /* WIN32 */
/* Generate a frame-buffer to use for blitting into the texture. */
glGenFramebuffers(1, &m_fbo);
diff --git a/intern/ghost/intern/GHOST_Xr_openxr_includes.h b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
index 9706f51c027..1c16f746f7a 100644
--- a/intern/ghost/intern/GHOST_Xr_openxr_includes.h
+++ b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
@@ -28,13 +28,8 @@
# include <d3d12.h>
#endif
#ifdef WITH_GHOST_X11
-# ifdef WITH_GL_EGL
-/* TODO: Why do we have to create this typedef manually? */
-typedef void (*(*PFNEGLGETPROCADDRESSPROC)(const char *procname))(void);
-# include <GL/eglew.h>
-# else
-# include <GL/glxew.h>
-# endif
+# include <epoxy/egl.h>
+# include <epoxy/glx.h>
#endif
#include <openxr/openxr.h>
diff --git a/intern/ghost/intern/GHOST_utildefines.h b/intern/ghost/intern/GHOST_utildefines.h
index f0ae6e12d3e..ff092099c7c 100644
--- a/intern/ghost/intern/GHOST_utildefines.h
+++ b/intern/ghost/intern/GHOST_utildefines.h
@@ -208,3 +208,32 @@
(void)0
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name String Macros
+ * \{ */
+
+/* Macro to convert a value to string in the preprocessor:
+ * - `STRINGIFY_ARG`: gives the argument as a string
+ * - `STRINGIFY_APPEND`: appends any argument 'b' onto the string argument 'a',
+ * used by `STRINGIFY` because some preprocessors warn about zero arguments.
+ * - `STRINGIFY`: gives the argument's value as a string. */
+
+#define STRINGIFY_ARG(x) "" #x
+#define STRINGIFY_APPEND(a, b) "" a #b
+#define STRINGIFY(x) STRINGIFY_APPEND("", x)
+
+/* generic strcmp macros */
+#if defined(_MSC_VER)
+# define strcasecmp _stricmp
+# define strncasecmp _strnicmp
+#endif
+
+#define STREQ(a, b) (strcmp(a, b) == 0)
+#define STRCASEEQ(a, b) (strcasecmp(a, b) == 0)
+#define STREQLEN(a, b, n) (strncmp(a, b, n) == 0)
+#define STRCASEEQLEN(a, b, n) (strncasecmp(a, b, n) == 0)
+
+#define STRPREFIX(a, b) (strncmp((a), (b), strlen(b)) == 0)
+
+/** \} */