https://bugs.kde.org/show_bug.cgi?id=478219

Duncan <[email protected]> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |[email protected]

--- Comment #22 from Duncan <[email protected]> ---
User comment, with the solution I just switched to here, FWIW.  Maybe this will
help the original filer (if they haven't found a wayland solution yet), along
with anyone else that finds this bug while searching for wayland input
solutions to replace their legacy X solutions.

Upstream links first but the below covers a couple kinks in initial config that
I wished upstream had covered in more detail.

esekeyd:  https://github.com/burghardt/esekeyd

ydotool:  https://github.com/ReimuNotMoe/ydotool

 Warning: Many find I'm overly verbose.  Others find the detail useful and I've
the thanks to prove it.   Either way I'll point to my position on the Autism
spectrum as to why, tho I do both try to headline sections for those wishing to
skip ahead, and edit down from first draft before posting.  YMMV.  Skip from
here entirely if you wish (that's why the links are up top).

Personal use-case and usage background:

My primary autoinput use-case is automating programmable input-injection to
"game the chance mechanism" of an old DOS-based game I still play in DOSBox
(now dosbox-staging as the original dosbox itself has been effectively stalled,
without release for years), repeatedly hitting the "gl n" (game, load,
accept-first-slot, next-turn) sequence, until I get the desired
single-digit-probability outcome (which uses different keys to continue from so
ignores further repeats of the sequence until I kill the auto-input).  With the
tools for that installed I use them for other things too, but that's the
primary auto-input usecase.  While DOSBox (original dosbox, dosbox-staging, and
another fork I have available on gentoo, dosbox-x) is still X-based for now, at
least one of the forks (dosbox-x) has preliminary wayland support available but
not ready for normal use yet, and they actively feature-share new developments
(at least the two unstalled forks do...) so it's coming.

There's a second, related but different, primary use-case as well, detecting
and doing something with the exotic keys/keycodes that my (Logitech) keyboard
has that the kernel and libinput recognize and output, but that qt (as of
6.11.1, tho it learned about some of them over the years and versions) and thus
kde/plasma don't recognize and thus ignore, so I can't assign them as shortcuts
using the normal plasma mechanism.

Until just days ago I was using the two-decade-old evrouter to deal with the
second case, listening for exotic keys and translating them into X keysyms (??)
that normal X-based apps could see and process.  For the first case I was using
a combination of xdotool and sxhkd (simple X hotkey daemon), and for some usage
I combined both, sometimes with other apps (xprop, wmctrl...) as needed in my
scripts.

In particular, I had things setup to detect what X-based window was active
(feeding the wmctrl-reported active window to xprop to get various window
properties to match against those of the desired target window) and emit keys
to activate desired app-specific functions accordingly.  Even tho I've been on
plasma/kwin_wayland for some time now, until recently that worked fine for that
game in dosbox at least, since dosbox is still X based (for now).  (Other
app-specific functionality had gradually disappeared as the apps in question
went wayland, but as I said, input to that game still running in still X-based
dosbox was my primary use-case, the others were just a bonus that I got with it
back on X so I didn't miss them all that much.)

Recent upgrade-trigger problem:

Recent plasma changes apparently ratcheted up security another notch, however,
which while a good thing in general, had the (apparent) effect of not allowing
X-based apps to know when other X-based apps were active.  Specifically,
without any updates to wmctrl/xprop/sxhkd (the tooling in the input chain in
question) or to dosbox, suddenly, when querying for dosbox as the active
window, it was *always* getting returned as active, even when a wayland window
was actually active, *and* even when dosbox wasn't even running!  Several times
I apparently triggered a shortcut that was only *supposed* to trigger input
with dosbox as the active window, and it was causing all sorts of unexpected
results in whatever (wayland!) app happened to actually be active.

While normally I'd have (very quickly!) filed that as a the blocker-level bug
it was (unpredicted input doing unpredicted things in apps that it should have
never activated for!!), given the legacy X-based programmable input-injection
apps I was running and that I knew there were more modern alternatives, I chose
to treat this as the hint I needed that now was the time to stop putting things
off, investigate the modern alternatives, upgrade, and reconfigure as
necessary.

Into to my solution:

esekeyd replaces evrouter for the second use-case above (detecting keys
qt/kde/plasma ignore and doing something with them), and ydotool replaces
xdotool and sxhkd for the first use-case (actually injecting emulated input). 
Unfortunately I don't believe kwin_wayland exposes a bash-scriptable way to get
the active window, so I had to use alternate methods to work around not being
able to avoid sending input to the active window if it wasn't the desired
target.

esekeyd:

esekeyd needs read permission on the desired /dev/input/eventNN device.  With
that it can listen for the events it's configured for, and invoke commands or
scripts as so configured.  As such, it does *not* allow directly translating
keys qt/kde/plasma can't see/hear into something they can deal with, that could
then be configured as keyboard shortcuts, but it *does* allow invoking ordinary
commands/scripts based on those keys.  So basically, for anything that can be
command-invoked at least, it substitutes for plasma's keyboard shortcuts
mechanism for keys qt/plasma is deaf/blind to.  (So it can be used as a
launcher, including to launch scripts, but can't be used to trigger say kwin
effects or the like, unless you can figure out a dbus invoke to trigger them
and script that, as I did for zoomin/zoomout/zoomoriginal,for instance.)

Configuration-wise, in practice you'll need to point esekeyd at the appropriate
/lib/input/eventNN device (it'll try to use the first "keyboard" device it
finds otherwise, which is usually a power key or some such, not a full
keyboard).  That's a commandline option.  Since the eventNN ordering may differ
depending on module load and device detection order at boot (or plug for usb
devices), what I ended up doing is using a startup script that greps the line
with my Logitech keyboard from the output of libinput list-kernel-devices, then
cuts to the first field (the device path) using : as the delimiter:

evfile=$(libinput list-kernel-devices | grep 'Logitech K350' | cut -f1 -d: )

The config file is also a commandline option (which I set with my launcher
script), with much better documentation on the config file format and how to
get the keys (like KEY_580 for the exotic AppSelect key qt/kde/plasma doesn't
yet see) and set the command to invoke than on properly detecting the correct
eventNN device.  So I won't detail that further here.

Then I can launch it as esekeyd $config $evfile

My launch script also kills any existing esekeyd before redetecting the
event-dev and starting the new esekeyd, so if the target event-dev changes I
can simply relaunch and it kills the old one before starting the new one using
the newly detected device.

If you have device-permissions issues, check the ownership and permissions on
/dev/input/eventNN and see the discussion below on ydotoold permissions issues,
except that you'll need 0640 (group readable) or 0660 permissions, not 0620 or
0660.

ydotool:

ydotool fills the other gap, actually emulating and injecting input.  As one
might guess the inspiration for it comes from the legacy xdotool  but as its
documentation (README.md) explains, it works at the libinput level, using the
/dev/uinput software-emulated-input device, creating  a new software-emulated
/lib/input/eventNN virtual device, instead of working at the X level.  That
allows ydotool to work in both X and wayland, and even at a CLI login if
desired, but in ordered to do that it uses a daemon, ydotoold, to handle the
emulated device end of things, which the scriptable ydotool itself talks to
over a socket.

ydotool must therefore have ydotoold running in order to do what it does, and
exits with an error if it can't find it.

The most common problem configuring ydotoold is likely to be a permissions
issue on /dev/uinput.  Check its ownership and permissions.  On most distros
it'll be either root:root or root:input owner:group.  policykit may set dynamic
permissions allowing access to the locally logged-in (aka local-seated) user if
you're running it (which I'm not).  Else if the group is input, your user
should be in the input group and permissions should preferably be 0620 (group
writable) tho 0660 (group read/writable) will also work.  Else if ownership is
root:root you will likely need to run ydotoold as root (unless permissions are
0662 or the like (world-writable, but that's an unnecessary security risk since
anything can write to it).   If ownership or permissions need changed (as
opposed to simply adding your user to the input group and rebooting), assuming
a modern udev-device-administered system you'll need to read up on  udev (udev
7 manpage, udevadm 8 manpage) and go from there.  While that documentation's
clear enough for the technically inclined, it's definitely a bit scary for
those who aren't used to routinely tweaking udev rules, and could be confusing
for the less technically inclined, but that's why most distros run policykit by
default these days, to handle such things for those who "prefer not to go
there".

The ydotoold commandline has several options available, but the defaults should
work for most people.  Here I did set --mouse-off since I only needed keyboard
(with --keyboard-off the corresponding keyboard option, and --touch-on
available if you want to emulate a touchscreen since that defaults to off).  
FWIW the other options are socket settings (path, ownership, permissions), help
and version.  Even with mouse disabled as I did, however, it will still try to
use xinput to disable mouse pointer acceleration, and warn (on STDERR I
believe, visible if you run it from a terminal) if it can't find it.  But on
wayland that'd normally be a noop anyway (at least with kwin_wayland as
compositor, tho I suppose for backward compatibility some compositors might
detect and use the xwayland setting that xinput would be trying to set).

As for ydotool itself, it checks the YDOTOOL_SOCKET environmental variable if
you decided to point ydotoold at some non-default socket path (the default
being /run/user/$UID/.ydotool_socket), but works fine with the defaults
otherwise.   Available actions are type, key, mousemove, and click.  type types
normal text and is definitely easier to use than key (which uses codes in the
form of KEY_* that you need to lookup in
/usr/include/linux/input-event-codes.h), but key can be used to emulate exotic
keys that you can't (easily at least) type, or if you need to separate
keydown/keyup emulation.  mousemove and click are of course pointer-device
emulation commands, which as I mentioned above I disabled as unneeded.   key,
type and click have delay options (with type having both key-delay and
between-string delay options) if the defaults don't suffice.  While I have
mouse emulation disabled and haven't used them, according to the documentation
mousemove can be relative or absolute, and  click uses hex codes to select
mouse buttons (0-7 possible) and up/down/both/neither (aka select-button only,
used for additional delay), with a repeat option to repeat the entire
click-sequence if desired.  (FWIW I could have actually used a repeat option on
the type command too, but apparently type doesn't implement repeat full
sequence, only click does.)

The ydotool documentation also discusses how to configure alternative keyboard
layouts if necessary (as it could be for non-US-QWERTY  code2key mapping for
the  type action), but as I use the standard US QWERTY layout I didn't have to
bother myself with that and thus can't intelligently discuss it, except to note
that IIRC kde/plasma didn't have the detailed instructions a couple others had
(presumably because the author couldn't find the info himself, which might be
because it didn't exist yet, I've no idea if it does now).

Integrating both:

So, if I wanted, using both ydotool (along with ydotoold) and esekeyd, I could
have esekeyd listen for those keys (keycodes) that qt/kde/plasma can't see,
configuring it with the corresponding commands to run ydotool to emit keycodes
that qt/kde/plasma *can* see, and then configure plasma shortcuts as desired
for those.  And if it wasn't something I could easier just run a command to do
from esekeyd directly, I'd do that.  However, given that qt/kde/plasma can see
most of those keys/keycodes now, I've configured the hotkeys for commands I
can't just run directly that way, so esekeyd only needs to deal with commands
it can run directly.   That leaves ydotool the primary task of emulating normal
typing, easiest done using type, but I know the fancy key emulation is there if
I need it for something (say to send modifier keys or if I otherwise needed to
emulate key chording, with more than one key down at a time), and I can
un-disable the mouse emulation and try mousemove and click too, if someday I
get curious or need to, tho I never needed that with X  and it's even more
unlikely I'll need to on wayland, where the ability to do so can't be taken for
granted as it can with X.

OK, but what about active window selection?:

As mentioned above, on X I was doing injection conditional on the active
window, and (not mentioned above) the injection used (AFAIK) the xtest
extension or something else that directed the emulated input to a specific
window, thus allowing me to switch away from that window and do something else
while the input was still ongoing without it redirecting to the new window (for
programmed input lasting long enough that switching away was something one
might consider).  That worked real well for the dosbox gaming usage since I
could set it up doing the repeat thing and then switch to something else while
it did it.

With the new setup I can't detect the active window, so (a) I can't detect the
active window and use that to decide whether and what input I emulate to it,
and (b) I can't switch away from that window once I start sending input to it,
because the emulated input will then go to whatever I switch to instead.

Inability to detect active window: my workaround:

To work around (a) I setup an autoinput tree in my customized menu config
(FWIW, pdmenu in a konsole window, using a custom konsole profile, custom
konsole commandline, with custom kwin rules applied to it; FWIW I already use
that for my routine launching from apps and scripts to an entire subtree of
youtube channel links, because it's far easier to configure new entries there
an entire menufile at a time, than it is to have to deal with individual
*.desktop file configuration a single command at a time, for the normal kde
desktop menu plasmoids, which thus get very little use), tho ATM I'm only doing
the transfer from sxhkd of the input sequences for that game in dosbox and will
fill in others as I decide I need them, later.

Inability to direct emulated input to a specific window and keep it routed
there or stop it if the selected window loses focus, no present workaround
found, I live with it:

For (b), being able to switch away from an app once I started emulated input to
it and have that input keep going to it, I don't have a replacement yet and I'm
not sure how long it'll be (if ever) until I get one.  For now, I'll just stay
focused on the target app, tho I did setup an emergency killall ydotool
invokable by a normal one-stroke plasma shortcut panic-button, should I
suddenly find myself getting unexpected input where it doesn't belong.  I guess
the other alternative is switching to a more scripting-accessible compositor
that exposes stuff like active-window to scripts that could use that info, tho
of course the security tradeoff that wayland took vs X still stands.  But then
again, it still stands for the whole emulated input thing in the first place
too, and we're already making that choice, the difference here being that's
standardized enough for third-party apps to expose the functionality, while
wayland active-window info isn't, AFAIK, making the compositor the only thing
that can expose it to us, which kwin_wayland doesn't appear to do.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to