diff -ru gpm-1.19.4.orig/README.synaptics gpm-1.19.4/README.synaptics
--- gpm-1.19.4.orig/README.synaptics	Mon Jan 17 13:21:00 2000
+++ gpm-1.19.4/README.synaptics	Tue Sep 11 18:31:38 2001
@@ -178,3 +178,59 @@
 
                                            The default value is 3 (right)
 
+  /* wmode parameters */
+  use_wmode                      flag      This is to enable the wmode of
+                                           Synaptics touchpad which
+					   supports more configurable
+					   options and buttons.
+
+					   The default value is 0 (disable)
+					   
+  finger_threshold               int       The threshold of the pressure
+                                           reading to consider the finger
+					   is on the pad.
+
+					   The default value is 30
+
+  tap_lower_limit                msec      The lower bound of finger
+                                           contact time to be considerred
+					   a tap.
+
+					   The default value is 5 (0.005 sec)
+					   
+  tap_upper_limit                msec      The upper bound of finger
+                                           contact time to be considerred
+					   a tap.
+
+					   The default value is 200 (0.2 sec)
+					   
+  tap_range                      int       The maximum displacement of
+                                           finger contact to be considered
+					   a tap.
+
+					   The default value is 100 (0.1 sec)
+
+  tap_interval			 msec      The time length of button press
+                                           generated when a tap is
+					   recognized, which is also the
+					   time within which further
+					   finger contact will be consider
+					   a drag (or multiple click, if
+					   it's also a tap).
+					   
+					   The default value is 200 (0.2 sec)
+
+  drag_lock                      flag      Whether to enable drag lock,
+                                           that is, do not break a drag
+					   until next tap even when the
+					   finger is off the pad.
+
+					   The default value is 0 (disable)
+
+  multiple_click_delay           msec      Break length between button
+                                           presses when generating multiple
+					   click.
+
+					   The default value is 30 (0.03 sec)
+  
+  
diff -ru gpm-1.19.4.orig/contrib/Makefile gpm-1.19.4/contrib/Makefile
--- gpm-1.19.4.orig/contrib/Makefile	Wed May  2 10:54:00 2001
+++ gpm-1.19.4/contrib/Makefile	Tue Sep 11 18:36:26 2001
@@ -1,7 +1,7 @@
 # Generated automatically from Makefile.in by configure.
 
 top_builddir = ..
-srcdir = /home/user/nico/computer/programming/gpm/gpm-1.19.4/contrib
+srcdir = /home/cjj/src/gpm-syn/gpm-1.19.4/contrib
 
 all:
 
diff -ru gpm-1.19.4.orig/synaptics.c gpm-1.19.4/synaptics.c
--- gpm-1.19.4.orig/synaptics.c	Mon Jan 17 13:34:00 2000
+++ gpm-1.19.4/synaptics.c	Tue Sep 11 18:06:27 2001
@@ -145,10 +145,19 @@
 /* edge motion related configuration constants */
 static int   x_min_center            = 1632;  /* left edge   */
 static int   x_max_center            = 5312;  /* right edge  */
-static int   y_min_center            = 1568;  /* bottom edge */
-static int   y_max_center            = 4288;  /* top edge    */
+static int   y_min_center            = 1408;  /* bottom edge */
+static int   y_max_center            = 4108;  /* top edge    */
 static int   edge_speed              = 20;                                /*C*/
 
+/* use wmode */
+static int use_wmode		     = 0;
+static int finger_threshold	     = 30;
+static int tap_lower_limit	     = 5;
+static int tap_upper_limit	     = 200;
+static int tap_range		     = 100;
+static int tap_interval		     = 200;
+static int drag_lock		     = 0;
+static int multiple_click_delay	     = 30;
 
 /*
 ** Types for describing corner actions.
@@ -229,8 +238,17 @@
   { "lower_left_action",          Corner_Param,  &corner_actions [1]         },
   { "upper_right_action",         Corner_Param,  &corner_actions [2]         },
   { "lower_right_action",         Corner_Param,  &corner_actions [3]         },
+  /* use wmode */
+  { "use_wmode",		  Flag_Param,	 &use_wmode		     },
+  { "finger_threshold",		  Integer_Param, &finger_threshold	     },
+  { "tap_lower_limit",		  Integer_Param, &tap_lower_limit	     },
+  { "tap_upper_limit",		  Integer_Param, &tap_upper_limit	     },
+  { "tap_range",		  Integer_Param, &tap_range		     },
+  { "tap_interval",		  Integer_Param, &tap_interval		     },
+  { "drag_lock",		  Flag_Param,	 &drag_lock		     },
+  { "multiple_click_delay",	  Integer_Param, &multiple_click_delay	     },
   /* end of list */
-  { NULL,                         Flag_Param,    NULL                        },
+  { NULL,                         Flag_Param,    NULL                        }
 };
 
 
@@ -258,6 +276,17 @@
   int info_geometry;
 } model_id_type;
 
+/*
+** The information returned in the extended capibility packet.
+*/
+
+typedef struct {
+  int cap_ext;
+  int cap_sleep;
+  int cap_four_button;
+  int cap_multi_finger;
+  int cap_palm_detect;
+} ext_cap_type;
 
 /*
 ** The format of the reported absolute data.
@@ -267,6 +296,7 @@
   int finger;
   int left;
   int middle;
+  int down;
   int right;
   int x;
   int y;
@@ -658,7 +688,7 @@
     ** If there is a continuing gesture then report the same buttons.
     ** Otherwise compute new buttons.
     */
-    if (!report.gesture && !report.left && !report.right) {
+    if (!report.gesture && !report.left && !report.right && !report.middle && !report.down) {
       state->buttons = 0;
     } else if (last_gesture) {
       state->buttons = last_buttons;
@@ -670,6 +700,12 @@
       if (report.right) 
         state->buttons |= GPM_B_RIGHT;
 
+      if (report.middle)
+	state->buttons |= GPM_B_MIDDLE;
+
+      if (report.down)
+	state->buttons |= 0x8;
+
       process_corner_taps (state, report);
     }
   }
@@ -1106,6 +1142,19 @@
   extract_model_id_info (model_int, model);
 }
 
+/* read the extended capibility from the ps2 touchpad */
+static void syn_read_ps2_cap (int fd,
+                              ext_cap_type *cap)
+{
+  unsigned char bytes [3];
+  ps2_status_rqst (fd, 0x02, bytes);
+  cap->cap_ext          = check_bits (bytes[0], 0x80);
+  cap->cap_sleep        = check_bits (bytes[2], 0x10);
+  cap->cap_four_button  = check_bits (bytes[2], 0x08);
+  cap->cap_multi_finger = check_bits (bytes[2], 0x02);
+  cap->cap_palm_detect  = check_bits (bytes[2], 0x01);
+}
+
 /* read the modes from the touchpad (in ps/2 format) */
 static void read_ps2_modes (int fd) 
 {
@@ -1168,6 +1217,100 @@
   }
 }
 
+static void syn_translate_ps2_wmode_report (unsigned char *data,
+				      report_type *report) 
+{
+  int i;
+  static int finger_timer = 0;
+  static int gesture_timer = 0;
+  static int gesture_delay = 0;
+  static int stroke_x;
+  static int stroke_y;
+  static int drag_locked = 0;
+
+  if (((data[0] & 0xc8) == 0x80) && ((data[3] & 0xc8) == 0xc0)) {
+    unsigned int w = ((data[3] & 0x04) >> 2) |
+	    		((data[0] & 0x04) >> 1) |
+			((data[0] & 0x30) >> 2);
+    report->left     = check_bits (data[0], 0x01);
+    report->middle   = check_bits (data[0] ^ data[3], 0x01);
+    report->down     = check_bits (data[0] ^ data[3], 0x02);
+    report->right    = check_bits (data[0], 0x02);
+    report->x        = (((data[1] & 0x0f) << 8) |
+			((data[3] & 0x10) << 8) |
+			data[4]);
+    report->y        = (((data[1] & 0xf0) << 4) |
+			((data[3] & 0x20) << 7) |
+			data[5]);
+    report->pressure = data[2];
+    report->finger   = (data[2] > finger_threshold);
+    
+    if (report->finger) {
+	    
+      if (finger_timer == 0) { /* finger down */
+	stroke_x = report->x;
+	stroke_y = report->y;
+      }
+      
+      if (finger_timer < (tap_upper_limit * 80 / 1000)) finger_timer ++; /* don't want timer to overflow */
+      
+      if (gesture_timer > 0) gesture_timer = 1; /* dragging or consecutive tap, gesture to end with finger up */
+      
+    } else { /* interesting things happen when finger is up */
+	    
+      /* tap determination */
+      if ((finger_timer > (tap_lower_limit * 80 / 1000)) &&  /* minimum finger down time */
+	  (finger_timer < (tap_upper_limit * 80 / 1000)) &&  /* maximum finger down time */
+	  (distance((double)(stroke_x - report->x),  /* maximum range for finger to drift while down */
+	    (double)(stroke_y - report->y))
+	    < sqr((double)tap_range))) {
+
+	/* not a consecutive tap? */
+	if (gesture_timer == 0) gesture_delay = 0; /* right -> don't delay gesture */
+	else { /* a consecutive tap! */
+	  gesture_delay = multiple_click_delay * 80 / 1000; /* delay gesture to create multiple click */
+	}
+	
+	/* is drag locked */
+	if (drag_locked) {
+	  drag_locked = 0; /* unlock it and don't gesture. */
+	  gesture_timer = 0;
+	} else gesture_timer = tap_interval * 80 / 1000; /* setup gesture time to count down */
+	
+      } else {
+	      
+	/* a drag to lock? */
+	if (drag_lock && (gesture_timer > 0) && (finger_timer >= (tap_upper_limit * 80 / 1000)))
+	  drag_locked = 1;
+	      
+	if (gesture_timer > 0) gesture_timer --;
+	if (gesture_delay > 0) gesture_delay --;
+	
+      }
+      
+      finger_timer = 0;
+      
+    }
+    
+    report->gesture  = ((gesture_timer > 0) && (gesture_delay == 0)) || drag_locked;
+    report->left = (report->left || report->gesture);
+
+  } else {
+    gpm_debug_log (LOG_NOTICE,"tossing PS/2 data: ");
+    for (i = 0; i < 6; i++)
+      gpm_debug_log (LOG_NOTICE,"%02X ", data [i]);
+    report->gesture  = 0;
+    report->finger   = 0;
+    report->left     = 0;
+    report->middle   = 0;
+    report->down     = 0;
+    report->right    = 0;
+    report->x        = 0;
+    report->y        = 0;
+    report->pressure = 0;
+  }
+}
+
 
 /****************************************************************************
 **
@@ -1200,7 +1343,8 @@
 {
   report_type   report;
 
-  syn_translate_ps2_report (data, &report);
+  if (use_wmode) syn_translate_ps2_wmode_report (data, &report);
+  else syn_translate_ps2_report (data, &report);
   syn_process_data (state, report);
 }
 
@@ -1243,16 +1387,19 @@
 {
   model_id_type     model;
   info_type         ident;
+  ext_cap_type      cap;
 
   puts ("Initializing Synaptics PS/2 TouchPad");
 
   syn_read_ps2_ident (fd, &ident);
   syn_read_ps2_model_id (fd, &model);
+  syn_read_ps2_cap (fd, &cap);
+  if (! (cap.cap_ext)) use_wmode = 0; /* wmode not support by the pad */
   syn_process_config (ident, model);
 
   /* select 6 byte packet, high packet rate, no-sleep */
   ps2_set_mode2 (fd, (ABSOLUTE_MODE    |
 		      HIGH_REPORT_RATE |
 		      PS2_NO_SLEEP     |
-		      REPORT_W_OFF));
+		      (use_wmode ? REPORT_W_ON : REPORT_W_OFF)));
 }
