1 | /* |
2 | * Copyright (C) 2008 Nuanti Ltd. |
3 | * Copyright (C) 2009 Jan Alonzo |
4 | * Copyright (C) 2009, 2012 Igalia S.L. |
5 | * |
6 | * Portions from Mozilla a11y, copyright as follows: |
7 | * |
8 | * The Original Code is mozilla.org code. |
9 | * |
10 | * The Initial Developer of the Original Code is |
11 | * Sun Microsystems, Inc. |
12 | * Portions created by the Initial Developer are Copyright (C) 2002 |
13 | * the Initial Developer. All Rights Reserved. |
14 | * |
15 | * This library is free software; you can redistribute it and/or |
16 | * modify it under the terms of the GNU Library General Public |
17 | * License as published by the Free Software Foundation; either |
18 | * version 2 of the License, or (at your option) any later version. |
19 | * |
20 | * This library is distributed in the hope that it will be useful, |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
23 | * Library General Public License for more details. |
24 | * |
25 | * You should have received a copy of the GNU Library General Public License |
26 | * along with this library; see the file COPYING.LIB. If not, write to |
27 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
28 | * Boston, MA 02110-1301, USA. |
29 | */ |
30 | |
31 | #include "config.h" |
32 | #include "WebKitAccessibleInterfaceComponent.h" |
33 | |
34 | #if HAVE(ACCESSIBILITY) |
35 | |
36 | #include "AccessibilityObject.h" |
37 | #include "FrameView.h" |
38 | #include "IntRect.h" |
39 | #include "RenderLayer.h" |
40 | #include "WebKitAccessible.h" |
41 | #include "WebKitAccessibleUtil.h" |
42 | |
43 | using namespace WebCore; |
44 | |
45 | static IntPoint atkToContents(const AccessibilityObject& coreObject, AtkCoordType coordType, gint x, gint y) |
46 | { |
47 | auto* frameView = coreObject.documentFrameView(); |
48 | if (!frameView) |
49 | return { x, y }; |
50 | |
51 | switch (coordType) { |
52 | case ATK_XY_SCREEN: |
53 | return frameView->screenToContents({ x, y }); |
54 | case ATK_XY_WINDOW: |
55 | return frameView->windowToContents({ x, y }); |
56 | #if ATK_CHECK_VERSION(2, 30, 0) |
57 | case ATK_XY_PARENT: |
58 | RELEASE_ASSERT_NOT_REACHED(); |
59 | #endif |
60 | } |
61 | |
62 | return { x, y }; |
63 | } |
64 | |
65 | static AtkObject* webkitAccessibleComponentRefAccessibleAtPoint(AtkComponent* component, gint x, gint y, AtkCoordType coordType) |
66 | { |
67 | auto* accessible = WEBKIT_ACCESSIBLE(component); |
68 | returnValIfWebKitAccessibleIsInvalid(accessible, nullptr); |
69 | |
70 | auto& coreObject = webkitAccessibleGetAccessibilityObject(accessible); |
71 | auto* target = downcast<AccessibilityObject>(coreObject.accessibilityHitTest(atkToContents(coreObject, coordType, x, y))); |
72 | if (!target) |
73 | return nullptr; |
74 | |
75 | if (auto* wrapper = target->wrapper()) |
76 | return ATK_OBJECT(g_object_ref(wrapper)); |
77 | |
78 | return nullptr; |
79 | } |
80 | |
81 | static void webkitAccessibleComponentGetExtents(AtkComponent* component, gint* x, gint* y, gint* width, gint* height, AtkCoordType coordType) |
82 | { |
83 | auto* accessible = WEBKIT_ACCESSIBLE(component); |
84 | returnIfWebKitAccessibleIsInvalid(accessible); |
85 | |
86 | auto& coreObject = webkitAccessibleGetAccessibilityObject(accessible); |
87 | contentsRelativeToAtkCoordinateType(&coreObject, coordType, snappedIntRect(coreObject.elementRect()), x, y, width, height); |
88 | } |
89 | |
90 | static gboolean webkitAccessibleComponentGrabFocus(AtkComponent* component) |
91 | { |
92 | auto* accessible = WEBKIT_ACCESSIBLE(component); |
93 | returnValIfWebKitAccessibleIsInvalid(accessible, FALSE); |
94 | |
95 | auto& coreObject = webkitAccessibleGetAccessibilityObject(accessible); |
96 | coreObject.setFocused(true); |
97 | return coreObject.isFocused(); |
98 | } |
99 | |
100 | #if ATK_CHECK_VERSION(2, 30, 0) |
101 | static gboolean webkitAccessibleComponentScrollTo(AtkComponent* component, AtkScrollType scrollType) |
102 | { |
103 | auto* accessible = WEBKIT_ACCESSIBLE(component); |
104 | returnValIfWebKitAccessibleIsInvalid(accessible, FALSE); |
105 | |
106 | ScrollAlignment alignX; |
107 | ScrollAlignment alignY; |
108 | |
109 | switch (scrollType) { |
110 | case ATK_SCROLL_TOP_LEFT: |
111 | alignX = ScrollAlignment::alignLeftAlways; |
112 | alignY = ScrollAlignment::alignTopAlways; |
113 | break; |
114 | case ATK_SCROLL_BOTTOM_RIGHT: |
115 | alignX = ScrollAlignment::alignRightAlways; |
116 | alignY = ScrollAlignment::alignBottomAlways; |
117 | break; |
118 | case ATK_SCROLL_TOP_EDGE: |
119 | case ATK_SCROLL_BOTTOM_EDGE: |
120 | // Align to a particular edge is not supported, it's always the closest edge. |
121 | alignX = ScrollAlignment::alignCenterIfNeeded; |
122 | alignY = ScrollAlignment::alignToEdgeIfNeeded; |
123 | break; |
124 | case ATK_SCROLL_LEFT_EDGE: |
125 | case ATK_SCROLL_RIGHT_EDGE: |
126 | // Align to a particular edge is not supported, it's always the closest edge. |
127 | alignX = ScrollAlignment::alignToEdgeIfNeeded; |
128 | alignY = ScrollAlignment::alignCenterIfNeeded; |
129 | break; |
130 | case ATK_SCROLL_ANYWHERE: |
131 | alignX = ScrollAlignment::alignCenterIfNeeded; |
132 | alignY = ScrollAlignment::alignCenterIfNeeded; |
133 | break; |
134 | } |
135 | |
136 | auto& coreObject = webkitAccessibleGetAccessibilityObject(accessible); |
137 | coreObject.scrollToMakeVisible({ SelectionRevealMode::Reveal, alignX, alignY, ShouldAllowCrossOriginScrolling::Yes }); |
138 | |
139 | return TRUE; |
140 | } |
141 | |
142 | static gboolean webkitAccessibleComponentScrollToPoint(AtkComponent* component, AtkCoordType coordType, gint x, gint y) |
143 | { |
144 | auto* accessible = WEBKIT_ACCESSIBLE(component); |
145 | returnValIfWebKitAccessibleIsInvalid(accessible, FALSE); |
146 | |
147 | auto& coreObject = webkitAccessibleGetAccessibilityObject(accessible); |
148 | |
149 | IntPoint point(x, y); |
150 | if (coordType == ATK_XY_SCREEN) { |
151 | if (auto* frameView = coreObject.documentFrameView()) |
152 | point = frameView->contentsToWindow(frameView->screenToContents(point)); |
153 | } |
154 | |
155 | coreObject.scrollToGlobalPoint(point); |
156 | |
157 | return TRUE; |
158 | } |
159 | #endif |
160 | |
161 | void webkitAccessibleComponentInterfaceInit(AtkComponentIface* iface) |
162 | { |
163 | iface->ref_accessible_at_point = webkitAccessibleComponentRefAccessibleAtPoint; |
164 | iface->get_extents = webkitAccessibleComponentGetExtents; |
165 | iface->grab_focus = webkitAccessibleComponentGrabFocus; |
166 | #if ATK_CHECK_VERSION(2, 30, 0) |
167 | iface->scroll_to = webkitAccessibleComponentScrollTo; |
168 | iface->scroll_to_point = webkitAccessibleComponentScrollToPoint; |
169 | #endif |
170 | } |
171 | |
172 | #endif // HAVE(ACCESSIBILITY) |
173 | |