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_Buttons.h8
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp48
-rw-r--r--intern/ghost/intern/GHOST_CallbackEventConsumer.h4
-rw-r--r--intern/ghost/intern/GHOST_Context.cpp159
-rw-r--r--intern/ghost/intern/GHOST_Context.h161
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h153
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm354
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.cpp640
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.h167
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp411
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h156
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.cpp79
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.h97
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.cpp204
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.h131
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp956
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h190
-rw-r--r--intern/ghost/intern/GHOST_Debug.h2
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.h12
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.h12
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.cpp8
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.h2
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.cpp3
-rw-r--r--intern/ghost/intern/GHOST_Event.h8
-rw-r--r--intern/ghost/intern/GHOST_EventButton.h5
-rw-r--r--intern/ghost/intern/GHOST_EventDragnDrop.h1
-rw-r--r--intern/ghost/intern/GHOST_EventManager.h28
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.cpp3
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.h2
-rw-r--r--intern/ghost/intern/GHOST_EventTrackpad.h2
-rw-r--r--intern/ghost/intern/GHOST_EventWheel.h6
-rw-r--r--intern/ghost/intern/GHOST_ISystem.cpp39
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp520
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h405
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.h18
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp61
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h4
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerX11.cpp12
-rw-r--r--intern/ghost/intern/GHOST_System.cpp24
-rw-r--r--intern/ghost/intern/GHOST_System.h50
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h35
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm224
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsCocoa.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsCocoa.mm9
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsX11.cpp2
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsX11.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp14
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h3
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp207
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h96
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp49
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h25
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.h16
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h30
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp70
-rw-r--r--intern/ghost/intern/GHOST_Window.h191
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h110
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm448
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h24
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h8
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp184
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h25
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp621
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h165
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp719
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h61
71 files changed, 6385 insertions, 2118 deletions
diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h
index 6b0d74e7eb9..0aa93a2fad0 100644
--- a/intern/ghost/intern/GHOST_Buttons.h
+++ b/intern/ghost/intern/GHOST_Buttons.h
@@ -48,26 +48,26 @@ struct GHOST_Buttons {
*/
GHOST_Buttons();
- virtual ~GHOST_Buttons();
+ ~GHOST_Buttons();
/**
* Returns the state of a single button.
* \param mask Key button to return.
* \return The state of the button (pressed == true).
*/
- virtual bool get(GHOST_TButtonMask mask) const;
+ bool get(GHOST_TButtonMask mask) const;
/**
* Updates the state of a single button.
* \param mask Button state to update.
* \param down The new state of the button.
*/
- virtual void set(GHOST_TButtonMask mask, bool down);
+ void set(GHOST_TButtonMask mask, bool down);
/**
* Sets the state of all buttons to up.
*/
- virtual void clear();
+ void clear();
GHOST_TUns8 m_ButtonLeft : 1;
GHOST_TUns8 m_ButtonMiddle : 1;
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index eaa59f096aa..af992bf5a3c 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -140,20 +140,12 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const int stereoVisual,
- const GHOST_TUns16 numOfAASamples)
+ GHOST_GLSettings glSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *) systemhandle;
- bool bstereoVisual;
-
- if (stereoVisual)
- bstereoVisual = true;
- else
- bstereoVisual = false;
return (GHOST_WindowHandle) system->createWindow(title, left, top, width, height,
- state, type, bstereoVisual, false,
- numOfAASamples);
+ state, type, glSettings, false);
}
GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle)
@@ -421,6 +413,13 @@ GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
}
+void GHOST_setNDOFDeadZone(float deadzone)
+{
+ GHOST_ISystem *system = GHOST_ISystem::getSystem();
+ system->setNDOFDeadZone(deadzone);
+}
+
+
void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept)
{
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
@@ -698,14 +697,21 @@ GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interv
return window->setSwapInterval(interval);
}
-int GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle)
+GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int* intervalOut)
{
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
- return window->getSwapInterval();
+ return window->getSwapInterval(*intervalOut);
}
+GHOST_TUns16 GHOST_GetNumOfAASamples(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+
+ return window->getNumOfAASamples();
+}
+
GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
@@ -914,3 +920,21 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+
+void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int complete)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->beginIME(x, y, w, h, complete);
+}
+
+void GHOST_EndIME(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->endIME();
+}
+
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
index 770ebdc8b78..3505d651fa3 100644
--- a/intern/ghost/intern/GHOST_CallbackEventConsumer.h
+++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
@@ -57,7 +57,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_CallbackEventConsumer(void)
+ ~GHOST_CallbackEventConsumer(void)
{
}
@@ -66,7 +66,7 @@ public:
* \param event The event that can be handled or ignored.
* \return Indication as to whether the event was handled.
*/
- virtual bool processEvent(GHOST_IEvent *event);
+ bool processEvent(GHOST_IEvent *event);
protected:
/** The call-back routine invoked. */
diff --git a/intern/ghost/intern/GHOST_Context.cpp b/intern/ghost/intern/GHOST_Context.cpp
new file mode 100644
index 00000000000..f69f2181ef7
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Context.cpp
@@ -0,0 +1,159 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_Context.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_Context class.
+ */
+
+#include "GHOST_Context.h"
+
+#ifdef _WIN32
+# include <GL/wglew.h> // only for symbolic constants, do not use API functions
+# include <tchar.h>
+#
+# ifndef ERROR_PROFILE_DOES_NOT_MATCH_DEVICE
+# define ERROR_PROFILE_DOES_NOT_MATCH_DEVICE 0x7E7 // Mingw64 headers may have had this
+# endif
+#endif
+
+#include <cstdio>
+#include <cstring>
+
+
+#ifdef _WIN32
+
+bool win32_chk(bool result, const char *file, int line, const char *text)
+{
+ if (!result) {
+ LPTSTR formattedMsg = NULL;
+
+ DWORD error = GetLastError();
+
+ const char *msg;
+
+ DWORD count = 0;
+
+ switch (error) {
+ case ERROR_INVALID_VERSION_ARB:
+ msg = "The specified OpenGL version and feature set are either invalid or not supported.\n";
+ break;
+
+ case ERROR_INVALID_PROFILE_ARB:
+ msg = "The specified OpenGL profile and feature set are either invalid or not supported.\n";
+ break;
+
+ case ERROR_INVALID_PIXEL_TYPE_ARB:
+ msg = "The specified pixel type is invalid.\n";
+ break;
+
+ case ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB:
+ msg = ("The device contexts specified are not compatible. "
+ "This can occur if the device contexts are managed by "
+ "different drivers or possibly on different graphics adapters.\n");
+ break;
+
+#ifdef WITH_GLEW_ES
+ case ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV:
+ msg = "The device context(s) and rendering context have non-matching affinity masks.\n";
+ break;
+
+ case ERROR_MISSING_AFFINITY_MASK_NV:
+ msg = "The rendering context does not have an affinity mask set.\n";
+ break;
+#endif
+
+ case ERROR_PROFILE_DOES_NOT_MATCH_DEVICE:
+ msg = ("The specified profile is intended for a device of a "
+ "different type than the specified device.\n");
+ break;
+
+ default:
+ {
+ count =
+ FormatMessage(
+ (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS),
+ NULL,
+ error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)(&formattedMsg),
+ 0,
+ NULL);
+
+ msg = count > 0 ? formattedMsg : "<no system message>\n";
+ break;
+ }
+ }
+
+#ifndef NDEBUG
+ _ftprintf(
+ stderr,
+ "%s(%d):[%s] -> Win32 Error# (%lu): %s",
+ file,
+ line,
+ text,
+ (unsigned long)error,
+ msg);
+#else
+ _ftprintf(
+ stderr,
+ "Win32 Error# (%lu): %s",
+ (unsigned long)error,
+ msg);
+#endif
+
+ SetLastError(NO_ERROR);
+
+ if (count != 0)
+ LocalFree(formattedMsg);
+ }
+
+ return result;
+}
+
+#endif // _WIN32
+
+
+void GHOST_Context::initContextGLEW()
+{
+ mxDestroyContext(m_mxContext); // no-op if m_mxContext is NULL
+
+ mxMakeCurrentContext(mxCreateContext());
+
+ m_mxContext = mxGetCurrentContext();
+}
+
+
+void GHOST_Context::initClearGL()
+{
+ glClearColor(0.447, 0.447, 0.447, 0.000);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0.000, 0.000, 0.000, 0.000);
+}
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
new file mode 100644
index 00000000000..18d36c40e9c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -0,0 +1,161 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_Context.h
+ * \ingroup GHOST
+ * Declaration of GHOST_Context class.
+ */
+
+#ifndef __GHOST_CONTEXT_H__
+#define __GHOST_CONTEXT_H__
+
+#include "GHOST_Types.h"
+
+#include "glew-mx.h"
+
+#include <cstdlib> // for NULL
+
+
+class GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ * \param stereoVisual Stereo visual for quad buffered stereo.
+ * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ */
+ GHOST_Context(bool stereoVisual, GHOST_TUns16 numOfAASamples)
+ : m_stereoVisual(stereoVisual),
+ m_numOfAASamples(numOfAASamples),
+ m_mxContext(NULL)
+ {}
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_Context() {
+ mxDestroyContext(m_mxContext);
+ }
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess swapBuffers() = 0;
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess activateDrawingContext() = 0;
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ virtual GHOST_TSuccess initializeDrawingContext() = 0;
+
+ /**
+ * Updates the drawing context of this window. Needed
+ * whenever the window is changed.
+ * \return Indication of success.
+ */
+ virtual GHOST_TSuccess updateDrawingContext() {
+ return GHOST_kFailure;
+ }
+
+ /**
+ * Checks if it is OK for a remove the native display
+ * \return Indication as to whether removal has succeeded.
+ */
+ virtual GHOST_TSuccess releaseNativeHandles() = 0;
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess setSwapInterval(int /*interval*/) {
+ return GHOST_kFailure;
+ }
+
+ /**
+ * 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.
+ */
+ virtual GHOST_TSuccess getSwapInterval(int&) {
+ return GHOST_kFailure;
+ }
+
+ /** Stereo visual created. Only necessary for 'real' stereo support,
+ * ie quad buffered stereo. This is not always possible, depends on
+ * the graphics h/w
+ */
+ inline bool isStereoVisual() const {
+ return m_stereoVisual;
+ }
+
+ /** Number of samples used in anti-aliasing, set to 0 if no AA **/
+ inline GHOST_TUns16 getNumOfAASamples() const {
+ return m_numOfAASamples;
+ }
+
+protected:
+ void initContextGLEW();
+
+ inline void activateGLEW() const {
+ mxMakeCurrentContext(m_mxContext);
+ }
+
+ bool m_stereoVisual;
+
+ GHOST_TUns16 m_numOfAASamples;
+
+ static void initClearGL();
+
+private:
+ MXContext *m_mxContext;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_Context")
+#endif
+};
+
+
+#ifdef _WIN32
+bool win32_chk(bool result, const char *file = NULL, int line = 0, const char *text = NULL);
+
+# ifndef NDEBUG
+# define WIN32_CHK(x) win32_chk((x), __FILE__, __LINE__, #x)
+# else
+# define WIN32_CHK(x) win32_chk(x)
+# endif
+#endif /* _WIN32 */
+
+
+#endif // __GHOST_CONTEXT_H__
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
new file mode 100644
index 00000000000..92fdbfc53de
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -0,0 +1,153 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextCGL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTCGL_H__
+#define __GHOST_CONTEXTCGL_H__
+
+#include "GHOST_Context.h"
+
+//#define cglewGetContext() cglewContext
+//#include <GL/cglew.h>
+//extern "C" CGLEWContext *cglewContext;
+
+#ifndef GHOST_OPENGL_CGL_CONTEXT_FLAGS
+#define GHOST_OPENGL_CGL_CONTEXT_FLAGS 0
+#endif
+
+#ifndef GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+@class NSWindow;
+@class NSOpenGLView;
+@class NSOpenGLContext;
+
+
+class GHOST_ContextCGL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextCGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ NSWindow *window,
+ NSOpenGLView *openGLView,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextCGL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * 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();
+
+ /**
+ * 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();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * 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&);
+
+ /**
+ * Updates the drawing context of this window.
+ * Needed whenever the window is changed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess updateDrawingContext();
+
+//protected:
+// inline void activateCGLEW() const {
+// cglewContext = m_cglewContext;
+// }
+
+private:
+ //void initContextCGLEW()
+
+ /** The window containing the OpenGL view */
+ NSWindow *m_window;
+
+ /** The openGL view */
+ NSOpenGLView *m_openGLView;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ /** The OpenGL drawing context */
+ NSOpenGLContext *m_openGLContext;
+
+ //static CGLEWContext *s_cglewContext;
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static NSOpenGLContext *s_sharedOpenGLContext;
+ static int s_sharedCount;
+};
+
+#endif // __GHOST_CONTEXTCGL_H__
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
new file mode 100644
index 00000000000..51895e5fa1a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -0,0 +1,354 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextCGL.mm
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextCGL class.
+ */
+
+#include "GHOST_ContextCGL.h"
+
+#include <Cocoa/Cocoa.h>
+
+#ifdef GHOST_MULTITHREADED_OPENGL
+#include <OpenGL/OpenGL.h>
+#endif
+
+#include <vector>
+#include <cassert>
+
+
+NSOpenGLContext *GHOST_ContextCGL::s_sharedOpenGLContext = nil;
+int GHOST_ContextCGL::s_sharedCount = 0;
+
+
+GHOST_ContextCGL::GHOST_ContextCGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ NSWindow *window,
+ NSOpenGLView *openGLView,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_window(window),
+ m_openGLView(openGLView),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_openGLContext(nil)
+{
+ assert(window != nil);
+ assert(openGLView != nil);
+}
+
+
+GHOST_ContextCGL::~GHOST_ContextCGL()
+{
+ if (m_openGLContext != nil) {
+ if (m_openGLContext == [NSOpenGLContext currentContext]) {
+ [NSOpenGLContext clearCurrentContext];
+ [m_openGLView clearGLContext];
+ }
+
+ if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedOpenGLContext = nil;
+
+ [m_openGLContext release];
+ }
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::swapBuffers()
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext flushBuffer];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+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;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::getSwapInterval(int &intervalOut)
+{
+ if (m_openGLContext != nil) {
+ GLint interval;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [m_openGLContext setValues:&interval forParameter:NSOpenGLCPSwapInterval];
+
+ [pool drain];
+
+ intervalOut = static_cast<int>(interval);
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::activateDrawingContext()
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext makeCurrentContext];
+
+ activateGLEW();
+
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext update];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+static void makeAttribList(
+ std::vector<NSOpenGLPixelFormatAttribute>& attribs,
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil)
+{
+ // Pixel Format Attributes for the windowed NSOpenGLContext
+ attribs.push_back(NSOpenGLPFADoubleBuffer);
+
+ // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object's flushBuffer
+ // needed for 'Draw Overlap' drawing method
+ attribs.push_back(NSOpenGLPFABackingStore);
+
+ // Force software OpenGL, for debugging
+ /* XXX jwilkins: fixed this to work on Intel macs? useful feature for Windows and Linux too?
+ * Maybe a command line flag is better... */
+ if (getenv("BLENDER_SOFTWAREGL")) {
+ attribs.push_back(NSOpenGLPFARendererID);
+ attribs.push_back(kCGLRendererGenericFloatID);
+ }
+ else {
+ attribs.push_back(NSOpenGLPFAAccelerated);
+ }
+
+ /* Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway */
+ //attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
+
+ attribs.push_back(NSOpenGLPFADepthSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 32);
+
+ attribs.push_back(NSOpenGLPFAAccumSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 32);
+
+ if (stereoVisual)
+ attribs.push_back(NSOpenGLPFAStereo);
+
+ if (needAlpha) {
+ attribs.push_back(NSOpenGLPFAAlphaSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 8);
+ }
+
+ if (needStencil) {
+ attribs.push_back(NSOpenGLPFAStencilSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 8);
+ }
+
+ if (numOfAASamples > 0) {
+ // Multisample anti-aliasing
+ attribs.push_back(NSOpenGLPFAMultisample);
+
+ attribs.push_back(NSOpenGLPFASampleBuffers);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 1);
+
+ attribs.push_back(NSOpenGLPFASamples);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) numOfAASamples);
+
+ attribs.push_back(NSOpenGLPFANoRecovery);
+ }
+
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 0);
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ std::vector<NSOpenGLPixelFormatAttribute> attribs;
+ attribs.reserve(40);
+
+ NSOpenGLContext *prev_openGLContext = [m_openGLView openGLContext];
+
+#ifdef GHOST_OPENGL_ALPHA
+ static const bool needAlpha = true;
+#else
+ static const bool needAlpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ static const bool needStencil = true;
+#else
+ static const bool needStencil = false;
+#endif
+
+ makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil);
+
+ NSOpenGLPixelFormat *pixelFormat;
+
+ pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
+
+ // Fall back to no multisampling if Antialiasing init failed
+ if (m_numOfAASamples > 0 && pixelFormat == nil) {
+ // XXX jwilkins: Does CGL only succeed when it makes an exact match on the number of samples?
+ // Does this need to explicitly try for a lesser match before giving up?
+ // (Now that I think about it, does WGL really require the code that it has for finding a lesser match?)
+
+ attribs.clear();
+ makeAttribList(attribs, m_stereoVisual, 0, needAlpha, needStencil);
+ pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
+ }
+
+ if (pixelFormat == nil)
+ goto error;
+
+ if (m_numOfAASamples > 0) { //Set m_numOfAASamples to the actual value
+ GLint actualSamples;
+ [pixelFormat getValues:&actualSamples forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
+
+ if (m_numOfAASamples != (GHOST_TUns16)actualSamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ m_numOfAASamples, actualSamples);
+
+ m_numOfAASamples = (GHOST_TUns16)actualSamples;
+ }
+ }
+
+ [m_openGLView setPixelFormat:pixelFormat];
+
+ m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext]; // +1 refCount to pixelFormat
+
+ if (m_openGLContext == nil)
+ goto error;
+
+ if (s_sharedCount == 0)
+ s_sharedOpenGLContext = m_openGLContext;
+
+ [pixelFormat release]; // -1 refCount to pixelFormat
+
+ s_sharedCount++;
+
+#ifdef GHOST_MULTITHREADED_OPENGL
+ //Switch openGL to multhreaded mode
+ CGLContextObj cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
+ if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
+ printf("\nSwitched openGL to multithreaded mode\n");
+#endif
+
+#ifdef GHOST_WAIT_FOR_VSYNC
+ {
+ GLint swapInt = 1;
+ /* wait for vsync, to avoid tearing artifacts */
+ [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+ }
+#endif
+
+ [m_openGLView setOpenGLContext:m_openGLContext];
+ [m_openGLContext setView:m_openGLView];
+
+ initContextGLEW();
+
+ initClearGL();
+ [m_openGLContext flushBuffer];
+
+ [pool drain];
+
+ return GHOST_kSuccess;
+
+error:
+
+ [m_openGLView setOpenGLContext:prev_openGLContext];
+ [pixelFormat release];
+
+ [pool drain];
+
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()
+{
+ m_openGLContext = NULL;
+ m_openGLView = NULL;
+
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
new file mode 100644
index 00000000000..520aa0fffb2
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -0,0 +1,640 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextEGL.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextEGL class.
+ */
+
+#include "GHOST_ContextEGL.h"
+
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+
+#ifdef WITH_GLEW_MX
+EGLEWContext *eglewContext = NULL;
+#endif
+
+
+#define CASE_CODE_RETURN_STR(code) case code: return #code;
+
+static const char *get_egl_error_enum_string(EGLenum error)
+{
+ switch (error) {
+ CASE_CODE_RETURN_STR(EGL_SUCCESS)
+ CASE_CODE_RETURN_STR(EGL_NOT_INITIALIZED)
+ CASE_CODE_RETURN_STR(EGL_BAD_ACCESS)
+ CASE_CODE_RETURN_STR(EGL_BAD_ALLOC)
+ CASE_CODE_RETURN_STR(EGL_BAD_ATTRIBUTE)
+ CASE_CODE_RETURN_STR(EGL_BAD_CONTEXT)
+ CASE_CODE_RETURN_STR(EGL_BAD_CONFIG)
+ CASE_CODE_RETURN_STR(EGL_BAD_CURRENT_SURFACE)
+ CASE_CODE_RETURN_STR(EGL_BAD_DISPLAY)
+ CASE_CODE_RETURN_STR(EGL_BAD_SURFACE)
+ CASE_CODE_RETURN_STR(EGL_BAD_MATCH)
+ CASE_CODE_RETURN_STR(EGL_BAD_PARAMETER)
+ CASE_CODE_RETURN_STR(EGL_BAD_NATIVE_PIXMAP)
+ CASE_CODE_RETURN_STR(EGL_BAD_NATIVE_WINDOW)
+ CASE_CODE_RETURN_STR(EGL_CONTEXT_LOST)
+ default:
+ return NULL;
+ }
+}
+
+static const char *get_egl_error_message_string(EGLenum error)
+{
+ switch (error) {
+ case EGL_SUCCESS:
+ return "The last function succeeded without error.";
+
+ case EGL_NOT_INITIALIZED:
+ return ("EGL is not initialized, or could not be initialized, "
+ "for the specified EGL display connection.");
+
+ case EGL_BAD_ACCESS:
+ return ("EGL cannot access a requested resource "
+ "(for example a context is bound in another thread).");
+
+ case EGL_BAD_ALLOC:
+ return "EGL failed to allocate resources for the requested operation.";
+
+ case EGL_BAD_ATTRIBUTE:
+ return "An unrecognized attribute or attribute value was passed in the attribute list.";
+
+ case EGL_BAD_CONTEXT:
+ return "An EGLContext argument does not name a valid EGL rendering context.";
+
+ case EGL_BAD_CONFIG:
+ return "An EGLConfig argument does not name a valid EGL frame buffer configuration.";
+
+ case EGL_BAD_CURRENT_SURFACE:
+ return ("The current surface of the calling thread is a window, "
+ "pixel buffer or pixmap that is no longer valid.");
+
+ case EGL_BAD_DISPLAY:
+ return "An EGLDisplay argument does not name a valid EGL display connection.";
+
+ case EGL_BAD_SURFACE:
+ return ("An EGLSurface argument does not name a valid surface "
+ "(window, pixel buffer or pixmap) configured for GL rendering.");
+
+ case EGL_BAD_MATCH:
+ return ("Arguments are inconsistent "
+ "(for example, a valid context requires buffers not supplied by a valid surface).");
+
+ case EGL_BAD_PARAMETER:
+ return "One or more argument values are invalid.";
+
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "A NativePixmapType argument does not refer to a valid native pixmap.";
+
+ case EGL_BAD_NATIVE_WINDOW:
+ return "A NativeWindowType argument does not refer to a valid native window.";
+
+ case EGL_CONTEXT_LOST:
+ return ("A power management event has occurred. "
+ "The application must destroy all contexts and reinitialise OpenGL ES state "
+ "and objects to continue rendering.");
+
+ default:
+ return NULL;
+ }
+}
+
+
+static bool egl_chk(bool result, const char *file = NULL, int line = 0, const char *text = NULL)
+{
+ if (!result) {
+ EGLenum error = eglGetError();
+
+ const char *code = get_egl_error_enum_string(error);
+ const char *msg = get_egl_error_message_string(error);
+
+#ifndef NDEBUG
+ fprintf(stderr,
+ "%s(%d):[%s] -> EGL Error (0x%04X): %s: %s\n",
+ file, line, text, error,
+ code ? code : "<Unknown>",
+ msg ? msg : "<Unknown>");
+#else
+ fprintf(stderr,
+ "EGL Error (0x%04X): %s: %s\n",
+ error,
+ code ? code : "<Unknown>",
+ msg ? msg : "<Unknown>");
+#endif
+ }
+
+ return result;
+}
+
+#ifndef NDEBUG
+#define EGL_CHK(x) egl_chk((x), __FILE__, __LINE__, #x)
+#else
+#define EGL_CHK(x) egl_chk(x)
+#endif
+
+
+static inline bool bindAPI(EGLenum api)
+{
+#ifdef WITH_GLEW_MX
+ if (eglewContext != NULL)
+#endif
+ {
+ if (EGLEW_VERSION_1_2) {
+ return (EGL_CHK(eglBindAPI(api)) == EGL_TRUE);
+ }
+ }
+
+ return false;
+}
+
+
+#ifdef WITH_GL_ANGLE
+HMODULE GHOST_ContextEGL::s_d3dcompiler = NULL;
+#endif
+
+
+EGLContext GHOST_ContextEGL::s_gl_sharedContext = EGL_NO_CONTEXT;
+EGLint GHOST_ContextEGL::s_gl_sharedCount = 0;
+
+EGLContext GHOST_ContextEGL::s_gles_sharedContext = EGL_NO_CONTEXT;
+EGLint GHOST_ContextEGL::s_gles_sharedCount = 0;
+
+EGLContext GHOST_ContextEGL::s_vg_sharedContext = EGL_NO_CONTEXT;
+EGLint GHOST_ContextEGL::s_vg_sharedCount = 0;
+
+
+#pragma warning(disable : 4715)
+
+template <typename T>
+T &choose_api(EGLenum api, T &a, T &b, T &c)
+{
+ switch (api) {
+ case EGL_OPENGL_API:
+ return a;
+ case EGL_OPENGL_ES_API:
+ return b;
+ case EGL_OPENVG_API:
+ return c;
+ default:
+ abort();
+ }
+}
+
+
+GHOST_ContextEGL::GHOST_ContextEGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ EGLNativeWindowType nativeWindow,
+ EGLNativeDisplayType nativeDisplay,
+ EGLint contextProfileMask,
+ EGLint contextMajorVersion,
+ EGLint contextMinorVersion,
+ EGLint contextFlags,
+ EGLint contextResetNotificationStrategy,
+ EGLenum api)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_nativeDisplay(nativeDisplay),
+ m_nativeWindow (nativeWindow),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_api(api),
+ m_context(EGL_NO_CONTEXT),
+ m_surface(EGL_NO_SURFACE),
+ m_display(EGL_NO_DISPLAY),
+ m_swap_interval(1),
+#ifdef WITH_GLEW_MX
+ m_eglewContext(NULL),
+#endif
+ m_sharedContext(choose_api(api, s_gl_sharedContext, s_gles_sharedContext, s_vg_sharedContext)),
+ m_sharedCount (choose_api(api, s_gl_sharedCount, s_gles_sharedCount, s_vg_sharedCount))
+{
+ assert(m_nativeWindow != 0);
+ assert(m_nativeDisplay != NULL);
+}
+
+
+GHOST_ContextEGL::~GHOST_ContextEGL()
+{
+ if (m_display != EGL_NO_DISPLAY) {
+ activateEGLEW();
+
+ bindAPI(m_api);
+
+ if (m_context != EGL_NO_CONTEXT) {
+ if (m_context == ::eglGetCurrentContext())
+ EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+
+ if (m_context != m_sharedContext || m_sharedCount == 1) {
+ assert(m_sharedCount > 0);
+
+ m_sharedCount--;
+
+ if (m_sharedCount == 0)
+ m_sharedContext = EGL_NO_CONTEXT;
+
+ EGL_CHK(::eglDestroyContext(m_display, m_context));
+ }
+ }
+
+ if (m_surface != EGL_NO_SURFACE)
+ EGL_CHK(::eglDestroySurface(m_display, m_surface));
+
+ EGL_CHK(::eglTerminate(m_display));
+
+#ifdef WITH_GLEW_MX
+ delete m_eglewContext;
+#endif
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::swapBuffers()
+{
+ return EGL_CHK(::eglSwapBuffers(m_display, m_surface)) ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::setSwapInterval(int interval)
+{
+ if (EGLEW_VERSION_1_1) {
+ if (EGL_CHK(::eglSwapInterval(m_display, interval))) {
+ m_swap_interval = interval;
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::getSwapInterval(int &intervalOut)
+{
+ // This is a bit of a kludge because there does not seem to
+ // be a way to query the swap interval with EGL.
+ intervalOut = m_swap_interval;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::activateDrawingContext()
+{
+ if (m_display) {
+ activateEGLEW();
+ activateGLEW();
+
+ bindAPI(m_api);
+
+ return EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context)) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+void GHOST_ContextEGL::initContextEGLEW()
+{
+#ifdef WITH_GLEW_MX
+ eglewContext = new EGLEWContext;
+ memset(eglewContext, 0, sizeof(EGLEWContext));
+
+ delete m_eglewContext;
+ m_eglewContext = eglewContext;
+#endif
+
+ if (GLEW_CHK(eglewInit(m_display)) != GLEW_OK)
+ fprintf(stderr, "Warning! EGLEW failed to initialize properly.\n");
+}
+
+
+static const std::string &api_string(EGLenum api)
+{
+ static const std::string a("OpenGL");
+ static const std::string b("OpenGL ES");
+ static const std::string c("OpenVG");
+
+ return choose_api(api, a, b, c);
+}
+
+GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
+{
+ // objects have to be declared here due to the use of goto
+ std::vector<EGLint> attrib_list;
+ EGLint num_config = 0;
+
+ if (m_stereoVisual)
+ fprintf(stderr, "Warning! Stereo OpenGL ES contexts are not supported.\n");
+
+ m_stereoVisual = false; // It doesn't matter what the Window wants.
+
+#ifdef WITH_GL_ANGLE
+ // d3dcompiler_XX.dll needs to be loaded before ANGLE will work
+ if (s_d3dcompiler == NULL) {
+ s_d3dcompiler = LoadLibrary(D3DCOMPILER);
+
+ WIN32_CHK(s_d3dcompiler != NULL);
+
+ if (s_d3dcompiler == NULL) {
+ 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();
+
+ m_display = ::eglGetDisplay(m_nativeDisplay);
+
+ if (!EGL_CHK(m_display != EGL_NO_DISPLAY))
+ return GHOST_kFailure;
+
+ EGLint egl_major, egl_minor;
+
+ if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor)))
+ goto error;
+
+ fprintf(stderr, "EGL Version %d.%d\n", egl_major, egl_minor);
+
+ if (!EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)))
+ goto error;
+
+ initContextEGLEW();
+
+ if (!bindAPI(m_api))
+ goto error;
+
+
+ // build attribute list
+
+ attrib_list.reserve(20);
+
+ if (m_api == EGL_OPENGL_ES_API && EGLEW_VERSION_1_2) {
+ // According to the spec it seems that you are required to set EGL_RENDERABLE_TYPE,
+ // but some implementations (ANGLE) do not seem to care.
+
+ if (m_contextMajorVersion == 1) {
+ attrib_list.push_back(EGL_RENDERABLE_TYPE);
+ attrib_list.push_back(EGL_OPENGL_ES_BIT);
+ }
+ else if (m_contextMajorVersion == 2) {
+ attrib_list.push_back(EGL_RENDERABLE_TYPE);
+ attrib_list.push_back(EGL_OPENGL_ES2_BIT);
+ }
+ else if (m_contextMajorVersion == 3) {
+ attrib_list.push_back(EGL_RENDERABLE_TYPE);
+ attrib_list.push_back(EGL_OPENGL_ES3_BIT_KHR);
+ }
+ else {
+ fprintf(stderr,
+ "Warning! Unable to request an ES context of version %d.%d\n",
+ m_contextMajorVersion, 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)))
+ {
+ fprintf(stderr,
+ "Warning! May not be able to create a version %d.%d ES context with version %d.%d of EGL\n",
+ m_contextMajorVersion, m_contextMinorVersion, egl_major, egl_minor);
+ }
+ }
+
+ attrib_list.push_back(EGL_RED_SIZE);
+ attrib_list.push_back(8);
+
+ attrib_list.push_back(EGL_GREEN_SIZE);
+ attrib_list.push_back(8);
+
+ attrib_list.push_back(EGL_BLUE_SIZE);
+ attrib_list.push_back(8);
+
+#ifdef GHOST_OPENGL_ALPHA
+ attrib_list.push_back(EGL_ALPHA_SIZE);
+ attrib_list.push_back(8);
+#endif
+
+ attrib_list.push_back(EGL_DEPTH_SIZE);
+ attrib_list.push_back(24);
+
+#ifdef GHOST_OPENGL_STENCIL
+ attrib_list.push_back(EGL_STENCIL_SIZE);
+ attrib_list.push_back(8);
+#endif
+
+ if (m_numOfAASamples > 0) {
+ attrib_list.push_back(EGL_SAMPLE_BUFFERS);
+ attrib_list.push_back(1);
+
+ attrib_list.push_back(EGL_SAMPLES);
+ attrib_list.push_back(m_numOfAASamples);
+ }
+
+ attrib_list.push_back(EGL_NONE);
+
+ EGLConfig config;
+
+ if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &config, 1, &num_config)))
+ goto error;
+
+ // A common error is to assume that ChooseConfig worked because it returned EGL_TRUE
+ if (num_config != 1) // num_config should be exactly 1
+ goto error;
+
+ if (m_numOfAASamples > 0) {
+ EGLint actualSamples;
+
+ if (!EGL_CHK(::eglGetConfigAttrib(m_display, config, EGL_SAMPLE_BUFFERS, &actualSamples)))
+ goto error;
+
+ if (m_numOfAASamples != actualSamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ m_numOfAASamples,
+ actualSamples);
+
+ m_numOfAASamples = (GHOST_TUns16)actualSamples;
+ }
+ }
+
+ m_surface = ::eglCreateWindowSurface(m_display, config, m_nativeWindow, NULL);
+
+ if (!EGL_CHK(m_surface != EGL_NO_SURFACE))
+ goto error;
+
+ attrib_list.clear();
+
+ if (EGLEW_VERSION_1_5 || EGLEW_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);
+ attrib_list.push_back(m_contextMajorVersion);
+ }
+
+ if (m_contextMinorVersion != 0) {
+ attrib_list.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
+ attrib_list.push_back(m_contextMinorVersion);
+ }
+
+ if (m_contextFlags != 0) {
+ attrib_list.push_back(EGL_CONTEXT_FLAGS_KHR);
+ attrib_list.push_back(m_contextFlags);
+ }
+ }
+ else {
+ if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
+ fprintf(stderr,
+ "Warning! Cannot request specific versions of %s contexts.",
+ api_string(m_api).c_str());
+ }
+
+ if (m_contextFlags != 0) {
+ fprintf(stderr,
+ "Warning! Flags cannot be set on %s contexts.",
+ api_string(m_api).c_str());
+ }
+ }
+
+ if (m_api == EGL_OPENGL_API) {
+ if (m_contextProfileMask != 0) {
+ attrib_list.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
+ attrib_list.push_back(m_contextProfileMask);
+ }
+ }
+ else {
+ if (m_contextProfileMask != 0)
+ fprintf(stderr,
+ "Warning! Cannot select profile for %s contexts.",
+ api_string(m_api).c_str());
+ }
+
+ if (m_api == EGL_OPENGL_API || EGLEW_VERSION_1_5) {
+ if (m_contextResetNotificationStrategy != 0) {
+ attrib_list.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
+ attrib_list.push_back(m_contextResetNotificationStrategy);
+ }
+ }
+ else {
+ if (m_contextResetNotificationStrategy != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d cannot set the reset notification strategy on %s contexts.",
+ egl_major, egl_minor, api_string(m_api).c_str());
+ }
+ }
+ }
+ else {
+ if (m_api == EGL_OPENGL_ES_API) {
+ if (m_contextMajorVersion != 0) {
+ attrib_list.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ attrib_list.push_back(m_contextMajorVersion);
+ }
+ }
+ else {
+ if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to select between versions of %s.",
+ egl_major, egl_minor, api_string(m_api).c_str());
+ }
+ }
+
+ if (m_contextFlags != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to set context flags.",
+ egl_major, egl_minor);
+ }
+ if (m_contextProfileMask != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to select between profiles.",
+ egl_major, egl_minor);
+ }
+ if (m_contextResetNotificationStrategy != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to set the reset notification strategies.",
+ egl_major, egl_minor);
+ }
+ }
+
+ attrib_list.push_back(EGL_NONE);
+
+ m_context = ::eglCreateContext(m_display, config, m_sharedContext, &(attrib_list[0]));
+
+ if (!EGL_CHK(m_context != EGL_NO_CONTEXT))
+ goto error;
+
+ if (m_sharedContext == EGL_NO_CONTEXT)
+ m_sharedContext = m_context;
+
+ m_sharedCount++;
+
+ if (!EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context)))
+ goto error;
+
+ initContextGLEW();
+
+ initClearGL();
+ ::eglSwapBuffers(m_display, m_surface);
+
+ return GHOST_kSuccess;
+
+error:
+ if (prev_display != EGL_NO_DISPLAY)
+ EGL_CHK(eglMakeCurrent(prev_display, prev_draw, prev_read, prev_context));
+
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::releaseNativeHandles()
+{
+ m_nativeWindow = 0;
+ m_nativeDisplay = NULL;
+
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h
new file mode 100644
index 00000000000..70c26c940fc
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextEGL.h
@@ -0,0 +1,167 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextEGL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTEGL_H__
+#define __GHOST_CONTEXTEGL_H__
+
+#include "GHOST_Context.h"
+
+#ifdef WITH_GLEW_MX
+# define eglewGetContext() eglewContext
+#endif
+
+#include <GL/eglew.h>
+
+#ifdef WITH_GLEW_MX
+extern "C" EGLEWContext *eglewContext;
+#endif
+
+
+#ifndef GHOST_OPENGL_EGL_CONTEXT_FLAGS
+#define GHOST_OPENGL_EGL_CONTEXT_FLAGS 0
+#endif
+
+#ifndef GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+class GHOST_ContextEGL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextEGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ EGLNativeWindowType nativeWindow,
+ EGLNativeDisplayType nativeDisplay,
+ EGLint contextProfileMask,
+ EGLint contextMajorVersion,
+ EGLint contextMinorVersion,
+ EGLint contextFlags,
+ EGLint contextResetNotificationStrategy,
+ EGLenum api);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextEGL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * 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();
+
+ /**
+ * 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();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * 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 &intervalOut);
+
+protected:
+ inline void activateEGLEW() const {
+#ifdef WITH_GLEW_MX
+ eglewContext = m_eglewContext;
+#endif
+ }
+
+private:
+ void initContextEGLEW();
+
+ EGLNativeDisplayType m_nativeDisplay;
+ EGLNativeWindowType m_nativeWindow;
+
+ const EGLint m_contextProfileMask;
+ const EGLint m_contextMajorVersion;
+ const EGLint m_contextMinorVersion;
+ const EGLint m_contextFlags;
+ const EGLint m_contextResetNotificationStrategy;
+
+ const EGLenum m_api;
+
+ EGLContext m_context;
+ EGLSurface m_surface;
+ EGLDisplay m_display;
+
+ EGLint m_swap_interval;
+
+#ifdef WITH_GLEW_MX
+ EGLEWContext *m_eglewContext;
+#endif
+
+ EGLContext &m_sharedContext;
+ EGLint &m_sharedCount;
+
+ static EGLContext s_gl_sharedContext;
+ static EGLint s_gl_sharedCount;
+
+ static EGLContext s_gles_sharedContext;
+ static EGLint s_gles_sharedCount;
+
+ static EGLContext s_vg_sharedContext;
+ static EGLint s_vg_sharedCount;
+
+#ifdef WITH_GL_ANGLE
+ static HMODULE s_d3dcompiler;
+#endif
+};
+
+#endif // __GHOST_CONTEXTEGL_H__
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
new file mode 100644
index 00000000000..02b43abec6c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -0,0 +1,411 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextGLX.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextGLX class.
+ */
+
+#include "GHOST_ContextGLX.h"
+#include "GHOST_SystemX11.h"
+
+#include <vector>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+
+#ifdef WITH_GLEW_MX
+GLXEWContext *glxewContext = NULL;
+#endif
+
+GLXContext GHOST_ContextGLX::s_sharedContext = None;
+int GHOST_ContextGLX::s_sharedCount = 0;
+
+
+GHOST_ContextGLX::GHOST_ContextGLX(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ Window window,
+ Display *display,
+ XVisualInfo *visualInfo,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_display(display),
+ m_visualInfo(visualInfo),
+ m_window(window),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_context(None)
+#ifdef WITH_GLEW_MX
+ ,
+ m_glxewContext(NULL)
+#endif
+{
+ assert(m_window != 0);
+ assert(m_display != NULL);
+}
+
+
+GHOST_ContextGLX::~GHOST_ContextGLX()
+{
+ if (m_display != NULL) {
+ activateGLXEW();
+
+ if (m_context != None) {
+ if (m_window != 0 && m_context == ::glXGetCurrentContext())
+ ::glXMakeCurrent(m_display, m_window, NULL);
+
+ if (m_context != s_sharedContext || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedContext = NULL;
+
+ ::glXDestroyContext(m_display, m_context);
+ }
+ }
+
+#ifdef WITH_GLEW_MX
+ if (m_glxewContext)
+ delete m_glxewContext;
+#endif
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::swapBuffers()
+{
+ ::glXSwapBuffers(m_display, m_window);
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::activateDrawingContext()
+{
+ if (m_display) {
+ activateGLXEW();
+ activateGLEW();
+
+ return ::glXMakeCurrent(m_display, m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+void GHOST_ContextGLX::initContextGLXEW()
+{
+#ifdef WITH_GLEW_MX
+ glxewContext = new GLXEWContext;
+ memset(glxewContext, 0, sizeof(GLXEWContext));
+
+ if (m_glxewContext)
+ delete m_glxewContext;
+ m_glxewContext = glxewContext;
+#endif
+
+ initContextGLEW();
+}
+
+GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
+{
+#ifdef WITH_X11_XINPUT
+ /* use our own event handlers to avoid exiting blender,
+ * this would happen for eg:
+ * if you open blender, unplug a tablet, then open a new window. */
+ XErrorHandler old_handler = XSetErrorHandler (GHOST_X11_ApplicationErrorHandler );
+ XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
+#endif
+
+ /* needed so 'GLXEW_ARB_create_context' is valid */
+ mxIgnoreNoVersion(1);
+ initContextGLXEW();
+ mxIgnoreNoVersion(0);
+
+ if (GLXEW_ARB_create_context) {
+ int profileBitCore = m_contextProfileMask & GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ int profileBitCompat = m_contextProfileMask & GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+
+#ifdef WITH_GLEW_ES
+ int profileBitES = m_contextProfileMask & GLX_CONTEXT_ES_PROFILE_BIT_EXT;
+#endif
+
+ if (!GLXEW_ARB_create_context_profile && profileBitCore)
+ fprintf(stderr, "Warning! OpenGL core profile not available.\n");
+
+ if (!GLXEW_ARB_create_context_profile && profileBitCompat)
+ fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
+
+#ifdef WITH_GLEW_ES
+ if (!GLXEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
+ fprintf(stderr, "Warning! OpenGL ES profile not available.\n");
+
+ if (!GLXEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
+ fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
+#endif
+
+ int profileMask = 0;
+
+ if (GLXEW_ARB_create_context_profile && profileBitCore)
+ profileMask |= profileBitCore;
+
+ if (GLXEW_ARB_create_context_profile && profileBitCompat)
+ profileMask |= profileBitCompat;
+
+#ifdef WITH_GLEW_ES
+ if (GLXEW_EXT_create_context_es_profile && profileBitES)
+ profileMask |= profileBitES;
+#endif
+
+ if (profileMask != m_contextProfileMask)
+ fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
+
+
+ /* max 10 attributes plus terminator */
+ int attribs[11];
+ int i = 0;
+
+ if (profileMask) {
+ attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB;
+ attribs[i++] = profileMask;
+ }
+
+ if (m_contextMajorVersion != 0) {
+ attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
+ attribs[i++] = m_contextMajorVersion;
+ }
+
+ if (m_contextMinorVersion != 0) {
+ attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
+ attribs[i++] = m_contextMinorVersion;
+ }
+
+ if (m_contextFlags != 0) {
+ attribs[i++] = GLX_CONTEXT_FLAGS_ARB;
+ attribs[i++] = m_contextFlags;
+ }
+
+ if (m_contextResetNotificationStrategy != 0) {
+ if (GLXEW_ARB_create_context_robustness) {
+ attribs[i++] = GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
+ attribs[i++] = m_contextResetNotificationStrategy;
+ }
+ else {
+ fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
+ }
+ }
+ attribs[i++] = 0;
+
+ /* Create a GL 3.x context */
+ GLXFBConfig *framebuffer_config = NULL;
+ {
+ int glx_attribs[64];
+ int fbcount = 0;
+
+ GHOST_X11_GL_GetAttributes(glx_attribs, 64, m_numOfAASamples, m_stereoVisual, true);
+
+ framebuffer_config = glXChooseFBConfig(m_display, DefaultScreen(m_display), glx_attribs, &fbcount);
+ }
+
+ if (framebuffer_config) {
+ m_context = glXCreateContextAttribsARB(m_display, framebuffer_config[0], s_sharedContext, True, attribs);
+ XFree(framebuffer_config);
+ }
+ }
+ else {
+ /* Create legacy context */
+ m_context = glXCreateContext(m_display, m_visualInfo, s_sharedContext, True);
+ }
+
+ GHOST_TSuccess success;
+
+ if (m_context != NULL) {
+ if (!s_sharedContext)
+ s_sharedContext = m_context;
+
+ s_sharedCount++;
+
+ glXMakeCurrent(m_display, m_window, m_context);
+
+ initClearGL();
+ ::glXSwapBuffers(m_display, m_window);
+
+ /* re initialize to get the extensions properly */
+ initContextGLXEW();
+
+ success = GHOST_kSuccess;
+ }
+ else {
+ /* freeing well clean up the context initialized above */
+ success = GHOST_kFailure;
+ }
+
+#ifdef WITH_X11_XINPUT
+ /* Restore handler */
+ XSetErrorHandler (old_handler);
+ XSetIOErrorHandler(old_handler_io);
+#endif
+
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::releaseNativeHandles()
+{
+ m_window = 0;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::setSwapInterval(int interval)
+{
+ if (GLXEW_EXT_swap_control) {
+ ::glXSwapIntervalEXT(m_display, m_window, interval);
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::getSwapInterval(int &intervalOut)
+{
+ if (GLXEW_EXT_swap_control) {
+ unsigned int interval = 0;
+
+ ::glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &interval);
+
+ intervalOut = static_cast<int>(interval);
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+/**
+ * Utility function to get GLX attributes.
+ *
+ * \param for_fb_config: There are some small differences in
+ * #glXChooseVisual and #glXChooseFBConfig's attribute encoding.
+ *
+ * \note Similar to SDL's 'X11_GL_GetAttributes'
+ */
+int GHOST_X11_GL_GetAttributes(
+ int *attribs, int attribs_max,
+ int samples, bool is_stereo_visual,
+ bool for_fb_config)
+{
+ int i = 0;
+
+#ifdef GHOST_OPENGL_ALPHA
+ const bool need_alpha = true;
+#else
+ const bool need_alpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ const bool need_stencil = true;
+#else
+ const bool need_stencil = false;
+#endif
+
+ if (is_stereo_visual) {
+ attribs[i++] = GLX_STEREO;
+ if (for_fb_config) {
+ attribs[i++] = True;
+ }
+ }
+
+ if (for_fb_config) {
+ attribs[i++] = GLX_RENDER_TYPE;
+ attribs[i++] = GLX_RGBA_BIT;
+ }
+ else {
+ attribs[i++] = GLX_RGBA;
+ }
+
+ attribs[i++] = GLX_DOUBLEBUFFER;
+ if (for_fb_config) {
+ attribs[i++] = True;
+ }
+
+ attribs[i++] = GLX_RED_SIZE;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_BLUE_SIZE;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_GREEN_SIZE;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_DEPTH_SIZE;
+ attribs[i++] = True;
+
+ if (need_alpha) {
+ attribs[i++] = GLX_ALPHA_SIZE;
+ attribs[i++] = True;
+ }
+
+ if (need_stencil) {
+ attribs[i++] = GLX_STENCIL_SIZE;
+ attribs[i++] = True;
+ }
+
+ if (samples) {
+ attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_SAMPLES_ARB;
+ attribs[i++] = samples;
+ }
+
+ attribs[i++] = 0;
+
+ GHOST_ASSERT(i <= attribs_max, "attribute size too small");
+
+ (void)attribs_max;
+
+ return i;
+}
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
new file mode 100644
index 00000000000..8c2231a0b01
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -0,0 +1,156 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextGLX.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTGLX_H__
+#define __GHOST_CONTEXTGLX_H__
+
+#include "GHOST_Context.h"
+
+#ifdef WITH_GLEW_MX
+# define glxewGetContext() glxewContext
+#endif
+
+#include <GL/glxew.h>
+
+#ifdef WITH_GLEW_MX
+extern "C" GLXEWContext *glxewContext;
+#endif
+
+
+#ifndef GHOST_OPENGL_GLX_CONTEXT_FLAGS
+/* leave as convenience define for the future */
+#define GHOST_OPENGL_GLX_CONTEXT_FLAGS 0
+#endif
+
+#ifndef GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+class GHOST_ContextGLX : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextGLX(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ Window window,
+ Display *display,
+ XVisualInfo *visualInfo,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextGLX();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * 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();
+
+ /**
+ * 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();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * 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 &intervalOut);
+
+protected:
+ inline void activateGLXEW() const {
+#ifdef WITH_GLEW_MX
+ glxewContext = m_glxewContext;
+#endif
+ }
+
+private:
+ void initContextGLXEW();
+
+ Display *m_display;
+ XVisualInfo *m_visualInfo;
+ Window m_window;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ GLXContext m_context;
+
+#ifdef WITH_GLEW_MX
+ GLXEWContext *m_glxewContext;
+#endif
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static GLXContext s_sharedContext;
+ static int s_sharedCount;
+};
+
+/* used to get GLX info */
+int GHOST_X11_GL_GetAttributes(
+ int *attribs, int attribs_max,
+ int samples, bool is_stereo_visual,
+ bool for_fb_config);
+
+#endif // __GHOST_CONTEXTGLX_H__
diff --git a/intern/ghost/intern/GHOST_ContextNone.cpp b/intern/ghost/intern/GHOST_ContextNone.cpp
new file mode 100644
index 00000000000..380ab532f7a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextNone.cpp
@@ -0,0 +1,79 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextNone.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextNone class.
+ */
+
+#include "GHOST_ContextNone.h"
+
+
+GHOST_TSuccess GHOST_ContextNone::swapBuffers()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::activateDrawingContext()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::updateDrawingContext()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::initializeDrawingContext()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::releaseNativeHandles()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::setSwapInterval(int interval)
+{
+ m_swapInterval = interval;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::getSwapInterval(int &intervalOut)
+{
+ intervalOut = m_swapInterval;
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h
new file mode 100644
index 00000000000..80cce76190d
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextNone.h
@@ -0,0 +1,97 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextNone.h
+ * \ingroup GHOST
+ *
+ * Declaration of GHOST_Context class.
+ */
+
+#ifndef __GHOST_CONTEXTNONE_H__
+#define __GHOST_CONTEXTNONE_H__
+
+#include "GHOST_Context.h"
+
+class GHOST_ContextNone : public GHOST_Context
+{
+public:
+
+ GHOST_ContextNone(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_swapInterval(1)
+ {}
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess updateDrawingContext();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * Dummy function
+ * \param intervalOut Gets whatever was set by setSwapInterval
+ * \return Always succeeds
+ */
+ GHOST_TSuccess getSwapInterval(int &intervalOut);
+
+private:
+ int m_swapInterval;
+};
+
+#endif // __GHOST_CONTEXTNONE_H__
diff --git a/intern/ghost/intern/GHOST_ContextSDL.cpp b/intern/ghost/intern/GHOST_ContextSDL.cpp
new file mode 100644
index 00000000000..d80a638818c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextSDL.cpp
@@ -0,0 +1,204 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextSDL.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextSDL class.
+ */
+
+#include "GHOST_ContextSDL.h"
+
+#include <vector>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+
+SDL_GLContext GHOST_ContextSDL::s_sharedContext = NULL;
+int GHOST_ContextSDL::s_sharedCount = 0;
+
+
+GHOST_ContextSDL::GHOST_ContextSDL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ SDL_Window *window,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_window(window),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_context(NULL)
+{
+ assert(m_window != NULL);
+}
+
+
+GHOST_ContextSDL::~GHOST_ContextSDL()
+{
+ if (m_context != NULL) {
+ if (m_window != 0 && m_context == SDL_GL_GetCurrentContext())
+ SDL_GL_MakeCurrent(m_window, m_context);
+
+ if (m_context != s_sharedContext || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedContext = NULL;
+
+ SDL_GL_DeleteContext(m_context);
+ }
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::swapBuffers()
+{
+ SDL_GL_SwapWindow(m_window);
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::activateDrawingContext()
+{
+ if (m_context) {
+ activateGLEW();
+
+ return SDL_GL_MakeCurrent(m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
+{
+#ifdef GHOST_OPENGL_ALPHA
+ const bool needAlpha = true;
+#else
+ const bool needAlpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ const bool needStencil = true;
+#else
+ const bool needStencil = false;
+#endif
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, m_contextProfileMask);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, m_contextMajorVersion);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, m_contextMinorVersion);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, m_contextFlags);
+
+ SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+
+ if (needAlpha) {
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ }
+
+ if (needStencil) {
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
+ }
+
+ if (m_stereoVisual) {
+ SDL_GL_SetAttribute(SDL_GL_STEREO, 1);
+ }
+
+ if (m_numOfAASamples) {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, m_numOfAASamples);
+ }
+
+ m_context = SDL_GL_CreateContext(m_window);
+
+ GHOST_TSuccess success;
+
+ if (m_context != NULL) {
+ if (!s_sharedContext)
+ s_sharedContext = m_context;
+
+ s_sharedCount++;
+
+ success = (SDL_GL_MakeCurrent(m_window, m_context) < 0) ?
+ GHOST_kFailure : GHOST_kSuccess;
+
+ initContextGLEW();
+
+ initClearGL();
+ SDL_GL_SwapWindow(m_window);
+
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::releaseNativeHandles()
+{
+ m_window = NULL;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::setSwapInterval(int interval)
+{
+ if (SDL_GL_SetSwapInterval(interval) != -1) {
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::getSwapInterval(int &intervalOut)
+{
+ intervalOut = SDL_GL_GetSwapInterval();
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h
new file mode 100644
index 00000000000..61f339c1bc2
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextSDL.h
@@ -0,0 +1,131 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextSDL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTSDL_H__
+#define __GHOST_CONTEXTSDL_H__
+
+#include "GHOST_Context.h"
+
+extern "C" {
+ #include "SDL.h"
+}
+
+
+#ifndef GHOST_OPENGL_SDL_CONTEXT_FLAGS
+# ifdef WITH_GPU_DEBUG
+# define GHOST_OPENGL_SDL_CONTEXT_FLAGS SDL_GL_CONTEXT_DEBUG_FLAG
+# else
+# define GHOST_OPENGL_SDL_CONTEXT_FLAGS 0
+# endif
+#endif
+
+#ifndef GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+class GHOST_ContextSDL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextSDL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ SDL_Window *window,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextSDL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * 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();
+
+ /**
+ * 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();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * 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 &intervalOut);
+
+private:
+ SDL_Window *m_window;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ SDL_GLContext m_context; /* m_sdl_glcontext */
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static SDL_GLContext s_sharedContext;
+ static int s_sharedCount;
+};
+
+#endif // __GHOST_CONTEXTSDL_H__
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
new file mode 100644
index 00000000000..d2a9eed95d9
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -0,0 +1,956 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextWGL.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextWGL class.
+ */
+
+#include "GHOST_ContextWGL.h"
+
+#include <tchar.h>
+
+#include <cstdio>
+#include <cassert>
+#include <vector>
+
+
+#ifdef WITH_GLEW_MX
+WGLEWContext *wglewContext = NULL;
+#endif
+
+HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL;
+int GHOST_ContextWGL::s_sharedCount = 0;
+
+bool GHOST_ContextWGL::s_singleContextMode = false;
+bool GHOST_ContextWGL::s_warn_old = false;
+
+
+/* Intel video-cards don't work fine with multiple contexts and
+ * have to share the same context for all windows.
+ * But if we just share context for all windows it could work incorrect
+ * with multiple videocards configuration. Suppose, that Intel videocards
+ * can't be in multiple-devices configuration. */
+static bool is_crappy_intel_card()
+{
+ return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL;
+}
+
+
+GHOST_ContextWGL::GHOST_ContextWGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ HWND hWnd,
+ HDC hDC,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_hWnd(hWnd),
+ m_hDC(hDC),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_hGLRC(NULL)
+#ifdef WITH_GLEW_MX
+ ,
+ m_wglewContext(NULL)
+#endif
+#ifndef NDEBUG
+ ,
+ m_dummyVendor(NULL),
+ m_dummyRenderer(NULL),
+ m_dummyVersion(NULL)
+#endif
+{
+ assert(m_hWnd);
+ assert(m_hDC);
+}
+
+
+GHOST_ContextWGL::~GHOST_ContextWGL()
+{
+ if (m_hGLRC != NULL) {
+ if (m_hGLRC == ::wglGetCurrentContext())
+ WIN32_CHK(::wglMakeCurrent(NULL, NULL));
+
+ if (m_hGLRC != s_sharedHGLRC || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedHGLRC = NULL;
+
+ WIN32_CHK(::wglDeleteContext(m_hGLRC));
+ }
+ }
+
+#ifdef WITH_GLEW_MX
+ delete m_wglewContext;
+#endif
+
+#ifndef NDEBUG
+ free((void*)m_dummyRenderer);
+ free((void*)m_dummyVendor);
+ free((void*)m_dummyVersion);
+#endif
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::swapBuffers()
+{
+ return WIN32_CHK(::SwapBuffers(m_hDC)) ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::setSwapInterval(int interval)
+{
+ if (WGLEW_EXT_swap_control)
+ return WIN32_CHK(::wglSwapIntervalEXT(interval)) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ else
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::getSwapInterval(int &intervalOut)
+{
+ if (WGLEW_EXT_swap_control) {
+ intervalOut = ::wglGetSwapIntervalEXT();
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::activateDrawingContext()
+{
+ if (WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
+ activateGLEW();
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+/* Ron Fosner's code for weighting pixel formats and forcing software.
+ * See http://www.opengl.org/resources/faq/technical/weight.cpp
+ */
+static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd)
+{
+ int weight = 0;
+
+ /* assume desktop color depth is 32 bits per pixel */
+
+ /* cull unusable pixel formats */
+ /* if no formats can be found, can we determine why it was rejected? */
+ if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
+ !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
+ !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
+ !(pfd.iPixelType == PFD_TYPE_RGBA) ||
+ (pfd.cDepthBits < 16) ||
+ (pfd.dwFlags & PFD_GENERIC_FORMAT)) /* no software renderers */
+ {
+ return 0;
+ }
+
+ weight = 1; /* it's usable */
+
+ /* the bigger the depth buffer the better */
+ /* give no weight to a 16-bit depth buffer, because those are crap */
+ weight += pfd.cDepthBits - 16;
+
+ weight += pfd.cColorBits - 8;
+
+#ifdef GHOST_OPENGL_ALPHA
+ if (pfd.cAlphaBits > 0)
+ weight++;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ if (pfd.cStencilBits >= 8)
+ weight++;
+#endif
+
+ /* want swap copy capability -- it matters a lot */
+ if (pfd.dwFlags & PFD_SWAP_COPY)
+ weight += 16;
+
+ return weight;
+}
+
+
+/*
+ * A modification of Ron Fosner's replacement for ChoosePixelFormat
+ * returns 0 on error, else returns the pixel format number to be used
+ */
+static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredPFD)
+{
+ int iPixelFormat = 0;
+ int weight = 0;
+
+ int iStereoPixelFormat = 0;
+ int stereoWeight = 0;
+
+ /* choose a pixel format using the useless Windows function in case we come up empty handed */
+ int iLastResortPixelFormat = ::ChoosePixelFormat(hDC, &preferredPFD);
+
+ WIN32_CHK(iLastResortPixelFormat != 0);
+
+ int lastPFD = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
+
+ WIN32_CHK(lastPFD != 0);
+
+ for (int i = 1; i <= lastPFD; i++) {
+ PIXELFORMATDESCRIPTOR pfd;
+ int check = ::DescribePixelFormat(hDC, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+ WIN32_CHK(check == lastPFD);
+
+ int w = weight_pixel_format(pfd);
+
+ if (w > weight) {
+ weight = w;
+ iPixelFormat = i;
+ }
+
+ if (w > stereoWeight && (preferredPFD.dwFlags & pfd.dwFlags & PFD_STEREO)) {
+ stereoWeight = w;
+ iStereoPixelFormat = i;
+ }
+ }
+
+ /* choose any available stereo format over a non-stereo format */
+ if (iStereoPixelFormat != 0)
+ iPixelFormat = iStereoPixelFormat;
+
+ if (iPixelFormat == 0) {
+ fprintf(stderr, "Warning! Using result of ChoosePixelFormat.\n");
+ iPixelFormat = iLastResortPixelFormat;
+ }
+
+ return iPixelFormat;
+}
+
+
+/*
+ * Clone a window for the purpose of creating a temporary context to initialize WGL extensions.
+ * There is no generic way to clone the lpParam parameter, so the caller is responsible for cloning it themselves.
+ */
+
+static HWND clone_window(HWND hWnd, LPVOID lpParam)
+{
+ int count;
+
+ SetLastError(NO_ERROR);
+
+ DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ WCHAR lpClassName[100] = L"";
+ count = GetClassNameW(hWnd, lpClassName, sizeof(lpClassName));
+ WIN32_CHK(count != 0);
+
+ WCHAR lpWindowName[100] = L"";
+ count = GetWindowTextW(hWnd, lpWindowName, sizeof(lpWindowName));
+ WIN32_CHK(count != 0);
+
+ DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ RECT rect;
+ GetWindowRect(hWnd, &rect);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HWND hWndParent = (HWND)GetWindowLongPtr(hWnd, GWLP_HWNDPARENT);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HMENU hMenu = GetMenu(hWnd);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HWND hwndCloned = CreateWindowExW(
+ dwExStyle,
+ lpClassName,
+ lpWindowName,
+ dwStyle,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ hWndParent,
+ hMenu,
+ hInstance,
+ lpParam);
+
+ WIN32_CHK(hwndCloned != NULL);
+
+ return hwndCloned;
+}
+
+
+void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
+{
+ HWND dummyHWND = NULL;
+ HDC dummyHDC = NULL;
+ HGLRC dummyHGLRC = NULL;
+
+ HDC prevHDC;
+ HGLRC prevHGLRC;
+
+ int iPixelFormat;
+
+
+#ifdef WITH_GLEW_MX
+ wglewContext = new WGLEWContext;
+ memset(wglewContext, 0, sizeof(WGLEWContext));
+
+ delete m_wglewContext;
+ m_wglewContext = wglewContext;
+#endif
+
+ SetLastError(NO_ERROR);
+
+ prevHDC = ::wglGetCurrentDC();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ prevHGLRC = ::wglGetCurrentContext();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ dummyHWND = clone_window(m_hWnd, NULL);
+
+ if (dummyHWND == NULL)
+ goto finalize;
+
+ dummyHDC = GetDC(dummyHWND);
+
+ if (!WIN32_CHK(dummyHDC != NULL))
+ goto finalize;
+
+ iPixelFormat = choose_pixel_format_legacy(dummyHDC, preferredPFD);
+
+ if (iPixelFormat == 0)
+ goto finalize;
+
+ PIXELFORMATDESCRIPTOR chosenPFD;
+ if (!WIN32_CHK(::DescribePixelFormat(dummyHDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
+ 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;
+
+#ifdef WITH_GLEW_MX
+ if (GLEW_CHK(wglewInit()) != GLEW_OK)
+ fprintf(stderr, "Warning! WGLEW failed to initialize properly.\n");
+#else
+ if (GLEW_CHK(glewInit()) != GLEW_OK)
+ fprintf(stderr, "Warning! Dummy GLEW/WGLEW failed to initialize properly.\n");
+#endif
+
+ // the following are not technially 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
+
+ s_singleContextMode = is_crappy_intel_card();
+
+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,
+ int numOfAASamples,
+ int swapMethod,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB)
+{
+ out.clear();
+ out.reserve(30);
+
+ out.push_back(WGL_SUPPORT_OPENGL_ARB);
+ out.push_back(GL_TRUE);
+
+ out.push_back(WGL_DRAW_TO_WINDOW_ARB);
+ out.push_back(GL_TRUE);
+
+ out.push_back(WGL_DOUBLE_BUFFER_ARB);
+ out.push_back(GL_TRUE);
+
+ out.push_back(WGL_ACCELERATION_ARB);
+ out.push_back(WGL_FULL_ACCELERATION_ARB);
+
+ out.push_back(WGL_SWAP_METHOD_ARB);
+ out.push_back(swapMethod);
+
+ if (stereoVisual) {
+ out.push_back(WGL_STEREO_ARB);
+ out.push_back(GL_TRUE);
+ }
+
+ out.push_back(WGL_PIXEL_TYPE_ARB);
+ out.push_back(WGL_TYPE_RGBA_ARB);
+
+ out.push_back(WGL_COLOR_BITS_ARB);
+ out.push_back(24);
+
+ out.push_back(WGL_DEPTH_BITS_ARB);
+ out.push_back(24);
+
+ if (needAlpha) {
+ out.push_back(WGL_ALPHA_BITS_ARB);
+ out.push_back(8);
+ }
+
+ if (needStencil) {
+ out.push_back(WGL_STENCIL_BITS_ARB);
+ out.push_back(8);
+ }
+
+ if (numOfAASamples > 0) {
+ out.push_back(WGL_SAMPLES_ARB);
+ out.push_back(numOfAASamples);
+
+ out.push_back(WGL_SAMPLE_BUFFERS_ARB);
+ out.push_back(GL_TRUE);
+ }
+
+ if (sRGB) {
+ out.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
+ out.push_back(GL_TRUE);
+ }
+
+ out.push_back(0);
+}
+
+
+int GHOST_ContextWGL::_choose_pixel_format_arb_2(
+ bool stereoVisual,
+ int *numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int swapMethod)
+{
+ std::vector<int> iAttributes;
+
+ int iPixelFormat = 0;
+
+ int samples;
+
+ // guard against some insanely high number of samples
+ if (*numOfAASamples > 64) {
+ fprintf(stderr, "Warning! Clamping number of samples to 64.\n");
+ samples = 64;
+ }
+ else {
+ samples = *numOfAASamples;
+ }
+
+ // request a format with as many samples as possible, but not more than requested
+ while (samples >= 0) {
+ makeAttribList(
+ iAttributes,
+ stereoVisual,
+ samples,
+ swapMethod,
+ needAlpha,
+ needStencil,
+ sRGB);
+
+ UINT nNumFormats;
+ WIN32_CHK(wglChoosePixelFormatARB(m_hDC, &(iAttributes[0]), NULL, 1, &iPixelFormat, &nNumFormats));
+
+ /* total number of formats that match (regardless of size of iPixelFormat array)
+ * see: WGL_ARB_pixel_format extension spec */
+ if (nNumFormats > 0)
+ break;
+
+ /* if not reset, then the state of iPixelFormat is undefined after call to wglChoosePixelFormatARB
+ * see: WGL_ARB_pixel_format extension spec */
+ iPixelFormat = 0;
+
+ samples--;
+ }
+
+ // check how many samples were actually gotten
+ if (iPixelFormat != 0) {
+ int iQuery[] = { WGL_SAMPLES_ARB };
+ int actualSamples;
+ wglGetPixelFormatAttribivARB(m_hDC, iPixelFormat, 0, 1, iQuery, &actualSamples);
+
+ if (actualSamples != *numOfAASamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ *numOfAASamples, actualSamples);
+
+ *numOfAASamples = actualSamples; // set context property to actual value
+ }
+ }
+ else {
+ *numOfAASamples = 0;
+ }
+ return iPixelFormat;
+}
+
+
+int GHOST_ContextWGL::_choose_pixel_format_arb_1(bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int *swapMethodOut)
+{
+ int iPixelFormat;
+ int copyPixelFormat = 0;
+ int undefPixelFormat = 0;
+ int exchPixelFormat = 0;
+ int copyNumOfAASamples = 0;
+ int undefNumOfAASamples = 0;
+ int exchNumOfAASamples = 0;
+
+ *swapMethodOut = WGL_SWAP_COPY_ARB;
+ copyNumOfAASamples = numOfAASamples;
+ copyPixelFormat = _choose_pixel_format_arb_2(
+ stereoVisual, &copyNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
+
+ if (copyPixelFormat == 0 || copyNumOfAASamples < numOfAASamples) {
+ *swapMethodOut = WGL_SWAP_UNDEFINED_ARB;
+ undefNumOfAASamples = numOfAASamples;
+ undefPixelFormat = _choose_pixel_format_arb_2(
+ stereoVisual, &undefNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
+
+ if (undefPixelFormat == 0 || undefNumOfAASamples < numOfAASamples) {
+ *swapMethodOut = WGL_SWAP_EXCHANGE_ARB;
+ exchNumOfAASamples = numOfAASamples;
+ exchPixelFormat = _choose_pixel_format_arb_2(
+ stereoVisual, &exchNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
+ if (exchPixelFormat == 0 || exchNumOfAASamples < numOfAASamples) {
+ // the number of AA samples cannot be met, take the highest
+ if (undefPixelFormat != 0 && undefNumOfAASamples >= exchNumOfAASamples) {
+ exchNumOfAASamples = undefNumOfAASamples;
+ exchPixelFormat = undefPixelFormat;
+ *swapMethodOut = WGL_SWAP_UNDEFINED_ARB;
+ }
+ if (copyPixelFormat != 0 && copyNumOfAASamples >= exchNumOfAASamples) {
+ exchNumOfAASamples = copyNumOfAASamples;
+ exchPixelFormat = copyPixelFormat;
+ *swapMethodOut = WGL_SWAP_COPY_ARB;
+ }
+ }
+ iPixelFormat = exchPixelFormat;
+ m_numOfAASamples = exchNumOfAASamples;
+ }
+ else {
+ iPixelFormat = undefPixelFormat;
+ m_numOfAASamples = undefNumOfAASamples;
+ }
+ }
+ else {
+ iPixelFormat = copyPixelFormat;
+ m_numOfAASamples = copyNumOfAASamples;
+ }
+ return iPixelFormat;
+}
+
+
+int GHOST_ContextWGL::choose_pixel_format_arb(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB)
+{
+ int iPixelFormat;
+ int swapMethodOut;
+
+ iPixelFormat = _choose_pixel_format_arb_1(
+ stereoVisual,
+ numOfAASamples,
+ needAlpha,
+ needStencil,
+ sRGB,
+ &swapMethodOut);
+
+ if (iPixelFormat == 0 && stereoVisual) {
+ fprintf(stderr, "Warning! Unable to find a stereo pixel format.\n");
+
+ iPixelFormat = _choose_pixel_format_arb_1(
+ false,
+ numOfAASamples,
+ needAlpha,
+ needStencil,
+ sRGB,
+ &swapMethodOut);
+
+ m_stereoVisual = false; // set context property to actual value
+ }
+
+ if (swapMethodOut != WGL_SWAP_COPY_ARB) {
+ fprintf(stderr,
+ "Warning! Unable to find a pixel format that supports WGL_SWAP_COPY_ARB. "
+ "Substituting one that uses %s.\n",
+ swapMethodOut == WGL_SWAP_UNDEFINED_ARB ? "WGL_SWAP_UNDEFINED_ARB" : "WGL_SWAP_EXCHANGE_ARB");
+ }
+
+ return iPixelFormat;
+}
+
+
+int GHOST_ContextWGL::choose_pixel_format(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB)
+{
+ PIXELFORMATDESCRIPTOR preferredPFD = {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size */
+ 1, /* version */
+ PFD_SUPPORT_OPENGL |
+ PFD_DRAW_TO_WINDOW |
+ PFD_SWAP_COPY | /* support swap copy */
+ PFD_DOUBLEBUFFER | /* support double-buffering */
+ (stereoVisual ? PFD_STEREO : 0), /* support stereo */
+ PFD_TYPE_RGBA, /* color type */
+ 24, /* preferred color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
+ needAlpha ? 8 : 0, /* alpha buffer */
+ 0, /* alpha shift (ignored) */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits (ignored) */
+ 24, /* depth buffer */
+ needStencil ? 8 : 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);
+
+ if (numOfAASamples > 0 && !WGLEW_ARB_multisample) {
+ fprintf(stderr, "Warning! Unable to request a multisample framebuffer.\n");
+ numOfAASamples = 0;
+ }
+
+ if (sRGB && !(WGLEW_ARB_framebuffer_sRGB || WGLEW_EXT_framebuffer_sRGB)) {
+ fprintf(stderr, "Warning! Unable to request an sRGB framebuffer.\n");
+ sRGB = false;
+ }
+
+ int iPixelFormat = 0;
+
+ if (WGLEW_ARB_pixel_format)
+ iPixelFormat = choose_pixel_format_arb(stereoVisual, numOfAASamples, needAlpha, needStencil, sRGB);
+
+ 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)
+{
+ fprintf(stderr, "%s: %s\n", name, context);
+
+ if (strcmp(dummy, context) != 0)
+ fprintf(stderr, "Warning! Dummy %s: %s\n", name, dummy);
+}
+#endif
+
+
+GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
+{
+#ifdef GHOST_OPENGL_ALPHA
+ const bool needAlpha = true;
+#else
+ const bool needAlpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ const bool needStencil = true;
+#else
+ const bool needStencil = false;
+#endif
+
+#ifdef GHOST_OPENGL_SRGB
+ const bool sRGB = true;
+#else
+ const bool sRGB = false;
+#endif
+
+ HGLRC prevHGLRC;
+ HDC prevHDC;
+
+ int iPixelFormat;
+ int lastPFD;
+
+ PIXELFORMATDESCRIPTOR chosenPFD;
+
+
+ SetLastError(NO_ERROR);
+
+ prevHGLRC = ::wglGetCurrentContext();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ prevHDC = ::wglGetCurrentDC();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB);
+
+ if (iPixelFormat == 0) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
+
+ if (!WIN32_CHK(lastPFD != 0)) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ if (needAlpha && chosenPFD.cAlphaBits == 0)
+ fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
+
+ if (needStencil && chosenPFD.cStencilBits == 0)
+ fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n");
+
+ if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ activateWGLEW();
+
+ 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;
+
+#ifdef WITH_GLEW_ES
+ int profileBitES = m_contextProfileMask & WGL_CONTEXT_ES_PROFILE_BIT_EXT;
+#endif
+
+ if (!WGLEW_ARB_create_context_profile && profileBitCore)
+ fprintf(stderr, "Warning! OpenGL core profile not available.\n");
+
+ if (!WGLEW_ARB_create_context_profile && profileBitCompat)
+ fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
+
+#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 (!WGLEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
+ fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
+#endif
+
+ int profileMask = 0;
+
+ if (WGLEW_ARB_create_context_profile && profileBitCore)
+ profileMask |= profileBitCore;
+
+ if (WGLEW_ARB_create_context_profile && profileBitCompat)
+ profileMask |= profileBitCompat;
+
+#ifdef WITH_GLEW_ES
+ if (WGLEW_EXT_create_context_es_profile && profileBitES)
+ profileMask |= profileBitES;
+#endif
+
+ if (profileMask != m_contextProfileMask)
+ fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
+
+ 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 (m_contextMinorVersion != 0) {
+ iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ iAttributes.push_back(m_contextMinorVersion);
+ }
+
+ if (m_contextFlags != 0) {
+ iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
+ iAttributes.push_back(m_contextFlags);
+ }
+
+ if (m_contextResetNotificationStrategy != 0) {
+ if (WGLEW_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);
+
+ if (!s_singleContextMode || s_sharedHGLRC == NULL)
+ m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
+ else
+ m_hGLRC = s_sharedHGLRC;
+ }
+ else {
+ if (m_contextProfileMask != 0)
+ fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL profiles.");
+
+ if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0)
+ fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL versions.");
+
+ if (m_contextFlags != 0)
+ fprintf(stderr, "Warning! Legacy WGL is unable to set context flags.");
+
+ if (!s_singleContextMode || s_sharedHGLRC == NULL)
+ m_hGLRC = ::wglCreateContext(m_hDC);
+ else
+ m_hGLRC = s_sharedHGLRC;
+ }
+
+ if (!WIN32_CHK(m_hGLRC != NULL)) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ if (s_sharedHGLRC == NULL)
+ s_sharedHGLRC = m_hGLRC;
+
+ s_sharedCount++;
+
+ if (!s_singleContextMode && s_sharedHGLRC != m_hGLRC && !WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ initContextGLEW();
+
+ initClearGL();
+ ::SwapBuffers(m_hDC);
+
+ const char *vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
+ const char *renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
+ const char *version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
+
+#ifndef NDEBUG
+ reportContextString("Vendor", m_dummyVendor, vendor);
+ reportContextString("Renderer", m_dummyRenderer, renderer);
+ reportContextString("Version", m_dummyVersion, version);
+#endif
+
+ if (!s_warn_old) {
+ if ((strcmp(vendor, "Microsoft Corporation") == 0 ||
+ strcmp(renderer, "GDI Generic") == 0) && version[0] == '1' && version[2] == '1')
+ {
+ MessageBox(m_hWnd, "Your system does not use 3D hardware acceleration.\n"
+ "Such systems can cause stability problems in Blender and they are unsupported.\n\n"
+ "This may be caused by:\n"
+ "* A missing or faulty graphics driver installation.\n"
+ " Blender needs a graphics card driver to work correctly.\n"
+ "* Accessing Blender through a remote connection.\n"
+ "* Using Blender through a virtual machine.\n\n"
+ "Disable this message in <User Preferences - Interface - Warn On Deprecated OpenGL>",
+ "Blender - Can't detect 3D hardware accelerated Driver!", MB_OK | MB_ICONWARNING);
+ }
+ else if (version[0] == '1' && version[2] < '4') {
+ MessageBox(m_hWnd, "The OpenGL version provided by your graphics driver version is too low\n"
+ "Blender requires version 1.4 and may not work correctly\n\n"
+ "Disable this message in <User Preferences - Interface - Warn On Deprecated OpenGL>",
+ "Blender - Unsupported Graphics Driver!", MB_OK | MB_ICONWARNING);
+ }
+ s_warn_old = true;
+ }
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles()
+{
+ GHOST_TSuccess success = m_hGLRC != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess : GHOST_kFailure;
+
+ m_hWnd = NULL;
+ m_hDC = NULL;
+
+ return success;
+}
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
new file mode 100644
index 00000000000..c457ddab2f7
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -0,0 +1,190 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextWGL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTWGL_H__
+#define __GHOST_CONTEXTWGL_H__
+
+#include "GHOST_Context.h"
+
+#ifdef WITH_GLEW_MX
+#define wglewGetContext() wglewContext
+#endif
+
+#include <GL/wglew.h>
+
+#ifdef WITH_GLEW_MX
+extern "C" WGLEWContext *wglewContext;
+#endif
+
+#ifndef GHOST_OPENGL_WGL_CONTEXT_FLAGS
+# ifdef WITH_GPU_DEBUG
+# define GHOST_OPENGL_WGL_CONTEXT_FLAGS WGL_CONTEXT_DEBUG_BIT_ARB
+# else
+# define GHOST_OPENGL_WGL_CONTEXT_FLAGS 0
+# endif
+#endif
+
+#ifndef GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+class GHOST_ContextWGL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextWGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ HWND hWnd,
+ HDC hDC,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextWGL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * 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();
+
+ /**
+ * 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();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * 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 &intervalOut);
+
+ static void unSetWarningOld(){s_warn_old = true;}
+
+protected:
+ inline void activateWGLEW() const {
+#ifdef WITH_GLEW_MX
+ wglewContext = m_wglewContext;
+#endif
+ }
+
+private:
+ int choose_pixel_format(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB);
+
+ int choose_pixel_format_arb(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB);
+
+ int _choose_pixel_format_arb_1(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int *swapMethodOut);
+
+ int _choose_pixel_format_arb_2(bool stereoVisual,
+ int *numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int swapMethod);
+
+ void initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD);
+
+ HWND m_hWnd;
+ HDC m_hDC;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ HGLRC m_hGLRC;
+
+#ifdef WITH_GLEW_MX
+ WGLEWContext *m_wglewContext;
+#endif
+
+#ifndef NDEBUG
+ const char *m_dummyVendor;
+ const char *m_dummyRenderer;
+ const char *m_dummyVersion;
+#endif
+
+ static HGLRC s_sharedHGLRC;
+ static int s_sharedCount;
+
+ static bool s_singleContextMode;
+ static bool s_warn_old;
+};
+
+#endif // __GHOST_CONTEXTWGL_H__
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
index 9292235a9c7..db49627b378 100644
--- a/intern/ghost/intern/GHOST_Debug.h
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -80,7 +80,7 @@
} \
} (void)0
#else // GHOST_DEBUG
-# define GHOST_ASSERT(x, info)
+# define GHOST_ASSERT(x, info) ((void)0)
#endif // GHOST_DEBUG
#endif // __GHOST_DEBUG_H__
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
index 1f17b4dd976..f580820d8f6 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
@@ -58,15 +58,15 @@ public:
* \param numDisplays The number of displays on this system.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
+ GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
/**
* Returns the number of display settings for this display device.
* \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The number of settings of the display device with this index.
+ * \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
/**
* Returns the current setting for this display device.
@@ -75,7 +75,7 @@ public:
* \param setting The setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
/**
* Returns the current setting for this display device.
@@ -83,7 +83,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
/**
* Changes the current setting for this display device.
@@ -91,7 +91,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
+ GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
protected:
//Do not cache values as OS X supports screen hot plug
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
index ced4ceac044..ff8849f03c9 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
@@ -58,15 +58,15 @@ public:
* \param numDisplays The number of displays on this system.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
+ GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
/**
* Returns the number of display settings for this display device.
* \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The number of settings of the display device with this index.
+ * \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
/**
* Returns the current setting for this display device.
@@ -75,7 +75,7 @@ public:
* \param setting The setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
/**
* Returns the current setting for this display device.
@@ -83,7 +83,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
/**
* Changes the current setting for this display device.
@@ -91,7 +91,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
+ GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
protected:
};
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
index 24289e6b006..b3e6f2e53fa 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
@@ -90,6 +90,7 @@ getNumDisplaySettings(
numSettings = 1;
#endif
+ (void) display;
return GHOST_kSuccess;
}
@@ -116,6 +117,8 @@ getDisplaySetting(
if (dpy == NULL)
return GHOST_kFailure;
+ (void)display;
+
#ifdef WITH_X11_XF86VMODE
int majorVersion, minorVersion;
@@ -146,6 +149,7 @@ getDisplaySetting(
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
+ (void)index;
setting.xPixels = DisplayWidth(dpy, DefaultScreen(dpy));
setting.yPixels = DisplayHeight(dpy, DefaultScreen(dpy));
@@ -171,7 +175,7 @@ getCurrentDisplaySetting(
GHOST_TSuccess
GHOST_DisplayManagerX11::
setCurrentDisplaySetting(
- GHOST_TUns8 display,
+ GHOST_TUns8 /*display*/,
const GHOST_DisplaySetting& setting)
{
#ifdef WITH_X11_XF86VMODE
@@ -264,6 +268,8 @@ setCurrentDisplaySetting(
return GHOST_kSuccess;
#else
+ (void)setting;
+
/* Just pretend the request was successful. */
return GHOST_kSuccess;
#endif
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h
index 66fd1e5c15e..b54c53c67bd 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h
@@ -66,7 +66,7 @@ public:
/**
* Returns the number of display settings for this display device.
* \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The number of settings of the display device with this index.
+ * \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h
index fb85feffde0..56bae1fd1b2 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.h
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.h
@@ -89,7 +89,7 @@ public:
* Destructor
* Do NOT destroy directly. Use Release() instead to make COM happy.
*/
- virtual ~GHOST_DropTargetWin32();
+ ~GHOST_DropTargetWin32();
private:
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp
index 639fd503759..0efc8a78df5 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp
@@ -132,7 +132,8 @@ void GHOST_DropTargetX11::UrlDecode(char *decodedOut, int bufferSize, const char
unsigned int i;
unsigned int len = strlen(encodedIn);
DecodeState_e state = STATE_SEARCH;
- int j, asciiCharacter;
+ int j;
+ unsigned int asciiCharacter;
char tempNumBuf[3] = {0};
bool bothDigits = true;
diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h
index ea4d603be83..6a715498b87 100644
--- a/intern/ghost/intern/GHOST_Event.h
+++ b/intern/ghost/intern/GHOST_Event.h
@@ -59,7 +59,7 @@ public:
* Returns the event type.
* \return The event type.
*/
- virtual GHOST_TEventType getType()
+ GHOST_TEventType getType()
{
return m_type;
}
@@ -68,7 +68,7 @@ public:
* Returns the time this event was generated.
* \return The event generation time.
*/
- virtual GHOST_TUns64 getTime()
+ GHOST_TUns64 getTime()
{
return m_time;
}
@@ -78,7 +78,7 @@ public:
* or NULL if it is a 'system' event.
* \return The generating window.
*/
- virtual GHOST_IWindow *getWindow()
+ GHOST_IWindow *getWindow()
{
return m_window;
}
@@ -87,7 +87,7 @@ public:
* Returns the event data.
* \return The event data.
*/
- virtual GHOST_TEventDataPtr getData()
+ GHOST_TEventDataPtr getData()
{
return m_data;
}
diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h
index f88fe6e201d..ef5c5efa202 100644
--- a/intern/ghost/intern/GHOST_EventButton.h
+++ b/intern/ghost/intern/GHOST_EventButton.h
@@ -47,9 +47,8 @@ public:
* Constructor.
* \param time The time this event was generated.
* \param type The type of this event.
- * \param x The x-coordinate of the location the cursor was at at the time of the event.
- * \param y The y-coordinate of the location the cursor was at at the time of the event.
- * \param buttons The state of the buttons was at at the time of the event.
+ * \param window: The window of this event.
+ * \param button: The state of the buttons were at at the time of the event.
*/
GHOST_EventButton(GHOST_TUns64 time, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask button)
: GHOST_Event(time, type, window)
diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h
index c51f9568087..b7bf37c99d8 100644
--- a/intern/ghost/intern/GHOST_EventDragnDrop.h
+++ b/intern/ghost/intern/GHOST_EventDragnDrop.h
@@ -112,6 +112,7 @@ public:
for (i = 0; i < strArray->count; i++)
free(strArray->strings[i]);
+ free(strArray->strings);
free(strArray);
}
break;
diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h
index 8e513b4ee76..c8b5d1debe5 100644
--- a/intern/ghost/intern/GHOST_EventManager.h
+++ b/intern/ghost/intern/GHOST_EventManager.h
@@ -58,27 +58,27 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_EventManager();
+ ~GHOST_EventManager();
/**
* Returns the number of events currently on the stack.
* \return The number of events on the stack.
*/
- virtual GHOST_TUns32 getNumEvents();
+ GHOST_TUns32 getNumEvents();
/**
* Returns the number of events of a certain type currently on the stack.
* \param type The type of events to be counted.
* \return The number of events on the stack of this type.
*/
- virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type);
+ GHOST_TUns32 getNumEvents(GHOST_TEventType type);
/**
* Return the event at the top of the stack without removal.
* Do not delete the event!
* \return The event at the top of the stack.
*/
- virtual GHOST_IEvent *peekEvent();
+ GHOST_IEvent *peekEvent();
/**
* Pushes an event on the stack.
@@ -86,47 +86,47 @@ public:
* Do not delete the event!
* \param event The event to push on the stack.
*/
- virtual GHOST_TSuccess pushEvent(GHOST_IEvent *event);
+ GHOST_TSuccess pushEvent(GHOST_IEvent *event);
/**
* Dispatches the given event directly, bypassing the event stack.
* \return Indication as to whether any of the consumers handled the event.
*/
- virtual bool dispatchEvent(GHOST_IEvent *event);
+ bool dispatchEvent(GHOST_IEvent *event);
/**
* Dispatches the event at the back of the stack.
* The event will be removed from the stack.
* \return Indication as to whether any of the consumers handled the event.
*/
- virtual bool dispatchEvent();
+ bool dispatchEvent();
/**
* Dispatches all the events on the stack.
* The event stack will be empty afterwards.
* \return Indication as to whether any of the consumers handled the events.
*/
- virtual bool dispatchEvents();
+ bool dispatchEvents();
/**
* Adds a consumer to the list of event consumers.
* \param consumer The consumer added to the list.
* \return Indication as to whether addition has succeeded.
*/
- virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer);
/**
* Removes a consumer from the list of event consumers.
* \param consumer The consumer removed from the list.
* \return Indication as to whether removal has succeeded.
*/
- virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer);
/**
* Removes all events for a window from the stack.
* \param window The window to remove events for.
*/
- virtual void
+ void
removeWindowEvents(
GHOST_IWindow *window
);
@@ -138,7 +138,7 @@ public:
* \param type The type of events to be removed.
* \param window The window to remove the events for.
*/
- virtual void
+ void
removeTypeEvents(
GHOST_TEventType type,
GHOST_IWindow *window = NULL
@@ -150,12 +150,12 @@ protected:
* Delete the event after use!
* \return The event at the top of the stack.
*/
- virtual GHOST_IEvent *popEvent();
+ GHOST_IEvent *popEvent();
/**
* Removes all events from the stack.
*/
- virtual void disposeEvents();
+ void disposeEvents();
/** A stack with events. */
typedef std::deque<GHOST_IEvent *> TEventStack;
diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp
index 4b7be84ac81..f25f6637cb1 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.cpp
+++ b/intern/ghost/intern/GHOST_EventPrinter.cpp
@@ -179,6 +179,9 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event)
std::cout << "not found"; handled = false;
break;
}
+
+ std::cout.flush();
+
return handled;
}
diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h
index 280d4208413..0cbb7ca467d 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.h
+++ b/intern/ghost/intern/GHOST_EventPrinter.h
@@ -49,7 +49,7 @@ public:
* \param event The event that can be handled or not.
* \return Indication as to whether the event was handled.
*/
- virtual bool processEvent(GHOST_IEvent *event);
+ bool processEvent(GHOST_IEvent *event);
protected:
/**
diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h
index dc8b1649754..b4e80b5fd06 100644
--- a/intern/ghost/intern/GHOST_EventTrackpad.h
+++ b/intern/ghost/intern/GHOST_EventTrackpad.h
@@ -45,7 +45,7 @@ public:
/**
* Constructor.
* \param msec The time this event was generated.
- * \param type The type of this event.
+ * \param window: The window of this event.
* \param subtype The subtype of the event.
* \param x The x-delta of the pan event.
* \param y The y-delta of the pan event.
diff --git a/intern/ghost/intern/GHOST_EventWheel.h b/intern/ghost/intern/GHOST_EventWheel.h
index 216f13fda4e..a632492acb9 100644
--- a/intern/ghost/intern/GHOST_EventWheel.h
+++ b/intern/ghost/intern/GHOST_EventWheel.h
@@ -47,9 +47,9 @@ class GHOST_EventWheel : public GHOST_Event
public:
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of this event.
- * \param z The displacement of the mouse wheel.
+ * \param msec: The time this event was generated.
+ * \param window: The window of this event.
+ * \param z: The displacement of the mouse wheel.
*/
GHOST_EventWheel(GHOST_TUns64 msec, GHOST_IWindow *window, GHOST_TInt32 z)
: GHOST_Event(msec, GHOST_kEventWheel, window)
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
index 009753cb29e..d7dd2b1cde1 100644
--- a/intern/ghost/intern/GHOST_ISystem.cpp
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -38,21 +38,22 @@
#include "GHOST_ISystem.h"
-#ifdef WITH_HEADLESS
-# include "GHOST_SystemNULL.h"
-#elif defined(WITH_GHOST_SDL)
-# include "GHOST_SystemSDL.h"
-#elif defined(WIN32)
-# include "GHOST_SystemWin32.h"
+#ifdef WITH_X11
+# include "GHOST_SystemX11.h"
#else
-# ifdef __APPLE__
-# include "GHOST_SystemCocoa.h"
+# ifdef WITH_HEADLESS
+# include "GHOST_SystemNULL.h"
+# elif defined(WITH_GHOST_SDL)
+# include "GHOST_SystemSDL.h"
+# elif defined(WIN32)
+# include "GHOST_SystemWin32.h"
# else
-# include "GHOST_SystemX11.h"
+# ifdef __APPLE__
+# include "GHOST_SystemCocoa.h"
+# endif
# endif
#endif
-
GHOST_ISystem *GHOST_ISystem::m_system = 0;
@@ -60,19 +61,21 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
{
GHOST_TSuccess success;
if (!m_system) {
-#ifdef WITH_HEADLESS
+#ifdef WITH_X11
+ m_system = new GHOST_SystemX11();
+#else
+# ifdef WITH_HEADLESS
m_system = new GHOST_SystemNULL();
-#elif defined(WITH_GHOST_SDL)
+# elif defined(WITH_GHOST_SDL)
m_system = new GHOST_SystemSDL();
-#elif defined(WIN32)
+# elif defined(WIN32)
m_system = new GHOST_SystemWin32();
-#else
-# ifdef __APPLE__
- m_system = new GHOST_SystemCocoa();
# else
- m_system = new GHOST_SystemX11();
+# ifdef __APPLE__
+ m_system = new GHOST_SystemCocoa();
+# endif
# endif
-#endif
+#endif
success = m_system != 0 ? GHOST_kSuccess : GHOST_kFailure;
}
else {
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
new file mode 100644
index 00000000000..af5a2ed7097
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -0,0 +1,520 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (c) 2010 The Chromium Authors. All rights reserved.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/** \file ghost/intern/GHOST_ImeWin32.cpp
+ * \ingroup GHOST
+ */
+
+#ifdef WITH_INPUT_IME
+
+#include "GHOST_C-api.h"
+#include "GHOST_ImeWin32.h"
+#include "GHOST_WindowWin32.h"
+#include "utfconv.h"
+
+
+GHOST_ImeWin32::GHOST_ImeWin32()
+ : ime_status_(false),
+ input_language_id_(LANG_USER_DEFAULT),
+ is_composing_(false),
+ system_caret_(false),
+ caret_rect_(-1, -1, 0, 0),
+ is_first(true),
+ is_enable(true)
+{
+}
+
+
+GHOST_ImeWin32::~GHOST_ImeWin32()
+{
+}
+
+
+bool GHOST_ImeWin32::SetInputLanguage()
+{
+ /**
+ * Retrieve the current keyboard layout from Windows and determine whether
+ * or not the current input context has IMEs.
+ * Also save its input language for language-specific operations required
+ * while composing a text.
+ */
+ HKL keyboard_layout = ::GetKeyboardLayout(0);
+ input_language_id_ = reinterpret_cast<LANGID>(keyboard_layout);
+ ime_status_ = ::ImmIsIME(keyboard_layout);
+ return ime_status_;
+}
+
+
+void GHOST_ImeWin32::CreateImeWindow(HWND window_handle)
+{
+ /**
+ * When a user disables TSF (Text Service Framework) and CUAS (Cicero
+ * Unaware Application Support), Chinese IMEs somehow ignore function calls
+ * to ::ImmSetCandidateWindow(), i.e. they do not move their candidate
+ * window to the position given as its parameters, and use the position
+ * of the current system caret instead, i.e. it uses ::GetCaretPos() to
+ * retrieve the position of their IME candidate window.
+ * Therefore, we create a temporary system caret for Chinese IMEs and use
+ * it during this input context.
+ * Since some third-party Japanese IME also uses ::GetCaretPos() to determine
+ * their window position, we also create a caret for Japanese IMEs.
+ */
+ if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE ||
+ PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) {
+ if (!system_caret_) {
+ if (::CreateCaret(window_handle, NULL, 1, 1)) {
+ system_caret_ = true;
+ }
+ }
+ }
+ /* Restore the positions of the IME windows. */
+ UpdateImeWindow(window_handle);
+}
+
+
+void GHOST_ImeWin32::SetImeWindowStyle(HWND window_handle, UINT message, WPARAM wparam, LPARAM lparam, BOOL *handled)
+{
+ /**
+ * To prevent the IMM (Input Method Manager) from displaying the IME
+ * composition window, Update the styles of the IME windows and EXPLICITLY
+ * call ::DefWindowProc() here.
+ * NOTE(hbono): We can NEVER let WTL call ::DefWindowProc() when we update
+ * the styles of IME windows because the 'lparam' variable is a local one
+ * and all its updates disappear in returning from this function, i.e. WTL
+ * does not call ::DefWindowProc() with our updated 'lparam' value but call
+ * the function with its original value and over-writes our window styles.
+ */
+ *handled = TRUE;
+ lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
+ ::DefWindowProc(window_handle, message, wparam, lparam);
+}
+
+
+void GHOST_ImeWin32::DestroyImeWindow(HWND window_handle)
+{
+ /* Destroy the system caret if we have created for this IME input context. */
+ if (system_caret_) {
+ ::DestroyCaret();
+ system_caret_ = false;
+ }
+}
+
+
+void GHOST_ImeWin32::MoveImeWindow(HWND window_handle, HIMC imm_context)
+{
+ int x = caret_rect_.m_l;
+ int y = caret_rect_.m_t;
+ const int kCaretMargin = 1;
+ /**
+ * As written in a comment in GHOST_ImeWin32::CreateImeWindow(),
+ * Chinese IMEs ignore function calls to ::ImmSetCandidateWindow()
+ * when a user disables TSF (Text Service Framework) and CUAS (Cicero
+ * Unaware Application Support).
+ * On the other hand, when a user enables TSF and CUAS, Chinese IMEs
+ * ignore the position of the current system caret and uses the
+ * parameters given to ::ImmSetCandidateWindow() with its 'dwStyle'
+ * parameter CFS_CANDIDATEPOS.
+ * Therefore, we do not only call ::ImmSetCandidateWindow() but also
+ * set the positions of the temporary system caret if it exists.
+ */
+ CANDIDATEFORM candidate_position = { 0, CFS_CANDIDATEPOS, { x, y },
+ { 0, 0, 0, 0 } };
+ ::ImmSetCandidateWindow(imm_context, &candidate_position);
+ if (system_caret_) {
+ switch (PRIMARYLANGID(input_language_id_)) {
+ case LANG_JAPANESE:
+ ::SetCaretPos(x, y + caret_rect_.getHeight());
+ break;
+ default:
+ ::SetCaretPos(x, y);
+ break;
+ }
+ }
+ if (PRIMARYLANGID(input_language_id_) == LANG_KOREAN) {
+ /**
+ * Chinese IMEs and Japanese IMEs require the upper-left corner of
+ * the caret to move the position of their candidate windows.
+ * On the other hand, Korean IMEs require the lower-left corner of the
+ * caret to move their candidate windows.
+ */
+ y += kCaretMargin;
+ }
+ /**
+ * Japanese IMEs and Korean IMEs also use the rectangle given to
+ * ::ImmSetCandidateWindow() with its 'dwStyle' parameter CFS_EXCLUDE
+ * to move their candidate windows when a user disables TSF and CUAS.
+ * Therefore, we also set this parameter here.
+ */
+ CANDIDATEFORM exclude_rectangle = { 0, CFS_EXCLUDE, { x, y },
+ { x, y, x + caret_rect_.getWidth(), y + caret_rect_.getHeight() } };
+ ::ImmSetCandidateWindow(imm_context, &exclude_rectangle);
+}
+
+
+void GHOST_ImeWin32::UpdateImeWindow(HWND window_handle)
+{
+ /* Just move the IME window attached to the given window. */
+ if (caret_rect_.m_l >= 0 && caret_rect_.m_t >= 0) {
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ MoveImeWindow(window_handle, imm_context);
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ }
+}
+
+
+void GHOST_ImeWin32::CleanupComposition(HWND window_handle)
+{
+ /**
+ * Notify the IMM attached to the given window to complete the ongoing
+ * composition, (this case happens when the given window is de-activated
+ * while composing a text and re-activated), and reset the omposition status.
+ */
+ if (is_composing_) {
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ ResetComposition(window_handle);
+ }
+}
+
+
+void GHOST_ImeWin32::CheckFirst(HWND window_handle)
+{
+ if (is_first) {
+ this->EndIME(window_handle);
+ is_first = false;
+ }
+}
+
+
+void GHOST_ImeWin32::ResetComposition(HWND window_handle)
+{
+ /* Currently, just reset the composition status. */
+ is_composing_ = false;
+}
+
+
+void GHOST_ImeWin32::CompleteComposition(HWND window_handle, HIMC imm_context)
+{
+ /**
+ * We have to confirm there is an ongoing composition before completing it.
+ * This is for preventing some IMEs from getting confused while completing an
+ * ongoing composition even if they do not have any ongoing compositions.)
+ */
+ if (is_composing_) {
+ ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ ResetComposition(window_handle);
+ }
+}
+
+
+void GHOST_ImeWin32::GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *composition)
+{
+ /**
+ * This operation is optional and language-dependent because the caret
+ * style is depended on the language, e.g.:
+ * * Korean IMEs: the caret is a blinking block,
+ * (It contains only one hangul character);
+ * * Chinese IMEs: the caret is a blinking line,
+ * (i.e. they do not need to retrieve the target selection);
+ * * Japanese IMEs: the caret is a selection (or underlined) block,
+ * (which can contain one or more Japanese characters).
+ */
+ int target_start = -1;
+ int target_end = -1;
+ switch (PRIMARYLANGID(input_language_id_)) {
+ case LANG_KOREAN:
+ if (lparam & CS_NOMOVECARET) {
+ target_start = 0;
+ target_end = 1;
+ }
+ break;
+ case LANG_CHINESE:
+ {
+ int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, NULL, 0);
+ if (clause_size) {
+ static std::vector<unsigned long> clauses;
+ clause_size = clause_size / sizeof(clauses[0]);
+ clauses.resize(clause_size);
+ ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, &clauses[0],
+ sizeof(clauses[0]) *clause_size);
+ if (composition->cursor_position == composition->ime_string.size()) {
+ target_start = clauses[clause_size - 2];
+ target_end = clauses[clause_size - 1];
+ }
+ else {
+ for (int i = 0; i < clause_size - 1; i++) {
+ if (clauses[i] == composition->cursor_position) {
+ target_start = clauses[i];
+ target_end = clauses[i + 1];
+ break;
+ }
+ }
+ }
+ }
+ else {
+ if (composition->cursor_position != -1) {
+ target_start = composition->cursor_position;
+ target_end = composition->ime_string.size();
+ }
+ }
+ break;
+ }
+ case LANG_JAPANESE:
+
+ /**
+ * For Japanese IMEs, the robustest way to retrieve the caret
+ * is scanning the attribute of the latest composition string and
+ * retrieving the begining and the end of the target clause, i.e.
+ * a clause being converted.
+ */
+ if (lparam & GCS_COMPATTR) {
+ int attribute_size = ::ImmGetCompositionStringW(imm_context,
+ GCS_COMPATTR,
+ NULL, 0);
+ if (attribute_size > 0) {
+ char *attribute_data = new char[attribute_size];
+ if (attribute_data) {
+ ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR,
+ attribute_data, attribute_size);
+ for (target_start = 0; target_start < attribute_size;
+ ++target_start) {
+ if (IsTargetAttribute(attribute_data[target_start]))
+ break;
+ }
+ for (target_end = target_start; target_end < attribute_size;
+ ++target_end) {
+ if (!IsTargetAttribute(attribute_data[target_end]))
+ break;
+ }
+ if (target_start == attribute_size) {
+ /**
+ * This composition clause does not contain any target clauses,
+ * i.e. this clauses is an input clause.
+ * We treat whole this clause as a target clause.
+ */
+ target_end = target_start;
+ target_start = 0;
+ }
+ if (target_start != -1 && target_start < attribute_size &&
+ attribute_data[target_start] == ATTR_TARGET_NOTCONVERTED)
+ {
+ composition->cursor_position = target_start;
+ }
+ }
+ delete[] attribute_data;
+ }
+ }
+ break;
+ }
+ composition->target_start = target_start;
+ composition->target_end = target_end;
+}
+
+
+bool GHOST_ImeWin32::GetString(HIMC imm_context, WPARAM lparam, int type, ImeComposition *composition)
+{
+ bool result = false;
+ if (lparam & type) {
+ int string_size = ::ImmGetCompositionStringW(imm_context, type, NULL, 0);
+ if (string_size > 0) {
+ int string_length = string_size / sizeof(wchar_t);
+ wchar_t *string_data = new wchar_t[string_length + 1];
+ string_data[string_length] = '\0';
+ if (string_data) {
+ /* Fill the given ImeComposition object. */
+ ::ImmGetCompositionStringW(imm_context, type,
+ string_data, string_size);
+ composition->string_type = type;
+ composition->ime_string = string_data;
+ result = true;
+ }
+ delete[] string_data;
+ }
+ }
+ return result;
+}
+
+
+bool GHOST_ImeWin32::GetResult(HWND window_handle, LPARAM lparam, ImeComposition *composition)
+{
+ bool result = false;
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ /* Copy the result string to the ImeComposition object. */
+ result = GetString(imm_context, lparam, GCS_RESULTSTR, composition);
+ /**
+ * Reset all the other parameters because a result string does not
+ * have composition attributes.
+ */
+ composition->cursor_position = -1;
+ composition->target_start = -1;
+ composition->target_end = -1;
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ return result;
+}
+
+
+bool GHOST_ImeWin32::GetComposition(HWND window_handle, LPARAM lparam, ImeComposition *composition)
+{
+ bool result = false;
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ /* Copy the composition string to the ImeComposition object. */
+ result = GetString(imm_context, lparam, GCS_COMPSTR, composition);
+
+ /* Retrieve the cursor position in the IME composition. */
+ int cursor_position = ::ImmGetCompositionStringW(imm_context, GCS_CURSORPOS, NULL, 0);
+ composition->cursor_position = cursor_position;
+ composition->target_start = -1;
+ composition->target_end = -1;
+
+ /* Retrieve the target selection and Update the ImeComposition object. */
+ GetCaret(imm_context, lparam, composition);
+
+ /* Mark that there is an ongoing composition. */
+ is_composing_ = true;
+
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ return result;
+}
+
+
+void GHOST_ImeWin32::EndIME(HWND window_handle)
+{
+ /**
+ * A renderer process have moved its input focus to a password input
+ * when there is an ongoing composition, e.g. a user has clicked a
+ * mouse button and selected a password input while composing a text.
+ * For this case, we have to complete the ongoing composition and
+ * clean up the resources attached to this object BEFORE DISABLING THE IME.
+ */
+ if (!is_enable) return;
+ is_enable = false;
+ CleanupComposition(window_handle);
+ ::ImmAssociateContextEx(window_handle, NULL, 0);
+ eventImeData.composite_len = 0;
+}
+
+
+void GHOST_ImeWin32::BeginIME(HWND window_handle, const GHOST_Rect &caret_rect, bool complete)
+{
+ if (is_enable && complete) return;
+ is_enable = true;
+ /**
+ * Load the default IME context.
+ * NOTE(hbono)
+ * IMM ignores this call if the IME context is loaded. Therefore, we do
+ * not have to check whether or not the IME context is loaded.
+ */
+ ::ImmAssociateContextEx(window_handle, NULL, IACE_DEFAULT);
+ /* Complete the ongoing composition and move the IME windows. */
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ if (complete) {
+ /**
+ * A renderer process have moved its input focus to another edit
+ * control when there is an ongoing composition, e.g. a user has
+ * clicked a mouse button and selected another edit control while
+ * composing a text.
+ * For this case, we have to complete the ongoing composition and
+ * hide the IME windows BEFORE MOVING THEM.
+ */
+ CompleteComposition(window_handle, imm_context);
+ }
+ /**
+ * Save the caret position, and Update the position of the IME window.
+ * This update is used for moving an IME window when a renderer process
+ * resize/moves the input caret.
+ */
+ if (caret_rect.m_l >= 0 && caret_rect.m_t >= 0) {
+ caret_rect_ = caret_rect;
+ MoveImeWindow(window_handle, imm_context);
+ }
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+}
+
+
+static void convert_utf16_to_utf8_len(std::wstring s, int &len)
+{
+ if (len >= 0 && len <= s.size())
+ len = count_utf_8_from_16(s.substr(0, len).c_str()) - 1;
+ else
+ len = -1;
+}
+
+
+static size_t updateUtf8Buf(ImeComposition &info)
+{
+ size_t len = count_utf_8_from_16(info.ime_string.c_str());
+ info.utf8_buf.resize(len);
+ conv_utf_16_to_8(info.ime_string.c_str(), &info.utf8_buf[0], len);
+ convert_utf16_to_utf8_len(info.ime_string, info.cursor_position);
+ convert_utf16_to_utf8_len(info.ime_string, info.target_start);
+ convert_utf16_to_utf8_len(info.ime_string, info.target_end);
+ return len - 1;
+}
+
+
+void GHOST_ImeWin32::UpdateInfo(HWND window_handle)
+{
+ int res = this->GetResult(window_handle, GCS_RESULTSTR, &resultInfo);
+ int comp = this->GetComposition(window_handle, GCS_COMPSTR | GCS_COMPATTR, &compInfo);
+ /* convert wchar to utf8 */
+ if (res) {
+ eventImeData.result_len = (GHOST_TUserDataPtr)updateUtf8Buf(resultInfo);
+ eventImeData.result = &resultInfo.utf8_buf[0];
+ }
+ else {
+ eventImeData.result = 0;
+ eventImeData.result_len = 0;
+ }
+ if (comp) {
+ eventImeData.composite_len = (GHOST_TUserDataPtr)updateUtf8Buf(compInfo);
+ eventImeData.composite = &compInfo.utf8_buf[0];
+ eventImeData.cursor_position = compInfo.cursor_position;
+ eventImeData.target_start = compInfo.target_start;
+ eventImeData.target_end = compInfo.target_end;
+ }
+ else {
+ eventImeData.composite = 0;
+ eventImeData.composite_len = 0;
+ eventImeData.cursor_position = -1;
+ eventImeData.target_start = -1;
+ eventImeData.target_end = -1;
+ }
+}
+
+#endif // WITH_INPUT_IME
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
new file mode 100644
index 00000000000..bfd9a49d785
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -0,0 +1,405 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (c) 2010 The Chromium Authors. All rights reserved.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+/** \file ghost/intern/GHOST_ImeWin32.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_IME_H__
+#define __GHOST_IME_H__
+
+#ifdef WITH_INPUT_IME
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <string>
+
+#include "GHOST_Event.h"
+#include "GHOST_Rect.h"
+#include <vector>
+
+class GHOST_EventIME : public GHOST_Event
+{
+public:
+ /**
+ * Constructor.
+ * \param msec The time this event was generated.
+ * \param type The type of key event.
+ * \param key The key code of the key.
+ */
+ GHOST_EventIME(GHOST_TUns64 msec,
+ GHOST_TEventType type,
+ GHOST_IWindow *window, void *customdata)
+ : GHOST_Event(msec, type, window)
+ {
+ this->m_data = customdata;
+ }
+
+};
+
+
+/**
+ * This header file defines a struct and a class used for encapsulating IMM32
+ * APIs, controls IMEs attached to a window, and enables the 'on-the-spot'
+ * input without deep knowledge about the APIs, i.e. knowledge about the
+ * language-specific and IME-specific behaviors.
+ * The following items enumerates the simplest steps for an (window)
+ * application to control its IMEs with the struct and the class defined
+ * this file.
+ * 1. Add an instance of the GHOST_ImeWin32 class to its window class.
+ * (The GHOST_ImeWin32 class needs a window handle.)
+ * 2. Add messages handlers listed in the following subsections, follow the
+ * instructions written in each subsection, and use the GHOST_ImeWin32 class.
+ * 2.1. WM_IME_SETCONTEXT (0x0281)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::CreateImeWindow();
+ * - GHOST_ImeWin32::CleanupComposition(), and;
+ * - GHOST_ImeWin32::SetImeWindowStyle().
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.2. WM_IME_STARTCOMPOSITION (0x010D)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::CreateImeWindow(), and;
+ * - GHOST_ImeWin32::ResetComposition().
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.3. WM_IME_COMPOSITION (0x010F)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::UpdateImeWindow();
+ * - GHOST_ImeWin32::GetResult();
+ * - GHOST_ImeWin32::GetComposition(), and;
+ * - GHOST_ImeWin32::ResetComposition() (optional).
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.4. WM_IME_ENDCOMPOSITION (0x010E)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::ResetComposition(), and;
+ * - GHOST_ImeWin32::DestroyImeWindow().
+ * An application CAN call ::DefWindowProc().
+ * 2.5. WM_INPUTLANGCHANGE (0x0051)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::SetInputLanguage().
+ * An application CAN call ::DefWindowProc().
+ */
+
+/* This struct represents the status of an ongoing composition. */
+struct ImeComposition {
+ /* Represents the cursor position in the IME composition. */
+ int cursor_position;
+
+ /* Represents the position of the beginning of the selection */
+ int target_start;
+
+ /* Represents the position of the end of the selection */
+ int target_end;
+
+ /**
+ * Represents the type of the string in the 'ime_string' parameter.
+ * Its possible values and description are listed below:
+ * Value Description
+ * 0 The parameter is not used.
+ * GCS_RESULTSTR The parameter represents a result string.
+ * GCS_COMPSTR The parameter represents a composition string.
+ */
+ int string_type;
+
+ /* Represents the string retrieved from IME (Input Method Editor) */
+ std::wstring ime_string;
+ std::vector<char> utf8_buf;
+ std::vector<unsigned char> format;
+};
+
+/**
+ * This class controls the IMM (Input Method Manager) through IMM32 APIs and
+ * enables it to retrieve the string being controled by the IMM. (I wrote
+ * a note to describe the reason why I do not use 'IME' but 'IMM' below.)
+ * NOTE(hbono):
+ * Fortunately or unfortunately, TSF (Text Service Framework) and
+ * CUAS (Cicero Unaware Application Support) allows IMM32 APIs for
+ * retrieving not only the inputs from IMEs (Input Method Editors), used
+ * only for inputting East-Asian language texts, but also the ones from
+ * tablets (on Windows XP Tablet PC Edition and Windows Vista), voice
+ * recognizers (e.g. ViaVoice and Microsoft Office), etc.
+ * We can disable TSF and CUAS in Windows XP Tablet PC Edition. On the other
+ * hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e.
+ * THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN
+ * LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES.
+ */
+class GHOST_ImeWin32 {
+public:
+ GHOST_ImeWin32();
+ ~GHOST_ImeWin32();
+
+ /* Retrieves whether or not there is an ongoing composition. */
+ bool is_composing() const {return is_composing_;}
+
+ /**
+ * Retrieves the input language from Windows and update it.
+ * Return values
+ * * true
+ * The given input language has IMEs.
+ * * false
+ * The given input language does not have IMEs.
+ */
+ bool SetInputLanguage();
+
+ /**
+ * Create the IME windows, and allocate required resources for them.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void CreateImeWindow(HWND window_handle);
+
+ /**
+ * Update the style of the IME windows.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * message [in] (UINT)
+ * * wparam [in] (WPARAM)
+ * * lparam [in] (LPARAM)
+ * Represent the windows message of the caller.
+ * These parameters are used for verifying if this function is called
+ * in a handler function for WM_IME_SETCONTEXT messages because this
+ * function uses ::DefWindowProc() to update the style.
+ * A caller just has to pass the input parameters for the handler
+ * function without modifications.
+ * * handled [out] (BOOL*)
+ * Returns ::DefWindowProc() is really called in this function.
+ * PLEASE DO NOT CALL ::DefWindowProc() IF THIS VALUE IS TRUE!
+ * All the window styles set in this function are over-written when
+ * calling ::DefWindowProc() after returning this function.
+ */
+ void SetImeWindowStyle(HWND window_handle, UINT message,
+ WPARAM wparam, LPARAM lparam, BOOL* handled);
+
+ /**
+ * Destroy the IME windows and all the resources attached to them.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void DestroyImeWindow(HWND window_handle);
+
+ /**
+ * Update the position of the IME windows.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void UpdateImeWindow(HWND window_handle);
+
+ /**
+ * Clean up the all resources attached to the given GHOST_ImeWin32 object, and
+ * reset its composition status.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void CleanupComposition(HWND window_handle);
+
+ /**
+ * Reset the composition status.
+ * Cancel the ongoing composition if it exists.
+ * NOTE(hbono): This method does not release the allocated resources.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void ResetComposition(HWND window_handle);
+
+ /**
+ * Retrieve a composition result of the ongoing composition if it exists.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * lparam [in] (LPARAM)
+ * Specifies the updated members of the ongoing composition, and must be
+ * the same parameter of a WM_IME_COMPOSITION message handler.
+ * This parameter is used for checking if the ongoing composition has
+ * its result string,
+ * * composition [out] (ImeComposition)
+ * Represents the struct contains the composition result.
+ * Return values
+ * * true
+ * The ongoing composition has a composition result.
+ * * false
+ * The ongoing composition does not have composition results.
+ * Remarks
+ * This function is designed for being called from WM_IME_COMPOSITION
+ * message handlers.
+ */
+ bool GetResult(HWND window_handle, LPARAM lparam,
+ ImeComposition* composition);
+
+ /**
+ * Retrieve the current composition status of the ongoing composition.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * lparam [in] (LPARAM)
+ * Specifies the updated members of the ongoing composition, and must be
+ * the same parameter of a WM_IME_COMPOSITION message handler.
+ * This parameter is used for checking if the ongoing composition has
+ * its result string,
+ * * composition [out] (ImeComposition)
+ * Represents the struct contains the composition status.
+ * Return values
+ * * true
+ * The status of the ongoing composition is updated.
+ * * false
+ * The status of the ongoing composition is not updated.
+ * Remarks
+ * This function is designed for being called from WM_IME_COMPOSITION
+ * message handlers.
+ */
+ bool GetComposition(HWND window_handle, LPARAM lparam,
+ ImeComposition* composition);
+
+ /**
+ * Enable the IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * In Chrome, this function is used when:
+ * * a renderer process moves its input focus to another edit control, or;
+ * * a renrerer process moves the position of the focused edit control.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * caret_rect [in] (const gfx::Rect&)
+ * Represent the rectangle of the input caret.
+ * This rectangle is used for controlling the positions of IME windows.
+ * * complete [in] (bool)
+ * Represents whether or not to complete the ongoing composition.
+ * + true
+ * After finishing the ongoing composition and close its IME windows,
+ * start another composition and display its IME windows to the given
+ * position.
+ * + false
+ * Just move the IME windows of the ongoing composition to the given
+ * position without finishing it.
+ */
+ void BeginIME(HWND window_handle,
+ const GHOST_Rect& caret_rect,
+ bool complete);
+
+ /**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ * In Chrome, this function is used when:
+ * * a renreder process sets its input focus to a password input.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void EndIME(HWND window_handle);
+
+ /* Updatg resultInfo and compInfo */
+ void UpdateInfo(HWND window_handle);
+
+ /* disable ime when start up */
+ void CheckFirst(HWND window_handle);
+
+ ImeComposition resultInfo, compInfo;
+ GHOST_TEventImeData eventImeData;
+
+protected:
+ /* Determines whether or not the given attribute represents a target (a.k.a. a selection). */
+ bool IsTargetAttribute(char attribute) const {
+ return (attribute == ATTR_TARGET_CONVERTED ||
+ attribute == ATTR_TARGET_NOTCONVERTED);
+ }
+
+ /* Retrieve the target area. */
+ void GetCaret(HIMC imm_context, LPARAM lparam,
+ ImeComposition* composition);
+
+ /* Update the position of the IME windows. */
+ void MoveImeWindow(HWND window_handle, HIMC imm_context);
+
+ /* Complete the ongoing composition if it exists. */
+ void CompleteComposition(HWND window_handle, HIMC imm_context);
+
+ /* Retrieve a string from the IMM. */
+ bool GetString(HIMC imm_context, WPARAM lparam, int type,
+ ImeComposition* composition);
+
+private:
+ /**
+ * Represents whether or not there is an ongoing composition in a browser
+ * process, i.e. whether or not a browser process is composing a text.
+ */
+ bool is_composing_;
+
+ /**
+ * This value represents whether or not the current input context has IMEs.
+ * The following table shows the list of IME status:
+ * Value Description
+ * false The current input language does not have IMEs.
+ * true The current input language has IMEs.
+ */
+ bool ime_status_;
+
+ /**
+ * The current input Language ID retrieved from Windows, which consists of:
+ * * Primary Language ID (bit 0 to bit 9), which shows a natunal language
+ * (English, Korean, Chinese, Japanese, etc.) and;
+ * * Sub-Language ID (bit 10 to bit 15), which shows a geometrical region
+ * the language is spoken (For English, United States, United Kingdom,
+ * Australia, Canada, etc.)
+ * The following list enumerates some examples for the Language ID:
+ * * "en-US" (0x0409)
+ * MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
+ * * "ko-KR" (0x0412)
+ * MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
+ * * "zh-TW" (0x0404)
+ * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
+ * * "zh-CN" (0x0804)
+ * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
+ * * "ja-JP" (0x0411)
+ * MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), etc.
+ * (See <winnt.h> for other available values.)
+ * This Language ID is used for processing language-specific operations in
+ * IME functions.
+ */
+ LANGID input_language_id_;
+
+ /**
+ * Represents whether or not the current input context has created a system
+ * caret to set the position of its IME candidate window.
+ * * true: it creates a system caret.
+ * * false: it does not create a system caret.
+ */
+ bool system_caret_;
+
+ /* The rectangle of the input caret retrieved from a renderer process. */
+ GHOST_Rect caret_rect_;
+
+ /* used for disable ime when start up */
+ bool is_first, is_enable;
+};
+
+#endif // WITH_INPUT_IME
+#endif // __GHOST_IME_H__
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h
index 8189006f602..a30b66c4634 100644
--- a/intern/ghost/intern/GHOST_ModifierKeys.h
+++ b/intern/ghost/intern/GHOST_ModifierKeys.h
@@ -47,7 +47,7 @@ struct GHOST_ModifierKeys {
*/
GHOST_ModifierKeys();
- virtual ~GHOST_ModifierKeys();
+ ~GHOST_ModifierKeys();
/**
* Returns the modifier key's key code from a modifier key mask.
@@ -59,29 +59,29 @@ struct GHOST_ModifierKeys {
/**
* Returns the state of a single modifier key.
- * \param mask. Key state to return.
+ * \param mask: Key state to return.
* \return The state of the key (pressed == true).
*/
- virtual bool get(GHOST_TModifierKeyMask mask) const;
+ bool get(GHOST_TModifierKeyMask mask) const;
/**
* Updates the state of a single modifier key.
- * \param mask. Key state to update.
- * \param down. The new state of the key.
+ * \param mask: Key state to update.
+ * \param down: The new state of the key.
*/
- virtual void set(GHOST_TModifierKeyMask mask, bool down);
+ void set(GHOST_TModifierKeyMask mask, bool down);
/**
* Sets the state of all modifier keys to up.
*/
- virtual void clear();
+ void clear();
/**
* Determines whether to modifier key states are equal.
- * \param keys. The modifier key state to compare to.
+ * \param keys: The modifier key state to compare to.
* \return Indication of equality.
*/
- virtual bool equals(const GHOST_ModifierKeys& keys) const;
+ bool equals(const GHOST_ModifierKeys& keys) const;
/** Bitfield that stores the appropriate key state. */
GHOST_TUns8 m_LeftShift : 1;
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index 9bd6226d5c2..27285e49e9e 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -146,8 +146,8 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
NDOF_BUTTON_ROTATE
};
-/* this is the older SpacePilot (sans Pro)
- * thanks to polosson for info about this device */
+// this is the older SpacePilot (sans Pro)
+// thanks to polosson for info about this device
static const NDOF_ButtonT SpacePilot_HID_map[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
@@ -190,17 +190,17 @@ static const NDOF_ButtonT Generic_HID_map[] = {
static const int genericButtonCount = sizeof(Generic_HID_map) / sizeof(NDOF_ButtonT);
GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys)
- : m_system(sys),
- m_deviceType(NDOF_UnknownDevice), /* each platform has its own device detection code */
- m_buttonCount(genericButtonCount),
- m_buttonMask(0),
- m_hidMap(Generic_HID_map),
- m_buttons(0),
- m_motionTime(0),
- m_prevMotionTime(0),
- m_motionState(GHOST_kNotStarted),
- m_motionEventPending(false),
- m_deadZone(0.0f)
+ : m_system(sys),
+ m_deviceType(NDOF_UnknownDevice), // each platform has its own device detection code
+ m_buttonCount(genericButtonCount),
+ m_buttonMask(0),
+ m_hidMap(Generic_HID_map),
+ m_buttons(0),
+ m_motionTime(0),
+ m_prevMotionTime(0),
+ m_motionState(GHOST_kNotStarted),
+ m_motionEventPending(false),
+ m_deadZone(0.0f)
{
// to avoid the rare situation where one triple is updated and
// the other is not, initialize them both here:
@@ -228,7 +228,7 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
// that I don't have access to. Thanks!
switch (vendor_id) {
- case 0x046D: // Logitech (3Dconnexion)
+ case 0x046D: // Logitech (3Dconnexion was a subsidiary)
switch (product_id) {
// -- current devices --
case 0xC626: // full-size SpaceNavigator
@@ -281,6 +281,29 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
printf("ndof: unknown Logitech product %04hx\n", product_id);
}
break;
+ case 0x256F: // 3Dconnexion
+ switch (product_id) {
+ case 0xC62E: // plugged in
+ case 0xC62F: // wireless
+ puts("ndof: using SpaceMouse Wireless");
+ m_deviceType = NDOF_SpaceMouseWireless;
+ m_buttonCount = 2;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
+ case 0xC631: // plugged in
+ case 0xC632: // wireless
+ puts("ndof: using SpaceMouse Pro Wireless");
+ m_deviceType = NDOF_SpaceMouseProWireless;
+ m_buttonCount = 27;
+ // ^^ actually has 15 buttons, but their HID codes range from 0 to 26
+ m_buttonMask = 0x07C0F137;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
+
+ default:
+ printf("ndof: unknown 3Dconnexion product %04hx\n", product_id);
+ }
+ break;
default:
printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id);
}
@@ -390,9 +413,9 @@ void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time)
void GHOST_NDOFManager::setDeadZone(float dz)
{
- if (dz < 0.f) {
+ if (dz < 0.0f) {
// negative values don't make sense, so clamp at zero
- dz = 0.f;
+ dz = 0.0f;
}
else if (dz > 0.5f) {
// warn the rogue user/developer, but allow it
@@ -405,14 +428,14 @@ void GHOST_NDOFManager::setDeadZone(float dz)
static bool atHomePosition(GHOST_TEventNDOFMotionData *ndof)
{
-#define HOME(foo) (ndof->foo == 0.f)
+#define HOME(foo) (ndof->foo == 0.0f)
return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz);
#undef HOME
}
static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold)
{
- if (threshold == 0.f) {
+ if (threshold == 0.0f) {
return atHomePosition(ndof);
}
else {
@@ -442,7 +465,7 @@ bool GHOST_NDOFManager::sendMotionEvent()
// scale axis values here to normalize them to around +/- 1
// they are scaled again for overall sensitivity in the WM based on user prefs
- const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually
+ const float scale = 1.0f / 350.0f; // 3Dconnexion devices send +/- 350 usually
data->tx = scale * m_translation[0];
data->ty = scale * m_translation[1];
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index 0b2080e36a9..48a4881afb1 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -20,7 +20,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-
+
#ifndef __GHOST_NDOFMANAGER_H__
#define __GHOST_NDOFMANAGER_H__
@@ -38,6 +38,8 @@ typedef enum {
NDOF_SpaceExplorer,
NDOF_SpacePilotPro,
NDOF_SpaceMousePro,
+ NDOF_SpaceMouseWireless,
+ NDOF_SpaceMouseProWireless,
// older devices
NDOF_SpacePilot,
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
index 6c1627905e0..7ccd2e602b4 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
@@ -30,7 +30,7 @@
GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys)
: GHOST_NDOFManager(sys)
{
- setDeadZone(0.1f);
+ /* pass */
}
// whether multi-axis functionality is available (via the OS or driver)
diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
index 8e6f9994e51..753321be58e 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
@@ -33,8 +33,6 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
: GHOST_NDOFManager(sys),
m_available(false)
{
- setDeadZone(0.1f); /* how to calibrate on Linux? throw away slight motion! */
-
if (spnav_open() != -1) {
m_available = true;
@@ -42,8 +40,8 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
#define MAX_LINE_LENGTH 100
- /* look for USB devices with Logitech's vendor ID */
- FILE *command_output = popen("lsusb -d 046d:", "r");
+ /* look for USB devices with Logitech or 3Dconnexion's vendor ID */
+ FILE *command_output = popen("lsusb | grep '046d:\\|256f:'", "r");
if (command_output) {
char line[MAX_LINE_LENGTH] = {0};
while (fgets(line, MAX_LINE_LENGTH, command_output)) {
@@ -58,7 +56,7 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
}
else {
#ifdef DEBUG
- /* annoying for official builds, just adds noise and most prople don't own these */
+ /* annoying for official builds, just adds noise and most people don't own these */
puts("ndof: spacenavd not found");
/* This isn't a hard error, just means the user doesn't have a 3D mouse. */
#endif
@@ -81,11 +79,11 @@ bool GHOST_NDOFManagerX11::available()
* this causes any proceeding event to have a very high 'dt' (time delta),
* many seconds for eg, causing the view to jump.
*
- * this workaround expect's continuous events, if we miss a motion event,
+ * this workaround expects continuous events, if we miss a motion event,
* immediately send a dummy event with no motion to ensure the finished state is reached.
*/
#define USE_FINISH_GLITCH_WORKAROUND
-
+/* TODO: make this available on all platforms */
#ifdef USE_FINISH_GLITCH_WORKAROUND
static bool motion_test_prev = false;
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index d1f2d5d87c8..1698d2f0f31 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -169,7 +169,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
}
-GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window)
+GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow ** /*window*/)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(m_windowManager, "GHOST_System::updateFullScreen(): invalid window manager");
@@ -295,6 +295,15 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown
return success;
}
+void GHOST_System::setNDOFDeadZone(float deadzone)
+{
+#ifdef WITH_INPUT_NDOF
+ this->m_ndofManager->setDeadZone(deadzone);
+#else
+ (void)deadzone;
+#endif
+}
+
GHOST_TSuccess GHOST_System::init()
{
m_timerManager = new GHOST_TimerManager();
@@ -350,6 +359,12 @@ GHOST_TSuccess GHOST_System::exit()
GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
{
+ GHOST_GLSettings glSettings = {0};
+
+ if (stereoVisual)
+ glSettings.flags |= GHOST_glStereoVisual;
+ glSettings.numOfAASamples = numOfAASamples;
+
/* note: don't use getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger then the viewport. */
GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager");
@@ -359,14 +374,13 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const
0, 0, settings.xPixels, settings.yPixels,
GHOST_kWindowStateNormal,
GHOST_kDrawingContextTypeOpenGL,
- stereoVisual,
- true, /* exclusive */
- numOfAASamples);
+ glSettings,
+ true /* exclusive */);
return (*window == NULL) ? GHOST_kFailure : GHOST_kSuccess;
}
-int GHOST_System::confirmQuit(GHOST_IWindow *window) const
+int GHOST_System::confirmQuit(GHOST_IWindow * /*window*/) const
{
return 1;
}
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index 79230b0f505..9dcba11527c 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -97,7 +97,7 @@ public:
* \param userData Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
- virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
+ GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
GHOST_TUns64 interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData = NULL);
@@ -107,7 +107,7 @@ public:
* \param timerTask Timer task to be removed.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask);
+ GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask);
/***************************************************************************************
* Display/window management functionality
@@ -126,14 +126,14 @@ public:
* \param window Pointer to the window to be disposed.
* \return Indication of success.
*/
- virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window);
+ GHOST_TSuccess disposeWindow(GHOST_IWindow *window);
/**
* Returns whether a window is valid.
* \param window Pointer to the window to be checked.
* \return Indication of validity.
*/
- virtual bool validWindow(GHOST_IWindow *window);
+ bool validWindow(GHOST_IWindow *window);
/**
* Begins full screen mode.
@@ -143,7 +143,7 @@ public:
* This window is invalid after full screen has been ended.
* \return Indication of success.
*/
- virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
+ GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
/**
@@ -153,26 +153,26 @@ public:
*
* \return Indication of success.
*/
- virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window);
+ GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window);
/**
* Ends full screen mode.
* \return Indication of success.
*/
- virtual GHOST_TSuccess endFullScreen(void);
+ GHOST_TSuccess endFullScreen(void);
/**
* Returns current full screen mode status.
* \return The current status.
*/
- virtual bool getFullScreen(void);
+ bool getFullScreen(void);
/**
* Native pixel size support (MacBook 'retina').
* \return The pixel size in float.
*/
- virtual bool useNativePixel(void);
+ bool useNativePixel(void);
bool m_nativePixel;
/***************************************************************************************
@@ -192,21 +192,21 @@ public:
* The event stack will be empty afterwards.
* \return Indication as to whether any of the consumers handled the events.
*/
- virtual bool dispatchEvents();
+ bool dispatchEvents();
/**
* Adds the given event consumer to our list.
* \param consumer The event consumer to add.
* \return Indication of success.
*/
- virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer);
/**
* Remove the given event consumer to our list.
* \param consumer The event consumer to remove.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer);
/***************************************************************************************
* Cursor management functionality
@@ -227,7 +227,7 @@ public:
* \param isDown The state of a modifier key (true == pressed).
* \return Indication of success.
*/
- virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const;
+ GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const;
/**
* Returns the state of a mouse button (ouside the message queue).
@@ -235,9 +235,19 @@ public:
* \param isDown Button state.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const;
+ GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const;
/***************************************************************************************
+ * Access to 3D mouse.
+ ***************************************************************************************/
+
+ /**
+ * Sets 3D mouse deadzone
+ * \param deadzone: Deadzone of the 3D mouse (both for rotation and pan) relative to full range
+ */
+ void setNDOFDeadZone(float deadzone);
+
+ /***************************************************************************************
* Other (internal) functionality.
***************************************************************************************/
@@ -247,28 +257,28 @@ public:
* Do not delete the event!
* \param event The event to push on the stack.
*/
- virtual GHOST_TSuccess pushEvent(GHOST_IEvent *event);
+ GHOST_TSuccess pushEvent(GHOST_IEvent *event);
/**
* \return The timer manager.
*/
- inline virtual GHOST_TimerManager *getTimerManager() const;
+ inline GHOST_TimerManager *getTimerManager() const;
/**
* \return A pointer to our event manager.
*/
- virtual inline GHOST_EventManager *getEventManager() const;
+ inline GHOST_EventManager *getEventManager() const;
/**
* \return A pointer to our window manager.
*/
- virtual inline GHOST_WindowManager *getWindowManager() const;
+ inline GHOST_WindowManager *getWindowManager() const;
#ifdef WITH_INPUT_NDOF
/**
* \return A pointer to our n-degree of freedom manager.
*/
- virtual inline GHOST_NDOFManager *getNDOFManager() const;
+ inline GHOST_NDOFManager *getNDOFManager() const;
#endif
/**
@@ -326,7 +336,7 @@ protected:
* \param window The window created.
* \return Indication of success.
*/
- virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
+ GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
/** The display manager (platform dependent). */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 9b30abe75d5..3d6b40ee541 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -71,7 +71,7 @@ public:
* Based on ANSI clock() routine.
* \return The number of milliseconds.
*/
- virtual GHOST_TUns64 getMilliSeconds() const;
+ GHOST_TUns64 getMilliSeconds() const;
/***************************************************************************************
* Display/window management functionality
@@ -81,18 +81,18 @@ public:
* Returns the number of displays on this system.
* \return The number of displays.
*/
- virtual GHOST_TUns8 getNumDisplays() const;
+ GHOST_TUns8 getNumDisplays() const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/** Returns the combine dimensions of all monitors.
* \return The dimension of the workspace.
*/
- virtual void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/**
* Create a new window.
@@ -105,12 +105,12 @@ public:
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL settings.
+ * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
- virtual GHOST_IWindow *createWindow(
+ GHOST_IWindow *createWindow(
const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -118,9 +118,8 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual = false,
- const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
+ GHOST_GLSettings glSettings,
+ const bool exclusive = false,
const GHOST_TEmbedderWindowID parentWindow = 0
);
@@ -133,7 +132,7 @@ public:
* \param waitForEvent Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
- virtual bool processEvents(bool waitForEvent);
+ bool processEvents(bool waitForEvent);
/**
* Handle User request to quit, from Menu bar Quit, and Cmd+Q
@@ -169,7 +168,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
+ GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -177,7 +176,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
/***************************************************************************************
* Access to mouse button and keyboard states.
@@ -188,28 +187,28 @@ public:
* \param keys The state of all modifier keys (true == pressed).
* \return Indication of success.
*/
- virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
+ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
/**
* Returns the state of the mouse buttons (ouside the message queue).
* \param buttons The state of the buttons.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
+ GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
/**
* Returns Clipboard data
* \param selection Indicate which buffer to return
* \return Returns the selected buffer
*/
- virtual GHOST_TUns8 *getClipboard(bool selection) const;
+ GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* \param buffer The buffer to be copied
* \param selection Indicates which buffer to copy too, only used on X11
*/
- virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Handles a window event. Called by GHOST_WindowCocoa window delegate
@@ -268,7 +267,7 @@ protected:
* For now, it just registers the window class (WNDCLASS).
* \return A success value.
*/
- virtual GHOST_TSuccess init();
+ GHOST_TSuccess init();
/**
* Performs the actual cursor position update (location in screen coordinates).
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 7b08c46b65d..b9686e5af9b 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -22,6 +22,7 @@
*
* Contributors: Maarten Gribnau 05/2001
* Damien Plisson 09/2009
+ * Jens Verwiebe 10/2014
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -56,6 +57,7 @@
#include "AssertMacros.h"
+
#pragma mark KeyMap, mouse converters
static GHOST_TButtonMask convertButton(int button)
@@ -71,6 +73,10 @@ static GHOST_TButtonMask convertButton(int button)
return GHOST_kButtonMaskButton4;
case 4:
return GHOST_kButtonMaskButton5;
+ case 5:
+ return GHOST_kButtonMaskButton6;
+ case 6:
+ return GHOST_kButtonMaskButton7;
default:
return GHOST_kButtonMaskLeft;
}
@@ -203,6 +209,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return GHOST_kKeyUnknown;
default:
+ {
/* alphanumerical or punctuation key that is remappable in int'l keyboards */
if ((recvChar >= 'A') && (recvChar <= 'Z')) {
return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
@@ -211,27 +218,25 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
}
else {
-
- /* Leopard and Snow Leopard 64bit compatible API*/
- CFDataRef uchrHandle; /*the keyboard layout*/
- TISInputSourceRef kbdTISHandle;
-
- kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
- uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
- CFRelease(kbdTISHandle);
-
- /*get actual character value of the "remappable" keys in int'l keyboards,
- if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
- then fallback on using the received charactersIgnoringModifiers */
- if (uchrHandle)
- {
- UInt32 deadKeyState=0;
- UniCharCount actualStrLength=0;
+ /* Leopard and Snow Leopard 64bit compatible API*/
+ CFDataRef uchrHandle; /*the keyboard layout*/
+ TISInputSourceRef kbdTISHandle;
- UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
- LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
+ kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
+ uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
+ CFRelease(kbdTISHandle);
- }
+ /*get actual character value of the "remappable" keys in int'l keyboards,
+ if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
+ then fallback on using the received charactersIgnoringModifiers */
+ if (uchrHandle) {
+ UInt32 deadKeyState=0;
+ UniCharCount actualStrLength=0;
+
+ UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
+ LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
+
+ }
switch (recvChar) {
case '-': return GHOST_kKeyMinus;
@@ -249,13 +254,11 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return GHOST_kKeyUnknown;
}
}
+ }
}
return GHOST_kKeyUnknown;
}
-
-#pragma mark defines for 10.6 api not documented in 10.5
-
#pragma mark Utility functions
#define FIRSTFILEBUFLG 512
@@ -271,7 +274,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
return 1;
}
else {
- return 0;
+ return 0;
}
}
@@ -334,12 +337,8 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
@end
-
-
#pragma mark initialization/finalization
-char GHOST_user_locale[128]; // Global current user locale
-
GHOST_SystemCocoa::GHOST_SystemCocoa()
{
int mib[2];
@@ -377,15 +376,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
rstring = NULL;
m_ignoreWindowSizedMessages = false;
-
- //Get current locale
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- CFLocaleRef myCFLocale = CFLocaleCopyCurrent();
- NSLocale * myNSLocale = (NSLocale *) myCFLocale;
- [myNSLocale autorelease];
- NSString *nsIdentifier = [myNSLocale localeIdentifier];
- strncpy(GHOST_user_locale, [nsIdentifier UTF8String], sizeof(GHOST_user_locale) - 1);
- [pool drain];
}
GHOST_SystemCocoa::~GHOST_SystemCocoa()
@@ -544,9 +534,8 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow
)
{
@@ -565,27 +554,23 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
// Add contentRect.origin.y to respect docksize
bottom = bottom > contentRect.origin.y ? bottom + contentRect.origin.y : contentRect.origin.y;
- window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, stereoVisual, numOfAASamples);
+ window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, ((glSettings.flags & GHOST_glStereoVisual) != 0), glSettings.numOfAASamples);
- if (window) {
- if (window->getValid()) {
- // Store the pointer to the window
- GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
- m_windowManager->addWindow(window);
- m_windowManager->setActiveWindow(window);
- //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
- }
- else {
- GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
- delete window;
- window = 0;
- }
+ if (window->getValid()) {
+ // Store the pointer to the window
+ GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
+ m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
+ //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
}
else {
- GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
+ GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
+ delete window;
+ window = 0;
}
+
[pool drain];
return window;
}
@@ -672,7 +657,6 @@ GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
}
-
#pragma mark Event handlers
/**
@@ -740,7 +724,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
// For some reason NSApp is swallowing the key up events when modifier
// key is pressed, even if there seems to be no apparent reason to do
// so, as a workaround we always handle these up events.
- if ([event type] == NSKeyUp && (([event modifierFlags] & NSCommandKeyMask) || ([event modifierFlags] & NSAlternateKeyMask)))
+ if ([event type] == NSKeyUp && ([event modifierFlags] & (NSCommandKeyMask | NSAlternateKeyMask)))
handleKeyEvent(event);
[NSApp sendEvent:event];
@@ -812,58 +796,57 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
if (!validWindow(window)) {
return GHOST_kFailure;
}
- switch (eventType) {
- case GHOST_kEventWindowClose:
- // check for index of mainwindow as it would quit blender without dialog and discard
- if ([windowsList count] > 1 && window->getCocoaWindow() != [windowsList objectAtIndex:[windowsList count] - 1]) {
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
- }
- else {
- handleQuitRequest(); // -> quit dialog
- }
- break;
- case GHOST_kEventWindowActivate:
- m_windowManager->setActiveWindow(window);
- window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
- break;
- case GHOST_kEventWindowDeactivate:
- m_windowManager->setWindowInactive(window);
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
- break;
- case GHOST_kEventWindowUpdate:
- if (m_nativePixel) {
- window->setNativePixelSize();
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
- }
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
- break;
- case GHOST_kEventWindowMove:
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) );
- break;
- case GHOST_kEventWindowSize:
- if (!m_ignoreWindowSizedMessages)
- {
- //Enforce only one resize message per event loop (coalescing all the live resize messages)
- window->updateDrawingContext();
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
- //Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager
- pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, convertButton(0)));
- //m_ignoreWindowSizedMessages = true;
- }
- break;
- case GHOST_kEventNativeResolutionChange:
-
- if (m_nativePixel) {
- window->setNativePixelSize();
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
- }
+ switch (eventType) {
+ case GHOST_kEventWindowClose:
+ // check for index of mainwindow as it would quit blender without dialog and discard
+ if ([windowsList count] > 1 && window->getCocoaWindow() != [windowsList objectAtIndex:[windowsList count] - 1]) {
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
+ }
+ else {
+ handleQuitRequest(); // -> quit dialog
+ }
+ break;
+ case GHOST_kEventWindowActivate:
+ m_windowManager->setActiveWindow(window);
+ window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
+ break;
+ case GHOST_kEventWindowDeactivate:
+ m_windowManager->setWindowInactive(window);
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
+ break;
+ case GHOST_kEventWindowUpdate:
+ if (m_nativePixel) {
+ window->setNativePixelSize();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
+ }
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
+ break;
+ case GHOST_kEventWindowMove:
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) );
+ break;
+ case GHOST_kEventWindowSize:
+ if (!m_ignoreWindowSizedMessages) {
+ //Enforce only one resize message per event loop (coalescing all the live resize messages)
+ window->updateDrawingContext();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+ //Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager
+ pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, convertButton(0)));
+ //m_ignoreWindowSizedMessages = true;
+ }
+ break;
+ case GHOST_kEventNativeResolutionChange:
+
+ if (m_nativePixel) {
+ window->setNativePixelSize();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
+ }
+
+ default:
+ return GHOST_kFailure;
+ break;
+ }
- default:
- return GHOST_kFailure;
- break;
- }
-
m_outsideLoopEventProcessed = true;
return GHOST_kSuccess;
}
@@ -902,7 +885,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
if (!strArray) return GHOST_kFailure;
strArray->count = [droppedArray count];
- if (strArray->count == 0) return GHOST_kFailure;
+ if (strArray->count == 0) {
+ free(strArray);
+ return GHOST_kFailure;
+ }
strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*));
@@ -1059,16 +1045,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
}
eventData = (GHOST_TEventDataPtr) ibuf;
- }
+
break;
-
+ }
default:
return GHOST_kFailure;
break;
}
pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,eventData));
- }
+
break;
+ }
default:
return GHOST_kFailure;
}
@@ -1251,12 +1238,12 @@ bool GHOST_SystemCocoa::handleTabletEvent(void *eventPtr)
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
enum {
- NSEventPhaseNone = 0,
- NSEventPhaseBegan = 0x1 << 0,
- NSEventPhaseStationary = 0x1 << 1,
- NSEventPhaseChanged = 0x1 << 2,
- NSEventPhaseEnded = 0x1 << 3,
- NSEventPhaseCancelled = 0x1 << 4,
+ NSEventPhaseNone = 0,
+ NSEventPhaseBegan = 0x1 << 0,
+ NSEventPhaseStationary = 0x1 << 1,
+ NSEventPhaseChanged = 0x1 << 2,
+ NSEventPhaseEnded = 0x1 << 3,
+ NSEventPhaseCancelled = 0x1 << 4,
};
typedef NSUInteger NSEventPhase;
@@ -1609,7 +1596,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
}
-
#pragma mark Clipboard get/set
GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 77a741c2efb..868416cd227 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -75,12 +75,12 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool stereoVisual,
+ GHOST_GLSettings glSettings,
bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
- return new GHOST_WindowNULL(this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1);
+ return new GHOST_WindowNULL(this, title, left, top, width, height, state, parentWindow, type,
+ ((glSettings.flags & GHOST_glStereoVisual) != 0), 1);
}
};
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
index cd8d161ff9c..1c76284857c 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
@@ -57,20 +57,20 @@ public:
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
- virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
+ const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
- virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
+ const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
- virtual const GHOST_TUns8 *getBinaryDir() const;
+ const GHOST_TUns8 *getBinaryDir() const;
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
index 50ad91eeb99..36ae534da87 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
@@ -24,14 +24,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#import <Cocoa/Cocoa.h>
-
-/*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/
-#include <Carbon/Carbon.h>
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
+#import <Foundation/Foundation.h>
#include "GHOST_SystemPathsCocoa.h"
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h
index c074a7902b8..b63d20bfcbd 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.h
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h
@@ -60,7 +60,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemPathsWin32();
+ ~GHOST_SystemPathsWin32();
/**
* Determine the base dir in which shared resources are located. It will first try to use
diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.cpp b/intern/ghost/intern/GHOST_SystemPathsX11.cpp
index e2d9733a9b2..5473e404593 100644
--- a/intern/ghost/intern/GHOST_SystemPathsX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsX11.cpp
@@ -121,7 +121,7 @@ const GHOST_TUns8 *GHOST_SystemPathsX11::getBinaryDir() const
return NULL;
}
-void GHOST_SystemPathsX11::addToSystemRecentFiles(const char *filename) const
+void GHOST_SystemPathsX11::addToSystemRecentFiles(const char * /*filename*/) const
{
/* XXXXX TODO: Implementation for X11 if possible */
diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.h b/intern/ghost/intern/GHOST_SystemPathsX11.h
index 1b5710e0f57..23cc2e4b104 100644
--- a/intern/ghost/intern/GHOST_SystemPathsX11.h
+++ b/intern/ghost/intern/GHOST_SystemPathsX11.h
@@ -48,7 +48,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemPathsX11();
+ ~GHOST_SystemPathsX11();
/**
* Determine the base dir in which shared resources are located. It will first try to use
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index 1d2401e6f71..e9768e4b845 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -67,9 +67,8 @@ GHOST_SystemSDL::createWindow(const STR_String& title,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow
)
{
@@ -78,8 +77,8 @@ GHOST_SystemSDL::createWindow(const STR_String& title,
window = new GHOST_WindowSDL(this, title,
left, top, width, height,
state, parentWindow, type,
- stereoVisual, exclusive,
- numOfAASamples);
+ ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive,
+ glSettings.numOfAASamples);
if (window) {
if (GHOST_kWindowStateFullScreen == state) {
@@ -321,8 +320,9 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window);
break;
}
- }
+
break;
+ }
case SDL_QUIT:
g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL);
break;
@@ -418,8 +418,8 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
GHOST_WindowSDL *window = findGhostWindow(SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
assert(window != NULL);
g_event = new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y);
- }
break;
+ }
case SDL_KEYDOWN:
case SDL_KEYUP:
{
@@ -489,8 +489,8 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
}
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, NULL);
- }
break;
+ }
}
if (g_event) {
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 5ad4fe09833..6f4ecec586b 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -108,9 +108,8 @@ private:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0
);
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 3b95373f800..4f3b1127a18 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -31,11 +31,6 @@
* \author Maarten Gribnau
*/
-#ifdef WITH_GHOST_DEBUG
-# include <iostream>
-#endif
-
-#include <stdio.h> // [mce] temporary debug, remove soon!
#include "GHOST_SystemWin32.h"
#include "GHOST_EventDragnDrop.h"
@@ -152,7 +147,7 @@ static void initRawInput()
if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE)))
; // yay!
else
- printf("could not register for RawInput: %d\n", (int)GetLastError());
+ GHOST_PRINTF("could not register for RawInput: %d\n", (int)GetLastError());
#undef DEVICE_COUNT
}
@@ -231,44 +226,37 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(
GHOST_TInt32 left, GHOST_TInt32 top,
GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type,
- bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
- GHOST_Window *window = 0;
- window = new GHOST_WindowWin32(this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples, parentWindow);
- if (window) {
- if (window->getValid()) {
- // Store the pointer to the window
-// if (state != GHOST_kWindowStateFullScreen) {
- m_windowManager->addWindow(window);
- m_windowManager->setActiveWindow(window);
-// }
- }
- else {
-
- // Invalid parent window hwnd
- if (((GHOST_WindowWin32 *)window)->getNextWindow() == NULL) {
- delete window;
- window = 0;
- return window;
- }
-
- // An invalid window could be one that was used to test for AA
- window = ((GHOST_WindowWin32 *)window)->getNextWindow();
-
- // If another window is found, let the wm know about that one, but not the old one
- if (window->getValid()) {
- m_windowManager->addWindow(window);
- }
- else {
- delete window;
- window = 0;
- }
-
- }
+ GHOST_WindowWin32 *window =
+ new GHOST_WindowWin32(
+ this,
+ title,
+ left,
+ top,
+ width,
+ height,
+ state,
+ type,
+ ((glSettings.flags & GHOST_glStereoVisual) != 0),
+ ((glSettings.flags & GHOST_glWarnSupport) != 0),
+ glSettings.numOfAASamples,
+ parentWindow,
+ ((glSettings.flags & GHOST_glDebugContext) != 0));
+
+ if (window->getValid()) {
+ // Store the pointer to the window
+ m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
}
+ else {
+ GHOST_PRINT("GHOST_SystemWin32::createWindow(): window invalid\n");
+ delete window;
+ window = 0;
+ }
+
return window;
}
@@ -440,7 +428,7 @@ GHOST_TSuccess GHOST_SystemWin32::exit()
return GHOST_System::exit();
}
-GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw, int *keyDown, char *vk)
+GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw, int *keyDown, char *vk)
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
GHOST_TKey key = GHOST_kKeyUnknown;
@@ -452,7 +440,7 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw
unsigned int msg = raw.data.keyboard.Message;
*keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK) && msg != WM_KEYUP && msg != WM_SYSKEYUP;
- key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
+ 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) {
@@ -516,19 +504,24 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw
//! note: this function can be extended to include other exotic cases as they arise.
// This function was added in response to bug [#25715]
-GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const
+// This is going to be a long list [T42426]
+GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const
{
GHOST_TKey key = GHOST_kKeyUnknown;
switch (PRIMARYLANGID(m_langId)) {
case LANG_FRENCH:
if (vKey == VK_OEM_8) key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
break;
+ case LANG_ENGLISH:
+ if (SUBLANGID(m_langId) == SUBLANG_ENGLISH_UK && vKey == VK_OEM_8) // "`¬"
+ key = GHOST_kKeyAccentGrave;
+ break;
}
return key;
}
-GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, short scanCode, short extend) const
+GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short extend) const
{
GHOST_TKey key;
@@ -636,7 +629,7 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, shor
case VK_SCROLL: key = GHOST_kKeyScrollLock; break;
case VK_CAPITAL: key = GHOST_kKeyCapsLock; break;
case VK_OEM_8:
- key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(window, vKey, scanCode);
+ key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(vKey, scanCode);
break;
case VK_MEDIA_PLAY_PAUSE: key = GHOST_kKeyMediaPlay; break;
case VK_MEDIA_STOP: key = GHOST_kKeyMediaStop; break;
@@ -653,18 +646,17 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, shor
GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(
GHOST_TEventType type,
- GHOST_IWindow *window,
+ GHOST_WindowWin32 *window,
GHOST_TButtonMask mask)
{
return new GHOST_EventButton(getSystem()->getMilliSeconds(), type, window, mask);
}
-GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
+GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_WindowWin32 *window)
{
GHOST_TInt32 x_screen, y_screen;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *) getSystem();
- GHOST_WindowWin32 *window = (GHOST_WindowWin32 *) Iwindow;
system->getCursorPosition(x_screen, y_screen);
@@ -716,27 +708,27 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type,
}
-GHOST_EventWheel *GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
+GHOST_EventWheel *GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
{
// short fwKeys = LOWORD(wParam); // key flags
int zDelta = (short) HIWORD(wParam); // wheel rotation
// zDelta /= WHEEL_DELTA;
// temporary fix below: microsoft now has added more precision, making the above division not work
- if (zDelta <= 0) zDelta = -1; else zDelta = 1;
-
+ zDelta = (zDelta <= 0) ? -1 : 1;
+
// short xPos = (short) LOWORD(lParam); // horizontal position of pointer
// short yPos = (short) HIWORD(lParam); // vertical position of pointer
return new GHOST_EventWheel(getSystem()->getMilliSeconds(), window, zDelta);
}
-GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const &raw)
+GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const &raw)
{
int keyDown = 0;
char vk;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk);
+ GHOST_TKey key = system->hardKey(raw, &keyDown, &vk);
GHOST_EventKey *event;
if (key != GHOST_kKeyUnknown) {
@@ -771,10 +763,8 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
}
event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, key, ascii, utf8_char);
-
-#ifdef GHOST_DEBUG
- std::cout << ascii << std::endl;
-#endif
+
+ // GHOST_PRINTF("%c\n", ascii); // we already get this info via EventPrinter
}
else {
event = 0;
@@ -783,26 +773,35 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
}
-GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow *window)
+GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window)
{
- GHOST_System *system = (GHOST_System *)getSystem();
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
- ((GHOST_WindowWin32 *)window)->bringTabletContextToFront();
+ window->bringTabletContextToFront();
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
}
+#ifdef WITH_INPUT_IME
+GHOST_Event *GHOST_SystemWin32::processImeEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TEventImeData *data)
+{
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
+ return new GHOST_EventIME(system->getMilliSeconds(), type, window, data);
+}
+#endif
+
+
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(
GHOST_TEventType eventType,
GHOST_TDragnDropTypes draggedObjectType,
- GHOST_IWindow *window,
+ GHOST_WindowWin32 *window,
int mouseX, int mouseY,
void *data)
{
- GHOST_SystemWin32 *system = ((GHOST_SystemWin32 *)getSystem());
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
eventType,
draggedObjectType,
@@ -832,7 +831,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
if (info.dwType == RIM_TYPEHID)
m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
else
- puts("<!> not a HID device... mouse/kb perhaps?");
+ GHOST_PRINT("<!> not a HID device... mouse/kb perhaps?\n");
firstEvent = false;
}
@@ -877,7 +876,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
m_ndofManager->updateRotation(r, now);
// I've never gotten one of these, has anyone else?
- puts("ndof: combined T + R");
+ GHOST_PRINT("ndof: combined T + R\n");
}
break;
}
@@ -906,7 +905,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
bool eventHandled = false;
LRESULT lResult = 0;
- GHOST_SystemWin32 *system = ((GHOST_SystemWin32 *)getSystem());
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
+ GHOST_EventManager *eventManager = system->getEventManager();
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
if (hwnd) {
@@ -915,8 +915,13 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
switch (msg) {
// we need to check if new key layout has AltGr
case WM_INPUTLANGCHANGE:
+ {
system->handleKeyboardChange();
+#ifdef WITH_INPUT_IME
+ window->getImeInput()->SetInputLanguage();
+#endif
break;
+ }
////////////////////////////////////////////////////////////////////////
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
@@ -952,6 +957,64 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
}
+#ifdef WITH_INPUT_IME
+ ////////////////////////////////////////////////////////////////////////
+ // IME events, processed, read more in GHOST_IME.h
+ ////////////////////////////////////////////////////////////////////////
+ case WM_IME_SETCONTEXT:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ ime->SetInputLanguage();
+ ime->CreateImeWindow(hwnd);
+ ime->CleanupComposition(hwnd);
+ ime->CheckFirst(hwnd);
+ break;
+ }
+ case WM_IME_STARTCOMPOSITION:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ eventHandled = true;
+ /* remove input event before start comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ ime->CreateImeWindow(hwnd);
+ ime->ResetComposition(hwnd);
+ event = processImeEvent(
+ GHOST_kEventImeCompositionStart,
+ window,
+ &ime->eventImeData);
+ break;
+ }
+ case WM_IME_COMPOSITION:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ eventHandled = true;
+ ime->UpdateImeWindow(hwnd);
+ ime->UpdateInfo(hwnd);
+ if (ime->eventImeData.result_len) {
+ /* remove redundant IME event */
+ eventManager->removeTypeEvents(GHOST_kEventImeComposition, window);
+ }
+ event = processImeEvent(
+ GHOST_kEventImeComposition,
+ window,
+ &ime->eventImeData);
+ break;
+ }
+ case WM_IME_ENDCOMPOSITION:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ eventHandled = true;
+ /* remove input event after end comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ ime->ResetComposition(hwnd);
+ ime->DestroyImeWindow(hwnd);
+ event = processImeEvent(
+ GHOST_kEventImeCompositionEnd,
+ window,
+ &ime->eventImeData);
+ break;
+ }
+#endif /* WITH_INPUT_IME */
////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored
////////////////////////////////////////////////////////////////////////
@@ -1002,11 +1065,11 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
// Tablet events, processed
////////////////////////////////////////////////////////////////////////
case WT_PACKET:
- ((GHOST_WindowWin32 *)window)->processWin32TabletEvent(wParam, lParam);
+ window->processWin32TabletEvent(wParam, lParam);
break;
case WT_CSRCHANGE:
case WT_PROXIMITY:
- ((GHOST_WindowWin32 *)window)->processWin32TabletInitEvent();
+ window->processWin32TabletInitEvent();
break;
////////////////////////////////////////////////////////////////////////
// Mouse events, processed
@@ -1066,19 +1129,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* until it finds a window that processes it.
*/
- /* Get the winow under the mouse and send event to it's queue. */
+ /* Get the window under the mouse and send event to its queue. */
POINT mouse_pos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
- HWND mouse_hwnd = WindowFromPoint(mouse_pos);
+ HWND mouse_hwnd = ChildWindowFromPoint(HWND_DESKTOP, mouse_pos);
GHOST_WindowWin32 *mouse_window = (GHOST_WindowWin32 *)::GetWindowLongPtr(mouse_hwnd, GWLP_USERDATA);
if (mouse_window != NULL) {
event = processWheelEvent(mouse_window, wParam, lParam);
}
else {
- /* If it happened so window under the mouse is not found (which i'm not
- * really sure might happen), then we add event to the focused window
- * in order to avoid some possible negative side effects.
- * - sergey -
- */
+ /* Happens when mouse is not over any of blender's windows. */
event = processWheelEvent(window, wParam, lParam);
}
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 79fed06c6a5..0a8837294db 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -53,6 +53,8 @@ class GHOST_EventWheel;
class GHOST_EventWindow;
class GHOST_EventDragnDrop;
+class GHOST_WindowWin32;
+
/**
* WIN32 Implementation of GHOST_System class.
* \see GHOST_System.
@@ -69,7 +71,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemWin32();
+ ~GHOST_SystemWin32();
/***************************************************************************************
** Time(r) functionality
@@ -81,7 +83,7 @@ public:
* This overloaded method uses the high frequency timer if available.
* \return The number of milliseconds.
*/
- virtual GHOST_TUns64 getMilliSeconds() const;
+ GHOST_TUns64 getMilliSeconds() const;
/***************************************************************************************
** Display/window management functionality
@@ -91,19 +93,19 @@ public:
* Returns the number of displays on this system.
* \return The number of displays.
*/
- virtual GHOST_TUns8 getNumDisplays() const;
+ GHOST_TUns8 getNumDisplays() const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/**
* Returns the dimensions of all displays on this system.
* \return The dimension of the main display.
*/
- virtual void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/**
* Create a new window.
@@ -116,18 +118,17 @@ public:
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL settings.
+ * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
- virtual GHOST_IWindow *createWindow(
+ GHOST_IWindow *createWindow(
const STR_String& title,
GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type,
- const bool stereoVisual = false,
- const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
+ GHOST_GLSettings glSettings,
+ const bool exclusive = false,
const GHOST_TEmbedderWindowID parentWindow = 0);
/***************************************************************************************
@@ -139,7 +140,7 @@ public:
* \param waitForEvent Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
- virtual bool processEvents(bool waitForEvent);
+ bool processEvents(bool waitForEvent);
/***************************************************************************************
@@ -152,7 +153,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
+ GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -160,7 +161,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
/***************************************************************************************
** Access to mouse button and keyboard states.
@@ -171,28 +172,28 @@ public:
* \param keys The state of all modifier keys (true == pressed).
* \return Indication of success.
*/
- virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
+ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
/**
* Returns the state of the mouse buttons (ouside the message queue).
* \param buttons The state of the buttons.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
+ GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
/**
- * Returns unsinged char from CUT_BUFFER0
+ * Returns unsigned char from CUT_BUFFER0
* \param selection Used by X11 only
* \return Returns the Clipboard
*/
- virtual GHOST_TUns8 *getClipboard(bool selection) const;
+ GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* \param selection Used by X11 only
* \return No return
*/
- virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
@@ -204,13 +205,13 @@ public:
* \param window The window on which the event occurred
* \return Indication whether the event was handled.
*/
- static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_IWindow *window, int mouseX, int mouseY, void *data);
+ static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_WindowWin32 *window, int mouseX, int mouseY, void *data);
/**
* Confirms quitting he program when there is just one window left open
* in the application
*/
- virtual int confirmQuit(GHOST_IWindow *window) const;
+ int confirmQuit(GHOST_IWindow *window) const;
protected:
/**
@@ -218,42 +219,31 @@ protected:
* For now, it just registers the window class (WNDCLASS).
* \return A success value.
*/
- virtual GHOST_TSuccess init();
+ GHOST_TSuccess init();
/**
* Closes the system down.
* \return A success value.
*/
- virtual GHOST_TSuccess exit();
+ GHOST_TSuccess exit();
/**
* Converts raw WIN32 key codes from the wndproc to GHOST keys.
- * \param window-> The window for this handling
* \param vKey The virtual key from hardKey
- * \param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
+ * \param ScanCode The ScanCode of pressed key (similar to PS/2 Set 1)
* \param extend Flag if key is not primly (left or right)
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- virtual GHOST_TKey convertKey(GHOST_IWindow *window, short vKey, short ScanCode, short extend) const;
+ GHOST_TKey convertKey(short vKey, short ScanCode, short extend) const;
/**
* Catches raw WIN32 key codes from WM_INPUT in the wndproc.
- * \param window The window for this handling
* \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
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- virtual GHOST_TKey hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int *keyDown, char *vk);
-
- /**
- * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys).
- * With the modifier keys, we want to distinguish left and right keys.
- * Sometimes this is not possible (Windows ME for instance). Then, we want
- * events generated for both keys.
- * \param window The window receiving the event (the active window).
- */
- GHOST_EventKey *processModifierKeys(GHOST_IWindow *window);
+ GHOST_TKey hardKey(RAWINPUT const& raw, int *keyDown, char *vk);
/**
* Creates mouse button event.
@@ -262,7 +252,7 @@ protected:
* \param mask The button mask of this event.
* \return The event created.
*/
- static GHOST_EventButton *processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask);
+ static GHOST_EventButton *processButtonEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TButtonMask mask);
/**
* Creates cursor event.
@@ -270,7 +260,7 @@ protected:
* \param window The window receiving the event (the active window).
* \return The event created.
*/
- static GHOST_EventCursor *processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow);
+ static GHOST_EventCursor *processCursorEvent(GHOST_TEventType type, GHOST_WindowWin32 *window);
/**
* Creates a mouse wheel event.
@@ -278,7 +268,7 @@ protected:
* \param wParam The wParam from the wndproc
* \param lParam The lParam from the wndproc
*/
- static GHOST_EventWheel *processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam);
+ static GHOST_EventWheel *processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam);
/**
* Creates a key event and updates the key data stored locally (m_modifierKeys).
@@ -287,16 +277,15 @@ protected:
* \param window The window receiving the event (the active window).
* \param raw RawInput structure with detailed info about the key event
*/
- static GHOST_EventKey *processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw);
+ static GHOST_EventKey *processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const& raw);
/**
* Process special keys (VK_OEM_*), to see if current key layout
* gives us anything special, like ! on french AZERTY.
- * \param window The window receiving the event (the active window).
* \param vKey The virtual key from hardKey
- * \param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
+ * \param scanCode The ScanCode of pressed key (simular to PS/2 Set 1)
*/
- virtual GHOST_TKey processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const;
+ GHOST_TKey processSpecialKey(short vKey, short scanCode) const;
/**
* Creates a window event.
@@ -304,7 +293,18 @@ protected:
* \param window The window receiving the event (the active window).
* \return The event created.
*/
- static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_IWindow *window);
+ static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window);
+
+#ifdef WITH_INPUT_IME
+ /**
+ * Creates a IME event.
+ * \param type The type of event to create.
+ * \param window The window receiving the event (the active window).
+ * \param data IME data.
+ * \return The event created.
+ */
+ static GHOST_Event *processImeEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TEventImeData *data);
+#endif // WITH_INPUT_IME
/**
* Handles minimum window size.
@@ -327,19 +327,19 @@ protected:
* Returns the local state of the modifier keys (from the message queue).
* \param keys The state of the keys.
*/
- inline virtual void retrieveModifierKeys(GHOST_ModifierKeys& keys) const;
+ 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 virtual void storeModifierKeys(const GHOST_ModifierKeys& keys);
+ inline void storeModifierKeys(const GHOST_ModifierKeys& keys);
/**
* Check current key layout for AltGr
*/
- inline virtual void handleKeyboardChange(void);
+ inline void handleKeyboardChange(void);
/**
* Windows call back routine for our window class.
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index f797d8074e1..325cba0c631 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -32,6 +32,11 @@
* \ingroup GHOST
*/
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/XKBlib.h> /* allow detectable autorepeate */
+#include <X11/Xutil.h>
+
#include "GHOST_SystemX11.h"
#include "GHOST_WindowX11.h"
#include "GHOST_WindowManager.h"
@@ -52,10 +57,6 @@
#include "GHOST_Debug.h"
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/XKBlib.h> /* allow detectable autorepeate */
-
#ifdef WITH_XF86KEYSYM
#include <X11/XF86keysym.h>
#endif
@@ -279,40 +280,33 @@ getAllDisplayDimensions(
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param exclusive Use to show the window ontop and ignore others
- * (used fullscreen).
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL settings.
+ * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *
GHOST_SystemX11::
-createWindow(
- const STR_String& title,
+createWindow(const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
GHOST_WindowX11 *window = 0;
if (!m_display) return 0;
-
-
-
window = new GHOST_WindowX11(this, m_display, title,
left, top, width, height,
state, parentWindow, type,
- stereoVisual, exclusive,
- numOfAASamples);
+ ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive,
+ glSettings.numOfAASamples, (glSettings.flags & GHOST_glDebugContext) != 0);
if (window) {
/* Both are now handle in GHOST_WindowX11.cpp
@@ -333,7 +327,7 @@ createWindow(
}
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
-static void destroyIMCallback(XIM xim, XPointer ptr, XPointer data)
+static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/)
{
GHOST_PRINT("XIM server died\n");
@@ -1180,7 +1174,11 @@ GHOST_SystemX11::processEvent(XEvent *xe)
default:
{
#ifdef WITH_X11_XINPUT
- if (xe->type == m_xtablet.MotionEvent) {
+ if (xe->type == m_xtablet.MotionEvent ||
+ xe->type == m_xtablet.MotionEventEraser ||
+ xe->type == m_xtablet.PressEvent ||
+ xe->type == m_xtablet.PressEventEraser)
+ {
XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
const unsigned char axis_first = data->first_axis;
const unsigned char axes_end = axis_first + data->axes_count; /* after the last */
@@ -1873,13 +1871,16 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
}
#endif
-#ifdef WITH_X11_XINPUT
-/*
+#if defined(USE_X11_ERROR_HANDLERS) || defined(WITH_X11_XINPUT)
+/*
+ * These callbacks can be used for debugging, so we can breakpoint on an X11 error.
+
+ *
* Dummy function to get around IO Handler exiting if device invalid
* Basically it will not crash blender now if you have a X device that
* is configured but not plugged in.
*/
-int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
+int GHOST_X11_ApplicationErrorHandler(Display * /*display*/, XErrorEvent *theEvent)
{
fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
theEvent->error_code, theEvent->request_code);
@@ -1888,14 +1889,16 @@ int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
return 0;
}
-int GHOST_X11_ApplicationIOErrorHandler(Display *display)
+int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/)
{
fprintf(stderr, "Ignoring Xlib error: error IO\n");
/* No exit! - but keep lint happy */
return 0;
}
+#endif
+#ifdef WITH_X11_XINPUT
/* These C functions are copied from Wine 1.1.13's wintab.c */
#define BOOL int
#define TRUE 1
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index a21300e36f0..a0088dbe8f0 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -34,7 +34,6 @@
#define __GHOST_SYSTEMX11_H__
#include <X11/Xlib.h>
-#include <GL/glx.h>
#include "GHOST_System.h"
#include "../GHOST_Types.h"
@@ -53,6 +52,7 @@
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
int GHOST_X11_ApplicationIOErrorHandler(Display *display);
+
class GHOST_WindowX11;
/**
@@ -76,7 +76,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemX11();
+ ~GHOST_SystemX11();
GHOST_TSuccess
@@ -152,17 +152,12 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0
);
/**
- * \section Interface Inherited from GHOST_ISystem
- */
-
- /**
* Retrieves events from the system and stores them in the queue.
* \param waitForEvent Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
@@ -172,9 +167,6 @@ public:
bool waitForEvent
);
- /**
- * \section Interface Inherited from GHOST_System
- */
GHOST_TSuccess
getCursorPosition(
GHOST_TInt32& x,
@@ -208,7 +200,6 @@ public:
) const;
/**
- * \section Interface Dirty
* Flag a window as dirty. This will
* generate a GHOST window update event on a call to processEvents()
*/
@@ -243,7 +234,7 @@ public:
unsigned int *context) const;
/**
- * Returns unsinged char from CUT_BUFFER0
+ * Returns unsigned char from CUT_BUFFER0
* \param selection Get selection, X11 only feature
* \return Returns the Clipboard indicated by Flag
*/
@@ -273,7 +264,7 @@ public:
/**
* \see GHOST_ISystem
*/
- int toggleConsole(int action) {
+ int toggleConsole(int /*action*/) {
return 0;
}
@@ -287,6 +278,12 @@ public:
int MotionEvent;
int ProxInEvent;
int ProxOutEvent;
+ int PressEvent;
+
+ int MotionEventEraser;
+ int ProxInEventEraser;
+ int ProxOutEventEraser;
+ int PressEventEraser;
int PressureLevels;
int XtiltLevels, YtiltLevels;
diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h
index b94175e9ff8..6cf4bcf40eb 100644
--- a/intern/ghost/intern/GHOST_TimerManager.h
+++ b/intern/ghost/intern/GHOST_TimerManager.h
@@ -58,19 +58,19 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_TimerManager();
+ ~GHOST_TimerManager();
/**
* Returns the number of timer tasks.
* \return The number of events on the stack.
*/
- virtual GHOST_TUns32 getNumTimers();
+ GHOST_TUns32 getNumTimers();
/**
* Returns whether this timer task ins in our list.
* \return Indication of presence.
*/
- virtual bool getTimerFound(GHOST_TimerTask *timer);
+ bool getTimerFound(GHOST_TimerTask *timer);
/**
* Adds a timer task to the list.
@@ -78,7 +78,7 @@ public:
* \param timer The timer task added to the list.
* \return Indication as to whether addition has succeeded.
*/
- virtual GHOST_TSuccess addTimer(GHOST_TimerTask *timer);
+ GHOST_TSuccess addTimer(GHOST_TimerTask *timer);
/**
* Removes a timer task from the list.
@@ -86,21 +86,21 @@ public:
* \param timer The timer task to be removed from the list.
* \return Indication as to whether removal has succeeded.
*/
- virtual GHOST_TSuccess removeTimer(GHOST_TimerTask *timer);
+ GHOST_TSuccess removeTimer(GHOST_TimerTask *timer);
/**
* Finds the soonest time the next timer would fire.
* \return The soonest time the next timer would fire,
* or GHOST_kFireTimeNever if no timers exist.
*/
- virtual GHOST_TUns64 nextFireTime();
+ GHOST_TUns64 nextFireTime();
/**
* Checks all timer tasks to see if they are expired and fires them if needed.
* \param time The current time.
* \return True if any timers were fired.
*/
- virtual bool fireTimers(GHOST_TUns64 time);
+ bool fireTimers(GHOST_TUns64 time);
/**
* Checks this timer task to see if they are expired and fires them if needed.
@@ -108,7 +108,7 @@ public:
* \param task The timer task to check and optionally fire.
* \return True if the timer fired.
*/
- virtual bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task);
+ bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task);
protected:
/**
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
index e33788ec826..45aa66e4630 100644
--- a/intern/ghost/intern/GHOST_TimerTask.h
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -49,7 +49,7 @@ public:
* \param start The timer start time.
* \param interval The interval between calls to the timerProc
* \param timerProc The callback invoked when the interval expires.
- * \param data The timer user data.
+ * \param userData: The timer user data.
*/
GHOST_TimerTask(GHOST_TUns64 start,
GHOST_TUns64 interval,
@@ -68,7 +68,7 @@ public:
* Returns the timer start time.
* \return The timer start time.
*/
- inline virtual GHOST_TUns64 getStart() const
+ inline GHOST_TUns64 getStart() const
{
return m_start;
}
@@ -77,7 +77,7 @@ public:
* Changes the timer start time.
* \param start The timer start time.
*/
- virtual void setStart(GHOST_TUns64 start)
+ void setStart(GHOST_TUns64 start)
{
m_start = start;
}
@@ -86,7 +86,7 @@ public:
* Returns the timer interval.
* \return The timer interval.
*/
- inline virtual GHOST_TUns64 getInterval() const
+ inline GHOST_TUns64 getInterval() const
{
return m_interval;
}
@@ -95,7 +95,7 @@ public:
* Changes the timer interval.
* \param interval The timer interval.
*/
- virtual void setInterval(GHOST_TUns64 interval)
+ void setInterval(GHOST_TUns64 interval)
{
m_interval = interval;
}
@@ -104,7 +104,7 @@ public:
* Returns the time the timerProc will be called.
* \return The time the timerProc will be called.
*/
- inline virtual GHOST_TUns64 getNext() const
+ inline GHOST_TUns64 getNext() const
{
return m_next;
}
@@ -113,7 +113,7 @@ public:
* Changes the time the timerProc will be called.
* \param next The time the timerProc will be called.
*/
- virtual void setNext(GHOST_TUns64 next)
+ void setNext(GHOST_TUns64 next)
{
m_next = next;
}
@@ -122,16 +122,16 @@ public:
* Returns the timer callback.
* \return the timer callback.
*/
- inline virtual GHOST_TimerProcPtr getTimerProc() const
+ inline GHOST_TimerProcPtr getTimerProc() const
{
return m_timerProc;
}
/**
* Changes the timer callback.
- * \param The timer callback.
+ * \param timerProc: The timer callback.
*/
- inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc)
+ inline void setTimerProc(const GHOST_TimerProcPtr timerProc)
{
m_timerProc = timerProc;
}
@@ -140,16 +140,16 @@ public:
* Returns the timer user data.
* \return The timer user data.
*/
- inline virtual GHOST_TUserDataPtr getUserData() const
+ inline GHOST_TUserDataPtr getUserData() const
{
return m_userData;
}
/**
* Changes the time user data.
- * \param data The timer user data.
+ * \param userData: The timer user data.
*/
- virtual void setUserData(const GHOST_TUserDataPtr userData)
+ void setUserData(const GHOST_TUserDataPtr userData)
{
m_userData = userData;
}
@@ -158,7 +158,7 @@ public:
* Returns the auxiliary storage room.
* \return The auxiliary storage room.
*/
- inline virtual GHOST_TUns32 getAuxData() const
+ inline GHOST_TUns32 getAuxData() const
{
return m_auxData;
}
@@ -167,7 +167,7 @@ public:
* Changes the auxiliary storage room.
* \param auxData The auxiliary storage room.
*/
- virtual void setAuxData(GHOST_TUns32 auxData)
+ void setAuxData(GHOST_TUns32 auxData)
{
m_auxData = auxData;
}
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index 3673831c7b1..71fa260f0f2 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -38,21 +38,23 @@
#include "GHOST_Window.h"
+#include "GHOST_ContextNone.h"
+
#include <assert.h>
GHOST_Window::GHOST_Window(
GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
- const bool stereoVisual,
- const bool exclusive,
- const GHOST_TUns16 numOfAASamples)
- : m_drawingContextType(type),
+ const bool wantStereoVisual,
+ const bool /*exclusive*/,
+ const GHOST_TUns16 wantNumOfAASamples)
+ : m_drawingContextType(GHOST_kDrawingContextTypeNone),
m_cursorVisible(true),
m_cursorGrab(GHOST_kGrabDisable),
m_cursorShape(GHOST_kStandardCursorDefault),
- m_stereoVisual(stereoVisual),
- m_numOfAASamples(numOfAASamples)
+ m_wantStereoVisual(wantStereoVisual),
+ m_wantNumOfAASamples(wantNumOfAASamples),
+ m_context(new GHOST_ContextNone(false, 0))
{
m_isUnsavedChanges = false;
m_canAcceptDragOperation = false;
@@ -74,6 +76,7 @@ GHOST_Window::GHOST_Window(
GHOST_Window::~GHOST_Window()
{
+ delete m_context;
}
void *GHOST_Window::getOSWindow() const
@@ -83,18 +86,61 @@ void *GHOST_Window::getOSWindow() const
GHOST_TSuccess GHOST_Window::setDrawingContextType(GHOST_TDrawingContextType type)
{
- GHOST_TSuccess success = GHOST_kSuccess;
if (type != m_drawingContextType) {
- success = removeDrawingContext();
- if (success) {
- success = installDrawingContext(type);
+ delete m_context;
+ m_context = NULL;
+
+ if (type != GHOST_kDrawingContextTypeNone)
+ m_context = newDrawingContext(type);
+
+ if (m_context != NULL) {
m_drawingContextType = type;
}
else {
+ m_context = new GHOST_ContextNone(m_wantStereoVisual, m_wantNumOfAASamples);
m_drawingContextType = GHOST_kDrawingContextTypeNone;
}
+
+ return (type == m_drawingContextType) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kSuccess;
}
- return success;
+}
+
+GHOST_TSuccess GHOST_Window::swapBuffers()
+{
+ return m_context->swapBuffers();
+}
+
+GHOST_TSuccess GHOST_Window::setSwapInterval(int interval)
+{
+ return m_context->setSwapInterval(interval);
+}
+
+GHOST_TSuccess GHOST_Window::getSwapInterval(int& intervalOut)
+{
+ return m_context->getSwapInterval(intervalOut);
+}
+
+GHOST_TUns16 GHOST_Window::getNumOfAASamples()
+{
+ return m_context->getNumOfAASamples();
+}
+
+GHOST_TSuccess GHOST_Window::activateDrawingContext()
+{
+ return m_context->activateDrawingContext();
+}
+
+GHOST_TSuccess GHOST_Window::updateDrawingContext()
+{
+ return m_context->updateDrawingContext();
+}
+
+GHOST_TSuccess GHOST_Window::releaseNativeHandles()
+{
+ return m_context->releaseNativeHandles();
}
GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 77ee4db8543..52cb9cbf54b 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -36,6 +36,7 @@
#include "GHOST_IWindow.h"
class STR_String;
+class GHOST_Context;
/**
* Platform independent implementation of GHOST_IWindow.
@@ -49,29 +50,6 @@ class STR_String;
class GHOST_Window : public GHOST_IWindow
{
public:
- /**
- * \section Interface inherited from GHOST_IWindow left for derived class
- * implementation.
- * virtual bool getValid() const = 0;
- * virtual void setTitle(const STR_String& title) = 0;
- * virtual void getTitle(STR_String& title) const = 0;
- * virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
- * virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
- * virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
- * virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
- * virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
- * virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
- * virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
- * virtual GHOST_TWindowState getState() const = 0;
- * virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
- * virtual GHOST_TWindowOrder getOrder(void) = 0;
- * virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
- * virtual GHOST_TSuccess swapBuffers() = 0;
- * virtual GHOST_TSuccess setSwapInterval() = 0;
- * virtual int getSwapInterval() = 0;
- * virtual GHOST_TSuccess activateDrawingContext() = 0;
- * virtual GHOST_TSuccess invalidate() = 0;
- */
/**
* Constructor.
@@ -90,10 +68,9 @@ public:
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
- const bool stereoVisual = false,
+ const bool wantStereoVisual = false,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0);
+ const GHOST_TUns16 wantNumOfAASamples = 0);
/**
* \section Interface inherited from GHOST_IWindow left for derived class
@@ -113,7 +90,7 @@ public:
* virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
* virtual GHOST_TSuccess swapBuffers() = 0;
* virtual GHOST_TSuccess setSwapInterval() = 0;
- * virtual int getSwapInterval() = 0;
+ * virtual GHOST_TSuccess getSwapInterval(int& intervalOut) = 0;
* virtual GHOST_TSuccess activateDrawingContext() = 0;
* virtual GHOST_TSuccess invalidate() = 0;
*/
@@ -125,6 +102,14 @@ public:
virtual ~GHOST_Window();
/**
+ * Returns indication as to whether the window is valid.
+ * \return The validity of the window.
+ */
+ virtual bool getValid() const {
+ return m_context != 0;
+ }
+
+ /**
* Returns the associated OS object/handle
* \return The associated OS object/handle
*/
@@ -134,14 +119,14 @@ public:
* Returns the current cursor shape.
* \return The current cursor shape.
*/
- inline virtual GHOST_TStandardCursor getCursorShape() const;
+ inline GHOST_TStandardCursor getCursorShape() const;
/**
* Set the shape of the cursor.
- * \param cursor The new cursor shape type id.
+ * \param cursorShape: The new cursor shape type id.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
+ GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
/**
* Set the shape of the cursor to a custom cursor.
@@ -151,53 +136,53 @@ public:
* \param hotY The Y coordinate of the cursor hotspot.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
- GHOST_TUns8 mask[16][2],
- int hotX,
- int hotY);
-
- virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
- int sizex, int sizey,
- int hotX, int hotY,
- int fg_color, int bg_color);
-
+ GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY);
+
+ GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
+ GHOST_TUns8 *mask,
+ int sizex, int sizey,
+ int hotX, int hotY,
+ int fg_color, int bg_color);
+
/**
* Returns the visibility state of the cursor.
* \return The visibility state of the cursor.
*/
- inline virtual bool getCursorVisibility() const;
- inline virtual GHOST_TGrabCursorMode getCursorGrabMode() const;
- inline virtual bool getCursorGrabModeIsWarp() const;
- inline virtual void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
- inline virtual void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
- inline virtual void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
+ inline bool getCursorVisibility() const;
+ inline GHOST_TGrabCursorMode getCursorGrabMode() const;
+ inline bool getCursorGrabModeIsWarp() const;
+ inline void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ inline void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ inline void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
/**
* Shows or hides the cursor.
* \param visible The new visibility state of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorVisibility(bool visible);
+ GHOST_TSuccess setCursorVisibility(bool visible);
/**
* Sets the cursor grab.
* \param mode The new grab state of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]);
+ GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]);
/**
* Gets the cursor grab region, if unset the window is used.
* reset when grab is disabled.
*/
- virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect& bounds);
+ GHOST_TSuccess getCursorGrabBounds(GHOST_Rect& bounds);
/**
* Sets the progress bar value displayed in the window/application icon
* \param progress The progress % (0.0 to 1.0)
*/
- virtual GHOST_TSuccess setProgressBar(float progress) {
+ virtual GHOST_TSuccess setProgressBar(float /*progress*/) {
return GHOST_kFailure;
}
@@ -213,28 +198,30 @@ public:
* \param interval The swap interval to use.
* \return A boolean success indicator.
*/
- virtual GHOST_TSuccess setSwapInterval(int interval) {
- return GHOST_kFailure;
- }
-
+ GHOST_TSuccess setSwapInterval(int interval);
+
/**
* Gets the current swap interval for swapBuffers.
* \return An integer.
*/
- virtual int getSwapInterval() {
- return 0;
- }
-
+ GHOST_TSuccess getSwapInterval(int& intervalOut);
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \return Number of AA Samples (0 if there is no multisample buffer)
+ */
+ GHOST_TUns16 getNumOfAASamples();
+
/**
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
*/
- virtual void setAcceptDragOperation(bool canAccept);
+ void setAcceptDragOperation(bool canAccept);
/**
* Returns acceptance of the dropped object
* Usually called by the "object dropped" event handling function
*/
- virtual bool canAcceptDragOperation() const;
+ bool canAcceptDragOperation() const;
/**
* Sets the window "modified" status, indicating unsaved changes
@@ -253,55 +240,84 @@ public:
* Returns the type of drawing context used in this window.
* \return The current type of drawing context.
*/
- inline virtual GHOST_TDrawingContextType getDrawingContextType();
+ inline GHOST_TDrawingContextType getDrawingContextType();
/**
* Tries to install a rendering context in this window.
- * Child classes do not need to overload this method.
- * They should overload the installDrawingContext and removeDrawingContext instead.
+ * Child classes do not need to overload this method,
+ * They should overload newDrawingContext instead.
* \param type The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
- virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
+ GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Updates the drawing context of this window. Needed
+ * whenever the window is changed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess updateDrawingContext();
/**
* Returns the window user data.
* \return The window user data.
*/
- inline virtual GHOST_TUserDataPtr getUserData() const
+ inline GHOST_TUserDataPtr getUserData() const
{
return m_userData;
}
/**
* Changes the window user data.
- * \param data The window user data.
+ * \param userData: The window user data.
*/
- virtual void setUserData(const GHOST_TUserDataPtr userData)
+ void setUserData(const GHOST_TUserDataPtr userData)
{
m_userData = userData;
}
- virtual float getNativePixelSize(void)
+ float getNativePixelSize(void)
{
if (m_nativePixelSize > 0.0f)
return m_nativePixelSize;
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+ virtual void beginIME(GHOST_TInt32 x,
+ GHOST_TInt32 y,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h,
+ int completed)
+ {
+ /* do nothing temporarily if not in windows */
+ }
+
+ virtual void endIME()
+ {
+ /* do nothing temporarily if not in windows */
+ }
+#endif /* WITH_INPUT_IME */
+
protected:
/**
* Tries to install a rendering context in this window.
* \param type The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
- virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type) = 0;
-
- /**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
- */
- virtual GHOST_TSuccess removeDrawingContext() = 0;
+ virtual GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) = 0;
/**
* Sets the cursor visibility on the window using
@@ -313,7 +329,7 @@ protected:
* Sets the cursor grab on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) {
+ virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode /*mode*/) {
return GHOST_kSuccess;
}
@@ -333,7 +349,10 @@ protected:
virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
int szx, int szy, int hotX, int hotY, int fg, int bg) = 0;
- /** The the of drawing context installed in this window. */
+
+ GHOST_TSuccess releaseNativeHandles();
+
+ /** The drawing context installed in this window. */
GHOST_TDrawingContextType m_drawingContextType;
/** The window user data */
@@ -369,14 +388,11 @@ protected:
/** Stores whether this is a full screen window. */
bool m_fullScreen;
- /** Stereo visual created. Only necessary for 'real' stereo support,
- * ie quad buffered stereo. This is not always possible, depends on
- * the graphics h/w
- */
- bool m_stereoVisual;
-
- /** Number of samples used in anti-aliasing, set to 0 if no AA **/
- GHOST_TUns16 m_numOfAASamples;
+ /** Whether to attempt to initialize a context with a stereo framebuffer. */
+ bool m_wantStereoVisual;
+
+ /** Attempt to initialize a context with this many samples. */
+ GHOST_TUns16 m_wantNumOfAASamples;
/** Full-screen width */
GHOST_TUns32 m_fullScreenWidth;
@@ -385,6 +401,9 @@ protected:
/* OSX only, retina screens */
float m_nativePixelSize;
+
+private:
+ GHOST_Context *m_context;
};
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index b30f6a340ad..3ed88086184 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Maarten Gribnau, Jason Wilkins
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -42,20 +42,11 @@
@class CocoaWindow;
@class CocoaOpenGLView;
+@class NSCursor;
+@class NSScreen;
class GHOST_SystemCocoa;
-/**
- * Window on Mac OSX/Cocoa.
- * Carbon windows have a size widget in the lower right corner of the window.
- * To force it to be visible, the height of the client rectangle is reduced so
- * that applications do not draw in that area. GHOST will manage that area
- * which is called the gutter.
- * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent
- * OpenGL drawing outside the reduced client rectangle.
- * \author Maarten Gribnau
- * \date May 23, 2001
- */
class GHOST_WindowCocoa : public GHOST_Window {
public:
/**
@@ -90,77 +81,77 @@ public:
* Destructor.
* Closes the window and disposes resources allocated.
*/
- virtual ~GHOST_WindowCocoa();
+ ~GHOST_WindowCocoa();
/**
* Returns indication as to whether the window is valid.
* \return The validity of the window.
*/
- virtual bool getValid() const;
+ bool getValid() const;
/**
* Returns the associated NSWindow object
* \return The associated NSWindow object
*/
- virtual void *getOSWindow() const;
+ void *getOSWindow() const;
/**
* Sets the title displayed in the title bar.
* \param title The title to display in the title bar.
*/
- virtual void setTitle(const STR_String& title);
+ void setTitle(const STR_String& title);
/**
* Returns the title displayed in the title bar.
* \param title The title displayed in the title bar.
*/
- virtual void getTitle(STR_String& title) const;
+ void getTitle(STR_String& title) const;
/**
* Returns the window rectangle dimensions.
* The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
* \param bounds The bounding rectangle of the window.
*/
- virtual void getWindowBounds(GHOST_Rect& bounds) const;
+ void getWindowBounds(GHOST_Rect& bounds) const;
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
* \param bounds The bounding rectangle of the client area of the window.
*/
- virtual void getClientBounds(GHOST_Rect& bounds) const;
+ void getClientBounds(GHOST_Rect& bounds) const;
/**
* Resizes client rectangle width.
* \param width The new width of the client area of the window.
*/
- virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
/**
* Resizes client rectangle height.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
/**
* Resizes client rectangle.
* \param width The new width of the client area of the window.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
/**
* Returns the state of the window (normal, minimized, maximized).
* \return The state of the window.
*/
- virtual GHOST_TWindowState getState() const;
+ GHOST_TWindowState getState() const;
/**
* Sets the window "modified" status, indicating unsaved changes
* \param isUnsavedChanges Unsaved changes or not
* \return Indication of success.
*/
- virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
+ GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -169,7 +160,7 @@ public:
* \param outX The x-coordinate in the client rectangle.
* \param outY The y-coordinate in the client rectangle.
*/
- virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -178,7 +169,7 @@ public:
* \param outX The x-coordinate on the screen.
* \param outY The y-coordinate on the screen.
*/
- virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -211,37 +202,17 @@ public:
* \param state The state of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setState(GHOST_TWindowState state);
+ GHOST_TSuccess setState(GHOST_TWindowState state);
/**
* Sets the order of the window (bottom, top).
* \param order The order of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
-
- /**
- * Swaps front and back buffers of a window.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess swapBuffers();
-
- /**
- * Updates the drawing context of this window. Needed
- * whenever the window is changed.
- * \return Indication of success.
- */
- GHOST_TSuccess updateDrawingContext();
-
- /**
- * Activates the drawing context of this window.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess activateDrawingContext();
+ GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
- virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const;
+ void loadCursor(bool visible, GHOST_TStandardCursor cursor) const;
-
const GHOST_TabletData *GetTabletData()
{
return &m_tablet;
@@ -256,15 +227,15 @@ public:
* Sets the progress bar value displayed in the window/application icon
* \param progress The progress % (0.0 to 1.0)
*/
- virtual GHOST_TSuccess setProgressBar(float progress);
+ GHOST_TSuccess setProgressBar(float progress);
/**
* Hides the progress bar icon
*/
- virtual GHOST_TSuccess endProgressBar();
+ GHOST_TSuccess endProgressBar();
- virtual void setNativePixelSize(void);
+ void setNativePixelSize(void);
GHOST_TSuccess beginFullScreen() const {return GHOST_kFailure;}
@@ -278,51 +249,45 @@ public:
bool getImmediateDraw(void) const { return m_immediateDraw; }
protected:
- /**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication as to whether installation has succeeded.
- */
- virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
/**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
+ * \param type The type of rendering context create.
+ * \return Indication of success.
*/
- virtual GHOST_TSuccess removeDrawingContext();
-
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
+
/**
* Invalidates the contents of this window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess invalidate();
+ GHOST_TSuccess invalidate();
/**
* Sets the cursor visibility on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
+ GHOST_TSuccess setWindowCursorVisibility(bool visible);
/**
* Sets the cursor grab on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
+ GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
+ GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color);
- virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
+ GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
/** The window containing the OpenGL view */
CocoaWindow *m_window;
@@ -330,15 +295,9 @@ protected:
/** The openGL view */
CocoaOpenGLView *m_openGLView;
- /** The opgnGL drawing context */
- NSOpenGLContext *m_openGLContext;
-
/** The mother SystemCocoa class to send events */
GHOST_SystemCocoa *m_systemCocoa;
-
- /** The first created OpenGL context (for sharing display lists) */
- static NSOpenGLContext *s_firstOpenGLcontext;
-
+
NSCursor *m_customCursor;
GHOST_TabletData m_tablet;
@@ -349,4 +308,3 @@ protected:
};
#endif // __GHOST_WINDOWCOCOA_H__
-
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index f9b8899fbe5..9c7b5c3fee7 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -20,29 +20,31 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Maarten Gribnau 05/2001
- Damien Plisson 10/2009
+ * Contributor(s): Maarten Gribnau 05/2001
+ * Damien Plisson 10/2009
+ * Jason Wilkins 02/2014
+ * Jens Verwiebe 10/2014
*
* ***** END GPL LICENSE BLOCK *****
*/
-#include <Cocoa/Cocoa.h>
+#include "GHOST_WindowCocoa.h"
+#include "GHOST_SystemCocoa.h"
+#include "GHOST_ContextNone.h"
+#include "GHOST_Debug.h"
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
-//Use of the SetSystemUIMode function (64bit compatible)
-#include <Carbon/Carbon.h>
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextCGL.h"
#endif
-#include <OpenGL/gl.h>
-#include <OpenGL/CGLRenderers.h>
-/***** Multithreaded opengl code : uncomment for enabling
-#include <OpenGL/OpenGL.h>
-*/
+#include <Cocoa/Cocoa.h>
-
-#include "GHOST_WindowCocoa.h"
-#include "GHOST_SystemCocoa.h"
-#include "GHOST_Debug.h"
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
+ //Use of the SetSystemUIMode function (64bit compatible)
+# include <Carbon/Carbon.h>
+#endif
#include <sys/sysctl.h>
@@ -74,7 +76,6 @@ enum {
- (void)windowDidChangeBackingProperties:(NSNotification *)notification;
@end
-
@implementation CocoaWindowDelegate : NSObject
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
{
@@ -85,6 +86,8 @@ enum {
- (void)windowDidBecomeKey:(NSNotification *)notification
{
systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
+ // work around for broken appswitching when combining cmd-tab and missioncontrol
+ [(NSWindow*)associatedWindow->getOSWindow() orderFrontRegardless];
}
- (void)windowDidResignKey:(NSNotification *)notification
@@ -168,6 +171,7 @@ enum {
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
- (GHOST_SystemCocoa*)systemCocoa;
@end
+
@implementation CocoaWindow
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
{
@@ -258,8 +262,6 @@ enum {
@end
-
-
#pragma mark NSOpenGLView subclass
//We need to subclass it in order to give Cocoa the feeling key events are trapped
@interface CocoaOpenGLView : NSOpenGLView <NSTextInput>
@@ -274,6 +276,7 @@ enum {
}
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
@end
+
@implementation CocoaOpenGLView
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
@@ -535,8 +538,6 @@ enum {
@end
#endif
-NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;
-
GHOST_WindowCocoa::GHOST_WindowCocoa(
GHOST_SystemCocoa *systemCocoa,
const STR_String& title,
@@ -548,13 +549,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
GHOST_TDrawingContextType type,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples
) :
- GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, false, numOfAASamples),
+ GHOST_Window(width, height, state, stereoVisual, false, numOfAASamples),
m_customCursor(0)
{
- NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40];
- NSOpenGLPixelFormat *pixelFormat = nil;
- int i;
-
m_systemCocoa = systemCocoa;
m_fullScreen = false;
m_immediateDraw = false;
@@ -572,8 +569,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
rect.size.height = height;
m_window = [[CocoaWindow alloc] initWithContentRect:rect
- styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
- backing:NSBackingStoreBuffered defer:NO];
+ styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
+ backing:NSBackingStoreBuffered defer:NO];
+
if (m_window == nil) {
[pool drain];
return;
@@ -586,104 +584,10 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
minSize.height = 240;
[m_window setContentMinSize:minSize];
- setTitle(title);
-
-
- // Pixel Format Attributes for the windowed NSOpenGLContext
- i=0;
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
-
- // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object's flushBuffer
- // needed for 'Draw Overlap' drawing method
- pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore;
-
- // Force software OpenGL, for debugging
- if (getenv("BLENDER_SOFTWAREGL")) {
- pixelFormatAttrsWindow[i++] = NSOpenGLPFARendererID;
- pixelFormatAttrsWindow[i++] = kCGLRendererAppleSWID;
- }
- else
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
-
- //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccumSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
-
- if (numOfAASamples > 0) {
- // Multisample anti-aliasing
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery;
- }
-
- pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
-
- pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
-
-
- //Fall back to no multisampling if Antialiasing init failed
- if (pixelFormat == nil) {
- i=0;
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
-
- // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object's flushBuffer
- // needed for 'Draw Overlap' drawing method
- pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore;
-
- // Force software OpenGL, for debugging
- if (getenv("BLENDER_SOFTWAREGL")) {
- pixelFormatAttrsWindow[i++] = NSOpenGLPFARendererID;
- pixelFormatAttrsWindow[i++] = kCGLRendererAppleSWID;
- }
- else
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
-
- //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccumSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
-
- pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
-
- pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
-
- }
-
- if (numOfAASamples > 0) { //Set m_numOfAASamples to the actual value
- GLint gli;
- [pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
- if (m_numOfAASamples != (GHOST_TUns16)gli) {
- m_numOfAASamples = (GHOST_TUns16)gli;
- printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples);
- }
- }
-
//Creates the OpenGL View inside the window
- m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
- pixelFormat:pixelFormat];
-
- [m_openGLView setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
-
- [pixelFormat release];
+ m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect];
- m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after
+ [m_openGLView setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
[m_window setContentView:m_openGLView];
[m_window setInitialFirstResponder:m_openGLView];
@@ -694,6 +598,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
updateDrawingContext();
activateDrawingContext();
+ // XXX jwilkins: This seems like it belongs in GHOST_ContextCGL, but probably not GHOST_ContextEGL
if (m_systemCocoa->m_nativePixel) {
if ([m_openGLView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
[m_openGLView setWantsBestResolutionOpenGLSurface:YES];
@@ -703,6 +608,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
}
}
+ setTitle(title);
+
m_tablet.Active = GHOST_kTabletModeNone;
CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];
@@ -717,7 +624,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
#endif
[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
- NSStringPboardType, NSTIFFPboardType, nil]];
+ NSStringPboardType, NSTIFFPboardType, nil]];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
if (state != GHOST_kWindowStateFullScreen) {
@@ -728,15 +635,18 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
if (state == GHOST_kWindowStateFullScreen)
setState(GHOST_kWindowStateFullScreen);
- //Starting with 10.9 (darwin 13.x.x), we always use Lion fullscreen, since it
- //now has proper multi-monitor support for fullscreen
- char darwin_ver[10];
- size_t len = sizeof(darwin_ver);
- sysctlbyname("kern.osrelease", &darwin_ver, &len, NULL, 0);
- if(darwin_ver[0] == '1' && darwin_ver[1] >= '3') {
+ // Starting with 10.9 (darwin 13.x.x), we can use Lion fullscreen,
+ // since it now has better multi-monitor support
+ // if the screens are spawned, additional screens get useless,
+ // so we only use lionStyleFullScreen when screens have separate spaces
+
+ if ([NSScreen respondsToSelector:@selector(screensHaveSeparateSpaces)] && [NSScreen screensHaveSeparateSpaces]) {
+ // implies we are on >= OSX 10.9
m_lionStyleFullScreen = true;
}
+ [NSApp activateIgnoringOtherApps:YES]; // raise application to front, important for new blender instance animation play case
+
[pool drain];
}
@@ -750,6 +660,8 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
m_customCursor = nil;
}
+ releaseNativeHandles();
+
[m_openGLView release];
if (m_window) {
@@ -774,7 +686,7 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
bool GHOST_WindowCocoa::getValid() const
{
- return (m_window != 0);
+ return GHOST_Window::getValid() && m_window != 0 && m_openGLView != 0;
}
void* GHOST_WindowCocoa::getOSWindow() const
@@ -877,7 +789,7 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
//Max window contents as screen size (excluding title bar...)
NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
rect = [m_window contentRectForFrameRect:[m_window frame]];
@@ -962,7 +874,12 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const
if (masks & NSFullScreenWindowMask) {
// Lion style fullscreen
- state = GHOST_kWindowStateFullScreen;
+ if (!m_immediateDraw) {
+ state = GHOST_kWindowStateFullScreen;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
}
else
#endif
@@ -976,7 +893,12 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const
state = GHOST_kWindowStateMaximized;
}
else {
- state = GHOST_kWindowStateNormal;
+ if (m_immediateDraw) {
+ state = GHOST_kWindowStateFullScreen;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
}
[pool drain];
return state;
@@ -1119,10 +1041,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
}
//Create a fullscreen borderless window
CocoaWindow *tmpWindow = [[CocoaWindow alloc]
- initWithContentRect:[[m_window screen] frame]
- styleMask:NSBorderlessWindowMask
- backing:NSBackingStoreBuffered
- defer:YES];
+ initWithContentRect:[[m_window screen] frame]
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
@@ -1189,10 +1111,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
}
//Create a fullscreen borderless window
CocoaWindow *tmpWindow = [[CocoaWindow alloc]
- initWithContentRect:[[m_window screen] frame]
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
- backing:NSBackingStoreBuffered
- defer:YES];
+ initWithContentRect:[[m_window screen] frame]
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
+ backing:NSBackingStoreBuffered
+ defer:YES];
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
@@ -1200,7 +1122,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
[tmpWindow setDelegate:[m_window delegate]];
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];
[tmpWindow registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
- NSStringPboardType, NSTIFFPboardType, nil]];
+ NSStringPboardType, NSTIFFPboardType, nil]];
//Forbid to resize the window below the blender defined minimum one
[tmpWindow setContentMinSize:NSMakeSize(320, 240)];
@@ -1266,131 +1188,95 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
#pragma mark Drawing context
-/*#define WAIT_FOR_VSYNC 1*/
-
-GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext flushBuffer];
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext update];
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
+GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
+{
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+#if !defined(WITH_GL_EGL)
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextCGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ GL_CONTEXT_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextCGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ CGL_CONTEXT_ES2_PROFILE_BIT_EXT,
+ 2, 0,
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextCGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
+#else
+# error
+#endif
-GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext makeCurrentContext];
-
- // Disable AA by default
- if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB);
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
+#else
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ 0, // profile bit
+ 2, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_ES_API);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#else
+# error
+#endif
-GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
-{
- GHOST_TSuccess success = GHOST_kFailure;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSOpenGLPixelFormat *pixelFormat;
- NSOpenGLContext *tmpOpenGLContext;
-
- /***** Multithreaded opengl code : uncomment for enabling
- CGLContextObj cglCtx;
- */
-
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- if (!getValid()) break;
-
- pixelFormat = [m_openGLView pixelFormat];
- tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
- shareContext:s_firstOpenGLcontext];
- if (tmpOpenGLContext == nil) {
- success = GHOST_kFailure;
- break;
- }
-
- //Switch openGL to multhreaded mode
- /******* Multithreaded opengl code : uncomment for enabling
- cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
- if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
- printf("\nSwitched openGL to multithreaded mode\n");
- */
-
- if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;
-#ifdef WAIT_FOR_VSYNC
- {
- GLint swapInt = 1;
- /* wait for vsync, to avoid tearing artifacts */
- [tmpOpenGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
- }
#endif
- [m_openGLView setOpenGLContext:tmpOpenGLContext];
- [tmpOpenGLContext setView:m_openGLView];
-
- m_openGLContext = tmpOpenGLContext;
- break;
-
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
-
- default:
- break;
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- [pool drain];
- return success;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- switch (m_drawingContextType) {
- case GHOST_kDrawingContextTypeOpenGL:
- if (m_openGLContext) {
- [m_openGLView clearGLContext];
- if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil;
- m_openGLContext = nil;
- }
- [pool drain];
- return GHOST_kSuccess;
- case GHOST_kDrawingContextTypeNone:
- [pool drain];
- return GHOST_kSuccess;
- break;
- default:
- [pool drain];
- return GHOST_kFailure;
- }
+ return NULL;
}
+#pragma mark invalidate
GHOST_TSuccess GHOST_WindowCocoa::invalidate()
{
@@ -1442,6 +1328,17 @@ GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress)
return GHOST_kSuccess;
}
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+static void postNotification()
+{
+ NSUserNotification *notification = [[NSUserNotification alloc] init];
+ notification.title = @"Blender progress notification";
+ notification.informativeText = @"Calculation is finished";
+ notification.soundName = NSUserNotificationDefaultSoundName;
+ [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
+ [notification release];
+}
+#endif
GHOST_TSuccess GHOST_WindowCocoa::endProgressBar()
{
@@ -1455,14 +1352,23 @@ GHOST_TSuccess GHOST_WindowCocoa::endProgressBar()
[[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[dockIcon unlockFocus];
[NSApp setApplicationIconImage:dockIcon];
+
+
+ // With OSX 10.8 and later, we can use notifications to inform the user when the progress reached 100%
+ // Atm. just fire this when the progressbar ends, the behavior is controlled in the NotificationCenter
+ // If Blender is not frontmost window, a message pops up with sound, in any case an entry in notifications
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+ if ([NSUserNotificationCenter respondsToSelector:@selector(defaultUserNotificationCenter)]) {
+ postNotification();
+ }
+#endif
+
[dockIcon release];
[pool drain];
return GHOST_kSuccess;
}
-
-
#pragma mark Cursor handling
void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
@@ -1650,15 +1556,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
- pixelsWide:sizex
- pixelsHigh:sizey
- bitsPerSample:1
- samplesPerPixel:2
- hasAlpha:YES
- isPlanar:YES
- colorSpaceName:NSDeviceWhiteColorSpace
+ pixelsWide:sizex
+ pixelsHigh:sizey
+ bitsPerSample:1
+ samplesPerPixel:2
+ hasAlpha:YES
+ isPlanar:YES
+ colorSpaceName:NSDeviceWhiteColorSpace
bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0))
- bitsPerPixel:1];
+ bitsPerPixel:1];
cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData];
@@ -1686,7 +1592,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
//foreground and background color parameter is not handled for now (10.6)
m_customCursor = [[NSCursor alloc] initWithImage:cursorImage
- hotSpot:hotSpotPoint];
+ hotSpot:hotSpotPoint];
[cursorImageRep release];
[cursorImage release];
diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp
index 1f20e01ca73..83490cecce5 100644
--- a/intern/ghost/intern/GHOST_WindowManager.cpp
+++ b/intern/ghost/intern/GHOST_WindowManager.cpp
@@ -121,7 +121,7 @@ GHOST_IWindow *GHOST_WindowManager::getFullScreenWindow(void) const
GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow *window,
- bool stereoVisual)
+ bool /*stereoVisual*/)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(window, "GHOST_WindowManager::beginFullScreen(): invalid window");
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
index 8297e4d24d2..e868a9b0416 100644
--- a/intern/ghost/intern/GHOST_WindowManager.h
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -55,7 +55,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_WindowManager();
+ ~GHOST_WindowManager();
/**
* Add a window to our list.
@@ -63,67 +63,67 @@ public:
* \param window Pointer to the window to be added.
* \return Indication of success.
*/
- virtual GHOST_TSuccess addWindow(GHOST_IWindow *window);
+ GHOST_TSuccess addWindow(GHOST_IWindow *window);
/**
* Remove a window from our list.
* \param window Pointer to the window to be removed.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeWindow(const GHOST_IWindow *window);
+ GHOST_TSuccess removeWindow(const GHOST_IWindow *window);
/**
* Returns whether the window is in our list.
* \param window Pointer to the window to query.
* \return A boolean indicator.
*/
- virtual bool getWindowFound(const GHOST_IWindow *window) const;
+ bool getWindowFound(const GHOST_IWindow *window) const;
/**
* Returns whether one of the windows is fullscreen.
* \return A boolean indicator.
*/
- virtual bool getFullScreen(void) const;
+ bool getFullScreen(void) const;
/**
* Returns pointer to the full-screen window.
* \return The full-screen window (NULL if not in full-screen).
*/
- virtual GHOST_IWindow *getFullScreenWindow(void) const;
+ GHOST_IWindow *getFullScreenWindow(void) const;
/**
* Activates fullscreen mode for a window.
* \param window The window displayed fullscreen.
* \return Indication of success.
*/
- virtual GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual);
+ GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual);
/**
* Closes fullscreen mode down.
* \return Indication of success.
*/
- virtual GHOST_TSuccess endFullScreen(void);
+ GHOST_TSuccess endFullScreen(void);
/**
* Sets new window as active window (the window receiving events).
* There can be only one window active which should be in the current window list.
* \param window The new active window.
*/
- virtual GHOST_TSuccess setActiveWindow(GHOST_IWindow *window);
+ GHOST_TSuccess setActiveWindow(GHOST_IWindow *window);
/**
* Returns the active window (the window receiving events).
* There can be only one window active which should be in the current window list.
* \return window The active window (or NULL if there is none).
*/
- virtual GHOST_IWindow *getActiveWindow(void) const;
+ GHOST_IWindow *getActiveWindow(void) const;
/**
* Set this window to be inactive (not receiving events).
* \param window The window to deactivate.
*/
- virtual void setWindowInactive(const GHOST_IWindow *window);
+ void setWindowInactive(const GHOST_IWindow *window);
/**
@@ -140,7 +140,7 @@ public:
* \param osWindow The OS window object/handle
* \return The associated window, null if none corresponds
*/
- virtual GHOST_IWindow *getWindowAssociatedWithOSWindow(void *osWindow);
+ GHOST_IWindow *getWindowAssociatedWithOSWindow(void *osWindow);
/**
* Return true if any windows has a modified status
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index c848d773bd6..80a1274a2a9 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -53,7 +53,7 @@ public:
const bool stereoVisual,
const GHOST_TUns16 numOfAASamples
) :
- GHOST_Window(width, height, state, type, stereoVisual, false, numOfAASamples),
+ GHOST_Window(width, height, state, stereoVisual, false, numOfAASamples),
m_system(system)
{
setTitle(title);
@@ -91,6 +91,12 @@ protected:
private:
GHOST_SystemNULL *m_system;
+
+ /**
+ * \param type The type of rendering context create.
+ * \return Indication of success.
+ */
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) {return NULL;}
};
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index 4a1086144f4..1335c38d977 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -26,10 +26,11 @@
#include "GHOST_WindowSDL.h"
#include "SDL_mouse.h"
-#include <GL/glew.h>
-#include <assert.h>
+#include "glew-mx.h"
+
+#include "GHOST_ContextSDL.h"
-static SDL_GLContext s_firstContext = NULL;
+#include <assert.h>
GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
const STR_String& title,
@@ -44,39 +45,29 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
const bool exclusive,
const GHOST_TUns16 numOfAASamples
)
- :
- GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
- m_system(system),
- m_invalid_window(false),
- m_sdl_custom_cursor(NULL)
+ : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
+ m_system(system),
+ m_valid_setup(false),
+ m_invalid_window(false),
+ m_sdl_custom_cursor(NULL)
{
- SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
-
- if (numOfAASamples) {
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, numOfAASamples);
- }
/* creating the window _must_ come after setting attributes */
- m_sdl_win = SDL_CreateWindow(title,
- left,
- top,
- width,
- height,
- SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
-
-
-
- m_sdl_glcontext = SDL_GL_CreateContext(m_sdl_win);
+ m_sdl_win = SDL_CreateWindow(
+ title,
+ left, top,
+ width, height,
+ SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
+
+ /* now set up the rendering context. */
+ if (setDrawingContextType(type) == GHOST_kSuccess) {
+ m_valid_setup = true;
+ GHOST_PRINT("Created window\n");
+ }
- //fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
- // theEvent->error_code, theEvent->request_code);
+ if (exclusive) {
+ SDL_RaiseWindow(m_sdl_win);
+ }
setTitle(title);
}
@@ -87,64 +78,38 @@ GHOST_WindowSDL::~GHOST_WindowSDL()
SDL_FreeCursor(m_sdl_custom_cursor);
}
- if (m_sdl_glcontext != s_firstContext) {
- SDL_GL_DeleteContext(m_sdl_glcontext);
- }
+ releaseNativeHandles();
SDL_DestroyWindow(m_sdl_win);
}
-GHOST_TSuccess
-GHOST_WindowSDL::installDrawingContext(GHOST_TDrawingContextType type)
+GHOST_Context *
+GHOST_WindowSDL::newDrawingContext(GHOST_TDrawingContextType type)
{
- // only support openGL for now.
- GHOST_TSuccess success;
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- m_sdl_glcontext = SDL_GL_CreateContext(m_sdl_win);
-
- if (m_sdl_glcontext != NULL) {
- if (!s_firstContext) {
- s_firstContext = m_sdl_glcontext;
- }
-
- success = (SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext) < 0) ?
- GHOST_kFailure : GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
-
- break;
-
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
-
- default:
- success = GHOST_kFailure;
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+ GHOST_Context *context = new GHOST_ContextSDL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_sdl_win,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_SDL_CONTEXT_FLAGS,
+ GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- return success;
+
+ return NULL;
}
GHOST_TSuccess
GHOST_WindowSDL::invalidate(void)
{
- // So the idea of this function is to generate an expose event
- // for the window.
- // Unfortunately X does not handle expose events for you and
- // it is the client's job to refresh the dirty part of the window.
- // We need to queue up invalidate calls and generate GHOST events
- // for them in the system.
-
- // We implement this by setting a boolean in this class to concatenate
- // all such calls into a single event for this window.
-
- // At the same time we queue the dirty windows in the system class
- // and generate events for them at the next processEvents call.
-
if (m_invalid_window == false) {
m_system->addDirtyWindow(this);
m_invalid_window = true;
@@ -153,52 +118,6 @@ GHOST_WindowSDL::invalidate(void)
return GHOST_kSuccess;
}
-
-GHOST_TSuccess
-GHOST_WindowSDL::swapBuffers()
-{
- if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
- SDL_GL_SwapWindow(m_sdl_win);
- return GHOST_kSuccess;
- }
- else {
- return GHOST_kFailure;
- }
-}
-
-
-GHOST_TSuccess
-GHOST_WindowSDL::activateDrawingContext()
-{
- if (m_sdl_glcontext != NULL) {
- int status = SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext);
- (void)status;
- /* Disable AA by default */
- if (m_numOfAASamples > 0) {
- glDisable(GL_MULTISAMPLE_ARB);
- }
- return GHOST_kSuccess;
- }
- return GHOST_kFailure;
-}
-
-
-GHOST_TSuccess
-GHOST_WindowSDL::removeDrawingContext()
-{
- GHOST_TSuccess success;
-
- if (m_sdl_glcontext != NULL) {
- SDL_GL_DeleteContext(m_sdl_glcontext);
- success = GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
- return success;
-}
-
-
GHOST_TSuccess
GHOST_WindowSDL::setState(GHOST_TWindowState state)
{
@@ -236,6 +155,12 @@ GHOST_WindowSDL::getState() const
return GHOST_kWindowStateNormal;
}
+bool
+GHOST_WindowSDL::
+getValid() const
+{
+ return GHOST_Window::getValid() && m_valid_setup;
+}
void
GHOST_WindowSDL::setTitle(const STR_String& title)
@@ -638,16 +563,3 @@ GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
SDL_ShowCursor(visible);
return GHOST_kSuccess;
}
-
-GHOST_TSuccess
-GHOST_WindowSDL::setSwapInterval(int interval)
-{
- SDL_GL_SetSwapInterval(interval);
- return GHOST_kSuccess;
-}
-
-int
-GHOST_WindowSDL::getSwapInterval()
-{
- return SDL_GL_GetSwapInterval();
-}
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index 0c11ce19b50..5f658e8ad01 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -30,6 +30,7 @@
#include "GHOST_Window.h"
#include "GHOST_SystemSDL.h"
+
#include <map>
extern "C" {
@@ -47,10 +48,10 @@ class GHOST_WindowSDL : public GHOST_Window
{
private:
GHOST_SystemSDL *m_system;
+ bool m_valid_setup;
bool m_invalid_window;
SDL_Window *m_sdl_win;
- SDL_GLContext m_sdl_glcontext;
SDL_Cursor *m_sdl_custom_cursor;
public:
@@ -93,17 +94,18 @@ public:
m_invalid_window = false;
}
- bool getValid() const
- {
- return (m_sdl_win != NULL);
- }
+ bool getValid() const;
void getWindowBounds(GHOST_Rect& bounds) const;
void getClientBounds(GHOST_Rect& bounds) const;
protected:
- GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
- GHOST_TSuccess removeDrawingContext();
+
+ /**
+ * \param type The type of rendering context create.
+ * \return Indication of success.
+ */
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
GHOST_TSuccess
setWindowCursorGrab(GHOST_TGrabCursorMode mode);
@@ -151,12 +153,6 @@ protected:
GHOST_TInt32& outX, GHOST_TInt32& outY) const;
GHOST_TSuccess
- swapBuffers();
-
- GHOST_TSuccess
- activateDrawingContext();
-
- GHOST_TSuccess
setState(GHOST_TWindowState state);
GHOST_TWindowState
@@ -172,9 +168,6 @@ protected:
GHOST_TSuccess beginFullScreen() const { return GHOST_kFailure; }
GHOST_TSuccess endFullScreen() const { return GHOST_kFailure; }
-
- GHOST_TSuccess setSwapInterval(int interval);
- int getSwapInterval();
};
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 8e7e824186c..54689a96b66 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -29,90 +29,40 @@
* \ingroup GHOST
*/
-#include <string.h>
+#define _USE_MATH_DEFINES
+
#include "GHOST_WindowWin32.h"
#include "GHOST_SystemWin32.h"
#include "GHOST_DropTargetWin32.h"
+#include "GHOST_ContextNone.h"
#include "utfconv.h"
#include "utf_winfunc.h"
-// Need glew for some defines
-#include <GL/glew.h>
-#include <GL/wglew.h>
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextWGL.h"
+#endif
+
+
#include <math.h>
+#include <string.h>
+#include <assert.h>
-// MSVC6 still doesn't define M_PI
-#ifndef M_PI
-# define M_PI 3.1415926536
-#endif
-// Some more multisample defines
-#define WGL_SAMPLE_BUFFERS_ARB 0x2041
-#define WGL_SAMPLES_ARB 0x2042
const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
const int GHOST_WindowWin32::s_maxTitleLength = 128;
-HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL;
-HDC GHOST_WindowWin32::s_firstHDC = NULL;
-static int WeightPixelFormat(PIXELFORMATDESCRIPTOR &pfd);
-static int EnumPixelFormats(HDC hdc);
-/*
- * Color and depth bit values are not to be trusted.
- * For instance, on TNT2:
- * When the screen color depth is set to 16 bit, we get 5 color bits
- * and 16 depth bits.
- * When the screen color depth is set to 32 bit, we get 8 color bits
- * and 24 depth bits.
- * Just to be safe, we request high quality settings.
- */
-static PIXELFORMATDESCRIPTOR sPreferredFormat = {
- sizeof(PIXELFORMATDESCRIPTOR), /* size */
- 1, /* version */
- PFD_SUPPORT_OPENGL |
- PFD_DRAW_TO_WINDOW |
- PFD_SWAP_COPY | /* support swap copy */
- PFD_DOUBLEBUFFER, /* support double-buffering */
- PFD_TYPE_RGBA, /* color type */
- 32, /* prefered color depth */
- 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
- 0, /* no alpha buffer */
- 0, /* alpha bits (ignored) */
- 0, /* no accumulation buffer */
- 0, 0, 0, 0, /* accum bits (ignored) */
- 32, /* depth buffer */
- 0, /* no stencil buffer */
- 0, /* no auxiliary buffers */
- PFD_MAIN_PLANE, /* main layer */
- 0, /* reserved */
- 0, 0, 0 /* no layer, visible, damage masks */
-};
-
-/* Intel videocards don't work fine with multiple contexts and
- * have to share the same context for all windows.
- * But if we just share context for all windows it could work incorrect
- * with multiple videocards configuration. Suppose, that Intel videocards
- * can't be in multiple-devices configuration. */
-static int is_crappy_intel_card(void)
-{
- static short is_crappy = -1;
-
- if (is_crappy == -1) {
- const char *vendor = (const char *)glGetString(GL_VENDOR);
- is_crappy = (strstr(vendor, "Intel") != NULL);
- }
- return is_crappy;
-}
/* force NVidia Optimus to used dedicated graphics */
extern "C" {
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
-GHOST_WindowWin32::GHOST_WindowWin32(
- GHOST_SystemWin32 *system,
+GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
const STR_String &title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -120,17 +70,15 @@ GHOST_WindowWin32::GHOST_WindowWin32(
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
- const GHOST_TUns16 numOfAASamples,
+ bool wantStereoVisual, bool warnOld,
+ GHOST_TUns16 wantNumOfAASamples,
GHOST_TEmbedderWindowID parentwindowhwnd,
- GHOST_TSuccess msEnabled,
- int msPixelFormat)
- : GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone,
- stereoVisual, false, numOfAASamples),
+ bool is_debug)
+ : GHOST_Window(width, height, state,
+ wantStereoVisual, false, wantNumOfAASamples),
m_inLiveResize(false),
m_system(system),
m_hDC(0),
- m_hGlRc(0),
m_hasMouseCaptured(false),
m_hasGrabMouse(false),
m_nPressedButtons(0),
@@ -139,19 +87,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(
m_tabletData(NULL),
m_tablet(0),
m_maxPressure(0),
- m_multisample(numOfAASamples),
- m_multisampleEnabled(msEnabled),
- m_msPixelFormat(msPixelFormat),
- //For recreation
- m_title(title),
- m_left(left),
- m_top(top),
- m_width(width),
- m_height(height),
m_normal_state(GHOST_kWindowStateNormal),
- m_stereo(stereoVisual),
- m_nextWindow(NULL),
- m_parentWindowHwnd(parentwindowhwnd)
+ m_parentWindowHwnd(parentwindowhwnd),
+ m_debug_context(is_debug)
{
OSVERSIONINFOEX versionInfo;
bool hasMinVersionForTaskbar = false;
@@ -160,6 +98,13 @@ GHOST_WindowWin32::GHOST_WindowWin32(
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+#if !defined(WITH_GL_EGL)
+ if (!warnOld)
+ GHOST_ContextWGL::unSetWarningOld();
+#else
+ (void)(warnOld);
+#endif
+
if (!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
@@ -286,35 +231,32 @@ GHOST_WindowWin32::GHOST_WindowWin32(
// Store the device context
m_hDC = ::GetDC(m_hWnd);
- if (!s_firstHDC) {
- s_firstHDC = m_hDC;
- }
-
- // Show the window
- int nCmdShow;
- switch (state) {
- case GHOST_kWindowStateMaximized:
- nCmdShow = SW_SHOWMAXIMIZED;
- break;
- case GHOST_kWindowStateMinimized:
- nCmdShow = SW_SHOWMINIMIZED;
- break;
- case GHOST_kWindowStateNormal:
- default:
- nCmdShow = SW_SHOWNORMAL;
- break;
- }
- GHOST_TSuccess success;
- success = setDrawingContextType(type);
+ GHOST_TSuccess success = setDrawingContextType(type);
if (success) {
+ // Show the window
+ int nCmdShow;
+ switch (state) {
+ case GHOST_kWindowStateMaximized:
+ nCmdShow = SW_SHOWMAXIMIZED;
+ break;
+ case GHOST_kWindowStateMinimized:
+ nCmdShow = SW_SHOWMINIMIZED;
+ break;
+ case GHOST_kWindowStateNormal:
+ default:
+ nCmdShow = SW_SHOWNORMAL;
+ break;
+ }
+
::ShowWindow(m_hWnd, nCmdShow);
// Force an initial paint of the window
::UpdateWindow(m_hWnd);
}
else {
//invalidate the window
- m_hWnd = 0;
+ ::DestroyWindow(m_hWnd);
+ m_hWnd = NULL;
}
}
@@ -415,14 +357,8 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_customCursor = NULL;
}
- ::wglMakeCurrent(NULL, NULL);
- m_multisampleEnabled = GHOST_kFailure;
- m_multisample = 0;
- setDrawingContextType(GHOST_kDrawingContextTypeNone);
-
- if (m_hDC && m_hDC != s_firstHDC) {
+ if (m_hWnd != NULL && m_hDC != NULL && releaseNativeHandles()) {
::ReleaseDC(m_hWnd, m_hDC);
- m_hDC = 0;
}
if (m_hWnd) {
@@ -438,14 +374,9 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
}
}
-GHOST_Window *GHOST_WindowWin32::getNextWindow()
-{
- return m_nextWindow;
-}
-
bool GHOST_WindowWin32::getValid() const
{
- return m_hWnd != 0;
+ return GHOST_Window::getValid() && m_hWnd != 0 && m_hDC != 0;
}
HWND GHOST_WindowWin32::getHWND() const
@@ -678,49 +609,6 @@ GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order)
}
-GHOST_TSuccess GHOST_WindowWin32::swapBuffers()
-{
- HDC hDC = m_hDC;
-
- if (is_crappy_intel_card())
- hDC = ::wglGetCurrentDC();
-
- return ::SwapBuffers(hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
-}
-
-GHOST_TSuccess GHOST_WindowWin32::setSwapInterval(int interval)
-{
- if (!WGL_EXT_swap_control)
- return GHOST_kFailure;
- return wglSwapIntervalEXT(interval) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
-}
-
-int GHOST_WindowWin32::getSwapInterval()
-{
- if (WGL_EXT_swap_control)
- return wglGetSwapIntervalEXT();
-
- return 0;
-}
-
-GHOST_TSuccess GHOST_WindowWin32::activateDrawingContext()
-{
- GHOST_TSuccess success;
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_hDC && m_hGlRc) {
- success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kSuccess;
- }
- return success;
-}
-
-
GHOST_TSuccess GHOST_WindowWin32::invalidate()
{
GHOST_TSuccess success;
@@ -733,257 +621,93 @@ GHOST_TSuccess GHOST_WindowWin32::invalidate()
return success;
}
-GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd)
-{
- int pixelFormat;
- bool success = FALSE;
- UINT numFormats;
- HDC hDC = GetDC(getHWND());
- float fAttributes[] = {0, 0};
- UINT nMaxFormats = 1;
-
- // The attributes to look for
- int iAttributes[] = {
- WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
- WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
- WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
- WGL_COLOR_BITS_ARB, pfd.cColorBits,
- WGL_DEPTH_BITS_ARB, pfd.cDepthBits,
-#ifdef GHOST_OPENGL_ALPHA
- WGL_ALPHA_BITS_ARB, pfd.cAlphaBits,
-#endif
- WGL_STENCIL_BITS_ARB, pfd.cStencilBits,
- WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
- WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
- WGL_SAMPLES_ARB, m_multisample,
- 0, 0
- };
-
- // Get the function
- PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
-
- if (!wglChoosePixelFormatARB) {
- m_multisampleEnabled = GHOST_kFailure;
- return GHOST_kFailure;
- }
-
- // iAttributes[17] is the initial multisample. If not valid try to use the closest valid value under it.
- while (iAttributes[17] > 0) {
- // See if the format is valid
- success = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, nMaxFormats, &pixelFormat, &numFormats);
- GHOST_PRINTF("WGL_SAMPLES_ARB = %i --> success = %i, %i formats\n", iAttributes[17], success, numFormats);
-
- if (success && numFormats >= 1 && m_multisampleEnabled == GHOST_kFailure) {
- GHOST_PRINTF("valid pixel format with %i multisamples\n", iAttributes[17]);
- m_multisampleEnabled = GHOST_kSuccess;
- m_msPixelFormat = pixelFormat;
- }
- iAttributes[17] -= 1;
- success = GHOST_kFailure;
- }
- if (m_multisampleEnabled == GHOST_kSuccess) {
- return GHOST_kSuccess;
- }
- GHOST_PRINT("no available pixel format\n");
- return GHOST_kFailure;
-}
-GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type)
+GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType type)
{
- GHOST_TSuccess success;
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- {
- // If this window has multisample enabled, use the supplied format
- if (m_multisampleEnabled)
- {
- if (SetPixelFormat(m_hDC, m_msPixelFormat, &sPreferredFormat) == FALSE)
- {
- success = GHOST_kFailure;
- break;
- }
-
- // Create the context
- m_hGlRc = ::wglCreateContext(m_hDC);
- if (m_hGlRc) {
- if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
- if (s_firsthGLRc) {
- if (is_crappy_intel_card()) {
- if (::wglMakeCurrent(NULL, NULL) == TRUE) {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = s_firsthGLRc;
- }
- else {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = NULL;
- }
- }
- else {
- ::wglCopyContext(s_firsthGLRc, m_hGlRc, GL_ALL_ATTRIB_BITS);
- ::wglShareLists(s_firsthGLRc, m_hGlRc);
- }
- }
- else {
- s_firsthGLRc = m_hGlRc;
- }
-
- if (m_hGlRc) {
- success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
-
- if (success == GHOST_kFailure) {
- printf("Failed to get a context....\n");
- }
- }
- else {
- if (m_stereoVisual)
- sPreferredFormat.dwFlags |= PFD_STEREO;
-
- // Attempt to match device context pixel format to the preferred format
- int iPixelFormat = EnumPixelFormats(m_hDC);
- if (iPixelFormat == 0) {
- success = GHOST_kFailure;
- break;
- }
- if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) {
- success = GHOST_kFailure;
- break;
- }
- // For debugging only: retrieve the pixel format chosen
- PIXELFORMATDESCRIPTOR preferredFormat;
- ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat);
-
- // Create the context
- m_hGlRc = ::wglCreateContext(m_hDC);
- if (m_hGlRc) {
- if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
- if (s_firsthGLRc) {
- if (is_crappy_intel_card()) {
- if (::wglMakeCurrent(NULL, NULL) == TRUE) {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = s_firsthGLRc;
- }
- else {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = NULL;
- }
- }
- else {
- ::wglShareLists(s_firsthGLRc, m_hGlRc);
- }
- }
- else {
- s_firsthGLRc = m_hGlRc;
- }
-
- if (m_hGlRc) {
- success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
-
- if (success == GHOST_kFailure) {
- printf("Failed to get a context....\n");
- }
-
- // Attempt to enable multisample
- if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled && !is_crappy_intel_card())
- {
- success = initMultisample(preferredFormat);
-
- if (success)
- {
-
- // Make sure we don't screw up the context
- if (m_hGlRc == s_firsthGLRc)
- s_firsthGLRc = NULL;
- m_drawingContextType = GHOST_kDrawingContextTypeOpenGL;
- removeDrawingContext();
-
- // Create a new window
- GHOST_TWindowState new_state = getState();
-
- m_nextWindow = new GHOST_WindowWin32((GHOST_SystemWin32 *)GHOST_ISystem::getSystem(),
- m_title,
- m_left,
- m_top,
- m_width,
- m_height,
- new_state,
- type,
- m_stereo,
- m_multisample,
- m_parentWindowHwnd,
- m_multisampleEnabled,
- m_msPixelFormat);
-
- // Return failure so we can trash this window.
- success = GHOST_kFailure;
- break;
- }
- else {
- m_multisampleEnabled = GHOST_kSuccess;
- printf("Multisample failed to initialize\n");
- success = GHOST_kSuccess;
- }
- }
- }
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+#if !defined(WITH_GL_EGL)
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ WGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_WGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
+ 2, 0,
+ GHOST_OPENGL_WGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_WGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+#else
+# error
+#endif
- }
- break;
+#else
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ 0, // profile bit
+ 2, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_ES_API);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#else
+# error
+#endif
- default:
- success = GHOST_kFailure;
+#endif
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- return success;
-}
-GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext()
-{
- GHOST_TSuccess success;
- switch (m_drawingContextType) {
- case GHOST_kDrawingContextTypeOpenGL:
- // we shouldn't remove the drawing context if it's the first OpenGL context
- // If we do, we get corrupted drawing. See #19997
- if (m_hGlRc && m_hGlRc != s_firsthGLRc) {
- success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- m_hGlRc = 0;
- }
- else {
- success = GHOST_kFailure;
- }
- break;
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
- default:
- success = GHOST_kFailure;
- }
- return success;
+ return NULL;
}
void GHOST_WindowWin32::lostMouseCapture()
@@ -1334,93 +1058,16 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
return GHOST_kFailure;
}
-/* Ron Fosner's code for weighting pixel formats and forcing software.
- * See http://www.opengl.org/resources/faq/technical/weight.cpp */
-static int WeightPixelFormat(PIXELFORMATDESCRIPTOR &pfd)
+#ifdef WITH_INPUT_IME
+void GHOST_WindowWin32::beginIME(GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed)
{
- int weight = 0;
-
- /* assume desktop color depth is 32 bits per pixel */
-
- /* cull unusable pixel formats */
- /* if no formats can be found, can we determine why it was rejected? */
- if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
- !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
- !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
- (pfd.cDepthBits <= 8) ||
- !(pfd.iPixelType == PFD_TYPE_RGBA))
- {
- return 0;
- }
-
- weight = 1; /* it's usable */
-
- /* the bigger the depth buffer the better */
- /* give no weight to a 16-bit depth buffer, because those are crap */
- weight += pfd.cDepthBits - 16;
-
- weight += pfd.cColorBits - 8;
-
-#ifdef GHOST_OPENGL_ALPHA
- if (pfd.cAlphaBits > 0)
- weight ++;
-#endif
-
- /* want swap copy capability -- it matters a lot */
- if (pfd.dwFlags & PFD_SWAP_COPY) weight += 16;
-
- /* but if it's a generic (not accelerated) view, it's really bad */
- if (pfd.dwFlags & PFD_GENERIC_FORMAT) weight /= 10;
-
- return weight;
+ m_imeImput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), (bool)completed);
}
-/* A modification of Ron Fosner's replacement for ChoosePixelFormat */
-/* returns 0 on error, else returns the pixel format number to be used */
-static int EnumPixelFormats(HDC hdc)
+
+void GHOST_WindowWin32::endIME()
{
- int iPixelFormat;
- int i, n, w, weight = 0;
- PIXELFORMATDESCRIPTOR pfd;
-
- /* we need a device context to do anything */
- if (!hdc) return 0;
-
- iPixelFormat = 1; /* careful! PFD numbers are 1 based, not zero based */
-
- /* obtain detailed information about
- * the device context's first pixel format */
- n = 1 + ::DescribePixelFormat(hdc, iPixelFormat,
- sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-
- /* choose a pixel format using the useless Windows function in case
- * we come up empty handed */
- iPixelFormat = ::ChoosePixelFormat(hdc, &sPreferredFormat);
-
- if (!iPixelFormat) return 0; /* couldn't find one to use */
-
- for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
- ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- w = WeightPixelFormat(pfd);
- // be strict on stereo
- if (!((sPreferredFormat.dwFlags ^ pfd.dwFlags) & PFD_STEREO)) {
- if (w > weight) {
- weight = w;
- iPixelFormat = i;
- }
- }
- }
- if (weight == 0) {
- // we could find the correct stereo setting, just find any suitable format
- for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
- ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- w = WeightPixelFormat(pfd);
- if (w > weight) {
- weight = w;
- iPixelFormat = i;
- }
- }
- }
- return iPixelFormat;
+ m_imeImput.EndIME(m_hWnd);
}
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index cb6c09b335c..3666fa753f3 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -39,13 +39,9 @@
#include "GHOST_Window.h"
#include "GHOST_TaskbarWin32.h"
-
-#ifndef __MINGW64__
-#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#ifdef WITH_INPUT_IME
+# include "GHOST_ImeWin32.h"
#endif
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
#include <wintab.h>
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
@@ -80,11 +76,11 @@ public:
* \param height The height the window.
* \param state The state the window is initially opened with.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param wantStereoVisual Stereo visual for quad buffered stereo.
+ * \param wantNumOfAASamples Number of samples used for AA (zero if no AA)
+ * \param parentWindowHwnd
*/
- GHOST_WindowWin32(
- GHOST_SystemWin32 *system,
+ GHOST_WindowWin32(GHOST_SystemWin32 *system,
const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -92,88 +88,80 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
- const bool stereoVisual = false,
- const GHOST_TUns16 numOfAASamples = 0,
+ bool wantStereoVisual = false,
+ bool warnOld = false,
+ GHOST_TUns16 wantNumOfAASamples = 0,
GHOST_TEmbedderWindowID parentWindowHwnd = 0,
- GHOST_TSuccess msEnabled = GHOST_kFailure,
- int msPixelFormat = 0
- );
+ bool is_debug = false);
/**
* Destructor.
* Closes the window and disposes resources allocated.
*/
- virtual ~GHOST_WindowWin32();
-
- /**
- * Returns the window to replace this one if it's getting replaced
- * \return The window replacing this one.
- */
-
- GHOST_Window *getNextWindow();
+ ~GHOST_WindowWin32();
/**
* Returns indication as to whether the window is valid.
* \return The validity of the window.
*/
- virtual bool getValid() const;
+ bool getValid() const;
/**
* Access to the handle of the window.
* \return The handle of the window.
*/
- virtual HWND getHWND() const;
+ HWND getHWND() const;
/**
* Sets the title displayed in the title bar.
* \param title The title to display in the title bar.
*/
- virtual void setTitle(const STR_String& title);
+ void setTitle(const STR_String& title);
/**
* Returns the title displayed in the title bar.
* \param title The title displayed in the title bar.
*/
- virtual void getTitle(STR_String& title) const;
+ void getTitle(STR_String& title) const;
/**
* Returns the window rectangle dimensions.
* The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
* \param bounds The bounding rectangle of the window.
*/
- virtual void getWindowBounds(GHOST_Rect& bounds) const;
+ void getWindowBounds(GHOST_Rect& bounds) const;
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
* \param bounds The bounding rectangle of the client area of the window.
*/
- virtual void getClientBounds(GHOST_Rect& bounds) const;
+ void getClientBounds(GHOST_Rect& bounds) const;
/**
* Resizes client rectangle width.
* \param width The new width of the client area of the window.
*/
- virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
/**
* Resizes client rectangle height.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
/**
* Resizes client rectangle.
* \param width The new width of the client area of the window.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
/**
* Returns the state of the window (normal, minimized, maximized).
* \return The state of the window.
*/
- virtual GHOST_TWindowState getState() const;
+ GHOST_TWindowState getState() const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -182,7 +170,7 @@ public:
* \param outX The x-coordinate in the client rectangle.
* \param outY The y-coordinate in the client rectangle.
*/
- virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -191,70 +179,38 @@ public:
* \param outX The x-coordinate on the screen.
* \param outY The y-coordinate on the screen.
*/
- virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Sets the state of the window (normal, minimized, maximized).
* \param state The state of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setState(GHOST_TWindowState state);
+ GHOST_TSuccess setState(GHOST_TWindowState state);
/**
* Sets the order of the window (bottom, top).
* \param order The order of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
-
- /**
- * Swaps front and back buffers of a window.
- * \return Indication of success.
- */
- virtual GHOST_TSuccess swapBuffers();
-
- /**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess setSwapInterval(int interval);
-
- /**
- * Gets the current swap interval for swapBuffers.
- * \return An integer.
- */
- virtual int getSwapInterval();
-
- /**
- * Activates the drawing context of this window.
- * \return Indication of success.
- */
- virtual GHOST_TSuccess activateDrawingContext();
+ GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
/**
* Invalidates the contents of this window.
*/
- virtual GHOST_TSuccess invalidate();
+ GHOST_TSuccess invalidate();
/**
* Sets the progress bar value displayed in the window/application icon
* \param progress The progress %
*/
- virtual GHOST_TSuccess setProgressBar(float progress);
+ GHOST_TSuccess setProgressBar(float progress);
/**
* Hides the progress bar in the icon
*/
- virtual GHOST_TSuccess endProgressBar();
+ GHOST_TSuccess endProgressBar();
- /**
- * Returns the name of the window class.
- * \return The name of the window class.
- */
- static const wchar_t *getWindowClassName() {
- return s_windowClassName;
- }
/**
* Register a mouse click event (should be called
@@ -298,50 +254,53 @@ public:
/** if the window currently resizing */
bool m_inLiveResize;
-protected:
- GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd);
+#ifdef WITH_INPUT_IME
+ GHOST_ImeWin32 *getImeInput() {return &m_imeImput;}
- /**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication of success.
- */
- virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
+ void beginIME(
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int completed);
+
+ void endIME();
+#endif /* WITH_INPUT_IME */
+
+private:
/**
- * Removes the current drawing context.
+ * \param type The type of rendering context create.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeDrawingContext();
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
/**
* Sets the cursor visibility on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
+ GHOST_TSuccess setWindowCursorVisibility(bool visible);
/**
* Sets the cursor grab on the window using native window system calls.
* Using registerMouseClickEvent.
* \param mode GHOST_TGrabCursorMode.
*/
- virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
+ GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
+ GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
GHOST_TUns8 mask[16][2],
int hotX, int hotY);
- virtual GHOST_TSuccess setWindowCustomCursorShape(
+ GHOST_TSuccess setWindowCustomCursorShape(
GHOST_TUns8 *bitmap,
GHOST_TUns8 *mask,
int sizex,
@@ -360,12 +319,7 @@ protected:
HWND m_hWnd;
/** Device context handle. */
HDC m_hDC;
- /** OpenGL rendering context. */
- HGLRC m_hGlRc;
- /** The first created OpenGL context (for sharing display lists) */
- static HGLRC s_firsthGLRc;
- /** The first created device context handle. */
- static HDC s_firstHDC;
+
/** Flag for if window has captured the mouse */
bool m_hasMouseCaptured;
/** Flag if an operator grabs the mouse with WM_cursor_grab_enable/ungrab()
@@ -393,29 +347,16 @@ protected:
LONG m_maxPressure;
LONG m_maxAzimuth, m_maxAltitude;
- /** Preferred number of samples */
- GHOST_TUns16 m_multisample;
-
- /** Check if multisample is supported */
- GHOST_TSuccess m_multisampleEnabled;
-
- /** The pixelFormat to use for multisample */
- int m_msPixelFormat;
-
- /** We need to following to recreate the window */
- const STR_String& m_title;
- GHOST_TInt32 m_left;
- GHOST_TInt32 m_top;
- GHOST_TUns32 m_width;
- GHOST_TUns32 m_height;
GHOST_TWindowState m_normal_state;
- bool m_stereo;
-
- /** The GHOST_System passes this to wm if this window is being replaced */
- GHOST_Window *m_nextWindow;
/** Hwnd to parent window */
GHOST_TEmbedderWindowID m_parentWindowHwnd;
+
+#ifdef WITH_INPUT_IME
+ /** Handle input method editors event */
+ GHOST_ImeWin32 m_imeImput;
+#endif
+ bool m_debug_context;
};
#endif // __GHOST_WINDOWWIN32_H__
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 86c940b7396..fe99a8bee1e 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -29,8 +29,10 @@
* \ingroup GHOST
*/
-
-#include <GL/glxew.h>
+/* For standard X11 cursors */
+#include <X11/cursorfont.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
#include "GHOST_WindowX11.h"
#include "GHOST_SystemX11.h"
@@ -38,20 +40,25 @@
#include "GHOST_Debug.h"
#ifdef WITH_XDND
-#include "GHOST_DropTargetX11.h"
+# include "GHOST_DropTargetX11.h"
#endif
-/* For standard X11 cursors */
-#include <X11/cursorfont.h>
-#include <X11/Xatom.h>
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextGLX.h"
+#endif
#if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
-#include <strings.h>
+# include <strings.h>
#endif
#include <cstring>
#include <cstdio>
+/* gethostname */
+#include <unistd.h>
+
#include <algorithm>
#include <string>
@@ -65,16 +72,11 @@ typedef struct {
long input_mode;
} MotifWmHints;
-// Workaround for MESA bug #54080
-// https://bugs.freedesktop.org/show_bug.cgi?id=54080()
-#define SWAP_INTERVALS_WORKAROUND
-
-#ifdef SWAP_INTERVALS_WORKAROUND
-static bool g_swap_interval_disabled = false;
-#endif // SWAP_INTERVALS_WORKAROUND
-
#define MWM_HINTS_DECORATIONS (1L << 1)
+#ifndef HOST_NAME_MAX
+# define HOST_NAME_MAX 64
+#endif
// #define GHOST_X11_GRAB
@@ -156,14 +158,79 @@ static long BLENDER_ICON_48x48x32[] = {
4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
};
+static XVisualInfo *x11_visualinfo_from_glx(
+ Display *display,
+ bool stereoVisual, GHOST_TUns16 *r_numOfAASamples)
+{
+ XVisualInfo *visualInfo = NULL;
+ GHOST_TUns16 numOfAASamples = *r_numOfAASamples;
+ GHOST_TUns16 actualSamples;
+
+ /* Set up the minimum attributes that we require and see if
+ * X can find us a visual matching those requirements. */
+ int glx_major, glx_minor; /* GLX version: major.minor */
+
+ if (!glXQueryVersion(display, &glx_major, &glx_minor)) {
+ fprintf(stderr,
+ "%s:%d: X11 glXQueryVersion() failed, "
+ "verify working openGL system!\n",
+ __FILE__, __LINE__);
+
+ return NULL;
+ }
+
+ /* GLX >= 1.4 required for multi-sample */
+ if ((glx_major > 1) || (glx_major == 1 && glx_minor >= 4)) {
+ actualSamples = numOfAASamples;
+ }
+ else {
+ numOfAASamples = 0;
+ actualSamples = 0;
+ }
+
+ /* Find the display with highest samples, starting at level requested */
+ for (;;) {
+ int glx_attribs[64];
+
+ GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, false);
+
+ visualInfo = 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 (visualInfo != NULL) {
+ if (actualSamples < numOfAASamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ numOfAASamples, actualSamples);
+ }
+ break;
+ }
+
+ if (actualSamples == 0) {
+ /* All options exhausted, cannot continue */
+ fprintf(stderr,
+ "%s:%d: X11 glXChooseVisual() failed, "
+ "verify working openGL system!\n",
+ __FILE__, __LINE__);
+
+ return NULL;
+ }
+ else {
+ --actualSamples;
+ }
+ }
+
+ *r_numOfAASamples = actualSamples;
-GLXContext GHOST_WindowX11::s_firstContext = NULL;
+ return visualInfo;
+}
GHOST_WindowX11::
-GHOST_WindowX11(
- GHOST_SystemX11 *system,
+GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
- const STR_String& title,
+ const STR_String &title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -173,109 +240,51 @@ GHOST_WindowX11(
GHOST_TDrawingContextType type,
const bool stereoVisual,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples)
- : GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
- m_context(NULL),
+ const GHOST_TUns16 numOfAASamples, const bool is_debug)
+ : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
m_display(display),
+ m_visualInfo(NULL),
m_normal_state(GHOST_kWindowStateNormal),
m_system(system),
- m_valid_setup(false),
m_invalid_window(false),
m_empty_cursor(None),
m_custom_cursor(None),
- m_visible_cursor(None)
+ m_visible_cursor(None),
+#ifdef WITH_XDND
+ m_dropTarget(NULL),
+#endif
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+ m_xic(NULL),
+#endif
+ m_valid_setup(false),
+ m_is_debug_context(is_debug)
{
-
- /* Set up the minimum attributes that we require and see if
- * X can find us a visual matching those requirements. */
-
- int attributes[40], i, samples;
- int natom;
- int glxVersionMajor, glxVersionMinor; /* As in GLX major.minor */
-
- m_visual = NULL;
-
- if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) {
- printf("%s:%d: X11 glXQueryVersion() failed, verify working openGL system!\n", __FILE__, __LINE__);
-
- /* exit if this is the first window */
- if (s_firstContext == NULL) {
- printf("initial window could not find the GLX extension, exit!\n");
- exit(1);
- }
-
- return;
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+ m_visualInfo = x11_visualinfo_from_glx(m_display, stereoVisual, &m_wantNumOfAASamples);
}
-
- /* Find the display with highest samples, starting at level requested */
- for (samples = m_numOfAASamples; samples >= 0; samples--) {
- i = 0; /* Reusing attributes array, so reset counter */
-
- if (m_stereoVisual)
- attributes[i++] = GLX_STEREO;
-
- attributes[i++] = GLX_RGBA;
- attributes[i++] = GLX_DOUBLEBUFFER;
- attributes[i++] = GLX_RED_SIZE; attributes[i++] = 1;
- attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1;
- attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1;
- attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1;
-#ifdef GHOST_OPENGL_ALPHA
- attributes[i++] = GLX_ALPHA_SIZE; attributes[i++] = 1;
-#endif
- /* GLX >= 1.4 required for multi-sample */
- if (samples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) {
- attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1;
- attributes[i++] = GLX_SAMPLES; attributes[i++] = samples;
- }
- attributes[i] = None;
-
- m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes);
-
- /* Any sample level or even zero, which means oversampling disabled, is good
- * but we need a valid visual to continue */
- if (m_visual == NULL) {
- if (samples == 0) {
- /* All options exhausted, cannot continue */
- printf("%s:%d: X11 glXChooseVisual() failed, verify working openGL system!\n", __FILE__, __LINE__);
-
- if (s_firstContext == NULL) {
- printf("initial window could not find the GLX extension, exit!\n");
- exit(1);
- }
-
- return;
- }
- }
- else {
- if (m_numOfAASamples && (m_numOfAASamples > samples)) {
- printf("%s:%d: oversampling requested %i but using %i samples\n",
- __FILE__, __LINE__, m_numOfAASamples, samples);
- }
- break;
- }
+ else {
+ XVisualInfo tmp = {0};
+ int n;
+ m_visualInfo = XGetVisualInfo(m_display, 0, &tmp, &n);
}
- /* Create a bunch of attributes needed to create an X window. */
-
+ /* caller needs to check 'getValid()' */
+ if (m_visualInfo == NULL) {
+ fprintf(stderr, "initial window could not find the GLX extension\n");
+ return;
+ }
- /* First create a colormap for the window and visual.
- * This seems pretty much a legacy feature as we are in rgba mode anyway. */
+ unsigned int xattributes_valuemask = 0;
XSetWindowAttributes xattributes;
- unsigned int xattributes_valuemask = (CWBorderPixel | CWColormap | CWEventMask);
memset(&xattributes, 0, sizeof(xattributes));
- xattributes.colormap = XCreateColormap(m_display,
- RootWindow(m_display, m_visual->screen),
- m_visual->visual,
- AllocNone
- );
-
+ xattributes_valuemask |= CWBorderPixel;
xattributes.border_pixel = 0;
/* Specify which events we are interested in hearing. */
+ xattributes_valuemask |= CWEventMask;
xattributes.event_mask =
ExposureMask | StructureNotifyMask |
KeyPressMask | KeyReleaseMask |
@@ -289,24 +298,28 @@ GHOST_WindowX11(
xattributes.override_redirect = True;
}
+ xattributes_valuemask |= CWColormap;
+ xattributes.colormap = XCreateColormap(
+ m_display,
+ RootWindow(m_display, m_visualInfo->screen),
+ m_visualInfo->visual,
+ AllocNone
+ );
+
/* create the window! */
if (parentWindow == 0) {
- m_window = XCreateWindow(m_display,
- RootWindow(m_display, m_visual->screen),
- left,
- top,
- width,
- height,
- 0, /* no border. */
- m_visual->depth,
- InputOutput,
- m_visual->visual,
- xattributes_valuemask,
- &xattributes
- );
+ m_window = XCreateWindow(
+ m_display,
+ RootWindow(m_display, m_visualInfo->screen),
+ left, top, width, height,
+ 0, /* no border. */
+ m_visualInfo->depth,
+ InputOutput,
+ m_visualInfo->visual,
+ xattributes_valuemask,
+ &xattributes);
}
else {
-
Window root_return;
int x_return, y_return;
unsigned int w_return, h_return, border_w_return, depth_return;
@@ -320,19 +333,16 @@ GHOST_WindowX11(
height = h_return;
- m_window = XCreateWindow(m_display,
- parentWindow, /* reparent against embedder */
- left,
- top,
- width,
- height,
- 0, /* no border. */
- m_visual->depth,
- InputOutput,
- m_visual->visual,
- xattributes_valuemask,
- &xattributes
- );
+ m_window = XCreateWindow(
+ m_display,
+ parentWindow, /* reparent against embedder */
+ left, top, width, height,
+ 0, /* no border. */
+ m_visualInfo->depth,
+ InputOutput,
+ m_visualInfo->visual,
+ xattributes_valuemask,
+ &xattributes);
XSelectInput(m_display, parentWindow, SubstructureNotifyMask);
@@ -384,36 +394,43 @@ GHOST_WindowX11(
m_post_state = GHOST_kWindowStateNormal;
}
+
/* Create some hints for the window manager on how
* we want this window treated. */
+ {
+ XSizeHints *xsizehints = XAllocSizeHints();
+ xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
+ xsizehints->x = left;
+ xsizehints->y = top;
+ xsizehints->width = width;
+ xsizehints->height = height;
+ xsizehints->min_width = 320; /* size hints, could be made apart of the ghost api */
+ xsizehints->min_height = 240; /* limits are also arbitrary, but should not allow 1x1 window */
+ xsizehints->max_width = 65535;
+ xsizehints->max_height = 65535;
+ XSetWMNormalHints(m_display, m_window, xsizehints);
+ XFree(xsizehints);
+ }
+
+
+ /* XClassHint, title */
+ {
+ XClassHint *xclasshint = XAllocClassHint();
+ const int len = title.Length() + 1;
+ char *wmclass = (char *)malloc(sizeof(char) * len);
+ memcpy(wmclass, title.ReadPtr(), len * sizeof(char));
+ xclasshint->res_name = wmclass;
+ xclasshint->res_class = wmclass;
+ XSetClassHint(m_display, m_window, xclasshint);
+ free(wmclass);
+ XFree(xclasshint);
+ }
- XSizeHints *xsizehints = XAllocSizeHints();
- xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
- xsizehints->x = left;
- xsizehints->y = top;
- xsizehints->width = width;
- xsizehints->height = height;
- xsizehints->min_width = 320; /* size hints, could be made apart of the ghost api */
- xsizehints->min_height = 240; /* limits are also arbitrary, but should not allow 1x1 window */
- xsizehints->max_width = 65535;
- xsizehints->max_height = 65535;
- XSetWMNormalHints(m_display, m_window, xsizehints);
- XFree(xsizehints);
-
- XClassHint *xclasshint = XAllocClassHint();
- const int len = title.Length() + 1;
- char *wmclass = (char *)malloc(sizeof(char) * len);
- strncpy(wmclass, (const char *)title, sizeof(char) * len);
- xclasshint->res_name = wmclass;
- xclasshint->res_class = wmclass;
- XSetClassHint(m_display, m_window, xclasshint);
- free(wmclass);
- XFree(xclasshint);
/* The basic for a good ICCCM "work" */
if (m_system->m_atom.WM_PROTOCOLS) {
Atom atoms[2];
- natom = 0;
+ int natom = 0;
if (m_system->m_atom.WM_DELETE_WINDOW) {
atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
@@ -431,27 +448,48 @@ GHOST_WindowX11(
}
}
-#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- m_xic = NULL;
-#endif
-
/* Set the window hints */
- XWMHints *xwmhints = XAllocWMHints();
- xwmhints->initial_state = NormalState;
- xwmhints->input = True;
- xwmhints->flags = InputHint | StateHint;
- XSetWMHints(display, m_window, xwmhints);
- XFree(xwmhints);
- /* done setting the hints */
+ {
+ XWMHints *xwmhints = XAllocWMHints();
+ xwmhints->initial_state = NormalState;
+ xwmhints->input = True;
+ xwmhints->flags = InputHint | StateHint;
+ XSetWMHints(display, m_window, xwmhints);
+ XFree(xwmhints);
+ }
+
/* set the icon */
- Atom _NET_WM_ICON = XInternAtom(m_display, "_NET_WM_ICON", False);
- XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
- 32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
- BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
- /* done setting the icon */
+ {
+ Atom _NET_WM_ICON = XInternAtom(m_display, "_NET_WM_ICON", False);
+ XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
+ 32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
+ BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
+ }
- setTitle(title);
+ /* set the process ID (_NET_WM_PID) */
+ {
+ Atom _NET_WM_PID = XInternAtom(m_display, "_NET_WM_PID", False);
+ pid_t pid = getpid();
+ XChangeProperty(m_display, m_window, _NET_WM_PID, XA_CARDINAL,
+ 32, PropModeReplace, (unsigned char *)&pid, 1);
+ }
+
+
+ /* set the hostname (WM_CLIENT_MACHINE) */
+ {
+ char hostname[HOST_NAME_MAX];
+ char *text_array[1];
+ XTextProperty text_prop;
+
+ gethostname(hostname, sizeof(hostname));
+ hostname[sizeof(hostname) - 1] = '\0';
+ text_array[0] = hostname;
+
+ XStringListToTextProperty(text_array, 1, &text_prop);
+ XSetWMClientMachine(m_display, m_window, &text_prop);
+ XFree(text_prop.value);
+ }
#ifdef WITH_X11_XINPUT
initXInputDevices();
@@ -459,12 +497,15 @@ GHOST_WindowX11(
m_tabletData.Active = GHOST_kTabletModeNone;
#endif
+
/* now set up the rendering context. */
- if (installDrawingContext(type) == GHOST_kSuccess) {
+ if (setDrawingContextType(type) == GHOST_kSuccess) {
m_valid_setup = true;
GHOST_PRINT("Created window\n");
}
+ setTitle(title);
+
if (exclusive) {
XMapRaised(m_display, m_window);
}
@@ -477,7 +518,7 @@ GHOST_WindowX11(
}
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
-static void destroyICCallback(XIC xic, XPointer ptr, XPointer data)
+static void destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
{
GHOST_PRINT("XIM input context destroyed\n");
@@ -525,23 +566,32 @@ void GHOST_WindowX11::initXInputDevices()
if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
if (version->present) {
GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
- XEventClass xevents[10], ev;
+ XEventClass xevents[8], ev;
int dcount = 0;
+ /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
+ * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
+ * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
+ */
+
if (xtablet.StylusDevice) {
DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
if (ev) xevents[dcount++] = ev;
+ DeviceButtonPress(xtablet.StylusDevice, xtablet.PressEvent, ev);
+ if (ev) xevents[dcount++] = ev;
ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
if (ev) xevents[dcount++] = ev;
ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
if (ev) xevents[dcount++] = ev;
}
if (xtablet.EraserDevice) {
- DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEvent, ev);
+ DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEventEraser, ev);
if (ev) xevents[dcount++] = ev;
- ProximityIn(xtablet.EraserDevice, xtablet.ProxInEvent, ev);
+ DeviceButtonPress(xtablet.EraserDevice, xtablet.PressEventEraser, ev);
if (ev) xevents[dcount++] = ev;
- ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEvent, ev);
+ ProximityIn(xtablet.EraserDevice, xtablet.ProxInEventEraser, ev);
+ if (ev) xevents[dcount++] = ev;
+ ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEventEraser, ev);
if (ev) xevents[dcount++] = ev;
}
@@ -564,7 +614,7 @@ bool
GHOST_WindowX11::
getValid() const
{
- return m_valid_setup;
+ return GHOST_Window::getValid() && m_valid_setup;
}
void
@@ -685,7 +735,7 @@ screenToClient(
Window temp;
XTranslateCoordinates(m_display,
- RootWindow(m_display, m_visual->screen),
+ RootWindow(m_display, m_visualInfo->screen),
m_window,
inX, inY,
&ax, &ay,
@@ -708,7 +758,7 @@ clientToScreen(
XTranslateCoordinates(
m_display,
m_window,
- RootWindow(m_display, m_visual->screen),
+ RootWindow(m_display, m_visualInfo->screen),
inX, inY,
&ax, &ay,
&temp);
@@ -731,7 +781,7 @@ void GHOST_WindowX11::icccmSetState(int state)
xev.xclient.format = 32;
xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
xev.xclient.data.l[0] = state;
- XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
}
@@ -777,7 +827,7 @@ void GHOST_WindowX11::netwmMaximized(bool set)
xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
- XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
@@ -833,7 +883,7 @@ void GHOST_WindowX11::netwmFullScreen(bool set)
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
- XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
@@ -1052,7 +1102,7 @@ setOrder(
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
- root = RootWindow(m_display, m_visual->screen),
+ root = RootWindow(m_display, m_visualInfo->screen),
eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
XSendEvent(m_display, root, False, eventmask, &xev);
@@ -1079,34 +1129,6 @@ setOrder(
GHOST_TSuccess
GHOST_WindowX11::
-swapBuffers()
-{
- if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
- glXSwapBuffers(m_display, m_window);
- return GHOST_kSuccess;
- }
- else {
- return GHOST_kFailure;
- }
-}
-
-GHOST_TSuccess
-GHOST_WindowX11::
-activateDrawingContext()
-{
- if (m_context != NULL) {
- glXMakeCurrent(m_display, m_window, m_context);
- /* Disable AA by default */
- if (m_numOfAASamples > 0) {
- glDisable(GL_MULTISAMPLE_ARB);
- }
- return GHOST_kSuccess;
- }
- return GHOST_kFailure;
-}
-
-GHOST_TSuccess
-GHOST_WindowX11::
invalidate()
{
/* So the idea of this function is to generate an expose event
@@ -1151,15 +1173,6 @@ validate()
GHOST_WindowX11::
~GHOST_WindowX11()
{
- static Atom Primary_atom, Clipboard_atom;
- Window p_owner, c_owner;
- /*Change the owner of the Atoms to None if we are the owner*/
- Primary_atom = XInternAtom(m_display, "PRIMARY", False);
- Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
-
- p_owner = XGetSelectionOwner(m_display, Primary_atom);
- c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
-
std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
for (; it != m_standard_cursors.end(); ++it) {
XFreeCursor(m_display, it->second);
@@ -1172,17 +1185,29 @@ GHOST_WindowX11::
XFreeCursor(m_display, m_custom_cursor);
}
- if (m_context != s_firstContext) {
- glXDestroyContext(m_display, m_context);
+ if (m_valid_setup) {
+ static Atom Primary_atom, Clipboard_atom;
+ Window p_owner, c_owner;
+ /*Change the owner of the Atoms to None if we are the owner*/
+ Primary_atom = XInternAtom(m_display, "PRIMARY", False);
+ Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
+
+
+ p_owner = XGetSelectionOwner(m_display, Primary_atom);
+ c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
+
+ if (p_owner == m_window) {
+ XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
+ }
+ if (c_owner == m_window) {
+ XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
+ }
}
- if (p_owner == m_window) {
- XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
- }
- if (c_owner == m_window) {
- XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
+ if (m_visualInfo) {
+ XFree(m_visualInfo);
}
-
+
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
if (m_xic) {
XDestroyIC(m_xic);
@@ -1193,88 +1218,103 @@ GHOST_WindowX11::
delete m_dropTarget;
#endif
- XDestroyWindow(m_display, m_window);
- XFree(m_visual);
-}
-
+ releaseNativeHandles();
+ if (m_valid_setup) {
+ XDestroyWindow(m_display, m_window);
+ }
+}
-/**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication as to whether installation has succeeded.
- */
-GHOST_TSuccess
-GHOST_WindowX11::
-installDrawingContext(
- GHOST_TDrawingContextType type)
+GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
{
- /* only support openGL for now. */
- GHOST_TSuccess success;
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- {
-#ifdef WITH_X11_XINPUT
- /* use our own event handlers to avoid exiting blender,
- * this would happen for eg:
- * if you open blender, unplug a tablet, then open a new window. */
- XErrorHandler old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
- XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+#if !defined(WITH_GL_EGL)
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ 3, 2,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
+ 2, 0,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+#else
+# error
#endif
- m_context = glXCreateContext(m_display, m_visual, s_firstContext, True);
- if (m_context != NULL) {
- if (!s_firstContext) {
- s_firstContext = m_context;
- }
- glXMakeCurrent(m_display, m_window, m_context);
- glClearColor(0.447, 0.447, 0.447, 0);
- glClear(GL_COLOR_BUFFER_BIT);
- success = GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
+#else
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ 0, // profile bit
+ 2, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_ES_API);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#else
+# error
+#endif
-#ifdef WITH_X11_XINPUT
- /* Restore handler */
- (void) XSetErrorHandler(old_handler);
- (void) XSetIOErrorHandler(old_handler_io);
#endif
- break;
- }
- case GHOST_kDrawingContextTypeNone:
- {
- success = GHOST_kSuccess;
- break;
- }
- default:
- success = GHOST_kFailure;
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- return success;
-}
-
-
-
-/**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
- */
-GHOST_TSuccess
-GHOST_WindowX11::
-removeDrawingContext()
-{
- GHOST_TSuccess success;
- if (m_context != NULL) {
- glXDestroyContext(m_display, m_context);
- success = GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
- return success;
+ return NULL;
}
@@ -1336,13 +1376,13 @@ getEmptyCursor(
) {
if (!m_empty_cursor) {
Pixmap blank;
- XColor dummy;
+ XColor dummy = {0};
char data[1] = {0};
/* make a blank cursor */
blank = XCreateBitmapFromData(
m_display,
- RootWindow(m_display, DefaultScreen(m_display)),
+ RootWindow(m_display, m_visualInfo->screen),
data, 1, 1
);
@@ -1458,10 +1498,10 @@ setWindowCustomCursorShape(
int sizey,
int hotX,
int hotY,
- int fg_color,
- int bg_color)
+ int /*fg_color*/,
+ int /*bg_color*/)
{
- Colormap colormap = DefaultColormap(m_display, DefaultScreen(m_display));
+ Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
Pixmap bitmap_pix, mask_pix;
XColor fg, bg;
@@ -1530,72 +1570,3 @@ endFullScreen() const
return GHOST_kSuccess;
}
-
-GHOST_TSuccess
-GHOST_WindowX11::
-setSwapInterval(int interval) {
- if (!GLX_EXT_swap_control || !glXSwapIntervalEXT
-#ifdef SWAP_INTERVALS_WORKAROUND
- || g_swap_interval_disabled
-#endif // SWAP_INTERVALS_WORKAROUND
- )
- {
- return GHOST_kFailure;
- }
- glXSwapIntervalEXT(m_display, m_window, interval);
- return GHOST_kSuccess;
-}
-
-#ifdef SWAP_INTERVALS_WORKAROUND
-static int QueryDrawable_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
-{
- fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
- theEvent->error_code, theEvent->request_code);
- if (!g_swap_interval_disabled) {
- fprintf(stderr, "Disabling SWAP INTERVALS extension\n");
- g_swap_interval_disabled = true;
- }
- return 0;
-}
-
-static int QueryDrawable_ApplicationIOErrorHandler(Display *display)
-{
- fprintf(stderr, "Ignoring Xlib error: error IO\n");
- if (!g_swap_interval_disabled) {
- fprintf(stderr, "Disabling SWAP INTERVALS extension\n");
- g_swap_interval_disabled = true;
- }
- return 0;
-}
-#endif // SWAP_INTERVALS_WORKAROUND
-
-int
-GHOST_WindowX11::
-getSwapInterval() {
- if (GLX_EXT_swap_control) {
-#ifdef SWAP_INTERVALS_WORKAROUND
- /* XXX: Current MESA driver will give GLXBadDrawable for all
- * the glXQueryDrawable requests with direct contexts.
- *
- * To prevent crashes and unexpected behaviors, we will
- * disable swap intervals extension if query fails here.
- * (because if we will override interval without having
- * old value we couldn't restore it properly).
- */
- XErrorHandler old_handler = XSetErrorHandler(QueryDrawable_ApplicationErrorHandler);
- XIOErrorHandler old_handler_io = XSetIOErrorHandler(QueryDrawable_ApplicationIOErrorHandler);
-#endif // SWAP_INTERVALS_WORKAROUND
-
- unsigned int value = 0;
- glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &value);
-
-#ifdef SWAP_INTERVALS_WORKAROUND
- /* Restore handler */
- (void) XSetErrorHandler(old_handler);
- (void) XSetIOErrorHandler(old_handler_io);
-#endif // SWAP_INTERVALS_WORKAROUND
-
- return (int)value;
- }
- return 0;
-}
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index faaa05efe82..5beb7b43032 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -35,7 +35,7 @@
#include "GHOST_Window.h"
#include <X11/Xlib.h>
-#include <GL/glx.h>
+#include <X11/Xutil.h>
// For tablets
#ifdef WITH_X11_XINPUT
# include <X11/extensions/XInput.h>
@@ -88,7 +88,8 @@ public:
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0
+ const GHOST_TUns16 numOfAASamples = 0,
+ const bool is_debug = false
);
bool
@@ -160,13 +161,6 @@ public:
);
GHOST_TSuccess
- swapBuffers(
- );
-
- GHOST_TSuccess
- activateDrawingContext(
- );
- GHOST_TSuccess
invalidate(
);
@@ -235,37 +229,12 @@ public:
GHOST_TSuccess endFullScreen() const;
- /**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess setSwapInterval(int interval);
-
- /**
- * Gets the current swap interval for swapBuffers.
- * \return An integer.
- */
- virtual int getSwapInterval();
-
protected:
/**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication as to whether installation has succeeded.
+ * \param type The type of rendering context create.
+ * \return Indication of success.
*/
- GHOST_TSuccess
- installDrawingContext(
- GHOST_TDrawingContextType type
- );
-
- /**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
- */
- GHOST_TSuccess
- removeDrawingContext(
- );
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
/**
* Sets the cursor visibility on the window using
@@ -279,7 +248,6 @@ protected:
/**
* Sets the cursor grab on the window using
* native window system calls.
- * \param warp Only used when grab is enabled, hides the mouse and allows dragging outside the screen.
*/
GHOST_TSuccess
setWindowCursorGrab(
@@ -350,21 +318,15 @@ private:
void initXInputDevices();
#endif
- GLXContext m_context;
Window m_window;
- Display *m_display;
- XVisualInfo *m_visual;
- GHOST_TWindowState m_normal_state;
+ Display *m_display;
+ XVisualInfo *m_visualInfo;
- /** The first created OpenGL context (for sharing display lists) */
- static GLXContext s_firstContext;
+ GHOST_TWindowState m_normal_state;
- /// A pointer to the typed system class.
-
+ /** A pointer to the typed system class. */
GHOST_SystemX11 *m_system;
- bool m_valid_setup;
-
/** Used to concatenate calls to invalidate() on this window. */
bool m_invalid_window;
@@ -392,6 +354,9 @@ private:
XIC m_xic;
#endif
+ bool m_valid_setup;
+ bool m_is_debug_context;
+
void icccmSetState(int state);
int icccmGetState() const;