tor-browser

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

nsMaiInterfaceComponent.cpp (5379B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "InterfaceInitFuncs.h"
      8 
      9 #include "LocalAccessible-inl.h"
     10 #include "AccessibleWrap.h"
     11 #include "nsAccUtils.h"
     12 #include "nsMai.h"
     13 #include "nsWindow.h"
     14 #include "mozilla/Likely.h"
     15 #include "mozilla/a11y/DocAccessibleParent.h"
     16 #include "mozilla/a11y/RemoteAccessible.h"
     17 #include "mozilla/dom/BrowserParent.h"
     18 #include "mozilla/dom/Document.h"
     19 #include "nsAccessibilityService.h"
     20 
     21 using namespace mozilla;
     22 using namespace mozilla::a11y;
     23 
     24 extern "C" {
     25 
     26 static AtkObject* refAccessibleAtPointCB(AtkComponent* aComponent, gint aAccX,
     27                                         gint aAccY, AtkCoordType aCoordType) {
     28  return refAccessibleAtPointHelper(ATK_OBJECT(aComponent), aAccX, aAccY,
     29                                    aCoordType);
     30 }
     31 
     32 static void getExtentsCB(AtkComponent* aComponent, gint* aX, gint* aY,
     33                         gint* aWidth, gint* aHeight, AtkCoordType aCoordType) {
     34  getExtentsHelper(ATK_OBJECT(aComponent), aX, aY, aWidth, aHeight, aCoordType);
     35 }
     36 
     37 static gboolean grabFocusCB(AtkComponent* aComponent) {
     38  AtkObject* atkObject = ATK_OBJECT(aComponent);
     39  Accessible* acc = GetInternalObj(atkObject);
     40  if (acc) {
     41    acc->TakeFocus();
     42    return TRUE;
     43  }
     44  return FALSE;
     45 }
     46 
     47 // ScrollType is compatible
     48 MOZ_CAN_RUN_SCRIPT_BOUNDARY
     49 static gboolean scrollToCB(AtkComponent* aComponent, AtkScrollType type) {
     50  AtkObject* atkObject = ATK_OBJECT(aComponent);
     51  if (Accessible* acc = GetInternalObj(atkObject)) {
     52    acc->ScrollTo(type);
     53    return TRUE;
     54  }
     55 
     56  return FALSE;
     57 }
     58 
     59 // CoordType is compatible
     60 static gboolean scrollToPointCB(AtkComponent* aComponent, AtkCoordType coords,
     61                                gint x, gint y) {
     62  AtkObject* atkObject = ATK_OBJECT(aComponent);
     63  AccessibleWrap* accWrap = GetAccessibleWrap(atkObject);
     64  if (accWrap) {
     65    accWrap->ScrollToPoint(coords, x, y);
     66    return TRUE;
     67  }
     68 
     69  RemoteAccessible* proxy = GetProxy(atkObject);
     70  if (proxy) {
     71    proxy->ScrollToPoint(coords, x, y);
     72    return TRUE;
     73  }
     74 
     75  return FALSE;
     76 }
     77 }
     78 
     79 AtkObject* refAccessibleAtPointHelper(AtkObject* aAtkObj, gint aX, gint aY,
     80                                      AtkCoordType aCoordType) {
     81  Accessible* acc = GetInternalObj(aAtkObj);
     82  if (!acc) {
     83    return nullptr;
     84  }
     85 
     86  // Accessible::ChildAtPoint(x,y) is in screen pixels.
     87  if (aCoordType == ATK_XY_WINDOW) {
     88    mozilla::LayoutDeviceIntPoint winCoords =
     89        nsAccUtils::GetScreenCoordsForWindow(acc);
     90    aX += winCoords.x;
     91    aY += winCoords.y;
     92  }
     93 
     94  Accessible* accAtPoint =
     95      acc->ChildAtPoint(aX, aY, Accessible::EWhichChildAtPoint::DeepestChild);
     96  if (!accAtPoint) {
     97    return nullptr;
     98  }
     99  roles::Role role = accAtPoint->Role();
    100  if (role == roles::TEXT_LEAF || role == roles::STATICTEXT) {
    101    // We don't include text leaf nodes in the ATK tree, so return the parent.
    102    accAtPoint = accAtPoint->Parent();
    103    MOZ_ASSERT(accAtPoint, "Text leaf should always have a parent");
    104  }
    105  AtkObject* atkObj = GetWrapperFor(accAtPoint);
    106  if (atkObj) {
    107    g_object_ref(atkObj);
    108  }
    109  return atkObj;
    110 }
    111 
    112 static double getScaleFactor(Accessible* aAccessible) {
    113  DocAccessible* docAcc = nullptr;
    114  if (LocalAccessible* localAcc = aAccessible->AsLocal()) {
    115    docAcc = localAcc->Document();
    116  } else {
    117    RemoteAccessible* remote = aAccessible->AsRemote();
    118    LocalAccessible* outerDoc = remote->OuterDocOfRemoteBrowser();
    119    if (outerDoc) {
    120      docAcc = outerDoc->Document();
    121    }
    122  }
    123 
    124  if (!docAcc || !docAcc->DocumentNode()) {
    125    return 1.0;
    126  }
    127 
    128  nsCOMPtr<nsIWidget> rootWidget =
    129      nsContentUtils::WidgetForDocument(docAcc->DocumentNode());
    130  if (!rootWidget) {
    131    return 1.0;
    132  }
    133 
    134  if (RefPtr<nsWindow> window =
    135          static_cast<nsWindow*>(rootWidget->GetTopLevelWidget())) {
    136    return window->FractionalScaleFactor();
    137  }
    138 
    139  return 1.0;
    140 }
    141 
    142 void getExtentsHelper(AtkObject* aAtkObj, gint* aX, gint* aY, gint* aWidth,
    143                      gint* aHeight, AtkCoordType aCoordType) {
    144  *aX = *aY = *aWidth = *aHeight = -1;
    145 
    146  Accessible* acc = GetInternalObj(aAtkObj);
    147  if (!acc) {
    148    return;
    149  }
    150 
    151  mozilla::LayoutDeviceIntRect screenRect = acc->Bounds();
    152  if (screenRect.IsEmpty()) {
    153    return;
    154  }
    155 
    156  if (aCoordType == ATK_XY_WINDOW) {
    157    mozilla::LayoutDeviceIntPoint winCoords =
    158        nsAccUtils::GetScreenCoordsForWindow(acc);
    159    screenRect.x -= winCoords.x;
    160    screenRect.y -= winCoords.y;
    161  }
    162 
    163  double scaleFactor = getScaleFactor(acc);
    164 
    165  *aX = screenRect.x / scaleFactor;
    166  *aY = screenRect.y / scaleFactor;
    167  *aWidth = screenRect.width / scaleFactor;
    168  *aHeight = screenRect.height / scaleFactor;
    169 }
    170 
    171 void componentInterfaceInitCB(AtkComponentIface* aIface) {
    172  NS_ASSERTION(aIface, "Invalid Interface");
    173  if (MOZ_UNLIKELY(!aIface)) return;
    174 
    175  /*
    176   * Use default implementation in atk for contains, get_position,
    177   * and get_size
    178   */
    179  aIface->ref_accessible_at_point = refAccessibleAtPointCB;
    180  aIface->get_extents = getExtentsCB;
    181  aIface->grab_focus = grabFocusCB;
    182  if (IsAtkVersionAtLeast(2, 30)) {
    183    aIface->scroll_to = scrollToCB;
    184    aIface->scroll_to_point = scrollToPointCB;
    185  }
    186 }