13

I use a 10-button mouse (Logitech M705). Under X11, I was able to configure one of the extra buttons to behave as a second middle-click by modifying files in etc/X11/xorg.conf.d.

Under Wayland, this no longer works. My research shows that I need to do something with libinput. I thought this would be a common problem but can't find an answer anywhere.

Can someone explain how to remap mouse buttons or explain why it can't be done?

1
  • I'm using Wayland for a while and I couldn't find how to remap buttons so far. – paulodiovani May 24 '17 at 14:21
10

Remapping buttons if you're running Wayland could be done like this:

  1. Run xev | grep button to log mouse click events and get the number of the event by f.e clicking in the window. In my case, middle button is:

    state 0x10, button 2, same_screen YES
    

    and I want to map it on:

    state 0x10, button 13, same_screen YES
    
  2. Then run xinput --list and find your pointer device, mine is:

    Logitech Performance MX  id=9  [slave pointer  (2)]
    
  3. xinput get-button-map 9 returns:

    1 2 3 4 ... 20
    
  4. xinput set-button-map:

    $ xinput set-button-map 9  1 13 3 4 .. 12 2 14 .. 20
    

NOTE: replace the number 9 for the number returned by id=

And if that key's behavior is defined, your event is mapped. If it is not, that's a little bit different issue. Under Wayland TBH I haven't found a way for executing a command on an event (which is pretty easy with Xorg's xbindkeys) and therefore fully customizing behavior of key and mouse event.. I believe Wayland is trying to be more secure and disables this behavior.

In any case, you still have the opportunity to switch to Xorg pretty easily and enjoy the functionality.

5
  • Worked for me, but how do you make the change permanent? Seems I have to run xinput set-button-map for each new Wayland session... – mgalgs Nov 30 '17 at 5:21
  • 1
    Yes, you need to run it every time. To automate this, you can put this in a script and create a service file, or put this in an init folder that is ran at startup corresponding to your distro (on systemd-based OS that would be /etc/rc.d/init.d/) – CermakM Dec 1 '17 at 6:58
  • You can put an option in xconf files: Option "ButtonMapping" "1 2 3 ..." – le hollandais volant Jul 9 '18 at 11:29
  • 1
    This only changes the xorg input driver, not any applications that natively use wayland composition, like Gnome Shell or Nautilus – Ray Foss Apr 26 '19 at 19:55
  • This should not be the accepted answer. It does not change the configuration of the Wayland environment. – sjy Sep 11 '20 at 7:24
5

I made a small shell script + systemd unit file I call wayland-mouse-mapper.

excerpt mathportillo/wayland-mouse-mapper

A small script for mapping mouse buttons to keystrokes on Wayland.

I made for myself to use my mouse extra buttons for useful stuff. It's tested and works with Logitech MX Master 2S on Fedora 27 using Gnome, and works it on my old Logitech Performance MX too. It probably works on any Wayland and Any Logitech mouse (or any mouse if you edit mappings) because no other method (xdotools, xbindkeys, etc.) seemed to work.

It works by reading from libinput debug-events and triggering key events using evemu depending on the recognized button from the recognized device.

Buttons

These are just the default settings, you can customize them at the start of the mousemapper.sh script.

  • Forward: Move to workspace above (Super+Page up)
  • Back: Move to workspace below (Super+Page down)
4
  • Thank you for sharing this script! I see that it works by parsing the output of libinput debug-events. Has this been reliable in your experience? I am wondering if this could be used to handle high frequency scroll events or if a more efficient solution is needed. – sjy Sep 11 '20 at 7:29
  • 1
    @sjy I reckon that extremely high frequency events probably wont skip but can stack, resulting in lag. It is specially likely to happen if you map it to a button that triggers something that does not handle repeated events. However, this problem happens in the layer outside mapping. There is for sure more efficient solutions of mapping, as reading SO binary input buffer, but if you do so you are still subject to the same thing. The point is that although there is more efficient ways, this is not the bottleneck (at least for common interface mapping). – Matheus Portillo Sep 15 '20 at 0:01
  • Thanks, I think I will give this a try! I notice that it is also available via the wayland-mouse-mapper-git AUR package. – sjy Sep 15 '20 at 0:04
  • @sjy another way to answer is that there is already a absolutely ridiculous amount of libinput events being filtered out and scrolling as fast as you can probably wont be more than 10% of those, so if there was a performance issue, it would be in "trigger" part of mapping, not in the reading, and a better way of reading events wouldn't solve this. And the trigger part (cli command with evemu) is not the bottleneck when talking about any commom GUI event, so a better way to trigger wouldnt solve it too. – Matheus Portillo Sep 15 '20 at 0:11
4

I've spent 2 days googling, testing tens of methods I've found and struggling with remapping mouse buttons under Wayland...

So sharing what I've learned:

Logitech M570 trackball has 2 extra buttons. They produce BTN_SIDE a BTN_EXTRA in libinput:

[root@centos8 ~]# libinput debug-events --device /dev/input/event21
-event21  DEVICE_ADDED     Logitech M570                     
      seat0 default group1  cap:p left scroll-nat scroll-button
 event21  POINTER_BUTTON   +16.93s      BTN_EXTRA (276) pressed, seat count: 1
 event21  POINTER_BUTTON   +17.09s      BTN_EXTRA (276) released, seat count: 0
 event21  POINTER_BUTTON   +17.89s      BTN_SIDE (275) pressed, seat count: 1
 event21  POINTER_BUTTON   +17.99s      BTN_SIDE (275) released, seat count: 0

You can check it using evtest which will also show button scancodes:

[root@centos8 ~]# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
...
/dev/input/event21: Logitech M570
Select the device event number [0-21]: 21
Event: time 1589974995.415405, -------------- SYN_REPORT ------------
Event: time 1589974996.969613, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90004
Event: time 1589974996.969613, type 1 (EV_KEY), code 275 (BTN_SIDE), value 1
Event: time 1589975000.165574, -------------- SYN_REPORT ------------
Event: time 1589975000.611570, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90005
Event: time 1589975000.611570, type 1 (EV_KEY), code 276 (BTN_EXTRA), value 1
Event: time 1589975002.369616, -------------- SYN_REPORT ------------

Now create a rule file for udev hwdb to remap scancodes to desired buttons, e.g. /etc/udev/hwdb.d/70-mouse-remap.hwdb:

# remap buttons on Logitech M570 trackball
evdev:name:Logitech M570:*
 ID_INPUT_KEY=1
 KEYBOARD_KEY_90004=btn_middle
 KEYBOARD_KEY_90005=btn_middle

Yes, the buttons are really mapped as keyboard key scancodes back to mouse middle button. Do not use too general device identifier like evdev:input:* because it may interfere with you other devices, e.g. on my Thinkpad T490 it breaks mic mute button (Fn+F4).

Save the file and rescan hwdb

[root@centos8 ~]# systemd-hwdb update

I had also to physically unplug the mouse (wireless receiver in this case) from USB to see the changes. Plug it back and check that rules are applied:

[root@centos8 ~]# udevadm info /dev/input/event21
P: /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.4/1-4.4:1.2/0003:046D:C52B.0097/0003:046D:1028.0098/input/input84/event21
...
E: KEYBOARD_KEY_90004=btn_middle
E: KEYBOARD_KEY_90005=btn_middle

Now you can test libinput again and you should see both buttons generate BTN_MIDDLE event:

[root@centos8 ~]#  libinput debug-events --device /dev/input/event21
-event21  DEVICE_ADDED     Logitech M570                     seat0 default group1  cap:kp left scroll-nat scroll-button
 event21  POINTER_BUTTON    +1.45s  BTN_MIDDLE (274) pressed, seat count: 1
 event21  POINTER_BUTTON    +1.59s  BTN_MIDDLE (274) released, seat count: 0
 event21  POINTER_BUTTON    +2.20s  BTN_MIDDLE (274) pressed, seat count: 1    
 event21  POINTER_BUTTON    +2.28s  BTN_MIDDLE (274) released, seat count: 0

If everything is ok, you should be able to paste with both extra buttons in Wayland native application like gnome-terminal.

Enjoy.

1
  • Thank you, there is a lot of helpful information in this answer. I want to point out, since it wasn't immediately obvious to me, that this answer explains how to remap a mouse button so that Wayland sees different input events, whereas the wayland-mouse-mapper answer observes Wayland input events and uses evemu to emit additional, different events. – sjy Sep 13 '20 at 3:30
1

Try modifying the hwdb udev rules. This registers the mouse buttons as a keyboard key such as Launch8/F16 and disables their functionality in all programs, wayland or otherwise.

# /usr/lib/udev/hwdb.d/71-mouse-local.hwdb

evdev:input:*
 KEYBOARD_KEY_90004=key_f16
 KEYBOARD_KEY_90005=key_f17

then as root systemd-hwdb update; udevadm trigger and unplug the mouse then plug it back in.

Additional sanity check: sudo udevadm info /dev/input/by-path/*-usb-*-mouse | grep -A3 -P3 KEYBOARD_KEY, or query it as such systemd-hwdb query "evdev:input:v046dp406a* see source for details on pulling the id.

Source: https://yulistic.gitlab.io/2017/12/linux-keymapping-with-udev-hwdb/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.