зеркало из https://github.com/mozilla/gecko-dev.git
Bug 591874 - windows screen readers are broken due to post-130078 changes in the native widget structure, r=marcoz, davidb, a=blocking
This commit is contained in:
Родитель
a554f1f1f7
Коммит
67cc22e9ac
|
@ -93,7 +93,7 @@ nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull;
|
||||||
nsDocAccessible::
|
nsDocAccessible::
|
||||||
nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
|
nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
|
||||||
nsIWeakReference *aShell) :
|
nsIWeakReference *aShell) :
|
||||||
nsHyperTextAccessibleWrap(aRootContent, aShell), mWnd(nsnull),
|
nsHyperTextAccessibleWrap(aRootContent, aShell),
|
||||||
mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE)
|
mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE)
|
||||||
{
|
{
|
||||||
// XXX aaronl should we use an algorithm for the initial cache size?
|
// XXX aaronl should we use an algorithm for the initial cache size?
|
||||||
|
@ -103,17 +103,6 @@ nsDocAccessible::
|
||||||
if (!mDocument)
|
if (!mDocument)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Initialize mWnd
|
|
||||||
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
|
|
||||||
nsIViewManager* vm = shell->GetViewManager();
|
|
||||||
if (vm) {
|
|
||||||
nsCOMPtr<nsIWidget> widget;
|
|
||||||
vm->GetRootWidget(getter_AddRefs(widget));
|
|
||||||
if (widget) {
|
|
||||||
mWnd = widget->GetNativeData(NS_NATIVE_WINDOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsAccDocManager creates document accessible when scrollable frame is
|
// nsAccDocManager creates document accessible when scrollable frame is
|
||||||
// available already, it should be safe time to add scroll listener.
|
// available already, it should be safe time to add scroll listener.
|
||||||
AddScrollListener();
|
AddScrollListener();
|
||||||
|
@ -473,7 +462,8 @@ NS_IMETHODIMP nsDocAccessible::GetNameSpaceURIForID(PRInt16 aNameSpaceID, nsAStr
|
||||||
|
|
||||||
NS_IMETHODIMP nsDocAccessible::GetWindowHandle(void **aWindow)
|
NS_IMETHODIMP nsDocAccessible::GetWindowHandle(void **aWindow)
|
||||||
{
|
{
|
||||||
*aWindow = mWnd;
|
NS_ENSURE_ARG_POINTER(aWindow);
|
||||||
|
*aWindow = GetNativeWindow();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1335,6 +1325,20 @@ nsDocAccessible::HandleAccEvent(AccEvent* aAccEvent)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Public members
|
// Public members
|
||||||
|
|
||||||
|
void*
|
||||||
|
nsDocAccessible::GetNativeWindow() const
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
|
||||||
|
nsIViewManager* vm = shell->GetViewManager();
|
||||||
|
if (vm) {
|
||||||
|
nsCOMPtr<nsIWidget> widget;
|
||||||
|
vm->GetRootWidget(getter_AddRefs(widget));
|
||||||
|
if (widget)
|
||||||
|
return widget->GetNativeData(NS_NATIVE_WINDOW);
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
nsAccessible*
|
nsAccessible*
|
||||||
nsDocAccessible::GetCachedAccessibleInSubtree(void* aUniqueID)
|
nsDocAccessible::GetCachedAccessibleInSubtree(void* aUniqueID)
|
||||||
{
|
{
|
||||||
|
|
|
@ -141,6 +141,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void MarkAsLoaded() { mIsLoaded = PR_TRUE; }
|
void MarkAsLoaded() { mIsLoaded = PR_TRUE; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a native window handler or pointer depending on platform.
|
||||||
|
*/
|
||||||
|
virtual void* GetNativeWindow() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the parent document.
|
* Return the parent document.
|
||||||
*/
|
*/
|
||||||
|
@ -363,7 +368,6 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsAccessibleHashtable mAccessibleCache;
|
nsAccessibleHashtable mAccessibleCache;
|
||||||
|
|
||||||
void *mWnd;
|
|
||||||
nsCOMPtr<nsIDocument> mDocument;
|
nsCOMPtr<nsIDocument> mDocument;
|
||||||
nsCOMPtr<nsITimer> mScrollWatchTimer;
|
nsCOMPtr<nsITimer> mScrollWatchTimer;
|
||||||
PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
|
PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
|
||||||
|
|
|
@ -594,8 +594,12 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||||
|
|
||||||
nsAccessibleWrap *accWrap = static_cast<nsAccessibleWrap*>(mGeckoAccessible);
|
nsAccessibleWrap *accWrap = static_cast<nsAccessibleWrap*>(mGeckoAccessible);
|
||||||
|
|
||||||
|
// Get a pointer to the native window (NSWindow) we reside in.
|
||||||
NSWindow *nativeWindow = nil;
|
NSWindow *nativeWindow = nil;
|
||||||
accWrap->GetNativeWindow ((void**)&nativeWindow);
|
nsDocAccessible* docAcc = accWrap->GetDocAccessible();
|
||||||
|
if (docAcc)
|
||||||
|
nativeWindow = static_cast<NSWindow*>(docAcc->GetNativeWindow());
|
||||||
|
|
||||||
NSAssert1(nativeWindow, @"Could not get native window for %@", self);
|
NSAssert1(nativeWindow, @"Could not get native window for %@", self);
|
||||||
return nativeWindow;
|
return nativeWindow;
|
||||||
|
|
|
@ -72,9 +72,6 @@ class nsAccessibleWrap : public nsAccessible
|
||||||
// right type for this accessible's associated native object.
|
// right type for this accessible's associated native object.
|
||||||
virtual objc_class* GetNativeType ();
|
virtual objc_class* GetNativeType ();
|
||||||
|
|
||||||
// returns a pointer to the native window for this accessible tree.
|
|
||||||
void GetNativeWindow (void **aOutNativeWindow);
|
|
||||||
|
|
||||||
virtual void Shutdown ();
|
virtual void Shutdown ();
|
||||||
virtual void InvalidateChildren();
|
virtual void InvalidateChildren();
|
||||||
|
|
||||||
|
|
|
@ -86,17 +86,6 @@ nsAccessibleWrap::GetNativeInterface (void **aOutInterface)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the native NSWindow we reside in.
|
|
||||||
void
|
|
||||||
nsAccessibleWrap::GetNativeWindow (void **aOutNativeWindow)
|
|
||||||
{
|
|
||||||
*aOutNativeWindow = nsnull;
|
|
||||||
|
|
||||||
nsDocAccessible *docAcc = GetDocAccessible();
|
|
||||||
if (docAcc)
|
|
||||||
docAcc->GetWindowHandle (aOutNativeWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// overridden in subclasses to create the right kind of object. by default we create a generic
|
// overridden in subclasses to create the right kind of object. by default we create a generic
|
||||||
// 'mozAccessible' node.
|
// 'mozAccessible' node.
|
||||||
objc_class*
|
objc_class*
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "nsApplicationAccessibleWrap.h"
|
#include "nsApplicationAccessibleWrap.h"
|
||||||
#include "nsCoreUtils.h"
|
#include "nsCoreUtils.h"
|
||||||
#include "nsRootAccessible.h"
|
#include "nsRootAccessible.h"
|
||||||
|
#include "nsWinUtils.h"
|
||||||
|
|
||||||
#include "nsAttrName.h"
|
#include "nsAttrName.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
|
@ -63,6 +64,7 @@
|
||||||
HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
|
HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
|
||||||
HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
|
HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
|
||||||
LPFNACCESSIBLEOBJECTFROMWINDOW nsAccessNodeWrap::gmAccessibleObjectFromWindow = nsnull;
|
LPFNACCESSIBLEOBJECTFROMWINDOW nsAccessNodeWrap::gmAccessibleObjectFromWindow = nsnull;
|
||||||
|
LPFNLRESULTFROMOBJECT nsAccessNodeWrap::gmLresultFromObject = NULL;
|
||||||
LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
|
LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
|
||||||
LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
|
LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
|
||||||
|
|
||||||
|
@ -570,6 +572,13 @@ void nsAccessNodeWrap::InitAccessibility()
|
||||||
|
|
||||||
DoATSpecificProcessing();
|
DoATSpecificProcessing();
|
||||||
|
|
||||||
|
// Register window class that'll be used for document accessibles associated
|
||||||
|
// with tabs.
|
||||||
|
if (nsWinUtils::IsWindowEmulationEnabled()) {
|
||||||
|
nsWinUtils::RegisterNativeWindow(kClassNameTabContent);
|
||||||
|
sHWNDCache.Init(4);
|
||||||
|
}
|
||||||
|
|
||||||
nsAccessNode::InitXPAccessibility();
|
nsAccessNode::InitXPAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,6 +587,11 @@ void nsAccessNodeWrap::ShutdownAccessibility()
|
||||||
NS_IF_RELEASE(gTextEvent);
|
NS_IF_RELEASE(gTextEvent);
|
||||||
::DestroyCaret();
|
::DestroyCaret();
|
||||||
|
|
||||||
|
// Unregister window call that's used for document accessibles associated
|
||||||
|
// with tabs.
|
||||||
|
if (nsWinUtils::IsWindowEmulationEnabled())
|
||||||
|
::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
|
||||||
|
|
||||||
nsAccessNode::ShutdownXPAccessibility();
|
nsAccessNode::ShutdownXPAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,7 +638,7 @@ GetHRESULT(nsresult aResult)
|
||||||
|
|
||||||
PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
|
PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
|
||||||
{
|
{
|
||||||
HMODULE jhookhandle = ::GetModuleHandleW(L"jhook");
|
HMODULE jhookhandle = ::GetModuleHandleW(kJAWSModuleHandle);
|
||||||
if (!jhookhandle)
|
if (!jhookhandle)
|
||||||
return PR_FALSE; // No JAWS, or some other screen reader, use IA2
|
return PR_FALSE; // No JAWS, or some other screen reader, use IA2
|
||||||
|
|
||||||
|
@ -655,10 +669,10 @@ PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
|
||||||
|
|
||||||
void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
|
void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
|
||||||
{
|
{
|
||||||
HMODULE srHandle = ::GetModuleHandleW(L"jhook");
|
HMODULE srHandle = ::GetModuleHandleW(kJAWSModuleHandle);
|
||||||
if (!srHandle) {
|
if (!srHandle) {
|
||||||
// No JAWS, try Window-Eyes
|
// No JAWS, try Window-Eyes
|
||||||
srHandle = ::GetModuleHandleW(L"gwm32inc");
|
srHandle = ::GetModuleHandleW(kWEModuleHandle);
|
||||||
if (!srHandle) {
|
if (!srHandle) {
|
||||||
// no screen reader we're interested in. Bail out.
|
// no screen reader we're interested in. Bail out.
|
||||||
return;
|
return;
|
||||||
|
@ -694,3 +708,49 @@ void nsAccessNodeWrap::DoATSpecificProcessing()
|
||||||
|
|
||||||
TurnOffNewTabSwitchingForJawsAndWE();
|
TurnOffNewTabSwitchingForJawsAndWE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> nsAccessNodeWrap::sHWNDCache;
|
||||||
|
|
||||||
|
LRESULT CALLBACK
|
||||||
|
nsAccessNodeWrap::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg) {
|
||||||
|
case WM_GETOBJECT:
|
||||||
|
{
|
||||||
|
if (lParam == OBJID_CLIENT) {
|
||||||
|
nsDocAccessible* document = sHWNDCache.GetWeak(static_cast<void*>(hWnd));
|
||||||
|
if (document) {
|
||||||
|
IAccessible* msaaAccessible = NULL;
|
||||||
|
document->GetNativeInterface((void**)&msaaAccessible); // does an addref
|
||||||
|
if (msaaAccessible) {
|
||||||
|
LRESULT result = LresultFromObject(IID_IAccessible, wParam,
|
||||||
|
msaaAccessible); // does an addref
|
||||||
|
msaaAccessible->Release(); // release extra addref
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP_(LRESULT)
|
||||||
|
nsAccessNodeWrap::LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc)
|
||||||
|
{
|
||||||
|
// open the dll dynamically
|
||||||
|
if (!gmAccLib)
|
||||||
|
gmAccLib =::LoadLibraryW(L"OLEACC.DLL");
|
||||||
|
|
||||||
|
if (gmAccLib) {
|
||||||
|
if (!gmLresultFromObject)
|
||||||
|
gmLresultFromObject = (LPFNLRESULTFROMOBJECT)GetProcAddress(gmAccLib,"LresultFromObject");
|
||||||
|
|
||||||
|
if (gmLresultFromObject)
|
||||||
|
return gmLresultFromObject(riid, wParam, pAcc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -68,6 +68,8 @@
|
||||||
#include "nsICrashReporter.h"
|
#include "nsICrashReporter.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "nsRefPtrHashtable.h"
|
||||||
|
|
||||||
typedef LRESULT (STDAPICALLTYPE *LPFNNOTIFYWINEVENT)(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
|
typedef LRESULT (STDAPICALLTYPE *LPFNNOTIFYWINEVENT)(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
|
||||||
typedef LRESULT (STDAPICALLTYPE *LPFNGETGUITHREADINFO)(DWORD idThread, GUITHREADINFO* pgui);
|
typedef LRESULT (STDAPICALLTYPE *LPFNGETGUITHREADINFO)(DWORD idThread, GUITHREADINFO* pgui);
|
||||||
|
|
||||||
|
@ -154,6 +156,7 @@ public: // construction, destruction
|
||||||
static HINSTANCE gmAccLib;
|
static HINSTANCE gmAccLib;
|
||||||
static HINSTANCE gmUserLib;
|
static HINSTANCE gmUserLib;
|
||||||
static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
|
static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
|
||||||
|
static LPFNLRESULTFROMOBJECT gmLresultFromObject;
|
||||||
static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
|
static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
|
||||||
static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
|
static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
|
||||||
|
|
||||||
|
@ -165,6 +168,13 @@ public: // construction, destruction
|
||||||
|
|
||||||
static void DoATSpecificProcessing();
|
static void DoATSpecificProcessing();
|
||||||
|
|
||||||
|
static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc);
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,
|
||||||
|
WPARAM WParam, LPARAM lParam);
|
||||||
|
|
||||||
|
static nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> sHWNDCache;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "nsAccUtils.h"
|
#include "nsAccUtils.h"
|
||||||
#include "nsCoreUtils.h"
|
#include "nsCoreUtils.h"
|
||||||
#include "nsRelUtils.h"
|
#include "nsRelUtils.h"
|
||||||
|
#include "nsWinUtils.h"
|
||||||
|
|
||||||
#include "nsIAccessibleDocument.h"
|
#include "nsIAccessibleDocument.h"
|
||||||
#include "nsIAccessibleEvent.h"
|
#include "nsIAccessibleEvent.h"
|
||||||
|
@ -193,60 +194,25 @@ STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *pp
|
||||||
{
|
{
|
||||||
__try {
|
__try {
|
||||||
*ppdispParent = NULL;
|
*ppdispParent = NULL;
|
||||||
if (!mWeakShell)
|
|
||||||
return E_FAIL; // We've been shut down
|
|
||||||
|
|
||||||
nsIFrame *frame = GetFrame();
|
if (IsDefunct())
|
||||||
HWND hwnd = 0;
|
return E_FAIL;
|
||||||
if (frame) {
|
|
||||||
nsIView *view = frame->GetViewExternal();
|
|
||||||
if (view) {
|
|
||||||
// This code is essentially our implementation of WindowFromAccessibleObject,
|
|
||||||
// because MSAA iterates get_accParent() until it sees an object of ROLE_WINDOW
|
|
||||||
// to know where the window for a given accessible is. We must expose the native
|
|
||||||
// window accessible that MSAA creates for us. This must be done for the document
|
|
||||||
// object as well as any layout that creates its own window (e.g. via overflow: scroll)
|
|
||||||
nsIWidget *widget = view->GetWidget();
|
|
||||||
if (widget) {
|
|
||||||
hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
|
|
||||||
NS_ASSERTION(hwnd, "No window handle for window");
|
|
||||||
|
|
||||||
nsIViewManager* viewManager = view->GetViewManager();
|
nsRefPtr<nsDocAccessible> doc(do_QueryObject(this));
|
||||||
if (!viewManager)
|
if (doc) {
|
||||||
return E_UNEXPECTED;
|
// Return window system accessible object for root document and tab document
|
||||||
|
// accessibles.
|
||||||
nsIView *rootView;
|
if (!doc->ParentDocument() ||
|
||||||
viewManager->GetRootView(rootView);
|
nsWinUtils::IsWindowEmulationEnabled() &&
|
||||||
if (rootView == view) {
|
nsWinUtils::IsTabDocument(doc->GetDocumentNode())) {
|
||||||
// If the client accessible (OBJID_CLIENT) has a window but its window
|
HWND hwnd = static_cast<HWND>(doc->GetNativeWindow());
|
||||||
// was created by an outer window then we want the native accessible
|
if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
|
||||||
// for that outer window. If the accessible was created for outer
|
IID_IAccessible,
|
||||||
// window (if the outer window has inner windows then they share the
|
|
||||||
// same client accessible with it) then return native accessible for
|
|
||||||
// the outer window.
|
|
||||||
HWND parenthwnd = ::GetParent(hwnd);
|
|
||||||
if (parenthwnd)
|
|
||||||
hwnd = parenthwnd;
|
|
||||||
|
|
||||||
NS_ASSERTION(hwnd, "No window handle for window");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// If a frame is a scrollable frame, then it has one window for the client area,
|
|
||||||
// not an extra parent window for just the scrollbars
|
|
||||||
nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
|
|
||||||
if (scrollFrame) {
|
|
||||||
hwnd = (HWND)scrollFrame->GetScrolledFrame()->GetNearestWidget()->GetNativeData(NS_NATIVE_WINDOW);
|
|
||||||
NS_ASSERTION(hwnd, "No window handle for window");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible,
|
|
||||||
(void**)ppdispParent))) {
|
(void**)ppdispParent))) {
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsAccessible* xpParentAcc = GetParent();
|
nsAccessible* xpParentAcc = GetParent();
|
||||||
NS_ASSERTION(xpParentAcc,
|
NS_ASSERTION(xpParentAcc,
|
||||||
|
@ -1668,45 +1634,11 @@ PRInt32 nsAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
|
||||||
HWND
|
HWND
|
||||||
nsAccessibleWrap::GetHWNDFor(nsAccessible *aAccessible)
|
nsAccessibleWrap::GetHWNDFor(nsAccessible *aAccessible)
|
||||||
{
|
{
|
||||||
HWND hWnd = 0;
|
|
||||||
if (!aAccessible)
|
if (!aAccessible)
|
||||||
return hWnd;
|
|
||||||
|
|
||||||
nsIFrame *frame = aAccessible->GetFrame();
|
|
||||||
if (frame) {
|
|
||||||
nsIWidget *window = frame->GetNearestWidget();
|
|
||||||
PRBool isVisible;
|
|
||||||
window->IsVisible(isVisible);
|
|
||||||
if (isVisible) {
|
|
||||||
// Short explanation:
|
|
||||||
// If HWND for frame is inside a hidden window, fire the event on the
|
|
||||||
// containing document's visible window.
|
|
||||||
//
|
|
||||||
// Long explanation:
|
|
||||||
// This is really just to fix combo boxes with JAWS. Window-Eyes already
|
|
||||||
// worked with combo boxes because they use the value change event in
|
|
||||||
// the closed combo box case. JAWS will only pay attention to the focus
|
|
||||||
// events on the list items. The JAWS developers haven't fixed that, so
|
|
||||||
// we'll use the focus events to make JAWS work. However, JAWS is
|
|
||||||
// ignoring events on a hidden window. So, in order to fix the bug where
|
|
||||||
// JAWS doesn't echo the current option as it changes in a closed
|
|
||||||
// combo box, we need to use an ensure that we never fire an event with
|
|
||||||
// an HWND for a hidden window.
|
|
||||||
hWnd = (HWND)frame->GetNearestWidget()->GetNativeData(NS_NATIVE_WINDOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hWnd) {
|
|
||||||
void* handle = nsnull;
|
|
||||||
nsDocAccessible *accessibleDoc = aAccessible->GetDocAccessible();
|
|
||||||
if (!accessibleDoc)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
accessibleDoc->GetWindowHandle(&handle);
|
nsDocAccessible* document = aAccessible->GetDocAccessible();
|
||||||
hWnd = (HWND)handle;
|
return document ? static_cast<HWND>(document->GetNativeWindow()) : 0;
|
||||||
}
|
|
||||||
|
|
||||||
return hWnd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#include "nsDocAccessibleWrap.h"
|
#include "nsDocAccessibleWrap.h"
|
||||||
#include "ISimpleDOMDocument_i.c"
|
#include "ISimpleDOMDocument_i.c"
|
||||||
#include "nsIAccessibilityService.h"
|
#include "nsIAccessibilityService.h"
|
||||||
|
#include "nsRootAccessible.h"
|
||||||
|
#include "nsWinUtils.h"
|
||||||
|
|
||||||
#include "nsIDocShell.h"
|
#include "nsIDocShell.h"
|
||||||
#include "nsIDocShellTreeNode.h"
|
#include "nsIDocShellTreeNode.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
|
@ -60,7 +63,7 @@
|
||||||
nsDocAccessibleWrap::
|
nsDocAccessibleWrap::
|
||||||
nsDocAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
|
nsDocAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
|
||||||
nsIWeakReference *aShell) :
|
nsIWeakReference *aShell) :
|
||||||
nsDocAccessible(aDocument, aRootContent, aShell)
|
nsDocAccessible(aDocument, aRootContent, aShell), mHWND(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,3 +248,53 @@ STDMETHODIMP nsDocAccessibleWrap::get_accValue(
|
||||||
|
|
||||||
return get_URL(pszValue);
|
return get_URL(pszValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// nsAccessNode
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsDocAccessibleWrap::Init()
|
||||||
|
{
|
||||||
|
if (nsWinUtils::IsWindowEmulationEnabled()) {
|
||||||
|
// Create window for tab document.
|
||||||
|
if (nsWinUtils::IsTabDocument(mDocument)) {
|
||||||
|
nsRefPtr<nsRootAccessible> root = GetRootAccessible();
|
||||||
|
mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
|
||||||
|
static_cast<HWND>(root->GetNativeWindow()));
|
||||||
|
|
||||||
|
nsAccessibleWrap::sHWNDCache.Put(mHWND, this);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
nsDocAccessible* parentDocument = ParentDocument();
|
||||||
|
if (parentDocument)
|
||||||
|
mHWND = parentDocument->GetNativeWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsDocAccessible::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsDocAccessibleWrap::Shutdown()
|
||||||
|
{
|
||||||
|
if (nsWinUtils::IsWindowEmulationEnabled()) {
|
||||||
|
// Destroy window created for root document.
|
||||||
|
if (nsWinUtils::IsTabDocument(mDocument)) {
|
||||||
|
nsAccessibleWrap::sHWNDCache.Remove(mHWND);
|
||||||
|
::DestroyWindow(static_cast<HWND>(mHWND));
|
||||||
|
}
|
||||||
|
|
||||||
|
mHWND = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsDocAccessible::Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// nsDocAccessible
|
||||||
|
|
||||||
|
void*
|
||||||
|
nsDocAccessibleWrap::GetNativeWindow() const
|
||||||
|
{
|
||||||
|
return mHWND ? mHWND : nsDocAccessible::GetNativeWindow();
|
||||||
|
}
|
||||||
|
|
|
@ -89,8 +89,18 @@ public:
|
||||||
/* [optional][in] */ VARIANT varChild,
|
/* [optional][in] */ VARIANT varChild,
|
||||||
/* [retval][out] */ BSTR __RPC_FAR *pszValue);
|
/* [retval][out] */ BSTR __RPC_FAR *pszValue);
|
||||||
|
|
||||||
|
// nsAccessNode
|
||||||
|
virtual PRBool Init();
|
||||||
|
virtual void Shutdown();
|
||||||
|
|
||||||
// nsAccessibleWrap
|
// nsAccessibleWrap
|
||||||
virtual nsAccessible *GetXPAccessibleFor(const VARIANT& varChild);
|
virtual nsAccessible *GetXPAccessibleFor(const VARIANT& varChild);
|
||||||
|
|
||||||
|
// nsDocAccessible
|
||||||
|
virtual void* GetNativeWindow() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void* mHWND;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "nsAccessibleWrap.h"
|
#include "nsAccessibleWrap.h"
|
||||||
#include "nsIWinAccessNode.h"
|
#include "nsIWinAccessNode.h"
|
||||||
#include "nsArrayUtils.h"
|
#include "nsArrayUtils.h"
|
||||||
|
#include "nsIDocShellTreeItem.h"
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
||||||
|
@ -96,3 +97,56 @@ nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
||||||
*aIA2ArrayLen = length;
|
*aIA2ArrayLen = length;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass)
|
||||||
|
{
|
||||||
|
WNDCLASSW wc;
|
||||||
|
wc.style = CS_GLOBALCLASS;
|
||||||
|
wc.lpfnWndProc = nsAccessNodeWrap::WindowProc;
|
||||||
|
wc.cbClsExtra = 0;
|
||||||
|
wc.cbWndExtra = 0;
|
||||||
|
wc.hInstance = GetModuleHandle(NULL);
|
||||||
|
wc.hIcon = NULL;
|
||||||
|
wc.hCursor = NULL;
|
||||||
|
wc.hbrBackground = NULL;
|
||||||
|
wc.lpszMenuName = NULL;
|
||||||
|
wc.lpszClassName = aWindowClass;
|
||||||
|
::RegisterClassW(&wc);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND
|
||||||
|
nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd)
|
||||||
|
{
|
||||||
|
return ::CreateWindowW(aWindowClass,
|
||||||
|
L"NetscapeDispatchWnd",
|
||||||
|
WS_CHILD | WS_VISIBLE,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
0, 0,
|
||||||
|
aParentWnd,
|
||||||
|
NULL,
|
||||||
|
GetModuleHandle(NULL),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsWinUtils::IsWindowEmulationEnabled()
|
||||||
|
{
|
||||||
|
return ::GetModuleHandleW(kJAWSModuleHandle) ||
|
||||||
|
::GetModuleHandleW(kWEModuleHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsWinUtils::IsTabDocument(nsIDocument* aDocumentNode)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsISupports> container = aDocumentNode->GetContainer();
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
|
||||||
|
treeItem->GetParent(getter_AddRefs(parentTreeItem));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
|
||||||
|
treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||||
|
|
||||||
|
return parentTreeItem == rootTreeItem;
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,14 @@
|
||||||
#include "Accessible2.h"
|
#include "Accessible2.h"
|
||||||
|
|
||||||
#include "nsIArray.h"
|
#include "nsIArray.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
|
||||||
|
const LPCWSTR kClassNameRoot = L"MozillaUIWindowClass";
|
||||||
|
const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass";
|
||||||
|
|
||||||
|
const LPCWSTR kJAWSModuleHandle = L"jhook";
|
||||||
|
const LPCWSTR kWEModuleHandle = L"gwm32inc";
|
||||||
|
const LPCWSTR kNVDAModuleHandle = L"VBufBackend_gecko_ia2";
|
||||||
|
|
||||||
class nsWinUtils
|
class nsWinUtils
|
||||||
{
|
{
|
||||||
|
@ -54,6 +62,26 @@ public:
|
||||||
*/
|
*/
|
||||||
static HRESULT ConvertToIA2Array(nsIArray *aCollection,
|
static HRESULT ConvertToIA2Array(nsIArray *aCollection,
|
||||||
IUnknown ***aAccessibles, long *aCount);
|
IUnknown ***aAccessibles, long *aCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to register window class.
|
||||||
|
*/
|
||||||
|
static void RegisterNativeWindow(LPCWSTR aWindowClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to create a window.
|
||||||
|
*/
|
||||||
|
static HWND CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if window emulation is enabled.
|
||||||
|
*/
|
||||||
|
static bool IsWindowEmulationEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the given document node is for tab document accessible.
|
||||||
|
*/
|
||||||
|
static bool IsTabDocument(nsIDocument* aDocumentNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче