Closed nzahasan closed 4 years ago
Thank you for your report.
Could you please include the full string you're trying to type?
Edit: Sorry, found it
It appears that the letter you are trying to type does not have a corresponding X keysymdef as can be seen when searching for it in xorg_keysyms.py.
What output do you get when running xev
and pressing the key you use to type BENGALI LETTER KHA?
I do not have a BANGLA KHA in my keyboard. I my intention is to press k and type BANGLA KHA .
So what's the right solution for typing characters for which there is no keysym? I'm having the same problem with ⏎
. I know some applications using python-xlib
get around this by typing through CLIPBOARD
or PRIMARY
, but maybe there is a less hacky way?
You could potentially copy xdotool
's type
command:
https://github.com/jordansissel/xdotool/blob/master/cmd_type.c#L190
Theres also python-libxdo which implements Xdo.enter_text_window
, used above.
apparently you have to add the character in xorg_keysyms.py .
That is not entirely correct, as that file is generated by parsing the actual Xlib header files. These files, unfortunately, do not contain definitions for RETURN SYMBOL and BENGALI LETTER KHA.
Does anybody know whether xdotool
is able to type these characters?
Xdotool can type both.
On Jun 7, 2018 8:17 AM, "moses-palmer" notifications@github.com wrote:
That is not entirely correct, as that file is generated by parsing the actual Xlib header files. These files, unfortunately, do not contain definitions for RETURN SYMBOL and BENGALI LETTER KHA.
Does anybody know whether xdotool is able to type these characters?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/moses-palmer/pynput/issues/94#issuecomment-395416563, or mute the thread https://github.com/notifications/unsubscribe-auth/AFM_4aQ8gnVeAU5_T8EcLtMmxY6mXzmqks5t6SfbgaJpZM4UXnif .
@nzahasan @Evidlo If you run xev
at the same time as typing these characters with xdotool
, what events are displayed in the terminal?
xdotool type খ
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 53, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 57, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 248
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 63, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 1
MappingNotify event, serial 72, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 248
To resurrect this, I was able to remap Caps Lock to a unicode emoji with xmodmap like this:
xmodmap -e "keycode 66 = U0001F61A"
xev output:
KeyPress event, serial 37, synthetic NO, window 0x6800001,
root 0x6bf, subw 0x0, time 15707692, (11,-24), root:(1842,985),
state 0x12, keycode 66 (keysym 0x101f61a, U0001F61A), same_screen YES,
XLookupString gives 4 bytes: (f0 9f 98 9a) "😚"
XmbLookupString gives 4 bytes: (f0 9f 98 9a) "😚"
XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x6800001,
root 0x6bf, subw 0x0, time 15707774, (11,-24), root:(1842,985),
state 0x12, keycode 66 (keysym 0x101f61a, U0001F61A), same_screen YES,
XLookupString gives 4 bytes: (f0 9f 98 9a) "😚"
XFilterEvent returns: False
EDIT: And the OP's original:
KeyPress event, serial 37, synthetic NO, window 0x4000001,
root 0x6bf, subw 0x0, time 16154712, (938,637), root:(2769,1646),
state 0x10, keycode 66 (keysym 0x1000996, U0996), same_screen YES,
XLookupString gives 3 bytes: (e0 a6 96) "খ"
XmbLookupString gives 3 bytes: (e0 a6 96) "খ"
XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x4000001,
root 0x6bf, subw 0x0, time 16154792, (938,637), root:(2769,1646),
state 0x12, keycode 66 (keysym 0x1000996, U0996), same_screen YES,
XLookupString gives 3 bytes: (e0 a6 96) "খ"
XFilterEvent returns: False
EDIT2: Adding it to xorg_keysyms.py like this:
[...]
'nzahasan': (0x1000996, u'\u0996'),
'kissy': (0x101f61a, u'\U0001F61A')}
Causes it to no longer complain, but still does not send the keys.
EDIT3: Name appears to be important. 'kissy': (0x100002c, u'\u002c')
did the same until I changed the name to 'comma'. Unsure how to find or create names for these characters.
EDIT4: So I mapped them to Caps Lock again and tried having pynput tap Caps Lock, and this was the resulting error. The 😚 at the end is me pressing the physical Caps Lock key immediately after.
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/bin/StreamDeck/my/StreamDeck/Devices/StreamDeck.py", line 116, in _read
self.key_callback(self, k, new)
File "/usr/local/bin/StreamDeck/my/StreamDeck.py", line 38, in key_change_callback
key.callback(deck, state)
File "/usr/local/bin/StreamDeck/my/Keys/test.py", line 11, in callback
Controller().tap(PyKey.caps_lock)
File "/usr/lib/python3.8/site-packages/pynput/keyboard/_base.py", line 443, in tap
self.press(key)
File "/usr/lib/python3.8/site-packages/pynput/keyboard/_base.py", line 392, in press
self._handle(resolved, True)
File "/usr/lib/python3.8/site-packages/pynput/keyboard/_xorg.py", line 242, in _handle
Xlib.ext.xtest.fake_input(
File "/usr/lib/python3.8/contextlib.py", line 120, in __exit__
next(self.gen)
File "/usr/lib/python3.8/site-packages/pynput/_util/xorg.py", line 78, in display_manager
raise X11Error(errors)
pynput._util.xorg.X11Error: [(BadValue(<Xlib.display._BaseDisplay object at 0x7fad57f59fd0>, b'\x00\x02\x0b\x00\x00\x00\x00\x00\x02\x00\x84\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'), None)]
😚
@gdiShun, thank you for your thorough analysis!
I downloaded the source for xmodmap
to check what it does. keycode kc = ks
will eventually cause to to pass ks
to XStringToKeysym
. This is a utility function defined in C and is not available to the Python library Xlib
, but for strings starting with 'U'
it will perform the following:
if (*s == 'U') {
val = 0;
for (p = &s[1]; *p; p++) {
c = *p;
if ('0' <= c && c <= '9') val = (val<<4)+c-'0';
else if ('a' <= c && c <= 'f') val = (val<<4)+c-'a'+10;
else if ('A' <= c && c <= 'F') val = (val<<4)+c-'A'+10;
else return NoSymbol;
if (val > 0x10ffff)
return NoSymbol;
}
if (val < 0x20 || (val > 0x7e && val < 0xa0))
return NoSymbol;
if (val < 0x100)
return val;
return val | 0x01000000;
}
This is where 0x100002c
comes from. As you note, simply passing this as a keysym does not help. It will then call XChangeKeyboardMapping
to remap the keyboard. Perhaps this is what makes it work? In your experiments above, did you attempt to have pynput type '😚'
after having remapped it? Did you try with the following patch applied?
diff --git a/lib/pynput/_util/xorg_keysyms.py b/lib/pynput/_util/xorg_keysyms.py
index db501ff..ee61ead 100644
--- a/lib/pynput/_util/xorg_keysyms.py
+++ b/lib/pynput/_util/xorg_keysyms.py
@@ -18,6 +18,7 @@
# pylint: disable=C0111,C0302
SYMBOLS = {
+ 'Kissing_Face_with_Closed_Eye': (0x0101F61A, u'\u1F61A'),
'0': (0x0030, u'\u0030'),
'1': (0x0031, u'\u0031'),
'2': (0x0032, u'\u0032'),
In your experiments above, did you attempt to have pynput type '😚' after having remapped it?
I tried a lot of things, so I can't say with 100% certainty that I did, but I'm pretty sure I did. The result was likely just no output. What I do clearly remember doing is using from_vk(0x0001f61a)
. It would return the proper character ('😚'
) when print()'d. pynput's type would only return ''
. And pynput's tap would give a similar error as the last one in my previous post, until I added it to Xlib's keysymdef. Then it would once again do nothing.
Did you try with the following patch applied?
The patch as-is causes the same pynput.keyboard._base.InvalidCharacterException
error. The u'\u1F61A'
needs to be replaced with u'\U0001F61A'
for no errors. But still no output. Also tried adding XK_Kissing_Face_with_Closed_Eye = 0x1F61A
(and other variations) to the Xlib keysymdef. And again, no errors, but no output either. Interestingly, even with all these keysymdef changes, using tap(Key.caps_lock)
after mapping it will still cause that same BadValue
error.
I'm thinking this might be more font-, or software-based than input-, or hardware-based. More of a hunch than anything. Really don't know what I'm talking about here. :p But I've been scouring for a library to do this, and root-access or not, I can't find any that will actually output emojis or other non-standard unicode characters.
As a bit of a side-note, that may be helpful. I found a solution to inputting these characters, not with pynput, but evdev. A hacky solution using the CTRL+SHIFT+U shortcut. I posted it here.What's interesting to me, is that this works great with evdev, but inputting the same CTRL+SHIFT+U shortcut on pynput does not work either. I'm guessing it has to do with how evdev injects inputs directly?
I have pushed a proposed solution to fixup-xorg-chars-without-keysyms
. It actually appears to work on my system, but I would like confirmation from any of @Evidlo, @gdiShun or @nzahasan before merging into master.
Controller().type("'😚'\N{kissing face with closed eyes}\U0001F61A")
Controller().tap('😚')
'😚'😚😚😚'😚'😚😚😚'😚'😚😚😚'😚'😚😚😚
Working! Awesome stuff. Great job and thank you!
This has been released as pynput 1.7.
I was trying to type Bangla unicode character, but it fails with this error