Skip to content

Commit 1ecbe0b

Browse files
Merge 85a20d8 into a68e63c
2 parents a68e63c + 85a20d8 commit 1ecbe0b

6 files changed

Lines changed: 41 additions & 15 deletions

File tree

nvdaHelper/interfaces/nvdaControllerInternal/nvdaControllerInternal.idl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,9 @@ interface NvdaControllerInternal {
4747

4848
/**
4949
* Notifies NVDA that a character has been typed in this thread.
50-
* @param threadID the thread the layout change occured in
5150
* @param ch the character typed.
5251
*/
53-
error_status_t __stdcall typedCharacterNotify([in] const long threadID, [in] const wchar_t ch);
52+
error_status_t __stdcall typedCharacterNotify([in] const wchar_t ch);
5453

5554
/**
5655
* Notifies NVDA that text in the given rectangle (in screen coordinates), in the given window, has changed.

nvdaHelper/local/nvdaControllerInternal.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ error_status_t __stdcall nvdaControllerInternal_inputLangChangeNotify(const long
2424
return _nvdaControllerInternal_inputLangChangeNotify(threadID,hkl,layoutString);
2525
}
2626

27-
error_status_t(__stdcall *_nvdaControllerInternal_typedCharacterNotify)(const long, const wchar_t);
28-
error_status_t __stdcall nvdaControllerInternal_typedCharacterNotify(const long threadID, const wchar_t ch) {
29-
return _nvdaControllerInternal_typedCharacterNotify(threadID,ch);
27+
error_status_t(__stdcall *_nvdaControllerInternal_typedCharacterNotify)(const wchar_t);
28+
error_status_t __stdcall nvdaControllerInternal_typedCharacterNotify(const wchar_t ch) {
29+
return _nvdaControllerInternal_typedCharacterNotify(ch);
3030
}
3131

3232

nvdaHelper/remote/injection.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,14 +193,25 @@ DWORD WINAPI inprocMgrThreadFunc(LPVOID data) {
193193
// Even though we only registered for in-context winEvents, we may still receive some out-of-context events; e.g. console events.
194194
// Therefore, we must have a message loop.
195195
// Otherwise, any out-of-context events will cause major lag which increases over time.
196-
do {
197-
// Consume and handle all pending messages.
198-
MSG msg;
199-
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
200-
TranslateMessage(&msg);
201-
DispatchMessage(&msg);
196+
while(true) {
197+
const long handleCount=1;
198+
const long WAIT_PENDING_MESSAGES=WAIT_OBJECT_0+handleCount;
199+
DWORD res=MsgWaitForMultipleObjectsEx(handleCount,&nvdaUnregisteredEvent,INFINITE,QS_ALLINPUT,MWMO_ALERTABLE);
200+
if(res==(WAIT_PENDING_MESSAGES)) {
201+
// Consume and handle all pending messages.
202+
MSG msg;
203+
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
204+
TranslateMessage(&msg);
205+
DispatchMessage(&msg);
206+
}
207+
continue;
208+
} else if(res==WAIT_IO_COMPLETION) {
209+
// Woke for a queued APC function. Keep going.
210+
continue;
202211
}
203-
} while(MsgWaitForMultipleObjects(1,&nvdaUnregisteredEvent,FALSE,INFINITE,QS_ALLINPUT)==WAIT_OBJECT_0+1);
212+
// anything else (the registrationEvent was set, there was an error) means we need to stop.
213+
break;
214+
}
204215
nhAssert(inprocMgrThreadHandle);
205216
inprocThreadsLock.acquire();
206217
CloseHandle(inprocMgrThreadHandle);

nvdaHelper/remote/nvdaHelperRemote.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,7 @@ bool registerWindowsHook(int hookType, HOOKPROC hookProc);
6666
*/
6767
bool unregisterWindowsHook(int hookType, HOOKPROC hookProc);
6868

69+
// The handle for NVDA's inproc manager thread
70+
extern HANDLE inprocMgrThreadHandle;
71+
6972
#endif

nvdaHelper/remote/typedCharacter.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,21 @@ This license can be found at:
2121

2222
HWND typedCharacter_window=NULL;
2323

24+
void __stdcall typedCharacter_apcFunc(ULONG_PTR data) {
25+
nvdaControllerInternal_typedCharacterNotify(static_cast<wchar_t>(data));
26+
}
27+
2428
LRESULT CALLBACK typedCharacter_getMessageHook(int code, WPARAM wParam, LPARAM lParam) {
2529
static WPARAM lastCharacter=0;
2630
MSG* pmsg=(MSG*)lParam;
2731
if(pmsg->message==WM_KEYDOWN) {
2832
typedCharacter_window=pmsg->hwnd;
2933
lastCharacter=0;
3034
} else if((typedCharacter_window!=0)&&(pmsg->message==WM_CHAR)&&(pmsg->hwnd==typedCharacter_window)&&(pmsg->wParam!=lastCharacter)) {
31-
nvdaControllerInternal_typedCharacterNotify(GetCurrentThreadId(),static_cast<wchar_t>(pmsg->wParam));
35+
// Instruct NVDA's inproc manager thread to report the typed chracter to NVDA via rpc.
36+
// If we were to call the rpc function directly, it might cause a deadlock
37+
// if NvDA were to interact with this app's main thread while the rpc function was in progress.
38+
QueueUserAPC(typedCharacter_apcFunc, inprocMgrThreadHandle, static_cast<ULONG_PTR>(pmsg->wParam));
3239
lastCharacter=pmsg->wParam;
3340
}
3441
return 0;

source/NVDAHelper.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
import config
1414

1515
from ctypes import *
16+
from ctyps import (
17+
WINFUNCTYPE,
18+
c_long,
19+
c_wchar,
20+
)
1621
from ctypes.wintypes import *
1722
from comtypes import BSTR
1823
import winUser
@@ -394,8 +399,9 @@ def nvdaControllerInternal_inputLangChangeNotify(threadID,hkl,layoutString):
394399
queueHandler.queueFunction(queueHandler.eventQueue,ui.message,msg)
395400
return 0
396401

397-
@WINFUNCTYPE(c_long,c_long,c_wchar)
398-
def nvdaControllerInternal_typedCharacterNotify(threadID,ch):
402+
403+
@WINFUNCTYPE(c_long, c_wchar)
404+
def nvdaControllerInternal_typedCharacterNotify(ch):
399405
focus=api.getFocusObject()
400406
if focus.windowClassName!="ConsoleWindowClass":
401407
eventHandler.queueEvent("typedCharacter", focus, ch=ch)

0 commit comments

Comments
 (0)