nsWinUtils.cpp (5025B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:expandtab:shiftwidth=2:tabstop=2: 3 */ 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/. */ 7 8 #include "nsWinUtils.h" 9 10 #include "Compatibility.h" 11 #include "DocAccessible.h" 12 #include "MsaaAccessible.h" 13 #include "nsAccessibilityService.h" 14 #include "nsCoreUtils.h" 15 16 #include "mozilla/a11y/DocAccessibleParent.h" 17 #include "mozilla/Preferences.h" 18 #include "nsArrayUtils.h" 19 #include "mozilla/dom/Document.h" 20 #include "mozilla/dom/Element.h" 21 #include "nsXULAppAPI.h" 22 23 using namespace mozilla; 24 using namespace mozilla::a11y; 25 using mozilla::dom::Element; 26 27 // Window property used by ipc related code in identifying accessible 28 // tab windows. 29 const wchar_t* kPropNameTabContent = L"AccessibleTabWindow"; 30 31 /** 32 * WindowProc to process WM_GETOBJECT messages, used in windows emulation mode. 33 */ 34 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, 35 LPARAM lParam); 36 37 bool nsWinUtils::sWindowEmulationStarted = false; 38 39 bool nsWinUtils::MaybeStartWindowEmulation() { 40 // Register window class that'll be used for document accessibles associated 41 // with tabs. 42 if (IPCAccessibilityActive()) return false; 43 44 if (Compatibility::IsJAWS() || Compatibility::IsWE() || 45 Compatibility::IsDolphin() || Compatibility::IsVisperoShared()) { 46 RegisterNativeWindow(kClassNameTabContent); 47 sWindowEmulationStarted = true; 48 return true; 49 } 50 51 return false; 52 } 53 54 void nsWinUtils::ShutdownWindowEmulation() { 55 // Unregister window call that's used for document accessibles associated 56 // with tabs. 57 if (IsWindowEmulationStarted()) { 58 ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(nullptr)); 59 sWindowEmulationStarted = false; 60 } 61 } 62 63 void nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass) { 64 WNDCLASSW wc; 65 wc.style = CS_GLOBALCLASS; 66 wc.lpfnWndProc = WindowProc; 67 wc.cbClsExtra = 0; 68 wc.cbWndExtra = 0; 69 wc.hInstance = GetModuleHandle(nullptr); 70 wc.hIcon = nullptr; 71 wc.hCursor = nullptr; 72 wc.hbrBackground = nullptr; 73 wc.lpszMenuName = nullptr; 74 wc.lpszClassName = aWindowClass; 75 ::RegisterClassW(&wc); 76 } 77 78 HWND nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd, 79 int aX, int aY, int aWidth, int aHeight, 80 bool aIsActive, 81 NativeWindowCreateProc* aOnCreateProc) { 82 return ::CreateWindowExW( 83 WS_EX_TRANSPARENT, aWindowClass, L"NetscapeDispatchWnd", 84 WS_CHILD | (aIsActive ? WS_VISIBLE : 0), aX, aY, aWidth, aHeight, 85 aParentWnd, nullptr, GetModuleHandle(nullptr), aOnCreateProc); 86 } 87 88 void nsWinUtils::ShowNativeWindow(HWND aWnd) { ::ShowWindow(aWnd, SW_SHOW); } 89 90 void nsWinUtils::HideNativeWindow(HWND aWnd) { 91 ::SetWindowPos( 92 aWnd, nullptr, 0, 0, 0, 0, 93 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 94 } 95 96 LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { 97 // Note, this window's message handling should not invoke any call that 98 // may result in a cross-process ipc call. Doing so may violate RPC 99 // message semantics. 100 101 switch (msg) { 102 case WM_CREATE: { 103 // Mark this window so that ipc related code can identify it. 104 ::SetPropW(hWnd, kPropNameTabContent, reinterpret_cast<HANDLE>(1)); 105 106 auto createStruct = reinterpret_cast<CREATESTRUCT*>(lParam); 107 auto createProc = reinterpret_cast<nsWinUtils::NativeWindowCreateProc*>( 108 createStruct->lpCreateParams); 109 110 if (createProc && *createProc) { 111 (*createProc)(hWnd); 112 } 113 114 return 0; 115 } 116 case WM_GETOBJECT: { 117 // Do explicit casting to make it working on 64bit systems (see bug 649236 118 // for details). 119 int32_t objId = static_cast<DWORD>(lParam); 120 if (objId == OBJID_CLIENT) { 121 RefPtr<IAccessible> msaaAccessible; 122 DocAccessible* document = 123 reinterpret_cast<DocAccessible*>(::GetPropW(hWnd, kPropNameDocAcc)); 124 if (document) { 125 document->GetNativeInterface(getter_AddRefs(msaaAccessible)); 126 } else { 127 DocAccessibleParent* docParent = static_cast<DocAccessibleParent*>( 128 ::GetPropW(hWnd, kPropNameDocAccParent)); 129 if (docParent) { 130 msaaAccessible = MsaaAccessible::GetFrom(docParent); 131 } 132 } 133 if (msaaAccessible) { 134 LRESULT result = 135 ::LresultFromObject(IID_IAccessible, wParam, 136 msaaAccessible); // does an addref 137 return result; 138 } 139 } 140 return 0; 141 } 142 case WM_NCHITTEST: { 143 LRESULT lRet = ::DefWindowProc(hWnd, msg, wParam, lParam); 144 if (HTCLIENT == lRet) lRet = HTTRANSPARENT; 145 return lRet; 146 } 147 } 148 149 return ::DefWindowProcW(hWnd, msg, wParam, lParam); 150 }