1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/windows/msaa/nsWinUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,173 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:expandtab:shiftwidth=2:tabstop=2: 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include "nsWinUtils.h" 1.12 + 1.13 +#include "Compatibility.h" 1.14 +#include "DocAccessible.h" 1.15 +#include "nsCoreUtils.h" 1.16 + 1.17 +#include "mozilla/Preferences.h" 1.18 +#include "nsArrayUtils.h" 1.19 +#include "nsIArray.h" 1.20 +#include "nsIDocument.h" 1.21 +#include "nsIDocShellTreeItem.h" 1.22 +#include "nsXULAppAPI.h" 1.23 + 1.24 +using namespace mozilla; 1.25 +using namespace mozilla::a11y; 1.26 + 1.27 +// Window property used by ipc related code in identifying accessible 1.28 +// tab windows. 1.29 +const wchar_t* kPropNameTabContent = L"AccessibleTabWindow"; 1.30 + 1.31 +/** 1.32 + * WindowProc to process WM_GETOBJECT messages, used in windows emulation mode. 1.33 + */ 1.34 +static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, 1.35 + WPARAM wParam, LPARAM lParam); 1.36 + 1.37 +nsRefPtrHashtable<nsPtrHashKey<void>, DocAccessible>* nsWinUtils::sHWNDCache = nullptr; 1.38 + 1.39 +already_AddRefed<nsIDOMCSSStyleDeclaration> 1.40 +nsWinUtils::GetComputedStyleDeclaration(nsIContent* aContent) 1.41 +{ 1.42 + nsIContent* elm = nsCoreUtils::GetDOMElementFor(aContent); 1.43 + if (!elm) 1.44 + return nullptr; 1.45 + 1.46 + // Returns number of items in style declaration 1.47 + nsCOMPtr<nsIDOMWindow> window = 1.48 + do_QueryInterface(elm->OwnerDoc()->GetWindow()); 1.49 + if (!window) 1.50 + return nullptr; 1.51 + 1.52 + nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl; 1.53 + nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(elm)); 1.54 + window->GetComputedStyle(domElement, EmptyString(), getter_AddRefs(cssDecl)); 1.55 + return cssDecl.forget(); 1.56 +} 1.57 + 1.58 +bool 1.59 +nsWinUtils::MaybeStartWindowEmulation() 1.60 +{ 1.61 + // Register window class that'll be used for document accessibles associated 1.62 + // with tabs. 1.63 + if (Compatibility::IsJAWS() || Compatibility::IsWE() || 1.64 + Compatibility::IsDolphin() || 1.65 + XRE_GetProcessType() == GeckoProcessType_Content) { 1.66 + RegisterNativeWindow(kClassNameTabContent); 1.67 + sHWNDCache = new nsRefPtrHashtable<nsPtrHashKey<void>, DocAccessible>(4); 1.68 + return true; 1.69 + } 1.70 + 1.71 + return false; 1.72 +} 1.73 + 1.74 +void 1.75 +nsWinUtils::ShutdownWindowEmulation() 1.76 +{ 1.77 + // Unregister window call that's used for document accessibles associated 1.78 + // with tabs. 1.79 + if (IsWindowEmulationStarted()) 1.80 + ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(nullptr)); 1.81 +} 1.82 + 1.83 +bool 1.84 +nsWinUtils::IsWindowEmulationStarted() 1.85 +{ 1.86 + return sHWNDCache != nullptr; 1.87 +} 1.88 + 1.89 +void 1.90 +nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass) 1.91 +{ 1.92 + WNDCLASSW wc; 1.93 + wc.style = CS_GLOBALCLASS; 1.94 + wc.lpfnWndProc = WindowProc; 1.95 + wc.cbClsExtra = 0; 1.96 + wc.cbWndExtra = 0; 1.97 + wc.hInstance = GetModuleHandle(nullptr); 1.98 + wc.hIcon = nullptr; 1.99 + wc.hCursor = nullptr; 1.100 + wc.hbrBackground = nullptr; 1.101 + wc.lpszMenuName = nullptr; 1.102 + wc.lpszClassName = aWindowClass; 1.103 + ::RegisterClassW(&wc); 1.104 +} 1.105 + 1.106 +HWND 1.107 +nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd, 1.108 + int aX, int aY, int aWidth, int aHeight, 1.109 + bool aIsActive) 1.110 +{ 1.111 + HWND hwnd = ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass, 1.112 + L"NetscapeDispatchWnd", 1.113 + WS_CHILD | (aIsActive ? WS_VISIBLE : 0), 1.114 + aX, aY, aWidth, aHeight, 1.115 + aParentWnd, 1.116 + nullptr, 1.117 + GetModuleHandle(nullptr), 1.118 + nullptr); 1.119 + if (hwnd) { 1.120 + // Mark this window so that ipc related code can identify it. 1.121 + ::SetPropW(hwnd, kPropNameTabContent, (HANDLE)1); 1.122 + } 1.123 + return hwnd; 1.124 +} 1.125 + 1.126 +void 1.127 +nsWinUtils::ShowNativeWindow(HWND aWnd) 1.128 +{ 1.129 + ::ShowWindow(aWnd, SW_SHOW); 1.130 +} 1.131 + 1.132 +void 1.133 +nsWinUtils::HideNativeWindow(HWND aWnd) 1.134 +{ 1.135 + ::SetWindowPos(aWnd, nullptr, 0, 0, 0, 0, 1.136 + SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 1.137 + SWP_NOZORDER | SWP_NOACTIVATE); 1.138 +} 1.139 + 1.140 +LRESULT CALLBACK 1.141 +WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 1.142 +{ 1.143 + // Note, this window's message handling should not invoke any call that 1.144 + // may result in a cross-process ipc call. Doing so may violate RPC 1.145 + // message semantics. 1.146 + 1.147 + switch (msg) { 1.148 + case WM_GETOBJECT: 1.149 + { 1.150 + if (lParam == OBJID_CLIENT) { 1.151 + DocAccessible* document = 1.152 + nsWinUtils::sHWNDCache->GetWeak(static_cast<void*>(hWnd)); 1.153 + if (document) { 1.154 + IAccessible* msaaAccessible = nullptr; 1.155 + document->GetNativeInterface((void**)&msaaAccessible); // does an addref 1.156 + if (msaaAccessible) { 1.157 + LRESULT result = ::LresultFromObject(IID_IAccessible, wParam, 1.158 + msaaAccessible); // does an addref 1.159 + msaaAccessible->Release(); // release extra addref 1.160 + return result; 1.161 + } 1.162 + } 1.163 + } 1.164 + return 0; 1.165 + } 1.166 + case WM_NCHITTEST: 1.167 + { 1.168 + LRESULT lRet = ::DefWindowProc(hWnd, msg, wParam, lParam); 1.169 + if (HTCLIENT == lRet) 1.170 + lRet = HTTRANSPARENT; 1.171 + return lRet; 1.172 + } 1.173 + } 1.174 + 1.175 + return ::DefWindowProcW(hWnd, msg, wParam, lParam); 1.176 +}