version 0.1.0 v0.1.0
authorMats Johannesson <devel@bredband.net>
Thu, 26 Jun 2008 14:31:46 +0000 (10:31 -0400)
committerAristeu Rozanski <arozansk@redhat.com>
Thu, 26 Jun 2008 14:31:46 +0000 (10:31 -0400)
Just internal changes. A massive rewrite to get rid of cruft, and
put my own stink on the whole code structure. Ah yes, I then GPL-d
the result...

18 files changed:
AUTHORS [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
ChangeLog.old [new file with mode: 0644]
Copyright [new file with mode: 0644]
INSTALL [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
UserConfig-Pad [new file with mode: 0644]
UserConfig-Pen [new file with mode: 0644]
event_loop.c [new file with mode: 0644]
expresskeys.c [deleted file]
get_device.c [new file with mode: 0644]
globals.c [new file with mode: 0644]
globals.h [new file with mode: 0644]
main_setup.c [new file with mode: 0644]
pen_mode.c [new file with mode: 0644]
reg_events.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..426a2e0
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,7 @@
+
+A certain company now unpacks code-archives to facilitate searching.
+Spammers around the globe rejoice. Obfuscating addresses is necessary:
+
+Mats Johannesson MAINTAINER, BUGS and QUESTIONS handler:
+"devel" followed by "bredband" which is a "net" domain.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..5f12c63
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,7 @@
+
+_Version 0.1.0 5 April 2005_
+
+Just internal changes. A massive rewrite to get rid of cruft, and
+put my own stink on the whole code structure. Ah yes, I then GPL-d
+the result...
+
diff --git a/ChangeLog.old b/ChangeLog.old
new file mode 100644 (file)
index 0000000..845b2f5
--- /dev/null
@@ -0,0 +1,171 @@
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+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 or Cintiq 21UX. 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).
+
+Update example 17 March 2005: Myself I've put it in the .xinitrc as
+"exec /usr/local/bin/expresskeys pad &" (without quotes) right before
+the window manager is started.
+
+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.
+
+Note 2 April 2005: Sometimes desktops or window managers "steal"
+certain keypresses/combinations. If you experience that, look for
+a way to change the keybindings of your environment.
+
+_Version 0.09 4 April 2005_
+
+Bugfix to handle some weird windows who don't set the "class",
+and even their parents lack it (like the "xev" program...). I
+won't go further back in a hierarchy, so these weirdos get the
+"default" keyset.
+
+Note: Without this fix expresskeys will crash in such cases.
+
+_Version 0.08 3 April 2005_
+
+When I was customizing the keyboard shortcuts within Gimp itself
+(I wanted Alt + and Alt - to do Next Brush and Previous Brush) it
+became obvious that I couldn't assign these brush steppings to any
+touch strip, due to my shortsightedness.
+
+Now touch strips can send two keys at a time, just like the pad
+buttons: l_touch_up, l_touch_up_plus etc. All of the "_plus" touch
+strip definitions are set to 0 (nothing) per default.
+
+Being able to use the touch strips for things like this is really
+neat. Look in Gimp's File -> Preferences -> Interface -> Configure
+Keyboard Shortcuts -> Context for some good touch strip candidates.
+
+Bugfix: Would crash if _no_ window had focus (except the root win).
+
+_Version 0.07 2 April 2005_
+
+Multiple configurations to rule them all... Yes, we now send
+keypresses intelligently based on several configurations. I've
+included a "default" catch all type, one for Gimp, for Blender
+and for XTerm. Observe the spelling! It is case sensitive.
+
+To create a new definition, just copy a full block and alter the
+Name and the keycodes. To find the proper name of a program/window
+fire up "xprop". It should be included with your X. xprop without
+any arguments expects you to then click on the target window.
+What comes out is a flood of information in the terminal window
+you used to run xprop from. What we're after is something called
+WM_CLASS. And within that, only one string. Let me show you:
+
+$ xprop | grep WM_CLASS
+WM_CLASS(STRING) = "<unknown>", "Eclipse"
+
+It's the last string we would use, the "Eclipse" part. That is,
+if we were doing a definition for this program, an IDE ;-)
+
+You can see above why I use the last part. Program windows do not
+always set their "name" (the first string). But they should
+absolutely set the "class" they belong to, which often coincides
+with the name.
+
+So non-technically, this is how expresskeys works now:
+
+1) Pad button pressed or Touch strips touched.
+2) Examine which window is the current active one (has focus).
+3) Get the "class" name of the window.
+4) Compare that name with an internal list of program names.
+5) If a match is found, use those keydefinitions.
+6) If no match is found, use a "default" set of definitions.
+7) Send the keypress to the specified window.
+
+In order to achieve this functionality I had to change the
+"user config area" somewhat. I've done my very best to retain
+a simple design, and at the same time keep it compact. But
+success is in the eye of the beholder... Cut out example:
+
+/*     key_9   */ <-- A visual reminder of which pad button it is.
+       50,     <-- The actual keycode and a COMMA (don't erase it).
+
+Otherwise all the keys and options from past versions are, almost,
+the same. End Version Note Rant.
+
+_Version 0.06 29 March 2005_
+
+Comment 2 April 2005: This is default only in Gimp. Basic defaults
+are now Arrow-keys Up/Down/Right/Left. End comment.
+
+Touch Strip simple implementation. Default, if turned on, sends plus
+(+) and minus (-) key presses based on finger/stylus up/down motion.
+This was chosen for Gimp Zoom In/Out functionality. It must be turned
+on by setting a value in the "user config area", just as for pen mode
+handling. Default is off, don't handle the touch strips.
+
+It turns out that with linuxwacom-0.6.7 (beta is out) this program
+works better than ever! The blender "confusion" I talked about in
+the previous version note has vanished completely. Also blender
+zoom, translation and rotation work flawlessly with the pad buttons
+and pen middle button (was half-working in linuxwacom-0.6.6). So the
+XTestFakeKeyEvent was no bad choice at all. I'm very pleased :-)
+
+_Version 0.05 16 March 2005_
+
+Bugfix. My key scan "case:, if, else, break" flow was somewhat borked.
+Ugly function but does the right thing now. There are still issues
+with (I believe) the timing of the XTestFakeKeyEvent of the XTest
+extension. Using the "u" and "Shift-u" for undo and redo in blender
+works, but sometimes blender gets confused. Waiting some seconds and
+doing a "slow-push-release" of the key can fix the issue. Ah well,
+this simulates keypresses, it's not the real thing... I'll look into
+using another extension for the simulation.
+
+_Version 0.04 15 March 2005_
+
+Bugfix to handle certain key combinations better. Not perfect though.
+Will debug further.
+
+_Version 0.03 15 March 2005_:
+
+Handle a pen from the pad keys (toggle between absolute and relative mode).
+See the new "user config area" for details. Observe: Whatever pen mode
+you are in when exiting or killing this program, that's the pen mode
+you have... So if wrong, fire up the program again and toggle until it's
+the right mode. Default is off, don't handle a pen.
+
+Clearly marked and cleaned up a "user config area" at the very beginning
+of the code.
+
+_Version 0.02 14 March 2005_:
+
+Comment 2 April 2005: These instructions are dated. #define
+for the keycodes are not used anymore. End comment.
+
+Added the option to specify an extra key for each pad key.
+"#define KEY_xx_PLUS yy". By setting yy of KEY_11_PLUS to 57 you'd get
+the famous Ctrl-n ;-). I needed this for undo and redo in blender.
+
+_Version 0.01 14 March 2005_:
+
+Original release
+
+Have fun,
+Mats
+
diff --git a/Copyright b/Copyright
new file mode 100644 (file)
index 0000000..ec74b4a
--- /dev/null
+++ b/Copyright
@@ -0,0 +1,9 @@
+
+ExpressKeys was written by Mats Johannesson aka Voluspa in 2005.
+The original framework (one big .c file) built heavily on some
+functions in Frederic Lepied's xinput-1.2 from 1996. Without that
+smooth entrypoint the program had remained a pipe dream for sure.
+
+You are free to use it under the terms of the GNU General Public
+License, as described in the LICENSE file.
+
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..bb482c6
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,16 @@
+
+The ChangeLog.old file contains all necessary information for
+a proper configuration and execution of this program.
+
+After that read, change the UserConfig-Pad/Pen files to your
+taste. Take a look in the extremely simple Makefile if
+setting CFLAGS is your want. Next step is to type:
+
+make
+
+Then copy the binary to a suitable location. There's also the
+option to type "make clean", which deletes all the .o files after
+a compilation (it will also remove the binary). The cleaning
+up must be done inbetween configurations in the UserConfig-x and
+compiles, otherwise make won't do a new compile.
+
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 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.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public 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.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..dcc7566
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+CC = gcc
+CFLAGS = -O2 -fomit-frame-pointer -Wall
+
+INCLUDES = -I/usr/X11R6/lib
+LDFLAGS = -s -L/usr/X11R6/lib
+LIBS = -lX11 -lXi -lXext -lXtst
+
+TARGET = expresskeys
+
+SRCS = globals.c get_device.c reg_events.c pen_mode.c event_loop.c main_setup.c
+OBJS = globals.o get_device.o reg_events.o pen_mode.o event_loop.o main_setup.o
+ALL =  $(SRCS)
+
+all:   $(TARGET)
+
+$(TARGET):     $(OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+.c.o:
+       $(CC) $(CFLAGS) $(INCLUDES) -c $*.c
+
+clean:
+       rm -f $(OBJS) $(TARGET)
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..8b8f16b
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+
+This program gives basic linux support for the ExpressKeys and
+Touch Strips of a Wacom Intuos3 tablet.
+
+The ChangeLog.old and UserConfig-Pad/Pen files contain all
+available documentation.
+
diff --git a/UserConfig-Pad b/UserConfig-Pad
new file mode 100644 (file)
index 0000000..58af99a
--- /dev/null
@@ -0,0 +1,161 @@
+
+/* ++++++++++ Begin user Pad area ++++++++++ */
+
+/* Now, on to the real 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 in the separate
+ * UserConfig-Pen file 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 Pad area ++++++++++ */
+
+};
+
+/* End Code */
+
diff --git a/UserConfig-Pen b/UserConfig-Pen
new file mode 100644 (file)
index 0000000..c422ac3
--- /dev/null
@@ -0,0 +1,13 @@
+
+/* ++++++++++ Begin user Pen 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 */
+
+/* ++++++++++ End user Pen area ++++++++++ */
+
+/* End Code */
+
diff --git a/event_loop.c b/event_loop.c
new file mode 100644 (file)
index 0000000..e8836d0
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * event_loop -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ *
+ * Copyright (C) 2005 - Mats Johannesson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "globals.h"
+#include "UserConfig-Pad"
+
+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;
+                       }
+               }
+       }
+       return EXIT_OK;
+}
+
+/* End code */
+
diff --git a/expresskeys.c b/expresskeys.c
deleted file mode 100644 (file)
index e040ce5..0000000
+++ /dev/null
@@ -1,919 +0,0 @@
-/* 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 or Cintiq 21UX. 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).
- *
- * Update example 17 March 2005: Myself I've put it in the .xinitrc as
- * "exec /usr/local/bin/expresskeys pad &" (without quotes) right before
- * the window manager is started.
- * 
- * 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.
- *
- * Note 2 April 2005: Sometimes desktops or window managers "steal"
- * certain keypresses/combinations. If you experience that, look for
- * a way to change the keybindings of your environment.
- *
- * _Version 0.09 4 April 2005_
- *
- * Bugfix to handle some weird windows who don't set the "class",
- * and even their parents lack it (like the "xev" program...). I
- * won't go further back in a hierarchy, so these weirdos get the
- * "default" keyset.
- *
- * Note: Without this fix expresskeys will crash in such cases.
- *
- * _Version 0.08 3 April 2005_
- * 
- * When I was customizing the keyboard shortcuts within Gimp itself
- * (I wanted Alt + and Alt - to do Next Brush and Previous Brush) it
- * became obvious that I couldn't assign these brush steppings to any
- * touch strip, due to my shortsightedness.
- * 
- * Now touch strips can send two keys at a time, just like the pad
- * buttons: l_touch_up, l_touch_up_plus etc. All of the "_plus" touch
- * strip definitions are set to 0 (nothing) per default.
- * 
- * Being able to use the touch strips for things like this is really
- * neat. Look in Gimp's File -> Preferences -> Interface -> Configure
- * Keyboard Shortcuts -> Context for some good touch strip candidates.
- * 
- * Bugfix: Would crash if _no_ window had focus (except the root win).
- *
- * _Version 0.07 2 April 2005_
- * 
- * Multiple configurations to rule them all... Yes, we now send
- * keypresses intelligently based on several configurations. I've
- * included a "default" catch all type, one for Gimp, for Blender
- * and for XTerm. Observe the spelling! It is case sensitive.
- * 
- * To create a new definition, just copy a full block and alter the
- * Name and the keycodes. To find the proper name of a program/window
- * fire up "xprop". It should be included with your X. xprop without
- * any arguments expects you to then click on the target window.
- * What comes out is a flood of information in the terminal window
- * you used to run xprop from. What we're after is something called
- * WM_CLASS. And within that, only one string. Let me show you:
- * 
- * $ xprop | grep WM_CLASS
- * WM_CLASS(STRING) = "<unknown>", "Eclipse"
- * 
- * It's the last string we would use, the "Eclipse" part. That is,
- * if we were doing a definition for this program, an IDE ;-)
- * 
- * You can see above why I use the last part. Program windows do not
- * always set their "name" (the first string). But they should
- * absolutely set the "class" they belong to, which often coincides
- * with the name.
- * 
- * So non-technically, this is how expresskeys works now:
- * 
- * 1) Pad button pressed or Touch strips touched.
- * 2) Examine which window is the current active one (has focus).
- * 3) Get the "class" name of the window.
- * 4) Compare that name with an internal list of program names.
- * 5) If a match is found, use those keydefinitions.
- * 6) If no match is found, use a "default" set of definitions.
- * 7) Send the keypress to the specified window.
- * 
- * In order to achieve this functionality I had to change the
- * "user config area" somewhat. I've done my very best to retain
- * a simple design, and at the same time keep it compact. But
- * success is in the eye of the beholder... Cut out example:
- * 
- *//*  key_9   *//* <-- A visual reminder of which pad button it is. */
-/*     50,             <-- The actual keycode and a COMMA (don't erase it).
- * 
- * Otherwise all the keys and options from past versions are, almost,
- * the same. End Version Note Rant.
- * 
- * _Version 0.06 29 March 2005_
- * 
- * Comment 2 April 2005: This is default only in Gimp. Basic defaults
- * are now Arrow-keys Up/Down/Right/Left. End comment.
- * 
- * Touch Strip simple implementation. Default, if turned on, sends plus
- * (+) and minus (-) key presses based on finger/stylus up/down motion.
- * This was chosen for Gimp Zoom In/Out functionality. It must be turned
- * on by setting a value in the "user config area", just as for pen mode
- * handling. Default is off, don't handle the touch strips.
- * 
- * It turns out that with linuxwacom-0.6.7 (beta is out) this program
- * works better than ever! The blender "confusion" I talked about in
- * the previous version note has vanished completely. Also blender
- * zoom, translation and rotation work flawlessly with the pad buttons
- * and pen middle button (was half-working in linuxwacom-0.6.6). So the
- * XTestFakeKeyEvent was no bad choice at all. I'm very pleased :-)
- * 
- * _Version 0.05 16 March 2005_
- *
- * Bugfix. My key scan "case:, if, else, break" flow was somewhat borked.
- * Ugly function but does the right thing now. There are still issues
- * with (I believe) the timing of the XTestFakeKeyEvent of the XTest
- * extension. Using the "u" and "Shift-u" for undo and redo in blender
- * works, but sometimes blender gets confused. Waiting some seconds and
- * doing a "slow-push-release" of the key can fix the issue. Ah well,
- * this simulates keypresses, it's not the real thing... I'll look into
- * using another extension for the simulation.
- *
- * _Version 0.04 15 March 2005_
- *
- * Bugfix to handle certain key combinations better. Not perfect though.
- * Will debug further.
- *
- * _Version 0.03 15 March 2005_:
- * 
- * Handle a pen from the pad keys (toggle between absolute and relative mode).
- * See the new "user config area" for details. Observe: Whatever pen mode
- * you are in when exiting or killing this program, that's the pen mode
- * you have... So if wrong, fire up the program again and toggle until it's
- * the right mode. Default is off, don't handle a pen.
- * 
- * Clearly marked and cleaned up a "user config area" at the very beginning
- * of the code.
- * 
- * _Version 0.02 14 March 2005_:
- *
- * Comment 2 April 2005: These instructions are dated. #define
- * for the keycodes are not used anymore. End comment.
- * 
- * Added the option to specify an extra key for each pad key.
- * "#define KEY_xx_PLUS yy". By setting yy of KEY_11_PLUS to 57 you'd get
- * the famous Ctrl-n ;-). I needed this for undo and redo in blender.
- * 
- * _Version 0.01 14 March 2005_:
- *
- * Original release
- * 
- * Have fun,
- * Mats
- */
-/*
- * CopyLeft 2005 by Mats Johannesson aka Voluspa. One working address
- * is devel with the ISP bredband which is a net domain.
- *
- * Hacked code from xinput-1.2.tar.gz (the test.c, setmode.c and xinput.c)
- * Most of the pure xinput is left as Frederic Lepied wrote it - I'm no coder!
- */
-/*
- * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
- *                                                                            
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is  hereby granted without fee, provided that
- * the  above copyright   notice appear  in   all  copies and  that both  that
- * copyright  notice   and   this  permission   notice  appear  in  supporting
- * documentation, and that   the  name of  Frederic   Lepied not  be  used  in
- * advertising or publicity pertaining to distribution of the software without
- * specific,  written      prior  permission.     Frederic  Lepied   makes  no
- * representations about the suitability of this software for any purpose.  It
- * is provided "as is" without express or implied warranty.                   
- *                                                                            
- * FREDERIC  LEPIED DISCLAIMS ALL   WARRANTIES WITH REGARD  TO  THIS SOFTWARE,
- * INCLUDING ALL IMPLIED   WARRANTIES OF MERCHANTABILITY  AND   FITNESS, IN NO
- * EVENT  SHALL FREDERIC  LEPIED BE   LIABLE   FOR ANY  SPECIAL, INDIRECT   OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA  OR PROFITS, WHETHER  IN  AN ACTION OF  CONTRACT,  NEGLIGENCE OR OTHER
- * TORTIOUS  ACTION, ARISING    OUT OF OR   IN  CONNECTION  WITH THE USE    OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/* ++++++++++ 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 <device-name>\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; loop<len; loop++) {
-       if (!isdigit(name[loop])) {
-               is_id = False;
-               break;
-       }
-       }
-
-       if (is_id) {
-       id = atoi(name);
-       }
-    
-       devices = XListInputDevices(display, &num_devices);
-
-       for(loop=0; loop<num_devices; loop++) {
-       if ((!only_extended || (devices[loop].use == IsXExtensionDevice)) &&
-               ((!is_id && strcmp(devices[loop].name, name) == 0) ||
-               (is_id && devices[loop].id == id))) {
-               return &devices[loop];
-               }
-       }
-       return 0;
-}
-
-static int motion_type = INVALID_EVENT_TYPE;
-static int button_press_type = INVALID_EVENT_TYPE;
-static int button_release_type = INVALID_EVENT_TYPE;
-int register_events(Display    *display, XDeviceInfo *info, char *dev_name)
-{
-       int number = 0;
-       XEventClass event_list[3];
-       int i;
-       XDevice *device;
-       Window root_win;
-       unsigned long screen;
-       XInputClassInfo *ip;
-
-       screen = DefaultScreen(display);
-       root_win = RootWindow(display, screen);
-
-       device = XOpenDevice(display, info->id);
-
-       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; i<info->num_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;
-       }
-}
-
-/* End code */
-
diff --git a/get_device.c b/get_device.c
new file mode 100644 (file)
index 0000000..3b74b43
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * get_device.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ *
+ * Copyright (C) 2005 - Mats Johannesson
+ *
+ * Based on xinput.c 1996 by Frederic Lepied
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "globals.h"
+
+int get_device_info(Display *display, char *name)
+{
+       int             i;
+       int             nr_devices;
+
+       info = XListInputDevices(display, &nr_devices);
+
+       for(i = 0; i < nr_devices; i++) {
+               if ((info[i].use == IsXExtensionDevice) &&
+               (strcmp (info[i].name, name) == 0)){
+                       return (int) &info[i];
+               }
+       }
+       return 0;
+}
+
+/* End Code */
+
diff --git a/globals.c b/globals.c
new file mode 100644 (file)
index 0000000..992d2c8
--- /dev/null
+++ b/globals.c
@@ -0,0 +1,45 @@
+/*
+ * globals.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ *
+ * Copyright (C) 2005 - Mats Johannesson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "globals.h"
+
+Display *display;
+int screen;
+
+XDeviceInfo *info;
+XDeviceInfo *pad_info;
+XDeviceInfo *pen_info;
+XDevice *pad_device;
+XDevice *pen_device;
+
+int pen_mode = 1;
+int pen_open = 0;
+int elder_rotation = 4097;
+int old_rotation = 4097;
+int elder_throttle = 4097;
+int old_throttle = 4097;
+
+int motion_type = NON_VALID;
+int button_press_type = NON_VALID;
+int button_release_type = NON_VALID;
+
+/* End Code */
+
diff --git a/globals.h b/globals.h
new file mode 100644 (file)
index 0000000..f9d10fc
--- /dev/null
+++ b/globals.h
@@ -0,0 +1,66 @@
+/*
+ * globals.h -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ *
+ * Copyright (C) 2005 - Mats Johannesson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "UserConfig-Pen"
+
+#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 NON_VALID -1
+#define TOGGLE_PEN 999
+#define NUM_LIST (sizeof prog_list / sizeof prog_list[0])
+
+extern Display *display;
+extern int screen;
+
+extern XDeviceInfo *info;
+extern XDeviceInfo *pad_info;
+extern XDeviceInfo *pen_info;
+extern XDevice *pad_device;
+extern XDevice *pen_device;
+
+extern int pen_mode;
+extern int pen_open;
+extern int elder_rotation;
+extern int old_rotation;
+extern int elder_throttle;
+extern int old_throttle;
+
+extern int motion_type;
+extern int button_press_type;
+extern int button_release_type;
+
+extern int get_device_info(Display *display, char *name);
+extern int register_events(Display *display, XDeviceInfo *pad_info, char *name);
+extern int toggle_pen_mode(Display *display, char *name);
+extern int use_events(Display *display);
+
+/* End Code */
+
diff --git a/main_setup.c b/main_setup.c
new file mode 100644 (file)
index 0000000..d664f61
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * main_setup.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ *
+ * Copyright (C) 2005 - Mats Johannesson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "globals.h"
+
+int main (int argc, char *argv[])
+{
+
+       if (PEN_MODE == "Absolute") {
+               pen_mode = Absolute;
+       } else {
+               pen_mode = Relative;
+       }
+
+       if ((display = XOpenDisplay(NULL)) == NULL) {
+               fprintf(stderr, "ERROR: Can not connect to your X Server\n");
+               return EXIT_KO; 
+       }
+
+       screen = DefaultScreen(display);
+
+       int event_base, error_base;
+       int major_version, minor_version;
+       if (!XTestQueryExtension (display, &event_base, &error_base,
+               &major_version, &minor_version)) {
+               fprintf (stderr, "ERROR: XTest extension not present on your X server\n");
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+       XExtensionVersion *xinputext;
+       xinputext = XGetExtensionVersion (display, INAME);
+       if (xinputext && (xinputext != (XExtensionVersion*) NoSuchExtension)) {
+               XFree(xinputext);
+       } else {
+               fprintf (stderr, "ERROR: XInput extension not present on your X server\n");
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+       if (argc < 2) {
+               fprintf(stderr, "Usage: expresskeys <device-name>\n");
+               fprintf(stderr, "Example: expresskeys pad &\n");
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+       pad_info = (void *) get_device_info(display, argv[1]);
+       XFreeDeviceList (info);
+       if (!pad_info) {
+               fprintf(stderr, "ERROR: Can not find pad device: %s\n", argv[1]);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+       if (HANDLE_PEN){
+               pen_info = (void *) get_device_info(display, PEN_NAME);
+               XFreeDeviceList (info);
+               if (!pen_info) {
+                       fprintf(stderr, "ERROR: Can not find pen device: %s\n", PEN_NAME);
+                       XCloseDisplay(display);
+                       return EXIT_KO;
+               }
+       }
+
+       if (register_events(display, pad_info, argv[1])) {
+               use_events(display);
+       } else {
+               fprintf(stderr, "ERROR: Could not register any events!\n");
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+       XCloseDisplay(display);
+       return EXIT_OK;
+}
+
+/* End Code */
+
diff --git a/pen_mode.c b/pen_mode.c
new file mode 100644 (file)
index 0000000..71ca865
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * pen_mode.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ *
+ * Copyright (C) 2005 - Mats Johannesson
+ *
+ * Based on setmode.c 1996 by Frederic Lepied
+ *
+ * This code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this code; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "globals.h"
+
+int toggle_pen_mode(Display *display, char *name)
+{
+
+       if (pen_mode == Absolute) {
+               pen_mode = Relative;
+       } else {
+               pen_mode = Absolute;
+       }
+       if (!pen_open){
+               pen_device = XOpenDevice(display, pen_info->id);
+               pen_open = 1;
+       }
+       if ((pen_device) && (pen_open)) {
+               XSetDeviceMode(display, pen_device, pen_mode);
+               return 0;
+       } else {
+               fprintf(stderr, "ERROR: Can not open pen device: %s\n", PEN_NAME);
+               return 0;
+       }
+}
+
+/* End Code */
+
diff --git a/reg_events.c b/reg_events.c
new file mode 100644 (file)
index 0000000..824576a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * reg_events.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ *
+ * Copyright (C) 2005 - Mats Johannesson
+ *
+ * Based on test.c 1996 by Frederic Lepied
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "globals.h"
+
+int register_events(Display *display, XDeviceInfo *pad_info, char *name)
+{
+       int i;
+       int count = 0;
+       XEventClass event_list[3];
+       XInputClassInfo *ip;
+       Window root_win;
+
+       root_win = RootWindow(display, screen);
+
+       pad_device = XOpenDevice(display, pad_info->id);
+       if (!pad_device) {
+               fprintf(stderr, "ERROR: Can not open device %s\n", name);
+               return 0;
+       }
+
+       if (pad_device->num_classes > 0) {
+               for (ip = pad_device->classes, i = 0; i < pad_info->num_classes; ip++, i++) {
+                       switch (ip->input_class) {
+
+                       case ButtonClass:
+                       DeviceButtonPress(pad_device, button_press_type, event_list[count]);
+                       count++;
+                       DeviceButtonRelease(pad_device, button_release_type, event_list[count]);
+                       count++;
+                       break;
+
+                       case ValuatorClass:
+                       DeviceMotionNotify(pad_device, motion_type, event_list[count]);
+                       count++;
+                       break;
+
+                       default:
+                       break;
+                       }
+               }
+
+       if (XSelectExtensionEvent(display, root_win, event_list, count)) {
+               fprintf(stderr, "ERROR: Could not select extended events!\n");
+               return 0;
+               }
+       }
+       return count;
+}
+
+/* End Code */
+