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 "AccessibleWrap.h"
10 #include "nsAccUtils.h"
11 #include "nsCoreUtils.h"
12 #include "nsMai.h"
13 #include "mozilla/Likely.h"
14 #include "mozilla/a11y/ProxyAccessible.h"
15 
16 using namespace mozilla::a11y;
17 
18 extern "C" {
19 
20 static AtkObject*
refAccessibleAtPointCB(AtkComponent * aComponent,gint aAccX,gint aAccY,AtkCoordType aCoordType)21 refAccessibleAtPointCB(AtkComponent* aComponent, gint aAccX, gint aAccY,
22                        AtkCoordType aCoordType)
23 {
24   return refAccessibleAtPointHelper(ATK_OBJECT(aComponent),
25                                     aAccX, aAccY, aCoordType);
26 }
27 
28 static void
getExtentsCB(AtkComponent * aComponent,gint * aX,gint * aY,gint * aWidth,gint * aHeight,AtkCoordType aCoordType)29 getExtentsCB(AtkComponent* aComponent, gint* aX, gint* aY,
30              gint* aWidth, gint* aHeight, AtkCoordType aCoordType)
31 {
32   getExtentsHelper(ATK_OBJECT(aComponent),
33                    aX, aY, aWidth, aHeight, aCoordType);
34 }
35 
36 static gboolean
grabFocusCB(AtkComponent * aComponent)37 grabFocusCB(AtkComponent* aComponent)
38 {
39   AtkObject* atkObject = ATK_OBJECT(aComponent);
40   AccessibleWrap* accWrap = GetAccessibleWrap(atkObject);
41   if (accWrap) {
42     accWrap->TakeFocus();
43     return TRUE;
44   }
45 
46   ProxyAccessible* proxy = GetProxy(atkObject);
47   if (proxy) {
48     proxy->TakeFocus();
49     return TRUE;
50   }
51 
52   return FALSE;
53 }
54 }
55 
56 AtkObject*
refAccessibleAtPointHelper(AtkObject * aAtkObj,gint aX,gint aY,AtkCoordType aCoordType)57 refAccessibleAtPointHelper(AtkObject* aAtkObj, gint aX, gint aY,
58                            AtkCoordType aCoordType)
59 {
60   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
61   if (accWrap) {
62     if (accWrap->IsDefunct() || nsAccUtils::MustPrune(accWrap)) {
63       return nullptr;
64     }
65 
66     // Accessible::ChildAtPoint(x,y) is in screen pixels.
67     if (aCoordType == ATK_XY_WINDOW) {
68       nsIntPoint winCoords =
69         nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode());
70       aX += winCoords.x;
71       aY += winCoords.y;
72     }
73 
74     Accessible* accAtPoint = accWrap->ChildAtPoint(aX, aY,
75                                                    Accessible::eDirectChild);
76     if (!accAtPoint) {
77       return nullptr;
78     }
79 
80     AtkObject* atkObj = AccessibleWrap::GetAtkObject(accAtPoint);
81     if (atkObj) {
82       g_object_ref(atkObj);
83     }
84 
85     return atkObj;
86   }
87 
88   if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
89     ProxyAccessible* result =
90       proxy->AccessibleAtPoint(aX, aY, aCoordType == ATK_XY_WINDOW);
91     AtkObject* atkObj = result ? GetWrapperFor(result) : nullptr;
92     if (atkObj) {
93       g_object_ref(atkObj);
94     }
95     return atkObj;
96   }
97 
98   return nullptr;
99 }
100 
101 void
getExtentsHelper(AtkObject * aAtkObj,gint * aX,gint * aY,gint * aWidth,gint * aHeight,AtkCoordType aCoordType)102 getExtentsHelper(AtkObject* aAtkObj,
103                  gint* aX, gint* aY, gint* aWidth, gint* aHeight,
104                  AtkCoordType aCoordType)
105 {
106   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
107   *aX = *aY = *aWidth = *aHeight = 0;
108 
109   if (accWrap) {
110     if (accWrap->IsDefunct()) {
111       return;
112     }
113 
114     nsIntRect screenRect = accWrap->Bounds();
115     if (screenRect.IsEmpty())
116       return;
117 
118     if (aCoordType == ATK_XY_WINDOW) {
119       nsIntPoint winCoords =
120         nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode());
121       screenRect.x -= winCoords.x;
122       screenRect.y -= winCoords.y;
123     }
124 
125     *aX = screenRect.x;
126     *aY = screenRect.y;
127     *aWidth = screenRect.width;
128     *aHeight = screenRect.height;
129     return;
130   }
131 
132   if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
133     proxy->Extents(aCoordType == ATK_XY_WINDOW, aX, aY, aWidth, aHeight);
134   }
135 }
136 
137 void
componentInterfaceInitCB(AtkComponentIface * aIface)138 componentInterfaceInitCB(AtkComponentIface* aIface)
139 {
140   NS_ASSERTION(aIface, "Invalid Interface");
141   if(MOZ_UNLIKELY(!aIface))
142     return;
143 
144   /*
145    * Use default implementation in atk for contains, get_position,
146    * and get_size
147    */
148   aIface->ref_accessible_at_point = refAccessibleAtPointCB;
149   aIface->get_extents = getExtentsCB;
150   aIface->grab_focus = grabFocusCB;
151 }
152