Saturday 12 December 2015

Horizontal scroll on FreeBSD guest

Setting up horizontal scroll on a FreeBSD Guest in VirtualBox


One of the annoyance I came across on FreeBSD as a VirtualBox guest is the mouse. Although not a heavy mouse user, I rely very much on scrolling, both horizontal and vertical. Unfortunately scrolling doesn't work out-of-the-box. The relevant section in the handbook doesn't specify clearly how things work (or outdated?).

So even with the guest additions installed often than not one or more of these happen:
  • the mouse cursor doesn't move
  • none of the mouse buttons work - no mouse click detected
  • scrolling doesn't work - no button 4, 5, 6 or 7 (more on that later)

If you share the same fate as I do, the instructions below will hopefully save you some hours of trial and error and hair pulling moments.

NOTE: The instructions are tested for a Linux host + FreeBSD guest environment only. As of writing, I can't get the horizontal scroll working on a Windows host. Some claim that Windows (or the Synaptics driver) doesn't implement horizontal scroll properly. Comments are welcome.

Quick instructions for the impatient

 

1. Test your moused setting

In a virtual terminal, log in as root and type:

# moused -df -p /dev/psm0 -t auto -z 4 5 6 7

Now moused is in debug mode. As you move the mouse you'll see lots of messages spitted out by moused.

moused: mstate[2]->count:6
moused: button 3  count 0


Note the lines with mstate[n] and button m. It should reflect the buttons you press. For a mouse with scroll wheel the mappings are:

1 - left button
2 - middle button
3 - right button
4 - scroll up
5 - scroll down
6 - scroll left
7 - scroll right

If that's what you see, congrats. Now hit control-c to quit moused and move on.


2. Enable moused in /etc/rc.conf

Add these lines to /etc/rc.conf:
moused_enable="YES"
moused_flags="-z 4 5 6 7"
moused_type="auto"
moused_port="/dev/psm0"

Now start moused:
/etc/rc.d/moused start


3. Set up InputClass in xorg.conf

Copy and paste the following lines to /usr/local/etc/X11/xorg.conf.d/10-vboxmouse.conf.

NOTE: The below setting is for FreeBSD as VirtualBox guest only. If you're running FreeBSD on Thinkpad models with the UltraNav (TrackPoint + Touchpad) device, I'll write another article on that.

Section "InputClass"
        Identifier "sysmouse0"
        MatchDevicePath "/dev/sysmouse"
        Option "Buttons" "7"
        Option "EmulateWheel" "true"
        Option "EmulateWheelButton" "2"
        Option "YAxisMapping" "4 5"
        Option "XAxisMapping" "6 7"
EndSection


Section "InputClass"
        Identifier "vboxguest0"
        MatchDevicePath "/dev/vboxguest"
        Driver "vboxmouse"
        Option "Protocol" "auto"
EndSection



4. Test it in X

Fire up X the usual way. For me it's:
> startx &

Open a terminal and type
> xev

Move the cursor inside the Event Tester window and try some clicks and scrolling. You should see the mouse button events get printed in the terminal. Scrolling should report button 4 and 5. And here's the fun stuff. Hold down the middle button and move the mouse. You should see button 4 and 5 reported with scrolling up and down, while button 6 and 7 scrolling left and right.

If you don't like that just comment out the EmulateWheel and EmulateWheelButton lines in 10-vboxmouse.conf.

That's it. Your pointing device should work in the virtual terminals as well as X. Any mice plugged in after X fired up should work too.


The long explanation

 

Why not turning off AutoAddDevices? 

Many of the solutions on the Internet suggest turning off AutoAddDevices and adding an InputDevice section in /usr/local/etc/X11/xorg.conf. That might work for you but I think it's not the perfect solution. It has a few downsides:
  1. It requires disabling moused. No more copy and paste in virtual terminals.
  2. Any mice plugged in after X fired up won't work unless you use InputClass instead of hardcoding InputDevice. But the behavior of each pointing device is not consistent.

The perfect solution - moused

Moused acts as a hub connecting all the physical pointing devices and talks to X as one logical device (dough). So you get a consistent behavior across them. Copy & paste works in virtual terminals, as well as vert and horiz scrolling.

So in the case of VirtualBox, all physical pointing devices are nicely emulated by /dev/psm0. Moused binds to /dev/psm0 (the emulated device that FreeBSD thinks is the physical device) and the combined signal goes to /dev/sysmouse. X then reads the signal from /dev/sysmouse.

Any newly plugged-in devices are automagically picked up by moused so everything just works, both in X and the virtual terminals. Nicely, isn't it?


What about /dev/vboxguest?

In order for the pointing devices to work properly in VirtualBox, the X server needs to see one more logical device, namely /dev/vboxguest.

For reasons not understood (these are found out by reverse engineering), VirtualBox emulates cursor movements and all mouse button events san button 2 to /dev/sysmouse, while /dev/vboxguest reports button 2 events to the guest. Mouse Integration with the host is also implemented via /dev/vboxguest.


How scrolling works?

There is no such thing as "scrolling signal". Instead they are represented by mouse button events just like clicking the left or right buttons. Scrolling up usually maps to button 4 event, down 5, left 6 and right 7. (Even events 8 - 11 are possible with the UltraNav device since there are basically 2 physical devices).


More explanations on the settings

The important setting with moused is "-z 4 5 6 7". I discourage the use of -V and -H cuz as soon as the middle button is clicked in X, button event > 4 stops working. And since the -z option has already taken care of the scrolling signals, why bothered with -V and -H?

If horizontal scroll still doesn't work for you, before bashing your mouse you may try to replace the XAxisMapping and YAxisMapping lines with

Option ZAxisMapping "4 5 6 7"


Or if you're like me, prefer "natural scrolling", i.e. scroll the page itself instead of the scroll bars:

Option ZAxisMapping "5 4 7 6"


Enjoy scrolling. :)

No comments:

Post a Comment