The Logitech MX-500 mouse in Linux

Author: Will Dickson
Version: 0.1.0
Date: 31-Mar-2004
 

You will need

Everything you never wanted to know about XFree86 mouse handling but have been forced to find out

Mouse handling under X is a bit of a mess, and happens in several stages. The first phase happens in the X configuration. This file should be somewhere like /etc/X11/XF86Config or /etc/X11/XF86Config-4 (note non-standard case). It's a big beast, but the important section for our purposes should look something like this:

Section "InputDevice"
  Driver       "mouse"
  Identifier   "Mouse[1]"
  Option       "ButtonNumber" "7"
  Option       "Buttons" "7" 	   
  Option       "Device" "/dev/input/mice"
  Option       "InputFashion" "Mouse"
  Option       "Name" "USB-Mouse;ExplorerPS/2"
  Option       "Protocol" "ExplorerPS/2"
  Option       "ZAxisMapping" "6 7"
EndSection

X usually comes with a mangrove swamp of interconnecting compatibility symlinks; it's a mess. Therefore if you search for this file you may find it apparently in about 47 different places. The chances are good that 37 of these are the same file via different chains of symlinks, and the other 10 are obsolete files which haven't been used for anything sensible since some time last century but are still shipped either to be on the safe side, or because nobody has yet organised a cleanup.

  • The lines Driver, Identifier, Option Name, and Option InputFashion are of no interest to us (you may or may not have all of these, and / or you may have some others which aren't mentioned here). Leave well alone.
  • Option Buttons, and apparently Option ButtonNumber as well (the latter was given to me by SuSE's X config tool, but isn't documented anywhere I've been able to find), tell X how many buttons the mouse has. Set both of these to 7.
  • Option ZAxisMapping comes later.
  • Option Device defines where the mouse plugs into the back of the box. Since our mouse is USB, it should plug into a USB socket, which is hooked by /dev/input/mice as shown. Alternatively you may see some kind of symlink (eg. /dev/mouse) here, but that ought to point to /dev/input/mice.
  • The next most important setting is Option Protocol. This defines how the bits coming down the wire from the mouse hardware are interpreted. There are a number of these, but we need the "PS/2" series of protocols. The most basic version is PS/2, which is for basic three-button mice. Next up is IMPS/2, which is for standard scroll-wheel mice. The one we need is Explorer/PS/2, which is the closest match to our mouse. NB. This protocol got its name from the fact that originally all mice that spoke the protocol, also plugged into the PS/2 mouse socket, but this is a coincidence. The "PS/2" tag on the protocol doesn't imply anything about where the mouse plugs in; that's Option Device's bailiwick.
  • Unfortunately, the ExplorerPS/2 protocol is actually intended for Microsoft IntelliMouseExplorers, ie. a completely different piece of kit. Thus is makes a bit of a hash of our MX-500, but we have to live with it unless some X mage writes a proper protocol handler for us. In particular:
    • The left main button, the scrollwheel button and the right main button come out as X buttons 1, 2, and 3 respectively. This is OK.
    • The scrollwheel comes out as Z-axis movement. (Moving the mouse counts as X-axis and Y-axis movement).
    • So do the two buttons immediately before and behind the scrollwheel. If (like me) you use these as alternative scrollers, you're OK; if you wanted to program them to do something else, you're out of luck.
    • The two thumb buttons come out as X buttons 4 and 5.
    • The task-switcher button (slightly in front of top dead centre on the mouse body) isn't recognised at all, and won't work.

So much for all that. The next stage is the scrollwheel, which works out as follows.

  • As above, the raw scrollwheel events come out as Z-axis movement, which apps don't understand. This is where the Option ZAxisMapping in XF86Config comes in: this option maps the Z-axis movements onto a pair of buttons. We need it to map onto buttons 6 and 7. Thus moving the scrollwheel generates X button press events for buttons 6 and 7.
  • Unfortunately, most apps don't understand buttons 6 and 7 either. However, they mostly do understand buttons 4 and 5: in fact, they assume that these buttons represent the scroll-wheel, and act accordingly.
  • Based on that, the obvious answer is to change the ZAxisMapping to "4 5", right? This does work, but it has the side-effect of inhibiting the two thumb buttons, so that's no good.
  • This is where a tool called xmodmap comes in. It mostly does keyboard mapping, but for no especially obvious reason it also allows you to remap mouse buttons. So, we use this tool to map 6/7 to 4/5 and vice-versa. Now the scroll wheel should work, and the thumb buttons are still enabled, but not doing anything much.

The final step is to make the thumb buttons do something useful. This is where imwheel comes in. Imwheel works by intercepting X mouse-button events. When it recieves such an event, it eats it (usually) and instead sends an arbitrary collection of other events to the window which would've received the mouse event. Specifically you can program it to send X keyboard events; thus you can emulate whatever set of keypresses you like. You can also tailor imwheel's reaction depending on the application it's aimed at.

This step varies a bit depending on what you want the thumb buttons to do. My case is pretty simple: I want the thumb buttons to emulate ^X and ^V (ie. cut and paste - most of the apps I use are cross-platform and ape Windows in this respect). For the interesting details, look at the imwheel man page (comes with imwheel itself) and the sample imwheelrc configuration file (likewise).

The one thing I'd like to do but haven't been able to is to rig the middle button (button 2) to emulate double-click; the only thing it seems to be useful for otherwise is X-style select-and-paste, which I don't use very much. I'd guess that it shouldn't be impossible to extend imwheel to allow this, but at the moment I don't think it does.

How to

Given all that theory, we can now write down a step-by-step guide, as follows.

  1. Obtain imwheel, and if necessary compile and install it (see above).
  2. Login to the console (ie. text mode) as root.
  3. Locate your XF86Config, probably in /etc/X11/. Copy it to somewhere safe, in case you make a mess of the original.
  4. Edit it. Encourage the mouse section to look something like the example above. The Option Protocol, Option Buttons, Option ButtonNumber and Option ZAxisMapping lines should be exactly as given, the others may vary a bit and should probably be left alone.
  5. Start X and verify that you still have a functioning three-button mouse.
  6. Logout from X, logout from root, log back in as yourself. Start X. Bring up a console (xterm) window, and a whichever apps you especially care about.
  7. In the console window, type xmodmap -pp. It will list the current X mouse-button mappings. They should be one for one - 1 -> 1, 2 -> 2 etc. If not, you need to find the erring mapping. It may be in the file ~/.xinitrc.
  8. In the console window, type xmodmap -e "pointer = 1 2 3 6 7 4 5". Then xmodmap -pp again. Verify that the 4/5 and 6/7 pairs have swapped over.
  9. Try out the scroll wheel in your selection of apps. It ought to work. If not you're going to have to hack something together with imwheel, but most modern apps know about 4 / 5 now.
  10. Bring up a second console window, su root and cd /etc/imwheel. Take a safety copy of the file imwheelrc located there, as you did for XF86Config.
  11. Edit it (as root). You can either use a text-mode editor as you did for XF86Config, or you may be able to use a graphical editor. If the editor won't start and spews a load of gobbledegook about MIT and / or magic cookies, try typing xhost +localhost and trying again.
  12. What you do next depends on what you want the thumb buttons to do. Mine is below (in it's entirety). NOTE: imwheel thinks the thumb buttons are the ones it calls "left" and "right", NOT "thumb1" and "thumb2". Hello again, ExplorerPS/2 protocol.
  13. When you think you've set your imwheelrc correctly, type the following into the first console window (the one running as you, not root): imwheel -p -b "0067". It'll print some vague threats about "there may be one of these already running, in which case it'll all go horribly wrong" which you can ignore (if you're worried, do ps aux | grep imwheel; there should only be one of them). If a prints a real error message, you've probably bent imwheelrc somehow: go back and recheck, then killall imwheel and retry.
  14. You may find that this works in some of your apps, but not others; GTK-based apps seem to start trouble here. If you get this, try imwheel -p -f -b "0067" instead.
  15. When you've got it working, you need to transfer the required commands - that is, the xmodmap -e "pointer = <whatever>" and imwheel <whatever> - to the appropriate file so that they'll start automatically when you go into X:
    • If you want to normally login to a console and then start X manually (as you've been doing during this kerfuffle) then it's easy: simply stash the required commands in a file called ~/.xinitrc. You may well already have one of these, possibly filled with gibberish, courtesy of your distro; if so, just slip the extra commands in at the top.
    • If you want to go back to graphical logins, .xinitrc may not work. If not, I'm not sure of the replacement. IIRC it depends on exactly what program you use to do the graphical login - ISTR there's one for KDE, another for GNOME, and maybe even a third one for other window managers if you're that way inclined.

Finally, as promised, my imwheelrc:

# IMWheel Configuration file ($HOME/.imwheelrc or /etc/imwheelrc)
# (GPL)Jon Atkins 
# Please read the README and/or imwheel(1) manpage for info
# and this is best operated on using vim (as I said: It's crunchy)

#
# This is only for demonstration of the priority command...
# See the other global Exclude command below for the one you want to use!
# If this is activated it will only apps that have a lower priority
# priority is based first on the priority command, then the position in this
# file - the higher the line is in a file the higher in a priority class it is
# thus for a default priority you can see that the position in the file is
# important, but the priority command CAN appear anywahere in a window's list
# of translations, and the priority will be assigned to all translations below
# it until either a new window is defined or the priority is set again.
#
#".*"
#@Priority=-1000 #the default priority is zero, higher numbers take precedence
#@Exclude
#@Repeat

# want it to type something?
# this would type "Rofl" and press Return in any window
".*"
#None,Left,Shift_L|R|-R|-Shift_L|O|-O|F|-F|L|-L|Return
#None,Right,Shift_L|S|-S|-Shift_L|P|-P|A|-A|M|-M|Return
None,Left,Control_L|V
None,Right,Control_L|X
#None,Button2,Shift_L|S|-S|-Shift_L|P|-P|A|-A|M|-M
#This doesn't work. Arse.



# This one rule can send button events, as if you used ZAxisMapping "4 5"
# Make sure your XF86Config allows for the max buttons needed...
# otherwise the events will NOT even be generated...
#".*"
#, Up, Button4
#, Down, Button5
#, Left, Button6
#, Right, Button7
#, Thumb1, Button6
#, Thumb2, Button7

# WRD: app-specific hacks snipped. See ./imwheelrc.wrdsave for original version.

"WRD" is me, BTW.

 
Authored in CXD using Checkpoint Information Engineering Workbench   Copyright © 2004 Caversham Computer Services Ltd.