6

Note: this is not a duplicate of either this or this, as I will make clear.

I have a Logitech Proteus Core mouse. Under Windows 10, I have set one of its buttons (the small one labeled "G9" on top of the mouse) to show a task list, which can be brought up using the Win+Tab keys. Note that this stays up even if you release both the Win and the Tab keys, it only goes away once you click on the Window you want to go to. So the workflow is: push and release the G9 mouse button, click the window I want.

I want a similar behavior under Kubuntu 15.04. AFAIK, there is no way to bring up a similar task list, which stays up until you click on something, without having to hold down any keys.

So my idea was to emulate Alt+Tab with this button. The workflow I have in mind is: push G9 (shortcut for "push alt, push tab, realease tab") => select the window I want, release G9 (shortcut for "release alt").

The problem is that, as far as I can tell, this G9 button is not being read by the OS as a normal mouse button. If I run:

xbindkeys -mk

And click the G9 button, I get this output:

"(Scheme function)"
m:0x40 + c:23
Mod4 + Tab
"(Scheme function)"
m:0x40 + c:133
Mod4 + Super_L

Note: I am running this in a VM for testing purposes. Let me know if that can affect things, although I'd need it to work in this case as well.

If I run:

xev | grep button

I get no output when I click the G9 button I'm interested in. If I click other buttons, I get expected outputs like:

state 0x0, button 2, same_screen YES

This is weird, but I thought I could just add what xbindkeys -mk outputs to my ~/.xbindkeysrc:

"xte 'keydown Alt_L' 'key Tab'"
  m:0x40 + c:23 + Release

Obviously, even if this worked, it wouldn't do what I want it to, but it doesn't even work. Nothing happens when I click the G9 button after running:

xbindkeys -v -n

Which gives this warning:

Please verify that there is not another program running which captures one of the keys captured by xbindkeys. It seems that there is a conflict, and xbindkeys can't grab all the keys defined in its configuration file.

If I type the xte command in the console, it brings up the task selection alt+tab menu. Nothing for the bound mouse button however.

If I assign the same xte call to another button, one that's shown by the xev output (I tried the right mouse button), it's still not executed (it seems like only the tab is executed, as it tabs things in the text editor), but the warning is gone, and the regular function of the button is also gone:

How can I get the Alt+Tab behavior I described when clicking the G9 button? What about another button, one that xev detects, like b:3?

Note: this mouse saves the configuration made from its Windows software internally. So all my other buttons keep their functions in the VM: back/forward in browser, switch browser tabs etc. The Logitech software allows macro recordings in Windows, but it doesn't allow specifying different actions for push / release events, AFAIK.

If there is a way to record the right macro under Windows, or there is a way to simplify what I want to achieve under Kubuntu - that is, use the G9 button to get similar functionality to alt+tab -, I would also accept those solutions.

IVlad
  • 125
  • Please do not forget to accept Velkan's answer if it solved your problem and to award it the bounty. Besides this, you should not edit your question to provide another solution, but write a new answer to the question yourself. If it's basically the same content that Velkan described in his post, you should consider just leaving it away or proposing a minor edit to his answer so that it fits all details of the question. Thanks for your participation here. – Byte Commander Sep 25 '15 at 07:11
  • @ByteCommander I can only award the bounty in 7 hours. The content is similar, but tailored to my specific situation. I thought it's not worth a self answer, since Velkan's gave me what I needed to know to come up with it and I'm accepting his anyway, so I just edited in what worked for me. If you insist on adding an answer I will, but I think it's more appropriate to keep it like this. – IVlad Sep 25 '15 at 07:30
  • I am not sure which is the better approach. Usually the rule is that the question should only contain the question and everything that is an answer to it should in contrast be posted as separate answer. I'm going to check some other opinions on this... – Byte Commander Sep 25 '15 at 07:39
  • People who are used to the stack exchange network, are not used to find the solution in the question itself. And it is totally OK (in fact, it is encouraged) to answer your own question when you find your own solution. You can still offer the bounty Velkan, even after you add your own solution. – Dan Sep 25 '15 at 08:45
  • @Dan OK, I posted it as an answer. – IVlad Sep 25 '15 at 08:50
  • @IVlad And you can award the bounty to Velikan now by clicking the 50 at the left of the answer too ;-) – Pilot6 Sep 25 '15 at 13:42
  • 1
    @Pilot6 it says I need to wait another hour :). I promise I will award it. I have a high-rep account on SO; I would never not accept a helpful answer or not award a bounty. – IVlad Sep 25 '15 at 13:44

2 Answers2

5

evrouter can help to do that. It will even allow to release G9 before selecting the task from the list.

http://www.bedroomlan.org/projects/evrouter

I've built it from source and installed with checkinstall, but there is something that looks like a repository there.

Hooks

It can be configured in the ~/.evrouterrc:

"Logitech Gaming Mouse G300" "/dev/input/event.*" any key/272 "SHELL//home/velkan/click.sh"

"Logitech Gaming Mouse G300" "/dev/input/event.*" any key/275 "SHELL//home/velkan/atab.sh"

Running sudo evrouter -d /dev/input/event* and clicking around will help to compose these lines.

"Logitech Gaming Mouse G300" is the name of my mouse.

"/dev/input/event.*" means that input will be intercepted regardless of the name of device file to which the mouse is bound.

any - means that the event will be accepted with any Alt/Ctrl/Shift modifier.

key/272 - left mouse button.

key/275 - back mouse button (on G4 for me).

"SHELL//home/velkan/click.sh" - run /home/velkan/click.sh when that event occurs.

Alt-Tab scripts

So, the /home/velkan/atab.sh script (that is bound to G4 in this case):

#!/bin/bash

mktemp /tmp/evr-alt-tab-XXXX

/usr/bin/xte 'usleep 100000' 'keydown Alt_L' 'usleep 50000' 'key Tab'

It creates a temporary file that will inform the click.sh (bound to the left button) that it needs to release Alt.

click.sh script:

#!/bin/bash

if [ -e /tmp/evr-alt-tab-???? ]; then
    /usr/bin/xte 'usleep 100000' 'keyup Alt_L'
    rm /tmp/evr-alt-tab-????
fi

Activating evrouter on startup

Haven't tried that on KDE.

Launch script /usr/local/sbin/evrouter_launch.sh:

#!/bin/sh
/usr/local/bin/evrouter /dev/input/event* 0<&- > /dev/null

(or it may be /usr/bin/evrouter instead of /usr/local/bin/evrouter)

Config /etc/lightdm/lightdm.conf to start evrouter with the desktop manager:

[SeatDefaults]
autologin-user=
session-setup-script=/usr/local/sbin/evrouter_launch.sh
Velkan
  • 3,616
  • +1 and many thanks: I used your ideas to come up with a solution that used xbindkeys and xte. I added it to my question as the solution. Can you please comment if there are any disadvantages to this, or if I can improve it in any way? I'm also adding a bounty, since this has been bothering me for a while! – IVlad Sep 24 '15 at 15:22
  • @IVlad, I've tried in Unity and it doesn't release Alt. In ~/.xbindkeysrc script is bound to the middle click, but as far as I understand, Alt should be released by the script when the left mouse button is pressed. Middle click: Alt keydown and Tab keypress (down/up), left click: Alt keyup. By default xbindkeys doesn't do a pass-through for captured events, so need to look into docs to be able to attach script to the left click correctly. Side note: middle click copy-paste is too valuable to be overridden. – Velkan Sep 24 '15 at 17:35
  • The current functionality is: G9 press and release => alt keydown, tab keypress. G9 press again => alt release. So the alt+tab windows display stays up, allowing me to select a window, and then go to it by clicking G9 again. I understand what you mean by using a combination of two mouse buttons, but in my case, I can sacrifice G9, as it's not the middle button. It's kind of like a second middle button. The script works for me in KDE, Are there any improvements to it that you think might be worth doing? Any scenarios in which it might fail that I missed? – IVlad Sep 24 '15 at 19:15
  • Don't see anything else. It's becoming too theoretical for me, because in my config the 'Alt + b:2' part doesn't trigger, so Alt stays pressed even after multiple middle-clicks; another thing is that the Unity window switcher needs a left click to select a window. – Velkan Sep 24 '15 at 19:48
  • Hmm, the KDE switcher requires a left click too. The Alt + b:2 part does trigger for me though. Strange, maybe it has something to do with the delays, or differences between Desktops? I'll see if I can try it on Unity too and get back to you in a few days. – IVlad Sep 24 '15 at 19:50
  • @Velkan I just wanted to say thank you so much for this how-to! Unfortunately, evrouter doesnt have practically any documentation and I used this post to make a pretty awesome custom macro keyboard from a spare keyboard. Your post was vital to my learning how the tool worked. Thanks so much! :) – Michael Tunnell Feb 27 '18 at 18:47
3

I got it done using ideas from Velkan's answer. I'll list the necessary steps.

  1. First of all, the Win+Tab macro I had set on the G9 button in Windows was interfering with how Linux detects the mouse. Instead of detecting the mouse button, it simply detected the Win and Tab keys in xev. I believe the mouse is internally set to send these if you configure the button as a "Multikey Macro" in its Windows software.

    To fix this, don't set the button to use a Multikey Macro in Windows. Set it to anything else. I set it to be a middle click.

  2. Now, xev | grep button detected the G9 as button 2.

  3. I wrote this script in ~/alttab.sh, which is a combination of Velkan's scripts:

    #!/bin/bash
    
    if [ -e /tmp/alt-tab-mouse-script-???? ]; then
       xte 'usleep 100000' 'keyup Alt_L'
       rm /tmp/alt-tab-mouse-script-????
    else
       mktemp /tmp/alt-tab-mouse-script-XXXX
       xte 'usleep 100000' 'keydown Alt_L' 'usleep 50000' 'key Tab'
    fi
    
  4. I added this in my ~/.xbindkeysrc. We need two lines to make the click work in both states: when alt is down and when it isn't.

    "~/alttab.sh"
      b:2 + Release 
    
    "~/alttab.sh"
      Alt + b:2
    

This worked great for me. The flow is: click G9 (push and release), select the window you want (left click or mouse wheel), then click G9 again to go to that Window. You can modify the first if in the .sh file to also send a mouseclick 1 before keyupping alt, if you want to go directly to the window you click on with the G9 button in the windows display.

I also experimented with removing the usleep calls. It worked for me without them.

The behavior is not exactly like the Windows one, but I find it close enough. Perhaps even more convenient, since you can make the selection with the same button, so you don't have to move your finger to another button!

IVlad
  • 125