:mod:`wintab` --- Wrapper around the Wintab Developer Kit
=========================================================

.. module:: cgkit.wintab
   :synopsis: Wrapper around the Wintab Developer Kit


The Wintab specification is an open industry standard interface that provides
access to pointing devices such as a pen tablet, for example. The API was
developed by `LCS/Telegraphics <http://www.pointing.com/>`_.

The :mod:`wintab` module is a wrapper around the Wintab Developer Kit and can be
used to add tablet support to your Python application. Before you can get any
data from the tablet you have to create an instance of the :class:`Context`
class, set the desired parameters and open the context. Once the context is open
you will either receive messages from the tablet driver or you can poll the
current tablet state. Either way, you will receive the tablet data via
:class:`Packet` objects that contain all the data that was generated by the
tablet. See also the Wintab Interface Specification at
`<http://www.wacomeng.com/devsupport/index.html>`_ for more detailed usage information.

The constants used in this module are either available in the  :mod:`wintab`
module or in the :mod:`wintab.constants` module. The latter can be used if you
want to import only the constants into your namespace.

.. function:: available()

   Returns ``True`` if the Wintab functionality is available. As the Wintab
   Developer Kit is only available on Windows, this function will always return
   ``False`` on other operating systems.

   On Windows, this function can still return ``False`` if either the Wintab
   drivers are not installed or cgkit was compiled without Wintab support.

   If this function returns ``False``, an exception will be raised whenever you try
   to call another function or instantiate a class from this module.

.. function:: info(category)

   This function returns a dictionary with global information about the  interface.
   *category* specifies the category from which information is being requested. It
   can be one of the values in the following table:

   +----------------------+---------------------------------------------+
   | Category             | Description                                 |
   +======================+=============================================+
   | ``WTI_INTERFACE``    | Global interface identification and         |
   |                      | capability information                      |
   +----------------------+---------------------------------------------+
   | ``WTI_STATUS``       | Current interface resource usage statistics |
   +----------------------+---------------------------------------------+
   | ``WTI_DEFCONTEXT``   | ...                                         |
   +----------------------+---------------------------------------------+
   | ``WTI_DEFSYSCTX``    | ...                                         |
   +----------------------+---------------------------------------------+
   | ``WTI_DEVICES+n``    | Capability and status information for a     |
   |                      | device                                      |
   +----------------------+---------------------------------------------+
   | ``WTI_CURSORS+n``    | Capability and status information for a     |
   |                      | cursor                                      |
   +----------------------+---------------------------------------------+
   | ``WTI_EXTENSIONS+n`` | Descriptive information and defaults for an |
   |                      | extension                                   |
   +----------------------+---------------------------------------------+
   | ``WTI_DDCTXS``       | ...                                         |
   +----------------------+---------------------------------------------+
   | ``WTI_DSCTXS``       | ...                                         |
   +----------------------+---------------------------------------------+

.. note::

   The module uses the Wintab Programmer's Kit which can be found at
   `<http://www.wacomeng.com/devsupport/index.html>`_.

   *The Wintab Programmer's Kit is copyright 1991-1998 by LCS/Telegraphics.*


Context class
-------------

The :class:`Context` class provides the interface to the tablet driver.


.. class:: Context()

   The class takes no parameters. All the context attributes will be initialized
   with the default values as provided by the driver.

Context attributes:


.. attribute:: Context.name

   Context name.


.. attribute:: Context.options

   Specifies options for the context and must be a combination of the following
   flags:

   +---------------------+---------------------------------------------+
   | Option              | Description                                 |
   +=====================+=============================================+
   | ``CXO_SYSTEM``      | The context is a system cursor context      |
   +---------------------+---------------------------------------------+
   | ``CXO_PEN``         | The context is a Pen Windows (and system    |
   |                     | cursor) context                             |
   +---------------------+---------------------------------------------+
   | ``CXO_MESSAGES``    | The context sends WT_PACKET messages to its |
   |                     | owner                                       |
   +---------------------+---------------------------------------------+
   | ``CXO_MARGIN``      | The input context will have a margin        |
   +---------------------+---------------------------------------------+
   | ``CXO_MGNINSIDE``   | The margin will be inside the specified     |
   |                     | context                                     |
   +---------------------+---------------------------------------------+
   | ``CXO_CSRMESSAGES`` | The context sends WT_CSRCHANGE messages to  |
   |                     | its owner                                   |
   +---------------------+---------------------------------------------+


.. attribute:: Context.status

   Specifies current status conditions for the context. The status value is a
   combination of the following bits:

   +------------------+--------------------------------------------+
   | Status bit       | Description                                |
   +==================+============================================+
   | ``CXS_DISABLED`` | The context has been disabled              |
   +------------------+--------------------------------------------+
   | ``CXS_OBSCURED`` | The context is at least partially obscured |
   |                  | by another context                         |
   +------------------+--------------------------------------------+
   | ``CXS_ONTOP``    | The context is the topmost context         |
   +------------------+--------------------------------------------+


.. attribute:: Context.locks

   Specifies which attributes of the context the application wishes to be  locked.
   The value can be a combination of the following bits:

   +---------------------+-------------------------------------------+
   | Lock                | Description                               |
   +=====================+===========================================+
   | ``CXL_INSIZE``      | The input size cannot be changed          |
   +---------------------+-------------------------------------------+
   | ``CXL_INASPECT``    | The input aspect ration cannot be changed |
   +---------------------+-------------------------------------------+
   | ``CXL_MARGIN``      | The margin options cannot be changed      |
   +---------------------+-------------------------------------------+
   | ``CXL_SENSITIVITY`` | The sensitivity settings for x, y and z   |
   |                     | cannot be changed                         |
   +---------------------+-------------------------------------------+
   | ``CXL_SYSOUT``      | The system pointing control variables     |
   |                     | cannot be changed                         |
   +---------------------+-------------------------------------------+


.. attribute:: Context.msgbase

   Base number for the message IDs.


.. attribute:: Context.device

   Specifies the device whose input the context processes.


.. attribute:: Context.pktrate

   Specifies the desired packet report rate in Hertz. Once the context is open,
   this field will contain the actual report rate.


.. attribute:: Context.pktdata

   Specifies which optional data items will be in packets returned from the
   context.


.. attribute:: Context.pktmode

   Specifies whether the packet data items will be returned in absolute or relative
   mode. If the item's bit is set in this field, the item will be returned in
   relative mode.


.. attribute:: Context.movemask

   Specifies which packet data items can generate move events in the context.


.. attribute:: Context.btndnmask

   Specifies the buttons for which button press events will be processed in the
   context.


.. attribute:: Context.btnupmask

   Specifies the buttons for which button release events will be processed in the
   context.


.. attribute:: Context.inorgx

   Specifies the origin of the context's input area in the tablet's native
   coordinates along the x axis.


.. attribute:: Context.inorgy

   Specifies the origin of the context's input area in the tablet's native
   coordinates along the y axis.


.. attribute:: Context.inorgz

   Specifies the origin of the context's input area in the tablet's native
   coordinates along the z axis.


.. attribute:: Context.inextx

   Specifies the extent of the context's input area in the tablet's native
   coordinates along the x axis.


.. attribute:: Context.inexty

   Specifies the extent of the context's input area in the tablet's native
   coordinates along the y axis.


.. attribute:: Context.inextz

   Specifies the extent of the context's input area in the tablet's native
   coordinates along the z axis.


.. attribute:: Context.outorgx

   Specifies the extent of the context's output area in context output coordinates
   along the x axis.


.. attribute:: Context.outorgy

   Specifies the extent of the context's output area in context output coordinates
   along the y axis.


.. attribute:: Context.outorgz

   Specifies the extent of the context's output area in context output coordinates
   along the z axis.


.. attribute:: Context.outextx

   Specifies the extent of the context's output area in context output coordinates
   along the x axis.


.. attribute:: Context.outexty

   Specifies the extent of the context's output area in context output coordinates
   along the y axis.


.. attribute:: Context.outextz

   Specifies the extent of the context's output area in context output coordinates
   along the z axis.


.. attribute:: Context.sensx

   Specifies the relative-mode sensitivity factor for the x axis.


.. attribute:: Context.sensy

   Specifies the relative-mode sensitivity factor for the y axis.


.. attribute:: Context.sensz

   Specifies the relative-mode sensitivity factor for the z axis.


.. attribute:: Context.sysmode

   Specifies the system cursor tracking mode. ``True`` specifies absolute,
   ``False`` means relative.


.. attribute:: Context.sysorgx

   Specifies the origin in screen coordinates of the screen mapping area for system
   cursor tracking.


.. attribute:: Context.sysorgy

   Specifies the origin in screen coordinates of the screen mapping area for system
   cursor tracking.


.. attribute:: Context.sysextx

   Specifies the extent in screen coordinates of the screen mapping area for system
   cursor tracking.


.. attribute:: Context.sysexty

   Specifies the extent in screen coordinates of the screen mapping area for system
   cursor tracking.


.. attribute:: Context.syssensx

   Specifies the system-cursor relative-mode sensitivity factor for the x axis.


.. attribute:: Context.syssensy

   Specifies the system-cursor relative-mode sensitivity factor for the y axis.

Other attributes:


.. attribute:: Context.queuesize

   The number of packets the context's queue can hole. Setting this attribute may
   result in an exception if the queue size could not be set. In such a case, you
   must try again with a smaller value.


.. attribute:: Context.id_packet

   The final id of the WT_PACKET message.


.. attribute:: Context.id_csrchange

   The final id of the WT_CSRCHANGE message.


.. attribute:: Context.id_ctxopen

   The final id of the WT_CTXOPEN message.


.. attribute:: Context.id_ctxclose

   The final id of the WT_CTXCLOSE message.


.. attribute:: Context.id_ctxupdate

   The final id of the WT_CTXUPDATE message.


.. attribute:: Context.id_ctxoverlap

   The final id of the WT_CTXOVERLAP message.


.. attribute:: Context.id_proximity

   The final id of the WT_PROXIMITY message.


.. attribute:: Context.id_infochange

   The final id of the WT_INFOCHANGE message.

Methods:


.. method:: Context.open(hwnd, enable)

   Opens the context. *hwnd* is the window handle (as integer) of the window that
   owns the context and that receives messages from the context. *enable* is a
   boolean that specifies whether the context will immediately begin processing
   input data.

   Set the context attributes to the desired values before calling this method.
   Modifying context attributes after the context was opened is possible with the
   :meth:`set` method.


.. method:: Context.restore(hwnd, saveinfo, enable)

   This method is equivalent to the :meth:`open` method with the only difference
   that it takes the context attributes via the binary *saveinfo* string which was
   returned by the :meth:`save` method in a previous session.


.. method:: Context.close()

   Closes the context if it was open (or do nothing if it was already closed or if
   it was not open at all).


.. method:: Context.save()

   Returns a binary *saveinfo* string containing the current context state. This
   string can be used as argument to the :meth:`restore` method.


.. method:: Context.packet(serial)

   Returns the packet with the specified serial number.


.. method:: Context.enable(flag)

   If *flag* is ``True`` the context is enabled, otherwise it is disabled. Returns
   ``True`` if the operation was successful.


.. method:: Context.overlap(totop)

   If *totop* is ``True`` the context will become the topmost context, otherwise it
   will be send to the bottom. Returns ``True`` if the operation was successful.


.. method:: Context.config(hwnd=0)

   Prompts the user for changes to the context via a dialog box. *hwnd* is the
   window handle of the window that will be parent of the dialog. If it is 0, the
   context owning window will be used. The return value is ``True`` if the context
   was changed.


.. method:: Context.get()

   Update the local context attributes.


.. method:: Context.set()

   Update the tablet context with the settings stored in the local context
   attributes.


.. method:: Context.packetsGet(maxpkts)

   Return the next *maxpkts* packets and remove them from the queue.


.. method:: Context.packetsPeek(maxpkts)

   Return the next *maxpkts* packets without removing them from the queue.


.. method:: Context.dataGet(begin, end, maxpkts)

   Return all packets with serial numbers between *begin* and *end* inclusive and
   remove them from the queue. However, no more than *maxpkts* packets are
   returned. The return value is a 2-tuple (*numpackets*, *packet list*) where
   *numpackets* is the total number of packets found in the queue between *begin*
   and *end*.


.. method:: Context.dataPeek(begin, end, maxpkts)

   This is the same as :meth:`dataGet` but it doesn't remove the packets from the
   queue.


.. method:: Context.queuePacketsEx()

   Returns the serial numbers of the oldest and newest packets currently in the
   queue.

.. % ------------------------------------------------------------------


Packet class
------------


.. class:: Packet()


.. attribute:: Packet.pktdata

   This is a copy of the ``pktdata`` attribute of the corresponding context, i.e.
   this attribute determines which of the following attributes are actually valid.


.. attribute:: Packet.context

   Specifies the context that generated the event.


.. attribute:: Packet.status

   Contains a combination of the following status and error conditions:

   +-------------------+--------------------------------------------+
   | Status bit        | Description                                |
   +===================+============================================+
   | ``TPS_PROXIMITY`` | The cursor is out of the context           |
   +-------------------+--------------------------------------------+
   | ``TPS_QUEUE_ERR`` | The event queue for the context has        |
   |                   | overflowed                                 |
   +-------------------+--------------------------------------------+
   | ``TPS_MARGIN``    | The cursor is in the margin of the context |
   +-------------------+--------------------------------------------+
   | ``TPS_GRAB``      | The cursor is out of the context, but the  |
   |                   | context has grabbed input                  |
   +-------------------+--------------------------------------------+
   | ``TPS_INVERT``    | The cursor is in its inverted state        |
   +-------------------+--------------------------------------------+


.. attribute:: Packet.time

   In absolute mode, specifies the system time at which the event was posted. In
   relative mode, specifies the elapsed time in milliseconds since the last packet.


.. attribute:: Packet.changed

   Specifies which of the included packet data items have changed since the
   previously posted event.


.. attribute:: Packet.serial

   Contains a serial number assigned to the packet by the context.


.. attribute:: Packet.cursor

   Specifies which cursor type generated the packet.


.. attribute:: Packet.buttons

   In absolute, contains the current button state. In relative mode, the low word
   contains a button number and the high word contains one of the following codes:
   ``TBN_NONE`` if there was no change in button state, ``TBN_UP`` if the button
   was released or ``TBN_DOWN`` if the button was pressed.


.. attribute:: Packet.x

   In absolute mode, contains the scaled cursor location along the x axis. In
   relative mode, contains the scaled change in cursor position.


.. attribute:: Packet.y

   In absolute mode, contains the scaled cursor location along the y axis. In
   relative mode, contains the scaled change in cursor position.


.. attribute:: Packet.z

   In absolute mode, contains the scaled cursor location along the z axis. In
   relative mode, contains the scaled change in cursor position.


.. attribute:: Packet.normalpressure

   In absolute mode, contains the adjusted state of the normal pressure. In
   relative mode, contains the change in adjusted pressure state.


.. attribute:: Packet.tangentpressure

   In absolute mode, contains the adjusted state of the tangential pressure. In
   relative mode, contains the change in adjusted pressure state.


.. attribute:: Packet.orient_azimuth

   Specifies the clockwise rotation of the cursor about the z axis through a full
   circular range.


.. attribute:: Packet.orient_altitude

   Specifies the angle with the x-y plane through a signed, semicircular range.


.. attribute:: Packet.orient_twist

   Specifies the clockwise rotation of the cursor about its own major axis.


.. attribute:: Packet.rot_pitch

   Specifies the pitch of the cursor.


.. attribute:: Packet.rot_roll

   Specifies the roll of the cursor.


.. attribute:: Packet.rot_yaw

   Specifies the yaw of the cursor.