tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }