Emulate middle mouse when the actual one does not work

Sérgio Araújo - May 20 '22 - - Dev Community

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" 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 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:

sudo xbps-install -Sy xinput xvkbd sxhkd xdotool
Enter fullscreen mode Exit fullscreen mode

Getting your mouse ID:

xinput --list | grep 'id='
Enter fullscreen mode Exit fullscreen mode

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

How to swap mouse buttons using xinput?

xinput --set-button-map 11 1 3 2
Enter fullscreen mode Exit fullscreen mode

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

programatically sending a button2 click:

xvkbd -no-jump-pointer -xsendevent -text '\m2'
Enter fullscreen mode Exit fullscreen mode

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:

# 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
Enter fullscreen mode Exit fullscreen mode

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:

ctrl + button1
    xvkbd -no-jump-pointer -xsendevent -text '\m2'
Enter fullscreen mode Exit fullscreen mode

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:

# %%hotkey: paste primary selection %%
ctrl + ~button1
    xdotool click --clearmodifiers 2
Enter fullscreen mode Exit fullscreen mode

Nvim solution:

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

-- ~/.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
Enter fullscreen mode Exit fullscreen mode

In our mappings.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')
Enter fullscreen mode Exit fullscreen mode
  • 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:

# 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
Enter fullscreen mode Exit fullscreen mode

References:

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .