1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "nsWinUtils.h"
10 #include "Compatibility.h"
11 #include "DocAccessible.h"
12 #include "nsAccessibilityService.h"
13 #include "nsCoreUtils.h"
15 #include "mozilla/a11y/DocAccessibleParent.h"
16 #include "mozilla/Preferences.h"
17 #include "mozilla/StaticPrefs_accessibility.h"
18 #include "nsArrayUtils.h"
19 #include "nsICSSDeclaration.h"
20 #include "mozilla/dom/Document.h"
21 #include "mozilla/dom/Element.h"
22 #include "nsXULAppAPI.h"
24 using namespace mozilla
;
25 using namespace mozilla::a11y
;
26 using mozilla::dom::Element
;
28 // Window property used by ipc related code in identifying accessible
30 const wchar_t* kPropNameTabContent
= L
"AccessibleTabWindow";
33 * WindowProc to process WM_GETOBJECT messages, used in windows emulation mode.
35 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
,
38 bool nsWinUtils::sWindowEmulationStarted
= false;
40 already_AddRefed
<nsICSSDeclaration
> nsWinUtils::GetComputedStyleDeclaration(
41 nsIContent
* aContent
) {
42 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aContent
);
43 if (!elm
) return nullptr;
45 // Returns number of items in style declaration
46 nsCOMPtr
<nsPIDOMWindowInner
> window
= elm
->OwnerDoc()->GetInnerWindow();
47 if (!window
) return nullptr;
50 nsCOMPtr
<Element
> domElement(do_QueryInterface(elm
));
51 nsCOMPtr
<nsICSSDeclaration
> cssDecl
=
52 window
->GetComputedStyle(*domElement
, u
""_ns
, dummy
);
53 dummy
.SuppressException();
54 return cssDecl
.forget();
57 bool nsWinUtils::MaybeStartWindowEmulation() {
58 // Register window class that'll be used for document accessibles associated
60 if (IPCAccessibilityActive()) return false;
62 if (Compatibility::IsJAWS() || Compatibility::IsWE() ||
63 Compatibility::IsDolphin() || Compatibility::IsVisperoShared()) {
64 RegisterNativeWindow(kClassNameTabContent
);
65 sWindowEmulationStarted
= true;
72 void nsWinUtils::ShutdownWindowEmulation() {
73 // Unregister window call that's used for document accessibles associated
75 if (IsWindowEmulationStarted()) {
76 ::UnregisterClassW(kClassNameTabContent
, GetModuleHandle(nullptr));
77 sWindowEmulationStarted
= false;
81 void nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass
) {
83 wc
.style
= CS_GLOBALCLASS
;
84 wc
.lpfnWndProc
= WindowProc
;
87 wc
.hInstance
= GetModuleHandle(nullptr);
90 wc
.hbrBackground
= nullptr;
91 wc
.lpszMenuName
= nullptr;
92 wc
.lpszClassName
= aWindowClass
;
93 ::RegisterClassW(&wc
);
96 HWND
nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass
, HWND aParentWnd
,
97 int aX
, int aY
, int aWidth
, int aHeight
,
99 NativeWindowCreateProc
* aOnCreateProc
) {
100 return ::CreateWindowExW(
101 WS_EX_TRANSPARENT
, aWindowClass
, L
"NetscapeDispatchWnd",
102 WS_CHILD
| (aIsActive
? WS_VISIBLE
: 0), aX
, aY
, aWidth
, aHeight
,
103 aParentWnd
, nullptr, GetModuleHandle(nullptr), aOnCreateProc
);
106 void nsWinUtils::ShowNativeWindow(HWND aWnd
) { ::ShowWindow(aWnd
, SW_SHOW
); }
108 void nsWinUtils::HideNativeWindow(HWND aWnd
) {
110 aWnd
, nullptr, 0, 0, 0, 0,
111 SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
114 LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
) {
115 // Note, this window's message handling should not invoke any call that
116 // may result in a cross-process ipc call. Doing so may violate RPC
117 // message semantics.
121 // Mark this window so that ipc related code can identify it.
122 ::SetPropW(hWnd
, kPropNameTabContent
, reinterpret_cast<HANDLE
>(1));
124 auto createStruct
= reinterpret_cast<CREATESTRUCT
*>(lParam
);
125 auto createProc
= reinterpret_cast<nsWinUtils::NativeWindowCreateProc
*>(
126 createStruct
->lpCreateParams
);
128 if (createProc
&& *createProc
) {
135 // Do explicit casting to make it working on 64bit systems (see bug 649236
137 int32_t objId
= static_cast<DWORD
>(lParam
);
138 if (objId
== OBJID_CLIENT
) {
139 RefPtr
<IAccessible
> msaaAccessible
;
140 DocAccessible
* document
=
141 reinterpret_cast<DocAccessible
*>(::GetPropW(hWnd
, kPropNameDocAcc
));
143 document
->GetNativeInterface(getter_AddRefs(msaaAccessible
));
145 DocAccessibleParent
* docParent
= static_cast<DocAccessibleParent
*>(
146 ::GetPropW(hWnd
, kPropNameDocAccParent
));
148 if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
149 msaaAccessible
= MsaaAccessible::GetFrom(docParent
);
151 docParent
->GetCOMInterface(getter_AddRefs(msaaAccessible
));
155 if (msaaAccessible
) {
157 ::LresultFromObject(IID_IAccessible
, wParam
,
158 msaaAccessible
); // does an addref
165 LRESULT lRet
= ::DefWindowProc(hWnd
, msg
, wParam
, lParam
);
166 if (HTCLIENT
== lRet
) lRet
= HTTRANSPARENT
;
171 return ::DefWindowProcW(hWnd
, msg
, wParam
, lParam
);