The Linux Wacom Project
SourceForge.net Logo

The Linux Wacom Project

Copyright (C) 2002-2006 - LinuxWacom

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled
GNU
Free Documentation License
.


History

2002-12-26 JEJ Document created from "John's Linux USB Wacom Page." Hosted at http://linuxwacom.sourceforge.net. Entire website is available by anonymous CVS.

1.0 - Recent News

This is a list of the updates for the past month or so. The ChangeLog has a more complete list.

June 5, 2007 - Updated xsetwacom suppress option. Merged Ron's building and configuration patches. Label 0.7.7-11.
 
May 29, 2007 - Fixed a typo in 2.6.16/wacom_wac.c. Label 0.7.7-10.
 
May 25, 2007 - Added 2 new xsetwacom potions (TVResolution0/1 and Screen_No). Added support for Bamboo. Split wcmXCommand.c from xf86Wacom.c.
 
May 18, 2007 - Added 2 new xsetwacom options (Common DebugLevel and TwinView). Increased MAX_SUPPRESS from 20 to 100. Added new xsetwacom option to change suppress. Fixed suppress bug (Allan Wind).
 
April 30, 2007 - Fixed a xsetwacom button and a relative wheel bug. label 0.7.7-9.
 
April 17, 2007 - Prepared for toggling CoreEvent option. Fixed bug 1698123.
 
March 30, 2007 - Updated acinclude.m4 to default to system running kernel.
 
March 29, 2007 - Incorporated patch 1680163 from Magnus Vigerlöf. Updated wacom man page, wacom.4x.
 
March 21, 2007 - Updated wacomcpl with new xsetwacom command. Removed xsetwacom GetModel option. - no more writing to file from Wacom X driver. label 0.7.7-7.
 
March 19, 2007 - Fixed bug 1675567. Updated cordinates initialization.
 
March 9, 2007 - Report screen cordinates through xsetwacom. Support I3 strips and relatvie wheel with. button and keystroke events through xsetwacom.
 
February 20, 2007 - Fixed an install typo. Fixed a dual Cintiq TwinView setup in wacom_drv.o.
 
February 16, 2007 - Updated install script to deal with broken uname -p. Support pad as core and non-core device. Support keystrokes. Support 2.6.19 (Magnus Vigerlöf). label 0.7.7-5.
 
February 2, 2007 - Updated kernel driver to report full out-prox data. Updated pad in X driver. Fine tuned outbound tracking. label 0.7.7-4.
 
January 29, 2007 - Added 3 new xsetwacom options. Updated wacom_wac.c and wacom.c for Intuos outbound tracking. label 0.7.7-3.
 
January 25, 2007 - Added support for Thinkpad X60t. label 0.7.7-2 for testing.
 
January 22, 2007 - Incorporated Magnus' patches.
 
January 19, 2007 - Split wacom.c for 2.6.15. Fixed bugs related to multiarea support.
 
January 15, 2007 - Split wacom.c for 2.6.14. Fixed wacom_sys.c in 2.6.11 and 2.6.13. Fixed bugs related to multiarea support.
 
January 11, 2007 - Incorporated patches 1630928, 1630926, and 1614296. Updated xidump to ignore uninitialized tools. Fixed kfree bug in wacom_sys.c for 2.6.13.
 
January 8, 2007 - Report raw tablet data in valuators for relative mode. Improve relative movement accuracy in general.
 
January 3, 2007 - Improve relative small movement accuracy. Reset pressure for relative in-prox event. to fix bug 1562718.
 
December 27, 2006 - label 0.7.7-1 for testing.
 
December 22, 2006 - Update install and uninstall scripts for prebuilt. X driver and its utility programs. Feature request #1519017 and patch #1614296. Patch #1606288. Updated web scripts.
 
December 11, 2006 - Split wacom.c under 2.6.13 into 4 files. Fixed an ExpressKeys report bug in wcmUSB.c. Removed duplicated sync event in wacom_wac.c (Magnus Vigerlöf).
 
December 1, 2006 - Updated xsetwacom.
 
November 30, 2006 - Fixed cursor relative out-prox issue. Changed CursorProx option from 2 inputs into 1. Updated xsetwacom and wacom_drv. Split wacom.c under 2.6.11 into 4 files. label 0.7.7 for testing.
 
November 21, 2006 - Updated web scripts (Magnus Vigerlöf). Removed serial number and device ID in 4th - 5th high bytes due to bug 1592814. label 0.7.6-3.
 
November 13, 2006 - Updated acinclude.m4 and configure.in (Mats Johannesson). Updated X driver for Xinerama setup. Removed option gimp.
 
October 31, 2006 - Updated acinclude.m4 and wacom.c. label 0.7.6-2.
 
October 24, 2006 - Fixed a relative mode acceleration problem. Updated webpages, acinclude.m4, and configure.in. Updated wacdump for TabletPC. Supports Graphire outbound tracking.
 
October 16, 2006 - Updated README and NEWS.
 
October 13, 2006 - Removed 2.4 kernel unchanged lines. label 0.7.6-1.
 
October 9, 2006 - Updated install scripts to install wacom man. page, wacom.4x.gz, under /usr/share/man/man4. Updated release version to 0.7.6. Ready to label the source.
 
October 6, 2006 - Updated xf86Wacom.h to support Xorg 7.1. Fixed a bug in src/2.6.16/wacom_sys.c. Updates xidump and xsetwacom.
 
October 3, 2006 - Updated configure.in and acinclude.m4 for x86_64. Updated src/2.6.16/wacom_sys.c to sync with kernel.org.
 
September 27, 2006 - Updated wacserial.c (Adam Marmbrant). Updated package configuration scripts. (Patch 1538734, Magnus Vigerlöf and Kai Sattler).
 
September 22, 2006 - Updated wacom man page, wacom.4x. Updated wacdump. Fixed an I3 and Cintiq 21UX pad out-prox bit (Martin Wawro). Applied TabletPC button XFree86 workaround to Xorg.
 

2.0 - Frequently Asked Questions

This FAQ is based on the questions that I receive in email. If you have a question that is not answered here, send me email directly. Please add the word "WACOM" to the subject line to help me distinguish your message from the spam I normally receive.

Index




Who is responsible for this code?

We are. That is, Linux users with Wacom tablets are responsible for the development of this code. The source code was written by at least two dozen individuals, none of whom still seem to be directly involved in the project. I, John Joganic, took up the code in November of 2002, largely to satisfy my own needs, but also because I believe Linux needs to be more useful in the graphic and video industries. What I ask of you, is to use the drivers and report the problems you encounter.

Is my tablet supported? What about my special stylus?

The main page contains a list of all tablets that are known to be supported. Tablets with "(beta)" appended are only supported in the beta drivers at present.

Why does my cursor move randomly or stay at the top-left cornor?

If you use a USB tablet, it is most probably because you didn't configure the X driver properly. Please refer to Mouse1 for solutions.

If it happens to a serial tablet, please post your problem at general discussion

How do I get the special features of my stylus to work?

There are many different types of styli, mice, and pucks. All of them work to varying degrees, so if you are running into trouble, send me email. Also, if you are having trouble with the stable build, try the beta. Many of the tools have been recently added and have not yet been moved to the production release.

Note, tilt is only supported with protocol V tablets, which include Intuos series and Cintiq 21UX to date (Nov. 9, 2006). Any other tablets don't have tilt no matter you have the tilt option in your xorg.conf or not.

Is hot plug supported for X intput devices?

X Intput Device Hotplug is not fullly supported at Xorg yet. But, Wacom X driver has implemented a workaround for those who have to unplug/replug the tablet while X is running. To make your tablet work without restarting X server, please switch your virtual terminals after replug your tablet. That is, press Ctrl + Alt + F1 together then release them (screen turns to console); and press Ctrl + Alt + F7 together then release them (screen returns back to normal).

Another workaround made by Aristeu is available at wdaemon. The email message related to this solution can be found at Tablet Hotplugging.

3.0 - Downloads

Stable Packages by Version and Date:

FileDateComment
linuxwacom-0.7.6-4.tar.bz2-2006-12-01Updated xsetwacom and support kernel 2.6.17/18, Intuos3 4x6 and on-the-fly tablet rotation.
linuxwacom-0.7.4-3.tar.bz2-2006-06-19Supports kernels 2.6.15/16, 2 new Intuos3 (12x12 and 12x19), and DTF 521.
linuxwacom-0.7.2.tar.bz2-2005-12-21Updated configuration script and support kernel 2.6.13/14, Graphire4, PL710, DTF720, Intuos3 6x11 and Volito2 .
linuxwacom-0.7.0-1.tar.bz2-2005-09-23Updated wacomcpl and support 16 buttons for all tools.
linuxwacom-0.7.0-x86-64-1.tar.bz2-2005-09-23Updated wacomcpl and support 16 buttons for all tools.
linuxwacom-0.6.8.tar.bz2-2005-05-05Support Cintiq 21UX and kernel 2.6.11.
linuxwacom-0.6.6.tar.bz2-2004-12-01Build .ko locally and support kernel 2.6.10.
linuxwacom-0.6.4.tar.bz2-2004-08-06Updated wacusb.c and fixed USB tablet protocol V dual input bug.
linuxwacom-0.6.3.tar.bz2-2004-05-25Fixed tool on tablet and relative speed bugs.
linuxwacom-0.6.2.tar.bz2-2004-04-02Fixed DoubleSpeed, DoubleRadius, and TwinView issues.
linuxwacom-0.6.1.tar.bz2-2004-03-02added wacomcpl, support kernel 2.4.24 and 2.6.2/3
linuxwacom-0.6.0.tar.bz2-2004-02-04added wacomcpl, support kernel 2.4.22 and 2.6.0
linuxwacom-0.4.1.tar.gz-2003-03-22added xidump, checks for ncurses
linuxwacom-0.4.0.tar.gz-2003-01-31production release from 0.3.7-beta

Beta Packages by Version and Date:

FileDateComment
linuxwacom-0.7.7-11.tar.bz2-2007-06-05Support Bamboo. Updated installer under prebuilt directory to install X driver as well as its associated utilities. Support non-overlapped multi-areas for same InputDevice. Support pad with button and keystroke events through xsetwacom
linuxwacom-0.7.5-4.tar.bz2-2006-09-29Support kernel 2.6.17/18, Intuos3 4x6, and tablet detach/attach as well as rotation while X running.
linuxwacom-0.7.3-1.tar.bz2-2006-04-07Support kernel 2.6.15/16, Intuos3 12x12 and 12x19.
linuxwacom-0.7.1-2.tar.bz2-2005-12-06Support kernel 2.6.13/14, Graphire4, PL710, DTF720, Intuos3 6x11 and Volito2.
linuxwacom-0.6.9.tar.bz2-2005-08-08Support tablet orentation rotation.
linuxwacom-0.6.9-x86-64.tar.bz2-2005-08-08Support x86-64 system.
linuxwacom-0.6.7.tar.bz2-2005-03-28Added Cintiq 21UX and kernel 2.6.11 support.
linuxwacom-0.6.5.tar.bz2-2004-11-05Added Intuos3 support.
linuxwacom-0.5.4-beta.tar.bz2-2003-12-22General Tablet PC support. 2.6.0 kernel support.
linuxwacom-0.5.3-beta.tar.gz-2003-11-12Added wacomcpl utility. 2.4.22 kernel support. TwinView support.
linuxwacom-0.5.2-beta.tar.gz-2003-07-10Fixed Intuos filter code. 2.5 kernel support. Minor bug fixes.
linuxwacom-0.5.1-beta.tar.gz-2003-06-15Completely refactored data path, configurability.
linuxwacom-0.5.0-beta.tar.gz-2003-02-12Updated PL code. Numerous tweaks.

4.0 - Documentation

The following documentation is available at this time.

5.0 - Mini-HOWTO

Mini HOWTO for Updating Wacom Driver on FC4 and FC5


First, download the most recent linuxwacom driver package from Downloading the Code page to your home directory and unpack it:

[jej@ayukawa jej]$ bunzip2 linuxwacom-0.7.6-4.tar.bz2
[jej@ayukawa jej]$ tar xvf linuxwacom-0.7.6-4.tar

The following HOWTO describes the compiling and install details for linuxwacom-0.7.6-4on FC4 and FC5. For descriptions on other platforms, please refer to Success Stories page.

Kernel Drivers for USB Tablets

Note, this section is for USB tablets only. Serial tablet and Tablet PC users can skip this section since your tablets don't need kernel driver to run.

Before updating your system with linuxwacom driver, you need to make sure your FC4 or FC5 is up to date. To do so, issue up2date for FC4 and yum update for FC5. The following testings are based on FC4 (kernel 2.6.14-1.1653_FC4) and FC5 (kernel 2.6.17-1.2174_FC5).

Note, after updating your kernel, those of you with nVidia and other such graphics cards who like their 3D acceleration or dual monitor support will need to reinstall their drivers too.

Let's prepare your system with kernel driver updating.

The simplest way to do this is to use your system's kernel-devel package. However, both FC4 and FC5 have installed wrong kernel-devel by default. This leads to the following extra steps to remove the wrong kernel-devel and install the proper one.

 
[jej@ayukawa jej]$ su
Password:
[root@ayukawa jej]# yum remove kernel-devel
[root@ayukawa jej]# yum install kernel-devel

If you need to build hid-core.c (refer to Who is taking control? to see if you need to build hid-core.c or not), you'll need to install the corresponding kernel source rpm. For the FC4 in this example, you need to download kernel-2.6.14-1.1653_FC4.src.rpm to your home directory from http://download.fedora.redhat.com/pub/fedora/linux/core/updates/4/SRPMS/. Then executing

 
[jej@ayukawa jej]$ su
Password:
[root@ayukawa jej]# rpm -ivh kernel-2.6.14-1.1653_FC4.src.rpm.
[root@ayukawa jej]# rpmbuild -bp --target=`uname -m` /usr/src/redhat/SPECS/kernel-2.6.spec
[root@ayukawa jej]# cd /usr/src
[root@ayukawa src]# ln -s redhat/BUILD/kernel-2.6.14/linux-2.6.14 linux
[root@ayukawa src]# cd linux
[root@ayukawa linux]# cp ~/linuxwacom-0.7.6-4/src/2.6.14/wacom.c /usr/src/linux/drivers/usb/input/
[root@ayukawa linux]# cp ~/linuxwacom-0.7.6-4/src/2.6.14/hid-core.c /usr/src/linux/drivers/usb/input/
[root@ayukawa linux]# make all
[root@ayukawa linux]# make modules_install
[root@ayukawa linux]# make install

Then you need to edit /boot/grub/menu.lst and change the 'default' value from 1 to 0 .

Before rebooting your system, open /etc/inittab in an editor and change id:5:initdefault to id:3:initdefault. ONLY change 5 to 3 in the file of that line! This step is for testing purpose only.

After rebooting the system, more /proc/bus/usb/devices should return Driver=wacom for your tablet. If not, please post a message to general discussion mailing list.

Setting up building environment for X Driver and Utilities

Logging in as yourself then follow the steps below.

 

[jej@ayukawa jej]$ startx
[jej@ayukawa jej]$ su
Password:
[root@ayukawa jej]# yum install tcl
[root@ayukawa jej]# yum install tk
[root@ayukawa jej]# yum install tcl-devel
[root@ayukawa jej]# yum install tk-devel
[root@ayukawa jej]# yum install xorg-x11-sdk
[root@ayukawa jej]# exit
[jej@ayukawa jej]$ cd linuxwacom-0.7.6-4 
[jej@ayukawa linuxwacom-0.7.6-4]$ ./configure
[jej@ayukawa linuxwacom-0.7.6-4]$ make
[jej@ayukawa linuxwacom-0.7.6-4]$ su
Password:
[root@ayukawa ]# make install

Now, the driver upgrading part is done. You need to update /etc/X11/xorg.conf file to load the driver. Before jumping onto xorg.conf, you need to make a change in /etc/udev/rules.d/10-wacom.rules. Replace the simillar line with the following one and save the file:

 
KERNEL="event*", SYSFS{idVendor}=="056a", NAME="input/%k", SYMLINK="input/wacom"

Then open /etc/X11/xorg.conf and adding proper lines as stated at Configuring X driver.

Now reboot your system. When the system is up, login as yourself, and issue startx. If everything works, i.e., cursor follows the pen tip on the tablet, you are done. You can change id:3 back to id:5 in your /etc/inittab now.

Otherwise, post your problem to general discussion mailing list.

6.0 - Help

Having trouble? Help is available.



Step 1 - Are you using the correct software?

The following configuration is known to work on various platforms. Additionally, the production release recognize and work with all known Wacom tablets.

You will need to be running at least kernel 2.4.18, preferably 2.4.20. You should be aware that Redhat and other vendors will back-port features from newer kernels into their older packages, so if you are running Redhat's kernel-2.4.18-19.8.0.rpm package, you are actually running something half-way between 2.4.19 and 2.4.20.

The serial and USB wacom tablets work with XFree86 4.0 and up, but realistically, you should be running 4.1 or higher. This package maintains 5 prebuilt drivers for XFree86 4.2, 4.3, 4.4, 4.6 and X11R6 (xorg) for both kernel 2.4 and 2.6. Users with XFree86 4.1 need to build their own. Instructions for this are available in the Linux Wacom Project HOWTO under documentation.

The current beta versions, which I recommend if you cannot get your tablet working, for 32bit systems is linuxwacom-0.7.7-11 and for x86 64bit systems is linuxwacom-0.7.7-11-x86-64. This version may contain new features that have not been completely tested, but may be the difference between getting your tablet working or not. If you are running the stable package and your mouse does not work correctly, please try the beta package before doing anything else (if beta version number is larger than the stable one).


Step 2 - Have you read the appropriate HOWTO?

The HOWTO is a bit long, but it is comprehensive. If you cannot get your tablet working after going through the entire thing, please let me know so we can update it to better handle your situation.


Step 3 - Have you tested your tablet's output with wacdump?

The wacdump diagnostic program helps determine whether your tablet is working correctly, partially, or not at all.


Step 4 - Have you tested X's output with xidump?

The xidump diagnostic program shows you exactly what programs like gimp and gsumi are receiving from the XInput subsystem. If gimp is behaving strangely, xidump can tell you if the pressure values are out-of-range, or which buttons are actually pressed and when.


Step 5 - Have you checked the online resources?

There is an FAQ for some of the more general questions. Certainly, you've already been there. There are three mailing lists, including archives. They are linuxwacom-announce, linuxwacom-devel, and linuxwacom-discuss. SourceForge also provides the ability to track bugs and request features. Please report bugs, post feature requests, and commit patches so we can keep track of them and prioritize the development. Forums are available on SourceForge, but the preferred way to be heard is through the linuxwacom-discuss mailing list.


Step 6 - Totally and Completely Stumped?

Send me email, and I'll see what I can do. Please include the word WACOM in the subject field so I can sort it out of the mess that in my inbox. Generally, you will get a faster response (from me even), if you post to the linuxwacom-discuss mailing list.

7.0 - Third Party Developers

For application developers, we have an overview of adding new capabilities to your applications by using a Wacom tablet and sample code for getting the button and valuator values.

7.1 - Overview

Overview for Third Party Developers



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

1) Initialization

During initialization you need to determine if a tablet is attached.

If there is a tablet, you need to get static information about the tablet, such as tablet dimensions, coordinate resolution, pressure range, tangential pressure range, and other features.

2) Event Handler

Here, you will get data from the tablet and find information about the tablet device currently in use. The tablet data is used for line rendering or navigation. The device information can be used to change tools or screen cursors. Tablets produce three event types: pointer events, button events, and valuator events.

2a) Button and Pointer events

Tablet button and pointer events are indistinguishable from mouse button and pointer events. Since most applications use these events for drawing and navigation the tablet works transparently.

2b) Valuator events

The real tablet data is contained in valuator events. High resolution X and Y data, pressure, proximity, absolute or relative mode, and other information is available here. This information can be used for advanced navigation, such as using 4D Mouse rotation to rotate an object. It can also be used for advanced line rendering, such as modulation line width with pressure. The descriptions below explain special treatment of valuator events.

Controlling the Driver

To change the driver’s default values, there are options which can be defined through the configuration file, XF86Config, XF86Config-4, or xorg.conf under directory /etc/X11. Please refer to Adding the InputDevices for examples and a list of available options.

Getting Data From the Driver

The Linux Wacom driver for serial tablet is implemented as an XFree86 Input Extension device. The USB tablet is first loaded through wacom.o in the kernel and then communicated with the XFree86 module, xf86wacom.o, to fulfill the tablet events.

Device Stylus handles all kinds of the pens, such as the Grip Pen, AirBrush, InkingPen, etc.

Device Cursor handles all of the pucks, such as the 4D Mouse, 2D Mouse, Lens Cursor, etc.

Device Eraser handles the eraser button of a pen or airbrush device.

The driver sends events through the XFree86 event queue to applications. The Wacom tablet sends several types of events to the XFree86 event queue. The most immediately obvious are pointer and button events, which can be captured by applications to determine the current location and active buttons. Sample code shows how these values are defined.

The valuators are reported as follow:

  • X position
  • Y position
  • Pressure
  • Tilt X; or rotation for 4D mouse; or Tablet Left Menu strip (Intuos3 and Cintiq 21UX)
  • Tilt Y; or wheel for 4D mouse; or Tablet Right Menu strip (Intuos3 and Cintiq 21UX)
  • Airbrush Wheel position; or Marker Pen rotation (Intuos3 and Cintiq 21UX)

Coordinate Processing

Features That Have Been Around for a Long Time

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

Pressure

There are many obvious uses for pressure. It can be used to modulate the width of a stroke, opacity, color, etc. Be sure to scale the pressure value to use the full range of pressure. Don't assume a maximum pressure level, check the tablet's capabilities to find the maximum pressure value (Check the maximum for the third valuator). Don’t think of pressure as only useful for drawing. For example: Use pressure to control scrolling speed in a scroll bar. Or maybe Click-drag with low pressure does a move; click-drag with high pressure does a copy-move. Pressure is reported in the third valuator.

Eraser

The obvious purpose of the eraser is to use it as an erasing tool. But you can change the function of the eraser to perform more advanced tasks. Using the stylus tip in conjunction with the eraser, you can easily perform two opposing functions such as dodge and burn, or ink and bleach. The eraser can also function independently as any tool selected in the application.

Tilt

Stylus tilt has several uses, but the most obvious is to change brush shape. A good example of using stylus tilt to change brush shape is the Wacom PenTools Virtual Airbrush tool for the Macintosh or PC. Tilt can also be used for object rotation, or as a joystick. X and Y tilt are in the forth and fifth valuators respectively.

Airbrush Fingerwheel

The Intuos and Intuos2 series tablets have a device that is similar to an airbrush. It not only supports pressure on the tip, but also has a fingerwheel on the side to simultaneously vary a second value. For example, using the fingerwheel, you can vary line width with pressure and ink density.

The value of the fingerwheel on the side of the Airbrush is reported in the sixth valuator. The full range is from 0 when pushed forward to 1023 when pulled back, but be sure to use the value contained in the max_value field of the valuator to get the full range to allow for future changes.

4D Mouse Rotation

The Intuos and Intuos2 series tablets have a device that is similar to a puck. In addition to normal puck parameters, this puck supports axial rotation and a wheel. For example, using the 4D Mouse’s rotation you can rotate the paper, or an object, and zoom with the wheel.

4D Mouse axial rotation is reported in the forth valuator. Values in this field range from -900 to 900 in 0.2 degree increments.

4D Mouse Wheel

Uses for the 4D Mouse wheel include zooming, scrolling, and 3D navigation. The 4D Mouse wheel value is reported in the sixth valuator. The wheel varies from 1023 when pushed forward to -1023 when pulled back and snaps to the middle, which is of course zero, when released. But as usual, make sure to use the range reported in min_value and max_value fields of the valuator to allow for future changes.

2D Mouse Wheel

Intuos2 series tablets have 2D Mouse that is similar to a puck. In addition to normal puck parameters, this puck supports a wheel. This wheel reports relative movement value in the sixth valuator. The wheel value is 1 when pushed forward and -1 when pulled back. This wheel event is translated into 4th and 5th button events.

Device ID for Intuos Series and Cintiq 21UX

 
	0x812: /* Intuos2 ink pen */
	0x801: /* Intuos3 Inking pen */
	0x012: /* Inking pen */

	0x822: /* Intuos Pen */
	0x852: /* Intuos2 Grip Pen */
	0x842: /* Designer Pen */
	0x823: /* Intuos3 Grip Pen */
	0x813: /* Intuos3 Classic Pen */
	0x885: /* Intuos3 Marker Pen */
	0x022: /* Intuos Pen */

	0x832: /* Intuos2 stroke pen */
	0x032: /* Stroke pen */

	0x007: /* 2D Mouse */
	0x094: /* 4D Mouse */
	0x017: /* Intuos3 2D Mouse */

	0x096: /* Lens cursor */
	0x097: /* Intuos3 Lens cursor */

	0x82A: /* Intuos Eraser */
	0x85A: /* Intuos2 Eraser */
	0x91A: /* Intuos Eraser */
	0xD1A: /* Intuos Eraser */
	0x0FA: /* Intuos Eraser */
	0x82B: /* Intuos3 Grip Pen Eraser */
	0x81B: /* Intuos3 Classic Pen Eraser */
	0x91B: /* Intuos3 Airbrush Eraser */

	0x112: /* Airbrush */
	0x912: /* Intuos2 Airbrush */
	0xD12: /* Intuos Airbrush */
	0x913: /* Intuos3 Airbrush */

Device ID for all the other tablets

 
	0x002: /* pen */
	0x006: /* cursor */
	0x00A: /* eraser */

7.2 - Sample code



Getting Values Reported from Wacom Devices

The following is a routine of getting valuator data from xidump.c, a program helps users

trobleshooting Wacom X driver. The whole source code can be viewed from xidump.c source

static int RawRunDefault(Display* pDisp, XDeviceInfo* pDevInfo)
{
	XEvent event;
	XAnyEvent* pAny;
	struct timeval tv;
	double dStart, dNow;

	gettimeofday(&tv,NULL);
	dStart = tv.tv_sec + (double)tv.tv_usec / 1E6;

	while (1)
	{
		XNextEvent(pDisp,&event);

		pAny = (XAnyEvent*)&event;
		/* printf("event: type=%s\n",GetEventName(pAny->type)); */

		/* display time */
		gettimeofday(&tv,NULL);
		dNow = tv.tv_sec + (double)tv.tv_usec / 1E6;
		printf("%.8f: ",(dNow - dStart));

		if (pAny->type == gnInputEvent[INPUTEVENT_PROXIMITY_IN])
			printf("Proximity In\n");
		else if (pAny->type == gnInputEvent[INPUTEVENT_PROXIMITY_OUT])
			printf("Proximity Out\n");
		else if (pAny->type == gnInputEvent[INPUTEVENT_FOCUS_IN])
			printf("Focus In\n");
		else if (pAny->type == gnInputEvent[INPUTEVENT_FOCUS_OUT])
			printf("Focus Out\n");
		else if (pAny->type == gnInputEvent[INPUTEVENT_MOTION_NOTIFY])
		{
			XDeviceMotionEvent* pMove = (XDeviceMotionEvent*)pAny;
			int v = (pMove->axis_data[4]&0xffff0000) | 
					((pMove->axis_data[5]&0xffff0000)>>16);

			printf("Motion: x=%+6d y=%+6d p=%4d tx=%+4d ty=%+4d "
				"w=%+5d ID: %4d Serial: %11d \n",
					pMove->axis_data[0],
					pMove->axis_data[1],
					pMove->axis_data[2],
					(short)(pMove->axis_data[3]&0xffff),
					(short)(pMove->axis_data[4]&0xffff),
					(short)(pMove->axis_data[5]&0xffff),
					(pMove->axis_data[3]&0xffff0000)>>16,
					v);

		}
		else if ((pAny->type == gnInputEvent[INPUTEVENT_BTN_PRESS]) ||
				(pAny->type == gnInputEvent[INPUTEVENT_BTN_RELEASE]))
		{
			XDeviceButtonEvent* pBtn = (XDeviceButtonEvent*)pAny;
			printf("Button: %d %s\n",pBtn->button,
					pAny->type == gnInputEvent[INPUTEVENT_BTN_PRESS] ?
						"DOWN" : "UP");
		}
		else
		{
			printf("Event: %s\n",GetEventName(pAny->type));
		}

		/* flush data to terminal */
		fflush(stdout);
	}

	return 0;
}

Utilitizing Intuos3 or Cintiq 21UX Menu Strips

Mats Johannesson (aka Voluspa) offered an example for using the Tablet Menus and Touch

Strips of Intuos3 and Cintiq 21UX tablets. Listed below is his version 0.09.

Latest version and development history can be found at: Wacom Intuos3 ExpressKeys

/* Version 0.09 4 April 2005
 *
 * To compile (example in 2 steps):
 * gcc -O2 -fomit-frame-pointer -c expresskeys.c
 * gcc -s -L/usr/X11R6/lib -o expresskeys expresskeys.o -lX11 -lXi -lXext -lXtst
 *
 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * Important: If you use the linuxwacom-0.6.7-beta or in the future
 * released versions you must change the pad statement in X config
 * file to:
 *
 * Section "ServerLayout"
 * [...]
 * InputDevice "pad" # Intuos3, Cintiq 21UX or Graphire 4. It must NOT send core event
 * [...]
 * EndSection
 *
 * See: http://linuxwacom.sourceforge.net/index.php/howto/srvlayout
 *
 * If you use the old pad statement, any pad button press will jump the
 * mouse cursor to the upper left corner (0,0) when another tool isn't
 * in proximity.
 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * Run example: expresskeys pad &
 * Which will push it into the background. It is safe to close the terminal
 * afterwards. Oh, and X _must_ be running... The name, "pad" here, is
 * how it's called in xorg.conf (the "Identifier" option).
 * 
 * Key configuration is easy to change in the "user config area" below.
 * Use the "xev" program to find keycodes or look them up somewhere...
 * I've set the Wacom Intuos3 defaults on both sides, which is:
 * Shift, Alt, Control and Space. Touch strips are mildly supported.
 */

/* ++++++++++ Begin user config area ++++++++++ */

#define HANDLE_PEN 0	/* Main switch: 1 = yes handle a pen, 0 = no please */
#define PEN_NAME "stylus"	/* Identifier name as configured in xorg.conf */
#define PEN_MODE "Absolute"	/* The mode we should expect the pen to be in */
			/* when starting this program. Default usually */
			/* is Absolute. The "mousy" feeling is Relative */

/* Now, on to the next area. Please walk this way madam!		*/
/*----------------------------------------------.			*/
struct program {		/*		|			*/
	char *class_name;	/*		|			*/
	int handle_touch;	/*		|			*/
	int l_touch_up;		/*		|			*/
	int l_touch_up_plus;	/*		|			*/
	int l_touch_down;	/*		|			*/
	int l_touch_down_plus;	/*		|			*/
	int r_touch_up;		/*		|			*/
	int r_touch_up_plus;	/*		|			*/
	int r_touch_down;	/*		|			*/
	int r_touch_down_plus;	/*		|			*/
	int key_9;		/*		|			*/
	int key_9_plus;		/*		|			*/
	int key_10;		/*		|			*/
	int key_10_plus;	/*		|			*/
	int key_11;		/*	Nothing to see here		*/
	int key_11_plus;	/*	madam... Please move		*/
	int key_12;		/*	along.				*/
	int key_12_plus;	/*		|			*/
	int key_13;		/*		|			*/
	int key_13_plus;	/*		|			*/
	int key_14;		/*		|			*/
	int key_14_plus;	/*		|			*/
	int key_15;		/*		|			*/
	int key_15_plus;	/*		|			*/
	int key_16;		/*		|			*/
	int key_16_plus;	/*		|			*/
} prog_list[] = {		/*		|			*/
				/*		|			*/
/*-------------------------------.		V			*/
/*					Go further down, past
 * 					these comments for the
 * 					real configuration area.
 */
/* Left ExpressKey Pad
------------ 
|  |   |   |		Wacom Intuos3 defaults are:
|  | 9 | T |
|11|---| O |		Key 9  = (left) Shift	= keycode 50
|  |10 | U |		Key 10 = (left) Alt	= keycode 64
|------| C |		Key 11 = (left) Control	= keycode 37
|  12  | H |		Key 12 = Space		= keycode 65
------------
*/
/* Right ExpressKey Pad
------------ 
|   |   |  |		Wacom Intuos3 defaults are:
| T |13 |  |
| O |---|15|		Key 13 = (left) Shift	= keycode 50
| U |14 |  |		Key 14 = (left) Alt	= keycode 64
| C |------|		Key 15 = (left) Control	= keycode 37
| H |  16  |		Key 16 = Space		= keycode 65
------------
*/

/* The top configuration (named "default") will be used with
 * all programs and their windows that are not specified in a
 * separate configuration below this one. Default keycodes are
 * the now famous Wacom Intuos3 ones. I've also set totally
 * non-destructive touch strip keys (only used if handle_touch
 * is altered to a "1" - without quotes) which are: Arrow-keys
 * Up/Down on the left strip and Arrow-keys Right/Left on the
 * right strip. Change direction of the movement by switching
 * the _up and _down values.
 * 
 * If you want a key to do pen mode changes, use the value 999
 * under the corresponding keylabel. To be able to switch mode
 * anywhere, each configuration must contain one 999 definition.
 * And, of course, the main HANDLE_PEN definition above must
 * first be set to "1" - without quotes.
 * 
 * Please don't alter or remove the commas (,) after the keycodes.
 * They _must_ be there just as written.
 */
/*	Name	handle_touch */
{"default",	0,
/*		l_touch_up	l_touch_up_plus	l_touch_down	l_touch_down_plus */
		98,		0,		104,		0,
/*		r_touch_up	r_touch_up_plus	r_touch_down	r_touch_down_plus */
		102,		0,		100,		0,
/*		key_9		key_9_plus	key_10		key_10_plus */
		50,		0,		64,		0,
/*		key_11		key_11_plus	key_12		key_12_plus */
		37,		0,		65,		0,
/*		key_13		key_13_plus	key_14		key_14_plus */
		50,		0,		64,		0,
/*		key_15		key_15_plus	key_16		key_16_plus */
		37,		0,		65,		0	},

/*
 * Gimp has the touch strips turned on by default. The keycodes are:
 * 20 = "+" = Gimp Zoom In. Left/Right touch strip up motion
 * 61 = "-" = Gimp Zoom Out. Left/Right touch strip down motion
 * Change direction of the movement by switching _up and _down values.
 */
/*	Name	handle_touch */
{"Gimp",	1,
/*		l_touch_up	l_touch_up_plus	l_touch_down	l_touch_down_plus */
		20,		0,		61,		0,
/*		r_touch_up	r_touch_up_plus	r_touch_down	r_touch_down_plus */
		20,		0,		61,		0,
/*		key_9		key_9_plus	key_10		key_10_plus */
		50,		0,		64,		0,
/*		key_11		key_11_plus	key_12		key_12_plus */
		37,		0,		65,		0,
/*		key_13		key_13_plus	key_14		key_14_plus */
		50,		0,		64,		0,
/*		key_15		key_15_plus	key_16		key_16_plus */
		37,		0,		65,		0	},

/* This is my private definition for the 3D program blender...
 */
/*	Name	handle_touch */
{"Blender",	1,
/*		l_touch_up	l_touch_up_plus	l_touch_down	l_touch_down_plus */
		102,		0,		100,		0,
/*		r_touch_up	r_touch_up_plus	r_touch_down	r_touch_down_plus */
		98,		0,		104,		0,
/*		key_9		key_9_plus	key_10		key_10_plus */
		37,		0,		9,		0,
/*		key_11		key_11_plus	key_12		key_12_plus */
		50,		0,		23,		0,
/*		key_13		key_13_plus	key_14		key_14_plus */
		50,		30,		30,		0,
/*		key_15		key_15_plus	key_16		key_16_plus */
		999,		0,		65,		0	},

/* I feel that an xterm is too important a window to have _any_
 * interference from the pad. But observe that I want to be able
 * to switch pen mode even with such a window in focus.
 */
/*	Name	handle_touch */
{"XTerm",	0,
/*		l_touch_up	l_touch_up_plus	l_touch_down	l_touch_down_plus */
		0,		0,		0,		0,
/*		r_touch_up	r_touch_up_plus	r_touch_down	r_touch_down_plus */
		0,		0,		0,		0,
/*		key_9		key_9_plus	key_10		key_10_plus */
		0,		0,		0,		0,
/*		key_11		key_11_plus	key_12		key_12_plus */
		0,		0,		0,		0,
/*		key_13		key_13_plus	key_14		key_14_plus */
		0,		0,		0,		0,
/*		key_15		key_15_plus	key_16		key_16_plus */
		999,		0,		0,		0	},

/* And that's how it's done. Just copy a section and tweak the
 * settings for a new program. Your machine speed and memory
 * sets the limit ;-)
 */
/* ++++++++++ End user config area ++++++++++ */

};
#define NUM_LIST (sizeof prog_list / sizeof prog_list[0])

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XTest.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define EXIT_OK 1
#define EXIT_KO 0
#define INVALID_EVENT_TYPE -1
#define TOGGLE_PEN 999

Bool check_xinput (Display *display);
int find_device_info(Display *display, char *name, Bool only_extended);
int register_events(Display	*display, XDeviceInfo *info, char *dev_name);
int use_events(Display *display);
int toggle_pen_mode(Display *display, char *name);

int pen_mode = 1;
int elder_rotation = 4097;
int old_rotation = 4097;
int elder_throttle = 4097;
int old_throttle = 4097;

int main (int argc, char *argv[])
{

   if (PEN_MODE == "Absolute") {
	pen_mode = Absolute;
   } else {
	pen_mode = Relative;
   }

   Display *display = XOpenDisplay(NULL);

   if (display == NULL) {
	fprintf(stderr, "Can not connect to X-Server\n");
	return EXIT_KO;
   }

   int event_base, error_base;
   int major_version, minor_version;
   if (!XTestQueryExtension (display, &event_base, &error_base,
		&major_version, &minor_version)) {
	fprintf (stderr, "XTest extension not supported on server\n");
	XCloseDisplay(display);
	return EXIT_KO;
   }

   if (!check_xinput(display)) {
	fprintf(stderr, "%s extension not present\n", INAME);
	XCloseDisplay(display);
	return EXIT_KO;
   }

   if (argc < 2) {
	fprintf(stderr, "Usage: expresskeys \n");
	fprintf(stderr, "Example: expresskeys pad &\n");
	XCloseDisplay(display);
	return EXIT_KO;
   }

   XDeviceInfo	*info;
   int		idx = 1;

   info = find_device_info(display, argv[idx], True);

   if (!info) {
	fprintf(stderr, "Unable to find device %s\n", argv[idx]);
	XCloseDisplay(display);		
	return EXIT_KO;
   }

   if (register_events(display, info, argv[idx])) {
	use_events(display);
   } else {
	fprintf(stderr, "No event registered...\n");
	XCloseDisplay(display);
	return EXIT_KO;
   }

   XCloseDisplay(display);
   return EXIT_OK;
}

Bool check_xinput (Display *display)
{
   XExtensionVersion *version;
   Bool present;
	
   version = XGetExtensionVersion (display, INAME);
	
   if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
	present = version->present;
	XFree(version);
	return present;
   } else {
	return False;
   }
}	

int find_device_info(Display *display, char *name, Bool only_extended)
{
   XDeviceInfo	*devices; 
   int		loop;
   int		num_devices;
   int		len = strlen(name);
   Bool		is_id = True;
   XID		id = 0;
    
   for(loop=0; loopid);

   if (!device) {
	fprintf(stderr, "Unable to open device %s\n", dev_name);
	return 0;
   }

   if (device->num_classes > 0) {
	for (ip = device->classes, i=0; inum_classes; ip++, i++) {
	   switch (ip->input_class) {

		case ButtonClass:
		DeviceButtonPress(device, button_press_type, event_list[number]); number++;
		DeviceButtonRelease(device, button_release_type, event_list[number]); number++;
		break;

		case ValuatorClass:
		DeviceMotionNotify(device, motion_type, event_list[number]); number++;
		break;

		default:
		break;
	   }
	}
	if (XSelectExtensionEvent(display, root_win, event_list, number)) {
	   fprintf(stderr, "Error selecting extended events\n");
	   return 0;		
	}
   }
   return number;	
}

int use_events(Display *display)
{
   XEvent Event;
   while(1) {
	XNextEvent(display, &Event);

	XClassHint *class_hint;
	class_hint = XAllocClassHint();

	Window focus_window = None;
	int focus_state;

	Window root, parent;
	Window *children;
	unsigned int num_children;

	struct program *p;
	int in_list = 0;

	XGetInputFocus(display, &focus_window, &focus_state);
	XQueryTree(display, focus_window, &root, &parent, &children, &num_children);
	XGetClassHint(display, focus_window, class_hint);

	if ((!class_hint->res_class) && (parent) && (focus_window != root)){
	   XFree(class_hint->res_class);
	   XFree(class_hint->res_name);
	   XGetClassHint(display, parent, class_hint);
	}

	if ((focus_window == root) || (class_hint->res_class == NULL)){
	   p = prog_list;
	}
	else {
	   for (p = prog_list; p < prog_list + NUM_LIST; p++)
		if (strcmp (class_hint->res_class, p->class_name) == 0){
		   in_list = 1;
		   break;
		}
	}
		
	XFree(class_hint->res_class);
	XFree(class_hint->res_name);
	if (children) XFree((char *)children);

	if (!in_list){
	   p = prog_list;
	}

	if (Event.type == motion_type) {

	   if (p->handle_touch){
		int rotation;
		int throttle;
	
		XDeviceMotionEvent *motion = (XDeviceMotionEvent *) &Event;

		rotation = motion->axis_data[3];
		throttle = motion->axis_data[4];

		if (rotation > 1){
		   if ((rotation < old_rotation) && (old_rotation <= elder_rotation)){
			if (p->l_touch_up){
			   XTestFakeKeyEvent(display, p->l_touch_up, True, CurrentTime);
			   if (p->l_touch_up_plus){
				XTestFakeKeyEvent(display, p->l_touch_up_plus, True, CurrentTime);
				XTestFakeKeyEvent(display, p->l_touch_up_plus, False, CurrentTime);
			   }
			   XTestFakeKeyEvent(display, p->l_touch_up, False, CurrentTime);
			}
		   }
		   else if ((rotation > old_rotation) && (old_rotation >= elder_rotation)){
			if (p->l_touch_down){
			   XTestFakeKeyEvent(display, p->l_touch_down, True, CurrentTime);
			   if (p->l_touch_down_plus){
				XTestFakeKeyEvent(display, p->l_touch_down_plus, True, CurrentTime);
				XTestFakeKeyEvent(display, p->l_touch_down_plus, False, CurrentTime);
			   }
			   XTestFakeKeyEvent(display, p->l_touch_down, False, CurrentTime);
			}
		   }
		   elder_rotation = old_rotation;
		   old_rotation = rotation;
		}

		if (throttle > 1){
		   if ((throttle < old_throttle) && (old_throttle <= elder_throttle)){
			if (p->r_touch_up){
			   XTestFakeKeyEvent(display, p->r_touch_up, True, CurrentTime);
			   if (p->r_touch_up_plus){
				XTestFakeKeyEvent(display, p->r_touch_up_plus, True, CurrentTime);
				XTestFakeKeyEvent(display, p->r_touch_up_plus, False, CurrentTime);
			   }
			   XTestFakeKeyEvent(display, p->r_touch_up, False, CurrentTime);
			}
		   }
		   else if ((throttle > old_throttle) && (old_throttle >= elder_throttle)){
			if (p->r_touch_down){
			   XTestFakeKeyEvent(display, p->r_touch_down, True, CurrentTime);
			   if (p->r_touch_down_plus){
				XTestFakeKeyEvent(display, p->r_touch_down_plus, True, CurrentTime);
				XTestFakeKeyEvent(display, p->r_touch_down_plus, False, CurrentTime);
			   }
			   XTestFakeKeyEvent(display, p->r_touch_down, False, CurrentTime);
			}
		   }
		   elder_throttle = old_throttle;
		   old_throttle = throttle;
		}
	   }
	}

	if (Event.type == button_press_type) {

	   XDeviceButtonEvent *button = (XDeviceButtonEvent *) &Event;

	   switch (button->button) {
		case 9:
		   if (p->key_9 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else
			   break;
		   else if (p->key_9)
			XTestFakeKeyEvent(display, p->key_9, True, CurrentTime );
		   if (p->key_9_plus)
			XTestFakeKeyEvent(display, p->key_9_plus, True, CurrentTime );
		   else
			break;
		   break;
		case 10:
		   if (p->key_10 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else
			   break;
		   else if (p->key_10)
			XTestFakeKeyEvent(display, p->key_10, True, CurrentTime );
		   if (p->key_10_plus)
			XTestFakeKeyEvent(display, p->key_10_plus, True, CurrentTime );
		   else
			break;
		   break;
		case 11:
		   if (p->key_11 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else
			   break;
		   else if (p->key_11)
			XTestFakeKeyEvent(display, p->key_11, True, CurrentTime );
		   if (p->key_11_plus)
			XTestFakeKeyEvent(display, p->key_11_plus, True, CurrentTime );
		   else
			break;
		   break;
		case 12:
		   if (p->key_12 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else   
			   break;
		   else if (p->key_12)
			XTestFakeKeyEvent(display, p->key_12, True, CurrentTime );
		   if (p->key_12_plus)
			XTestFakeKeyEvent(display, p->key_12_plus, True, CurrentTime );
		   else
			break;
		   break;
		case 13:
		   if (p->key_13 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else
			   break;
		   else if (p->key_13)
			XTestFakeKeyEvent(display, p->key_13, True, CurrentTime );
		   if (p->key_13_plus)
			XTestFakeKeyEvent(display, p->key_13_plus, True, CurrentTime );
		   else
			break;
		   break;
		case 14:
		   if (p->key_14 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else
			   break;
		   else if (p->key_14)
			XTestFakeKeyEvent(display, p->key_14, True, CurrentTime );
		   if (p->key_14_plus)
			XTestFakeKeyEvent(display, p->key_14_plus, True, CurrentTime );
		   else
			break;
		   break;
		case 15:
		   if (p->key_15 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else
			   break;
		   else if (p->key_15)
			XTestFakeKeyEvent(display, p->key_15, True, CurrentTime );
		   if (p->key_15_plus)
			XTestFakeKeyEvent(display, p->key_15_plus, True, CurrentTime );
		   else
			break;
		   break;
		case 16:
		   if (p->key_16 == TOGGLE_PEN)
			if (HANDLE_PEN)
			   toggle_pen_mode(display, PEN_NAME);
			else
			   break;
		   else if (p->key_16)
			XTestFakeKeyEvent(display, p->key_16, True, CurrentTime );
		   if (p->key_16_plus)
			XTestFakeKeyEvent(display, p->key_16_plus, True, CurrentTime );
		   else
			break;
		   break;			
		default:
		   break;
	   }
	}

	if (Event.type == button_release_type) {
	   XDeviceButtonEvent *button = (XDeviceButtonEvent *) &Event;

           switch (button->button) {
		case 9:
		   if (p->key_9 == TOGGLE_PEN)
			break;
		   else if (p->key_9_plus)
			XTestFakeKeyEvent(display, p->key_9_plus, False, CurrentTime );
		   if (p->key_9)
			XTestFakeKeyEvent(display, p->key_9, False, CurrentTime );
		   else
			break;
		   break;
		case 10:
		   if (p->key_10 == TOGGLE_PEN)		
			break;
		   else if (p->key_10_plus)
			XTestFakeKeyEvent(display, p->key_10_plus, False, CurrentTime );
		   if (p->key_10)
			XTestFakeKeyEvent(display, p->key_10, False, CurrentTime );
		   else
			break;
		   break;
		case 11:
		   if (p->key_11 == TOGGLE_PEN)
			break;
		   else if (p->key_11_plus)
			XTestFakeKeyEvent(display, p->key_11_plus, False, CurrentTime );
		   if (p->key_11)
			XTestFakeKeyEvent(display, p->key_11, False, CurrentTime );
		   else
			break;
		   break;
		case 12:
		   if (p->key_12 == TOGGLE_PEN)
			break;
		   else if (p->key_12_plus)
			XTestFakeKeyEvent(display, p->key_12_plus, False, CurrentTime );
		   if (p->key_12)
			XTestFakeKeyEvent(display, p->key_12, False, CurrentTime );
		   else
			break;
		   break;
		case 13:
		   if (p->key_13 == TOGGLE_PEN)
			break;
		   else if (p->key_13_plus)		
			XTestFakeKeyEvent(display, p->key_13_plus, False, CurrentTime );
		   if (p->key_13)
			XTestFakeKeyEvent(display, p->key_13, False, CurrentTime );
		   else
			break;
		   break;
		case 14:
		   if (p->key_14 == TOGGLE_PEN)
			break;
		   else if (p->key_14_plus)
			XTestFakeKeyEvent(display, p->key_14_plus, False, CurrentTime );
		   if (p->key_14)
			XTestFakeKeyEvent(display, p->key_14, False, CurrentTime );
		   else
			break;
		   break;
		case 15:
		   if (p->key_15 == TOGGLE_PEN)
			break;
		   else if (p->key_15_plus)
			XTestFakeKeyEvent(display, p->key_15_plus, False, CurrentTime );
		   if (p->key_15)
			XTestFakeKeyEvent(display, p->key_15, False, CurrentTime );
		   else
			break;
		   break;
		case 16:
		   if (p->key_16 == TOGGLE_PEN)
			break;
		   else if (p->key_16_plus)
			XTestFakeKeyEvent(display, p->key_16_plus, False, CurrentTime );
		   if (p->key_16)
			XTestFakeKeyEvent(display, p->key_16, False, CurrentTime );
		   else
			break;
		   break;
		default:
		   break;
	   }
	}
   }
}

int toggle_pen_mode(Display *display, char *name)
{
   XDeviceInfo	*info;
   XDevice		*device;

   info = find_device_info(display, PEN_NAME, True);

   if (!info) {
	fprintf(stderr, "unable to find device %s\n", PEN_NAME);
	return 0;
   }

   if (pen_mode == Absolute) {
	pen_mode = Relative;
   } else {
	pen_mode = Absolute;
   }

   device = XOpenDevice(display, info->id);

   if (device) {
	XSetDeviceMode(display, device, pen_mode);
	return 0;
   } else {
	fprintf(stderr, "Unable to open device %s\n", PEN_NAME);
	return 0;
   }
}

8.0 - ChangeLog

9.0 - GNU Free Documentation License

Version 1.2, November 2002

Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

0. PREAMBLE

The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

1. APPLICABILITY AND DEFINITIONS

This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.

A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.

The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.

A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.

The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition.

The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.

2. VERBATIM COPYING

You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and you may publicly display copies.

3. COPYING IN QUANTITY

If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

4. MODIFICATIONS

You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

5. COMBINING DOCUMENTS

You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.

The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements."

6. COLLECTIONS OF DOCUMENTS

You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

7. AGGREGATION WITH INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.

8. TRANSLATION

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warrany Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.

If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.

9. TERMINATION

You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

10. FUTURE REVISIONS OF THIS LICENSE

The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.

HOW TO USE THIS LICENSE FOR YOUR DOCUMENTS

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

      Copyright (c)  YEAR  YOUR NAME.
      Permission is granted to copy, distribute and/or modify this document
      under the terms of the GNU Free Documentation License, Version 1.2
      or any later version published by the Free Software Foundation;
      with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
      A copy of the license is included in the section entitled "GNU
      Free Documentation License".

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this:

    with the Invariant Sections being LIST THEIR TITLES, with the
    Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.



Copyright (C) 2002-2007 - LinuxWacom -Last updated June 5, 2007
This website and its contents are licensed under the GNU FDL.