Touchpad vs. keyboard (typing) madness in Ubuntu

"A long time ago in a galaxy far, far away ..." there was a touchpad that would register touches/clicks even while the user was typing. Ubuntu has a setting to compensate for this: "System Settings / Mouse & Touchpad / Disable while typing". Unfortunately it does not work (at least in Ubuntu 14.04 / Trusty).

There're a couple of workarounds for this, I'll go over all of them and you can decide which one suits your needs the best.

First the official one. When you enable the "Disable while typing" feature, the settings daemon will start a background process (/usr/bin/syndaemon) which will monitor your keyboard usage and when typing is detected, it disables the touchpad.
The commandline for this daemon looks like this:
syndaemon -i 1.0 -t -K -R

The problem with this is that the "-t" option does not work properly. You can work around this by ...
  1. Unchecking the "Disable while typing" in System Settings
  2. And adding the syndaemon to your startup items. For this you've to launch the Startup Applications program, click on Add, specify an arbitrary Name (eg. "syndaemon") and enter syndaemon -i 1.0 -K -R into the Command field.
Essentially you're doing the same as Ubuntu/Gnome would, only without specifying the "-t" option for syndaemon. For a description of all the other options of syndaemon you can read it's manual page in a terminal (man syndaemon).

This is almost good enough, but not quite. Not for me at least. Because what if you stop for more than a second while typing? Are you always supposed to remove your hands/palms from the touchpad every time you insert a more than 1s pause in your typing? I don't think so.

Let's take a look at the next level of tweaking. There's a commandline utility called synclient (in the xserver-xorg-input-synaptics package) that you can use to interface with the touchpad driver (Synaptics). Without any options (or with the "-l" option) it'll list the driver's current settings.
Eg.
Parameter settings:
    LeftEdge                = 118
    RightEdge               = 2846
    TopEdge                 = 101
    BottomEdge              = 1771
    FingerLow               = 1
    FingerHigh              = 1
    MaxTapTime              = 180
    MaxTapMove              = 154
    MaxDoubleTapTime        = 180
    SingleTapTimeout        = 180
    ClickTime               = 100
    EmulateMidButtonTime    = 0
    EmulateTwoFingerMinZ    = 282
    EmulateTwoFingerMinW    = 7
    VertScrollDelta         = 70
    HorizScrollDelta        = 70
    VertEdgeScroll          = 0
    HorizEdgeScroll         = 0
    CornerCoasting          = 0
    VertTwoFingerScroll     = 1
    HorizTwoFingerScroll    = 1
    MinSpeed                = 1
    MaxSpeed                = 1.75
    AccelFactor             = 0.0570613
    TouchpadOff             = 0
    LockedDrags             = 0
    LockedDragTimeout       = 5000
    RTCornerButton          = 2
    RBCornerButton          = 3
    LTCornerButton          = 0
    LBCornerButton          = 0
    TapButton1              = 1
    TapButton2              = 3
    TapButton3              = 0
    ClickFinger1            = 1
    ClickFinger2            = 3
    ClickFinger3            = 0
    CircularScrolling       = 0
    CircScrollDelta         = 0.1
    CircScrollTrigger       = 0
    CircularPad             = 0
    PalmDetect              = 0
    PalmMinWidth            = 10
    PalmMinZ                = 200
    CoastingSpeed           = 20
    CoastingFriction        = 50
    PressureMotionMinZ      = 30
    PressureMotionMaxZ      = 160
    PressureMotionMinFactor = 1
    PressureMotionMaxFactor = 1
    ResolutionDetect        = 1
    GrabEventDevice         = 1
    TapAndDragGesture       = 1
    AreaLeftEdge            = 0
    AreaRightEdge           = 0
    AreaTopEdge             = 0
    AreaBottomEdge          = 0
    HorizHysteresis         = 17
    VertHysteresis          = 17
    ClickPad                = 1
    RightButtonAreaLeft     = 1482
    RightButtonAreaRight    = 0
    RightButtonAreaTop      = 1535
    RightButtonAreaBottom   = 0
    MiddleButtonAreaLeft    = 0
    MiddleButtonAreaRight   = 0
    MiddleButtonAreaTop     = 0
    MiddleButtonAreaBottom  = 0

Note: the utility naming is a bit confusing here ... the "synclient" program is not not a client application for the "syndaemon". Smile Both are changing Synaptics (touchpad) driver settings, so actually both are "clients".

Syndaemon adjusts the value of the TouchpadOff property to disable the touchpad, you can see this yourself too if you open up a terminal, launch the watch -n1 'synclient -l | fgrep TouchpadOff' command, launch another app (eg. Text Editor) and test how syndaemon changes this property in the background.

You disable/enable the touchpad directly using this client:
synclient TouchPadOff=1 # to disable
synclient TouchPadOff=0 # to enable

Now there's a feature in the driver called palm detection. Some people reported that playing around with the "Palm*" settings of the touchpad driver gave them acceptable results. Some reported that palm detection is faulty too and a patch is needed to make it work properly. I have not tried it myself, but if you feel adventurous, you can persist your synclient settings (so they'll be restored after a reboot) by creating a simple shellscript, adding the necessary commands and creating a startup item in Startup Applications to launch the script upon login to Ubuntu.
Eg. the script could be something like this (in /home/myuser/bin/my-touchpad-settings.sh):
#!/bin/sh

synclient PalmDetect=1
synclient PalmMinWidth=5

And of course give execution permission to the script:
chmod a+rx /home/myuser/bin/my-touchpad-settings.sh

Ok, so far so good. Going on. Smile
Synclient is just a high-level app for talking to the touchpad driver. There's another utility called xinput that you can use to interface with various input device drivers in your Xorg server (simplified: Xorg is the application that draws your GUI -windows, applications, everything- and manages your input devices -keyboard, mouse, etc.-).
To list all input devices, run xinput list. The result will be something like this:
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Bluetooth Mouse M557                      id=12   [slave  pointer  (2)]
⎜   ↳ ETPS/2 Elantech Touchpad                  id=11   [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Power Button                              id=8    [slave  keyboard (3)]
    ↳ Webcam SC-13HDL11624N                     id=9    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=10   [slave  keyboard (3)]

In xinput commands you've to specify the device that you want to address. Either by it's ID number or by name. To get the touchpad's name, you can use a command like this (assuming you've only one touchpad device and it's name contains the "touchpad" word Smile ):
xinput list --name-only | fgrep -i touchpad

Listing all the driver properties for this device is easy:
xinput list-props "$(xinput list --name-only | fgrep -i touchpad)"

If you play around with this, you can find out that synclient's "TouchpadOff" property is the same as the "Synaptics Off" property in your touchpad's xinput listing. Smile

And when you change the On/Off switch in "System Settings / Mouse & Touchpad" for the touchpad, it sets the "Device Enabled" xinput property of the touchpad device. It's almost the same as if you ran the following xinput commands:
xinput set-prop "$(xinput list --name-only | fgrep -i touchpad)" "Device Enabled" 1
# or
xinput set-prop "$(xinput list --name-only | fgrep -i touchpad)" "Device Enabled" 0

Xinput has special commands (shorthands) for the enable/disable operations:
xinput enable "$(xinput list --name-only | fgrep -i touchpad)"
# or
xinput disable "$(xinput list --name-only | fgrep -i touchpad)"

Note that the touchpad driver's "Device Enabled" and "Synaptics Off" properties both affect whether or not the touchpad works! So for the touchpad to work, the former has to be "1", the latter has to be "0". If either of them has a different value, then the touchpad'll be disabled.

There's one more thing to know about messing with the touchpad settings: the System Settings app stores it's settings in it's own database. You can interface with it using the gsettings command.

If you want to disable/enable the touchpad via a commandline command, you're best off using gsettings since it's effects'll persist over a reboot.
To disable the touchpad, use this:
gsettings set org.gnome.settings-daemon.peripherals.touchpad touchpad-enabled false

This will store the "Off" state of the System Settings switch for the touchpad and call xinput's disable action for the touchpad driver.


Finally, the solution that best works for me ... Smile
Most of the time I use an external (bluetooth) mouse, so I do not need the touchpad at all. But in the rare event I've no mouse lying around, I want a trustworthy method that makes sure the touchpad stays "silent" while I'm typing.

To do this, I've created a short shellscript that toggle's the state of the touchpad (i.e. if it's enabled, it disables the touchpad and vice versa).
You can save this script as eg. "toggle_touchpad.sh" anywhere (eg. /home/myuser/bin/toggle_touchpad.sh) and grant read+execution rights on it to all.
#!/bin/sh

state="$(gsettings get org.gnome.settings-daemon.peripherals.touchpad touchpad-enabled)"
if [ -n "$state" ]; then
  [ "$state" = "false" ] && state="true" || state="false"
  gsettings set org.gnome.settings-daemon.peripherals.touchpad touchpad-enabled "$state"
  # sometimes you need to set it twice, because setting it the first time gets reverted a few milliseconds later :-o (that's the reason for the "sleep")
  sleep 0.5
  [ "$(gsettings get org.gnome.settings-daemon.peripherals.touchpad touchpad-enabled)" = "$state" ] || gsettings set org.gnome.settings-daemon.peripherals.touchpad touchpad-enabled "$state"
fi

Some extra logic was necessary (besides two simple gsettings calls), because when disabling the touchpad with gsettings, usually something reverts the first gsettings call a few milliseconds later. Shock I've no idea what's causing this, but I already observed the same in the System Settings app while clicking the On/Off switch. Strange. However checking the state of the setting half a second later and repeating the "set" operation just works. Don't you love when there's a bug workaround in a bug workaround? Smile

If the script is in place, you can test it by running it in a terminal window. If it works, you just have to set up a custom keyboard shortcut to launch the script whenever you've to enable/disable the touchpad. You can do this in "System Settings / Keyboard / Shortcuts / Custom Shortcuts". It's pretty straightforward. I chose the "Super+Space" combination, where Super stands for the Windows key (yes ... my notebook was originally designed for Windows ... life is harsh Smile ). Nothing seems to use this combination, it's quite easy/fast to enter, so a good choice in case I need to use it a lot.

That's all. I hope this little introduction into touchpad driver configuration helps others to tame the touchpad while working in Ubuntu. Smile

Update (2018.03.28): in Ubuntu 16.04 the relevant Gnome setting is in the "org.gnome.desktop.peripherals.touchpad" schema in the "send-events" key. So the script looks like this ...
#!/bin/sh

state="$(gsettings get org.gnome.desktop.peripherals.touchpad send-events)"
if [ -n "$state" ]; then
  case "$state" in
    *disabled*) state="enabled" && break ;;
    *) state="disabled" ;;
  esac
  gsettings set org.gnome.desktop.peripherals.touchpad send-events "$state"
  # sometimes you need to set it twice, because setting it the first time gets reverted a few milliseconds later :-o (that's the reason for the "sleep")
  sleep 0.5
  [ "$(gsettings get org.gnome.desktop.peripherals.touchpad send-events)" = "$state" ] || gsettings set org.gnome.desktop.peripherals.touchpad send-events "$state"
fi

Update (2020.06.15): in Ubuntu 18.04 the latter method still works.
Update (2021.06.28): in Ubuntu 20.04 the latter method still works, however not perfectly. I've found that if you move your fingers wildly across the touchpad (trying "overstimulate it", sometimes the cursor moves even if the touchpad is disabled via this Gnome setting. This is bad if your touchpad gets broken and starts to simulate movements even without you touching it. In this case you'll need a more low-level method to disable the touchpad.