sway-input: add button_mapping option

Created on 23 Mar 2019  路  13Comments  路  Source: swaywm/sway

libinput(4) has this option which is missing in sway-input:

Option "ButtonMapping" "string"
Sets the logical button mapping for this device, see
XSetPointerMapping(3). The string must be a space-separated list
of button mappings in the order of the logical buttons on the
device, starting with button 1. The default mapping is "1 2 3
... 32". A mapping of 0 deactivates the button. Multiple buttons
can have the same mapping. Invalid mapping strings are
discarded and the default mapping is used for all buttons.
Buttons not specified in the user's mapping use the default
mapping. See section BUTTON MAPPING for more details.

My usecase: my mouse has swapped side buttons for <Back> and <Forward> (buttons 8 and 9) so I need to change the mapping.

enhancement

Most helpful comment

@msrd0 To use any button, the following steps should work:

  1. Run sudo libinput debug-events
  2. Press the button that you want to create the mapping for
  3. Locate the button name (it should start with BTN_) in the output
  4. Use that button name in the bindsym

All 13 comments

The ButtonMapping option is specific to the libinput X.Org driver and is not available via the libinput library. Additionally, Wayland does not use the logical button numbers and uses the raw event codes instead. Sway does provide compatibility mappings for buttons 1-9 in the config for anything that takes a button though for convenience.

The following could be added to your config, which should accomplish the swap without requiring any code changes:

set $MOUSE <id-of-mouse>
bindsym --input-device=$MOUSE --whole-window button8 seat - cursor press button9, seat - cursor release button9
bindsym --input-device=$MOUSE --whole-window button9 seat - cursor press button8, seat - cursor release button8

I'm not sure that I like the idea of implementing a button_mapping compatible command in Sway though

Thanks, it works as expected. If button_mapping won't get implemented, I suggest to at least mention the solution in the man page or other documentation.

Actually, the following would probably be better. I think the first version will still results in the surface getting a release event for the wrong button (which it will never get a pressed event for - related to #3063)

bindsym --input-device=$MOUSE --whole-window button8 seat - cursor press button9
bindsym --input-device=$MOUSE --whole-window --release button8 seat - cursor release button9

bindsym --input-device=$MOUSE --whole-window button9 seat - cursor press button8
bindsym --input-device=$MOUSE --whole-window --release button9 seat - cursor release button8

In the same vein as this, is it possible to have Sway revoke or abandon a bindsym? Would that be considered a valid enhancement?

Use case: if I don't bind button8 or button9 at all in the config, applications like nemo correctly process them as "back" and "forward" buttons. If I do create a binding in the config (or with swaymsg 'bindsym ' while running) like:
bindsym --whole-window button8 exec virsh send-key Arch KEY_LEFTALT KEY_LEFT

bindsym --whole-window button9 exec virsh send-key Arch KEY_LEFTALT KEY_RIGHT
It works exactly as it should- pressing button8 and button9 executes the respective virsh command and virsh sends the keys to my VM. Of course now nemo isn't going to see button8 or button9 since Sway is executing the virsh commands. I can't seem to get button8 and button9 to unmap- I can bindsym them to a different command, but they will not be recognized by nemo again unless I exit sway and start again (again with no bindsym commands for button8 or button9 in the config). xev doesn't even register them being pushed, though libinput events does.

I tried playing with seat - cursor like:
swaymsg 'bindsym --input-device=blahblah --whole-window button8 seat -cursor press button8

...etc
but that doesn't seem to set it back to how it would be if I hadn't bindsym'd button8 or button9 at all.

EDIT- Actually, reading this, Im not sure this is exactly button mapping. If this needs to be made a new issue with the enhancement label, let me know...

Actually, reading this, Im not sure this is exactly button mapping. If this needs to be made a new issue with the enhancement label, let me know.

That is indeed a separate issue. Can you please make a new issue for it?

@RedSoxFan Thanks for posting your workaround. However, it only works for buttons 1-9 (sway complains about config errors if I put button10), and my mouse manufacturer decided to use button 10 for what should be 8. Is it somehow possible to remap button 10 to button 8?

@msrd0 To use any button, the following steps should work:

  1. Run sudo libinput debug-events
  2. Press the button that you want to create the mapping for
  3. Locate the button name (it should start with BTN_) in the output
  4. Use that button name in the bindsym

Thanks, that works. I believe this should be documented somewhere.

set $MOUSE <id-of-mouse>
bindsym --input-device=$MOUSE --whole-window BTN_RIGHT seat - cursor press BTN_LEFT, seat - cursor release BTN_LEFT
bindsym --input-device=$MOUSE --whole-window BTN_LEFT seat - cursor press BTN_RIGHT, seat - cursor release BTN_RIGHT

I tried this to revers left/right button of mouse, but then dragging over text with right click (left-mouse-button) does not select

For dragging to work, reference my comment above with the press and release split
https://github.com/swaywm/sway/issues/3960#issuecomment-475907290

Also, if you just want to swap left/right, you should be able to just use input $MOUSE left_handed enabled.

I couldn't get full drag-remapping to work. As far as I can tell the mouse button remappings are applied in seatop_default.c/handle_button which seems only to trigger on press events. The release event is handled by seatop_down.c/handle_button. There isn't any mapping logic in this file. This makes it impossible to remap a mouse button release event.

There is a branch in the former function for button release events but I think it might be dead code. At least I only ever saw the function being called with state == WLR_BUTTON_PRESSED.

In the end I went down to evdev and remapped the buttons with an hwdb file.

Hello, @RedSoxFan.

Actually, the following would probably be better. I think the first version will still results in the surface getting a release event for the wrong button (which it will never get a pressed event for - related to #3063)

bindsym --input-device=$MOUSE --whole-window button8 seat - cursor press button9
bindsym --input-device=$MOUSE --whole-window --release button8 seat - cursor release button9

bindsym --input-device=$MOUSE --whole-window button9 seat - cursor press button8
bindsym --input-device=$MOUSE --whole-window --release button9 seat - cursor release button8

The release event is not being generated for some reason, and the "--input-device" flag doesn't work when I use the identifier that I get from swaymsg -t get_inputs (using type:touchpad doesn't seem to work either).

Hello, I have a problem related to this, my "Logitec Performance MX" mouse got a button "zoom" who is button13 on x11.
However it's currently not mapped to any libinput-event.

> sudo libinput debug-events
event21  POINTER_BUTTON   +190.866s ??? (280) pressed, seat count: 1

The ??? indicate that the code 280 is not mapped to any BTN_xxx event.
Do I have a way to map it ?

I guess that having a special name in bindsym to use the code directly can be useful, like "BTN_X280" (to directly use code 280) ? That do you think ?

Was this page helpful?
0 / 5 - 0 ratings