header wacom home tab bar home

Notes for Tablet Aware Application Developers

Audience

This document is mainly intended to assist developers who already have tablet aware applications and want to add new capabilities to their applications. You should already be able to access the tablet data and capabilities. Developers who are adding tablet features for the first time should start with the Overview section, and examine the sample code.

Any questions concerning this document or any aspects of using Wintab with Wacom products can be directed to: developer@wacom.com

Overview

Applications receive tablet-specific data by using the Wintab Application Programmers Interface. Wintab is an industry standard for interfacing with pointing devices. Not all features of the Wintab interface are supported and some pointing devices support feature while others do not. Information on Wintab, including a developers’ SDK can be obtained from the Windows download sample code at: http://www.wacomeng.com/windows/index.html. The TiltTest program which is included with this implementers guide is a good example of how to use Wintab to get tablet data.

There are two main points in an application where modifications may be made to support tablets:

  1. Initialization

    During initialization you need to:

    1. Determine if a tablet is attached by looking for the Wintab interface. Call the Wintab function WTInfo(0, 0, NULL) to see if Wintab is present.

    2. Use WTInfo() to get static information about the tablet, such as tablet dimensions, coordinate resolution, the presence of tilt, pressure range, tangential pressure range, and other features.

    3. Create at least one Wintab context for your application. Get a default context using WTInfo() and use it as a template to create your own tablet context. Set up the context as appropriate for your application. Applications can open two kinds of contexts: system contexts and digitizing contexts. http://www.sigchi.org/chi97/proceedings/video/gf2.htmWintab moves the system cursor on behalf of the application for system contexts, while applications must move the system cursor themselves for digitizing contexts. Most applications use system contexts. The user can change the area of a system context to make navigation easier. Digitizer contexts usually cover the entire tablet. Digitizer contexts are used for digitizing or to define tablet menus. Setting up the context includes determining what data items will be included in the packets. Although the documentation says you can not include items in the packet that are not supported by the tablet, it appears that this is incorrect. Unsupported items may be included and will be set to zero. Then call WTOpen() to create your context so you can begin processing packet data.

    4. Wintab passes data for a tablet point, such as coordinates, pressure and tilt, to an application as a Wintab packet. By default, the packet queue for a context is very small and can easily overflow. Applications should guard against overflowing their queues by increasing their context’s queue sizes using WTQueueSizeSet().

  2. Message Handling

    During device operation, you will get data from the tablet. This data is used for line rendering or navigation. You may need to find additional information about the tablet device currently in use. This device information can be used to change tools or screen cursors, for example, when a stylus eraser is placed in use or when tools are changed based on device ID.

    The following Windows messages should be handled.

    1. WM_LBUTTONDOWN / WM_LBUTTONUP message (for stylus buttons)

      On WM_LBUTTONDOWN the packets in the tablet queue should be flushed using, for example, WTPacketsGet() (since they are old). If you are very particular, you may want to flush all packets up to the one with the button pressed and use the rest for drawing. Set a flag indicating packet events should now be processed and drawn. On WM_LBUTTONUP clear the flag and stop processing packets. Again, if you are particular, on the WM_LBUTTONUP event process the packets in the queue that correspond to the button press state.

    2. WT_PACKET message (usually during a button down)

      In the draw loop (usually continuously done between WM_LBUTTONDOWN and WM_LBUTTONUP), tablet data is read from packets and used to modify the rendering of the line being drawn. Data such as current pressure, tilt angles, and fingerwheel values are used to change rendering parameters like opacity, brush direction, line thickness, and so forth. Wintab stores packets in a context-unique packet queue until the application that opened the context requests packet data using a Wintab function such as WTPacket().

      When applications open a context they pass Wintab a window handle. If the application sets the context’s CXO_MESSAGES option, the window receives notification that a packet has been added to the queue via the WT_PACKET message. This event contains the serial number for the packet that generated the event. Upon receiving the event, call WTPacket() with the serial number provided in the message.

      CAUTION! If the queue overflows, Wintab stops informing the application that packets have been queued, and it discards the subsequently received packets until the queue is no longer full. Be sure to avoid overflow by draining the queue during WT_PACKET messages.

    3. WT_CSRCHANGE (and/or WT_PROXIMITY) message

      When a pointing device enters or leaves a context, the application that opened the context is notified through the WT_PROXIMITY message. When a different pointing device enters proximity of the context, the application is informed through a WT_CSRCHANGE message, if the application requested this message when the context was created. When an application receives a WT_PROXIMITY and/or WT_CSRCHANGE message, it can call WTInfo() to get information about the pointing device, such as number of buttons on the device, which end of the stylus is in use, or the device’s physical ID. This message is very useful for changing drawing tools. The selected tool (and/or screen cursor) should change when the pointing device is first brought into use, not when drawing starts. Therefore, you will want to check for tip vs. eraser, and check the Unique ID at this point.

    4. WT_PACKET message (without a button down)

      You may want to look at device information for navigational purposes, such as rotating an object with the stylus tilt. You can do this by always reading tablet packets in response to WT_PACKET events, even when a button is not down. For example, if you are using a 4D Mouse for navigation, current device information can be used to modify an object’s position or to modify your own viewpoint.

Notes

With some exceptions the Wacom driver implements the Wintab specification version 1.1 as published by LCS/Telegraphics. The specification version returned by the Wacom driver is 1.4. A copy of this specification is included in the Windows download sample code at: http://www.wacomeng.com/windows/index.html

// Check the Wintab version in this manner
WORD thisVersion;
WTInfo(WTI_INTERFACE, IFC_SPECVERSION, &thisVersion); 

Version 1.2 added CSR_TYPE which is needed to carry information for Unique ID.

Version 1.3 add a now depricated incomplete extension for express keys. (WTX_EXPKEYS is not supported and has been replaced by WTX_EXPKEYS2)

Version 1.4 adds an updated extension for express keys and also adds extensions for touch strips and touch rings. (WTX_EXPKEYS2, WTX_TOUCHSTRIP, WTX_TOUCHRING)

You should not have to change any code to support the features you currently support, you simply add code to support new features. The depricated express key implementation of 1.3 will not return unsupported.

The latest header files, WINTAB.H and PKTDEF.H are included with the Windows download sample code at: http:://www.wacomeng.com/windows/index.html. These files bring the data structures up to specification 1.4, and add the 1.2 feature (CSR_TYPE).

Wintab holds all open contexts for all applications in a single overlaping container for each tablet. It uses the overlap order to decide which context should process each tablet packet. Each packet is put in only one context’s packet queue. In general, if context A is above context B in the overlap order, context A will receive tablet packets and context B will not. Applications bring their contexts to the top or bottom of the overlap order by calling WTOverlap(). Many applications fail to properly handle their context ordering. This causes simultaneously executing Wintab applications to stop working or to behave unpredictably. When applications receive the WM_ACTIVATE message, they should push their contexts to the bottom of the overlap order if their application is being deactivated, and should bring their context to the top if they are being activated. Applications should also disable their contexts when they are minimized.

The Wacom implentation of Wintab will manage the context order for the application. This means that the application will only get data when that application has keyboard focus. We did this because too many applications do not correctly handle their own contexts. Please help us out by correctly managing your contexts so some day we can remove this code.

It is best to have at least two undo buffers, or one more than the desired number. Don’t flush the undo buffer on a button down when you are about to draw, it takes too long. Flush the buffer on a button up. This will improve the beginning of your strokes.

Features You Should Already Have Implemented

Eraser and Tilt are features that have been around for some time. A large installed base of tablets supports these capabilities and, if you have not already done so, you can increase the power and performance of your application by implementing these features.

New Features to Implement

New features introduced with the Intuos series tablets include: Unique ID , Airbrush Fingerwheel, 4D Mouse Rotation, and 4D Mouse Thumbwheel. If your application already supports Wintab then these features are VERY easy to add. An old feature which is now fully supported is Dual Track.

Extensions

EXPKEYSDATA structure

typedef struct tagEXPKEYSDATA { /* 1.4 */
    BYTE    nTablet;    // index of the tablet
    BYTE    nControl;   // position index of the control
    BYTE    nLocation;  // location of the control
    BYTE    nReserved;  //
    DWORD   nState;     // state of the control (1 - pressed, 0 - released)
} EXPKEYSDATA;

This structure is returned as part of the PACKETEXT structure.

SLIDERDATA structure

typedef struct tagSLIDERDATA { /* 1.4 */
    BYTE    nTablet;    // index of the tablet
    BYTE    nControl;   // position index of the control
    BYTE    nFunction;  // control function index
    BYTE    nReserved;  //
    DWORD   nPosition;  // position of the finger on the control (zero for no touch)
} SLIDERDATA;

This structure is returned as part of the PACKETEXT structure.

EXTPROPERTY structure

typedef struct tagEXTPROPERTY { /* 1.4 */
    BYTE    version;        // Structure version, 0 for now
    BYTE    tabletIndex;    // 0-based index for tablet
    BYTE    controlIndex;   // 0-based index for control 
    BYTE    functionIndex;  // 0-based index for control's sub-function
    WORD    propertyID;     // property ID
    WORD    reserved;       // DWORD-alignment filler
    DWORD   dataSize;       // number of bytes in data[] buffer
    BYTE    data[1];        // raw data
} EXTPROPERTY;

This structure is used for WTExtGet and WTExtSet.

Note that this stucture is of variable size. The total size of the structure is sizeof(EXTPROPERTY) + dataSize. Take care to allocate the correct amount of memory before using this structure.