-
-
Notifications
You must be signed in to change notification settings - Fork 614
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
Speak typed characters in UWP apps on Windows 10 RS2 and above #6631
Changes from 5 commits
ad5cfc9
19e5352
41e23ec
73fd374
e1a6ef7
0a7b024
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,11 +7,15 @@ | |
|
||
"""Keyboard support""" | ||
|
||
import ctypes | ||
import sys | ||
import time | ||
import re | ||
import wx | ||
import winVersion | ||
import winUser | ||
import vkCodes | ||
import eventHandler | ||
import speech | ||
import ui | ||
from keyLabels import localizedKeyLabels | ||
|
@@ -73,6 +77,7 @@ def isNVDAModifierKey(vkCode,extended): | |
def internal_keyDownEvent(vkCode,scanCode,extended,injected): | ||
"""Event called by winInputHook when it receives a keyDown. | ||
""" | ||
gestureExecuted=False | ||
try: | ||
global lastNVDAModifier, lastNVDAModifierReleaseTime, bypassNVDAModifier, passKeyThroughCount, lastPassThroughKeyDown, currentModifiers, keyCounter, stickyNVDAModifier, stickyNVDAModifierLocked | ||
# Injected keys should be ignored in some cases. | ||
|
@@ -146,6 +151,7 @@ def internal_keyDownEvent(vkCode,scanCode,extended,injected): | |
|
||
try: | ||
inputCore.manager.executeGesture(gesture) | ||
gestureExecuted=True | ||
trappedKeys.add(keyCode) | ||
if canModifiersPerformAction(gesture.generalizedModifiers): | ||
# #3472: These modifiers can perform an action if pressed alone | ||
|
@@ -162,6 +168,22 @@ def internal_keyDownEvent(vkCode,scanCode,extended,injected): | |
return False | ||
except: | ||
log.error("internal_keyDownEvent", exc_info=True) | ||
finally: | ||
# #6017: handle typed characters for UWP apps in Win10 RS2 and above where we can't detect typed characters in-process | ||
# This code must be in the 'finally' block as code above returns in several places yet we still want to execute this particular code. | ||
focus=api.getFocusObject() | ||
if winVersion.winVersion.build>=14986 and not gestureExecuted and not isNVDAModifierKey(vkCode,extended) and not vkCode in KeyboardInputGesture.NORMAL_MODIFIER_KEYS and focus.windowClassName.startswith('Windows.UI.Core'): | ||
keyStates=(ctypes.c_byte*256)() | ||
for k in xrange(256): | ||
keyStates[k]=ctypes.windll.user32.GetKeyState(k) | ||
charBuf=ctypes.create_unicode_buffer(5) | ||
hkl=ctypes.windll.user32.GetKeyboardLayout(focus.windowThreadID) | ||
# In previous Windows builds, calling ToUnicodeEx would destroy keyboard buffer state and therefore cause the app to not produce the right WM_CHAR message. | ||
# However, ToUnicodeEx now can take a new flag of 0x4, which stops it from destroying keyboard state, thus allowing us to safely call it here. | ||
res=ctypes.windll.user32.ToUnicodeEx(vkCode,scanCode,keyStates,len(charBuf),0x4,hkl) | ||
if res>0: | ||
for ch in charBuf[:res]: | ||
eventHandler.queueEvent("typedCharacter",focus,ch=ch) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this saying there can be multiple separate characters? I know there are languages where a single key press produces a conjunct Unicode character sequence (e.g. Tamil), but we probably actually want that to be handled as one character. We can't do that with WM_CHAR right now, but is there a reason we shouldn't do this here since we can? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have certainly seen it produce at least 2 characters yes. For instance, if a dead key is hit, followed by a character that is not compatible with a dead key, then you get a char for the dead key (say ^) and also the actual character. |
||
return True | ||
|
||
def internal_keyUpEvent(vkCode,scanCode,extended,injected): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth commenting why we do this in the finally block; i.e. because we return early in several places but we still want this to be executed.