--- gpm-1.19.3.orig/synaptics.c	Mon Jan 17 13:34:00 2000
+++ gpm-1.19.3/synaptics.c	Sat Aug 25 18:22:24 2001
@@ -149,6 +149,14 @@
 static int   y_max_center            = 4288;  /* 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	     = 300;
+static int tap_range		     = 100;
+static int tap_interval		     = 200;
+static int multiple_click_delay	     = 30;
 
 /*
 ** Types for describing corner actions.
@@ -229,8 +237,16 @@
   { "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		     },
+  { "multiple_click_delay",	  Integer_Param, &multiple_click_delay	     },
   /* end of list */
-  { NULL,                         Flag_Param,    NULL                        },
+  { NULL,                         Flag_Param,    NULL                        }
 };
 
 
@@ -658,7 +674,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) {
       state->buttons = 0;
     } else if (last_gesture) {
       state->buttons = last_buttons;
@@ -670,6 +686,9 @@
       if (report.right) 
         state->buttons |= GPM_B_RIGHT;
 
+      if (report.middle)
+	state->buttons |= GPM_B_MIDDLE;
+
       process_corner_taps (state, report);
     }
   }
@@ -1168,6 +1187,70 @@
   }
 }
 
+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;
+
+  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->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) {
+	stroke_x = report->x;
+	stroke_y = report->y;
+      }
+      if (finger_timer < (tap_upper_limit * 80 / 1000)) finger_timer ++;
+      if (gesture_timer > 0) gesture_timer = 1;
+    } else {
+      if ((finger_timer > (tap_lower_limit * 80 / 1000)) &&
+	  (finger_timer < (tap_upper_limit * 80 / 1000)) &&
+	  (distance((double)(stroke_x - report->x),
+	    (double)(stroke_y - report->y))
+	    < sqr((double)tap_range))) {
+	if (gesture_timer == 0) gesture_delay = 0;
+	else gesture_delay = multiple_click_delay * 80 / 1000; // multiple click
+	gesture_timer = tap_interval * 80 / 1000;
+      } else {
+	if (gesture_timer > 0) gesture_timer --;
+	if (gesture_delay > 0) gesture_delay --;
+      }
+      finger_timer = 0;
+    }
+    report->gesture  = (gesture_timer > 0) && (gesture_delay == 0);
+    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->right    = 0;
+    report->x        = 0;
+    report->y        = 0;
+    report->pressure = 0;
+  }
+}
+
 
 /****************************************************************************
 **
@@ -1200,7 +1283,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);
 }
 
@@ -1254,5 +1338,5 @@
   ps2_set_mode2 (fd, (ABSOLUTE_MODE    |
 		      HIGH_REPORT_RATE |
 		      PS2_NO_SLEEP     |
-		      REPORT_W_OFF));
+		      (use_wmode ? REPORT_W_ON : REPORT_W_OFF)));
 }
