Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Williams2019-02-13 19:26:11 +0000
committerEric Williams2019-02-13 21:28:02 +0000
commitf2a41f7a4410a657943ce506c40fe9a7b2be8503 (patch)
tree51072d728564a1160b8a2764d07b703cc0dbdf04
parent73a25fb3b2f4e5472d1226f1b58edd392b2b5e6f (diff)
downloadeclipse.platform.swt-f2a41f7a4410a657943ce506c40fe9a7b2be8503.tar.gz
eclipse.platform.swt-f2a41f7a4410a657943ce506c40fe9a7b2be8503.tar.xz
eclipse.platform.swt-f2a41f7a4410a657943ce506c40fe9a7b2be8503.zip
Bug 543949: Orca's flat review mode can not be used
Not all SwtFixedAccessible instances have corresponding AccessibleObjects, meaning the implementation of ATK API is SwtFixedAccessible's responsibility to handle natively. Most ATK API like AtkEditableText or AtkAction doesn't need to worry about this since those API's are specialized for certain functions. However AtkComponent covers geometry which is pretty important information for a container accessibility implementation. The fix: if no AccessibleObject exists, calculate the extents/size/position manually. We can do this even with scaling by using JNI to call Java level methods like toDisplay. Change-Id: Ib54821fc006eedc039dc9dc4b3dc83ddc5cc58ab Signed-off-by: Eric Williams <ericwill@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java136
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c49
-rwxr-xr-xtests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/accessibility/Bug543949_ComponentExtentsTest.py38
3 files changed, 91 insertions, 132 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java
index 71ab8aa02b..a1561eb788 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java
@@ -406,113 +406,6 @@ class AccessibleObject {
}
/**
- * Gets the position of component in the form of a point specifying
- * component's top-left corner.
- *
- * This is the implementation of an ATK function which
- * queries the Accessible listeners at the Java level. On GTK3 the ATK
- * interfaces are implemented in os_custom.c and access this method via
- * JNI.
- *
- * @param atkObject a pointer to the current AtkObject
- * @param x memory address of gint to put x coordinate
- * @param y memory address of gint to put y coordinate
- * @param coord_type specifies whether the coordinates are relative to
- * the screen or to the components top level window
- *
- * @return 0 (this is a void function at the native level)
- */
- static long /*int*/ atkComponent_get_position (long /*int*/ atkObject, long /*int*/ x,
- long /*int*/ y, long /*int*/ coord_type) {
- AccessibleObject object = getAccessibleObject (atkObject);
- C.memmove (x, new int[] {0}, 4);
- C.memmove (y, new int[] {0}, 4);
- AtkComponentIface iface = getParentComponentIface (atkObject);
- if (iface != null && iface.get_position != 0) {
- OS.call (iface.get_position, atkObject, x, y, coord_type);
- }
- if (object != null) {
- Accessible accessible = object.accessible;
- List<AccessibleControlListener> listeners = accessible.accessibleControlListeners;
- int length = size(listeners);
- if (length > 0) {
- int[] parentX = new int [1], parentY = new int [1];
- C.memmove (parentX, x, 4);
- C.memmove (parentY, y, 4);
- AccessibleControlEvent event = new AccessibleControlEvent (accessible);
- event.childID = object.id;
- event.x = parentX [0]; event.y = parentY [0];
- int[] topWindowX = new int [1], topWindowY = new int [1];
- if (coord_type == ATK.ATK_XY_WINDOW) {
- windowPoint (object, topWindowX, topWindowY);
- event.x += topWindowX [0];
- event.y += topWindowY [0];
- }
- for (int i = 0; i < length; i++) {
- AccessibleControlListener listener = listeners.get (i);
- listener.getLocation (event);
- }
- if (coord_type == ATK.ATK_XY_WINDOW) {
- event.x -= topWindowX [0];
- event.y -= topWindowY [0];
- }
- C.memmove (x, new int[] {event.x}, 4);
- C.memmove (y, new int[] {event.y}, 4);
- }
- }
- return 0;
- }
-
- /**
- * Gets the size of the component in terms of width and height.
- *
- * This is the implementation of an ATK function which
- * queries the Accessible listeners at the Java level. On GTK3 the ATK
- * interfaces are implemented in os_custom.c and access this method via
- * JNI.
- *
- * @param atkObject a pointer to the current AtkObject
- * @param width memory address of gint to put x coordinate
- * @param height memory address of gint to put y coordinate
- * @param coord_type specifies whether the coordinates are relative to
- * the screen or to the components top level window (this parameter is always 0
- * on GTK3)
- *
- * @return 0 (this is a void function at the native level)
- */
- static long /*int*/ atkComponent_get_size (long /*int*/ atkObject, long /*int*/ width,
- long /*int*/ height, long /*int*/ coord_type) {
- AccessibleObject object = getAccessibleObject (atkObject);
- C.memmove (width, new int[] {0}, 4);
- C.memmove (height, new int[] {0}, 4);
- AtkComponentIface iface = getParentComponentIface (atkObject);
- if (iface != null && iface.get_size != 0) {
- // ATK with GTK3 doesn't have the coord_type parameter
- ATK.call (iface.get_size, atkObject, width, height);
- }
- if (object != null) {
- Accessible accessible = object.accessible;
- List<AccessibleControlListener> listeners = accessible.accessibleControlListeners;
- int length = size(listeners);
- if (length > 0) {
- int[] parentWidth = new int [1], parentHeight = new int [1];
- C.memmove (parentWidth, width, 4);
- C.memmove (parentHeight, height, 4);
- AccessibleControlEvent event = new AccessibleControlEvent (accessible);
- event.childID = object.id;
- event.width = parentWidth [0]; event.height = parentHeight [0];
- for (int i = 0; i < length; i++) {
- AccessibleControlListener listener = listeners.get (i);
- listener.getLocation (event);
- }
- C.memmove (width, new int[] {event.width}, 4);
- C.memmove (height, new int[] {event.height}, 4);
- }
- }
- return 0;
- }
-
- /**
* Gets a reference to the accessible child, if one exists,
* at the coordinate point specified by x and y.
*
@@ -4618,6 +4511,35 @@ class AccessibleObject {
return 0;
}
+ /**
+ * Static toDisplay implementation for accessibility purposes. This function
+ * is called from os_custom.c via JNI.
+ *
+ * @param gdkResource the GdkWindow (GTK3) or GdkSurface (GTK4)
+ * @param x a pointer to an integer which represents the x coordinate
+ * @param y a pointer to an integer which represents the y coordinate
+ * @return 0
+ */
+ static long /*int*/ toDisplay (long /*int*/ gdkResource, long /*int*/ x, long /*int*/ y) {
+ int [] origin_x = new int [1], origin_y = new int [1];
+ if (gdkResource == 0) {
+ // memmove anyways to prevent garbage data in the pointers
+ C.memmove (x, new int[] {0}, 4);
+ C.memmove (y, new int[] {0}, 4);
+ return 0;
+ }
+ if (GTK.GTK4) {
+ GDK.gdk_surface_get_origin (gdkResource, origin_x, origin_y);
+ } else {
+ GDK.gdk_window_get_origin (gdkResource, origin_x, origin_y);
+ }
+ int scaledX = DPIUtil.autoScaleDown (origin_x [0]);
+ int scaledY = DPIUtil.autoScaleDown (origin_y [0]);
+ C.memmove (x, new int[] {scaledX}, 4);
+ C.memmove (y, new int[] {scaledY}, 4);
+ return 0;
+ }
+
static void windowPoint (AccessibleObject object, int [] x, int [] y) {
long /*int*/ widget = GTK.gtk_accessible_get_widget(object.atkHandle);
while (widget == 0 && object.parent != null) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c
index e942805f66..dbc7dffb45 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c
@@ -1482,29 +1482,30 @@ static void swt_fixed_accessible_component_get_extents (AtkComponent *component,
if (private->has_accessible) {
call_accessible_object_function("atkComponent_get_extents", "(JJJJJJ)J", component, x, y,
width, height, coord_type);
- }
- return;
-}
-
-static void swt_fixed_accessible_component_get_position (AtkComponent *component, gint *x, gint *y,
- AtkCoordType coord_type) {
- SwtFixedAccessible *fixed = SWT_FIXED_ACCESSIBLE (component);
- SwtFixedAccessiblePrivate *private = fixed->priv;
-
- if (private->has_accessible) {
- call_accessible_object_function("atkComponent_get_position", "(JJJJ)J", component, x, y, coord_type);
- }
- return;
-}
-
-static void swt_fixed_accessible_component_get_size (AtkComponent *component, gint *width, gint *height) {
- SwtFixedAccessible *fixed = SWT_FIXED_ACCESSIBLE (component);
- SwtFixedAccessiblePrivate *private = fixed->priv;
-
- if (private->has_accessible) {
- // Note we are calling the Java method with 4 arguments: on GTK2 atk_component_get_size
- // accepts 4 parameters, on GTK3 it only accepts 3.
- call_accessible_object_function("atkComponent_get_size", "(JJJJ)J", component, width, height, 0);
+ } else {
+ // Only GTK3 has accessibility support at the moment.
+ #if !defined(GTK4)
+ GtkWidget *widget = gtk_accessible_get_widget(GTK_ACCESSIBLE(fixed));
+ GdkWindow *window = gtk_widget_get_window(widget);
+ gint fixed_x, fixed_y;
+ call_accessible_object_function("toDisplay", "(JJJ)J", window, &fixed_x, &fixed_y);
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ if (coord_type == ATK_XY_SCREEN) {
+ *x = fixed_x;
+ *y = fixed_y;
+ }
+ if (coord_type == ATK_XY_WINDOW) {
+ GtkWidget *top = gtk_widget_get_toplevel(widget);
+ GdkWindow *top_window = gtk_widget_get_window(top);
+ gint top_x, top_y;
+ call_accessible_object_function("toDisplay", "(JJJ)J", top_window, &top_x, &top_y);
+ *x = fixed_x - top_x;
+ *y = fixed_y - top_y;
+ }
+ *width = allocation.width;
+ *height = allocation.height;
+ #endif
}
return;
}
@@ -2176,8 +2177,6 @@ static void swt_fixed_accessible_action_iface_init (AtkActionIface *iface) {
static void swt_fixed_accessible_component_iface_init (AtkComponentIface *iface) {
iface->get_extents = swt_fixed_accessible_component_get_extents;
- iface->get_position = swt_fixed_accessible_component_get_position;
- iface->get_size = swt_fixed_accessible_component_get_size;
iface->ref_accessible_at_point = swt_fixed_accessible_component_ref_accessible_at_point;
}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/accessibility/Bug543949_ComponentExtentsTest.py b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/accessibility/Bug543949_ComponentExtentsTest.py
new file mode 100755
index 0000000000..a0fa0edd6b
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/accessibility/Bug543949_ComponentExtentsTest.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python3
+
+# Copyright (c) 2019 Red Hat and others. All rights reserved.
+# The contents of this file are made available under the terms
+# of the GNU Lesser General Public License (LGPL) Version 2.1 that
+# accompanies this distribution (lgpl-v21.txt). The LGPL is also
+# available at http://www.gnu.org/licenses/lgpl.html. If the version
+# of the LGPL at http://www.gnu.org is different to the version of
+# the LGPL accompanying this distribution and there is any conflict
+# between the two license versions, the terms of the LGPL accompanying
+# this distribution shall govern.
+#
+# Contributors:
+# Red Hat - initial API and implementation
+
+import pyatspi
+
+def printTree(root, indent=0):
+ try:
+ extents = root.queryComponent().getExtents(pyatspi.WINDOW_COORDS)
+ except:
+ extents = "()"
+
+ print ("%s-> %s %s" % (" " * indent, root, extents))
+ for child in root:
+ printTree(child, indent+4)
+
+def listener(e):
+ # Substitute SWT here for snippets
+ if e.host_application.name != "Eclipse":
+ return
+
+ print("%s is activated. Accessibility tree with extents:" % e.source)
+ printTree(e.source)
+
+
+pyatspi.Registry.registerEventListener(listener, "window:activate")
+pyatspi.Registry.start()

Back to the top