sway icon indicating copy to clipboard operation
sway copied to clipboard

xcape features (double bind modifiers)

Open timokau opened this issue 8 years ago • 45 comments

Hi, For me currently the main thing that stops me from giving wayland a try, is missing xcape support. Now https://github.com/alols/xcape/issues/67 is open for a while, and it doesn't seem like its going to come anytime soon or even is possible. Is it correct, that the windowmanager would have to implement these features? If so, have you considered implementing them?

My specific use-cas is:

  • Bind Caps to ctrl when I hold it, escape else
  • Bind Tab to alt-gr when I hold it, Tab else

timokau avatar Jun 20 '16 05:06 timokau

I think you should pitch this to libinput.

ddevault avatar Jun 20 '16 11:06 ddevault

Thank you, I did.

timokau avatar Jun 21 '16 18:06 timokau

They won't fix, apparently its too high-level for libinput.

timokau avatar Jun 24 '16 05:06 timokau

Ugh. I'll reopen this but I'm not sure how I want it to take shape in sway.

ddevault avatar Jun 24 '16 11:06 ddevault

Thanks It wouldn't really be a good solution if every compositor had to implement this (although I think that especially people using tiling window managers may profit from this). But if its the only one, I'm glad that you at least consider it.

timokau avatar Jun 24 '16 12:06 timokau

Is this even possible in sway without changing wlc? I think the whole keymapping is hidden and not accesible.

progandy avatar Jun 24 '16 13:06 progandy

Looks like this might be easier with wlroots.

Plus, here's an idea! Since every problem in Wayland is solved by inventing a protocol…

We need one that's kinda similar to xwayland-keyboard-grab, but:

  • obviously, not an exclusive grab — keypresses must be copied to the client;
  • the client should provide the set of keys it's interested in — the compositor can implement security policies based on that. e.g. sway can have two different permit levels, watch-modifier-keys and watch-all-keys, or just allow everyone to grab modifier keys (they're not that interesting after all) and require permit watch-keys for a keylogger;
  • and of course, the interface should also include a request that injects keypresses back.

Example flow:

  • the hypothetical wcape or waycape or whatever requests watch_keypresses(wl_seat, ['Shift_L', 'Shift_R', 'Control'])
  • the user presses and releases Control in a terminal window
  • the compositor sends an event for Control to the terminal (which ignores it), but also sends that event to wcape because it's registered for that key
  • wcape reads the event and requests inject_keypress('Escape')
  • the compositor sends an event for Escape to the terminal

Bonus idea: clients can request a "secure mode" like in macOS, so when you're entering a password, events would not be copied to wcape. (Not super necessary when only giving access to modifier keys, but would be great for, like, running a keylogger for typing statistics I guess :D)

valpackett avatar Nov 22 '17 22:11 valpackett

Seems annoying to have to define a whole protocol for this...but it is the most compositor agnostic option :\

Unless there was some other layer above libinput that's implemented that can implement this and all the compositors start using that. Though that seems mostly unnecessary and even less likely than all the compositors using the same protocol.

Timidger avatar Nov 23 '17 08:11 Timidger

Yeah, just setting xcape style key presses is simple enough to do directly in compositors, but this protocol allows for more stuff, such as TextExpander-like apps, typing statistics, etc.

valpackett avatar Nov 23 '17 10:11 valpackett

What do y'all think about this protocol?

valpackett avatar Nov 26 '17 21:11 valpackett

-1. This is not something I'm interested in doing with a protocol.

ddevault avatar Nov 26 '17 21:11 ddevault

So it won't be possible to do UI automation/testing/macros (java.awt.Robot, Sikuli, xdotool etc.), text snippet expansion, keyboard typing statistics, etc. under Sway?

I guess I'll have to do this on evdev level then. It's possible to listen directly on evdevs and create a fake keyboard (uinput on Linux, cuse on FreeBSD) to inject events. I believe that a Wayland protocol would've been a much cleaner and better solution >_<

valpackett avatar Nov 26 '17 22:11 valpackett

I don't think that any of those use-cases justify putting in what is literally a keylogger protocol extension.

ddevault avatar Nov 26 '17 22:11 ddevault

What if I want a literal keylogger to analyze my typing speed?

These features are useful. Global input access shouldn't be completely killed, it should be available to privileged applications. macOS uses accessibility APIs for this, you have to tick a checkbox in Preferences to allow an app to do this. Sway has IPC security already, which is pretty similar! permit /usr/local/bin/xcape keylogging

valpackett avatar Nov 26 '17 22:11 valpackett

Then you should patch sway.

ddevault avatar Nov 26 '17 22:11 ddevault

What do you mean by "patch"? "maintain your own fork"? :)

Actually, I'll probably do the evdev-level thing because it will work with GNOME, KDE, etc. out of the box. Would help with https://github.com/bulletmark/libinput-gestures/issues/27 as well.

valpackett avatar Nov 26 '17 22:11 valpackett

No, I mean patch. I run sway with some private patches myself. Patching software is not a big deal. Just do it until you get bored of gathering stats on your typing habits.

ddevault avatar Nov 26 '17 22:11 ddevault

I'm author of this, may be interesting on this topic:

  • https://gitlab.com/interception/linux/tools

Specifically the caps2esc plugin covers "Bind Caps to ctrl when I hold it, escape else" and hideaway covers "Hide mouse cursor on inactivity". I use it on Sway (works on X as well).

oblitum avatar Dec 17 '17 02:12 oblitum

That's pretty awesome!

ddevault avatar Dec 17 '17 02:12 ddevault

So, seems like the list of solutions is here: https://github.com/alols/xcape/issues/67

My solution is evscript, it runs Dyon scripts with access to evdev/uinput.

valpackett avatar Dec 17 '17 10:12 valpackett

I have a patch for sway which permits key event injection (and hence xcape behavior), although there are significant limitations. It requires that one have an identifier for the keyboard (for this example, 0:0:X11_keyboard press)† , and creates a new process every use, but does not require root.

0001-Add-fake_key-command.txt

Note that faked event timestamps are 0, and please read the warning.

Then in the sway config file, add a line like

bindsym --release Control_L exec swaymsg fake_key 0:0:X11_keyboard press_and_release 9

in which 9 is the xkb keycode for Escape. swaymsg indirection avoids a crash.

† You can find this by running with full logging (sway -d), and then reading the log for a line like

2018-06-02 11:13:59 - [sway/sway/input/input-manager.c:221] adding device: '1:3:example_keyboard'

frsfnrrg avatar Jun 02 '18 15:06 frsfnrrg

Related: https://github.com/swaywm/sway/issues/1779

Note that you can get keyboard identifiers with swaymsg -t get_inputs.

emersion avatar Jun 02 '18 15:06 emersion

I'm just going to drop my 2 cents here, I have been using this behaviour for more than a year, and it's awesome for tiling wm / vim / graphical apps with ctrl; left pinky finger has way less stress at the end of the day.

I used https://github.com/oblitum/caps2esc at first and packaged it to exherbo, then @oblitum moved it to https://gitlab.com/interception/linux/plugins/caps2esc as a plugin to a bigger interception-tools project.

Now that hideaway is built-in to sway, having such a generic input manipulation tool running just for the caps2esc behaviour seems a little overkill and being able to directly configure it from sway would be awesome.

julientechdev avatar Feb 20 '19 14:02 julientechdev

@avrelaun if you just want to map caps to escape (rather than conditionally to ctrl or escape depending on whether chorded as caps2esc does) you can do that with a hwdb rule as in https://github.com/edrex/etc/blob/master/udev/hwdb.d/90-custom-keyboards.hwdb.

edrex avatar May 24 '19 16:05 edrex

if you just want to map caps to escape (rather than conditionally to ctrl or escape depending on whether chorded as caps2esc does)

The preferred solution is to use the xkeyboard-config option.

emersion avatar May 24 '19 16:05 emersion

For chording keys I think an external tool is preferred over something builtin. It doesn't look like a task for sway. For example, caps2esc has to manipulate key-down and key-up in a specific way to make chording natural and not cause problems like missing keystrokes.

oblitum avatar May 24 '19 16:05 oblitum

@edrex I need the exact behaviour with both ctrl and escape depending on the case.

julientechdev avatar May 25 '19 12:05 julientechdev

I came here because I am looking for a way to replace this xcape config:

xcape -e 'Shift_L=Shift_L|parenleft;Shift_R=Shift_R|parenright'

Any ideas if this is possible to accomplish with Sway? or other Wayland compatible tools?

jcalonso avatar Jul 19 '19 07:07 jcalonso

Sorry for being off-topic, but if somebody has the same issue and it's the only thing that holds one back to switch, it can be super useful.

@jcalonso, not with (stable) Sway but at a lower level you can achieve it with the above mentioned Interception Tools (by @oblitum). If you could make that work and you don't want to reinvent the wheel you can use my general purpose plugin for a quick solution.

/* tap-rules.h.in */
{ .base_key   = KEY_LEFTSHIFT, /* change this key */
  .tap_key    = KEY_KPLEFTPAREN, /* what to do when pressed alone/pressed once */
  .repeat_key = KEY_KPLEFTPAREN, /* what to do when pressed for longer time (just remove it if you find it useless) */
  .hold_key   = KEY_LEFTSHIFT /* behave as this key as soon as other key pressed */  },
/* similar for right shift... */

@timokau, your config:

/* tap-rules.h.in */
{ .base_key = KEY_CAPSLOCK, .tap_key = KEY_ESC, .repeat_key = KEY_LEFTCTRL, .hold_key = KEY_LEFTCTRL },
{ .base_key = KEY_TAB, .tap_key = KEY_TAB, .hold_key = KEY_RIGHTALT/*altgr*/ },

zsugabubus avatar Aug 11 '19 21:08 zsugabubus

So, what is the current state of key event copying?

I am the maintainer of https://github.com/keyleds/keyleds. It implements visual feedback on gaming keyboards that have per-key lights, triggering animations to respond to key events.

How would I go about supporting sway/wlroot/wayland, whichever is the right level?

spectras avatar Oct 14 '19 21:10 spectras