Updated Win32 tablet code.

This commit is contained in:
Mike Erwin 2010-08-12 04:03:40 +00:00
parent 1c2d36344c
commit 485d1ef06e
10 changed files with 518 additions and 393 deletions

@ -291,29 +291,15 @@ GHOST_TSuccess GHOST_System::init()
GHOST_TSuccess GHOST_System::exit() GHOST_TSuccess GHOST_System::exit()
{ {
if (getFullScreen()) { if (getFullScreen())
endFullScreen(); endFullScreen();
}
if (m_displayManager) {
delete m_displayManager; delete m_displayManager;
m_displayManager = 0;
}
if (m_windowManager) {
delete m_windowManager; delete m_windowManager;
m_windowManager = 0;
}
if (m_timerManager) {
delete m_timerManager; delete m_timerManager;
m_timerManager = 0;
}
if (m_eventManager) {
delete m_eventManager; delete m_eventManager;
m_eventManager = 0;
}
if (m_ndofManager) {
delete m_ndofManager; delete m_ndofManager;
m_ndofManager = 0;
}
return GHOST_kSuccess; return GHOST_kSuccess;
} }

@ -44,10 +44,10 @@
// win64 doesn't define GWL_USERDATA // win64 doesn't define GWL_USERDATA
#ifdef WIN32 #ifdef WIN32
#ifndef GWL_USERDATA #ifndef GWL_USERDATA
#define GWL_USERDATA GWLP_USERDATA #define GWL_USERDATA GWLP_USERDATA
#define GWL_WNDPROC GWLP_WNDPROC #define GWL_WNDPROC GWLP_WNDPROC
#endif #endif
#endif #endif
#include "GHOST_Debug.h" #include "GHOST_Debug.h"
@ -61,44 +61,45 @@
#include "GHOST_WindowManager.h" #include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.h" #include "GHOST_WindowWin32.h"
#include "GHOST_NDOFManagerWin32.h" #include "GHOST_NDOFManagerWin32.h"
#include "GHOST_TabletManagerWin32.h"
// Key code values not found in winuser.h // Key code values not found in winuser.h
#ifndef VK_MINUS #ifndef VK_MINUS
#define VK_MINUS 0xBD #define VK_MINUS 0xBD
#endif // VK_MINUS #endif
#ifndef VK_SEMICOLON #ifndef VK_SEMICOLON
#define VK_SEMICOLON 0xBA #define VK_SEMICOLON 0xBA
#endif // VK_SEMICOLON #endif
#ifndef VK_PERIOD #ifndef VK_PERIOD
#define VK_PERIOD 0xBE #define VK_PERIOD 0xBE
#endif // VK_PERIOD #endif
#ifndef VK_COMMA #ifndef VK_COMMA
#define VK_COMMA 0xBC #define VK_COMMA 0xBC
#endif // VK_COMMA #endif
#ifndef VK_QUOTE #ifndef VK_QUOTE
#define VK_QUOTE 0xDE #define VK_QUOTE 0xDE
#endif // VK_QUOTE #endif
#ifndef VK_BACK_QUOTE #ifndef VK_BACK_QUOTE
#define VK_BACK_QUOTE 0xC0 #define VK_BACK_QUOTE 0xC0
#endif // VK_BACK_QUOTE #endif
#ifndef VK_SLASH #ifndef VK_SLASH
#define VK_SLASH 0xBF #define VK_SLASH 0xBF
#endif // VK_SLASH #endif
#ifndef VK_BACK_SLASH #ifndef VK_BACK_SLASH
#define VK_BACK_SLASH 0xDC #define VK_BACK_SLASH 0xDC
#endif // VK_BACK_SLASH #endif
#ifndef VK_EQUALS #ifndef VK_EQUALS
#define VK_EQUALS 0xBB #define VK_EQUALS 0xBB
#endif // VK_EQUALS #endif
#ifndef VK_OPEN_BRACKET #ifndef VK_OPEN_BRACKET
#define VK_OPEN_BRACKET 0xDB #define VK_OPEN_BRACKET 0xDB
#endif // VK_OPEN_BRACKET #endif
#ifndef VK_CLOSE_BRACKET #ifndef VK_CLOSE_BRACKET
#define VK_CLOSE_BRACKET 0xDD #define VK_CLOSE_BRACKET 0xDD
#endif // VK_CLOSE_BRACKET #endif
#ifndef VK_GR_LESS #ifndef VK_GR_LESS
#define VK_GR_LESS 0xE2 #define VK_GR_LESS 0xE2
#endif // VK_GR_LESS #endif
GHOST_SystemWin32::GHOST_SystemWin32() GHOST_SystemWin32::GHOST_SystemWin32()
@ -106,14 +107,14 @@ GHOST_SystemWin32::GHOST_SystemWin32()
m_separateLeftRight(false), m_separateLeftRight(false),
m_separateLeftRightInitialized(false) m_separateLeftRightInitialized(false)
{ {
m_displayManager = new GHOST_DisplayManagerWin32 (); m_displayManager = new GHOST_DisplayManagerWin32;
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
m_displayManager->initialize(); m_displayManager->initialize();
// Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
OleInitialize(0); OleInitialize(0);
m_input_fidelity_hint = LO_FI; // just for testing... m_input_fidelity_hint = HI_FI; // just for testing...
// register for RawInput devices // register for RawInput devices
RAWINPUTDEVICE devices[1]; RAWINPUTDEVICE devices[1];
@ -132,6 +133,8 @@ GHOST_SystemWin32::~GHOST_SystemWin32()
{ {
// Shutdown COM // Shutdown COM
OleUninitialize(); OleUninitialize();
delete m_tabletManager;
} }
@ -176,16 +179,19 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_TWindowState state, GHOST_TDrawingContextType type,
bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow )
{ {
GHOST_Window* window = 0; GHOST_WindowWin32* window =
window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
if (window) { if (window) {
if (window->getValid()) { if (window->getValid()) {
m_windowManager->addWindow(window); m_windowManager->addWindow(window);
m_windowManager->setActiveWindow(window); m_windowManager->setActiveWindow(window);
if (m_tabletManager->available())
window->becomeTabletAware(m_tabletManager);
} }
else { else {
// An invalid window could be one that was used to test for AA // An invalid window could be one that was used to test for AA
GHOST_Window *other_window = ((GHOST_WindowWin32*)window)->getNextWindow(); GHOST_WindowWin32* other_window = (GHOST_WindowWin32*) window->getNextWindow();
delete window; delete window;
window = 0; window = 0;
@ -329,6 +335,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess success = GHOST_System::init(); GHOST_TSuccess success = GHOST_System::init();
m_ndofManager = new GHOST_NDOFManagerWin32(*this); m_ndofManager = new GHOST_NDOFManagerWin32(*this);
m_tabletManager = new GHOST_TabletManagerWin32;
/* Disable scaling on high DPI displays on Vista */ /* Disable scaling on high DPI displays on Vista */
HMODULE user32 = ::LoadLibraryA("user32.dll"); HMODULE user32 = ::LoadLibraryA("user32.dll");
@ -374,14 +381,6 @@ GHOST_TSuccess GHOST_SystemWin32::init()
return success; return success;
} }
GHOST_TSuccess GHOST_SystemWin32::exit()
{
// [mce] since this duplicates its super, why bother?
return GHOST_System::exit();
}
GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
{ {
GHOST_TKey key; GHOST_TKey key;
@ -497,9 +496,17 @@ void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window)
((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers); ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
} }
bool eventIsFromTablet()
{
// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs
return GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen
}
GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
{ {
if (eventIsFromTablet())
return NULL;
return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
} }
@ -924,11 +931,13 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
case WT_PACKET: case WT_PACKET:
puts("WT_PACKET"); puts("WT_PACKET");
window->processWin32TabletEvent(wParam, lParam); // window->processWin32TabletEvent(wParam, lParam);
m_tabletManager->processPackets(window);
break; break;
case WT_CSRCHANGE: case WT_CSRCHANGE:
case WT_PROXIMITY: case WT_PROXIMITY:
window->processWin32TabletInitEvent(); // window->processWin32TabletInitEvent();
m_tabletManager->changeTool(window);
break; break;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -977,11 +986,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
{ {
// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs if (!eventIsFromTablet())
int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen
if (tabletTool)
puts("(from tablet)");
else
{ {
int xPrev = mousePosX; int xPrev = mousePosX;
int yPrev = mousePosY; int yPrev = mousePosY;
@ -992,7 +997,8 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM
if (m_input_fidelity_hint == HI_FI) if (m_input_fidelity_hint == HI_FI)
{ {
/* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); // int n =
getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window);
// printf("%d more mouse points found\n", n); // printf("%d more mouse points found\n", n);
} }

@ -57,6 +57,7 @@ class GHOST_EventWindow;
class GHOST_EventDragnDrop; class GHOST_EventDragnDrop;
class GHOST_WindowWin32; class GHOST_WindowWin32;
class GHOST_TabletManagerWin32;
/** /**
* WIN32 Implementation of GHOST_System class. * WIN32 Implementation of GHOST_System class.
@ -236,7 +237,7 @@ protected:
* Closes the system down. * Closes the system down.
* @return A success value. * @return A success value.
*/ */
virtual GHOST_TSuccess exit(); // virtual GHOST_TSuccess exit();
/** /**
* Converts raw WIN32 key codes from the wndproc to GHOST keys. * Converts raw WIN32 key codes from the wndproc to GHOST keys.
@ -357,6 +358,7 @@ protected:
/** Stores the initialization state of the member m_leftRightDistinguishable. */ /** Stores the initialization state of the member m_leftRightDistinguishable. */
bool m_separateLeftRightInitialized; bool m_separateLeftRightInitialized;
GHOST_TabletManagerWin32* m_tabletManager;
}; };
inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const
@ -370,4 +372,3 @@ inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys)
} }
#endif // _GHOST_SYSTEM_WIN32_H_ #endif // _GHOST_SYSTEM_WIN32_H_

@ -0,0 +1,300 @@
#include "GHOST_TabletManagerWin32.h"
#include "GHOST_WindowWin32.h"
#include <stdio.h>
#include <stdlib.h>
#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE
#define PACKETTILT PKEXT_ABSOLUTE
#define PACKETMODE PK_BUTTONS
#include "pktdef.h"
#define MAX_QUEUE_SIZE 128
GHOST_TabletManagerWin32::GHOST_TabletManagerWin32()
{
resetActiveTool();
// open WinTab
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");
func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet");
WORD specV, implV;
func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV);
func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV);
printf("Wintab version %d.%d (%d.%d)\n",
HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV));
// query for overall capabilities and ranges
char tabletName[LC_NAMELEN];
if (func_Info(WTI_DEVICES, DVC_NAME, tabletName))
puts(tabletName);
AXIS xRange, yRange;
func_Info(WTI_DEVICES, DVC_X, &xRange);
func_Info(WTI_DEVICES, DVC_Y, &yRange);
printf("active area: %dx%d\n", xRange.axMax, yRange.axMax);
AXIS pressureRange;
hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange) && pressureRange.axMax != 0;
printf("pressure sensitivity: ");
if (hasPressure)
{
printf("%d to %d\n", pressureRange.axMin, pressureRange.axMax);
pressureScale = 1.f / pressureRange.axMax;
}
else
{
printf("none\n");
pressureScale = 0.f;
}
AXIS tiltRange;
hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange) && tiltRange.axMax != 0;
printf("tilt sensitivity: ");
if (hasTilt)
{
printf("%d to %d\n", tiltRange.axMin, tiltRange.axMax);
tiltScale = 1.f / tiltRange.axMax;
}
else
{
printf("none\n");
tiltScale = 0.f;
}
}
}
GHOST_TabletManagerWin32::~GHOST_TabletManagerWin32()
{
// close WinTab
FreeLibrary(lib_Wintab);
}
bool GHOST_TabletManagerWin32::available()
{
return lib_Wintab // driver installed
&& func_Info(0,0,NULL); // tablet plugged in
}
void GHOST_TabletManagerWin32::resetActiveTool()
{
activeTool.type = TABLET_NONE;
activeTool.hasPressure = false;
activeTool.hasTilt = false;
}
HCTX GHOST_TabletManagerWin32::contextForWindow(GHOST_WindowWin32* window)
{
std::map<GHOST_WindowWin32*,HCTX>::iterator i = contexts.find(window);
if (i == contexts.end())
return 0; // not found
else
return i->second;
}
void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window)
{
if (contextForWindow(window) != 0)
// this window already has a tablet context
return;
// set up context
LOGCONTEXT archetype;
func_Info(WTI_DEFCONTEXT, 0, &archetype);
strcpy(archetype.lcName, "merwin special");
archetype.lcPktData = PACKETDATA;
archetype.lcPktMode = PACKETMODE;
archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES;
// BEGIN from Wacom's TILTTEST.c
/* output the data in screen coords */
archetype.lcOutOrgX = archetype.lcOutOrgY = 0;
archetype.lcOutExtX = GetSystemMetrics(SM_CXSCREEN);
/* move origin to upper left */
archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN);
// END
// open the context
HCTX context = func_Open(window->getHWND(), &archetype, TRUE);
// request a deep packet queue
int tabletQueueSize = MAX_QUEUE_SIZE;
while (!func_QueueSizeSet(context, tabletQueueSize))
--tabletQueueSize;
printf("tablet queue size: %d\n", tabletQueueSize);
contexts[window] = context;
}
void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window)
{
HCTX context = contextForWindow(window);
if (context)
{
func_Close(context);
// also remove it from our books:
contexts.erase(contexts.find(window));
}
}
void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window)
{
HCTX context = contextForWindow(window);
if (context)
{
PACKET packets[MAX_QUEUE_SIZE];
int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets);
printf("processing %d packets from ", n);
// every packet from a WT_PACKET message comes from the same tool
switch (packets[0].pkCursor) {
case 0: /* first device */
case 3: /* second device */
activeTool.type = TABLET_MOUSE;
puts("mouse");
break;
case 1:
case 4:
activeTool.type = TABLET_PEN;
puts("pen");
break;
case 2:
case 5:
activeTool.type = TABLET_ERASER;
puts("eraser");
break;
}
for (int i = 0; i < n; ++i)
{
PACKET const& packet = packets[i];
TabletToolData data = {activeTool};
int x = packet.pkX;
int y = packet.pkY;
if (data.tool.hasPressure)
{
if (packet.pkNormalPressure)
data.pressure = pressureScale * packet.pkNormalPressure;
else
data.tool.hasPressure = false;
}
if (data.tool.hasTilt)
{
data.tilt_x = tiltScale * packet.pkTilt.tiltX;
data.tilt_y = tiltScale * packet.pkTilt.tiltY;
}
printf(" %.3f @ (%d,%d) /%.2f,%.2f/\n", data.pressure, x, y, data.tilt_x, data.tilt_y);
}
}
}
void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window)
{
HCTX context = contextForWindow(window);
if (context)
{
puts("-- changing tool --");
if (hasPressure)
{
puts(" - pressure");
activeTool.hasPressure = true; // not necessarily, but good enough for testing
}
if (hasTilt)
{
puts(" - tilt");
activeTool.hasTilt = true;
}
#if 0
#define kTransducerDeviceIdBitMask 0x0001
#define kTransducerAbsXBitMask 0x0002
#define kTransducerAbsYBitMask 0x0004
#define kTransducerVendor1BitMask 0x0008
#define kTransducerVendor2BitMask 0x0010
#define kTransducerVendor3BitMask 0x0020
#define kTransducerButtonsBitMask 0x0040
#define kTransducerTiltXBitMask 0x0080
#define kTransducerTiltYBitMask 0x0100
#define kTransducerAbsZBitMask 0x0200
#define kTransducerPressureBitMask 0x0400
#define kTransducerTangentialPressureBitMask 0x0800
#define kTransducerOrientInfoBitMask 0x1000
#define kTransducerRotationBitMask 0x2000
// this is what I really want to know:
// UINT active;
// UINT active2 = func_Info(WTI_CURSORS, CSR_ACTIVE, &active);
// printf("active: %d %d\n", active, active2);
WTPKT toolData;
func_Info(WTI_CURSORS, CSR_PKTDATA, &toolData);
activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE;
activeTool.hasTilt = toolData & PK_ORIENTATION;
// UINT cap;
// UINT cap2 = func_Info(WTI_CURSORS, CSR_CAPABILITIES, &cap);
// capabilities same as Mac tablet code? Let's see...
// int cap = CGEventGetIntegerValueField(event, kCGTabletProximityEventCapabilityMask);
printf("cursor capabilities: %d %d\n", cap, cap2);
if (cap & kTransducerDeviceIdBitMask)
printf(" - device id\n");
if (cap & kTransducerAbsXBitMask)
printf(" - abs x\n");
if (cap & kTransducerAbsYBitMask)
printf(" - abs y\n");
if (cap & kTransducerAbsZBitMask)
printf(" - abs z\n");
if (cap & kTransducerVendor1BitMask)
printf(" - vendor 1\n");
if (cap & kTransducerVendor2BitMask)
printf(" - vendor 2\n");
if (cap & kTransducerVendor3BitMask)
printf(" - vendor 3\n");
if (cap & kTransducerButtonsBitMask)
printf(" - buttons\n");
if (cap & kTransducerTiltXBitMask)
{
printf(" - tilt x\n");
hasTilt = true;
}
if (cap & kTransducerTiltYBitMask)
{
printf(" - tilt y\n");
hasTilt = true;
}
if (cap & kTransducerPressureBitMask)
{
printf(" - pressure\n");
hasPressure = true;
}
if (cap & kTransducerTangentialPressureBitMask)
printf(" - tangential pressure\n");
if (cap & kTransducerOrientInfoBitMask)
printf(" - orientation\n");
if (cap & kTransducerRotationBitMask)
printf(" - rotation\n");
#endif
}
}

@ -0,0 +1,82 @@
// safe & friendly Wintab wrapper
// by Mike Erwin, July 2010
#ifndef GHOST_TABLET_MANAGER_WIN32_H
#define GHOST_TABLET_MANAGER_WIN32_H
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "wintab.h"
#include <map>
class GHOST_WindowWin32;
// 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 );
// END
typedef enum { TABLET_NONE, TABLET_PEN, TABLET_ERASER, TABLET_MOUSE } TabletToolType;
typedef struct
{
TabletToolType type : 6; // plenty of room to grow
// capabilities
bool hasPressure : 1;
bool hasTilt : 1;
} TabletTool;
typedef struct
{
TabletTool tool;
float pressure;
float tilt_x, tilt_y;
} TabletToolData;
class GHOST_TabletManagerWin32
{
// the Wintab library
HINSTANCE lib_Wintab; // or HMODULE?
// WinTab function pointers
WTOPENA func_Open;
WTCLOSE func_Close;
WTINFOA func_Info;
WTQUEUESIZESET func_QueueSizeSet;
WTPACKETSGET func_PacketsGet;
// tablet attributes
bool hasPressure;
float pressureScale;
bool hasTilt;
float tiltScale;
// candidates for a base class:
TabletTool activeTool;
void resetActiveTool();
// book-keeping
std::map<GHOST_WindowWin32*,HCTX> contexts;
HCTX contextForWindow(GHOST_WindowWin32*);
public:
GHOST_TabletManagerWin32();
~GHOST_TabletManagerWin32();
bool available(); // another base class candidate
void openForWindow(GHOST_WindowWin32* window);
void closeForWindow(GHOST_WindowWin32* window);
void processPackets(GHOST_WindowWin32* window);
void changeTool(GHOST_WindowWin32* window);
};
#endif

@ -854,8 +854,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges)
return GHOST_Window::setModifiedState(isUnsavedChanges); return GHOST_Window::setModifiedState(isUnsavedChanges);
} }
GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
{ {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

@ -38,9 +38,7 @@
#include "GHOST_WindowWin32.h" #include "GHOST_WindowWin32.h"
#include "GHOST_SystemWin32.h" #include "GHOST_SystemWin32.h"
#include "GHOST_DropTargetWin32.h" #include "GHOST_DropTargetWin32.h"
#include "GHOST_TabletManagerWin32.h"
//#include "wintab.h" // for tablets, naturally
#include "Utils.c" // that's right, .c, with permission from Wacom
#include <stdio.h> // for debug, remove soon [mce] #include <stdio.h> // for debug, remove soon [mce]
// Need glew for some defines // Need glew for some defines
@ -50,7 +48,7 @@
// MSVC6 still doesn't define M_PI // MSVC6 still doesn't define M_PI
#ifndef M_PI #ifndef M_PI
#define M_PI 3.1415926536 #define M_PI 3.1415926536
#endif #endif
// Some more multisample defines // Some more multisample defines
@ -59,10 +57,10 @@
// win64 doesn't define GWL_USERDATA // win64 doesn't define GWL_USERDATA
#ifdef WIN32 #ifdef WIN32
#ifndef GWL_USERDATA #ifndef GWL_USERDATA
#define GWL_USERDATA GWLP_USERDATA #define GWL_USERDATA GWLP_USERDATA
#define GWL_WNDPROC GWLP_WNDPROC #define GWL_WNDPROC GWLP_WNDPROC
#endif #endif
#endif #endif
LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass"; LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass";
@ -121,15 +119,16 @@ GHOST_WindowWin32::GHOST_WindowWin32(
GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone,
stereoVisual,numOfAASamples), stereoVisual,numOfAASamples),
m_system(system), m_system(system),
m_tabletManager(NULL),
m_hDC(0), m_hDC(0),
m_hGlRc(0), m_hGlRc(0),
m_hasMouseCaptured(false), m_hasMouseCaptured(false),
m_nPressedButtons(0), m_nPressedButtons(0),
m_customCursor(0), m_customCursor(0),
m_wintab(false), // m_wintab(false),
m_tabletData(NULL), // m_tabletData(NULL),
m_tablet(0), // m_tablet(0),
m_maxPressure(0), // m_maxPressure(0),
m_multisample(numOfAASamples), m_multisample(numOfAASamples),
m_multisampleEnabled(msEnabled), m_multisampleEnabled(msEnabled),
m_msPixelFormat(msPixelFormat), m_msPixelFormat(msPixelFormat),
@ -175,10 +174,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(
s_windowClassName, // pointer to registered class name s_windowClassName, // pointer to registered class name
title, // pointer to window name title, // pointer to window name
WS_OVERLAPPEDWINDOW, // window style WS_OVERLAPPEDWINDOW, // window style
left, // horizontal position of window left, top, // window position
top, // vertical position of window width, height, // window size
width, // window width
height, // window height
0, // handle to parent or owner window 0, // handle to parent or owner window
0, // handle to menu or child-window identifier 0, // handle to menu or child-window identifier
::GetModuleHandle(0), // handle to application instance ::GetModuleHandle(0), // handle to application instance
@ -189,10 +186,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(
s_windowClassName, // pointer to registered class name s_windowClassName, // pointer to registered class name
title, // pointer to window name title, // pointer to window name
WS_POPUP | WS_MAXIMIZE, // window style WS_POPUP | WS_MAXIMIZE, // window style
left, // horizontal position of window left, top, // window position
top, // vertical position of window width, height, // window size
width, // window width
height, // window height
0, // handle to parent or owner window 0, // handle to parent or owner window
0, // handle to menu or child-window identifier 0, // handle to menu or child-window identifier
::GetModuleHandle(0), // handle to application instance ::GetModuleHandle(0), // handle to application instance
@ -242,6 +237,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
} }
} }
#if 0
m_wintab = LoadWintab(); m_wintab = LoadWintab();
if (m_wintab) { if (m_wintab) {
// let's see if we can initialize tablet here // let's see if we can initialize tablet here
@ -300,11 +296,13 @@ GHOST_WindowWin32::GHOST_WindowWin32(
} }
} }
} }
#endif
} }
GHOST_WindowWin32::~GHOST_WindowWin32() GHOST_WindowWin32::~GHOST_WindowWin32()
{ {
#if 0
if (m_wintab) { if (m_wintab) {
if (m_tablet) if (m_tablet)
gpWTClose(m_tablet); gpWTClose(m_tablet);
@ -313,6 +311,11 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_tabletData = NULL; m_tabletData = NULL;
UnloadWintab(); UnloadWintab();
} }
#endif
if (m_tabletManager)
m_tabletManager->closeForWindow(this);
if (m_customCursor) { if (m_customCursor) {
DestroyCursor(m_customCursor); DestroyCursor(m_customCursor);
m_customCursor = NULL; m_customCursor = NULL;
@ -913,6 +916,13 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur
return GHOST_kSuccess; return GHOST_kSuccess;
} }
void GHOST_WindowWin32::becomeTabletAware(GHOST_TabletManagerWin32* manager)
{
m_tabletManager = manager;
m_tabletManager->openForWindow(this);
}
#if 0
void GHOST_WindowWin32::processWin32TabletInitEvent() void GHOST_WindowWin32::processWin32TabletInitEvent()
{ {
if (m_wintab) { if (m_wintab) {
@ -1016,6 +1026,7 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
putchar('\n'); putchar('\n');
} }
} }
#endif
/** Reverse the bits in a GHOST_TUns8 */ /** Reverse the bits in a GHOST_TUns8 */
static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)

@ -34,8 +34,8 @@
#define _GHOST_WINDOW_WIN32_H_ #define _GHOST_WINDOW_WIN32_H_
#ifndef WIN32 #ifndef WIN32
#error WIN32 only! #error WIN32 only!
#endif // WIN32 #endif
#include "GHOST_Window.h" #include "GHOST_Window.h"
@ -43,13 +43,16 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
/*
#include <wintab.h> #include <wintab.h>
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) #define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
#define PACKETMODE PK_BUTTONS #define PACKETMODE PK_BUTTONS
#include <pktdef.h> #include <pktdef.h>
*/
class GHOST_SystemWin32; class GHOST_SystemWin32;
class GHOST_DropTargetWin32; class GHOST_DropTargetWin32;
class GHOST_TabletManagerWin32;
/* /*
// typedefs for WinTab functions to allow dynamic loading // typedefs for WinTab functions to allow dynamic loading
@ -105,7 +108,6 @@ public:
* Returns the window to replace this one if it's getting replaced * Returns the window to replace this one if it's getting replaced
* @return The window replacing this one. * @return The window replacing this one.
*/ */
GHOST_Window *getNextWindow(); GHOST_Window *getNextWindow();
/** /**
@ -249,10 +251,12 @@ public:
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
const GHOST_TabletData* GetTabletData() const GHOST_TabletData* GetTabletData()
{ return m_tabletData; } { return NULL; /*m_tabletData;*/ }
void processWin32TabletInitEvent(); // void processWin32TabletInitEvent();
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); // void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
void becomeTabletAware(GHOST_TabletManagerWin32*);
protected: protected:
GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd); GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd);
@ -293,37 +297,50 @@ protected:
* Sets the cursor shape on the window using * Sets the cursor shape on the window using
* native window system calls. * native window system calls.
*/ */
virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); virtual GHOST_TSuccess setWindowCustomCursorShape(
GHOST_TUns8 bitmap[16][2],
GHOST_TUns8 mask[16][2],
int hotX, int hotY
);
virtual GHOST_TSuccess setWindowCustomCursorShape( virtual GHOST_TSuccess setWindowCustomCursorShape(
GHOST_TUns8 *bitmap, GHOST_TUns8 *bitmap,
GHOST_TUns8 *mask, GHOST_TUns8 *mask,
int sizex, int sizex, int sizey,
int sizey, int hotX, int hotY,
int hotX, int fg_color, int bg_color
int hotY,
int fg_color,
int bg_color
); );
/** Pointer to system */ /** Pointer to system */
GHOST_SystemWin32 * m_system; GHOST_SystemWin32 * m_system;
/** Pointer to COM IDropTarget implementor */ /** Pointer to COM IDropTarget implementor */
GHOST_DropTargetWin32 * m_dropTarget; GHOST_DropTargetWin32 * m_dropTarget;
/** Graphics tablet manager. System owns this, Window needs access to it. */
GHOST_TabletManagerWin32* m_tabletManager;
/** Window handle. */ /** Window handle. */
HWND m_hWnd; HWND m_hWnd;
/** Device context handle. */ /** Device context handle. */
HDC m_hDC; HDC m_hDC;
/** OpenGL rendering context. */ /** OpenGL rendering context. */
HGLRC m_hGlRc; HGLRC m_hGlRc;
/** The first created OpenGL context (for sharing display lists) */ /** The first created OpenGL context (for sharing display lists) */
static HGLRC s_firsthGLRc; static HGLRC s_firsthGLRc;
/** The first created device context handle. */ /** The first created device context handle. */
static HDC s_firstHDC; static HDC s_firstHDC;
/** Flag for if window has captured the mouse */ /** Flag for if window has captured the mouse */
bool m_hasMouseCaptured; bool m_hasMouseCaptured;
/** Count of number of pressed buttons */ /** Count of number of pressed buttons */
int m_nPressedButtons; int m_nPressedButtons;
/** HCURSOR structure of the custom cursor */ /** HCURSOR structure of the custom cursor */
HCURSOR m_customCursor; HCURSOR m_customCursor;
@ -332,15 +349,15 @@ protected:
/** WinTab dll handle */ /** WinTab dll handle */
// HMODULE m_wintab; // HMODULE m_wintab;
bool m_wintab; // bool m_wintab;
/** Tablet data for GHOST */ /** Tablet data for GHOST */
GHOST_TabletData* m_tabletData; // GHOST_TabletData* m_tabletData;
/** Stores the Tablet context if detected Tablet features using WinTab.dll */ /** Stores the Tablet context if detected Tablet features using WinTab.dll */
HCTX m_tablet; // HCTX m_tablet;
LONG m_maxPressure; // LONG m_maxPressure;
LONG m_maxAzimuth, m_maxAltitude; // LONG m_maxAzimuth, m_maxAltitude;
/** Preferred number of samples */ /** Preferred number of samples */
GHOST_TUns16 m_multisample; GHOST_TUns16 m_multisample;

@ -1,182 +0,0 @@
/*----------------------------------------------------------------------------
NAME
Utils.c
PURPOSE
Some general-purpose functions for the WinTab demos.
COPYRIGHT
Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved
All rights reserved.
---------------------------------------------------------------------------- */
#include "Utils.h"
#ifdef WACOM_DEBUG
void WacomTrace( char *lpszFormat, ...);
#define WACOM_ASSERT( x ) assert( x )
#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__)
#else
#define WACOM_TRACE(...)
#define WACOM_ASSERT( x )
#endif // WACOM_DEBUG
//////////////////////////////////////////////////////////////////////////////
HINSTANCE ghWintab = NULL;
WTINFOA gpWTInfoA = NULL;
WTOPENA gpWTOpenA = NULL;
WTGETA gpWTGetA = NULL;
WTSETA gpWTSetA = NULL;
WTCLOSE gpWTClose = NULL;
WTPACKET gpWTPacket = NULL;
WTENABLE gpWTEnable = NULL;
WTOVERLAP gpWTOverlap = NULL;
WTSAVE gpWTSave = NULL;
WTCONFIG gpWTConfig = NULL;
WTRESTORE gpWTRestore = NULL;
WTEXTSET gpWTExtSet = NULL;
WTEXTGET gpWTExtGet = NULL;
WTQUEUESIZESET gpWTQueueSizeSet = NULL;
WTDATAPEEK gpWTDataPeek = NULL;
WTPACKETSGET gpWTPacketsGet = NULL;
// TODO - add more wintab32 function pointers as needed
char* gpszProgramName = NULL;
#define GETPROCADDRESS(type, func) \
gp##func = (type)GetProcAddress(ghWintab, #func); \
if (!gp##func){ WACOM_ASSERT(FALSE); UnloadWintab(); return FALSE; }
//////////////////////////////////////////////////////////////////////////////
// Purpose
// Find wintab32.dll and load it.
// Find the exported functions we need from it.
//
// Returns
// TRUE on success.
// FALSE on failure.
//
BOOL LoadWintab( void )
{
ghWintab = LoadLibraryA( "Wintab32.dll" );
if ( !ghWintab )
{
DWORD err = GetLastError();
WACOM_TRACE("LoadLibrary error: %i\n", err);
ShowError("Could not load Wintab32.dll");
return FALSE;
}
// Explicitly find the exported Wintab functions in which we are interested.
// We are using the ASCII, not unicode versions (where applicable).
GETPROCADDRESS( WTOPENA, WTOpenA );
GETPROCADDRESS( WTINFOA, WTInfoA );
GETPROCADDRESS( WTGETA, WTGetA );
GETPROCADDRESS( WTSETA, WTSetA );
GETPROCADDRESS( WTPACKET, WTPacket );
GETPROCADDRESS( WTCLOSE, WTClose );
GETPROCADDRESS( WTENABLE, WTEnable );
GETPROCADDRESS( WTOVERLAP, WTOverlap );
GETPROCADDRESS( WTSAVE, WTSave );
GETPROCADDRESS( WTCONFIG, WTConfig );
GETPROCADDRESS( WTRESTORE, WTRestore );
GETPROCADDRESS( WTEXTSET, WTExtSet );
GETPROCADDRESS( WTEXTGET, WTExtGet );
GETPROCADDRESS( WTQUEUESIZESET, WTQueueSizeSet );
GETPROCADDRESS( WTDATAPEEK, WTDataPeek );
GETPROCADDRESS( WTPACKETSGET, WTPacketsGet );
// TODO - don't forget to NULL out pointers in UnloadWintab().
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
// Purpose
// Uninitializes use of wintab32.dll
//
// Returns
// Nothing.
//
void UnloadWintab( void )
{
WACOM_TRACE( "UnloadWintab()\n" );
if ( ghWintab )
{
FreeLibrary( ghWintab );
ghWintab = NULL;
}
gpWTOpenA = NULL;
gpWTClose = NULL;
gpWTInfoA = NULL;
gpWTPacket = NULL;
gpWTEnable = NULL;
gpWTOverlap = NULL;
gpWTSave = NULL;
gpWTConfig = NULL;
gpWTGetA = NULL;
gpWTSetA = NULL;
gpWTRestore = NULL;
gpWTExtSet = NULL;
gpWTExtGet = NULL;
gpWTQueueSizeSet = NULL;
gpWTDataPeek = NULL;
gpWTPacketsGet = NULL;
}
//////////////////////////////////////////////////////////////////////////////
// Purpose
// Display error to user.
//
void ShowError( char *pszErrorMessage )
{
WACOM_TRACE( "ShowError()\n" );
WACOM_ASSERT( pszErrorMessage );
MessageBoxA( NULL, pszErrorMessage, gpszProgramName, MB_OK | MB_ICONHAND );
}
#ifdef WACOM_DEBUG
//////////////////////////////////////////////////////////////////////////////
void WacomTrace( char *lpszFormat, ...)
{
char szTraceMessage[ 128 ];
int nBytesWritten;
va_list args;
WACOM_ASSERT( lpszFormat );
va_start( args, lpszFormat );
nBytesWritten = _vsnprintf( szTraceMessage, sizeof( szTraceMessage ) - 1,
lpszFormat, args );
if ( nBytesWritten > 0 )
{
OutputDebugStringA( szTraceMessage );
}
va_end( args );
}
#endif // WACOM_DEBUG

@ -1,94 +0,0 @@
/*----------------------------------------------------------------------------
NAME
Utils.h
PURPOSE
Defines for the general-purpose functions for the WinTab demos.
COPYRIGHT
Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved
All rights reserved.
---------------------------------------------------------------------------- */
#pragma once
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include <wintab.h> // NOTE: get from wactab header package
//////////////////////////////////////////////////////////////////////////////
#define WACOM_DEBUG
// Ignore warnings about using unsafe string functions.
#pragma warning( disable : 4996 )
//////////////////////////////////////////////////////////////////////////////
// Function pointers to Wintab functions exported from wintab32.dll.
typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID );
typedef HCTX ( API * WTOPENA )( HWND, LPLOGCONTEXTA, BOOL );
typedef BOOL ( API * WTGETA ) ( HCTX, LPLOGCONTEXT );
typedef BOOL ( API * WTSETA ) ( HCTX, LPLOGCONTEXT );
typedef BOOL ( API * WTCLOSE ) ( HCTX );
typedef BOOL ( API * WTENABLE ) ( HCTX, BOOL );
typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID );
typedef BOOL ( API * WTOVERLAP ) ( HCTX, BOOL );
typedef BOOL ( API * WTSAVE ) ( HCTX, LPVOID );
typedef BOOL ( API * WTCONFIG ) ( HCTX, HWND );
typedef HCTX ( API * WTRESTORE ) ( HWND, LPVOID, BOOL );
typedef BOOL ( API * WTEXTSET ) ( HCTX, UINT, LPVOID );
typedef BOOL ( API * WTEXTGET ) ( HCTX, UINT, LPVOID );
typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int );
typedef int ( API * WTDATAPEEK ) ( HCTX, UINT, UINT, int, LPVOID, LPINT);
typedef int ( API * WTPACKETSGET ) (HCTX, int, LPVOID);
// TODO - add more wintab32 function defs as needed
//////////////////////////////////////////////////////////////////////////////
extern char* gpszProgramName;
// Loaded Wintab32 API functions.
extern HINSTANCE ghWintab;
extern WTINFOA gpWTInfoA;
extern WTOPENA gpWTOpenA;
extern WTGETA gpWTGetA;
extern WTSETA gpWTSetA;
extern WTCLOSE gpWTClose;
extern WTPACKET gpWTPacket;
extern WTENABLE gpWTEnable;
extern WTOVERLAP gpWTOverlap;
extern WTSAVE gpWTSave;
extern WTCONFIG gpWTConfig;
extern WTRESTORE gpWTRestore;
extern WTEXTSET gpWTExtSet;
extern WTEXTGET gpWTExtGet;
extern WTQUEUESIZESET gpWTQueueSizeSet;
extern WTDATAPEEK gpWTDataPeek;
extern WTPACKETSGET gpWTPacketsGet;
// TODO - add more wintab32 function pointers as needed
//////////////////////////////////////////////////////////////////////////////
BOOL LoadWintab( void );
void UnloadWintab( void );
void ShowError( char *pszErrorMessage );
//////////////////////////////////////////////////////////////////////////////
#ifdef WACOM_DEBUG
void WacomTrace( char *lpszFormat, ...);
#define WACOM_ASSERT( x ) assert( x )
#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__)
#else
#define WACOM_TRACE(...)
#define WACOM_ASSERT( x )
#endif // WACOM_DEBUG