26. June 2008

How to use synaptics touchpad when screen is rotated with xrandr –orientation?

Do you use laptop rotated with xrandr --orientation? Then you may noticed that touchpad do not work rigth.
"Running 'xrandr -o right' in a terminal will rotate the screen so that it's portrait-format and a lot easier when reading long articles. The slight problem though is that using the touchpad with the laptop turned 90 degrees is next to impossible, as ones brain can't work out which way to move ones fingers in order to get the desired result". Look eee user forum

Solution (Ubuntu related)

First you must know something. The whole point is that we change the synaptics touchpad driver. It's not big deal, we change one file (actually two, keep on reading). Additional we must put one line in /etc/X11/xorg.conf (I suppose you have this Section already in your xorg.conf)
Section "InputDevice"
        Identifier      "Synaptics Touchpad"
        Driver          "synaptics"
        Option          "SendCoreEvents"        "true"
        Option          "Device"                "/dev/psaux"
        Option          "Protocol"              "auto-dev"
        Option          "SHMConfig"             "true"
EndSection

Reboot X. Now we can change synaptics settings on the fly with synclient. ”It’s a bit of an annoying irony that you have to manually edit the xorg.conf file to start a program that lets you avoid manually editing the xorg.conf file.” (Sayed about SHMConfig and synclient.)
Driver file is synaptics_drv.so and is located /usr/lib/xorg/modules/input/. Back-up your existing driver.

Ready compiled binaries

This is new driver for Hardy (Ubuntu 8.04) and its corresponding synclient. I got couple of mails that precompiled bianries do not work. This is updated 26. June 2008. Let me know if you test these.
This is compiled with my Asus EeePC with xubuntu Hardy, gcc 4.2.3-1ubuntu6. I really do not know how I compile it so that you can use it.
synaptics_drv.so
synclient

Compiling from sources

You need build-essentials etc. Additional you need some dependery packages. In ubuntu just use
sudo apt-get build-dep xserver-xorg-input-synaptics 

Modified sources

Here you can download modified sources. Just make it and you will get synaptics_drv.so and synclient.
Hardy: modified sources

Mod sources by yourself

Get official sources, example:
apt-get source xserver-xorg-input-synaptics 
Then test that everything is alright
make
It should make synclient and synaptics_drv_so.

Download my patch file:
axis_patch
(tested on xserver-xorg-input-synaptics 0.14.6 and 0.14.7)
Put patch-file on the same directory and command
patch < axis_patch
Output:
patching file eventcomm.c
patching file synaptics.c
patching file synaptics.h
patching file synclient.c
means everything is ok, just
make
(In gutsy (synaptics sources 0.14.6) it says:
patching file eventcomm.c
Hunk #1 succeeded at 147 (offset -4 lines)
Hunk #2 succeeded at 229 (offset -4 lines)
patching file synaptics.c
Hunk #1 succeeded at 362 with fuzz (offset -11 lines)
patching file synaptics.h
patching file synclient.c

This means all is ok and you can make it.)

By hands

If patch do not work (maybe you use another version of sources). Or you want to now what happens, I list and explain all changes.
File Code segment Row number (about) Add
synaptics.h typedef struct _SynapticsSHM 36 int xrandr;
synaptics.c static InputInfoPtr SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags) 376 (function:295) pars->xrandr = xf86SetIntOption(opts, "Xrandr", 0);
synclient.c static struct Parameter params[] = { 52 DEFINE_PAR("Xrandr", xrandr, PT_INT, 0, 3),
eventcomm.c static Bool EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw, 154
SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
SynapticsSHM *para = priv->synpara;
eventcomm.c static Bool EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw, 229 change
   case EV_ABS:
      switch (ev.code) {
      case ABS_X:
         hw->x = ev.value;
         break;
      case ABS_Y:
         hw->y = ev.value;
         break;
to this:
   case EV_ABS:
      switch (ev.code) {
      case ABS_X:
         if (para->xrandr==0)
	   	   hw->x = ev.value;
         if (para->xrandr==1)
	   	   hw->y = -ev.value;
         if (para->xrandr==2)
	   	   hw->y = ev.value;
         if (para->xrandr==3)
	   	   hw->x = -ev.value;
         break;
      case ABS_Y:
         if (para->xrandr==0)
	   	   hw->y = ev.value;
         if (para->xrandr==1)
	   	   hw->x = ev.value;
   		if (para->xrandr==2)
	   	   hw->x = -ev.value;
   		if (para->xrandr==3)
	   	   hw->y = -ev.value;
	   	break;

As you see, this hack is very small.
  1. synaptics.h : add one field to struct
  2. synaptics.c : initialize value
  3. synclient.c : make parameter which is between 0 and 3
  4. eventcomm.c : get the parameter value
  5. eventcomm.c : change the way how x and y is returned

Installing

There are no ready 'make install'. You just copy one file.
You have synaptics_drv.so and synclient files. Backup your old driver:
cp /usr/lib/xorg/modules/input/ ~/original_synaptics_drv.so
Shutdown X. If you have session manager (like kdm/gdm) you must kill them first.
If X is running and you change driver, system freezes. (But the new driver is there.)
Copy modified version to in use.
sudo cp synaptics_drv.so /usr/lib/xorg/modules/input/
startx

Usage

If you wish, you can drop synclient to /usr/bin (back-up existing)
I suppose now the synclient is your home directory

Commandline syntax is:
~/synclient Xrandr=1
This will change axis like screen is rotated to rigth.

I think easiest way is to make scripts that orient the screen and change axis in the same time. Then you can make shortcuts and what ever you want.
At least, from this list you can check synclient Xrandr parameter meanings.

~/synclient Xrandr=0 
xrandr --orientation normal
~/synclient Xrandr=1 
xrandr --orientation right
~/synclient Xrandr=2
xrandr --orientation left
~/synclient Xrandr=3
xrandr --orientation inverted

I use myself scripts that change wallpaper too. If you have some tile-pattern wallpaper is not affected when screen rotates, but if there are fixed size image, then it is scaled ugly. I think it's too window-manager-related, so I do not make this big point, but in xfce4: Set ~/own_background.jpg to your background. (you need portrait.jpg and landscape.jpg)
Add this kind of rows to scripts:
#left or right
cp ~/portrait.jpg ~/own_background.jpg
xfdesktop --reload
#normal or inverted
cp ~/landscape.jpg ~/own_background.jpg
xfdesktop --reload

Problems?

Even something is wrong with driver, X will start and mouse pointer moves. But axis do not swap, tapping/scrolling etc not work.
First check your Xorg.log
cat /var/log/Xorg.0.log | grep -i "synaptics"
It says very clear is driver loaded or not. If it is not loaded, the driver is compiled wrong to your system.

Note

I do not know what happens tap-clicking, vertical-scrolling, horizontal-scrolling, circular scrolling, two-fingers-tapping etc with this driver and/or when axis is swapped. I'm happy if you could tell me do these features works or not.

!NEW! - Scrolling

You can tweak scrolling with some variables.
synclient LeftEdge = 1872
synclient RightEdge = 5072
synclient TopEdge = 1712
synclient BottomEdge = 4144
These are (my computers) default values. I'm waiting if somebody manage what are good values and send them to me.

Working computers and systems

Here I collect the list of computers/systems which work. Drop me a mail if you test some.

Do you want help me?

Edge values. I do not yet know
-do we need different edge values in every orientation
-do we need negative edge values in some orientation

All testing and comments are very usefull.
Do you want make some graphical-screen-orienter-application? (I'm planning some, but if somebody wants to do it, it will be great.)

Feedback

aapo(dot)rantalainen(at)gmail(dot)com
26. June 2008