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. if injected and (ignoreInjected or not config.conf['keyboard']['handleInjectedKeys']): return True keyCode = (vkCode, extended) if passKeyThroughCount >= 0: # We're passing keys through. if lastPassThroughKeyDown != keyCode: # Increment the pass key through count. # We only do this if this isn't a repeat of the previous key down, as we don't receive key ups for repeated key downs. passKeyThroughCount += 1 lastPassThroughKeyDown = keyCode return True keyCounter += 1 stickyKeysFlags = winUser.getSystemStickyKeys().dwFlags if stickyNVDAModifier and not stickyKeysFlags & winUser.SKF_STICKYKEYSON: # Sticky keys has been disabled, # so clear the sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None stickyNVDAModifierLocked = False gesture = KeyboardInputGesture(currentModifiers, vkCode, scanCode, extended) if not (stickyKeysFlags & winUser.SKF_STICKYKEYSON) and ( bypassNVDAModifier or (keyCode == lastNVDAModifier and lastNVDAModifierReleaseTime and time.time() - lastNVDAModifierReleaseTime < 0.5)): # The user wants the key to serve its normal function instead of acting as an NVDA modifier key. # There may be key repeats, so ensure we do this until they stop. bypassNVDAModifier = True gesture.isNVDAModifierKey = False lastNVDAModifierReleaseTime = None if gesture.isNVDAModifierKey: lastNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_STICKYKEYSON: if keyCode == stickyNVDAModifier: if stickyKeysFlags & winUser.SKF_TRISTATE and not stickyNVDAModifierLocked: # The NVDA modifier is being locked. stickyNVDAModifierLocked = True if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) return False else: # The NVDA modifier is being unlatched/unlocked. stickyNVDAModifier = None stickyNVDAModifierLocked = False if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(496, 60) return False else: # The NVDA modifier is being latched. if stickyNVDAModifier: # Clear the previous sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifierLocked = False stickyNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) else: # Another key was pressed after the last NVDA modifier key, so it should not be passed through on the next press. lastNVDAModifier = None if gesture.isModifier: if gesture.speechEffectWhenExecuted in ( gesture.SPEECHEFFECT_PAUSE, gesture.SPEECHEFFECT_RESUME ) and keyCode in currentModifiers: # Ignore key repeats for the pause speech key to avoid speech stuttering as it continually pauses and resumes. return True currentModifiers.add(keyCode) elif stickyNVDAModifier and not stickyNVDAModifierLocked: # A non-modifier was pressed, so unlatch the NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None try: inputCore.manager.executeGesture(gesture) gestureExecuted = True trappedKeys.add(keyCode) if canModifiersPerformAction(gesture.generalizedModifiers): # #3472: These modifiers can perform an action if pressed alone # and we've just consumed the main key. # Send special reserved vkcode (0xff) to at least notify the app's key state that something happendd. # This allows alt and windows to be bound to scripts and # stops control+shift from switching keyboard layouts in cursorManager selection scripts. KeyboardInputGesture((), 0xff, 0, False).send() return False except inputCore.NoInputGestureAction: if gesture.isNVDAModifierKey: # Never pass the NVDA modifier key to the OS. trappedKeys.add(keyCode) 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, charBuf, len(charBuf), 0x4, hkl) if res > 0: for ch in charBuf[:res]: eventHandler.queueEvent("typedCharacter", focus, ch=ch) #nvdajp begin if config.conf["keyboard"]["nvdajpEnableKeyEvents"]: from NVDAObjects import inputComposition inputComposition.reportKeyDownEvent(gesture) #nvdajp end return True
def internal_keyDownEvent(vkCode, scanCode, extended, injected): """Event called by winInputHook when it receives a keyDown. """ try: global lastNVDAModifier, lastNVDAModifierReleaseTime, bypassNVDAModifier, passKeyThroughCount, lastPassThroughKeyDown, currentModifiers, keyCounter, stickyNVDAModifier, stickyNVDAModifierLocked # Injected keys should be ignored in some cases. if injected and (ignoreInjected or not config.conf['keyboard']['handleInjectedKeys']): return True keyCode = (vkCode, extended) if passKeyThroughCount >= 0: # We're passing keys through. if lastPassThroughKeyDown != keyCode: # Increment the pass key through count. # We only do this if this isn't a repeat of the previous key down, as we don't receive key ups for repeated key downs. passKeyThroughCount += 1 lastPassThroughKeyDown = keyCode return True keyCounter += 1 stickyKeysFlags = winUser.getSystemStickyKeys().dwFlags if stickyNVDAModifier and not stickyKeysFlags & winUser.SKF_STICKYKEYSON: # Sticky keys has been disabled, # so clear the sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None stickyNVDAModifierLocked = False gesture = KeyboardInputGesture(currentModifiers, vkCode, scanCode, extended) if not (stickyKeysFlags & winUser.SKF_STICKYKEYSON) and ( bypassNVDAModifier or (keyCode == lastNVDAModifier and lastNVDAModifierReleaseTime and time.time() - lastNVDAModifierReleaseTime < 0.5)): # The user wants the key to serve its normal function instead of acting as an NVDA modifier key. # There may be key repeats, so ensure we do this until they stop. bypassNVDAModifier = True gesture.isNVDAModifierKey = False lastNVDAModifierReleaseTime = None if gesture.isNVDAModifierKey: lastNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_STICKYKEYSON: if keyCode == stickyNVDAModifier: if stickyKeysFlags & winUser.SKF_TRISTATE and not stickyNVDAModifierLocked: # The NVDA modifier is being locked. stickyNVDAModifierLocked = True if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) return False else: # The NVDA modifier is being unlatched/unlocked. stickyNVDAModifier = None stickyNVDAModifierLocked = False if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(496, 60) return False else: # The NVDA modifier is being latched. if stickyNVDAModifier: # Clear the previous sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifierLocked = False stickyNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) else: # Another key was pressed after the last NVDA modifier key, so it should not be passed through on the next press. lastNVDAModifier = None if gesture.isModifier: if gesture.speechEffectWhenExecuted in ( gesture.SPEECHEFFECT_PAUSE, gesture.SPEECHEFFECT_RESUME ) and keyCode in currentModifiers: # Ignore key repeats for the pause speech key to avoid speech stuttering as it continually pauses and resumes. return True currentModifiers.add(keyCode) elif stickyNVDAModifier and not stickyNVDAModifierLocked: # A non-modifier was pressed, so unlatch the NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None try: inputCore.manager.executeGesture(gesture) trappedKeys.add(keyCode) if canModifiersPerformAction(gesture.generalizedModifiers): # #3472: These modifiers can perform an action if pressed alone # and we've just consumed the main key. # Send special reserved vkcode (0xff) to at least notify the app's key state that something happendd. # This allows alt and windows to be bound to scripts and # stops control+shift from switching keyboard layouts in cursorManager selection scripts. KeyboardInputGesture((), 0xff, 0, False).send() return False except inputCore.NoInputGestureAction: if gesture.isNVDAModifierKey: # Never pass the NVDA modifier key to the OS. trappedKeys.add(keyCode) return False except: log.error("internal_keyDownEvent", exc_info=True) #nvdajp begin if config.conf["keyboard"]["nvdajpEnableKeyEvents"]: from NVDAObjects import inputComposition inputComposition.reportKeyDownEvent(gesture) #nvdajp end return True
def internal_keyDownEvent(vkCode, scanCode, extended, injected): """Event called by winInputHook when it receives a keyDown. """ try: global lastNVDAModifier, lastNVDAModifierReleaseTime, bypassNVDAModifier, passKeyThroughCount, lastPassThroughKeyDown, currentModifiers, keyCounter, stickyNVDAModifier, stickyNVDAModifierLocked # Injected keys should be ignored in some cases. if ignoreInjected and injected: return True keyCode = (vkCode, extended) if passKeyThroughCount >= 0: # We're passing keys through. if lastPassThroughKeyDown != keyCode: # Increment the pass key through count. # We only do this if this isn't a repeat of the previous key down, as we don't receive key ups for repeated key downs. passKeyThroughCount += 1 lastPassThroughKeyDown = keyCode return True keyCounter += 1 stickyKeysFlags = winUser.getSystemStickyKeys().dwFlags if stickyNVDAModifier and not stickyKeysFlags & winUser.SKF_STICKYKEYSON: # Sticky keys has been disabled, # so clear the sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None stickyNVDAModifierLocked = False gesture = KeyboardInputGesture(currentModifiers, vkCode, scanCode, extended) if not (stickyKeysFlags & winUser.SKF_STICKYKEYSON) and ( bypassNVDAModifier or (keyCode == lastNVDAModifier and lastNVDAModifierReleaseTime and time.time() - lastNVDAModifierReleaseTime < 0.5)): # The user wants the key to serve its normal function instead of acting as an NVDA modifier key. # There may be key repeats, so ensure we do this until they stop. bypassNVDAModifier = True gesture.isNVDAModifierKey = False lastNVDAModifierReleaseTime = None if gesture.isNVDAModifierKey: lastNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_STICKYKEYSON: if keyCode == stickyNVDAModifier: if stickyKeysFlags & winUser.SKF_TRISTATE and not stickyNVDAModifierLocked: # The NVDA modifier is being locked. stickyNVDAModifierLocked = True if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) return False else: # The NVDA modifier is being unlatched/unlocked. stickyNVDAModifier = None stickyNVDAModifierLocked = False if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(496, 60) return False else: # The NVDA modifier is being latched. if stickyNVDAModifier: # Clear the previous sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifierLocked = False stickyNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) else: # Another key was pressed after the last NVDA modifier key, so it should not be passed through on the next press. lastNVDAModifier = None if gesture.isModifier: if gesture.speechEffectWhenExecuted in ( gesture.SPEECHEFFECT_PAUSE, gesture.SPEECHEFFECT_RESUME ) and keyCode in currentModifiers: # Ignore key repeats for the pause speech key to avoid speech stuttering as it continually pauses and resumes. return True currentModifiers.add(keyCode) elif stickyNVDAModifier and not stickyNVDAModifierLocked: # A non-modifier was pressed, so unlatch the NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None try: inputCore.manager.executeGesture(gesture) trappedKeys.add(keyCode) return False except inputCore.NoInputGestureAction: if gesture.isNVDAModifierKey: # Never pass the NVDA modifier key to the OS. trappedKeys.add(keyCode) return False except: log.error("internal_keyDownEvent", exc_info=True) return True
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. if injected and (ignoreInjected or not config.conf['keyboard']['handleInjectedKeys']): return True keyCode = (vkCode, extended) if passKeyThroughCount >= 0: # We're passing keys through. if lastPassThroughKeyDown != keyCode: # Increment the pass key through count. # We only do this if this isn't a repeat of the previous key down, as we don't receive key ups for repeated key downs. passKeyThroughCount += 1 lastPassThroughKeyDown = keyCode return True keyCounter += 1 stickyKeysFlags = winUser.getSystemStickyKeys().dwFlags if stickyNVDAModifier and not stickyKeysFlags & winUser.SKF_STICKYKEYSON: # Sticky keys has been disabled, # so clear the sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None stickyNVDAModifierLocked = False gesture = KeyboardInputGesture(currentModifiers, vkCode, scanCode, extended) if not (stickyKeysFlags & winUser.SKF_STICKYKEYSON) and (bypassNVDAModifier or (keyCode == lastNVDAModifier and lastNVDAModifierReleaseTime and time.time() - lastNVDAModifierReleaseTime < 0.5)): # The user wants the key to serve its normal function instead of acting as an NVDA modifier key. # There may be key repeats, so ensure we do this until they stop. bypassNVDAModifier = True gesture.isNVDAModifierKey = False lastNVDAModifierReleaseTime = None if gesture.isNVDAModifierKey: lastNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_STICKYKEYSON: if keyCode == stickyNVDAModifier: if stickyKeysFlags & winUser.SKF_TRISTATE and not stickyNVDAModifierLocked: # The NVDA modifier is being locked. stickyNVDAModifierLocked = True if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) return False else: # The NVDA modifier is being unlatched/unlocked. stickyNVDAModifier = None stickyNVDAModifierLocked = False if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(496, 60) return False else: # The NVDA modifier is being latched. if stickyNVDAModifier: # Clear the previous sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifierLocked = False stickyNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) else: # Another key was pressed after the last NVDA modifier key, so it should not be passed through on the next press. lastNVDAModifier = None if gesture.isModifier: if gesture.speechEffectWhenExecuted in (gesture.SPEECHEFFECT_PAUSE, gesture.SPEECHEFFECT_RESUME) and keyCode in currentModifiers: # Ignore key repeats for the pause speech key to avoid speech stuttering as it continually pauses and resumes. return True currentModifiers.add(keyCode) elif stickyNVDAModifier and not stickyNVDAModifierLocked: # A non-modifier was pressed, so unlatch the NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None try: inputCore.manager.executeGesture(gesture) gestureExecuted=True trappedKeys.add(keyCode) if canModifiersPerformAction(gesture.generalizedModifiers): # #3472: These modifiers can perform an action if pressed alone # and we've just consumed the main key. # Send special reserved vkcode (0xff) to at least notify the app's key state that something happendd. # This allows alt and windows to be bound to scripts and # stops control+shift from switching keyboard layouts in cursorManager selection scripts. KeyboardInputGesture((),0xff,0,False).send() return False except inputCore.NoInputGestureAction: if gesture.isNVDAModifierKey: # Never pass the NVDA modifier key to the OS. trappedKeys.add(keyCode) return False except: log.error("internal_keyDownEvent", exc_info=True) finally: # #6017: handle typed characters 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 ( # This is only possible in Windows 10 RS2 and above winVersion.winVersion.build>=14986 # And we only want to do this if the gesture did not result in an executed action and not gestureExecuted # and not if this gesture is a modifier key and not isNVDAModifierKey(vkCode,extended) and not vkCode in KeyboardInputGesture.NORMAL_MODIFIER_KEYS and ( # Either of # We couldn't inject in-process, and its not a console window (console windows have their own specific typed character support) (not focus.appModule.helperLocalBindingHandle and focus.windowClassName!='ConsoleWindowClass') # or the focus is within a UWP app, where WM_CHAR never gets sent or 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,charBuf,len(charBuf),0x4,hkl) if res>0: for ch in charBuf[:res]: eventHandler.queueEvent("typedCharacter",focus,ch=ch) return True
def internal_keyDownEvent(vkCode,scanCode,extended,injected): """Event called by winInputHook when it receives a keyDown. """ try: global lastNVDAModifier, lastNVDAModifierReleaseTime, bypassNVDAModifier, passKeyThroughCount, lastPassThroughKeyDown, currentModifiers, keyCounter, stickyNVDAModifier, stickyNVDAModifierLocked # Injected keys should be ignored in some cases. if ignoreInjected and injected: return True keyCode = (vkCode, extended) if passKeyThroughCount >= 0: # We're passing keys through. if lastPassThroughKeyDown != keyCode: # Increment the pass key through count. # We only do this if this isn't a repeat of the previous key down, as we don't receive key ups for repeated key downs. passKeyThroughCount += 1 lastPassThroughKeyDown = keyCode return True keyCounter += 1 stickyKeysFlags = winUser.getSystemStickyKeys().dwFlags if stickyNVDAModifier and not stickyKeysFlags & winUser.SKF_STICKYKEYSON: # Sticky keys has been disabled, # so clear the sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None stickyNVDAModifierLocked = False gesture = KeyboardInputGesture(currentModifiers, vkCode, scanCode, extended) if not (stickyKeysFlags & winUser.SKF_STICKYKEYSON) and (bypassNVDAModifier or (keyCode == lastNVDAModifier and lastNVDAModifierReleaseTime and time.time() - lastNVDAModifierReleaseTime < 0.5)): # The user wants the key to serve its normal function instead of acting as an NVDA modifier key. # There may be key repeats, so ensure we do this until they stop. bypassNVDAModifier = True gesture.isNVDAModifierKey = False lastNVDAModifierReleaseTime = None if gesture.isNVDAModifierKey: lastNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_STICKYKEYSON: if keyCode == stickyNVDAModifier: if stickyKeysFlags & winUser.SKF_TRISTATE and not stickyNVDAModifierLocked: # The NVDA modifier is being locked. stickyNVDAModifierLocked = True if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) return False else: # The NVDA modifier is being unlatched/unlocked. stickyNVDAModifier = None stickyNVDAModifierLocked = False if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(496, 60) return False else: # The NVDA modifier is being latched. if stickyNVDAModifier: # Clear the previous sticky NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifierLocked = False stickyNVDAModifier = keyCode if stickyKeysFlags & winUser.SKF_AUDIBLEFEEDBACK: tones.beep(1984, 60) else: # Another key was pressed after the last NVDA modifier key, so it should not be passed through on the next press. lastNVDAModifier = None if gesture.isModifier: if gesture.speechEffectWhenExecuted in (gesture.SPEECHEFFECT_PAUSE, gesture.SPEECHEFFECT_RESUME) and keyCode in currentModifiers: # Ignore key repeats for the pause speech key to avoid speech stuttering as it continually pauses and resumes. return True currentModifiers.add(keyCode) elif stickyNVDAModifier and not stickyNVDAModifierLocked: # A non-modifier was pressed, so unlatch the NVDA modifier. currentModifiers.discard(stickyNVDAModifier) stickyNVDAModifier = None try: inputCore.manager.executeGesture(gesture) trappedKeys.add(keyCode) if canModifiersPerformAction(gesture.generalizedModifiers): # #3472: These modifiers can perform an action if pressed alone # and we've just consumed the main key. # Send special reserved vkcode (0xff) to at least notify the app's key state that something happendd. # This allows alt and windows to be bound to scripts and # stops control+shift from switching keyboard layouts in cursorManager selection scripts. KeyboardInputGesture((),0xff,0,False).send() return False except inputCore.NoInputGestureAction: if gesture.isNVDAModifierKey: # Never pass the NVDA modifier key to the OS. trappedKeys.add(keyCode) return False except: log.error("internal_keyDownEvent", exc_info=True) return True