version 0.1.1 v0.1.1
authorMats Johannesson <devel@bredband.net>
Thu, 26 Jun 2008 15:29:14 +0000 (11:29 -0400)
committerAristeu Rozanski <arozansk@redhat.com>
Thu, 26 Jun 2008 15:29:14 +0000 (11:29 -0400)
* Now reads an external configuration file at program launch. It
searches in the user home directory under the hidden "/.expresskeys"
directory. File is called "expresskeys.conf". If none is found, or
the directory doesn't exist yet, it makes the dir, then creates and
populates a minimal file from an internal list. The original "default",
"Gimp", "Blender" and "XTerm" entries. It then goes on and reads in
that file immediately. A limit of 64 different program definitions
has been set (easily altered in the code). It's way more than most
would need, since the "default" is fine for a huge group of programs.

Rules for the configuration file is: Don't use { or } in comments,
and preferably keep comments outside of program definitions. The
comma (,) inside a definition is still used to separate all the
fields. Program names don't need the embracing quotes "" but I
kept the default list using them. Since spaces are accepted as part
of a class name, make sure there are no space _before or after_ the
name, prior to the terminating field comma:

{"A ProgramName", or {A ProgramName,    <-- OK
{"A ProgramName" , or { A ProgramName,  <-- NOT-OK

The extra space/s would become part of the class name. Not what you want.
If you absolutely must put some space before the comma, use TAB instead.
Those are discarded while parsing the string.

* Pen handling is now specified on the command line, eg:

ekeys pad stylus

The value for pen mode switch in the configuration file is still 999.

Yes, "ekeys" :-) I changed the compile output to that name. The code
tarball will still be named expresskeys though. Doing a web search
revealed it to be rather unique to the Intuos3, while ekeys turned
up music hardware and relatives. But, naturally, feel free to name it
badzilla or VincentVanGogh instead. Program behaviour is not dependent
on the file name.

* Another command line change, to make it run in the background:

ekeys pad stylus -d

It then runs in "daemon" mode. The difference between pushing it
with a terminating & or letting internal code "fork" it is beyond
most peoples interest. I can already hear the snores building up...
But in terms of how I've coded stuff it still matters.

If the program is launched into daemon mode, it writes out another
file in the configuration directory: "expresskeys.pid". A
process identification (PID) is a unique number, separating the
program from all the other stuff you have running. The number can
be used, for example, to do an easy kill.

I've included a simple shell script (called ekeys-kill.sh) which reads the
expresskeys.pid and tries to kill whatever process that has the pid,
so do a "ps aux | grep ekeys" beforehand to be sure it's running
(and don't confuse your "grep ekeys" with an actual "ekeys" instance).
Add a line to start ekeys directly after a kill and you have an easy
path when doing config file changes. The pid file is not automatically
deleted by internal code on exit (yet).

* For any programmer out there, or curious user, I've now filled the
code with comments. It had to be done at some point...

23 files changed:
ChangeLog
INSTALL
Makefile [deleted file]
README
USAGE [new file with mode: 0644]
UserConfig-Pad [deleted file]
UserConfig-Pen [deleted file]
ekeys-kill.sh [new file with mode: 0755]
globals.c [deleted file]
globals.h [deleted file]
main_setup.c [deleted file]
makefile [new file with mode: 0644]
src-client/main_dummy.c [new file with mode: 0644]
src-client/makefile [new file with mode: 0644]
src-server/config_all.c [new file with mode: 0644]
src-server/event_loop.c [moved from event_loop.c with 58% similarity]
src-server/get_device.c [moved from get_device.c with 66% similarity]
src-server/globals.c [new file with mode: 0644]
src-server/globals.h [new file with mode: 0644]
src-server/main_setup.c [new file with mode: 0644]
src-server/makefile [new file with mode: 0644]
src-server/pen_mode.c [moved from pen_mode.c with 72% similarity]
src-server/reg_events.c [moved from reg_events.c with 70% similarity]

index 5f12c63..3bf8fe2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,71 @@
 
+_Version 0.1.1 17 April 2005_
+
+* Now reads an external configuration file at program launch. It
+searches in the user home directory under the hidden "./expresskeys"
+directory. File is called "expresskeys.conf". If none is found, or
+the directory doesn't exist yet, it makes the dir, then creates and
+populates a minimal file from an internal list. The original "default",
+"Gimp", "Blender" and "XTerm" entries. It then goes on and reads in
+that file immediately. A limit of 64 different program definitions
+has been set (easily altered in the code). It's way more than most
+would need, since the "default" is fine for a huge group of programs.
+
+Rules for the configuration file is: Don't use { or } in comments,
+and preferably keep comments outside of program definitions. The
+comma (,) inside a definition is still used to separate all the
+fields. Program names don't need the embracing quotes "" but I
+kept the default list using them. Since spaces are accepted as part
+of a class name, make sure there are no space _before or after_ the
+name, prior to the terminating field comma:
+
+{"A ProgramName", or {A ProgramName,    <-- OK
+{"A ProgramName" , or { A ProgramName,  <-- NOT-OK
+
+The extra space/s would become part of the class name. Not what you want.
+If you absolutely must put some space before the comma, use TAB instead.
+Those are discarded while parsing the string.
+
+* Pen handling is now specified on the command line, eg:
+
+ekeys pad stylus
+
+The value for pen mode switch in the configuration file is still 999.
+
+Yes, "ekeys" :-) I changed the compile output to that name. The code
+tarball will still be named expresskeys though. Doing a web search
+revealed it to be rather unique to the Intuos3, while ekeys turned
+up music hardware and relatives. But, naturally, feel free to name it
+badzilla or VincentVanGogh instead. Program behaviour is not dependent
+on the file name.
+
+* Another command line change, to make it run in the background:
+
+ekeys pad stylus -d
+
+It then runs in "daemon" mode. The difference between pushing it
+with a terminating & or letting internal code "fork" it is beyond
+most peoples interest. I can already hear the snores building up...
+But in terms of how I've coded stuff it still matters.
+
+If the program is launched into daemon mode, it writes out another
+file in the configuration directory: "expresskeys.pid". A
+process identification (PID) is a unique number, separating the
+program from all the other stuff you have running. The number can
+be used, for example, to do an easy kill.
+
+I've included a simple shell script (kalled ekeys-kill.sh) which reads the
+expresskeys.pid and tries to kill whatever process that has the pid,
+so do a "ps aux | grep ekeys" beforehand to be sure it's running
+(and don't confuse your "grep ekeys" with an actual "ekeys" instance).
+Add a line to start ekeys directly after a kill and you have an easy
+path when doing config file changes. The pid file is not automatically
+deleted by internal code on exit (yet).
+
+* For any programmer out there, or curious user, I've now filled the
+code with comments. It had to be done at some point...
+
+
 _Version 0.1.0 5 April 2005_
 
 Just internal changes. A massive rewrite to get rid of cruft, and
diff --git a/INSTALL b/INSTALL
index bb482c6..36d33e5 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,16 +1,14 @@
 
-The ChangeLog.old file contains all necessary information for
-a proper configuration and execution of this program.
+The USAGE file contains all necessary information for a proper
+configuration and execution of this program. Some extra knowledge
+might be had by reading the ChangeLog files. I'm a talkative guy.
 
-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:
+After that read, take a look in the extremely simple Makefile in
+src-server 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.
+a compilation (it will also remove the binary).
 
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index dcc7566..0000000
--- a/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-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
index 8b8f16b..7e4c99f 100644 (file)
--- a/README
+++ b/README
@@ -2,6 +2,8 @@
 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.
+Reading the ChangeLog files from bottom and up can kill some time and
+provide historic insight. It essentially is all the available user
+documentation. However, since info change over time I'll try to list
+all the important and accurate key points in the USAGE file.
 
diff --git a/USAGE b/USAGE
new file mode 100644 (file)
index 0000000..1bce69c
--- /dev/null
+++ b/USAGE
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////
+
+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 can jump the
+mouse cursor to the upper left corner (0,0) when another tool isn't
+in proximity.
+
+///////////////////////////////////////////////////////////////////////////
+
+USAGE of ekeys (expresskeys):
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+* Program can not be started unless X is running.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+* Command line can be:
+
+ekeys <pad-device-name> [<pen-device-name>] [-d]
+
+Where the pad name is mandatory. Specify a pen name
+if you want the program to handle pen mode switches.
+Use -d to make the program a daemon (run in the background).
+
+Example: ekeys pad stylus -d
+
+The names are the "Identifier" strings in your X config file (xorg.conf)
+Myself I start ekeys just before the window manager in my .xinitrc with:
+/usr/local/bin/ekeys pad stylus -d
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+* A minimal configuration file is written on first run to the user home
+directory: ~/.expresskeys/expresskeys.conf
+
+It contains "default", "Gimp", "Blender" and "XTerm" entries and is
+recreated whenever a configuration file is missing on program start.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+* A file with the program PID number is written if run with -d in:
+~/.expresskeys/expresskeys.pid
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+* Use the X program "xev" to find keycodes when changing the configuration.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+* Use the X program "xprop" to find the name string to use when changing
+the configuration. xprop without any arguments expects you to then click
+on the target window. We are looking for the WM_CLASS info so running:
+
+$ xprop | grep WM_CLASS
+WM_CLASS(STRING) = "VCLSalFrame", "OpenOffice.org 1.1.4"
+
+It's the last string we would use, the "OpenOffice.org 1.1.4". We always
+use the last part, and the spelling is case sensitive. Putting
+"openoffice.org 1.1.4" in the configuration file would not match up.
+
+Also, since spaces are accepted as part of a class name, make sure there are
+no space _before or after_ the name, prior to the terminating field comma:
+
+{"A ProgramName", or {A ProgramName,    <-- OK
+{"A ProgramName" , or { A ProgramName,  <-- NOT-OK
+
+The extra space/s would become part of the class name. Not what you want.
+If you absolutely must put some space before the comma, use TAB instead.
+Those are discarded while parsing the string.
+
+The very first entry (at the top) in the configuration file is named
+"default" and holds a key definition for all programs not specified
+in another entry. It also takes care of the root window (the "background")
+and programs lacking a class name in their WM_CLASS.
+
+"default" must always stay as the first entry in the configuration file!
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+The "default" entry holds keycodes to make the pad buttons behave just
+as Wacom list them in the Quick Start Guide: Shift, Alt, Ctrl and Space
+mirrored on both sides. Touch Strip support is turned off by default.
+Use the number 1 in the handle_touch field to turn it on. You then get
+Arrow-key Up/Down on the left strip and Arrow-key Right/Left on the right.
+Change direction of the movement by switching the _up and _down values.
+
+If you want a button to do pen mode toggling between Absolute and Relative,
+use the value 999 in the corresponding keycode field. To be able to switch
+mode anywhere, each program block must contain one 999 definition. And,
+of course, a pen name must be used on the command line when starting the
+program.
+
+Both pad buttons and touch strips can send two keys at a time if so
+configured through usage of the _plus keycode fields.
+
+Please don't alter or remove the commas (,) after the class name or keycodes.
+They must be there to separate the fields, just like the { and } are used to
+separate and define the program blocks.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+The "Gimp" entry has the touch strips turned on by default. The keycodes
+used are:
+20 = "+" = Gimp Zoom In. Left/Right touch strip up motion
+61 = "-" = Gimp Zoom Out. Left/Right touch strip down motion.
+
+The "Blender" entry is a private choice for the 3D program blender...
+
+I felt, and 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, so I've set 999 in one field.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Below is some ASCII art showing the "default":
+
+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
+------------
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Sometimes desktops or window managers "steal" certain
+keypresses/combinations. If you experience that, look for
+a way to change the keybindings of your environment.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
diff --git a/UserConfig-Pad b/UserConfig-Pad
deleted file mode 100644 (file)
index 58af99a..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-
-/* ++++++++++ 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
deleted file mode 100644 (file)
index c422ac3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-
-/* ++++++++++ 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/ekeys-kill.sh b/ekeys-kill.sh
new file mode 100755 (executable)
index 0000000..a05ed29
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Kill ekeys by its PID number.
+if [ -f ~/.expresskeys/expresskeys.pid ]; then
+  echo "Will try to kill ekeys."
+  /bin/kill -15 `/bin/cat ~/.expresskeys/expresskeys.pid | /bin/head -n 1`
+fi
+
diff --git a/globals.c b/globals.c
deleted file mode 100644 (file)
index 992d2c8..0000000
--- a/globals.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index f9d10fc..0000000
--- a/globals.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index d664f61..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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/makefile b/makefile
new file mode 100644 (file)
index 0000000..5336577
--- /dev/null
+++ b/makefile
@@ -0,0 +1,10 @@
+
+all:
+       $(MAKE) -C src-server
+       mv src-server/ekeys .
+
+#      $(MAKE) -C src-client
+#      mv src-client/cekeys .
+clean:
+       rm -f ekeys cekeys src-server/*.o src-client/*.o
+
diff --git a/src-client/main_dummy.c b/src-client/main_dummy.c
new file mode 100644 (file)
index 0000000..c58abbf
--- /dev/null
@@ -0,0 +1,5 @@
+int main (int argc, char *argv[])
+{
+       return 0;
+}
+
diff --git a/src-client/makefile b/src-client/makefile
new file mode 100644 (file)
index 0000000..51e7234
--- /dev/null
@@ -0,0 +1,26 @@
+CC = gcc
+CFLAGS = -O2 -Wall
+# Use -g3 to get full debug info
+
+INCLUDES = -I/usr/X11R6/lib
+LDFLAGS = -L/usr/X11R6/lib
+LIBS = -lX11 -lXi -lXext -lXtst
+
+TARGET = cekeys
+
+SRCS = main_dummy.c
+
+OBJS = $(SRCS:.c=.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/src-server/config_all.c b/src-server/config_all.c
new file mode 100644 (file)
index 0000000..d939d36
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * config_all.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"
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* Function reads a configuration file containing program names and */
+/* definitions of which keys that should be mapped to pad buttons and */
+/* touch strips. It takes a file pointer and a pointer to a global */
+/* structure as input. Returns nothing unless an error occured.*/
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+int read_file_config(int *ip, FILE *fp)
+{
+
+       struct program *p;
+       p = (void *)*ip;
+
+       int i = 0;
+       int j = 0;
+       char c;
+       
+       int num_record = 0;
+       int num_field = 0;
+
+       char buffer [MAXBUFFER];
+       char *prog_name [MAXRECORDS];
+       char *prog_field [MAXFIELDS];
+       char *heap_protect;
+
+/* Previously allocated memory for the program names must be released */
+/* on subsequent reads of the config file. At program start the flag is 0 */
+
+       if (reread_config) {
+               for (i = 0; i < num_list; i++) {
+                       free(prog_name [i]);
+               }
+       }
+       reread_config = 1;
+
+/* Read the config file in one go from top to bottom. Parse out the info */
+/* between record start "{" and record end "}". Recognize field ends by a */
+/* comma ",".Each full record is written to a global memory structure, */
+/* while partial records are discarded and excessive fields are truncated. */
+/* No sanity check on program names or keycode functionality is performed */
+/* A global counter variable of full record instances is updated before */
+/* the function exits to reflect the new state. */
+
+       while ((c = fgetc(fp)) != EOF) {
+               if (num_record < MAXRECORDS) {
+                       if (c == '{') {
+                               while ((c = fgetc(fp)) != EOF && (c != ',')) {
+                                               if ((j < MAXBUFFER - 1) && (c != '"') && (isprint(c))) {
+                                                       buffer [j] = c;
+                                                       j++;
+                                               }
+                               }
+                               buffer [j] = '\0';
+                               i = 0;
+                               j = 0;
+                               if ((heap_protect = (char *)malloc(1024)) == NULL) {
+                                       for (i = 0; i < num_record; i++) {
+                                               free(prog_name [i]);
+                                       }
+                                       return 2; 
+                               }
+                               if ((prog_name [num_record] = (char *)malloc(strlen(buffer)+1)) == NULL) {
+                                       for (i = 0; i < num_record; i++) {
+                                               free(prog_name [i]);
+                                       }
+                                       free(heap_protect);
+                                       return 2;
+                               }
+                               free(heap_protect);
+                               memcpy(prog_name [num_record], buffer, (strlen(buffer)+1));
+                               while ((c = fgetc(fp)) != EOF && (c != '}')) {
+                                       if (num_field < MAXFIELDS) {
+                                               if ((c != ',') && (isdigit(c))) {
+                                                       if (i < MAXDIGITS) {
+                                                               buffer [i] = c;
+                                                               i++;
+                                                       }
+                                               }
+                                               if (c == ',') {
+                                                       buffer [i] = '\0';
+                                                       i=0;
+                                                       if ((heap_protect = (char *)malloc(1024)) == NULL) {
+                                                               for (i = 0; i < num_field; i++) {
+                                                                       free(prog_field [i]);
+                                                               }
+                                                               for (i = 0; i <= num_record; i++) {
+                                                                       free(prog_name [i]);
+                                                               }
+                                                               return 2; 
+                                                       }
+                                                       if ((prog_field [num_field] = (char *)malloc(strlen(buffer)+1)) == NULL) {
+                                                               for (i = 0; i < num_field; i++) {
+                                                                       free(prog_field [i]);
+                                                               }
+                                                               for (i = 0; i <= num_record; i++) {
+                                                                       free(prog_name [i]);
+                                                               }
+                                                               free(heap_protect);
+                                                               return 2;
+                                                       }
+                                                       free(heap_protect);
+                                                       memcpy(prog_field [num_field], buffer, (strlen(buffer)+1));
+                                                       num_field++;
+                                               }
+                                       }
+                               }
+                               if (num_field == MAXFIELDS) {
+
+                                       p->class_name = prog_name [num_record];
+                                       p->handle_touch = (atoi(prog_field [0]));
+                                       p->l_touch_up = (atoi(prog_field [1]));
+                                       p->l_touch_up_plus = (atoi(prog_field [2]));
+                                       p->l_touch_down = (atoi(prog_field [3]));
+                                       p->l_touch_down_plus = (atoi(prog_field [4]));
+                                       p->r_touch_up = (atoi(prog_field [5]));
+                                       p->r_touch_up_plus = (atoi(prog_field [6]));
+                                       p->r_touch_down = (atoi(prog_field [7]));
+                                       p->r_touch_down_plus = (atoi(prog_field [8]));
+                                       p->key_9 = (atoi(prog_field [9]));
+                                       p->key_9_plus = (atoi(prog_field [10]));
+                                       p->key_10 = (atoi(prog_field [11]));
+                                       p->key_10_plus = (atoi(prog_field [12]));
+                                       p->key_11 = (atoi(prog_field [13]));
+                                       p->key_11_plus = (atoi(prog_field [14]));
+                                       p->key_12 = (atoi(prog_field [15]));
+                                       p->key_12_plus = (atoi(prog_field [16]));
+                                       p->key_13 = (atoi(prog_field [17]));
+                                       p->key_13_plus = (atoi(prog_field [18]));
+                                       p->key_14 = (atoi(prog_field [19]));
+                                       p->key_14_plus = (atoi(prog_field [20]));
+                                       p->key_15 = (atoi(prog_field [21]));
+                                       p->key_15_plus = (atoi(prog_field [22]));
+                                       p->key_16 = (atoi(prog_field [23]));
+                                       p->key_16_plus = (atoi(prog_field [24]));
+
+                                       num_record++;
+                                       p++;
+                               } else {
+                                               free(prog_name [num_record]);
+                               }
+                               for (i = 0; i < num_field; i++) {
+                                       free(prog_field [i]);
+                               }
+                               num_field = 0;
+                       }
+               }
+       }
+       if (!num_record) {
+               return 1;
+       }
+       num_list = num_record;
+       return 0;
+}
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* Function writes out a short configuration file if none exists. It takes */
+/* the info from a global memory structure whose only purpose is this initial */
+/* write moment. The file should then be read back immediately to populate a */
+/* memory structure that other functions rely on for their proper operation. */
+/* Returns nothing useful. Write errors are checked in the calling function. */
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+int write_file_config(int *ip, FILE *fp)
+{
+
+       struct program *p;
+       p = (void *)*ip;
+
+       fprintf(fp, "------------------------------The field order is:-------------------------\n");
+       fprintf(fp, "Programname        handle_touch \n");
+       fprintf(fp, "l_touch_up l_touch_up_plus l_touch_down    l_touch_down_plus\n");
+       fprintf(fp, "r_touch_up r_touch_up_plus r_touch_down    r_touch_down_plus\n");
+       fprintf(fp, "key_9              key_9_plus      key_10          key_10_plus\n");
+       fprintf(fp, "key_11             key_11_plus     key_12          key_12_plus\n");
+       fprintf(fp, "key_13             key_13_plus     key_14          key_14_plus\n");
+       fprintf(fp, "key_15             key_15_plus     key_16          key_16_plus\n");
+       fprintf(fp, "--------------------------------------------------------------------------\n");
+       fprintf(fp, "Please don't put any comment inside the definition below this text block.\n");
+       fprintf(fp, "And please don't alter or remove the commas (,) after each field entry.\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "{\"%s\",   %d,\n", p->class_name, p->handle_touch);
+       fprintf(fp, "%d,                %d,             %d,             %d,\n", p->l_touch_up, p->l_touch_up_plus, p->l_touch_down, p->l_touch_down_plus);
+       fprintf(fp, "%d,                %d,             %d,             %d,\n", p->r_touch_up, p->r_touch_up_plus, p->r_touch_down, p->r_touch_down_plus);
+       fprintf(fp, "%d,                %d,             %d,             %d,\n", p->key_9, p->key_9_plus, p->key_10, p->key_10_plus);
+       fprintf(fp, "%d,                %d,             %d,             %d,\n", p->key_11, p->key_11_plus, p->key_12, p->key_12_plus);
+       fprintf(fp, "%d,                %d,             %d,             %d,\n", p->key_13, p->key_13_plus, p->key_14, p->key_14_plus);
+       fprintf(fp, "%d,                %d,             %d,             %d,     }\n\n", p->key_15, p->key_15_plus, p->key_16, p->key_16_plus);
+
+       return 0;
+}
+
+/* End Code */
+
similarity index 58%
rename from event_loop.c
rename to src-server/event_loop.c
index e8836d0..97a5f9c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * event_loop -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
+ * event_loop.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
  *
  * Copyright (C) 2005 - Mats Johannesson
  *
  */
 
 #include "globals.h"
-#include "UserConfig-Pad"
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* Function waits perpetually for the X server to deliver information */
+/* about events from the input device. Receipt of an event that we've */
+/* registered for (button press/release and motion) triggers a good deal */
+/* of activity in a setup phase, after which we send the fake key press */
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
 int use_events(Display *display)
 {
-       
+
+       XClassHint *class_hint;
+
+       Window focus_window;
+       int focus_state;
+
+       Window root, parent;
+       Window *children;
+       unsigned int num_children;
+
+       struct program *p;
+       int in_list;
+
+       int elder_rotation = 4097; /* Set the Touch Strip state histories to */
+       int old_rotation = 4097;   /* their max values. This is to ensure */
+       int elder_throttle = 4097; /* that no action is taken on the very */
+       int old_throttle = 4097;   /* first touch before a real history is */
+       int rotation;              /* recorded. Bottom is 4097. Top is 2 */
+       int throttle;
+
+       XDeviceMotionEvent *motion;
+       XDeviceButtonEvent *button;
+
        XEvent Event;
+
        while(1) {
-               XNextEvent(display, &Event);
 
-               XClassHint *class_hint;
-               class_hint = XAllocClassHint();
+               XNextEvent(display, &Event);
 
-               Window focus_window = None;
-               int focus_state;
+               class_hint = XAllocClassHint(); /* Memory allocation. Free it later! */
 
-               Window root, parent;
-               Window *children;
-               unsigned int num_children;
+               focus_window = None;
+               in_list = 0;
 
-               struct program *p;
-               int in_list = 0;
+/* Locate which window that currently has the focus and get its list of */
+/* related windows. Then pull its ClassHint into our allocated structure */
 
                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)){
+/* If the class hint (aka WM_CLASS) contains no class string we free the */
+/* allocated memory for each structure member and get the ClassHint of the */
+/* window parent, if it has one. Observe that we must skip the root window */
+
+               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;
+/* If the root window had the focus, or if the active window or its parent */
+/* had no class string at all, we use the top ("default") program definition */
+/* from the read in configuration file when evaluating the event. Otherwise */
+/* we start scanning for a match between the class strings in our list and */
+/* the found window class. Set a flag if a match is encountered */
+
+               if ((focus_window == root) || (class_hint->res_class == NULL)) {
+                       p = external_list;
                } else {
-                       for (p = prog_list; p < prog_list + NUM_LIST; p++)
-                               if (strcmp (class_hint->res_class, p->class_name) == 0){
+                       for (p = external_list; p < external_list + num_list; p++)
+                               if (strcmp (class_hint->res_class, p->class_name) == 0) {
                                        in_list = 1;
                                        break;
                                }
                        }
+
+/* Any program not found in our configuration gets the "default" treatment */
+
+               if (!in_list) {
+                       p = external_list;
+               }
+
+/* The allocated memory for the ClassHint structure, and each of its */
+/* members, must be freed here. Also, the call to XQueryTree to get a */
+/* list of related windows might have allocated memory for child entries. */
+/* It must be released as well */
                
                XFree(class_hint->res_class);
                XFree(class_hint->res_name);
+               XFree(class_hint);
                if (children) XFree((char *)children);
 
-               if (!in_list){
-                       p = prog_list;
-               }
+/* Finally start to look at the actual event. Touch Strips come first */
 
                if (Event.type == motion_type) {
 
-                       if (p->handle_touch){
-                               int rotation;
-                               int throttle;
-       
-                               XDeviceMotionEvent *motion = (XDeviceMotionEvent *) &Event;
+                       if (p->handle_touch) {
+
+                       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){
+/* As can be analyzed with Frederic Lepied's excellent xinput-1.2 program */
+/* the touch strip data comes in on axis 3 and 4 (left and right strips). */
+/* The pad device never uses x-axis [0], y-axis [1] or wheel [5]. The value */
+/* is always 0 there. The pressure [2], rotation [3] and throttle [4] all */
+/* rest with a value of 1. Touch strips send data about the finger position */
+/* in 13 steps. Furthest down is 4097 while the top is 2. Template: */
+/* 4097, 2049, 1025, 513, 257, 129, 65, 33, 17, 9, 5, 3, 2. We don't care */
+/* about those numbers per se (for now at least ;-), but just stick them */
+/* in history buffers. The present value is then compared to an old and */
+/* an even older one to determine direction of the finger movement. Observe */
+/* that when we finally send a fake keypress, it has two parts - true and */
+/* false. It corresponds with a key press and a key release. Order is key ;-) */
+
+/* Left Touch Strip */
+
+                               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){
+                                                       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){
+                                       } 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){
+                                                       if (p->l_touch_down_plus) {
                                                                XTestFakeKeyEvent(display, p->l_touch_down_plus, True, CurrentTime);
                                                                XTestFakeKeyEvent(display, p->l_touch_down_plus, False, CurrentTime);
                                                        }
@@ -105,20 +163,22 @@ int use_events(Display *display)
                                old_rotation = rotation;
                                }
 
-                               if (throttle > 1){
-                                       if ((throttle < old_throttle) && (old_throttle <= elder_throttle)){
-                                               if (p->r_touch_up){
+/* Right Touch Strip */
+
+                               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){
+                                                       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){
+                                       } 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){
+                                                       if (p->r_touch_down_plus) {
                                                                XTestFakeKeyEvent(display, p->r_touch_down_plus, True, CurrentTime);
                                                                XTestFakeKeyEvent(display, p->r_touch_down_plus, False, CurrentTime);
                                                        }
@@ -131,16 +191,46 @@ int use_events(Display *display)
                        }
                }
 
+/* Now see if the event concerned the pad buttons. Not much to talk about. */
+/* We follow the configuration definitions, and handle a pen if requested */
+/* to do so. The switch routine is ugly and easy to get wrong, but it */
+/* works! Ah yes, the xinput-1.2 program reveals Wacom to have numbered the */
+/* buttons 9, 10, 11, 12 on the left side and 13, 14, 15, 16 on the right. */
+/* Template: */
+/*
+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
+------------
+*/
+
+/* Pad Button Press */
+
                if (Event.type == button_press_type) {
 
-                       XDeviceButtonEvent *button = (XDeviceButtonEvent *) &Event;
+                       button = (XDeviceButtonEvent *) &Event;
 
                        switch (button->button) {
 
                                case 9:
                                if (p->key_9 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -154,8 +244,8 @@ int use_events(Display *display)
 
                                case 10:
                                if (p->key_10 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -169,8 +259,8 @@ int use_events(Display *display)
 
                                case 11:
                                if (p->key_11 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -184,8 +274,8 @@ int use_events(Display *display)
 
                                case 12:
                                if (p->key_12 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -199,8 +289,8 @@ int use_events(Display *display)
 
                                case 13:
                                if (p->key_13 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -214,8 +304,8 @@ int use_events(Display *display)
 
                                case 14:
                                if (p->key_14 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -229,8 +319,8 @@ int use_events(Display *display)
 
                                case 15:
                                if (p->key_15 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -244,8 +334,8 @@ int use_events(Display *display)
 
                                case 16:
                                if (p->key_16 == TOGGLE_PEN)
-                                       if (HANDLE_PEN)
-                                               toggle_pen_mode(display, PEN_NAME);
+                                       if (handle_pen)
+                                               toggle_pen_mode(display, pen_name);
                                        else
                                        break;
                                else
@@ -262,8 +352,14 @@ int use_events(Display *display)
                        }
                }
 
+/* Pad Button Release */
+
+/* There is just an exit point below */
+/* this switch routine by the way */
+
                if (Event.type == button_release_type) {
-                       XDeviceButtonEvent *button = (XDeviceButtonEvent *) &Event;
+
+                       button = (XDeviceButtonEvent *) &Event;
 
                        switch (button->button) {
 
@@ -368,7 +464,7 @@ int use_events(Display *display)
                        }
                }
        }
-       return EXIT_OK;
+       exit(EXIT_OK);
 }
 
 /* End code */
similarity index 66%
rename from get_device.c
rename to src-server/get_device.c
index 3b74b43..44e77c4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005 - Mats Johannesson
  *
- * Based on xinput.c 1996 by Frederic Lepied
+ * Based on xinput.c 1996 by Frederic Lepied (xinput-1.2)
  *
  * 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
 
 #include "globals.h"
 
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* Function queries the X server for input devices. It only cares about non */
+/* core ones, and compares them with what was specified on the command line. */
+/* The "info" is a scratch XDeviceInfo construct which is freed by the  */
+/* caller after having set a permanent global copy for later reference */
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
 int get_device_info(Display *display, char *name)
 {
        int             i;
@@ -32,7 +39,7 @@ int get_device_info(Display *display, char *name)
 
        for(i = 0; i < nr_devices; i++) {
                if ((info[i].use == IsXExtensionDevice) &&
-               (strcmp (info[i].name, name) == 0)){
+               (strcmp (info[i].name, name) == 0)) {
                        return (int) &info[i];
                }
        }
diff --git a/src-server/globals.c b/src-server/globals.c
new file mode 100644 (file)
index 0000000..508c16f
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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;
+XDeviceInfo *info;
+XDeviceInfo *pad_info;
+XDeviceInfo *pen_info;
+XDevice *pad_device;
+XDevice *pen_device;
+
+char *our_prog_name;
+char *pen_name;
+char *total_config_dir;
+char *config_dir = "/.expresskeys";    /* This is where in the user home */
+char *config_file = "/expresskeys.conf";/* directory we'd like to reside, */
+char *pid_file = "/expresskeys.pid";   /* and what our different status */
+char *error_file = "/error.log";       /* files should be called */
+
+int screen;
+int go_daemon = 0;     /* Do not become a daemon without a command */
+int reread_config = 0; /* No memory should be freed on the first read */
+int handle_pen = 0;    /* Pen should not be handled per default */
+int pen_mode = 1;      /* Assume pen is in Absolute mode initially */
+int pen_open = 0;      /* Pen device hasn't been opened */
+
+int motion_type = NON_VALID;
+int button_press_type = NON_VALID;
+int button_release_type = NON_VALID;
+
+/* Allocate space for a list of program definitions (config file based) */
+/* Also initialize a small list that is written out if no config file exists */
+
+struct program external_list [MAXRECORDS];
+struct program internal_list[] = {
+/*     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       },
+
+/*     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       },
+
+/*     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       },
+
+/*     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       },
+};
+/* The number of programs (num_list) must be computed here. After the struct */
+int num_list = (sizeof internal_list / sizeof internal_list[0]);
+
+/* End Code */
+
diff --git a/src-server/globals.h b/src-server/globals.h
new file mode 100644 (file)
index 0000000..543c414
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ *
+ */
+
+/* Standard Program includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+/* For the daemon and getpid calls */
+#include <unistd.h>
+/* For the mkdir and getpid calls */
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* Standard X includes */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+/* Special X extensions we use */
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XTest.h>
+
+/* Our internal defines */
+#define EXIT_OK 0
+#define EXIT_KO 1
+#define NON_VALID -1
+#define TOGGLE_PEN 999 /* String signaling the key's use as a mode toggle */
+#define MAXRECORDS 64  /* Max program definitions to handle (enough? ;-) */
+#define MAXFIELDS 25   /* Max entries (minus program name) in each record */
+#define MAXDIGITS 3    /* Max number of digits in a key entry */
+#define MAXBUFFER 64   /* Scratch buffer. Also sets program name length limit*/
+
+/* Our global variables */
+extern char *our_prog_name;    /* This program's file name */
+extern char *pen_name;         /* Identifier as set in the X config file */
+extern char *total_config_dir; /* The "~/" of the user, plus our config_dir */
+extern char *config_dir;       /* Set to a dot directory: .expresskeys */
+extern char *config_file;      /* Set to expresskeys.conf */
+extern char *pid_file;         /* Set to expresskeys.pid */
+extern char *error_file;       /* Set to error.log */
+
+extern int screen;     /* Active screen. An X thing */
+extern int num_list;   /* Number of programs we currently handle */
+
+extern int go_daemon;  /* Flag to see if this program is in daemon mode */
+extern int reread_config; /* Flag for memory release if redoing the config */
+extern int handle_pen; /* Flag (main switch) to see if a pen is handled */
+extern int pen_mode;   /* Flag to keep track of the pen mode we are in */
+extern int pen_open;   /* Flag to make sure we only open the pen once */
+
+extern int motion_type;                /* Event type to keep track of - Touch Strips */
+extern int button_press_type;  /* Event type to keep track of - Pad Buttons */
+extern int button_release_type;        /* Event type to keep track of - Pad Buttons */
+
+/* Global X functions */
+extern Display *display;       /* Active display. An X thing */
+extern XDeviceInfo *info;      /* Scratch while fishing for pad and pen info */
+extern XDeviceInfo *pad_info;  /* Keeps all X knowledge of the pad device */
+extern XDeviceInfo *pen_info;  /* Keeps all X knowledge of the pen device */
+extern XDevice *pad_device;    /* The actual pointer to the pad device */
+extern XDevice *pen_device;    /* The actual pointer to the pen device */
+
+/* Our global (internal) functions */
+/* In config_all.c */
+extern int read_file_config(int *ip, FILE *fp);
+extern int write_file_config(int *ip, FILE *fp);
+/* In get_device.c */
+extern int get_device_info(Display *display, char *name);
+/* In reg_events.c */
+extern int register_events(Display *display, XDeviceInfo *pad_info, char *name);
+/* In pen_mode.c */
+extern int toggle_pen_mode(Display *display, char *name);
+/* In event_loop.c */
+extern int use_events(Display *display);
+
+/* Our global structures */
+/* The internal_list is initialized in globals.c */
+/* The external_list is initialized from file reads */
+extern 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;
+       int key_11_plus;
+       int key_12;
+       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;
+}internal_list [], external_list [];
+
+/* End Code */
+
diff --git a/src-server/main_setup.c b/src-server/main_setup.c
new file mode 100644 (file)
index 0000000..f20f0d5
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * 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[])
+{
+
+       our_prog_name = argv[0];
+
+       struct program *p;
+
+       int i;
+       int len;
+
+       FILE *fp;
+
+/* Prelaunch sanity checks: See if X is OK */
+
+       if ((display = XOpenDisplay(NULL)) == NULL) {
+               fprintf(stderr, "%s ERROR: Can not connect to your X Server\n", our_prog_name);
+               return EXIT_KO; 
+       }
+       screen = DefaultScreen(display);
+
+/* Can we use XTest to send fake key presses */
+
+       int event_base, error_base;
+       int major_version, minor_version;
+       if (!XTestQueryExtension(display, &event_base, &error_base,
+               &major_version, &minor_version)) {
+               fprintf(stderr, "%s ERROR: XTest extension not present on your X server\n", our_prog_name);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+/* Can we use XInput to talk with the tablet */
+
+       XExtensionVersion *xinputext;
+       xinputext = XGetExtensionVersion(display, INAME);
+       if (xinputext && (xinputext != (XExtensionVersion*) NoSuchExtension)) {
+               XFree(xinputext);
+       } else {
+               fprintf(stderr, "%s ERROR: XInput extension not present on your X server\n", our_prog_name);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+/* We need at least the pad name specified... */
+
+       if (argc < 2) {
+               fprintf(stderr, "\n");
+               fprintf(stderr, "Usage: %s <pad-device-name> [<pen-device-name>] [-d]\n", our_prog_name);
+               fprintf(stderr, "\n");
+               fprintf(stderr, "Where the pad name is mandatory. Specify a pen name\n");
+               fprintf(stderr, "if you want the program to handle pen mode switches.\n");
+               fprintf(stderr, "Use -d to make the program a daemon (run in the background).\n");
+               fprintf(stderr, "\n");
+               fprintf(stderr, "Example: %s pad stylus -d\n", our_prog_name);
+               fprintf(stderr, "\n");
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+/* See if the pad is for real, and if it is active */
+
+       pad_info = (void *) get_device_info(display, argv[1]);
+       XFreeDeviceList(info);
+       if (!pad_info) {
+               fprintf(stderr, "%s ERROR: Can not find pad device: %s\n", our_prog_name, argv[1]);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+/* Set a flag if we should run as a daemon. Also register */
+/* and check a pen device, should such an action be requested */
+
+       if (argc > 2) {
+               for (i = 2; i < argc; i++) {
+                       if (strcmp(argv[i], "-d") == 0) {
+                               go_daemon = 1;
+                               break;
+                       }
+               }
+               for (i = 2; i < argc; i++) {
+                       if (strcmp(argv[i], "-d") != 0) {
+                               pen_name = argv[i];
+                               handle_pen = 1;
+                               pen_info = (void *) get_device_info(display, argv[i]);
+                               XFreeDeviceList(info);
+                               if (!pen_info) {
+                                       fprintf(stderr, "%s ERROR: Can not find pen device: %s\n", our_prog_name, pen_name);
+                                       XCloseDisplay(display);
+                                       return EXIT_KO;
+                               }
+                               break;
+                       }
+               }
+       }
+
+/* Make sure we can open a requested pen */
+
+       if (handle_pen) {
+               pen_mode = Relative;
+               if (toggle_pen_mode(display, pen_name)) {
+                       fprintf(stderr, "%s ERROR: Can not open pen device: %s\n", our_prog_name, pen_name);
+                       XCloseDisplay(display);
+                       return EXIT_KO;
+               }
+       }
+
+/* Locate the home directory of the user running this program */
+
+       char *user_homedir;
+       if ((user_homedir = getenv("HOME")) == NULL) {
+               fprintf(stderr, "%s ERROR: Can not find your HOME directory!\n", our_prog_name);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+/* This is silly, but in order to keep the heap from being stomped on */
+/* by malloc and even automatic allocations we first need to allocate */
+/* a slight bit of memory. Here I use 1024 bytes, which seems enough. */
+/* Not doing this results in random errors when changing the code. */
+/* The "heap_protect" memory is freed right after the next malloc */
+/* Another solution is to allocate a fair bit of memory in the actual */
+/* malloc that stomps on the heap. But it seems even sillier to use */
+/* a 1024 byte string when only needing 41, than this workaround is*/
+
+       char *heap_protect;
+       if ((heap_protect = (char *)malloc(1024)) == NULL) {
+               fprintf(stderr, "%s ERROR: Memory allocation trouble at stage 1!\n", our_prog_name);
+               return EXIT_KO; 
+       }
+
+/* Concatenate the home directory string with the string of our preferred*/
+/* configuration file directory. The address to the whole string is then */
+/* copied to a global pointer, so we won't have to perform this part again */
+
+       char *total_config_dir_block;
+       len = strlen(user_homedir) + strlen(config_dir) + 1;
+       if ((total_config_dir_block = (char *)malloc(len)) == NULL) {
+               fprintf(stderr, "%s ERROR: Memory allocation trouble at stage 2!\n", our_prog_name);
+               XCloseDisplay(display);
+               return EXIT_KO; 
+       }
+       sprintf(total_config_dir_block, "%s%s", user_homedir, config_dir);
+       total_config_dir = total_config_dir_block;
+
+/* And here's the heap_protect freeing... */
+
+       free(heap_protect);
+
+/* Try to open the the configuration directory for */
+/* reading, just as a test to see if it exists. A failure */
+/* here can mean many things, but we then try to create */
+/* it as a means to rule out a true lack of existence */
+
+       if ((fp = fopen(total_config_dir, "r")) == NULL) {
+               if ((mkdir(total_config_dir, 0777)) == NON_VALID) {
+                       fprintf(stderr, "%s ERROR: Can not read or create %s\n", our_prog_name, total_config_dir);
+                       XCloseDisplay(display);
+                       return EXIT_KO;
+               }
+       } else {
+               fclose(fp);
+       }
+
+/* Concatenate the full directory path string with */
+/* the string of our preferred configuration file name */
+
+       len = strlen(total_config_dir) + strlen(config_file) + 1;
+       char file_path [len];
+       sprintf(file_path, "%s%s", total_config_dir, config_file);
+       
+/* If no configuration file exists, write out a */
+/* short one from an internal memory structure */
+
+       if ((fp = fopen(file_path, "a+")) == NULL) {
+               fprintf(stderr, "%s ERROR: Can not open %s in read/write mode\n", our_prog_name, file_path);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       } else {
+               rewind(fp);
+               if (fgetc(fp) == EOF) {
+                       for (p = internal_list; p < internal_list + num_list; p++) {
+                               write_file_config((void *)&p, fp);
+                               if (ferror(fp)) {
+                                       fprintf(stderr, "%s ERROR: Write error in %s\n", our_prog_name, file_path);
+                                       XCloseDisplay(display);
+                                       return EXIT_KO;
+                               }
+                       }
+               }
+       }
+       fclose(fp);
+
+/* Read in an existing configuration file */
+
+       p = external_list;
+       if ((fp = fopen(file_path, "r")) == NULL) {
+               fprintf(stderr, "%s ERROR: Can not open %s in read mode\n", our_prog_name, file_path);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       } else {
+               switch (read_file_config((void *)&p, fp)){
+                       
+                       case 0:
+                       fclose(fp);
+                       break;
+
+                       case 1:
+                       fprintf(stderr, "%s ERROR: No complete record found in %s\n", our_prog_name, file_path);
+                       XCloseDisplay(display);
+                       return EXIT_KO;
+                       
+                       case 2:
+                       fprintf(stderr, "%s ERROR: Memory allocation error while parsing %s\n", our_prog_name, file_path);
+                       XCloseDisplay(display);
+                       return EXIT_KO;
+                       
+                       default:
+                       fprintf(stderr, "%s ERROR: Unknown error while parsing %s\n", our_prog_name, file_path);
+                       XCloseDisplay(display);
+                       return EXIT_KO;
+               }
+       }
+
+/* Ready to launch in the foreground or as a daemon after one last check. */
+/* In daemon mode we also take care of storing our PID in the config dir */
+
+       if (register_events(display, pad_info, argv[1])) {
+               if (go_daemon) {
+                       if ((daemon(0, 1)) == NON_VALID) {
+                               fprintf(stderr, "%s ERROR: Failed to fork into daemon mode! EXITING!\n", our_prog_name);
+                               XCloseDisplay(display);
+                               exit(EXIT_KO);
+                       } else {
+                               char pid_buffer [MAXBUFFER];
+                               sprintf(pid_buffer, "%d\n", getpid());
+
+                               len = strlen(total_config_dir) + strlen(pid_file) + 1;
+                               char pid_path [len];
+                               sprintf(pid_path, "%s%s", total_config_dir, pid_file);
+
+                               if ((fp = fopen(pid_path, "w")) == NULL) {
+                                       fprintf(stderr, "%s ERROR: Can not open %s in write mode\n", our_prog_name, pid_path);
+                                       XCloseDisplay(display);
+                                       exit(EXIT_KO);
+                               } else {
+                                       fprintf(fp, "%s", pid_buffer);
+                                       if (ferror(fp)) {
+                                               fprintf(stderr, "%s ERROR: Write error in %s\n", our_prog_name, pid_path);
+                                               XCloseDisplay(display);
+                                               exit(EXIT_KO);
+                                       } else {
+                                               fclose(fp);
+                                       }
+                               }
+                       }
+               }
+               use_events(display); /* <-- Our true launch! The event loop */
+       } else {
+               fprintf(stderr, "%s ERROR: Could not register any events!\n", our_prog_name);
+               XCloseDisplay(display);
+               return EXIT_KO;
+       }
+
+       XCloseDisplay(display);
+       return EXIT_OK;
+}
+
+/* End Code */
+
diff --git a/src-server/makefile b/src-server/makefile
new file mode 100644 (file)
index 0000000..b946e9e
--- /dev/null
@@ -0,0 +1,27 @@
+CC = gcc
+CFLAGS = -O2 -Wall
+# Use -g3 to get full debug info
+
+INCLUDES = -I/usr/X11R6/lib
+LDFLAGS = -L/usr/X11R6/lib
+LIBS = -lX11 -lXext -lXi -lXtst
+
+TARGET = ekeys
+
+SRCS = globals.c config_all.c get_device.c reg_events.c \
+       pen_mode.c event_loop.c main_setup.c
+
+OBJS = $(SRCS:.c=.o)
+ALL =  $(SRCS)
+
+all:   $(TARGET)
+
+$(TARGET):     $(OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+.c.o:
+       $(CC) $(CFLAGS) $(INCLUDES) -c $*.c
+
+clean:
+       rm -f $(OBJS) $(TARGET)
+
similarity index 72%
rename from pen_mode.c
rename to src-server/pen_mode.c
index 71ca865..52937e9 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005 - Mats Johannesson
  *
- * Based on setmode.c 1996 by Frederic Lepied
+ * Based on setmode.c 1996 by Frederic Lepied (xinput-1.2)
  *
  * This code is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 
 #include "globals.h"
 
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* Function opens the X input device (which stays open until program end) */
+/* and toggles mode between Absolute and Relative based on a flag status. */
+/* We make sure to only open the pen once by setting another flag. */
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
 int toggle_pen_mode(Display *display, char *name)
 {
 
@@ -39,8 +45,7 @@ int toggle_pen_mode(Display *display, char *name)
                XSetDeviceMode(display, pen_device, pen_mode);
                return 0;
        } else {
-               fprintf(stderr, "ERROR: Can not open pen device: %s\n", PEN_NAME);
-               return 0;
+               return 1;
        }
 }
 
similarity index 70%
rename from reg_events.c
rename to src-server/reg_events.c
index 824576a..2f09554 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005 - Mats Johannesson
  *
- * Based on test.c 1996 by Frederic Lepied
+ * Based on test.c 1996 by Frederic Lepied (xinput-1.2)
  *
  * 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
 
 #include "globals.h"
 
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* Function opens the X input device (which stays open until program end) */
+/* and starts to look for supported event types. The scope should be the */
+/* root window (ie everywhere) and we're only interested in motion events */
+/* (touch strip action) and button press/release. Having found the info */
+/* we ask the X server to keep us continuously notified about these events */
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
 int register_events(Display *display, XDeviceInfo *pad_info, char *name)
 {
        int i;
@@ -35,7 +43,7 @@ int register_events(Display *display, XDeviceInfo *pad_info, char *name)
 
        pad_device = XOpenDevice(display, pad_info->id);
        if (!pad_device) {
-               fprintf(stderr, "ERROR: Can not open device %s\n", name);
+               fprintf(stderr, "%s ERROR: Can not open device %s\n", our_prog_name, name);
                return 0;
        }
 
@@ -61,7 +69,7 @@ int register_events(Display *display, XDeviceInfo *pad_info, char *name)
                }
 
        if (XSelectExtensionEvent(display, root_win, event_list, count)) {
-               fprintf(stderr, "ERROR: Could not select extended events!\n");
+               fprintf(stderr, "%s ERROR: Could not select extended events!\n", our_prog_name);
                return 0;
                }
        }