moses-palmer / pynput

Sends virtual input commands
GNU Lesser General Public License v3.0
1.78k stars 248 forks source link

key 5 on the numeric pad does not print as 5 #530

Open mglt opened 1 year ago

mglt commented 1 year ago

Description Pressing the key 5 on the num pad returns the following object: {'vk': 65437, 'char': None, 'is_dead': False, 'combining': None, '_symbol': None}

I would have expected an object with its char set to '5'. I do not know if this is a bug or something I am not using correctly.

Other keys works fine for example typing 1 returns the following object: {'vk': None, 'char': '1', 'is_dead': False, 'combining': None, '_symbol': None}

Platform and pynput version Linux 5.4.0-136-generic #153-Ubuntu, pynput Version: 1.7.6 as well as the one of the git

To Reproduce Running keyboard-test.py results in:

$ python3 keyboard-test.py Press esc to exit =< Key.enter => <65437>5 =< <65437> => '1' 1=< '1'

AwesomeCronk commented 1 year ago

Can confirm I see this too. Numlock is enabled. I have debug script in one of my projects and noticed that it produces the output <65437> for numpad 5:

# This script just prints what each key is called

import sys, termios, time

from pynput import keyboard

run = True

def _onPress(key):
    print(key)

def _onRelease(key):
    global run
    if key == keyboard.Key.esc:
        run = False
        return False

# Modified version of `enable_echo` found at https://blog.hartwork.org/posts/disabling-terminal-echo-in-python/
def setEcho(value):
    iflag, oflag, cflag, lflag, ispeed, ospeed, cc = termios.tcgetattr(sys.stdin)

    if value: lflag |= termios.ECHO
    else: lflag &= ~termios.ECHO

    termios.tcsetattr(
        sys.stdin,
        termios.TCSANOW,
        [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
    )

def clearStdin():
    termios.tcflush(sys.stdin, termios.TCIFLUSH)
    # sys.stdin.flush()   # Doesn't seem to do anything

if __name__ == '__main__':
    print('Press keys to see what pynput shows them as. Hit Esc to exit.')
    try:
        setEcho(False)
        listener = keyboard.Listener(on_press=_onPress, on_release=_onRelease)
        listener.start()
        while run: time.sleep(0.1)
    finally:
        listener.stop()
        print('Listener stopped')
        clearStdin()
        setEcho(True)
        print('Echo reenabled')

I am on Ubuntu 20.04 x86_64, using pynput 1.7.6 with the xorg backend. All other numpad numbers work fine. If it's relevant my keyboard layout is standard US QWERTY.

Edios commented 1 year ago

Same problem on my side (With Manjaro). Saw similar post on stack overflow with same behavior: LINK

AwesomeCronk commented 1 year ago

I wonder does anyone see this on Windows or is it a keycode/map issue specific to Linux?

mglt commented 1 year ago

I am only using Linux, so I cannot tell if Windows has the same issue or not. Yours, Daniel

On Sun, Mar 12, 2023 at 3:51 PM AwesomeCronk @.***> wrote:

I wonder does anyone see this on Windows or is it a keycode/map issue specific to Linux?

— Reply to this email directly, view it on GitHub https://github.com/moses-palmer/pynput/issues/530#issuecomment-1465284377, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABSL7SUF5P53SDFWPEG72ELW3YZMRANCNFSM6AAAAAATUJD7RM . You are receiving this because you authored the thread.Message ID: @.***>

-- Daniel Migault Ericsson 8400 boulevard Decarie Montreal, QC H4P 2N2 Canada

Phone: +1 514-452-2160

moses-palmer commented 1 year ago

Thank you for your report.

I can confirm that I observe this behaviour as well. It appears that display.keycode_to_keysym returns KP_Begin for numpad 5. There is code to correct these values when numlock is active, but KP_Begin was not present in the list of codes to translate. By applying the fix below I can get numpad 5 to work on my system.

diff --git a/lib/pynput/keyboard/_xorg.py b/lib/pynput/keyboard/_xorg.py
index cfbc457..bbab3dd 100644
--- a/lib/pynput/keyboard/_xorg.py
+++ b/lib/pynput/keyboard/_xorg.py
@@ -528,6 +527,7 @@ class Listener(ListenerMixin, _base.Listener):
         KEYPAD_KEYS['KP_8']: KeyCode.from_char('8'),
         KEYPAD_KEYS['KP_9']: KeyCode.from_char('9'),
         KEYPAD_KEYS['KP_Add']: KeyCode.from_char('+'),
+        KEYPAD_KEYS['KP_Begin']: None,
         KEYPAD_KEYS['KP_Decimal']: KeyCode.from_char(','),
         KEYPAD_KEYS['KP_Delete']: Key.delete,
         KEYPAD_KEYS['KP_Divide']: KeyCode.from_char('/'),