Wednesday, September 02, 2009

Disable touchpad when USB Mouse connected on Ubuntu (Jaunty)

Do you have problem with Synaptics touchpad Palm detection? Do you accidentally touch the touchpad while typing? On Windows Vista, there is an option to disable touchpad when USB Mouse connected, but how to do that on Ubuntu? Here's how I 'properly' did it on my Ubuntu 9.04 (Jaunty).
  • Create a Dbus signal handler script using Python. Here's the script
#!/usr/bin/python

global DeviceName, AddAction, RemoveAction, bus, hal_manager

#DeviceName = 'usb_device_15ca_c3_noserial_if0_logicaldev_input'
DevicePattern = r'usb_device.*_input'
DeviceCap = 'input.mouse'
AddAction = '/usr/bin/gconftool --set --type=bool /desktop/gnome/peripherals/mouse/touchpad_enabled false'
RemoveAction = '/usr/bin/gconftool --set --type=bool /desktop/gnome/peripherals/mouse/touchpad_enabled true'

import dbus # needed to do anything
import dbus.decorators # needed to receive messages
import dbus.glib # needed to receive messages
import gobject # needed to loop & monitor
import os # needed to
import re, time

DeviceRe = re.compile(DevicePattern, re.IGNORECASE | re.DOTALL)

#@dbus.decorators.explicitly_pass_message
def add_device(*args, **keywords):
Path = args[0].split('/')
device_obj = bus.get_object('org.freedesktop.Hal', args[0])
device = dbus.Interface(device_obj, dbus_interface = "org.freedesktop.Hal.Device")

cap = device.QueryCapability(DeviceCap)

if cap and DeviceRe.match(Path[-1]) :
os.system(AddAction)

#@dbus.decorators.explicitly_pass_message
def remove_device(*args, **keywords):
Path = args[0].split('/')
try :
device_obj = bus.get_object('org.freedesktop.Hal', args[0])
device = dbus.Interface(device_obj, dbus_interface = "org.freedesktop.Hal.Device")
cap = device.QueryCapability(DeviceCap)
except :
# assume true, since device might be already removed
cap = True

if cap and DeviceRe.match(Path[-1]) : # Device found
os.system(RemoveAction)

bus = dbus.SystemBus() # connect to system bus
hal_manager_obj = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
hal_manager = dbus.Interface(hal_manager_obj, 'org.freedesktop.Hal.Manager')

# Add listeners for all devices being added or removed
bus.add_signal_receiver(add_device, 'DeviceAdded', 'org.freedesktop.Hal.Manager',
'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
bus.add_signal_receiver(remove_device, 'DeviceRemoved', 'org.freedesktop.Hal.Manager',
'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')

# Run remove action once to enable touchpad
os.system(RemoveAction)
time.sleep(1)

# Find mouse first
udis = hal_manager.FindDeviceByCapability('input.mouse')
for udi in udis :
Path = udi.split('/')
if DeviceRe.match(Path[-1]) : # Check if this is our prefer mouse
os.system(AddAction)
break # no need to keep looking

# monitor
loop = gobject.MainLoop()
loop.run()
  • If you wonder how I got the HAL path of USB mouse, try connecting your mouse and do "lshal", look for "Mouse" and see how your path looks like. Change the path properly if the default one is not match.
  • Add the script to run when log-in by going to System->Start up Applications
  • Log-out and re-Log-in again. That's it.
Another way to do this is to handle it in UDEV. However, I found that GNOME will always try to enable it back that way. Besides, UDEV is run by root, but touchpad setting is per-user. Disabling Touchpad permanently (in Mouse setting) and use synclient to control touchpad is another way to go.

3 comments:

fahadysf said...

Your post is made of pure awesomeness. This is the first thing that worked for me. I have been banging my head with the udev based approaches but none of them have worked for me.

somsak_sr said...

I don't sure if this is still working in Lucid. It stopped working in Karmic since Karmic tried to control the the touchpad by itself (touchpad got enabled shortly after disabled).

fahadysf said...

Oh I forgot to mention. You are right in that. After Karmic you can no longer use gconftool to enable or disable touchpad.

What I did was use the synclient commands to enable or disable touchpad instead of gconf.

AddAction = 'synclient TouchpadOff=1'
RemoveAction = 'synclient TouchpadOff=0'

This got the script working.