Commit: 1a3ef53a78d48439723f4be3d4fcaaf11f32cd60
Author: Nicholas Rishel
Date:   Sun Dec 6 00:20:27 2020 -0800
Branches: wintab-revised
https://developer.blender.org/rB1a3ef53a78d48439723f4be3d4fcaaf11f32cd60

Here lies a final attempt attempt at a sane Wintab implementation, smashed
against the reality of broken and bad APIs. If only rawinput events
mapped consistently, but for reasons unknown Wintab express buttons will
map to the device when stylus is in range, and map to an emulated button
when the pen is away. For this reason this commit must only exist for
posterity, a totem of my naivety in believing Wintab and Win32 could
be reasoned with.

===================================================================

M       intern/ghost/intern/GHOST_SystemWin32.cpp
M       intern/ghost/intern/GHOST_SystemWin32.h
M       intern/ghost/intern/GHOST_WindowWin32.cpp
M       intern/ghost/intern/GHOST_WindowWin32.h

===================================================================

diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp 
b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 8178b9bdf1e..071ffae1092 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -30,12 +30,21 @@
 #endif
 
 #include <commctrl.h>
+#include <memory>
 #include <psapi.h>
 #include <shellapi.h>
 #include <shlobj.h>
 #include <tlhelp32.h>
 #include <windowsx.h>
 
+#include <cfgmgr32.h>
+#include <initguid.h>  // XXX must include before devpkey.h
+
+#include <devpkey.h>
+#pragma comment(lib, "Cfgmgr32.lib")
+
+#pragma comment(lib, "Rpcrt4.lib")
+
 #include "utf_winfunc.h"
 #include "utfconv.h"
 
@@ -57,6 +66,8 @@
 
 #ifdef WITH_INPUT_NDOF
 #  include "GHOST_NDOFManagerWin32.h"
+#  define NDOF_USAGE_PAGE 0x01
+#  define NDOF_USAGE 0x08
 #endif
 
 // Key code values not found in winuser.h
@@ -143,12 +154,17 @@
  */
 #define BROKEN_PEEK_TOUCHPAD
 
+#define GUID_FORMAT 
"%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX"
+#define GUID_ARG(guid) \
+  guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], 
guid->Data4[2], \
+      guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], 
guid->Data4[7]
+
 static void initRawInput()
 {
 #ifdef WITH_INPUT_NDOF
-#  define DEVICE_COUNT 2
+  const int DEVICE_COUNT = 3;
 #else
-#  define DEVICE_COUNT 1
+  const int DEVICE_COUNT = 2;
 #endif
 
   RAWINPUTDEVICE devices[DEVICE_COUNT];
@@ -159,18 +175,19 @@ static void initRawInput()
   devices[0].usUsagePage = 0x01;
   devices[0].usUsage = 0x06; /* 
http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
 
+  // Initiates WM_INPUT messages from mouse
+  devices[1].usUsagePage = 0x01;
+  devices[1].usUsage = 0x02;
+
 #ifdef WITH_INPUT_NDOF
   // multi-axis mouse (SpaceNavigator, etc.)
-  devices[1].usUsagePage = 0x01;
-  devices[1].usUsage = 0x08;
+  devices[2].usUsagePage = NDOF_USAGE_PAGE;
+  devices[2].usUsage = NDOF_USAGE;
 #endif
 
-  if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE)))
-    ;  // yay!
-  else
+  if (!RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE))) 
{
     GHOST_PRINTF("could not register for RawInput: %d\n", (int)GetLastError());
-
-#undef DEVICE_COUNT
+  }
 }
 
 #ifndef DPI_ENUMS_DECLARED
@@ -566,17 +583,22 @@ GHOST_TSuccess 
GHOST_SystemWin32::getButtons(GHOST_Buttons &buttons) const
 {
   /* Check for swapped buttons (left-handed mouse buttons)
    * GetAsyncKeyState() will give back the state of the physical mouse buttons.
+   *
+   * Tested Wacom tablet swapped physical buttons when the OS swapped logical 
mouse buttons such
+   * that behavior was unchanged. Physical buttons were swapped for both the 
stylus and pad
+   * buttons.
    */
   bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
 
-  bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0;
+  bool down = HIBYTE(::GetAsyncKeyState(VK_LBUTTON)) != 0;
   buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
 
-  down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0;
+  down = HIBYTE(::GetAsyncKeyState(VK_MBUTTON)) != 0;
   buttons.set(GHOST_kButtonMaskMiddle, down);
 
-  down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0;
+  down = HIBYTE(::GetAsyncKeyState(VK_RBUTTON)) != 0;
   buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
+
   return GHOST_kSuccess;
 }
 
@@ -596,6 +618,50 @@ GHOST_TSuccess GHOST_SystemWin32::init()
   FreeLibrary(user32);
   initRawInput();
 
+  UINT nDevices;
+  if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) == 0) 
{
+    std::vector<RAWINPUTDEVICELIST> devices(nDevices);
+    if (GetRawInputDeviceList(devices.data(), &nDevices, 
sizeof(RAWINPUTDEVICELIST)) != -1) {
+      for (auto device : devices) {
+        if (device.dwType != RIM_TYPEHID) {
+          continue;
+        }
+
+        RID_DEVICE_INFO deviceInfo;
+        deviceInfo.cbSize = sizeof(deviceInfo);
+        UINT deviceInfoSize = sizeof(deviceInfo);
+        if (GetRawInputDeviceInfo(device.hDevice, RIDI_DEVICEINFO, 
&deviceInfo, &deviceInfoSize) ==
+            -1) {
+          continue;
+        }
+        if (deviceInfo.dwType == RIM_TYPEHID && deviceInfo.hid.usUsagePage == 
0x0D) {
+          if (deviceInfo.hid.usUsage == 0x01 || deviceInfo.hid.usUsage == 
0x02) {
+            // get device
+            UINT nameLen;
+            GetRawInputDeviceInfoW(device.hDevice, RIDI_DEVICENAME, NULL, 
&nameLen);
+            std::basic_string<WCHAR> name;
+            name.resize(nameLen);
+            GetRawInputDeviceInfoW(device.hDevice, RIDI_DEVICENAME, 
name.data(), &nameLen);
+
+            DEVPROPTYPE type = DEVPROP_TYPE_GUID;
+            GUID containerId;
+            ULONG containerIdSize = sizeof(containerId);
+            if (CM_Get_Device_Interface_PropertyW(name.data(),
+                                                  &DEVPKEY_Device_ContainerId,
+                                                  &type,
+                                                  (PBYTE)&containerId,
+                                                  &containerIdSize,
+                                                  0) == CR_SUCCESS) {
+              RPC_STATUS status;
+              m_tabletHandles.insert(UuidHash((GUID *)&containerId, &status));
+              printf("{" GUID_FORMAT "}\n", GUID_ARG(((GUID *)&containerId)));
+            }
+          }
+        }
+      }
+    }
+  }
+
   m_lfstart = ::GetTickCount();
   // Determine whether this system has a high frequency performance counter. */
   m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER 
*)&m_freq) == TRUE;
@@ -946,126 +1012,38 @@ GHOST_EventButton 
*GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
     window->updateMouseCapture(MouseReleased);
   }
 
-  /* Check for active Wintab mouse emulation in addition to a tablet in range 
because a proximity
-   * leave event might have fired before the Windows mouse up event, thus 
there are still tablet
-   * events to grab. The described behavior was observed in a Wacom Bamboo 
CTE-450. */
-  if (window->useTabletAPI(GHOST_kTabletWintab) &&
-      (window->m_tabletInRange || window->wintabSysButPressed()) &&
-      processWintabEvent(type, window, mask, window->getMousePressed())) {
-    /* Wintab processing only handles in-contact events. */
-    return NULL;
-  }
-
   return new GHOST_EventButton(
       system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE);
 }
 
-GHOST_TSuccess GHOST_SystemWin32::processWintabEvent(GHOST_TEventType type,
-                                                     GHOST_WindowWin32 *window,
-                                                     GHOST_TButtonMask mask,
-                                                     bool mousePressed)
+GHOST_TSuccess GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
 {
   GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
 
-  /* Only process Wintab packets if we can correlate them to a Window's mouse 
button event. When a
-   * button event associated to a mouse button by Wintab occurs outside of 
WM_*BUTTON events,
-   * there's no way to tell if other simultaneously pressed non-mouse mapped 
buttons are associated
-   * to a modifier key (shift, alt, ctrl) or a system event (scroll, etc.) and 
thus it is not
-   * possible to determine if a mouse click event should occur. */
-  if (!mousePressed && !window->wintabSysButPressed()) {
-    return GHOST_kFailure;
-  }
-
   std::vector<GHOST_WintabInfoWin32> wintabInfo;
   if (!window->getWintabInfo(wintabInfo)) {
     return GHOST_kFailure;
   }
 
-  auto wtiIter = wintabInfo.begin();
-
-  /* We only process events that correlate to a mouse button events, so there 
may exist Wintab
-   * button down events that were instead mapped to e.g. scroll still in the 
queue. We need to
-   * skip those and find the last button down mapped to mouse buttons. */
-  if (!window->wintabSysButPressed()) {
-    /* Assume there may be no button down event currently in the queue. */
-    wtiIter = wintabInfo.end();
-
-    for (auto it = wintabInfo.begin(); it != wintabInfo.end(); it++) {
-      if (it->type == GHOST_kEventButtonDown) {
-        wtiIter = it;
-      }
-    }
-  }
-
-  bool unhandledButton = type != GHOST_kEventCursorMove;
-
-  for (; wtiIter != wintabInfo.end(); wtiIter++) {
-    auto info = *wtiIter;
-
+  for (auto info : wintabInfo) {
     switch (info.type) {
-      case GHOST_kEventButtonDown: {
-        /* While changing windows with a tablet, Window's mouse button events 
normally occur before
-         * tablet proximity events, so a button up event can't be 
differentiated as occurring from
-         * a Wintab tablet or a normal mouse and a Ghost button event will 
always be generated.
-         *
-         * If we were called during a button down event create a ghost button 
down event, otherwise
-         * don't duplicate the prior button down as it interrupts drawing 
immediately after
-         * changing a window. */
-        system->pushEvent(new GHOST_EventCursor(
-            info.time, GHOST_kEventCursorMove, window, info.x, info.y, 
info.tabletData));
-        if (type == GHOST_kEventButtonDown && mask == info.button) {
-          system->pushEvent(
-              new GHOST_EventButton(info.time, info.type, window, info.button, 
info.tabletData));
-          unhandledButton = false;
-        }
-        window->updateWintabSysBut(MousePressed);
-        break;
-      }
       case GHOST_kEventCursorMove:
         system->pushEvent(new GHOST_EventCursor(
             info.time, GHOST_kEventCursorMove, window, info.x, info.y, 
info.tabletData));
         break;
+      case GHOST_kEventButtonDown:
+        system->pushEvent(
+            new GHOST_EventButton(info.time, info.type, window, info.button, 
info.tabletData));
+        break;
       case GHOST_kEventButtonUp:
         system->pushEvent(
             new GHOST_EventButton(info.time, info.type, window, info.button, 
info.tabletData));
-        if (type == GHOST_kEventButtonUp && mask == info.button) {
-          unhandledButton = false;
-        }
-        window->updateWintabSysBut(MouseReleased);
         break;
       default:
         break;
     }
   }

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to