Use xlib to map one shortcut to another (fighting the invisible cursor)

Philipp Otto philipp.4096+xorg at googlemail.com
Mon Apr 24 11:39:27 UTC 2017


Hi there,

My high level goal is to be able to map an arbitrary keyboard combination
to another one. I know that there is already a lot of web resources
regarding this, but I ended up writing C++ using xlib, since everything
else didn't work out for me.

Three typical use cases would be:

- Capslock + j should behave as if I pressed Left (move cursor for text
navigation)
- Capslock + h should behave as if I pressed CTRL + Left (jumps over words)
- Capslock + Alt + h should behave as if I pressed CTRL + Shift + Left
(selects words)

An important requirement is, that holding down a shortcut should behave as
if I *kept* pressing the combination it was mapped to.

I already tried using xmodmap as well xbindkeys with xdotool, but there was
always something which didn't work out.

That's why my current approach is to directly use Xlib with XGrabKey,
XNextEvent and XSendEvent. This works surprisingly well, but has two
problems (the first being the major one):

- When I keep pressing the shortcut, the text cursor (caret) will move as
expected, BUT it will be invisible as long as I'm pressing the shortcut,
which is very annoying. After I release the shortcut, the caret will become
visible again. I couldn't find any documentation nor workaround for this
behaviour. Does anybody know anything about this?

- It does not work in all programs. I've read that some programs choose to
ignore XEvents, if there were simulated. My current plan is to patch my
local xlib so that the "send_event" flag is always False. See [1]. If you
have a better idea, I'd be glad to hear it.

As a workaround for these problems, I already tried using
XTestFakeKeyEvent, but this has its own problem. Since it doesn't allow to
specify modifiers, each modifier has to be send as a keypress event.
However, this only works if I send events for releasing the actually
pressed keys on the keyboard beforehand. And due to this reason, I cannot
stop the mapped shortcut by releasing the keys on my keyboard, since there
were already released virtually.

My main problem is the one of the "invisible caret" since I don't have any
idea how to fix this. Any pointers would be highly appreciated!

Thank you
Philipp

[1]
http://www.semicomplete.com/blog/geekery/xsendevent-xdotool-and-ld_preload.html

Philipp Otto <philipp.4096 at gmail.com> schrieb am Mo., 24. Apr. 2017 um
09:35 Uhr:
Hi there,

My high level goal is to be able to map an arbitrary keyboard combination
to another one. I know that there is already a lot of web resources
regarding this, but I ended up writing C++ using xlib, since everything
else didn't work out for me.

Three typical use cases would be:

- Capslock + j should behave as if I pressed Left (move cursor for text
navigation)
- Capslock + h should behave as if I pressed CTRL + Left (jumps over words)
- Capslock + Alt + h should behave as if I pressed CTRL + Shift + Left
(selects words)

An important requirement is, that holding down a shortcut should behave as
if I *kept* pressing the combination it was mapped to.

I already tried using xmodmap as well xbindkeys with xdotool, but there was
always something which didn't work out.

That's why my current approach is to directly use Xlib with XGrabKey,
XNextEvent and XSendEvent. This works surprisingly well, but has two
problems (the first being the major one):

- When I keep pressing the shortcut, the text cursor (caret) will move as
expected, BUT it will be invisible as long as I'm pressing the shortcut,
which is very annoying. After I release the shortcut, the caret will become
visible again. I couldn't find any documentation nor workaround for this
behaviour. Does anybody know anything about this?

- It does not work in all programs. I've read that some programs choose to
ignore XEvents, if there were simulated. My current plan is to patch my
local xlib so that the "send_event" flag is always False. See [1]. If you
have a better idea, I'd be glad to hear it.

As a workaround for these problems, I already tried using
XTestFakeKeyEvent, but this has its own problem. Since it doesn't allow to
specify modifiers, each modifier has to be send as a keypress event.
However, this only works if I send events for releasing the actually
pressed keys on the keyboard beforehand. And due to this reason, I cannot
stop the mapped shortcut by releasing the keys on my keyboard, since there
were already released virtually.

My main problem is the one of the "invisible caret" since I don't have any
idea how to fix this. Any pointers would be highly appreciated!

Thank you
Philipp

[1]
http://www.semicomplete.com/blog/geekery/xsendevent-xdotool-and-ld_preload.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.x.org/archives/xorg/attachments/20170424/a9f28658/attachment.html>


More information about the xorg mailing list