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/GHOST_WindowWin32.cpp')
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp311
1 files changed, 216 insertions, 95 deletions
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index b3a262537fb..21d1ec0c5b1 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -17,8 +17,8 @@
* All rights reserved.
*/
-/** \file ghost/intern/GHOST_WindowWin32.cpp
- * \ingroup GHOST
+/** \file
+ * \ingroup GHOST
*/
#define _USE_MATH_DEFINES
@@ -39,11 +39,14 @@
#include <Dwmapi.h>
#endif
+#include <windowsx.h>
#include <math.h>
#include <string.h>
#include <assert.h>
-
+#ifndef GET_POINTERID_WPARAM
+#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam))
+#endif // GET_POINTERID_WPARAM
const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
const int GHOST_WindowWin32::s_maxTitleLength = 128;
@@ -80,7 +83,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_customCursor(0),
m_wantAlphaBackground(alphaBackground),
m_normal_state(GHOST_kWindowStateNormal),
- m_user32(NULL),
+ m_user32(NULL),
+ m_fpGetPointerInfo(NULL),
+ m_fpGetPointerPenInfo(NULL),
+ m_fpGetPointerTouchInfo(NULL),
m_parentWindowHwnd(parentwindowhwnd),
m_debug_context(is_debug)
{
@@ -102,7 +108,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
// MSVC 2012+ returns bogus values from GetSystemMetrics, bug in Windows
// http://connect.microsoft.com/VisualStudio/feedback/details/753224/regression-getsystemmetrics-delivers-different-values
RECT cxrect = {0, 0, 0, 0};
- AdjustWindowRectEx(&cxrect, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_THICKFRAME | WS_DLGFRAME, FALSE, 0);
+ AdjustWindowRectEx(&cxrect, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_THICKFRAME | WS_DLGFRAME, FALSE, 0);
int cxsizeframe = abs(cxrect.bottom);
int cysizeframe = abs(cxrect.left);
@@ -173,7 +179,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_hWnd = ::CreateWindowW(
s_windowClassName, // pointer to registered class name
title_16, // pointer to window name
- WS_POPUP | WS_MAXIMIZE, // window style
+ WS_MAXIMIZE, // window style
left, // horizontal position of window
top, // vertical position of window
width, // window width
@@ -276,6 +282,13 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
RegisterRawInputDevices(&device, 1, sizeof(device));
}
+ // Initialize Windows Ink
+ if (m_user32) {
+ m_fpGetPointerInfo = (GHOST_WIN32_GetPointerInfo) ::GetProcAddress(m_user32, "GetPointerInfo");
+ m_fpGetPointerPenInfo = (GHOST_WIN32_GetPointerPenInfo) ::GetProcAddress(m_user32, "GetPointerPenInfo");
+ m_fpGetPointerTouchInfo = (GHOST_WIN32_GetPointerTouchInfo) ::GetProcAddress(m_user32, "GetPointerTouchInfo");
+ }
+
// Initialize Wintab
m_wintab.handle = ::LoadLibrary("Wintab32.dll");
if (m_wintab.handle) {
@@ -345,6 +358,7 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
if (m_Bar) {
m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
m_Bar->Release();
+ m_Bar = NULL;
}
if (m_wintab.handle) {
@@ -356,6 +370,14 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
memset(&m_wintab, 0, sizeof(m_wintab));
}
+ if (m_user32) {
+ FreeLibrary(m_user32);
+ m_user32 = NULL;
+ m_fpGetPointerInfo = NULL;
+ m_fpGetPointerPenInfo = NULL;
+ m_fpGetPointerTouchInfo = NULL;
+ }
+
if (m_customCursor) {
DestroyCursor(m_customCursor);
m_customCursor = NULL;
@@ -363,6 +385,7 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
if (m_hWnd != NULL && m_hDC != NULL && releaseNativeHandles()) {
::ReleaseDC(m_hWnd, m_hDC);
+ m_hDC = NULL;
}
if (m_hWnd) {
@@ -371,16 +394,12 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
RevokeDragDrop(m_hWnd);
// Release our reference of the DropTarget and it will delete itself eventually.
m_dropTarget->Release();
+ m_dropTarget = NULL;
}
::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, NULL);
::DestroyWindow(m_hWnd);
m_hWnd = 0;
}
-
- if (m_user32) {
- FreeLibrary(m_user32);
- m_user32 = NULL;
- }
}
bool GHOST_WindowWin32::getValid() const
@@ -526,7 +545,7 @@ GHOST_TWindowState GHOST_WindowWin32::getState() const
}
else if (::IsZoomed(m_hWnd)) {
LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
- if ((result & (WS_POPUP | WS_MAXIMIZE)) != (WS_POPUP | WS_MAXIMIZE))
+ if ((result & (WS_DLGFRAME | WS_MAXIMIZE)) == (WS_DLGFRAME | WS_MAXIMIZE))
state = GHOST_kWindowStateMaximized;
else
state = GHOST_kWindowStateFullScreen;
@@ -584,7 +603,7 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
wp.showCmd = SW_SHOWMAXIMIZED;
wp.ptMaxPosition.x = 0;
wp.ptMaxPosition.y = 0;
- ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_MAXIMIZE);
+ ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_MAXIMIZE);
break;
case GHOST_kWindowStateEmbedded:
::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD);
@@ -642,101 +661,80 @@ GHOST_TSuccess GHOST_WindowWin32::invalidate()
GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType type)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
-#if !defined(WITH_GL_EGL)
+ GHOST_Context *context;
#if defined(WITH_GL_PROFILE_CORE)
- GHOST_Context *context = new GHOST_ContextWGL(
- m_wantStereoVisual,
- m_wantAlphaBackground,
- m_wantNumOfAASamples,
- m_hWnd,
- m_hDC,
- WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
- 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_wantAlphaBackground,
- 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);
+ /* - AMD and Intel give us exactly this version
+ * - NVIDIA gives at least this version <-- desired behavior
+ * So we ask for 4.5, 4.4 ... 3.3 in descending order to get the best version on the user's system. */
+ for (int minor = 5; minor >= 0; --minor) {
+ context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantAlphaBackground,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
+ 4, minor,
+ (m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ else {
+ delete context;
+ }
+ }
+ context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantAlphaBackground,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
+ 3, 3,
+ (m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ else {
+ MessageBox(
+ m_hWnd,
+ "A graphics card and driver with support for OpenGL 3.3 or higher is required.\n"
+ "Installing the latest driver for your graphics card may resolve the issue.\n\n"
+ "The program will now close.",
+ "Blender - Unsupported Graphics Card or Driver",
+ MB_OK | MB_ICONERROR);
+ delete context;
+ exit(0);
+ }
+
#elif defined(WITH_GL_PROFILE_COMPAT)
- GHOST_Context *context = new GHOST_ContextWGL(
+ // ask for 2.1 context, driver gives any GL version >= 2.1 (hopefully the latest compatibility profile)
+ // 2.1 ignores the profile bit & is incompatible with core profile
+ context = new GHOST_ContextWGL(
m_wantStereoVisual,
m_wantAlphaBackground,
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
-#if 1
- 0, // profile bit
- 2, 1, // GL version requested
-#else
- // switch to this for Blender 2.8 development
- WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
- 3, 2,
-#endif
+ 0, // no profile bit
+ 2, 1,
(m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
-#else
-# error
-#endif
-
-#else
-
-#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,
-#if 1
- 0, // profile bit
- 2, 1, // GL version requested
-#else
- // switch to this for Blender 2.8 development
- EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
- 3, 2,
-#endif
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
-# error
-#endif
-#endif
- if (context->initializeDrawingContext())
+ if (context->initializeDrawingContext()) {
return context;
- else
+ }
+ else {
delete context;
+ }
+#else
+# error // must specify either core or compat at build time
+#endif
}
return NULL;
@@ -880,8 +878,101 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur
return GHOST_kSuccess;
}
+GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(GHOST_PointerInfoWin32 *pointerInfo, WPARAM wParam, LPARAM lParam)
+{
+ ZeroMemory(pointerInfo, sizeof(GHOST_PointerInfoWin32));
+
+ // Obtain the basic information from the event
+ pointerInfo->pointerId = GET_POINTERID_WPARAM(wParam);
+ pointerInfo->isInContact = IS_POINTER_INCONTACT_WPARAM(wParam);
+ pointerInfo->isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
+
+ // Obtain more accurate and predicted information from the Pointer API
+ POINTER_INFO pointerApiInfo;
+ if (!(m_fpGetPointerInfo && m_fpGetPointerInfo(pointerInfo->pointerId, &pointerApiInfo))) {
+ return GHOST_kFailure;
+ }
+
+ pointerInfo->hasButtonMask = GHOST_kSuccess;
+ switch (pointerApiInfo.ButtonChangeType) {
+ case POINTER_CHANGE_FIRSTBUTTON_DOWN:
+ case POINTER_CHANGE_FIRSTBUTTON_UP:
+ pointerInfo->buttonMask = GHOST_kButtonMaskLeft;
+ break;
+ case POINTER_CHANGE_SECONDBUTTON_DOWN:
+ case POINTER_CHANGE_SECONDBUTTON_UP:
+ pointerInfo->buttonMask = GHOST_kButtonMaskRight;
+ break;
+ case POINTER_CHANGE_THIRDBUTTON_DOWN:
+ case POINTER_CHANGE_THIRDBUTTON_UP:
+ pointerInfo->buttonMask = GHOST_kButtonMaskMiddle;
+ break;
+ case POINTER_CHANGE_FOURTHBUTTON_DOWN:
+ case POINTER_CHANGE_FOURTHBUTTON_UP:
+ pointerInfo->buttonMask = GHOST_kButtonMaskButton4;
+ break;
+ case POINTER_CHANGE_FIFTHBUTTON_DOWN:
+ case POINTER_CHANGE_FIFTHBUTTON_UP:
+ pointerInfo->buttonMask = GHOST_kButtonMaskButton5;
+ break;
+ default:
+ pointerInfo->hasButtonMask = GHOST_kFailure;
+ break;
+ }
+
+ pointerInfo->pixelLocation = pointerApiInfo.ptPixelLocation;
+ pointerInfo->tabletData.Active = GHOST_kTabletModeNone;
+ pointerInfo->tabletData.Pressure = 1.0f;
+ pointerInfo->tabletData.Xtilt = 0.0f;
+ pointerInfo->tabletData.Ytilt = 0.0f;
+
+ if (pointerApiInfo.pointerType != PT_PEN) {
+ return GHOST_kFailure;
+ }
+
+ POINTER_PEN_INFO pointerPenInfo;
+ if (m_fpGetPointerPenInfo && m_fpGetPointerPenInfo(pointerInfo->pointerId, &pointerPenInfo)) {
+ pointerInfo->tabletData.Active = GHOST_kTabletModeStylus;
+
+ if (pointerPenInfo.penMask & PEN_MASK_PRESSURE) {
+ pointerInfo->tabletData.Pressure = pointerPenInfo.pressure / 1024.0f;
+ }
+
+ if (pointerPenInfo.penFlags & PEN_FLAG_ERASER) {
+ pointerInfo->tabletData.Active = GHOST_kTabletModeEraser;
+ }
+
+ if (pointerPenInfo.penFlags & PEN_MASK_TILT_X) {
+ pointerInfo->tabletData.Xtilt = fmin(fabs(pointerPenInfo.tiltX / 90), 1.0f);
+ }
+
+ if (pointerPenInfo.penFlags & PEN_MASK_TILT_Y) {
+ pointerInfo->tabletData.Ytilt = fmin(fabs(pointerPenInfo.tiltY / 90), 1.0f);
+ }
+ }
+
+ return GHOST_kSuccess;
+}
+
+void GHOST_WindowWin32::setTabletData(GHOST_TabletData * pTabletData)
+{
+ if (pTabletData) {
+ m_tabletData = *pTabletData;
+ }
+ else {
+ m_tabletData.Active = GHOST_kTabletModeNone;
+ m_tabletData.Pressure = 1.0f;
+ m_tabletData.Xtilt = 0.0f;
+ m_tabletData.Ytilt = 0.0f;
+ }
+}
+
void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state)
{
+ if (!useTabletAPI(GHOST_kTabletWintab)) {
+ return;
+ }
+
if (m_wintab.enable && m_wintab.tablet) {
m_wintab.enable(m_wintab.tablet, state);
@@ -891,8 +982,28 @@ void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state)
}
}
+bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
+{
+ if (m_system->getTabletAPI() == api) {
+ return true;
+ }
+ else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
+ if (m_wintab.tablet)
+ return api == GHOST_kTabletWintab;
+ else
+ return api == GHOST_kTabletNative;
+ }
+ else {
+ return false;
+ }
+}
+
void GHOST_WindowWin32::processWin32TabletInitEvent()
{
+ if (!useTabletAPI(GHOST_kTabletWintab)) {
+ return;
+ }
+
// Let's see if we can initialize tablet here
if (m_wintab.info && m_wintab.tablet) {
AXIS Pressure, Orientation[3]; /* The maximum tablet size */
@@ -917,10 +1028,16 @@ void GHOST_WindowWin32::processWin32TabletInitEvent()
m_tabletData.Active = GHOST_kTabletModeNone;
}
+
+ m_tabletData.Active = GHOST_kTabletModeNone;
}
void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
{
+ if (!useTabletAPI(GHOST_kTabletWintab)) {
+ return;
+ }
+
if (m_wintab.packet && m_wintab.tablet) {
PACKET pkt;
if (m_wintab.packet((HCTX)lParam, wParam, &pkt)) {
@@ -986,6 +1103,10 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
void GHOST_WindowWin32::bringTabletContextToFront()
{
+ if (!useTabletAPI(GHOST_kTabletWintab)) {
+ return;
+ }
+
if (m_wintab.overlap && m_wintab.tablet) {
m_wintab.overlap(m_wintab.tablet, TRUE);
}