#96536 Should support "wheel" buttons on synaptics touchpad

Package:
gpm
Source:
gpm
Description:
General Purpose Mouse interface
Submitter:
Tom Lear
Date:
2005-07-18 03:29:10 UTC
Severity:
wishlist
#96536#5
Date:
2001-05-06 16:41:19 UTC
From:
To:
Here's a patch to add support for "wheel" button on the synaptics
touchpad.  It also adds the ability to remap buttons.
							- Tom

diff -c gpm-1.19.3.orig/ChangeLog gpm-1.19.3/ChangeLog
*** gpm-1.19.3.orig/ChangeLog	Tue Jul 18 05:22:18 2000
--- gpm-1.19.3/ChangeLog	Sun May  6 09:26:27 2001
***************
*** 1,3 ****
--- 1,9 ----
+ 2001-05-06  Tom Lear  <tom@trap.mtview.ca.us>
+
+ 	* Added support for "wheel" buttons (and the gesture
+ 	  interpretation that support requires - grrrr)
+ 	* Added support for remapping buttons to gpm-syn.conf
+
  2000-07-18  Alessandro Rubini  <rubini@morgana.systemy.it>

  	* doc/doc.gpm (Command Line): removed "-q" documentation.
diff -c gpm-1.19.3.orig/gpm-syn.conf gpm-1.19.3/gpm-syn.conf
*** gpm-1.19.3.orig/gpm-syn.conf	Mon Sep 13 15:00:00 1999
--- gpm-1.19.3/gpm-syn.conf	Sun May  6 09:26:51 2001
***************
*** 25,27 ****
--- 25,33 ----
  [upper_right_action]         2 (middle)
  [lower_left_action]          0 (none)
  [lower_right_action]         3 (right)
+ /* button mapping */
+ [tap_button_mapping]         1 (left)
+ [left_button_mapping]        1 (left)
+ [right_button_mapping]       3 (right)
+ /* wmode is required to support "wheel" buttons */
+ [wmode]                      0
diff -c gpm-1.19.3.orig/synaptics.c gpm-1.19.3/synaptics.c
*** gpm-1.19.3.orig/synaptics.c	Mon Jan 17 13:34:00 2000
--- gpm-1.19.3/synaptics.c	Sun May  6 08:56:48 2001
***************
*** 180,185 ****
--- 180,199 ----


  /*
+ ** Default button mappings
+ */
+ static int button_mapping[] = {
+   1,	/* tap   defaults to left  click */
+   1,	/* left  defaults to left  click */
+   3,	/* right defaults to right click */
+ };
+
+ /* wmode parameters */
+ static int wmode = 0;
+ static int wheel_delay = 10;
+ static int recent_gesture = 0;
+
+ /*
  ** These types are used to read the configuration data from the config file.
  */
  typedef enum {
***************
*** 229,234 ****
--- 243,254 ----
    { "lower_left_action",          Corner_Param,  &corner_actions [1]         },
    { "upper_right_action",         Corner_Param,  &corner_actions [2]         },
    { "lower_right_action",         Corner_Param,  &corner_actions [3]         },
+   /* button mapping */
+   { "tap_button_mapping",         Integer_Param, &button_mapping[0]          },
+   { "left_button_mapping",        Integer_Param, &button_mapping[1]          },
+   { "right_button_mapping",       Integer_Param, &button_mapping[2]          },
+   /* should we use wmode? */
+   { "wmode",                      Integer_Param, &wmode                      },
    /* end of list */
    { NULL,                         Flag_Param,    NULL                        },
  };
***************
*** 271,276 ****
--- 291,298 ----
    int x;
    int y;
    int pressure;
+   int up;
+   int down;
  } report_type;


***************
*** 380,385 ****
--- 402,412 ----
  static location_type toss_speed;
  static location_type touch_loc;

+ /* remember the state of wheel buttons to control repeating */
+ static int last_up        = 0;
+ static int last_down      = 0;
+ static int cur_up_delay   = 0;
+ static int cur_down_delay = 0;

  /****************************************************************************
  **
***************
*** 508,513 ****
--- 535,560 ----


  /*
+ ** map_buttons
+ **
+ ** Remap buttons according to config file
+ */
+ static void map_buttons (Gpm_Event *state,
+ 			 int button) {
+   switch(button_mapping[button]) {
+     case 1:
+       state->buttons |= GPM_B_LEFT;
+       break;
+     case 2:
+       state->buttons |= GPM_B_MIDDLE;
+       break;
+     case 3:
+       state->buttons |= GPM_B_RIGHT;
+       break;
+   }
+ }
+
+ /*
  ** syn_process_data
  **
  ** Process the touchpad report.
***************
*** 531,541 ****
--- 578,625 ----
    state->buttons = 0;
    state->dx      = 0;
    state->dy      = 0;
+   state->wdx     = 0;
+   state->wdy     = 0;

  #if DEBUG_REPORTS
    dump_report_data (report, edges);
  #endif

+   /* in wmode we need to do our own gestures */
+   if(wmode) {
+     if(last_gesture) report.gesture=last_gesture-1;
+     if(last_gesture && report.finger) report.gesture=1;
+     if(recent_gesture && recent_gesture<12) report.gesture=1;
+     if(recent_gesture) recent_gesture--;
+     if(!report.finger && last_finger) {
+       if(last_gesture) {
+         if(packet_num < 16) recent_gesture=13;
+         report.gesture=0;
+       } else {
+         if(packet_num > 2 && packet_num < 16) report.gesture=8;
+       }
+     }
+   }
+
+   /* wheel proccessing - repeat faster the longer the button is down */
+   if(last_up) last_up--;
+   if(!report.up) {
+     cur_up_delay=wheel_delay;
+     last_up=0;
+   }
+   if(last_up==1) cur_up_delay--;
+   if(report.up && !last_up) last_up=report.up;
+   if(report.up != last_up) report.up=0;
+
+   if(last_down) last_down--;
+   if(!report.down) {
+     cur_down_delay=wheel_delay;
+     last_down=0;
+   }
+   if(last_down==1) cur_down_delay--;
+   if(report.down && !last_down) last_down=report.down;
+   if(report.down != last_down) report.down=0;
+
    /* We only need concern ourselves when a finger is on the pad */
    if (report.finger) {
      if (tossing_enabled) {
***************
*** 654,659 ****
--- 738,763 ----
    /* check for buttons if we didn't just complete a toss */
    if (!tossing && !was_tossing) {
      /*
+     ** set buttons according to mapping (though they may be overwritten
+     ** in the next segment of code)
+     */
+     if (taps_enabled &&
+ 	  (report.gesture && !is_corner (last_edges)))
+ 	map_buttons(state, 0);
+
+     if (report.left)
+ 	map_buttons(state, 1);
+
+     if (report.right)
+ 	map_buttons(state, 2);
+
+     if (report.up)
+ 	state->wdy = 1;
+
+     if (report.down)
+ 	state->wdy = -1;
+
+     /*
      ** If there is no gesture then there are no buttons.
      ** If there is a continuing gesture then report the same buttons.
      ** Otherwise compute new buttons.
***************
*** 663,675 ****
      } else if (last_gesture) {
        state->buttons = last_buttons;
      } else {
-       if (report.left || (taps_enabled &&
- 			  (report.gesture && !is_corner (last_edges))))
- 	state->buttons |= GPM_B_LEFT;
-
-       if (report.right)
-         state->buttons |= GPM_B_RIGHT;
-
        process_corner_taps (state, report);
      }
    }
--- 767,772 ----
***************
*** 1118,1128 ****
--- 1215,1267 ----
  }

  /* Translate the reported data into a record for processing */
+ static void syn_translate_ps2w_report (unsigned char *data,
+ 				       report_type *report)
+ {
+   int i;
+
+ //printf("mouse event: %02X %02X %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3],data[4],data[5]);
+   if (((data [0] & 0xc8) == 0x80) &&
+       ((data [3] & 0xc8) == 0xc0)) {
+     report->gesture  = 0;
+     report->finger   = data [2] > 23;
+     report->left     = check_bits (data [0], 0x01);
+     report->middle   = 0;
+     report->right    = check_bits (data [0], 0x02);
+     report->up       = cur_up_delay * check_bits(data[0] ^ data[3], 0x01);
+     report->down     = cur_down_delay * check_bits(data[0] ^ data[3], 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];
+   } 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;
+     report->up       = 0;
+     report->down     = 0;
+   }
+ }
+
+ /* Translate the reported data into a record for processing */
  static void syn_translate_ps2_report (unsigned char *data,
  				      report_type *report)
  {
    int i;

+   report->up         = 0;
+   report->down       = 0;
    if (((data [0] & 0xc8) == 0x80) &&
        ((data [3] & 0xc8) == 0xc0) &&
        ((data [0] & 0x0f) == (data [3] & 0x0f))) {
***************
*** 1200,1206 ****
  {
    report_type   report;

!   syn_translate_ps2_report (data, &report);
    syn_process_data (state, report);
  }
--- 1339,1348 ----
  {
    report_type   report;

!   if(wmode)
!     syn_translate_ps2w_report (data, &report);
!   else
!     syn_translate_ps2_report (data, &report);
    syn_process_data (state, report);
  }

***************
*** 1254,1258 ****
    ps2_set_mode2 (fd, (ABSOLUTE_MODE    |
  		      HIGH_REPORT_RATE |
  		      PS2_NO_SLEEP     |
! 		      REPORT_W_OFF));
  }
--- 1396,1401 ----
    ps2_set_mode2 (fd, (ABSOLUTE_MODE    |
  		      HIGH_REPORT_RATE |
  		      PS2_NO_SLEEP     |
! 		      (wmode?REPORT_W_ON:REPORT_W_OFF)));
!   if(wmode) cur_up_delay=cur_down_delay=wheel_delay;
  }