Wacom Tablet on OS X

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
MrTutu
Knows some wx things
Knows some wx things
Posts: 28
Joined: Tue Oct 03, 2006 10:21 am

Wacom Tablet on OS X

Post by MrTutu » Thu Jan 04, 2007 10:57 am

Hi,

Did anybody already try to capture tablet events with wxWidgets on OS X? My application needs the pen pressure sensitivity. I already have the tablet working on Windows by overloading wxWindow::MSWWindowProc in my main window, but on Mac it doesn't look that easy.

Thanks

PixelMachine
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jul 20, 2006 10:42 pm

Post by PixelMachine » Mon Mar 01, 2010 3:35 pm

I've managed to implement tablet support for wxmsw.
In OS X, however, I needed to modify the source:
I've modified the wxMouseEvent class and added a float member, m_tabletPressure;
In toplevel.cpp, I'm modifying the wxMacTopLevelMouseEventHandler function, adding the pressure data to the mouse event to be sent to the appropiate window.
I'm using this code to set the pressure data:

Code: Select all

// BEGIN ADDED
	UInt32 tabletEventType = 0;
        GetEventParameter((EventRef)event, kEventParamTabletEventType, typeUInt32, 0,
                                                sizeof(tabletEventType), 0, &tabletEventType);
        if (tabletEventType == kEventTabletPoint)
        {
                TabletPointRec tabletPointRec;
                GetEventParameter((EventRef)event, kEventParamTabletPointRec, typeTabletPointRec, 0,
                              sizeof(tabletPointRec), 0, &tabletPointRec);
				wxevent.m_tabletPressure=(float)(tabletPointRec.pressure / (float)(0xffff));
        }
	// END ADDED 
right after the

Code: Select all

SetupMouseEvent( wxevent , cEvent ) ; 
line.
I've taken the code sample above from another post in this forum: http://forums.wxwidgets.org/viewtopic.p ... ght=tablet
I'm yet to test it these days, I hope it's working.

User avatar
doublemax
Moderator
Moderator
Posts: 15186
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Mar 01, 2010 3:56 pm

I'd be interested to see your MSW code for tablet support if you're willing to share it.
Use the source, Luke!

PixelMachine
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jul 20, 2006 10:42 pm

Post by PixelMachine » Mon Mar 01, 2010 11:05 pm

I'm using a glcanvas derived window.
I've added this to the class declaration:

Code: Select all

#ifdef __WXMSW__
	HCTX tabletcontext;
	unsigned int oldpressure, maxpressure, minpressure;
	
	WXLRESULT MSWWindowProc ( WXUINT message, WXWPARAM wParam, WXLPARAM lParam ); 
#endif
Then initialize the tablet somewhere in the initialization code:

Code: Select all

AXIS TpPres;
	if (WTInfo(0, 0, NULL))
	{
		istablet=1;
		char	WName[50]; 
		WTInfo(WTI_DEVICES, DVC_NAME, WName);
		tabletname.Printf("%s", WName);
	}

	if(!istablet)
		Log("No tablet found\n");
	else
	{
		Log("Found tablet: ");
		Log((char *) tabletname.c_str());
		Log("\n");
		
		LOGCONTEXT      lcMine;           // The context of the tablet

		//TABLET: get current settings as a starting point for this context of the tablet.
		//WTInfo(WTI_DEFCONTEXT, 0, &lcMine);	// default settings may be different to current settings
		WTInfo(WTI_DEFSYSCTX, 0, &lcMine);	// current settings as set in control panel
		WTInfo(WTI_DEVICES,DVC_NPRESSURE,&TpPres);
		wxString str;
		str.Printf("Tablet pen min pressure level: %d\n", (unsigned int) (TpPres.axMin));
		Log((char *) str.c_str());
		str.Printf("Tablet pen max pressure level: %d\n", (unsigned int) (TpPres.axMin));
		Log((char *) str.c_str());
		minpressure=(unsigned int) (TpPres.axMin);
		maxpressure=(unsigned int) (TpPres.axMax);

		lcMine.lcOptions |= CXO_MESSAGES;	// keep existing options and make sure message handling is on for this context
		//TABLET: PACKETDATA must be defined FIRST before including pktdef.h. See the header file of this class for more details
		lcMine.lcPktData = PACKETDATA;	// these settings MUST be defined in the pktdef.h file, see notes
		lcMine.lcPktMode = PACKETMODE;
		lcMine.lcMoveMask = PACKETDATA;

		/* open the region */
		HWND            hWnd=(HWND)this->GetHandle();
		tabletcontext= WTOpen(hWnd, &lcMine, TRUE);
		if(tabletcontext)
			Log("Tablet successfully initialized\n");
		else
		{
			istablet=0;
			Log("Couldn't initialize tablet\n");
		}

	}
And then use a custom windows event handler function, to update the penpressure member value:

Code: Select all

WXLRESULT MyGLCanvas::MSWWindowProc ( WXUINT message, WXWPARAM wParam, WXLPARAM lParam )
{
	PACKET          pkt;
//	PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
	switch ( message )
	{
	case WT_PACKET: /* A packet is waiting from WINTAB */
		if (WTPacket((HCTX)lParam, wParam, &pkt)) 
		{
			penpressure = (float) pkt.pkNormalPressure;
			unsigned int newpressure=pkt.pkNormalPressure;
			if(oldpressure!=newpressure)
			{
				oldpressure=newpressure;
				if(oldpressure==0)
			oldpressure=maxpressure;
		        penpressure=(float)oldpressure/((float)(maxpressure-minpressure));
			}
		}
		break;
	}
	return wxGLCanvas::MSWWindowProc ( message, wParam, lParam );
} 

You also have to define this:

Code: Select all

#include <wintab.h>
#define PACKETDATA      (PK_NORMAL_PRESSURE)
#define PACKETMODE      0
#include <pktdef.h>

Also, you'll have to release the tablet context, when closing the app:

Code: Select all

if(istablet)
		if (tabletcontext)
		{
			Log("Closing tablet...\n");
			WTClose(tabletcontext);
			Log("Done\n");
		}

One more thing you should handle is to regain access to the tablet when another app is using it.
Add this when focus is received:

Code: Select all

if(istablet)
  WTOverlap( viewport->tabletcontext, TRUE );
and this when focus is lost:

Code: Select all

if(istablet)
  WTOverlap( viewport->tabletcontext, FALSE );
I'm only interested about the pressure data, so the setup is pretty simple.

User avatar
doublemax
Moderator
Moderator
Posts: 15186
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Mar 01, 2010 11:07 pm

Nice, thanks!
Use the source, Luke!

PixelMachine
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jul 20, 2006 10:42 pm

Post by PixelMachine » Mon Mar 01, 2010 11:17 pm

I've just tried the OS X stuff, doesn't work.
For some reason, the pressure is always set to 0.0, even if I modify it right after getting the pressure from the tablet.
I've also modified the Assign wxMouseEvent function, to have a working = operator and constructor, but doesn't work.

PixelMachine
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jul 20, 2006 10:42 pm

Post by PixelMachine » Thu Mar 04, 2010 7:34 pm

Looks like it was my mistake, was copying the dynlibs to the wrong place.
It's now working, so I have tablet support for both Windows and OS X (Carbon).
I hope I'll be able to implement something similar on Linux, with XInput or something.

User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: Wacom Tablet on OS X

Post by eranon » Mon Aug 24, 2015 6:38 pm

Hello,

About the code sample for MSW/Wintab above, did you successfully received the WT_PACKET events ? I tried in a wxGLCanvas derived class and, in spite of a tablet context with CXO_MESSAGES, the window never receives these packets event. I see the others Wintab events, but no WT_PACKET.

I tried to drain the packets queue before all too (since the Wintab documentation says that the tablet may stop to send WT_PACKET if the queue is full), but not better.

Also, I taken a try with the Pressure Test delivered in Wacom support page : it works with their test project (so, the tablet well sends the event), but not if I move the code toward a wxWidgets-based project... Next step is to do it starting from the minimal wxWidgets sample, of course, but I would like to know if there's a known problem you encountered on your side... If someone see this old (but still interesting) thread of course ^o^
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]

Post Reply