DEV Community

Cover image for Emulate middle mouse when the actual one does not work
Sérgio Araújo
Sérgio Araújo

Posted on

Emulate middle mouse when the actual one does not work

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.

Top comments (1)

Collapse
 
voyeg3r profile image
Sérgio Araújo

Interestingly, my post had a typo in the title so that you can still see it on the url :)