Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions source/IAccessibleHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

from typing import Dict
import heapq
import itertools
import struct
Expand Down Expand Up @@ -575,6 +576,10 @@ def winEventCallback(handle,eventID,window,objectID,childID,threadID,timestamp):
window=tempWindow

windowClassName=winUser.getClassName(window)
if windowClassName == "ConsoleWindowClass":
# #10113: we need to use winEvents to track the real thread for console windows.
consoleWindowsToThreadIDs[window] = threadID

# Modern IME candidate list windows fire menu events which confuse us
# and can't be used properly in conjunction with input composition support.
if windowClassName=="Microsoft.IME.UIManager.CandidateWindow.Host" and eventID in MENU_EVENTIDS:
Expand Down Expand Up @@ -1102,3 +1107,13 @@ def isMarshalledIAccessible(IAccessibleObject):
windll.kernel32.GetModuleHandleExW(6,addr,byref(handle))
windll.kernel32.GetModuleFileNameW(handle,buf,1024)
return not buf.value.lower().endswith('oleacc.dll')


#: Maps from console windows (ConsoleWindowClass) to thread IDs
# Windows hacks GetWindowThreadProcessId to return the input thread of the first attached process in a console
# But NVDA really requires to know the actual thread the window was created in,
# I.e. inside conhost,
# In order to handle speaking of typed characters etc.
# winEventCallback adds these whenever it sees an event for ConsoleWindowClass windows,
# As winEvents always contain the true thread ID.
consoleWindowsToThreadIDs: Dict[int, int] = {}
11 changes: 11 additions & 0 deletions source/NVDAObjects/UIA/winConsoleUIA.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,17 @@ class WinConsoleUIA(KeyboardHandlerBasedTypedCharSupport):
#: the caret in consoles can take a while to move on Windows 10 1903 and later.
_caretMovementTimeoutMultiplier = 1.5

def _get_windowThreadID(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I think this should happen now, but I wonder whether we want a base class for console windows that the legacy and UIA impls inherit from.

# #10113: Windows forces the thread of console windows to match the thread of the first attached process.
# However, To correctly handle speaking of typed characters,
# NVDA really requires the real thread the window was created in,
# I.e. a thread inside conhost.
from IAccessibleHandler import consoleWindowsToThreadIDs
threadID = consoleWindowsToThreadIDs.get(self.windowHandle, 0)
if not threadID:
threadID = super().windowThreadID
return threadID

def _get_TextInfo(self):
"""Overriding _get_TextInfo and thus the TextInfo property
on NVDAObjects.UIA.UIA
Expand Down
11 changes: 11 additions & 0 deletions source/NVDAObjects/window/winConsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ def initOverlayClass(self):
if isinstance(self, KeyboardHandlerBasedTypedCharSupport):
self._supportsTextChange = False

def _get_windowThreadID(self):
# #10113: Windows forces the thread of console windows to match the thread of the first attached process.
# However, To correctly handle speaking of typed characters,
# NVDA really requires the real thread the window was created in,
# I.e. a thread inside conhost.
from IAccessibleHandler import consoleWindowsToThreadIDs
threadID = consoleWindowsToThreadIDs.get(self.windowHandle, 0)
if not threadID:
threadID = super().windowThreadID
return threadID

def _get_TextInfo(self):
consoleObject=winConsoleHandler.consoleObject
if consoleObject and self.windowHandle == consoleObject.windowHandle:
Expand Down