tor-browser

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

nsMaiInterfaceAction.cpp (5064B)


      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 "nsMai.h"
     11 #include "mozilla/Likely.h"
     12 #include "nsAccessibilityService.h"
     13 #include "Relation.h"
     14 #include "RemoteAccessible.h"
     15 #include "nsString.h"
     16 
     17 using namespace mozilla;
     18 using namespace mozilla::a11y;
     19 
     20 extern "C" {
     21 
     22 static gboolean doActionCB(AtkAction* aAction, gint aActionIndex) {
     23  AtkObject* atkObject = ATK_OBJECT(aAction);
     24  Accessible* acc = GetInternalObj(atkObject);
     25  if (!acc) {
     26    // If we don't have an Accessible, we can't have any actions.
     27    return false;
     28  }
     29 
     30  if (aActionIndex < acc->ActionCount()) {
     31    acc->DoAction(aActionIndex);
     32    return true;
     33  }
     34 
     35  // Check for custom actions.
     36  Relation customActions(acc->RelationByType(RelationType::ACTION));
     37  gint actionIndex = acc->ActionCount();
     38  while (Accessible* target = customActions.Next()) {
     39    if (target->HasPrimaryAction()) {
     40      MOZ_ASSERT(target->ActionCount() > 0);
     41      if (actionIndex == aActionIndex) {
     42        target->DoAction(0);
     43        return true;
     44      }
     45      actionIndex++;
     46    }
     47  }
     48 
     49  return false;
     50 }
     51 
     52 static gint getActionCountCB(AtkAction* aAction) {
     53  AtkObject* atkObject = ATK_OBJECT(aAction);
     54  Accessible* acc = GetInternalObj(atkObject);
     55  if (!acc) {
     56    // If we don't have an Accessible, we can't have any actions.
     57    return 0;
     58  }
     59 
     60  gint actionCount = acc->ActionCount();
     61  Relation customActions(acc->RelationByType(RelationType::ACTION));
     62  while (Accessible* target = customActions.Next()) {
     63    if (target->HasPrimaryAction()) {
     64      actionCount++;
     65    }
     66  }
     67 
     68  return actionCount;
     69 }
     70 
     71 static const gchar* getActionDescriptionCB(AtkAction* aAction,
     72                                           gint aActionIndex) {
     73  AtkObject* atkObject = ATK_OBJECT(aAction);
     74  nsAutoString description;
     75  Accessible* acc = GetInternalObj(atkObject);
     76  if (!acc) {
     77    // If we don't have an Accessible, we can't have any actions.
     78    return 0;
     79  }
     80 
     81  if (aActionIndex < acc->ActionCount()) {
     82    acc->ActionDescriptionAt(aActionIndex, description);
     83  } else {
     84    // Check for custom actions.
     85    Relation customActions(acc->RelationByType(RelationType::ACTION));
     86    gint actionIndex = acc->ActionCount();
     87    while (Accessible* target = customActions.Next()) {
     88      if (target->HasPrimaryAction()) {
     89        MOZ_ASSERT(target->ActionCount() > 0);
     90        if (actionIndex == aActionIndex) {
     91          // Use target's name as action description.
     92          target->Name(description);
     93          break;
     94        }
     95        actionIndex++;
     96      }
     97    }
     98  }
     99 
    100  if (!description.IsEmpty()) {
    101    return AccessibleWrap::ReturnString(description);
    102  }
    103 
    104  return nullptr;
    105 }
    106 
    107 static const gchar* getActionNameCB(AtkAction* aAction, gint aActionIndex) {
    108  AtkObject* atkObject = ATK_OBJECT(aAction);
    109  nsAutoString name;
    110  Accessible* acc = GetInternalObj(atkObject);
    111  if (!acc) {
    112    // If we don't have an Accessible, we can't have any actions.
    113    return 0;
    114  }
    115 
    116  if (aActionIndex < acc->ActionCount()) {
    117    acc->ActionNameAt(aActionIndex, name);
    118  } else {
    119    // Check for custom actions.
    120    Relation customActions(acc->RelationByType(RelationType::ACTION));
    121    gint actionIndex = acc->ActionCount();
    122    while (Accessible* target = customActions.Next()) {
    123      if (target->HasPrimaryAction()) {
    124        MOZ_ASSERT(target->ActionCount() > 0);
    125        if (actionIndex == aActionIndex) {
    126          name.AssignLiteral("custom");
    127          nsAutoString domNodeId;
    128          target->DOMNodeID(domNodeId);
    129          if (!domNodeId.IsEmpty()) {
    130            name.AppendPrintf("_%s", NS_ConvertUTF16toUTF8(domNodeId).get());
    131          }
    132          break;
    133        }
    134        actionIndex++;
    135      }
    136    }
    137  }
    138 
    139  if (!name.IsEmpty()) {
    140    return AccessibleWrap::ReturnString(name);
    141  }
    142 
    143  return nullptr;
    144 }
    145 
    146 static const gchar* getActionLocalizedNameCB(AtkAction* aAction,
    147                                             gint aActionIndex) {
    148  // Mirror action description into localized name.
    149  return getActionDescriptionCB(aAction, aActionIndex);
    150 }
    151 
    152 static const gchar* getKeyBindingCB(AtkAction* aAction, gint aActionIndex) {
    153  Accessible* acc = GetInternalObj(ATK_OBJECT(aAction));
    154  if (!acc) {
    155    return nullptr;
    156  }
    157  nsAutoString keyBindingsStr;
    158  AccessibleWrap::GetKeyBinding(acc, keyBindingsStr);
    159 
    160  return AccessibleWrap::ReturnString(keyBindingsStr);
    161 }
    162 }
    163 
    164 void actionInterfaceInitCB(AtkActionIface* aIface) {
    165  NS_ASSERTION(aIface, "Invalid aIface");
    166  if (MOZ_UNLIKELY(!aIface)) return;
    167 
    168  aIface->do_action = doActionCB;
    169  aIface->get_n_actions = getActionCountCB;
    170  aIface->get_description = getActionDescriptionCB;
    171  aIface->get_keybinding = getKeyBindingCB;
    172  aIface->get_name = getActionNameCB;
    173  aIface->get_localized_name = getActionLocalizedNameCB;
    174 }