Emulate middle mouse when the actual one does not work
Tags: linux, hack, xinput, xvkbd
Published: 2022-05-20 13:51:22


## The scenario:

The old school boys like me that started using Linux when you had to manually mount a floppy disk used to paste using the ["Primary Selection"](https://en.wikipedia.org/wiki/Primary_election) quite often.

What happened to me and many other guys is that our middle mouse is broken, the `Shift + Insert` works normally, then I started a search to learn how we can temporarily swap the middle mouse button with the button3. 

Two more things: 

1 - I am using **[bspwm](https://github.com/baskerville/bspwm)** that already has the sxhkd which can bind keys to commands, if you are using other desktop install it and make sure it is running!

2 - My graphical server is X11, for wayland I think you have more things to do.

## Installing the needed tools:

In my case, a voidlinux user:

```sh
sudo xbps-install -Sy xinput xvkbd sxhkd xdotool
```

## Getting your mouse ID:

```sh
xinput --list | grep 'id='
```

In my case the "USB OPTICAL MOUSE" has the id '11'.

### How to swap mouse buttons using `xinput`?

```sh
xinput --set-button-map 11 1 3 2
```

Where 11 represents my mouse id. After that your button 3 will "be" the 2 :)

programatically sending a button2 click:


```sh
xvkbd -no-jump-pointer -xsendevent -text '\m2'
```

Now I can press the button 3 (which will recognized as 2) to get the Primary Selection, but I need to set mouse back to the original setting, so I am using this `xhkbdrc` mapping:

```sh
# add these lines to your ~/.config/sxhkbd/sxhkbdrc
# %%hotkey: paste primary selection %%
ctrl + button1
    xinput --set-button-map 11 1 3 2 ; xvkbd -no-jump-pointer -xsendevent -text '\m2'; \
    xinput --set-button-map 11 1 2 3
```

Usint `Ctrl + button1` to call three commands at once:

1 - Swap mouse buttons 2,3
2 - Emulate the button2 click
3 - Swap mouse buttons 3,2

## Update:

Actually we can use just:

```sh
ctrl + button1
    xvkbd -no-jump-pointer -xsendevent -text '\m2'
```

Even having to use a key press, it is faster than having to reach `Shift-Insert`, in those situations where I am for example, browsing where my left hand is over the keyboard.

## Better solution using xdotool:
+ source: https://askubuntu.com/a/390334/3798

```sh
# %%hotkey: paste primary selection %%
ctrl + ~button1
    xdotool click --clearmodifiers 2
```

## Nvim solution:

Considering we are sending `Ctrl + button1` as if it was button2 our neovim solution will be someting like this:

```lua
-- ~/.config/nvim/lua/core/utils
local M = {}

-- https://blog.devgenius.io/create-custom-keymaps-in-neovim-with-lua-d1167de0f2c2
-- https://oroques.dev/notes/neovim-init/
M.map = function(mode, lhs, rhs, opts)
    local options = { noremap = true }
    if opts then
        options = vim.tbl_extend("force", options, opts)
    end
    vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end
return M
```

In our mappings.lua 
```lua
local map = require('core.utils').map

-- copy to the primary selection on mouse release
map("v", "<LeftRelease>", '"*y')
map("i", "<C-MiddleMouse>", '<C-o>"*p')
map("n", "<C-MiddleMouse>", '"*p')
```

- In visual mode, when there is an `Left Mouse Release` the selection will be copied to the primary selection
- In insert mode a `<C-MiddleMouse>` we are receving via xhkbdrc config, will go temporarelly to normal mode `<C-o>`and run a paste of the "Primary Selection" `"*p`.
- Slightly different in normal mode, though!

A nice thing happens here, now I can open up my nvim and just press `Ctrl + MiddleMouse` and have some texto I have just selected pasted on it

## ZSH widgets:

```sh
# Edit content of clipboard on vim (ZQ to discard)
function _edit_clipboard(){
    # pbpaste | vim -c 'setlocal bt=nofile bh=wipe nobl noswapfile nu'
    export LC_ALL=en_US.UTF-8
    /bin/xclip -i -selection clipboard -o | /usr/bin/nvim
}
zle -N edit-clipboard _edit_clipboard
bindkey '^x^v' edit-clipboard

# Edit content of primary selection (ZQ discard)
function _edit_primary_selection(){
    export LC_ALL=en_US.UTF-8
    /bin/xclip -i -selection primary -o | /usr/bin/nvim
}
zle -N edit-primary_slection _edit_primary_selection
bindkey '^x^p' edit-primary_slection
```

## References:

* http://xahlee.info/linux/linux_xvkbd_tutorial.html
* https://www.reddit.com/r/linuxquestions/comments/q761a2
* https://askubuntu.com/a/390334/3798

## Improving this article:

I am still testing this solution but at least for now it works like a charm! If you have any suggetstions or improvements, feel free to comment, I will be glad to hear what you have to say.