Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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