[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [33724] branches/soc-2010-merwin/intern/ ghost/intern: late summer -- overhauled tablet-handling for Windows

Mike Erwin significant.bit at gmail.com
Fri Dec 17 01:13:23 CET 2010


Revision: 33724
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=33724
Author:   merwin
Date:     2010-12-17 01:13:23 +0100 (Fri, 17 Dec 2010)

Log Message:
-----------
late summer -- overhauled tablet-handling for Windows

Modified Paths:
--------------
    branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp
    branches/soc-2010-merwin/intern/ghost/intern/GHOST_TabletManagerWin32.cpp
    branches/soc-2010-merwin/intern/ghost/intern/GHOST_TabletManagerWin32.h

Modified: branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp
===================================================================
--- branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp	2010-12-17 00:12:23 UTC (rev 33723)
+++ branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp	2010-12-17 00:13:23 UTC (rev 33724)
@@ -1022,7 +1022,7 @@
 					{
 					// tablet manager handles all its own cursor moves.
 					// ignore 'regular' mouse while a tablet tool is being used.
-					DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam);
+					// DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam);
 					eventHandled = true;
 					break;
 					}

Modified: branches/soc-2010-merwin/intern/ghost/intern/GHOST_TabletManagerWin32.cpp
===================================================================
--- branches/soc-2010-merwin/intern/ghost/intern/GHOST_TabletManagerWin32.cpp	2010-12-17 00:12:23 UTC (rev 33723)
+++ branches/soc-2010-merwin/intern/ghost/intern/GHOST_TabletManagerWin32.cpp	2010-12-17 00:13:23 UTC (rev 33724)
@@ -10,14 +10,30 @@
 #include <stdlib.h>
 #include <math.h>
 
-#define PACKETDATA (PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION)
-#define PACKETMODE (0 /*PK_BUTTONS*/)
-// #define PACKETTILT PKEXT_ABSOLUTE
+#define MAX_QUEUE_SIZE 100
 
-#include "pktdef.h"
+static bool wintab_initialized = false;
 
-#define MAX_QUEUE_SIZE 100
+// BEGIN from Wacom's Utils.h
+typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID );
+typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL );
+typedef BOOL ( API * WTCLOSE ) ( HCTX );
+typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int );
+typedef int  ( API * WTPACKETSGET ) ( HCTX, int, LPVOID );
+typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID );
+// END
 
+// the Wintab library
+static HMODULE lib_Wintab;
+
+// WinTab function pointers
+static WTOPENA func_Open;
+static WTCLOSE func_Close;
+static WTINFOA func_Info;
+static WTQUEUESIZESET func_QueueSizeSet;
+static WTPACKETSGET func_PacketsGet;
+static WTPACKET func_Packet;
+
 static void print(AXIS const& t, char const* label = NULL)
 	{
 	const char* unitName[] = {"dinosaur","inch","cm","circle"};
@@ -54,121 +70,225 @@
 		}
 	}
 
-GHOST_TabletManagerWin32::GHOST_TabletManagerWin32()
-	: activeWindow(NULL)
+Tablet::Tablet(int tabletID)
+	: id(tabletID)
 	{
-	dropTool();
+	GHOST_ASSERT(wintab_initialized, "Tablet objects should only be created by TabletManager");
 
-	// open WinTab
-	lib_Wintab = LoadLibrary("wintab32.dll");
+	// query for overall capabilities and ranges
+	func_Info(WTI_DEVICES, DVC_NAME, name);
+	printf("\n-- tablet %d: %s --\n", id, name);
 
-	if (lib_Wintab)
+	puts("\nactive tablet area");
+	AXIS xRange, yRange;
+	func_Info(WTI_DEVICES + id, DVC_X, &xRange);
+	func_Info(WTI_DEVICES + id, DVC_Y, &yRange);
+	print(xRange,"x"); print(yRange,"y");
+	size_x = xRange.axMax;
+	size_y = yRange.axMax;
+
+	func_Info(WTI_DEVICES + id, DVC_NCSRTYPES, &cursorCount);
+	func_Info(WTI_DEVICES + id, DVC_FIRSTCSR, &cursorBase);
+	printf("\nowns tools %d to %d\n", cursorBase, cursorBase + cursorCount - 1);
+
+	func_Info(WTI_DEVICES + id, DVC_PKTDATA, &(allTools));
+	puts("\nall tools have"); print(allTools);
+	func_Info(WTI_DEVICES + id, DVC_CSRDATA, &(someTools));
+	puts("some tools also have"); print(someTools);
+
+	puts("\npressure sensitivity");
+	AXIS pressureRange;
+	hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE
+		&& func_Info(WTI_DEVICES + id, DVC_NPRESSURE, &pressureRange)
+		&& pressureRange.axMax;
+
+	if (hasPressure)
 		{
-		// connect function pointers
-		func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA");
-		func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose");
-		func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA");
-		func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet");
-		func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet");
-		func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket");
+		print(pressureRange);
+		pressureScale = 1.f / pressureRange.axMax;
+		}
+	else
+		pressureScale = 0.f;
 
-		puts("\n-- essential tablet info --");
-		func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount);
-		func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase);
+	puts("\ntilt sensitivity");
+	AXIS tiltRange[3];
+	hasTilt = (allTools|someTools) & PK_ORIENTATION
+		&& func_Info(WTI_DEVICES + id, DVC_ORIENTATION, tiltRange)
+		&& tiltRange[0].axResolution && tiltRange[1].axResolution;
 
-		func_Info(WTI_DEVICES, DVC_PKTDATA, &allTools);
-		puts("\nall tools have"); print(allTools);
-		func_Info(WTI_DEVICES, DVC_CSRDATA, &someTools);
-		puts("some tools also have"); print(someTools);
+	if (hasTilt)
+		{
+		// leave this code in place to help support tablets I haven't tested
+		const char* axisName[] = {"azimuth","altitude","twist"};
+		for (int i = 0; i < 3; ++i)
+			print(tiltRange[i], axisName[i]);
 
-		puts("\npressure sensitivity");
-		AXIS pressureRange;
-		hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE
-			&& func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange);
+		azimuthScale = 1.f / tiltRange[0].axMax;
+		altitudeScale = 1.f / tiltRange[1].axMax;
+		}
+	else
+		{
+		puts("none");
+		azimuthScale = altitudeScale = 0.f;
+		}
 
-		if (hasPressure)
-			{
-			print(pressureRange);
-			pressureScale = 1.f / pressureRange.axMax;
-			}
-		else
-			pressureScale = 0.f;
+	for (UINT i = cursorBase; i < cursorBase + cursorCount; ++i)
+		{
+		// what can each cursor do?
 
-		puts("\ntilt sensitivity");
-		AXIS tiltRange[3];
-		hasTilt = (allTools|someTools) & PK_ORIENTATION
-			&& func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange);
+		UINT physID;
+		func_Info(WTI_CURSORS + i, CSR_PHYSID, &physID);
+		if (physID == 0)
+			// each 'real' cursor has a physical ID
+			//  (on Wacom at least, not tested with other vendors)
+			continue;
 
-		if (hasTilt)
-			{
-			// leave this code in place to help support tablets I haven't tested
-			const char* axisName[] = {"azimuth","altitude","twist"};
-			for (int i = 0; i < 3; ++i)
-				print(tiltRange[i], axisName[i]);
+		TCHAR name[40];
+		func_Info(WTI_CURSORS + i, CSR_NAME, name);
+		printf("\ncursor %d: %s\n", i, name);
 
-			// cheat by using available data from Intuos4. test on other tablets!!!
-			azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution);
-			altitudeScale = 1.f / tiltRange[1].axMax;
-			}
-		else
+		// always returns 'yes' so don't bother
+		// BOOL active;
+		// func_Info(WTI_CURSORS + i, CSR_ACTIVE, &active);
+		// printf("active: %s\n", active ? "yes" : "no");
+
+		WTPKT packet;
+		func_Info(WTI_CURSORS + i, CSR_PKTDATA, &packet);
+		// only report the 'special' bits that distinguish this cursor from the rest
+		puts("packet support"); print(packet & someTools);
+
+		puts("buttons:");
+		BYTE buttons;
+		BYTE sysButtonMap[32];
+		func_Info(WTI_CURSORS + i, CSR_BUTTONS, &buttons);
+		func_Info(WTI_CURSORS + i, CSR_SYSBTNMAP, sysButtonMap);
+		for (int i = 0; i < buttons; ++i)
+			printf("  %d -> %d\n", i, sysButtonMap[i]);
+		}
+	}
+
+bool Tablet::ownsCursor(int cursor)
+	{
+	return (cursor - cursorBase) < cursorCount;
+	}
+
+TabletTool Tablet::toolForCursor(int cursor)
+	{
+	TabletTool tool = {TABLET_NONE,false,false};
+	if (ownsCursor(cursor))
+		{
+		// try one way to classify cursor
+		UINT cursorType = (cursor - cursorBase) % cursorCount;
+		printf("%d mod %d = %d\n", cursor - cursorBase, cursorCount, cursorType);
+		switch (cursorType)
 			{
-			puts("none");
-			azimuthScale = altitudeScale = 0.f;
+			case 0: // older Intuos tablets can track two cursors at once
+			case 3: // so we test for both here
+				tool.type = TABLET_MOUSE;
+				break;
+			case 1:
+			case 4:
+				tool.type = TABLET_PEN;
+				break;
+			case 2:
+			case 5:
+				tool.type = TABLET_ERASER;
+				break;
+			default:
+				tool.type = TABLET_NONE;
 			}
 
-#if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed
-		// this isn't working for [mce], so let it rest for now
-		puts("\nraw tilt sensitivity");
-		hasTilt = false;
-		UINT tag = 0;
-		UINT extensionCount;
-		func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount);
-		for (UINT i = 0; i < extensionCount; ++i)
+		#if 0
+		// now try another way
+		func_Info(WTI_CURSORS + cursor, CSR_TYPE, &cursorType);
+		switch (cursorType & 0xf06)
 			{
-			printf("trying extension %d\n", i);
-			func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag);
-			if (tag == WTX_TILT)
-				{
-				hasTilt = true;
+			case 0x802:
+				puts("general stylus");
 				break;
-				}
+			case 0x902:
+				puts("airbrush");
+				break;
+			case 0x804:
+				puts("art pen");
+				break;
+			case 0x004:
+				puts("4D mouse");
+				break;
+			case 0x006:
+				puts("5-button puck");
+				break;
+			default:
+				puts("???");
 			}
+		#endif
 
-		if (hasTilt)
+		WTPKT toolData;
+		func_Info(WTI_CURSORS + cursor, CSR_PKTDATA, &toolData);
+		// discard any stray capabilities
+		// (sometimes cursors claim to be able to do things
+		//    that their tablet doesn't support)
+		toolData &= (allTools|someTools);
+		// only report the 'special' bits that distinguish this cursor from the rest
+		puts("packet support"); print(toolData & someTools);
+		putchar('\n');
+
+		if (tool.type == TABLET_MOUSE)
 			{
-			AXIS tiltRange[2];
-			func_Info(WTI_EXTENSIONS + tag, EXT_AXES, tiltRange);
-			print("x", tiltRange[0]);
-			print("y", tiltRange[1]);
-			tiltScaleX = 1.f / tiltRange[0].axMax;
-			tiltScaleY = 1.f / tiltRange[1].axMax;
-			func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask);
+			// don't always trust CSR_PKTDATA!
+			tool.hasPressure = false;
+			tool.hasTilt = false;
 			}
 		else
 			{
-			puts("none");
-			tiltScaleX = tiltScaleY = 0.f;
+			tool.hasPressure = toolData & PK_NORMAL_PRESSURE;
+			tool.hasTilt = toolData & PK_ORIENTATION;
 			}
-#endif // WTX_TILT
+		}
 
-		getExtraInfo();
+	return tool;
+	}
+
+GHOST_TabletManagerWin32::GHOST_TabletManagerWin32()
+	: activeWindow(NULL)
+	{
+	dropTool();
+
+	// open WinTab
+	GHOST_ASSERT(!wintab_initialized,"There should be only one TabletManagerWin32 object");
+	lib_Wintab = LoadLibrary("wintab32.dll");
+
+	if (lib_Wintab)
+		{
+		// connect function pointers
+		func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA");
+		func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose");
+		func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA");
+		func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet");

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list