11. November 2009

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
ubuntu forum


Click if you use hardy or even older Ubuntu.

News

11. November 2009
This is for Ubuntu 9.04

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).
In Ubuntu 8.10 and later we can't use xorg.conf anymore (because of bulletproofX), so the new way to enable SHMConfig is:
Make or edit file:
/etc/hal/fdi/policy/shmconfig.fdi
<?xml version="1.0" encoding="ISO-8859-1"?>
<deviceinfo version="0.2">
 <device>
  <match key="input.x11_driver" string="synaptics">
   <merge key="input.x11_options.SHMConfig" type="string">True</merge>
  </match>
 </device>
</deviceinfo>
Cite: https://help.ubuntu.com/community/SynapticsTouchpad#shmconfig

Reboot X. Now we can change synaptics settings on the fly with synclient.


Driver file is synaptics_drv.so and is located /usr/lib/xorg/modules/input/. Back-up your existing driver.

Ready compiled binaries

No ready compiled binaries. It is very easy with ubuntu to compile it yourself. Otherwise take contact to original driver author/ubuntu/debian-packager and ask them to add this patch on official release.

Compiling from sources

You need build-essentials to compile (almost) anything.
sudo apt-get install build-essential
Additional you need some dependery packages. In ubuntu just use
sudo apt-get build-dep xserver-xorg-input-synaptics 
And last get the sources of driver. NOTE: The last directory might have different name, but it is only directory, so you will find it.
mkdir some_directory
cd some_directory
apt-get source xserver-xorg-input-synaptics 
cd xfree86-driver-synaptics-0.14.7~git20070706


Then download my patch file and do patching.
It will affects these files:
patching file include/synaptics.h
patching file src/eventcomm.c
patching file src/synaptics.c
patching file tools/synclient.c

If you are interested in what there are in patch file, you can read it below.
wget http://cc.oulu.fi/~rantalai/synaptics/synaptics_xrandr.diff
patch -p1 < synaptics_xrandr.diff
And then with traditionally:
./configure
make

Installing

There are no ready 'make install'. You just copy 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 src/.libs/synaptics_drv.so /usr/lib/xorg/modules/input/
startx

Each driver needs it's corresponding synclient. It is in tools/synclient.
If you wish, you can drop it to /usr/bin (back-up existing)

Usage

If you do not want install synclient (cp it to /usr/bin), you can use it ./synclient.
If you use gsynaptics or any other program that launch synclient on startup you must install synclient. Running the original, unpatched version of synclient with the patched driver will make your touchpad behave strangely
Commandline syntax is: (This will change axis like screen is rotated to rigth.)
synclient Xrandr=1

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 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.


Mod sources by yourself

There will be time when my patch is too old to work, upstream is not interested in and I am too busy. So I made list what I have changed in synaptics-driver, you can figure how to use it. (You can ask me first)

Get official sources, example:
apt-get source xserver-xorg-input-synaptics 

List and explaining all changes.
File (in src/) Code segment Row number (about) Add
synaptics.c static InputInfoPtr SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags) 387 (function:304) pars->xrandr = xf86SetIntOption(opts, "Xrandr", 0);
eventcomm.c static Bool EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw, 195
SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
SynapticsSHM *para = priv->synpara;
eventcomm.c static Bool EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw, 275 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;
../tools/synclient.c static struct Parameter params[] = { 63 DEFINE_PAR("Xrandr", xrandr, PT_INT, 0, 3),
../include/synaptics.h typedef struct _SynapticsSHM 64 int xrandr;

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

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.

Scrolling

Scrolling with swapped axis do not work correct. Somebody pointed me that we should not use hw->x = -ev.value; but hw->x = MAX_VALUE-ev.value;
But I do not know what is that MAX_VALUE. So if you figure it out, let me know it.

Instead 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?

Feedback

aapo(dot)rantalainen(at)gmail(dot)com

This text can be used in any way (public domain).