Configure extra mouse button as a second middle click under Wayland

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.


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)

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.