Skip to content

Commit b035766

Browse files
authored
Merge 509c4e4 into a46d8d6
2 parents a46d8d6 + 509c4e4 commit b035766

30 files changed

Lines changed: 696 additions & 257 deletions

nvdaHelper/common/ia2utils.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This file is a part of the NVDA project.
33
URL: http://www.nvda-project.org/
4-
Copyright 2007-2019 NV Access Limited, Mozilla Corporation
4+
Copyright 2007-2021 NV Access Limited, Mozilla Corporation
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License version 2.0, as published by
77
the Free Software Foundation.
@@ -15,9 +15,21 @@ This license can be found at:
1515
#include <string>
1616
#include <map>
1717
#include "ia2utils.h"
18+
#include <ia2.h>
1819

1920
using namespace std;
2021

22+
bool fetchIA2Attributes(IAccessible2* pacc2, map<wstring, wstring>& attribsMap) {
23+
BSTR attribs = NULL;
24+
pacc2->get_attributes(&attribs);
25+
if (!attribs) {
26+
return false;
27+
}
28+
IA2AttribsToMap(attribs, attribsMap);
29+
SysFreeString(attribs);
30+
return true;
31+
}
32+
2133
void IA2AttribsToMap(const wstring &attribsString, map<wstring, wstring> &attribsMap) {
2234
wstring str, key;
2335
bool inEscape = false;

nvdaHelper/common/ia2utils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This file is a part of the NVDA project.
33
URL: http://www.nvda-project.org/
4-
Copyright 2007-2019 NV Access Limited, Mozilla Corporation
4+
Copyright 2007-2021 NV Access Limited, Mozilla Corporation
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License version 2.0, as published by
77
the Free Software Foundation.
@@ -21,6 +21,8 @@ This license can be found at:
2121
#include <memory>
2222
#include <ia2.h>
2323

24+
bool fetchIA2Attributes(IAccessible2* pacc2, std::map<std::wstring, std::wstring>& attribsMap);
25+
2426
/**
2527
* Convert an IAccessible2 attributes string to a map of attribute keys and values.
2628
* An IAccessible2 attributes string is of the form "name:value;name:value;...;"

nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.acf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This file is a part of the NVDA project.
33
URL: http://www.nvda-project.org/
4-
Copyright 2006-2010 NVDA contributers.
4+
Copyright 2006-2021 NV Access Limited, Leonard de Ruijter
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License version 2.0, as published by
77
the Free Software Foundation.
@@ -24,6 +24,7 @@ interface NvdaInProcUtils {
2424
[fault_status,comm_status] getActiveObject();
2525
[fault_status,comm_status] dumpOnCrash();
2626
[fault_status,comm_status] IA2Text_findContentDescendant();
27+
[fault_status,comm_status] getTextFromIAccessible();
2728
[fault_status,comm_status] outlook_getMAPIProp();
2829

2930
[fault_status,comm_status] excel_getCellInfos();

nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.idl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This file is a part of the NVDA project.
33
URL: http://www.nvda-project.org/
4-
Copyright 2006-2020 NV Access Limited, Leonard de Ruijter.
4+
Copyright 2006-2021 NV Access Limited, Leonard de Ruijter.
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License version 2.0, as published by
77
the Free Software Foundation.
@@ -15,7 +15,7 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
1515
cpp_quote("/*")
1616
cpp_quote("This file is a part of the NVDA project.")
1717
cpp_quote("URL: http://www.nvda-project.org/")
18-
cpp_quote("Copyright 2006-2020 NV Access Limited, Leonard de Ruijter.")
18+
cpp_quote("Copyright 2006-2021 NV Access Limited, Leonard de Ruijter.")
1919
cpp_quote("This program is free software: you can redistribute it and/or modify")
2020
cpp_quote("it under the terms of the GNU General Public License version 2.0, as published by")
2121
cpp_quote("the Free Software Foundation.")
@@ -74,6 +74,22 @@ interface NvdaInProcUtils {
7474

7575
error_status_t IA2Text_findContentDescendant([in] handle_t bindingHandle, [in] const unsigned long hwnd, [in] long parentID, [in] long what, [out] long* descendantID, [out] long* descendantOffset);
7676

77+
78+
cpp_quote("/* Actually maps to nvdaInProcUtils_getTextFromIAccessible")
79+
cpp_quote("*/")
80+
error_status_t getTextFromIAccessible(
81+
[in] handle_t bindingHandle,
82+
[in] const unsigned long hwnd,
83+
[in] long parentID,
84+
// Params for getTextFromIAccessible
85+
[out, string] BSTR* textBuf,
86+
[in, defaultvalue(FALSE)] const boolean useNewText,
87+
[in, defaultvalue(TRUE)] const boolean recurse,
88+
[in, defaultvalue(TRUE)] const boolean includeTopLevelText
89+
);
90+
91+
92+
7793
/*
7894
* Fetches the requested property from the given MAPIProp object.
7995
* @param threadID the threadID of the Outlook GUI thread where the MAPI object came from.

nvdaHelper/local/nvdaHelperLocal.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ EXPORTS
1212
nvdaInProcUtils_sysListView32_getColumnContent
1313
nvdaInProcUtils_dumpOnCrash
1414
nvdaInProcUtils_IA2Text_findContentDescendant
15+
nvdaInProcUtils_getTextFromIAccessible
1516
nvdaInProcUtils_getActiveObject
1617
nvdaInProcUtils_winword_expandToLine
1718
nvdaInProcUtils_winword_getTextInRange

nvdaHelper/readme.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,15 @@ When `fillVBuf` is called, it recursively descends through the child elements th
7171
`controlFieldNode`s or `textFieldNode`s for them.
7272
This code is responsible for interacting with the IA2 accessibility API, these calls should be minimised for
7373
performance reasons.
74+
75+
76+
### Overview
77+
78+
- NVDA's python code calls into the (`NVDAHelperLocal.dll` / `NVDAHelperLocalWin10.dll`).
79+
- Generated RPC Wrappers are called.
80+
- The RPC Wrappers call through to the "remote in-process DLL" (`nvdaHelperRemote.dll`)
81+
82+
#### Build notes
83+
IDL/ACF files are input to MSRPCStubs to generate headers in `build/<arch>`
84+
- See `MSRPCStubs` in `*scons*` files.
85+
- Note these set a prefix, making whole word searches for methods difficult.

nvdaHelper/remote/IA2Support.cpp

Lines changed: 101 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This file is a part of the NVDA project.
33
URL: http://www.nvda-project.org/
4-
Copyright 2006-2010 NVDA contributers.
4+
Copyright 2006-2021 NV Access Limited
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License version 2.0, as published by
77
the Free Software Foundation.
@@ -26,6 +26,8 @@ This license can be found at:
2626
#include <remote/nvdaInProcUtils.h>
2727
#include "COMProxyRegistration.h"
2828
#include "IA2Support.h"
29+
#include <atlcomcli.h>
30+
#include "textFromIAccessible.h"
2931

3032
using namespace std;
3133

@@ -251,26 +253,107 @@ bool findContentDescendant(IAccessible2* pacc2, long what, long* descendantID, l
251253
return foundDescendant;
252254
}
253255

256+
257+
CComPtr<IAccessible2> getIA2(const HWND hwnd, const long parentID) {
258+
VARIANT varChild;
259+
CComPtr<IAccessible> pacc;
260+
AccessibleObjectFromEvent(
261+
hwnd,
262+
OBJID_CLIENT,
263+
parentID,
264+
&pacc.p,
265+
&varChild
266+
);
267+
268+
if (!pacc) {
269+
return nullptr;
270+
};
271+
272+
CComQIPtr<IServiceProvider, &IID_IServiceProvider> pserv(pacc);
273+
if (!pserv) {
274+
return nullptr;
275+
}
276+
277+
CComPtr<IAccessible2> pacc2;
278+
{ // scoping for: ppvObject
279+
void** ppvObject = reinterpret_cast<void**>(&pacc2.p);
280+
pserv->QueryService(IID_IAccessible, IID_IAccessible2, ppvObject);
281+
}
282+
283+
return pacc2;
284+
}
285+
254286
error_status_t nvdaInProcUtils_IA2Text_findContentDescendant(handle_t bindingHandle, const unsigned long windowHandle, long parentID, long what, long* descendantID, long* descendantOffset) {
255-
HWND hwnd=(HWND)UlongToHandle(windowHandle);
287+
HWND hwnd = static_cast<HWND>(UlongToHandle(windowHandle));
256288
auto func=[&] {
257-
IAccessible* pacc=NULL;
258-
VARIANT varChild;
259-
AccessibleObjectFromEvent((HWND)hwnd,OBJID_CLIENT,parentID,&pacc,&varChild);
260-
if(!pacc) return;
261-
IAccessible2* pacc2=NULL;
262-
IServiceProvider* pserv=NULL;
263-
pacc->QueryInterface(IID_IServiceProvider,(void**)&pserv);
264-
pacc->Release();
265-
if(!pserv) return;
266-
pserv->QueryService(IID_IAccessible,IID_IAccessible2,(void**)&pacc2);
267-
pserv->Release();
268-
if(!pacc2) return;
269-
findContentDescendant(pacc2,what,descendantID,descendantOffset);
270-
pacc2->Release();
289+
auto pacc2 = getIA2(hwnd, parentID);
290+
if (!pacc2) {
291+
return;
292+
}
293+
findContentDescendant(pacc2, what, descendantID, descendantOffset);
271294
};
272-
if(!execInThread(GetWindowThreadProcessId(hwnd,NULL),func)) {
273-
LOG_DEBUGWARNING(L"Could not execute findContentDescendant in UI thread");
295+
296+
auto windowThreadProcId = GetWindowThreadProcessId(hwnd, nullptr);
297+
auto res = execInThread(windowThreadProcId, func);
298+
if(!res) {
299+
LOG_DEBUGWARNING(L"Could not execute findContentDescendant in UI thread");
274300
}
275301
return 0;
276302
}
303+
304+
305+
error_status_t nvdaInProcUtils_getTextFromIAccessible(
306+
handle_t bindingHandle,
307+
const unsigned long windowHandle,
308+
long parentID,
309+
// Params for getTextFromIAccessible
310+
BSTR* outBuf,
311+
const boolean useNewText,
312+
const boolean recurse,
313+
const boolean includeTopLevelText
314+
) {
315+
LOG_DEBUG(L"Called nvdaInProcUtils_getTextFromIAccessible");
316+
if (outBuf == nullptr) {
317+
LOG_ERROR(L"outBuff is null.");
318+
return 0;
319+
}
320+
HWND hwnd = static_cast<HWND>(UlongToHandle(windowHandle));
321+
auto func = [&] () -> void{
322+
auto pacc2 = getIA2(hwnd, parentID);
323+
if (!pacc2) {
324+
return;
325+
}
326+
wstring textBuf;
327+
const auto gotText = getTextFromIAccessible(
328+
textBuf,
329+
pacc2,
330+
useNewText,
331+
recurse,
332+
includeTopLevelText
333+
);
334+
if (!gotText) {
335+
LOG_DEBUGWARNING(L"Unable to get text.");
336+
return;
337+
}
338+
if (textBuf.empty()) {
339+
LOG_DEBUGWARNING(L"textBuf empty.");
340+
return;
341+
}
342+
auto copySize = size_t(std::numeric_limits<UINT>::max);
343+
if (copySize < textBuf.size()) {
344+
LOG_ERROR(L"Size of buffer larger than can be allocated with SysAllocStringLen, buffer will be truncated.");
345+
}
346+
else {
347+
copySize = textBuf.size();
348+
}
349+
*outBuf = SysAllocStringLen(textBuf.data(), UINT(copySize));
350+
return;
351+
};
352+
353+
auto windowThreadProcId = GetWindowThreadProcessId(hwnd, nullptr);
354+
auto res = execInThread(windowThreadProcId, func);
355+
if (!res) {
356+
LOG_DEBUGWARNING(L"Could not execute getTextFromIAccessible in UI thread");
357+
}
358+
return 0;
359+
}

0 commit comments

Comments
 (0)