Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should it be this awkward to have a user define a hotkey? #47

Closed
Hyphen-ated opened this issue Feb 3, 2017 · 9 comments
Closed

Should it be this awkward to have a user define a hotkey? #47

Hyphen-ated opened this issue Feb 3, 2017 · 9 comments

Comments

@Hyphen-ated
Copy link

Hyphen-ated commented Feb 3, 2017

I'm writing an application where the user can define their own global hotkeys. The interface for this is: they click a button, it says "press the key you want", they press it.

This was slightly more complicated to accomplish using "keyboard" than I expected it to be. Here is some simplified example code:

import keyboard
my_key = None

def record_key(event):
    global my_key
    if event.event_type == keyboard.KEY_DOWN:
        my_key = event.scan_code

print "select a hotkey"
callback = keyboard.hook(record_key)
while my_key is None:
    pass
keyboard.unhook(callback)
print "selected key code: " + str(my_key)

def fn():
    print "you pressed it"
keyboard.hook_key(int(my_key), keydown_callback=fn)

while True:
    pass

Am I missing something that makes this simpler? I expected to find something like, say, "keyboard.read_key()" that blocks until they press a key and returns what key they pressed.

I also found it surprising that if I don't cast my_key to int on that third-to-last line, I receive an error like

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\keyboard\_generic.py", line 23, in invoke_handlers
    if handler(event):
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 350, in handler
    if not matches(event, key):
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 139, in matches
    normalized = _normalize_name(name)
  File "C:\Python27\lib\site-packages\keyboard\_keyboard_event.py", line 215, in normalize_name
    raise ValueError('Can only normalize string names. Unexpected '+ repr(name))
ValueError: Can only normalize string names. Unexpected 30L

(30L is what it says if I press 'a', since its scancode is 30)
Shouldn't the library be able to receive a scancode back as the same kind of datatype it gave to me?

(I'm using the scancode and not the name because the name is reported as "unknown" for many some keys, and incorrectly for others. like my left ctrl and left alt both show as having "right" in their name instead of left)

@boppreh
Copy link
Owner

boppreh commented Feb 4, 2017

I expected to find something like, say, "keyboard.read_key()" that blocks until they press a key and returns what key they pressed.

That's a very good request. I think the existing wait function is perfect for that, but a read_key alias wouldn't hurt. I'll post here when this gets implemented.

I also found it surprising that if I don't cast my_key to int on that third-to-last line

That's a bug. Thanks for reporting.


By the way, using while ...: pass is called "busy waiting" and is usually frowned upon because the CPU is running at 100% while it waits. Fans speed up, notebook batteries are trashed, etc. You can use locks and queues for that, or at least add a sleep inside the loop instead of "pass". Take a look at the source code for the wait function to see an example of more efficient waiting.

@boppreh
Copy link
Owner

boppreh commented Feb 4, 2017

  • wait was already overloaded to wait forever when not given a hotkey, so I had to create a new function read_key.
  • long values in Python2 no longer create type errors when used in hotkeys.
  • Windows should now report left and right modifiers correctly. Not sure about the unknown keys though, could you give more details?

As for your previously awkward code, it should be possible to reimplement this way:

import keyboard
print('Enter the key to be registered')
hotkey = keyboard.read_key().scan_code
def fn():
    print('you pressed it')
keyboard.add_hotkey(hotkey, fn)

keyboard.wait('esc')

Does this look ok to you?

@Hyphen-ated
Copy link
Author

Yes, that looks great, thanks.

On further inspection, I was only seeing the F13 key show up as "unknown", but it was the one I was actually trying to use in the application I'm writing, so I was testing it more than other keys.

(I have my left windows key bound to F13 using a registry script from this website: http://www.grismar.net/ventrilocapsfix/ )

@boppreh
Copy link
Owner

boppreh commented Feb 4, 2017

Can you give a try on the latest version and tell me if it's reporting as F13 correctly?

@Hyphen-ated
Copy link
Author

Hyphen-ated commented Feb 4, 2017

Yes, F13 works now.
I tested every key I have with the following program:

import keyboard
def info(event):
    print event.name + " " + event.event_type
keyboard.hook(info)
keyboard.wait("esc")

When I press and release left alt, I get 4 events instead of 2: down, up, down, up. They are correctly "left" instead of "right" now, though. I think I saw this happen on 0.9.10, but I blamed it on a jittery finger or piece of keyboard debris.
When I press right alt, it's reported as left alt. I do not think this was happening on 0.9.10. (the opposite was happening)

Every other key appears to be working correctly.

@boppreh
Copy link
Owner

boppreh commented Feb 4, 2017

Hmm. I don't have a right alt to test (only alt+gr). Left/right ctrl/shift are working as expected, though, in both the built-in keyboard and an external one.

Also I can't reproduce the double alt issue at all, in either Python2 or Python3. This is really weird.

Did you modify you registry to alter keys in any other way?

@Hyphen-ated
Copy link
Author

I have two of my media keys reymapped to volume up and volume down, and I have capslock mapped to esc, which is being detected correctly.

@boppreh
Copy link
Owner

boppreh commented Feb 4, 2017

I just tested on linux too, and everything seems working, though some keys don't report side (e.g. "ctrl" instead of "left ctrl").

To be honest I have absolutely no idea why this is happening, or event how to debug it. There's only one place that KeyboardEvents are created, and that's inside the Windows low level keyboard hook. If the alt is being reported more than once, it's because the hook is being invoked more than once, and that's indistinguishable from two separate events. I'm sorry, but I don't think I can fix this problem at the moment.

I'm going to close this issue, as the original problem was solved (we now have read_key). If the right-alt problems persist, please do create a new one with as much information as you can. Or email me, or continue posting here. I'll be read and reply anyway.

And thank you for the previous reports. This sort of feedback is highly appreciated.

@boppreh boppreh closed this as completed Feb 4, 2017
@boppreh
Copy link
Owner

boppreh commented Feb 18, 2018

Note for future visitors: the library now includes a keyboard.read_hotkey() function that returns complex hotkeys, such as "ctrl+shift+a".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants