org.eclipse.swt.accessibility.AccessibleObject Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.swt.gtk.linux.aarch64 Show documentation
Show all versions of org.eclipse.swt.gtk.linux.aarch64 Show documentation
Standard Widget Toolkit for GTK on aarch64
The newest version!
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.accessibility;
import java.util.*;
import java.util.List;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.accessibility.gtk.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.internal.gtk3.*;
import org.eclipse.swt.widgets.*;
class AccessibleObject {
long atkHandle;
int index = -1, id = ACC.CHILDID_SELF;
Accessible accessible;
AccessibleObject parent;
AccessibleObject[] children;
/*
* a lightweight object does not correspond to a concrete gtk widget, but
* to a logical child of a widget (eg.- a CTabItem, which is simply drawn)
*/
boolean isLightweight = false;
static long actionNamePtr = -1;
static long descriptionPtr = -1;
static long keybindingPtr = -1;
static long namePtr = -1;
static final Map AccessibleObjects = new HashMap<> (9);
static final boolean DEBUG = Device.DEBUG;
AccessibleObject (long type, long widget, Accessible accessible, boolean isLightweight) {
super ();
if (GTK.GTK4) {
//TODO: Make use of Accessibility interface of GtkWidget rather than atk object which has been removed
} else {
if (type == OS.swt_fixed_get_type()) {
if (widget != 0 && !isLightweight) {
atkHandle = GTK3.gtk_widget_get_accessible(widget);
} else {
// Lightweight widgets map to no "real" GTK widget, so we
// just instantiate a new SwtFixedAccessible
atkHandle = OS.g_object_new (OS.swt_fixed_accessible_get_type(), 0);
}
OS.swt_fixed_accessible_register_accessible(atkHandle, false, widget);
} else {
// TODO_a11y: accessibility listeners on the Java side have not yet
// been implemented for native GTK widgets on GTK3.
atkHandle = GTK3.gtk_widget_get_accessible(widget);
}
}
this.accessible = accessible;
this.isLightweight = isLightweight;
AccessibleObjects.put (new LONG (atkHandle), this);
}
static void print (String str) {
System.out.println (str);
}
static int size(Collection> listeners) {
return listeners == null ? 0 : listeners.size();
}
/**
* Fills a Java AtkActionIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkActionIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkActionIface getParentActionIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type();
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_ACTION())) {
AtkActionIface iface = new AtkActionIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_ACTION_GET_IFACE (atkObject)));
return iface;
}
return null;
}
/**
* Performs the specified action on atkObject.
*
* 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 index the action index corresponding to the action to be performed
*
* @return long int representing whether the action succeeded: 1 for success,
* 0 for failure
*/
static long atkAction_do_action (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleActionListeners;
int length = size(listeners);
if (length > 0) {
AccessibleActionEvent event = new AccessibleActionEvent(accessible);
event.index = (int)index;
for (int i = 0; i < length; i++) {
AccessibleActionListener listener = listeners.get(i);
listener.doAction(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkActionIface iface = getParentActionIface (atkObject);
if (iface != null && iface.do_action != 0) {
parentResult = ATK.call (iface.do_action, atkObject, index);
}
return parentResult;
}
/**
* Returns the number of accessible actions available on atkObject.
* If there are more than one, the first is considered the default
* action of the object.
*
* 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
*
* @return the number of actions available
*/
static long atkAction_get_n_actions (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleActionListeners;
int length = size(listeners);
if (length > 0) {
AccessibleActionEvent event = new AccessibleActionEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleActionListener listener = listeners.get(i);
listener.getActionCount(event);
}
return event.count;
}
}
long parentResult = 0;
AtkActionIface iface = getParentActionIface (atkObject);
if (iface != null && iface.get_n_actions != 0) {
parentResult = ATK.call (iface.get_n_actions, atkObject);
}
return parentResult;
}
/**
* Returns a description of the specified action of the atkObject.
*
* 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 index the action index corresponding to the action to be performed
*
* @return a pointer to the description string
*/
static long atkAction_get_description (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleActionListeners;
int length = size(listeners);
if (length > 0) {
AccessibleActionEvent event = new AccessibleActionEvent(accessible);
event.index = (int)index;
for (int i = 0; i < length; i++) {
AccessibleActionListener listener = listeners.get(i);
listener.getDescription(event);
}
if (event.result == null) return 0;
if (descriptionPtr != -1) OS.g_free (descriptionPtr);
return descriptionPtr = getStringPtr (event.result);
}
}
long parentResult = 0;
AtkActionIface iface = getParentActionIface (atkObject);
if (iface != null && iface.get_description != 0) {
parentResult = ATK.call (iface.get_description, atkObject, index);
}
return parentResult;
}
/**
* Returns the keybinding which can be used to activate
* this atkObject, if one exists. Example: "Ctrl+1"
*
* 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 index the action index corresponding to the action to be performed
*
* @return a pointer to the keybinding string
*/
static long atkAction_get_keybinding (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkActionIface iface = getParentActionIface (atkObject);
if (iface != null && iface.get_keybinding != 0) {
parentResult = ATK.call (iface.get_keybinding, atkObject, index);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleActionListeners;
int length = size(listeners);
if (length > 0) {
AccessibleActionEvent event = new AccessibleActionEvent(accessible);
event.index = (int)index;
for (int i = 0; i < length; i++) {
AccessibleActionListener listener = listeners.get(i);
listener.getKeyBinding(event);
}
if (event.result != null) {
if (keybindingPtr != -1) OS.g_free (keybindingPtr);
return keybindingPtr = getStringPtr (event.result);
}
}
List listeners2 = accessible.accessibleListeners;
length = size(listeners2);
if (length > 0) {
AccessibleEvent event = new AccessibleEvent (accessible);
event.childID = object.id;
if (parentResult != 0) event.result = getString (parentResult);
for (int i = 0; i < length; i++) {
AccessibleListener listener = listeners2.get(i);
listener.getKeyboardShortcut (event);
}
if (event.result != null) {
if (keybindingPtr != -1) OS.g_free (keybindingPtr);
return keybindingPtr = getStringPtr (event.result);
}
}
}
return parentResult;
}
/**
* Returns the name of the specified action of the atkObject.
*
* 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 index the action index corresponding to the action to be performed
*
* @return a pointer to the name string
*/
static long atkAction_get_name (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkActionIface iface = getParentActionIface (atkObject);
if (iface != null && iface.get_name != 0) {
parentResult = ATK.call (iface.get_name, atkObject, index);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleActionListeners;
int length = size(listeners);
if (length > 0) {
AccessibleActionEvent event = new AccessibleActionEvent(accessible);
event.index = (int)index;
for (int i = 0; i < length; i++) {
AccessibleActionListener listener = listeners.get(i);
listener.getName(event);
}
if (event.result != null) {
if (actionNamePtr != -1) OS.g_free (actionNamePtr);
return actionNamePtr = getStringPtr (event.result);
}
}
if (index == 0) {
List listeners2 = accessible.accessibleControlListeners;
length = size(listeners2);
if (length > 0) {
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
if (parentResult != 0) event.result = getString (parentResult);
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners2.get(i);
listener.getDefaultAction (event);
}
if (event.result != null) {
if (actionNamePtr != -1) OS.g_free (actionNamePtr);
return actionNamePtr = getStringPtr (event.result);
}
}
}
}
return parentResult;
}
/**
* Fills a Java AtkComponentIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkComponentIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkComponentIface getParentComponentIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type();
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_COMPONENT())) {
AtkComponentIface iface = new AtkComponentIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (atkObject)));
return iface;
}
return null;
}
/**
* Gets the rectangle which gives the extent of the component.
*
* 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 width memory address of gint to put width coordinate
* @param height memory address of gint to put height 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 atkComponent_get_extents (long atkObject, long x, long y,
long width, long height, long coord_type) {
AccessibleObject object = getAccessibleObject (atkObject);
C.memmove (x, new int[] {0}, 4);
C.memmove (y, new int[] {0}, 4);
C.memmove (width, new int[] {0}, 4);
C.memmove (height, new int[] {0}, 4);
AtkComponentIface iface = getParentComponentIface (atkObject);
if (iface != null && iface.get_extents != 0) {
OS.call (iface.get_extents, atkObject, x, y, width, height, coord_type);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
int[] parentX = new int [1], parentY = new int [1];
int[] parentWidth = new int [1], parentHeight = new int [1];
C.memmove (parentX, x, 4);
C.memmove (parentY, y, 4);
C.memmove (parentWidth, width, 4);
C.memmove (parentHeight, height, 4);
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
event.x = parentX [0]; event.y = parentY [0];
event.width = parentWidth [0]; event.height = parentHeight [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);
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.
*
* 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 long integer representing the x coordinate
* @param y long integer representing the y coordinate
* @param coord_type specifies whether the coordinates are relative to
* the screen or to the components top level window
*
* @return a pointer to the accessible child, if one exists
*/
static long atkComponent_ref_accessible_at_point (long atkObject, long x,
long y, long coord_type) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
event.x = (int)x; event.y = (int)y;
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.getChildAtPoint (event);
}
if (event.childID == object.id) event.childID = ACC.CHILDID_SELF;
Accessible result = event.accessible;
AccessibleObject accObj = result != null ? result.getAccessibleObject() : object.getChildByID (event.childID);
if (accObj != null) {
return OS.g_object_ref (accObj.atkHandle);
}
}
}
long parentResult = 0;
AtkComponentIface iface = getParentComponentIface (atkObject);
if (iface != null && iface.ref_accessible_at_point != 0) {
parentResult = OS.call (iface.ref_accessible_at_point, atkObject, x, y, coord_type);
}
return parentResult;
}
/**
* Fills a Java AtkEditableTextIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkEdtiableTextIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkEditableTextIface getParentEditableTextIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type();
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_EDITABLE_TEXT())) {
AtkEditableTextIface iface = new AtkEditableTextIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_EDITABLE_TEXT_GET_IFACE (atkObject)));
return iface;
}
return null;
}
/**
* Sets the attributes for a specified range.
*
* 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 attrib_set a pointer to an AtkAttributeSet
* @param start_offset start range in which to set attributes
* @param end_offset end of range in which to set attributes
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkEditableText_set_run_attributes (long atkObject, long attrib_set,
long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleEditableTextListeners;
int length = size(listeners);
if (length > 0) {
Display display = accessible.control.getDisplay();
long fontDesc = OS.pango_font_description_new ();
boolean createFont = false;
TextStyle style = new TextStyle();
String [] attributes = new String [0];
long current = attrib_set;
int listLength = OS.g_slist_length (attrib_set);
for (int i = 0; i < listLength; i++) {
long attrPtr = OS.g_slist_data (current);
if (attrPtr != 0) {
AtkAttribute attr = new AtkAttribute();
ATK.memmove(attr, attrPtr, AtkAttribute.sizeof);
String name = getString(attr.name);
String value = getString(attr.value);
OS.g_free(attrPtr);
String [] newAttributes = new String [attributes.length + 2];
System.arraycopy (attributes, 0, newAttributes, 0, attributes.length);
newAttributes[attributes.length] = name;
newAttributes[attributes.length + 1] = value;
attributes = newAttributes;
try {
if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_RISE)))) {
// number of pixels above baseline
style.rise = Integer.parseInt(value);
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_UNDERLINE)))) {
// "none", "single", "double", "low", or "error" (also allow "squiggle")
if (value.equals("single") || value.equals("low")) {
style.underline = true;
style.underlineStyle = SWT.UNDERLINE_SINGLE;
} else if (value.equals("double")) {
style.underline = true;
style.underlineStyle = SWT.UNDERLINE_DOUBLE;
} else if (value.equals("error")) {
style.underline = true;
style.underlineStyle = SWT.UNDERLINE_ERROR;
} else if (value.equals("squiggle")) {
style.underline = true;
style.underlineStyle = SWT.UNDERLINE_SQUIGGLE;
}
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_STRIKETHROUGH)))) {
// "true" or "false" (also allow "1" and "single")
if (value.equals("true") || value.equals("1") || value.equals("single")) style.strikeout = true;
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_FAMILY_NAME)))) {
// font family name
byte [] buffer = Converter.wcsToMbcs(value, true);
OS.pango_font_description_set_family(fontDesc, buffer);
createFont = true;
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_SIZE)))) {
// size of characters in points (allow fractional points)
float size = Float.parseFloat(value);
OS.pango_font_description_set_size(fontDesc, (int)(size * OS.PANGO_SCALE));
createFont = true;
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_STYLE)))) {
// "normal", "italic" or "oblique"
int fontStyle = -1;
if (value.equals("normal")) fontStyle = OS.PANGO_STYLE_NORMAL;
else if (value.equals("italic")) fontStyle = OS.PANGO_STYLE_ITALIC;
else if (value.equals("oblique")) fontStyle = OS.PANGO_STYLE_OBLIQUE;
if (fontStyle != -1) {
OS.pango_font_description_set_style(fontDesc, fontStyle);
createFont = true;
}
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_VARIANT)))) {
// "normal" or "small_caps"
int variant = -1;
if (value.equals("normal")) variant = OS.PANGO_VARIANT_NORMAL;
else if (value.equals("small_caps")) variant = OS.PANGO_VARIANT_SMALL_CAPS;
if (variant != -1) {
OS.pango_font_description_set_variant(fontDesc, variant);
createFont = true;
}
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_STRETCH)))) {
//"ultra_condensed", "extra_condensed", "condensed", "semi_condensed", "normal", "semi_expanded", "expanded", "extra_expanded" or "ultra_expanded"
int stretch = -1;
if (value.equals("ultra_condensed")) stretch = OS.PANGO_STRETCH_ULTRA_CONDENSED;
else if (value.equals("extra_condensed")) stretch = OS.PANGO_STRETCH_EXTRA_CONDENSED;
else if (value.equals("condensed")) stretch = OS.PANGO_STRETCH_CONDENSED;
else if (value.equals("semi_condensed")) stretch = OS.PANGO_STRETCH_SEMI_CONDENSED;
else if (value.equals("normal")) stretch = OS.PANGO_STRETCH_NORMAL;
else if (value.equals("semi_expanded")) stretch = OS.PANGO_STRETCH_SEMI_EXPANDED;
else if (value.equals("expanded")) stretch = OS.PANGO_STRETCH_EXPANDED;
else if (value.equals("extra_expanded")) stretch = OS.PANGO_STRETCH_EXTRA_EXPANDED;
else if (value.equals("ultra_expanded")) stretch = OS.PANGO_STRETCH_ULTRA_EXPANDED;
if (stretch != -1) {
OS.pango_font_description_set_stretch(fontDesc, stretch);
createFont = true;
}
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_WEIGHT)))) {
// weight of the characters
int weight = Integer.parseInt(value);
OS.pango_font_description_set_weight(fontDesc, weight);
createFont = true;
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_FG_COLOR)))) {
// RGB value of the format "u,u,u"
style.foreground = colorFromString(display, value);
} else if (name.equals(getString(ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_BG_COLOR)))) {
// RGB value of the format "u,u,u"
style.background = colorFromString(display, value);
} else {
//TODO language and direction
}
} catch (NumberFormatException ex) {}
}
current = OS.g_slist_next (current);
}
if (createFont) {
style.font = Font.gtk_new(display, fontDesc);
}
AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(accessible);
event.start = (int)start_offset;
event.end = (int)end_offset;
event.textStyle = style;
event.attributes = attributes;
for (int i = 0; i < length; i++) {
AccessibleEditableTextListener listener = listeners.get(i);
listener.setTextAttributes(event);
}
if (style.font != null) {
style.font.dispose();
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkEditableTextIface iface = getParentEditableTextIface (atkObject);
if (iface != null && iface.set_run_attributes != 0) {
parentResult = OS.call (iface.set_run_attributes, atkObject, attrib_set, start_offset, end_offset);
}
return parentResult;
}
/*
* Return a Color given a string of the form "n,n,n".
* @param display must be the display for the accessible's control
* @param rgbString must not be null
*/
static Color colorFromString(Display display, String rgbString) {
try {
int comma1 = rgbString.indexOf(',');
int comma2 = rgbString.indexOf(',', comma1 + 1);
int r = Integer.parseInt(rgbString.substring(0, comma1));
int g = Integer.parseInt(rgbString.substring(comma1 + 1, comma2));
int b = Integer.parseInt(rgbString.substring(comma2 + 1, rgbString.length()));
return new Color(r, g, b);
} catch (NumberFormatException ex) {}
return null;
}
/**
* Sets text contents of the atkObject.
*
* 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 string the text to be set
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkEditableText_set_text_contents (long atkObject, long string) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleEditableTextListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(accessible);
event.start = 0;
String text = object.getText ();
event.end = text == null ? 0 : text.length ();
event.string = getString (string);
for (int i = 0; i < length; i++) {
AccessibleEditableTextListener listener = listeners.get(i);
listener.replaceText(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkEditableTextIface iface = getParentEditableTextIface (atkObject);
if (iface != null && iface.set_text_contents != 0) {
parentResult = ATK.call (iface.set_text_contents, atkObject, string);
}
return parentResult;
}
/**
* Inserts text at a given position.
*
* 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 string the text to insert
* @param string_length the length of the text to insert, in bytes
* @param position the caller initializes this to the position at which to
* insert the text. After the call, it points at the position after the
* newly inserted text.
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkEditableText_insert_text (long atkObject, long string,
long string_length, long position) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleEditableTextListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(accessible);
int[] pos = new int [1];
C.memmove (pos, position, C.PTR_SIZEOF);
event.start = event.end = pos[0];
event.string = getString (string);
for (int i = 0; i < length; i++) {
AccessibleEditableTextListener listener = listeners.get(i);
listener.replaceText(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkEditableTextIface iface = getParentEditableTextIface (atkObject);
if (iface != null && iface.insert_text != 0) {
parentResult = OS.call (iface.insert_text, atkObject, string, string_length, position);
}
return parentResult;
}
/**
* Copies text from start_pos up to (but not including) end_pos
* into the clipboard.
*
* 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 start_pos the start position of the text to be copied
* @param end_pos the end position of the text to be copied
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkEditableText_copy_text(long atkObject, long start_pos, long end_pos) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleEditableTextListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(accessible);
event.start = (int)start_pos;
event.end = (int)end_pos;
for (int i = 0; i < length; i++) {
AccessibleEditableTextListener listener = listeners.get(i);
listener.copyText(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkEditableTextIface iface = getParentEditableTextIface (atkObject);
if (iface != null && iface.copy_text != 0) {
parentResult = ATK.call (iface.copy_text, atkObject, start_pos, end_pos);
}
return parentResult;
}
/**
* Cuts text from start_pos up to (but not including) end_pos
* into the clipboard.
*
* 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 start_pos the start position of the text to be cut
* @param end_pos the end position of the text to be cut
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkEditableText_cut_text (long atkObject, long start_pos, long end_pos) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleEditableTextListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(accessible);
event.start = (int)start_pos;
event.end = (int)end_pos;
for (int i = 0; i < length; i++) {
AccessibleEditableTextListener listener = listeners.get(i);
listener.cutText(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkEditableTextIface iface = getParentEditableTextIface (atkObject);
if (iface != null && iface.cut_text != 0) {
parentResult = ATK.call (iface.cut_text, atkObject, start_pos, end_pos);
}
return parentResult;
}
/**
* Delete text start_pos up to (but not including) end_pos.
*
* 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 start_pos the start position of the text to be deleted
* @param end_pos the end position of the text to be deleted
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkEditableText_delete_text (long atkObject, long start_pos, long end_pos) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleEditableTextListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(accessible);
event.start = (int)start_pos;
event.end = (int)end_pos;
event.string = "";
for (int i = 0; i < length; i++) {
AccessibleEditableTextListener listener = listeners.get(i);
listener.replaceText(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkEditableTextIface iface = getParentEditableTextIface (atkObject);
if (iface != null && iface.delete_text != 0) {
parentResult = ATK.call (iface.delete_text, atkObject, start_pos, end_pos);
}
return parentResult;
}
/**
* Paste text from clipboard to specified position.
*
* 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 position the position to paste
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkEditableText_paste_text (long atkObject, long position) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleEditableTextListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(accessible);
event.start = (int)position;
for (int i = 0; i < length; i++) {
AccessibleEditableTextListener listener = listeners.get(i);
listener.pasteText(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkEditableTextIface iface = getParentEditableTextIface (atkObject);
if (iface != null && iface.paste_text != 0) {
parentResult = ATK.call (iface.paste_text, atkObject, position);
}
return parentResult;
}
/**
* Fills a Java AtkHypertextIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkHypertextIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkHypertextIface getParentHypertextIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type();
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_HYPERTEXT())) {
AtkHypertextIface iface = new AtkHypertextIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_HYPERTEXT_GET_IFACE (atkObject)));
return iface;
}
return null;
}
/**
* Gets the link in this hypertext document at index link_index.
*
* 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 link_index the index of the link
*
* @return a pointer to the AtkHypertext at link_index in atkObject
*/
static long atkHypertext_get_link (long atkObject, long link_index) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.index = (int)link_index;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getHyperlink(event);
}
Accessible result = event.accessible;
return result != null ? result.getAccessibleObject().atkHandle : 0;
}
}
long parentResult = 0;
AtkHypertextIface iface = getParentHypertextIface (atkObject);
if (iface != null && iface.get_link != 0) {
parentResult = ATK.call (iface.get_link, atkObject, link_index);
}
return parentResult;
}
/**
* Gets the number of links in this hypertext document.
*
* 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
*
* @return an integer representing the number of links in the hypertext
* in atkObject
*/
static long atkHypertext_get_n_links (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getHyperlinkCount(event);
}
return event.count;
}
}
long parentResult = 0;
AtkHypertextIface iface = getParentHypertextIface (atkObject);
if (iface != null && iface.get_n_links != 0) {
parentResult = ATK.call (iface.get_n_links, atkObject);
}
return parentResult;
}
/**
* Gets the index into the array of hyperlinks that is
* associated with the character specified by char_index.
*
* 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 char_index a character index
*
* @return an integer representing the index into the array of
* hypertexts
*/
static long atkHypertext_get_link_index (long atkObject, long char_index) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.offset = (int)char_index;
event.index = -1;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getHyperlinkIndex(event);
}
return event.index;
}
}
long parentResult = 0;
AtkHypertextIface iface = getParentHypertextIface (atkObject);
if (iface != null && iface.get_link_index != 0) {
parentResult = ATK.call (iface.get_link_index, atkObject, char_index);
}
return parentResult;
}
/**
* Fills a Java AtkObjectClass struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkObjectClass object representing the class struct of atkObject's
* parent
*/
static AtkObjectClass getParentAtkObjectClass () {
AtkObjectClass objectClass = new AtkObjectClass ();
long type = OS.swt_fixed_accessible_get_type();
if (type != 0) {
long parentType = OS.g_type_parent (type);
if (parentType != 0) ATK.memmove (objectClass, OS.g_type_class_peek (parentType));
}
return objectClass;
}
/**
* Gets the accessible description of the widget associated with
* atkObject.
*
* 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
*
* @return a pointer to the gchar representation of the accessible description
*/
static long atkObject_get_description (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.get_description != 0) {
parentResult = ATK.call (objectClass.get_description, atkObject);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEvent event = new AccessibleEvent (accessible);
event.childID = object.id;
if (parentResult != 0) event.result = getString (parentResult);
for (int i = 0; i < length; i++) {
AccessibleListener listener = listeners.get (i);
listener.getDescription (event);
}
if (event.result == null) return parentResult;
if (descriptionPtr != -1) OS.g_free (descriptionPtr);
return descriptionPtr = getStringPtr (event.result);
}
}
return parentResult;
}
/**
* Get a list of properties applied to this object as a whole,
* as an AtkAttributeSet consisting of name-value pairs.
*
* 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
*
* @return a pointer to the AtkAttributeSet consisting of all properties
* applied to atkObject (can be empty if no properties are set)
*/
static long atkObject_get_attributes (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.get_attributes != 0) {
parentResult = ATK.call (objectClass.get_attributes, atkObject);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleAttributeListeners;
int length = size(listeners);
if (length > 0) {
AccessibleAttributeEvent event = new AccessibleAttributeEvent (accessible);
event.topMargin = event.bottomMargin = event.leftMargin = event.rightMargin = event.alignment
= event.indent = event.groupLevel = event.groupCount = event.groupIndex = -1;
for (int i = 0; i < length; i++) {
AccessibleAttributeListener listener = listeners.get (i);
listener.getAttributes (event);
}
AtkAttribute attr = new AtkAttribute();
if (event.leftMargin != -1) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_LEFT_MARGIN));
attr.value = getStringPtr (String.valueOf(event.leftMargin));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (event.rightMargin != -1) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_RIGHT_MARGIN));
attr.value = getStringPtr (String.valueOf(event.rightMargin));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (event.topMargin != -1) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = getStringPtr ("top-margin"); //$NON-NLS-1$
attr.value = getStringPtr (String.valueOf(event.topMargin));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (event.bottomMargin != -1) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = getStringPtr ("bottom-margin"); //$NON-NLS-1$
attr.value = getStringPtr (String.valueOf(event.bottomMargin));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (event.indent != -1) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_INDENT));
attr.value = getStringPtr (String.valueOf(event.indent));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (event.justify) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_JUSTIFICATION));
attr.value = getStringPtr ("fill"); //$NON-NLS-1$
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
} else if (event.alignment != -1) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_JUSTIFICATION));
String str = "left"; //$NON-NLS-1$
switch (event.alignment) {
case SWT.LEFT: str = "left"; break; //$NON-NLS-1$
case SWT.RIGHT: str = "right"; break; //$NON-NLS-1$
case SWT.CENTER: str = "center"; break; //$NON-NLS-1$
}
attr.value = getStringPtr (str);
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
//TODO - tabStops
/* Check for group attributes. */
int level = (event.groupLevel != -1) ? event.groupLevel : 0;
int setsize = (event.groupCount != -1) ? event.groupCount : 0;
int posinset = (event.groupIndex != -1) ? event.groupIndex : 0;
if (setsize == 0 && posinset == 0) {
/* Determine position and count for radio buttons. */
Control control = accessible.control;
if (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) {
Control [] children = control.getParent().getChildren();
posinset = 1;
setsize = 1;
for (int i = 0; i < children.length; i++) {
Control child = children[i];
if (child instanceof Button && ((child.getStyle() & SWT.RADIO) != 0)) {
if (child == control) posinset = setsize;
else setsize++;
}
}
}
}
if (level != 0) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = getStringPtr ("level"); //$NON-NLS-1$
attr.value = getStringPtr (String.valueOf(level));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (setsize != 0) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = getStringPtr ("setsize"); //$NON-NLS-1$
attr.value = getStringPtr (String.valueOf(setsize));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (posinset != 0) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = getStringPtr ("posinset"); //$NON-NLS-1$
attr.value = getStringPtr (String.valueOf(posinset));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
if (event.attributes != null) {
int end = event.attributes.length / 2 * 2;
for (int i = 0; i < end; i+= 2) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = getStringPtr (event.attributes[i]);
attr.value = getStringPtr (event.attributes[i + 1]);
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
parentResult = OS.g_slist_append(parentResult, attrPtr);
}
}
}
}
return parentResult;
}
/**
* Gets the accessible name of the widget associated with
* atkObject.
*
* 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
*
* @return a pointer to the gchar representation of the accessible name
*/
static long atkObject_get_name (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.get_name != 0) {
parentResult = ATK.call (objectClass.get_name, atkObject);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleListeners;
int length = size(listeners);
if (length > 0) {
AccessibleEvent event = new AccessibleEvent (accessible);
event.childID = object.id;
if (parentResult != 0) event.result = getString (parentResult);
for (int i = 0; i < length; i++) {
AccessibleListener listener = listeners.get (i);
listener.getName (event);
}
if (event.result == null) return parentResult;
if (namePtr != -1) OS.g_free (namePtr);
return namePtr = getStringPtr (event.result);
}
}
return parentResult;
}
/**
* Gets the number of accessible children of the widget associated with
* atkObject.
*
* 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
*
* @return an int representing the number of accessible children associated
* with atkObject
*/
static long atkObject_get_n_children (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.get_n_children != 0) {
parentResult = ATK.call (objectClass.get_n_children, atkObject);
}
if (object != null && object.id == ACC.CHILDID_SELF) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
event.detail = (int)parentResult;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getChildCount (event);
}
return event.detail;
}
}
return parentResult;
}
/**
* Gets the 0-based index of the widget (associated with atkObject)
* in its parent.
*
* 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
*
* @return an int which is the index of the accessible atkObject in its
* parent
*/
static long atkObject_get_index_in_parent (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
AccessibleControlEvent event = new AccessibleControlEvent(accessible);
event.childID = ACC.CHILDID_CHILD_INDEX;
event.detail = -1;
for (int i = 0; i < size(listeners); i++) {
AccessibleControlListener listener = listeners.get(i);
listener.getChild(event);
}
if (event.detail != -1) {
return event.detail;
}
if (object.index != -1) {
return object.index;
}
}
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.get_index_in_parent == 0) return 0;
long result = ATK.call (objectClass.get_index_in_parent, atkObject);
return result;
}
/**
* Gets the accessible parent of the widget associated with
* atkObject.
*
* 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
*
* @return a pointer to the AtkObject representing the accessible parent of
* atkObject
*/
static long atkObject_get_parent (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
if (object.parent != null) {
return object.parent.atkHandle;
}
}
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.get_parent == 0) return 0;
long parentResult = ATK.call (objectClass.get_parent, atkObject);
return parentResult;
}
/**
* Gets the role of the accessible associated with atkObject.
*
* 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
*
* @return the AtkRole of atkObject
*/
static long atkObject_get_role (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
event.detail = -1;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getRole (event);
}
if (event.detail != -1) {
switch (event.detail) {
/* Convert from win32 role values to atk role values */
case ACC.ROLE_CHECKBUTTON: return ATK.ATK_ROLE_CHECK_BOX;
case ACC.ROLE_CLIENT_AREA: return ATK.ATK_ROLE_DRAWING_AREA;
case ACC.ROLE_COMBOBOX: return ATK.ATK_ROLE_COMBO_BOX;
case ACC.ROLE_DIALOG: return ATK.ATK_ROLE_DIALOG;
case ACC.ROLE_LABEL: return ATK.ATK_ROLE_LABEL;
case ACC.ROLE_LINK: return ATK.ATK_ROLE_TEXT;
case ACC.ROLE_LIST: return ATK.ATK_ROLE_LIST;
case ACC.ROLE_LISTITEM: return ATK.ATK_ROLE_LIST_ITEM;
case ACC.ROLE_MENU: return ATK.ATK_ROLE_MENU;
case ACC.ROLE_MENUBAR: return ATK.ATK_ROLE_MENU_BAR;
case ACC.ROLE_MENUITEM: return ATK.ATK_ROLE_MENU_ITEM;
case ACC.ROLE_PROGRESSBAR: return ATK.ATK_ROLE_PROGRESS_BAR;
case ACC.ROLE_PUSHBUTTON: return ATK.ATK_ROLE_PUSH_BUTTON;
case ACC.ROLE_SCROLLBAR: return ATK.ATK_ROLE_SCROLL_BAR;
case ACC.ROLE_SEPARATOR: return ATK.ATK_ROLE_SEPARATOR;
case ACC.ROLE_SLIDER: return ATK.ATK_ROLE_SLIDER;
case ACC.ROLE_TABLE: return ATK.ATK_ROLE_TABLE;
case ACC.ROLE_TABLECELL: return ATK.ATK_ROLE_TABLE_CELL;
case ACC.ROLE_TABLECOLUMNHEADER: return ATK.ATK_ROLE_TABLE_COLUMN_HEADER;
case ACC.ROLE_TABLEROWHEADER: return ATK.ATK_ROLE_TABLE_ROW_HEADER;
case ACC.ROLE_TABFOLDER: return ATK.ATK_ROLE_PAGE_TAB_LIST;
case ACC.ROLE_TABITEM: return ATK.ATK_ROLE_PAGE_TAB;
case ACC.ROLE_TEXT: return ATK.ATK_ROLE_TEXT;
case ACC.ROLE_TOOLBAR: return ATK.ATK_ROLE_TOOL_BAR;
case ACC.ROLE_TOOLTIP: return ATK.ATK_ROLE_TOOL_TIP;
case ACC.ROLE_TREE: return ATK.ATK_ROLE_TREE;
case ACC.ROLE_TREEITEM: return ATK.ATK_ROLE_LIST_ITEM;
case ACC.ROLE_RADIOBUTTON: return ATK.ATK_ROLE_RADIO_BUTTON;
case ACC.ROLE_SPLITBUTTON: return ATK.ATK_ROLE_PUSH_BUTTON;
case ACC.ROLE_WINDOW: return ATK.ATK_ROLE_WINDOW;
case ACC.ROLE_ROW: return ATK.ATK_ROLE_TABLE_ROW;
case ACC.ROLE_COLUMN: return ATK.ATK_ROLE_UNKNOWN; //Column role doesn't exist on Gtk.
case ACC.ROLE_ALERT: return ATK.ATK_ROLE_ALERT;
case ACC.ROLE_ANIMATION: return ATK.ATK_ROLE_ANIMATION;
case ACC.ROLE_CANVAS: return ATK.ATK_ROLE_CANVAS;
case ACC.ROLE_GROUP: return ATK.ATK_ROLE_PANEL;
case ACC.ROLE_SPINBUTTON: return ATK.ATK_ROLE_SPIN_BUTTON;
case ACC.ROLE_STATUSBAR: return ATK.ATK_ROLE_STATUSBAR;
case ACC.ROLE_CHECKMENUITEM: return ATK.ATK_ROLE_CHECK_MENU_ITEM;
case ACC.ROLE_RADIOMENUITEM: return ATK.ATK_ROLE_RADIO_MENU_ITEM;
case ACC.ROLE_CLOCK: return ATK.ATK_ROLE_UNKNOWN;
case ACC.ROLE_CALENDAR: return ATK.ATK_ROLE_CALENDAR;
case ACC.ROLE_DATETIME: return ATK.ATK_ROLE_DATE_EDITOR;
case ACC.ROLE_FOOTER: return ATK.ATK_ROLE_FOOTER;
case ACC.ROLE_FORM: return ATK.ATK_ROLE_FORM;
case ACC.ROLE_HEADER: return ATK.ATK_ROLE_HEADER;
case ACC.ROLE_HEADING: return ATK.ATK_ROLE_HEADING;
case ACC.ROLE_PAGE: return ATK.ATK_ROLE_PAGE;
case ACC.ROLE_PARAGRAPH: return ATK.ATK_ROLE_PARAGRAPH;
case ACC.ROLE_SECTION: return ATK.ATK_ROLE_SECTION;
case ACC.ROLE_DOCUMENT: return ATK.ATK_ROLE_DOCUMENT_FRAME;
case ACC.ROLE_GRAPHIC: return ATK.ATK_ROLE_IMAGE;
}
}
}
}
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.get_role == 0) return 0;
return ATK.call (objectClass.get_role, atkObject);
}
/**
* Gets a reference to the accessible child whose parent is atkObject.
*
* 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 index the index of the child
*
* @return a pointer to the AtkObject of the child at the provided index
*/
static long atkObject_ref_child (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null && object.id == ACC.CHILDID_SELF) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
AccessibleControlEvent event = new AccessibleControlEvent(accessible);
event.childID = ACC.CHILDID_CHILD_AT_INDEX;
event.detail = (int)index;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get(i);
listener.getChild(event);
}
if (event.accessible != null) {
AccessibleObject accObject = event.accessible.getAccessibleObject();
if (accObject != null) {
return OS.g_object_ref (accObject.atkHandle);
}
}
}
object.updateChildren ();
AccessibleObject accObject = object.getChildByIndex ((int)index);
if (accObject != null) {
return OS.g_object_ref (accObject.atkHandle);
}
}
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.ref_child == 0) return 0;
return ATK.call (objectClass.ref_child, atkObject, index);
}
/**
* Gets a reference to the state set of the accessible associated with
* atkObject.
*
* 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
*
* @return a pointer to the AtkStateSet for the accessible widget atkObject
*/
static long atkObject_ref_state_set (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkObjectClass objectClass = getParentAtkObjectClass ();
if (objectClass.ref_state_set != 0) {
parentResult = ATK.call (objectClass.ref_state_set, atkObject);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
long set = parentResult;
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
event.detail = -1;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getState (event);
}
if (event.detail != -1) {
/* Convert from win32 state values to atk state values */
int state = event.detail;
if ((state & ACC.STATE_BUSY) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_BUSY);
if ((state & ACC.STATE_CHECKED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_CHECKED);
if ((state & ACC.STATE_EXPANDED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_EXPANDED);
if ((state & ACC.STATE_FOCUSABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_FOCUSABLE);
if ((state & ACC.STATE_FOCUSED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_FOCUSED);
if ((state & ACC.STATE_HOTTRACKED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_ARMED);
if ((state & ACC.STATE_INVISIBLE) == 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_VISIBLE);
if ((state & ACC.STATE_MULTISELECTABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_MULTISELECTABLE);
if ((state & ACC.STATE_OFFSCREEN) == 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SHOWING);
if ((state & ACC.STATE_PRESSED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_PRESSED);
if ((state & ACC.STATE_READONLY) == 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_EDITABLE);
if ((state & ACC.STATE_SELECTABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SELECTABLE);
if ((state & ACC.STATE_SELECTED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SELECTED);
if ((state & ACC.STATE_SIZEABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_RESIZABLE);
if ((state & ACC.STATE_DISABLED) == 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_ENABLED);
if ((state & ACC.STATE_ACTIVE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_ACTIVE);
if ((state & ACC.STATE_SINGLELINE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SINGLE_LINE);
if ((state & ACC.STATE_MULTILINE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_MULTI_LINE);
if ((state & ACC.STATE_REQUIRED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_REQUIRED);
if ((state & ACC.STATE_INVALID_ENTRY) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_INVALID_ENTRY);
if ((state & ACC.STATE_SUPPORTS_AUTOCOMPLETION) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SUPPORTS_AUTOCOMPLETION);
/* Note: STATE_COLLAPSED, STATE_LINKED and STATE_NORMAL have no ATK equivalents */
}
return set;
}
}
return parentResult;
}
/**
* Fills a Java AtkSelectionIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkSelectionIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkSelectionIface getParentSelectionIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type() ;
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_SELECTION())) {
AtkSelectionIface iface = new AtkSelectionIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_SELECTION_GET_IFACE (atkObject)));
return iface;
}
return null;
}
/**
* Determines if the current child of this atkObject is selected.
*
* 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 index a long integer representing the index
*
* @return a long integer where 1 represents TRUE, 0 otherwise
*/
static long atkSelection_is_child_selected (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkSelectionIface iface = getParentSelectionIface (atkObject);
if (iface != null && iface.is_child_selected != 0) {
parentResult = ATK.call (iface.is_child_selected, atkObject, index);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getSelection (event);
}
Accessible result = event.accessible;
AccessibleObject accessibleObject = result != null ? result.getAccessibleObject() : object.getChildByID (event.childID);
if (accessibleObject != null) {
return accessibleObject.index == index ? 1 : 0;
}
}
}
return parentResult;
}
/**
* Gets a reference to the atkObject representing the specified
* selected child of the object.
*
* 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 index a long integer representing the index
*
* @return a pointer to the AtkObject representing the selected accessible,
* or 0
*/
static long atkSelection_ref_selection (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkSelectionIface iface = getParentSelectionIface (atkObject);
if (iface != null && iface.ref_selection != 0) {
parentResult = ATK.call (iface.ref_selection, atkObject, index);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = object.id;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getSelection (event);
}
AccessibleObject accObj = object.getChildByID (event.childID);
if (accObj != null) {
if (parentResult != 0) OS.g_object_unref (parentResult);
OS.g_object_ref (accObj.atkHandle);
return accObj.atkHandle;
}
}
}
return parentResult;
}
/**
* Fills a Java AtkTableIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkTableIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkTableIface getParentTableIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type();
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_TABLE())) {
AtkTableIface iface = new AtkTableIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_TABLE_GET_IFACE (atkObject)));
return iface;
}
return null;
}
/**
* Get a reference to the table cell at row, column.
*
* 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 row a long integer representing a row in atkObject
* @param column a long integer representing a column in atkObject
*
* @return a pointer to an AtkObject representing the specified table
*/
static long atkTable_ref_at (long atkObject, long row, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getCell(event);
}
Accessible result = event.accessible;
if (result != null) {
AccessibleObject accessibleObject = result.getAccessibleObject();
OS.g_object_ref(accessibleObject.atkHandle);
return accessibleObject.atkHandle;
}
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.ref_at != 0) {
parentResult = ATK.call (iface.ref_at, atkObject, row, column);
}
return parentResult;
}
/**
* Get a reference to the table cell at row, column.
*
* 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 row a long integer representing a row in atkObject
* @param column a long integer representing a column in atkObject
*
* @return a pointer to an AtkObject representing the specified table
*/
static long atkTable_get_index_at (long atkObject, long row, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getCell(event);
}
Accessible result = event.accessible;
if (result == null) return -1;
event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getColumnCount(event);
}
return row * event.count + column;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_index_at != 0) {
parentResult = ATK.call (iface.get_index_at, atkObject, row, column);
}
return parentResult;
}
/**
* Gets a gint representing the column at the specified index.
*
* 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 index a long integer representing an index in the table
*
* @return a long integer representing the column at the specified index, or
* -1
*/
static long atkTable_get_column_at_index (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getColumnCount(event);
}
long result = event.count == 0 ? -1 : index % event.count;
return result;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_column_at_index != 0) {
parentResult = ATK.call (iface.get_column_at_index, atkObject, index);
}
return parentResult;
}
/**
* Gets a gint representing the row at the specified index.
*
* 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 index a long integer representing an index in the table
*
* @return a long integer representing the row at the specified index, or
* -1
*/
static long atkTable_get_row_at_index (long atkObject, long index) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getColumnCount(event);
}
long result = event.count == 0 ? -1 : index / event.count;
return result;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_row_at_index != 0) {
parentResult = ATK.call (iface.get_row_at_index, atkObject, index);
}
return parentResult;
}
/**
* Gets the number of columns in the table.
*
* 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
*
* @return a long integer representing the number of columns, or
* 0
*/
static long atkTable_get_n_columns (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_n_columns != 0) {
parentResult = ATK.call (iface.get_n_columns, atkObject);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.count = (int)parentResult;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getColumnCount(event);
parentResult = event.count;
}
}
}
return parentResult;
}
/**
* Gets the number of rows in the table.
*
* 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
*
* @return a long integer representing the number of rows, or
* 0
*/
static long atkTable_get_n_rows (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_n_rows != 0) {
parentResult = ATK.call (iface.get_n_rows, atkObject);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.count = (int)parentResult;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getRowCount(event);
parentResult = event.count;
}
}
}
return parentResult;
}
/**
* Gets the number of columns occupied at the specified row
* and column.
*
* 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 row a long integer representing the row
* @param column a long integer representing the column
*
* @return a long integer representing the column extent at the
* specified position, or 0
*/
static long atkTable_get_column_extent_at (long atkObject, long row, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_column_extent_at != 0) {
parentResult = ATK.call (iface.get_column_extent_at, atkObject, row, column);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getCell(event);
}
Accessible result = event.accessible;
if (result != null) {
List listeners2 = result.accessibleTableCellListeners;
length = size(listeners2);
if (length > 0) {
AccessibleTableCellEvent cellEvent = new AccessibleTableCellEvent(result);
cellEvent.count = (int)parentResult;
for (int i = 0; i < length; i++) {
AccessibleTableCellListener listener = listeners2.get(i);
listener.getColumnSpan(cellEvent);
}
return cellEvent.count;
}
}
}
}
return parentResult;
}
/**
* Gets the number of rows occupied at the specified row
* and column.
*
* 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 row a long integer representing the row
* @param column a long integer representing the column
*
* @return a long integer representing the row extent at the specified
* position, or 0
*/
static long atkTable_get_row_extent_at (long atkObject, long row, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_row_extent_at != 0) {
parentResult = ATK.call (iface.get_row_extent_at, atkObject, row, column);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getCell(event);
}
Accessible result = event.accessible;
if (result != null) {
List listeners2 = result.accessibleTableCellListeners;
length = size(listeners2);
if (length > 0) {
AccessibleTableCellEvent cellEvent = new AccessibleTableCellEvent(result);
cellEvent.count = (int)parentResult;
for (int i = 0; i < length; i++) {
AccessibleTableCellListener listener = listeners2.get(i);
listener.getRowSpan(cellEvent);
}
return cellEvent.count;
}
}
}
}
return parentResult;
}
/**
* Gets the caption for the table.
*
* 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
*
* @return a pointer to the AtkObject representing the caption, or 0
*/
static long atkTable_get_caption (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getCaption(event);
}
Accessible result = event.accessible;
if (result != null) return result.getAccessibleObject().atkHandle;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_caption != 0) {
parentResult = ATK.call (iface.get_caption, atkObject);
}
return parentResult;
}
/**
* Gets the summary for the table.
*
* 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
*
* @return a pointer to the AtkObject representing the summary, or 0
*/
static long atkTable_get_summary (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getSummary(event);
}
Accessible result = event.accessible;
if (result != null) return result.getAccessibleObject().atkHandle;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_summary != 0) {
parentResult = ATK.call (iface.get_summary, atkObject);
}
return parentResult;
}
/**
* Gets the description text of the specified column.
*
* 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 column a long integer representing the specified column
*
* @return a pointer to the gchar representation of the column description,
* or 0
*/
static long atkTable_get_column_description (long atkObject, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_column_description != 0) {
parentResult = ATK.call (iface.get_column_description, atkObject, column);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.column = (int)column;
if (parentResult != 0) event.result = getString (parentResult);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getColumnDescription(event);
}
if (event.result == null) return parentResult;
if (descriptionPtr != -1) OS.g_free (descriptionPtr);
return descriptionPtr = getStringPtr (event.result);
}
}
return parentResult;
}
/**
* Gets the column header of a specified column.
*
* 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 column a long integer representing the specified column
*
* @return a pointer to the AtkObject representing the specified column
* header, or 0
*/
static long atkTable_get_column_header (long atkObject, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getRowHeaderCells(event);
}
Accessible[] accessibles = event.accessibles;
if (accessibles != null) {
if (0 <= column && column < accessibles.length) {
return accessibles[(int)column].getAccessibleObject().atkHandle;
}
}
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_column_header != 0) {
parentResult = ATK.call (iface.get_column_header, atkObject, column);
}
return parentResult;
}
/**
* Gets the description text of the specified row.
*
* 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 row a long integer representing the specified row
*
* @return a pointer to the gchar representation of the row description,
* or 0
*/
static long atkTable_get_row_description (long atkObject, long row) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_row_description != 0) {
parentResult = ATK.call (iface.get_row_description, atkObject, row);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
if (parentResult != 0) event.result = getString (parentResult);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getRowDescription(event);
}
if (event.result == null) return parentResult;
if (descriptionPtr != -1) OS.g_free (descriptionPtr);
return descriptionPtr = getStringPtr (event.result);
}
}
return parentResult;
}
/**
* Gets the column header of a specified row.
*
* 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 row a long integer representing the specified row
*
* @return a pointer to the AtkObject representing the specified row
* header, or 0
*/
static long atkTable_get_row_header (long atkObject, long row) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getRowHeaderCells(event);
}
Accessible[] accessibles = event.accessibles;
if (accessibles != null) {
if (0 <= row && row < accessibles.length) {
return accessibles[(int)row].getAccessibleObject().atkHandle;
}
}
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_row_header != 0) {
parentResult = ATK.call (iface.get_row_header, atkObject, row);
}
return parentResult;
}
/**
* Gets the selected columns of the table.
*
* 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 selected an array of integer pointers that is to contain the
* selected column numbers
*
* @return a long integer representing the number of columns selected,
* or 0
*/
static long atkTable_get_selected_columns (long atkObject, long selected) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getSelectedColumns(event);
}
int count = event.selected != null ? event.selected.length : 0;
long result = OS.g_malloc(count * 4);
if (event.selected != null) C.memmove(result, event.selected, count * 4);
if (selected != 0) C.memmove(selected, new long []{result}, C.PTR_SIZEOF);
return count;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_selected_columns != 0) {
parentResult = ATK.call (iface.get_selected_columns, atkObject, selected);
}
return parentResult;
}
/**
* Gets the selected rows of the table.
*
* 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 selected an array of integer pointers that is to contain the
* selected row numbers
*
* @return a long integer representing the number of rows selected,
* or 0
*/
static long atkTable_get_selected_rows (long atkObject, long selected) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getSelectedRows(event);
}
int count = event.selected != null ? event.selected.length : 0;
long result = OS.g_malloc(count * 4);
if (event.selected != null) C.memmove(result, event.selected, count * 4);
if (selected != 0) C.memmove(selected, new long []{result}, C.PTR_SIZEOF);
return count;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.get_selected_rows != 0) {
parentResult = ATK.call (iface.get_selected_rows, atkObject, selected);
}
return parentResult;
}
/**
* Determines if the specified column is selected.
*
* 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 column a long integer representing the column
*
* @return a long integer where 1 represents TRUE, 0 otherwise
*/
static long atkTable_is_column_selected (long atkObject, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.is_column_selected != 0) {
parentResult = ATK.call (iface.is_column_selected, atkObject, column);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.isSelected = parentResult != 0;
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.isColumnSelected(event);
}
return event.isSelected ? 1 : 0;
}
}
return parentResult;
}
/**
* Determines if the specified row is selected.
*
* 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 row a long integer representing the row
*
* @return a long integer where 1 represents TRUE, 0 otherwise
*/
static long atkTable_is_row_selected (long atkObject, long row) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.is_row_selected != 0) {
parentResult = ATK.call (iface.is_row_selected, atkObject, row);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.isSelected = parentResult != 0;
event.row = (int)row;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.isRowSelected(event);
}
return event.isSelected ? 1 : 0;
}
}
return parentResult;
}
/**
* Determines if the AtkObject at the specified
* column and row is selected.
*
* 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 row a long integer representing the row
* @param column a long integer representing the column
*
* @return a long integer where 1 represents TRUE, 0 otherwise
*/
static long atkTable_is_selected (long atkObject, long row, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.is_selected != 0) {
parentResult = ATK.call (iface.is_selected, atkObject, row, column);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.getCell(event);
}
Accessible result = event.accessible;
if (result != null) {
List listeners2 = result.accessibleTableCellListeners;
length = size(listeners2);
if (length > 0) {
AccessibleTableCellEvent cellEvent = new AccessibleTableCellEvent(result);
cellEvent.isSelected = parentResult != 0;
for (int i = 0; i < length; i++) {
AccessibleTableCellListener listener = listeners2.get(i);
listener.isSelected(cellEvent);
}
return cellEvent.isSelected ? 1 : 0;
}
}
}
}
return parentResult;
}
/**
* Adds the specified row to the selection.
*
* 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 row a long integer representing the row
*
* @return a long int representing whether the action succeeded: 1 for success,
* 0 for failure
*/
static long atkTable_add_row_selection (long atkObject, long row) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.selectRow(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.add_row_selection != 0) {
parentResult = ATK.call (iface.add_row_selection, atkObject, row);
}
return parentResult;
}
/**
* Removes the specified row to the selection.
*
* 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 row a long integer representing the row
*
* @return a long int representing whether the action succeeded: 1 for success,
* 0 for failure
*/
static long atkTable_remove_row_selection (long atkObject, long row) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.row = (int)row;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.deselectRow(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.remove_row_selection != 0) {
parentResult = ATK.call (iface.remove_row_selection, atkObject, row);
}
return parentResult;
}
/**
* Adds the specified column to the selection.
*
* 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 column a long integer representing the column
*
* @return a long int representing whether the action succeeded: 1 for success,
* 0 for failure
*/
static long atkTable_add_column_selection (long atkObject, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.selectColumn(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.add_column_selection != 0) {
parentResult = ATK.call (iface.add_column_selection, atkObject, column);
}
return parentResult;
}
/**
* Removes the specified column to the selection.
*
* 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 column a long integer representing the column
*
* @return a long int representing whether the action succeeded: 1 for success,
* 0 for failure
*/
static long atkTable_remove_column_selection (long atkObject, long column) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTableListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTableEvent event = new AccessibleTableEvent(accessible);
event.column = (int)column;
for (int i = 0; i < length; i++) {
AccessibleTableListener listener = listeners.get(i);
listener.deselectColumn(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkTableIface iface = getParentTableIface (atkObject);
if (iface != null && iface.remove_column_selection != 0) {
parentResult = ATK.call (iface.remove_column_selection, atkObject, column);
}
return parentResult;
}
/**
* Fills a Java AtkTextIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkTextIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkTextIface getParentTextIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type();
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_TEXT())) {
AtkTextIface iface = new AtkTextIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (atkObject)));
return iface;
}
return null;
}
static String getString (long strPtr) {
int length = C.strlen (strPtr);
byte [] buffer = new byte [length];
C.memmove (buffer, strPtr, length);
return new String (Converter.mbcsToWcs (buffer));
}
static long getStringPtr (String str) {
byte [] buffer = Converter.wcsToMbcs(str != null ? str : "", true);
long ptr = OS.g_malloc(buffer.length);
C.memmove(ptr, buffer, buffer.length);
return ptr;
}
/**
* Get the bounding box containing the glyph representing the character
* at a particular text offset.
*
* 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 offset the offset of the text character for which bounding info
* is required
* @param x the pointer for the x coordinate of the bounding box
* @param y the pointer for the y coordinate of the bounding box
* @param width the pointer for the width of the bounding box
* @param height the pointer for the height of the bounding box
* @param coords long int representing the AtkCoordType for the coordinates
*
* @return a long int representation of 0 indicating that the method completed
* successfully
*/
static long atkText_get_character_extents (long atkObject, long offset,
long x, long y, long width, long height, long coords) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = (int)offset;
event.end = (int)(offset + 1);
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getTextBounds(event);
}
int[] topWindowX = new int [1], topWindowY = new int [1];
if (coords == ATK.ATK_XY_WINDOW) {
windowPoint (object, topWindowX, topWindowY);
event.x -= topWindowX [0];
event.y -= topWindowY [0];
}
C.memmove (x, new int[]{event.x}, 4);
C.memmove (y, new int[]{event.y}, 4);
C.memmove (width, new int[]{event.width}, 4);
C.memmove (height, new int[]{event.height}, 4);
return 0;
}
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_character_extents != 0) {
OS.call (iface.get_character_extents, atkObject, offset, x, y, width, height, coords);
}
return 0;
}
/**
* Get the bounding box for text within the specified range.
*
* 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 start_offset the offset of the first text character for which
* bounding info is required
* @param end_offset the offset of the last text character after the last
* character for which boundary info is required
* @param coord_type long int representing the AtkCoordType for the coordinates
* @param rect a pointer to the AtkTextRectangle which is filled by this function
*
* @return a long int representation of 0 indicating that the method completed
* successfully
*/
static long atkText_get_range_extents (long atkObject, long start_offset,
long end_offset, long coord_type, long rect) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = (int)start_offset;
event.end = (int)end_offset;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getTextBounds(event);
}
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];
}
AtkTextRectangle atkRect = new AtkTextRectangle();
atkRect.x = event.x;
atkRect.y = event.y;
atkRect.width = event.width;
atkRect.height = event.height;
ATK.memmove (rect, atkRect, AtkTextRectangle.sizeof);
return 0;
}
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_range_extents != 0) {
ATK.call (iface.get_range_extents, atkObject, start_offset, end_offset, coord_type, rect);
}
return 0;
}
/**
* Creates an AtkAttributeSet which consists of the attributes explicitly
* set at the position offset in the text.
*
* 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 offset the offset at which to get the attributes
* @param start_offset the address to put the start offset of the range
* @param end_offset the address to put the end offset of the range
*
* @return a pointer to the AtkAttributeSet created
*/
static long atkText_get_run_attributes (long atkObject, long offset,
long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleAttributeListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(accessible);
event.offset = (int)offset;
for (int i = 0; i < length; i++) {
AccessibleAttributeListener listener = listeners.get(i);
listener.getTextAttributes(event);
}
C.memmove (start_offset, new int []{event.start}, 4);
C.memmove (end_offset, new int []{event.end}, 4);
TextStyle style = event.textStyle;
long result = 0;
AtkAttribute attr = new AtkAttribute();
if (style != null) {
if (style.rise != 0) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_RISE));
attr.value = getStringPtr (String.valueOf(style.rise));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
}
if (style.underline) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_UNDERLINE));
String str = "none"; //$NON-NLS-1$
switch (style.underlineStyle) {
case SWT.UNDERLINE_DOUBLE: str = "double"; break; //$NON-NLS-1$
case SWT.UNDERLINE_SINGLE: str = "single"; break; //$NON-NLS-1$
case SWT.UNDERLINE_ERROR: str = "error"; break; //$NON-NLS-1$
case SWT.UNDERLINE_SQUIGGLE: str = "squiggle"; break; //$NON-NLS-1$
}
attr.value = getStringPtr (str);
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
}
if (style.strikeout) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_STRIKETHROUGH));
attr.value = getStringPtr ("1");
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
}
Font font = style.font;
if (font != null && !font.isDisposed()) {
//TODO language and direction
long attrPtr;
attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_FAMILY_NAME));
attr.value = OS.g_strdup (OS.pango_font_description_get_family (font.handle));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_SIZE));
attr.value = getStringPtr (String.valueOf (OS.pango_font_description_get_size(font.handle) / OS.PANGO_SCALE));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_STYLE));
attr.value = OS.g_strdup (ATK.atk_text_attribute_get_value(ATK.ATK_TEXT_ATTR_STYLE, OS.pango_font_description_get_style(font.handle)));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_VARIANT));
attr.value = OS.g_strdup (ATK.atk_text_attribute_get_value(ATK.ATK_TEXT_ATTR_VARIANT, OS.pango_font_description_get_variant(font.handle)));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_STRETCH));
attr.value = OS.g_strdup (ATK.atk_text_attribute_get_value(ATK.ATK_TEXT_ATTR_STRETCH, OS.pango_font_description_get_stretch(font.handle)));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_WEIGHT));
attr.value = getStringPtr (String.valueOf (OS.pango_font_description_get_weight(font.handle)));
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
}
Color color = style.foreground;
if (color != null && !color.isDisposed()) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_FG_COLOR));
attr.value = getStringPtr ((color.handle.red * 255) + "," + (color.handle.green * 255) + "," + (color.handle.blue * 255)); //$NON-NLS-1$ //$NON-NLS-2$
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
}
color = style.background;
if (color != null && !color.isDisposed()) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = OS.g_strdup (ATK.atk_text_attribute_get_name(ATK.ATK_TEXT_ATTR_BG_COLOR));
attr.value = getStringPtr ((color.handle.red * 255) + "," + (color.handle.green * 255) + "," + (color.handle.blue * 255)); //$NON-NLS-1$ //$NON-NLS-2$
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
}
}
if (event.attributes != null) {
int end = event.attributes.length / 2 * 2;
for (int i = 0; i < end; i+= 2) {
long attrPtr = OS.g_malloc(AtkAttribute.sizeof);
attr.name = getStringPtr (event.attributes[i]);
attr.value = getStringPtr (event.attributes[i + 1]);
ATK.memmove(attrPtr, attr, AtkAttribute.sizeof);
result = OS.g_slist_append(result, attrPtr);
}
}
return result;
}
}
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_run_attributes != 0) {
parentResult = OS.call (iface.get_run_attributes, atkObject, offset, start_offset, end_offset);
}
return parentResult;
}
/**
* Gets the offset of the character located at coordinates x and y.
*
* 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 screen x-position of the character
* @param y screen y-position of the character
* @param coords long int representing the AtkCoordType for the coordinates
*
* @return the offset to the character which is located at the specified
* x and y coordinates
*/
static long atkText_get_offset_at_point (long atkObject, long x,
long y, long coords) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.x = (int)x;
event.y = (int)y;
int[] topWindowX = new int [1], topWindowY = new int [1];
if (coords == ATK.ATK_XY_WINDOW) {
windowPoint (object, topWindowX, topWindowY);
event.x += topWindowX [0];
event.y += topWindowY [0];
}
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getOffsetAtPoint(event);
}
return event.offset;
}
}
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_offset_at_point != 0) {
parentResult = OS.call (iface.get_offset_at_point, atkObject, x, y, coords);
}
return parentResult;
}
/**
* Adds a selection bounded by the specified offsets.
*
* 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 start_offset the start position of the selected region
* @param end_offset the offset of the first character after the selected region
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkText_add_selection (long atkObject, long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = (int)start_offset;
event.end = (int)end_offset;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.addSelection(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.add_selection != 0) {
parentResult = ATK.call (iface.add_selection, atkObject, start_offset, end_offset);
}
return parentResult;
}
/**
* Removes the specified selection.
*
* 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 selection_num the selection number.
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkText_remove_selection (long atkObject, long selection_num) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.index = (int)selection_num;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.removeSelection(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.remove_selection != 0) {
parentResult = ATK.call (iface.remove_selection, atkObject, selection_num);
}
return parentResult;
}
/**
* Sets the caret (cursor) position to the specified offset.
*
* 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 offset the position
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkText_set_caret_offset (long atkObject, long offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.offset = (int)offset;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.setCaretOffset(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.set_caret_offset != 0) {
return ATK.call (iface.set_caret_offset, atkObject, offset);
}
return 0;
}
/**
* Changes the start and end offset of the specified selection.
*
* 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 selection_num the selection number
* @param start_offset the new start position of the selection
* @param end_offset the new end position of the selection
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkText_set_selection (long atkObject, long selection_num,
long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.index = (int)selection_num;
event.start = (int)start_offset;
event.end = (int)end_offset;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.setSelection(event);
}
return ACC.OK.equals(event.result) ? 1 : 0;
}
}
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.set_selection != 0) {
parentResult = OS.call (iface.set_selection, atkObject, selection_num, start_offset, end_offset);
}
return parentResult;
}
/**
* Gets the offset position of the caret (cursor).
*
* 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
*
* @return a long int representation of the offset position of the caret (cursor)
*/
static long atkText_get_caret_offset (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_caret_offset != 0) {
parentResult = ATK.call (iface.get_caret_offset, atkObject);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getCaretOffset (event);
}
return event.offset;
}
List listeners2 = accessible.accessibleTextListeners;
length = size(listeners2);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent (object.accessible);
event.childID = object.id;
event.offset = (int)parentResult;
for (int i = 0; i < length; i++) {
AccessibleTextListener listener = listeners2.get(i);
listener.getCaretOffset (event);
}
return event.offset;
}
}
return parentResult;
}
/**
* Get the ranges of text in the specified bounding box.
*
* 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 rect the AtkTextRectangle giving the dimensions of the bounding box
* @param coord_type long int representing the AtkCoordType for the coordinates
* @param x_clip_type a long int representing the AtkTextClipType of the
* horizontal clip
* @param y_clip_type a long int representing the AtkTextClipType of the
* vertical clip
*
* @return a pointer to the array of AtkTextRanges
*/
static long atkText_get_bounded_ranges (long atkObject, long rect,
long coord_type, long x_clip_type, long y_clip_type) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
AtkTextRectangle atkRect = new AtkTextRectangle();
ATK.memmove (atkRect, rect, AtkTextRectangle.sizeof);
event.x = atkRect.x;
event.y = atkRect.y;
event.width = atkRect.width;
event.height = atkRect.height;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getRanges (event);
}
int [] ranges = event.ranges;
int size = ranges == null ? 1 : ranges.length / 2;
long result = C.malloc(size * AtkTextRange.sizeof);
AtkTextRange range = new AtkTextRange();
for (int j = 0, end = (ranges != null ? ranges.length / 2 : 1); j < end; j++) {
if (ranges != null) {
int index = j * 2;
event.start = ranges[index];
event.end = ranges[index+1];
}
event.count = 0;
event.type = ACC.TEXT_BOUNDARY_ALL;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
range.start_offset = event.start;
range.end_offset = event.end;
range.content = getStringPtr (event.result);
event.result = null;
event.count = event.type = event.x = event.y = event.width = event.height = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getTextBounds(event);
}
range.bounds.x = event.x;
range.bounds.y = event.y;
range.bounds.width = event.width;
range.bounds.height = event.height;
ATK.memmove(result + j * AtkTextRange.sizeof, range, AtkTextRange.sizeof);
}
return result;
}
}
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_bounded_ranges != 0) {
parentResult = ATK.call (iface.get_bounded_ranges, atkObject);
}
return parentResult;
}
/**
* Gets the specified text.
*
* 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 offset position
*
* @return a long int representing the character at offset
*/
static long atkText_get_character_at_offset (long atkObject, long offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = (int)offset;
event.end = (int)(offset + 1);
event.type = ACC.TEXT_BOUNDARY_CHAR;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
String text = event.result;
return text != null && text.length() > 0 ? text.charAt(0) : 0;
}
String text = object.getText ();
if (text != null && text.length() > offset) return text.charAt ((int)offset);
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_character_at_offset != 0) {
return ATK.call (iface.get_character_at_offset, atkObject, offset);
}
return 0;
}
/**
* Gets the character count.
*
* 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
*
* @return the number of characters
*/
static long atkText_get_character_count (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getCharacterCount(event);
}
return event.count;
}
String text = object.getText ();
if (text != null) return text.length ();
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_character_count != 0) {
return ATK.call (iface.get_character_count, atkObject);
}
return 0;
}
/**
* Gets the number of selected regions.
*
* 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
*
* @return the number of selected regions, or -1 if a failure occurred
*/
static long atkText_get_n_selections (long atkObject) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getSelectionCount (event);
}
return event.count;
}
List listeners2 = accessible.accessibleTextListeners;
length = size(listeners2);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent (object.accessible);
event.childID = object.id;
for (int i = 0; i < length; i++) {
AccessibleTextListener listener = listeners2.get(i);
listener.getSelectionRange (event);
}
if (event.length > 0) return 1;
}
}
long parentResult = 0;
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_n_selections != 0) {
parentResult = ATK.call (iface.get_n_selections, atkObject);
}
return parentResult;
}
/**
* Gets the text from the specified selection.
*
* 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 selection_num the selection number
* @param start_offset passes back the start position of the selected region
* @param end_offset passes back the end position of the selected region
*
* @return a pointer to the newly allocated string containing the selected text
*/
static long atkText_get_selection (long atkObject, long selection_num,
long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
long parentResult = 0;
C.memmove (start_offset, new int[] {0}, 4);
C.memmove (end_offset, new int[] {0}, 4);
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_selection != 0) {
parentResult = OS.call (iface.get_selection, atkObject, selection_num, start_offset, end_offset);
}
if (object != null) {
int[] parentStart = new int [1];
int[] parentEnd = new int [1];
C.memmove (parentStart, start_offset, 4);
C.memmove (parentEnd, end_offset, 4);
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.index = (int)selection_num;
event.start = parentStart[0];
event.end = parentEnd[0];
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getSelection (event);
}
parentStart [0] = event.start;
parentEnd [0] = event.end;
C.memmove (start_offset, parentStart, 4);
C.memmove (end_offset, parentEnd, 4);
event.count = event.index = 0;
event.type = ACC.TEXT_BOUNDARY_ALL;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
if (parentResult != 0) OS.g_free(parentResult);
return getStringPtr (event.result);
}
if (selection_num == 0) {
List listeners2 = accessible.accessibleTextListeners;
length = size(listeners2);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent (accessible);
event.childID = object.id;
event.offset = parentStart [0];
event.length = parentEnd [0] - parentStart [0];
for (int i = 0; i < length; i++) {
AccessibleTextListener listener = listeners2.get(i);
listener.getSelectionRange (event);
}
C.memmove (start_offset, new int[] {event.offset}, 4);
C.memmove (end_offset, new int[] {event.offset + event.length}, 4);
if (parentResult != 0) OS.g_free(parentResult);
String text = object.getText();
if (text != null && text.length () > event.offset && text.length() >= event.offset + event.length) {
return getStringPtr (text.substring(event.offset, event.offset + event.length));
}
if (iface != null && iface.get_text != 0) {
return ATK.call (iface.get_text, atkObject, event.offset, event.offset + event.length);
}
return 0;
}
}
}
return parentResult;
}
/**
* Gets the specified text.
*
* 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 start_offset start position
* @param end_offset end position, or -1 for the end of the string
*
* @return a pointer to the newly allocated string containing the text
* from start_offset up to (but not including) end_offset
*/
static long atkText_get_text (long atkObject, long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = (int)start_offset;
event.end = (int)end_offset;
event.type = ACC.TEXT_BOUNDARY_ALL;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
return getStringPtr (event.result);
}
String text = object.getText ();
if (text != null && text.length () > 0) {
if (end_offset == -1) {
end_offset = text.length ();
} else {
end_offset = Math.min (end_offset, text.length ());
}
start_offset = Math.min (start_offset, end_offset);
text = text.substring ((int)start_offset, (int)end_offset);
return getStringPtr (text);
}
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_text != 0) {
return ATK.call (iface.get_text, atkObject, start_offset, end_offset);
}
return 0;
}
/**
* Gets the specified text.
*
* 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 offset position
* @param boundary_type the AtkTextBoundary
* @param start_offset the start offset of the returned string
* @param end_offset the end_offset of the first character after the returned string
*
* @return a pointer to the newly allocated string containing
* the text after offset bounded by the specified boundary_type
*/
static long atkText_get_text_after_offset (long atkObject, long offset_value,
long boundary_type, long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
long charCount = atkText_get_character_count (atkObject);
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = event.end = (int)offset_value;
event.count = 1;
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
case ATK.ATK_TEXT_BOUNDARY_WORD_START: event.type = ACC.TEXT_BOUNDARY_WORD; break;
case ATK.ATK_TEXT_BOUNDARY_WORD_END: event.type = ACC.TEXT_BOUNDARY_WORD; break;
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
case ATK.ATK_TEXT_BOUNDARY_LINE_START: event.type = ACC.TEXT_BOUNDARY_LINE; break;
case ATK.ATK_TEXT_BOUNDARY_LINE_END: event.type = ACC.TEXT_BOUNDARY_LINE; break;
}
int eventStart = event.start;
int eventEnd = event.end;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_WORD_START:
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START:
case ATK.ATK_TEXT_BOUNDARY_LINE_START:
if (event.end < charCount) {
int start = event.start;
event.start = eventStart;
event.end = eventEnd;
event.count = 2;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
event.end = event.start;
event.start = start;
event.type = ACC.TEXT_BOUNDARY_ALL;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
}
break;
case ATK.ATK_TEXT_BOUNDARY_WORD_END:
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END:
case ATK.ATK_TEXT_BOUNDARY_LINE_END:
if (0 < event.start) {
int end = event.end;
event.start = eventStart;
event.end = eventEnd;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
event.start = event.end;
event.end = end;
event.type = ACC.TEXT_BOUNDARY_ALL;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
}
break;
}
C.memmove (start_offset, new int[] {event.start}, 4);
C.memmove (end_offset, new int[] {event.end}, 4);
return getStringPtr (event.result);
}
int offset = (int)offset_value;
String text = object.getText ();
if (text != null && text.length () > 0) {
length = text.length ();
offset = Math.min (offset, length - 1);
int startBounds = offset;
int endBounds = offset;
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: {
if (length > offset) endBounds++;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
int wordStart1 = nextIndexOfChar (text, " !?.\n", offset - 1);
if (wordStart1 == -1) {
startBounds = endBounds = length;
break;
}
wordStart1 = nextIndexOfNotChar (text, " !?.\n", wordStart1);
if (wordStart1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = wordStart1;
int wordStart2 = nextIndexOfChar (text, " !?.\n", wordStart1);
if (wordStart2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, " !?.\n", wordStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
int previousWordEnd = previousIndexOfNotChar (text, " \n", offset);
if (previousWordEnd == -1 || previousWordEnd != offset - 1) {
offset = nextIndexOfNotChar (text, " \n", offset);
}
if (offset == -1) {
startBounds = endBounds = length;
break;
}
int wordEnd1 = nextIndexOfChar (text, " !?.\n", (int)offset);
if (wordEnd1 == -1) {
startBounds = endBounds = length;
break;
}
wordEnd1 = nextIndexOfNotChar (text, "!?.", wordEnd1);
if (wordEnd1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = wordEnd1;
int wordEnd2 = nextIndexOfNotChar (text, " \n", wordEnd1);
if (wordEnd2 == length) {
startBounds = endBounds = length;
break;
}
wordEnd2 = nextIndexOfChar (text, " !?.\n", wordEnd2);
if (wordEnd2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", wordEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
int previousSentenceEnd = previousIndexOfChar (text, "!?.", offset);
int previousText = previousIndexOfNotChar (text, " !?.\n", offset);
int sentenceStart1 = 0;
if (previousSentenceEnd >= previousText) {
sentenceStart1 = nextIndexOfNotChar (text, " !?.\n", offset);
} else {
sentenceStart1 = nextIndexOfChar (text, "!?.", offset);
if (sentenceStart1 == -1) {
startBounds = endBounds = length;
break;
}
sentenceStart1 = nextIndexOfNotChar (text, " !?.\n", sentenceStart1);
}
if (sentenceStart1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = sentenceStart1;
int sentenceStart2 = nextIndexOfChar (text, "!?.", sentenceStart1);
if (sentenceStart2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, " !?.\n", sentenceStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
int sentenceEnd1 = nextIndexOfChar (text, "!?.", offset);
if (sentenceEnd1 == -1) {
startBounds = endBounds = length;
break;
}
sentenceEnd1 = nextIndexOfNotChar (text, "!?.", sentenceEnd1);
if (sentenceEnd1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = sentenceEnd1;
int sentenceEnd2 = nextIndexOfNotChar (text, " \n", sentenceEnd1);
if (sentenceEnd2 == length) {
startBounds = endBounds = length;
break;
}
sentenceEnd2 = nextIndexOfChar (text, "!?.", sentenceEnd2);
if (sentenceEnd2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", sentenceEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
int lineStart1 = text.indexOf ('\n', offset - 1);
if (lineStart1 == -1) {
startBounds = endBounds = length;
break;
}
lineStart1 = nextIndexOfNotChar (text, "\n", lineStart1);
if (lineStart1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = lineStart1;
int lineStart2 = text.indexOf ('\n', lineStart1);
if (lineStart2 == -1) {
endBounds = length;
break;
}
lineStart2 = nextIndexOfNotChar (text, "\n", lineStart2);
endBounds = lineStart2;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
int lineEnd1 = nextIndexOfChar (text, "\n", offset);
if (lineEnd1 == -1) {
startBounds = endBounds = length;
break;
}
startBounds = lineEnd1;
if (startBounds == length) {
endBounds = length;
break;
}
int lineEnd2 = nextIndexOfChar (text, "\n", lineEnd1 + 1);
if (lineEnd2 == -1) {
endBounds = length;
break;
}
endBounds = lineEnd2;
break;
}
}
C.memmove (start_offset, new int[] {startBounds}, 4);
C.memmove (end_offset, new int[] {endBounds}, 4);
text = text.substring (startBounds, endBounds);
return getStringPtr (text);
}
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_text_after_offset != 0) {
return ATK.call (iface.get_text_after_offset, atkObject, offset_value, boundary_type, start_offset, end_offset);
}
return 0;
}
/**
* Gets the specified text.
*
* 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 offset position
* @param boundary_type the AtkTextBoundary
* @param start_offset the start offset of the returned string
* @param end_offset the end_offset of the first character after the returned string
*
* @return a pointer to the newly allocated string containing the
* text at offset bounded by the specified boundary_type
*/
static long atkText_get_text_at_offset (long atkObject, long offset_value,
long boundary_type, long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
long charCount = atkText_get_character_count (atkObject);
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = event.end = (int)offset_value;
event.count = 0;
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
case ATK.ATK_TEXT_BOUNDARY_WORD_START: event.type = ACC.TEXT_BOUNDARY_WORD; break;
case ATK.ATK_TEXT_BOUNDARY_WORD_END: event.type = ACC.TEXT_BOUNDARY_WORD; break;
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
case ATK.ATK_TEXT_BOUNDARY_LINE_START: event.type = ACC.TEXT_BOUNDARY_LINE; break;
case ATK.ATK_TEXT_BOUNDARY_LINE_END: event.type = ACC.TEXT_BOUNDARY_LINE; break;
}
int eventStart = event.start;
int eventEnd = event.end;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_WORD_START:
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START:
case ATK.ATK_TEXT_BOUNDARY_LINE_START:
if (event.end < charCount) {
int start = event.start;
event.start = eventStart;
event.end = eventEnd;
event.count = 1;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
event.end = event.start;
event.start = start;
event.type = ACC.TEXT_BOUNDARY_ALL;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
}
break;
case ATK.ATK_TEXT_BOUNDARY_WORD_END:
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END:
case ATK.ATK_TEXT_BOUNDARY_LINE_END:
if (0 < event.start) {
int end = event.end;
event.start = eventStart;
event.end = eventEnd;
event.count = -1;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
event.start = event.end;
event.end = end;
event.type = ACC.TEXT_BOUNDARY_ALL;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
}
break;
}
C.memmove (start_offset, new int[] {event.start}, 4);
C.memmove (end_offset, new int[] {event.end}, 4);
return getStringPtr (event.result);
}
int offset = (int)offset_value;
String text = object.getText ();
if (text != null && text.length () > 0) {
length = text.length ();
offset = Math.min (offset, length - 1);
int startBounds = offset;
int endBounds = offset;
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: {
if (length > offset) endBounds++;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
int wordStart1 = previousIndexOfNotChar (text, " !?.\n", offset);
if (wordStart1 == -1) {
startBounds = endBounds = 0;
break;
}
wordStart1 = previousIndexOfChar (text, " !?.\n", wordStart1) + 1;
if (wordStart1 == -1) {
startBounds = 0;
break;
}
startBounds = wordStart1;
int wordStart2 = nextIndexOfChar (text, " !?.\n", wordStart1);
endBounds = nextIndexOfNotChar (text, " !?.\n", wordStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
int wordEnd1 = previousIndexOfNotChar (text, "!?.", offset + 1);
wordEnd1 = previousIndexOfChar (text, " !?.\n", wordEnd1);
wordEnd1 = previousIndexOfNotChar (text, " \n", wordEnd1 + 1);
if (wordEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
startBounds = wordEnd1 + 1;
int wordEnd2 = nextIndexOfNotChar (text, " \n", startBounds);
if (wordEnd2 == length) {
endBounds = startBounds;
break;
}
wordEnd2 = nextIndexOfChar (text, " !?.\n", wordEnd2);
if (wordEnd2 == -1) {
endBounds = startBounds;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", wordEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
int sentenceStart1 = previousIndexOfNotChar (text, " !?.\n", offset + 1);
if (sentenceStart1 == -1) {
startBounds = endBounds = 0;
break;
}
sentenceStart1 = previousIndexOfChar (text, "!?.", sentenceStart1) + 1;
startBounds = nextIndexOfNotChar (text, " \n", sentenceStart1);
int sentenceStart2 = nextIndexOfChar (text, "!?.", startBounds);
endBounds = nextIndexOfNotChar (text, " !?.\n", sentenceStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
int sentenceEnd1 = previousIndexOfNotChar (text, "!?.", offset + 1);
sentenceEnd1 = previousIndexOfChar (text, "!?.", sentenceEnd1);
sentenceEnd1 = previousIndexOfNotChar (text, " \n", sentenceEnd1 + 1);
if (sentenceEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
startBounds = sentenceEnd1 + 1;
int sentenceEnd2 = nextIndexOfNotChar (text, " \n", startBounds);
if (sentenceEnd2 == length) {
endBounds = startBounds;
break;
}
sentenceEnd2 = nextIndexOfChar (text, "!?.", sentenceEnd2);
if (sentenceEnd2 == -1) {
endBounds = startBounds;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", sentenceEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
startBounds = previousIndexOfChar (text, "\n", offset) + 1;
int lineEnd2 = nextIndexOfChar (text, "\n", startBounds);
if (lineEnd2 < length) lineEnd2++;
endBounds = lineEnd2;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
int lineEnd1 = previousIndexOfChar (text, "\n", offset);
if (lineEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
startBounds = lineEnd1;
endBounds = nextIndexOfChar (text, "\n", lineEnd1 + 1);
}
}
C.memmove (start_offset, new int[] {startBounds}, 4);
C.memmove (end_offset, new int[] {endBounds}, 4);
text = text.substring (startBounds, endBounds);
return getStringPtr (text);
}
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_text_at_offset != 0) {
return ATK.call (iface.get_text_at_offset, atkObject, offset_value, boundary_type, start_offset, end_offset);
}
return 0;
}
/**
* Gets the specified text.
*
* 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 offset position
* @param boundary_type the AtkTextBoundary
* @param start_offset the start offset of the returned string
* @param end_offset the end_offset of the first character after the returned string
*
* @return a pointer to the newly allocated string containing
* the text before offset bounded by the specified boundary_type
*/
static long atkText_get_text_before_offset (long atkObject, long offset_value,
long boundary_type, long start_offset, long end_offset) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
if (length > 0) {
long charCount = atkText_get_character_count (atkObject);
AccessibleTextEvent event = new AccessibleTextEvent(accessible);
event.start = event.end = (int)offset_value;
event.count = -1;
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
case ATK.ATK_TEXT_BOUNDARY_WORD_START: event.type = ACC.TEXT_BOUNDARY_WORD; break;
case ATK.ATK_TEXT_BOUNDARY_WORD_END: event.type = ACC.TEXT_BOUNDARY_WORD; break;
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
case ATK.ATK_TEXT_BOUNDARY_LINE_START: event.type = ACC.TEXT_BOUNDARY_LINE; break;
case ATK.ATK_TEXT_BOUNDARY_LINE_END: event.type = ACC.TEXT_BOUNDARY_LINE; break;
}
int eventStart = event.start;
int eventEnd = event.end;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
C.memmove (start_offset, new int[] {event.start}, 4);
C.memmove (end_offset, new int[] {event.end}, 4);
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_WORD_START:
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START:
case ATK.ATK_TEXT_BOUNDARY_LINE_START:
if (event.end < charCount) {
int start = event.start;
event.start = eventStart;
event.end = eventEnd;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
event.end = event.start;
event.start = start;
event.type = ACC.TEXT_BOUNDARY_ALL;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
}
break;
case ATK.ATK_TEXT_BOUNDARY_WORD_END:
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END:
case ATK.ATK_TEXT_BOUNDARY_LINE_END:
if (0 < event.start) {
int end = event.end;
event.start = eventStart;
event.end = eventEnd;
event.count = -2;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
event.start = event.end;
event.end = end;
event.type = ACC.TEXT_BOUNDARY_ALL;
event.count = 0;
for (int i = 0; i < length; i++) {
AccessibleTextExtendedListener listener = listeners.get(i);
listener.getText(event);
}
}
break;
}
return getStringPtr (event.result);
}
int offset = (int)offset_value;
String text = object.getText ();
if (text != null && text.length () > 0) {
length = text.length ();
offset = Math.min (offset, length - 1);
int startBounds = offset;
int endBounds = offset;
switch ((int)boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: {
if (length >= offset && offset > 0) startBounds--;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
int wordStart1 = previousIndexOfChar (text, " !?.\n", offset - 1);
if (wordStart1 == -1) {
startBounds = endBounds = 0;
break;
}
int wordStart2 = previousIndexOfNotChar (text, " !?.\n", wordStart1);
if (wordStart2 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = wordStart1 + 1;
startBounds = previousIndexOfChar (text, " !?.\n", wordStart2) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
int wordEnd1 =previousIndexOfChar (text, " !?.\n", offset);
if (wordEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
wordEnd1 = previousIndexOfNotChar (text, " \n", wordEnd1 + 1);
if (wordEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = wordEnd1 + 1;
int wordEnd2 = previousIndexOfNotChar (text, " !?.\n", endBounds);
wordEnd2 = previousIndexOfChar (text, " !?.\n", wordEnd2);
if (wordEnd2 == -1) {
startBounds = 0;
break;
}
startBounds = previousIndexOfNotChar (text, " \n", wordEnd2 + 1) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
int sentenceStart1 = previousIndexOfChar (text, "!?.", offset);
if (sentenceStart1 == -1) {
startBounds = endBounds = 0;
break;
}
int sentenceStart2 = previousIndexOfNotChar (text, "!?.", sentenceStart1);
if (sentenceStart2 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = sentenceStart1 + 1;
startBounds = previousIndexOfChar (text, "!?.", sentenceStart2) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
int sentenceEnd1 = previousIndexOfChar (text, "!?.", offset);
if (sentenceEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
sentenceEnd1 = previousIndexOfNotChar (text, " \n", sentenceEnd1 + 1);
if (sentenceEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = sentenceEnd1 + 1;
int sentenceEnd2 = previousIndexOfNotChar (text, "!?.", endBounds);
sentenceEnd2 = previousIndexOfChar (text, "!?.", sentenceEnd2);
if (sentenceEnd2 == -1) {
startBounds = 0;
break;
}
startBounds = previousIndexOfNotChar (text, " \n", sentenceEnd2 + 1) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
int lineStart1 = previousIndexOfChar (text, "\n", offset);
if (lineStart1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = lineStart1 + 1;
startBounds = previousIndexOfChar (text, "\n", lineStart1) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
int lineEnd1 = previousIndexOfChar (text, "\n", offset);
if (lineEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = lineEnd1;
startBounds = previousIndexOfChar (text, "\n", lineEnd1);
if (startBounds == -1) startBounds = 0;
break;
}
}
C.memmove (start_offset, new int[] {startBounds}, 4);
C.memmove (end_offset, new int[] {endBounds}, 4);
text = text.substring (startBounds, endBounds);
return getStringPtr (text);
}
}
AtkTextIface iface = getParentTextIface (atkObject);
if (iface != null && iface.get_text_before_offset != 0) {
return ATK.call (iface.get_text_before_offset, atkObject, offset_value, boundary_type, start_offset, end_offset);
}
return 0;
}
static void setGValue (long value, Number number) {
if (number == null) return;
if (OS.G_VALUE_TYPE(value) != 0) OS.g_value_unset(value);
if (number instanceof Double) {
OS.g_value_init(value, OS.G_TYPE_DOUBLE());
OS.g_value_set_double(value, number.doubleValue());
} else if (number instanceof Float) {
OS.g_value_init(value, OS.G_TYPE_FLOAT());
OS.g_value_set_float(value, number.floatValue());
} else if (number instanceof Long) {
OS.g_value_init(value, OS.G_TYPE_INT64());
OS.g_value_set_int64(value, number.longValue());
} else {
OS.g_value_init(value, OS.G_TYPE_INT());
OS.g_value_set_int(value, number.intValue());
}
}
static Number getGValue (long value) {
long type = OS.G_VALUE_TYPE(value);
if (type == 0) return null;
if (type == OS.G_TYPE_DOUBLE()) return Double.valueOf(OS.g_value_get_double(value));
if (type == OS.G_TYPE_FLOAT()) return Float.valueOf(OS.g_value_get_float(value));
if (type == OS.G_TYPE_INT64()) return Long.valueOf(OS.g_value_get_int64(value));
return Integer.valueOf(OS.g_value_get_int(value));
}
/**
* Fills a Java AtkValueIface struct with that of the parent class.
* This is a Java implementation of what is referred to in GObject as "chaining up".
* See: https://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AtkValueIface Java object representing the interface struct of atkObject's
* parent
*/
static AtkValueIface getParentValueIface (long atkObject) {
long type = OS.swt_fixed_accessible_get_type();
if (OS.g_type_is_a (OS.g_type_parent (type), ATK.ATK_TYPE_VALUE())) {
AtkValueIface iface = new AtkValueIface ();
ATK.memmove (iface, OS.g_type_interface_peek_parent (ATK.ATK_VALUE_GET_IFACE (atkObject)));
return iface;
}
return null;
}
/**
* Gets the value of this atkObject.
*
* 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 value a pointer to a GValue that represents the current value
*
* @return 0, this is a void function -- the value is stored in the parameter
*/
static long atkValue_get_current_value (long atkObject, long value) {
AccessibleObject object = getAccessibleObject (atkObject);
AtkValueIface iface = getParentValueIface (atkObject);
if (iface != null && iface.get_current_value != 0) {
ATK.call (iface.get_current_value, atkObject, value);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleValueListeners;
int length = size(listeners);
if (length > 0) {
AccessibleValueEvent event = new AccessibleValueEvent(accessible);
event.value = getGValue(value);
for (int i = 0; i < length; i++) {
AccessibleValueListener listener = listeners.get(i);
listener.getCurrentValue(event);
}
setGValue(value, event.value);
}
}
return 0;
}
/**
* Gets the maximum value of this atkObject.
*
* 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 value a pointer to a GValue that represents the current maximum
* value
*
* @return 0, this is a void function -- the value is stored in the parameter
*/
static long atkValue_get_maximum_value (long atkObject, long value) {
AccessibleObject object = getAccessibleObject (atkObject);
AtkValueIface iface = getParentValueIface (atkObject);
if (iface != null && iface.get_maximum_value != 0) {
ATK.call (iface.get_maximum_value, atkObject, value);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleValueListeners;
int length = size(listeners);
if (length > 0) {
AccessibleValueEvent event = new AccessibleValueEvent(accessible);
event.value = getGValue(value);
for (int i = 0; i < length; i++) {
AccessibleValueListener listener = listeners.get(i);
listener.getMaximumValue(event);
}
setGValue(value, event.value);
}
}
return 0;
}
/**
* Gets the minimum value of this atkObject.
*
* 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 value a pointer to a GValue that represents the current minimum
* value
*
* @return 0, this is a void function -- the value is stored in the parameter
*/
static long atkValue_get_minimum_value (long atkObject, long value) {
AccessibleObject object = getAccessibleObject (atkObject);
AtkValueIface iface = getParentValueIface (atkObject);
if (iface != null && iface.get_minimum_value != 0) {
ATK.call (iface.get_minimum_value, atkObject, value);
}
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleValueListeners;
int length = size(listeners);
if (length > 0) {
AccessibleValueEvent event = new AccessibleValueEvent(accessible);
event.value = getGValue(value);
for (int i = 0; i < length; i++) {
AccessibleValueListener listener = listeners.get(i);
listener.getMinimumValue(event);
}
setGValue(value, event.value);
}
}
return 0;
}
/**
* Sets the value of this atkObject.
*
* 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 value a pointer to the new GValue to be set
*
* @return a long int representation of 1 for success, 0 otherwise
*/
static long atkValue_set_current_value (long atkObject, long value) {
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
Accessible accessible = object.accessible;
List listeners = accessible.accessibleValueListeners;
int length = size(listeners);
if (length > 0) {
AccessibleValueEvent event = new AccessibleValueEvent(accessible);
event.value = getGValue(value);
for (int i = 0; i < length; i++) {
AccessibleValueListener listener = listeners.get(i);
listener.setCurrentValue(event);
}
return event.value != null ? 1 : 0;
}
}
long parentResult = 0;
AtkValueIface iface = getParentValueIface (atkObject);
if (iface != null && iface.set_current_value != 0) {
parentResult = ATK.call (iface.set_current_value, atkObject, value);
}
return parentResult;
}
/**
* Gets the AccessibleObject associated with the AtkObject handle
* from the Java map of AccessibleObjects.
*
* @param atkObject a pointer to the current AtkObject
*
* @return an AccessibleObject associated with the provided AtkObject pointer
*/
static AccessibleObject getAccessibleObject (long atkObject) {
AccessibleObject object = AccessibleObjects.get (new LONG (atkObject));
if (object == null) return null;
if (object.accessible == null) return null;
Control control = object.accessible.control;
if (control == null || control.isDisposed()) return null;
return object;
}
AccessibleObject getChildByID (int childId) {
if (childId == ACC.CHILDID_SELF) return this;
if (childId == ACC.CHILDID_NONE || childId == ACC.CHILDID_MULTIPLE) return null;
if (children != null) {
for (int i = 0; i < children.length; i++) {
AccessibleObject child = children[i];
if (child != null && child.id == childId) return child;
}
}
return null;
}
AccessibleObject getChildByIndex (int childIndex) {
if (children != null && childIndex < children.length) return children [childIndex];
return null;
}
String getText () {
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
if (length > 0) {
String parentText = ""; //$NON-NLS-1$
AtkTextIface iface = getParentTextIface (atkHandle);
if (iface != null && iface.get_character_count != 0) {
long characterCount = ATK.call (iface.get_character_count, atkHandle);
if (characterCount > 0 && iface.get_text != 0) {
long parentResult = ATK.call (iface.get_text, atkHandle, 0, characterCount);
if (parentResult != 0) {
parentText = getString (parentResult);
OS.g_free(parentResult);
}
}
}
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = id;
event.result = parentText;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getValue (event);
}
return event.result;
}
return null;
}
static long gObjectClass_finalize (long atkObject) {
/*
* GObject destruction is handled in os_custom.c in GTK3.
* AccessibleObject has to be removed from the map of AccessibleObjects, though.
*/
AccessibleObject object = AccessibleObjects.get (new LONG (atkObject));
if (object != null) {
AccessibleObjects.remove (new LONG (atkObject));
}
return 0;
}
static int toATKRelation (int relation) {
switch (relation) {
case ACC.RELATION_CONTROLLED_BY: return ATK.ATK_RELATION_CONTROLLED_BY;
case ACC.RELATION_CONTROLLER_FOR: return ATK.ATK_RELATION_CONTROLLER_FOR;
case ACC.RELATION_DESCRIBED_BY: return ATK.ATK_RELATION_DESCRIBED_BY;
case ACC.RELATION_DESCRIPTION_FOR: return ATK.ATK_RELATION_DESCRIPTION_FOR;
case ACC.RELATION_EMBEDDED_BY: return ATK.ATK_RELATION_EMBEDDED_BY;
case ACC.RELATION_EMBEDS: return ATK.ATK_RELATION_EMBEDS;
case ACC.RELATION_FLOWS_FROM: return ATK.ATK_RELATION_FLOWS_FROM;
case ACC.RELATION_FLOWS_TO: return ATK.ATK_RELATION_FLOWS_TO;
case ACC.RELATION_LABEL_FOR: return ATK.ATK_RELATION_LABEL_FOR;
case ACC.RELATION_LABELLED_BY: return ATK.ATK_RELATION_LABELLED_BY;
case ACC.RELATION_MEMBER_OF: return ATK.ATK_RELATION_MEMBER_OF;
case ACC.RELATION_NODE_CHILD_OF: return ATK.ATK_RELATION_NODE_CHILD_OF;
case ACC.RELATION_PARENT_WINDOW_OF: return ATK.ATK_RELATION_PARENT_WINDOW_OF;
case ACC.RELATION_POPUP_FOR: return ATK.ATK_RELATION_POPUP_FOR;
case ACC.RELATION_SUBWINDOW_OF: return ATK.ATK_RELATION_SUBWINDOW_OF;
}
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 toDisplay (long gdkResource, long x, long 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) {
//TODO: GTK4 no gdk_surface_get_origin
} 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 widget = GTK3.gtk_accessible_get_widget(object.atkHandle);
while (widget == 0 && object.parent != null) {
object = object.parent;
widget = GTK3.gtk_accessible_get_widget(object.atkHandle);
}
if (widget == 0) return;
if (GTK.GTK4) {
//TODO: GTK4 no gdk_surface_get_origin
} else {
long topLevel = GTK3.gtk_widget_get_toplevel (widget);
long window = GTK3.gtk_widget_get_window (topLevel);
GDK.gdk_window_get_origin (window, x, y);
}
}
static int nextIndexOfChar (String string, String searchChars, int startIndex) {
int result = string.length ();
for (int i = 0; i < searchChars.length (); i++) {
char current = searchChars.charAt (i);
int index = string.indexOf (current, startIndex);
if (index != -1) result = Math.min (result, index);
}
return result;
}
static int nextIndexOfNotChar (String string, String searchChars, int startIndex) {
int length = string.length ();
int index = startIndex;
while (index < length) {
char current = string.charAt (index);
if (searchChars.indexOf (current) == -1) break;
index++;
}
return index;
}
static int previousIndexOfChar (String string, String searchChars, int startIndex) {
int result = -1;
if (startIndex < 0) return result;
string = string.substring (0, startIndex);
for (int i = 0; i < searchChars.length (); i++) {
char current = searchChars.charAt (i);
int index = string.lastIndexOf (current);
if (index != -1) result = Math.max (result, index);
}
return result;
}
static int previousIndexOfNotChar (String string, String searchChars, int startIndex) {
if (startIndex < 0) return -1;
int index = startIndex - 1;
while (index >= 0) {
char current = string.charAt (index);
if (searchChars.indexOf (current) == -1) break;
index--;
}
return index;
}
void addRelation (int type, Accessible target) {
AccessibleObject targetAccessibleObject = target.getAccessibleObject();
if (targetAccessibleObject != null) {
/*
* FIXME: Workaround for https://bugs.eclipse.org/312451
*
* This null check is conceptually wrong and will probably cause
* inconsistent behavior, but since we don't know in what
* circumstances the target doesn't have an accessibleObject, that's
* the best way we know to avoid throwing an NPE.
*/
ATK.atk_object_add_relationship(atkHandle, toATKRelation(type), targetAccessibleObject.atkHandle);
}
}
void release () {
accessible = null;
/*
* GObject destruction is implemented in os_custom.c for GTK3:
* only unref lightweight widgets and children.
*/
if (children != null) {
for (int i = 0; i < children.length; i++) {
AccessibleObject child = children [i];
if (child != null) OS.g_object_unref(child.atkHandle);
}
children = null;
}
if (isLightweight) {
OS.g_object_unref(atkHandle);
}
}
void removeRelation (int type, Accessible target) {
AccessibleObject targetAccessibleObject = target.getAccessibleObject();
if (targetAccessibleObject != null) {
/*
* FIXME: Workaround for https://bugs.eclipse.org/312451
*
* This null check is conceptually wrong and will probably cause
* inconsistent behavior, but since we don't know in what
* circumstances the target doesn't have an accessibleObject, that's
* the best way we know to avoid throwing an NPE.
*/
ATK.atk_object_remove_relationship (atkHandle, toATKRelation(type), targetAccessibleObject.atkHandle);
}
}
void selectionChanged () {
OS.g_signal_emit_by_name (atkHandle, ATK.selection_changed);
}
void sendEvent(int event, Object eventData) {
switch (event) {
case ACC.EVENT_SELECTION_CHANGED:
OS.g_signal_emit_by_name (atkHandle, ATK.selection_changed);
break;
case ACC.EVENT_TEXT_SELECTION_CHANGED:
OS.g_signal_emit_by_name (atkHandle, ATK.text_selection_changed);
break;
case ACC.EVENT_STATE_CHANGED: {
if (!(eventData instanceof int[])) break;
int[] array = (int[])eventData;
int state = array[0];
int value = array[1];
int atkState = -1;
switch (state) {
case ACC.STATE_SELECTED: atkState = ATK.ATK_STATE_SELECTED; break;
case ACC.STATE_SELECTABLE: atkState = ATK.ATK_STATE_SELECTABLE; break;
case ACC.STATE_MULTISELECTABLE: atkState = ATK.ATK_STATE_MULTISELECTABLE; break;
case ACC.STATE_FOCUSED: atkState = ATK.ATK_STATE_FOCUSED; break;
case ACC.STATE_FOCUSABLE: atkState = ATK.ATK_STATE_FOCUSABLE; break;
case ACC.STATE_PRESSED: atkState = ATK.ATK_STATE_PRESSED; break;
case ACC.STATE_CHECKED: atkState = ATK.ATK_STATE_CHECKED; break;
case ACC.STATE_EXPANDED: atkState = ATK.ATK_STATE_EXPANDED; break;
case ACC.STATE_COLLAPSED: atkState = ATK.ATK_STATE_EXPANDED; break;
case ACC.STATE_HOTTRACKED: atkState = ATK.ATK_STATE_ARMED; break;
case ACC.STATE_BUSY: atkState = ATK.ATK_STATE_BUSY; break;
case ACC.STATE_READONLY: atkState = ATK.ATK_STATE_EDITABLE; break;
case ACC.STATE_INVISIBLE: atkState = ATK.ATK_STATE_VISIBLE; break;
case ACC.STATE_OFFSCREEN: atkState = ATK.ATK_STATE_SHOWING; break;
case ACC.STATE_SIZEABLE: atkState = ATK.ATK_STATE_RESIZABLE; break;
case ACC.STATE_LINKED: break;
case ACC.STATE_DISABLED: atkState = ATK.ATK_STATE_ENABLED; break;
case ACC.STATE_ACTIVE: atkState = ATK.ATK_STATE_ACTIVE; break;
case ACC.STATE_SINGLELINE: atkState = ATK.ATK_STATE_SINGLE_LINE; break;
case ACC.STATE_MULTILINE: atkState = ATK.ATK_STATE_MULTI_LINE; break;
case ACC.STATE_REQUIRED: atkState = ATK.ATK_STATE_REQUIRED; break;
case ACC.STATE_INVALID_ENTRY: atkState = ATK.ATK_STATE_INVALID_ENTRY; break;
case ACC.STATE_SUPPORTS_AUTOCOMPLETION: atkState = ATK.ATK_STATE_SUPPORTS_AUTOCOMPLETION; break;
}
if (atkState == -1) break;
ATK.atk_object_notify_state_change(atkHandle, atkState, value != 0);
break;
}
case ACC.EVENT_LOCATION_CHANGED: {
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
GdkRectangle rect = new GdkRectangle();
if (length > 0) {
AccessibleControlEvent e = new AccessibleControlEvent (accessible);
e.childID = id;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getLocation (e);
}
rect.x = e.x;
rect.y = e.y;
rect.width = e.width;
rect.height = e.height;
}
OS.g_signal_emit_by_name (atkHandle, ATK.bounds_changed, rect);
break;
}
case ACC.EVENT_NAME_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_name);
break;
case ACC.EVENT_DESCRIPTION_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_description);
break;
case ACC.EVENT_VALUE_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_value);
break;
case ACC.EVENT_DOCUMENT_LOAD_COMPLETE:
OS.g_signal_emit_by_name (atkHandle, ATK.load_complete);
break;
case ACC.EVENT_DOCUMENT_LOAD_STOPPED:
OS.g_signal_emit_by_name (atkHandle, ATK.load_stopped);
break;
case ACC.EVENT_DOCUMENT_RELOAD:
OS.g_signal_emit_by_name (atkHandle, ATK.reload);
break;
case ACC.EVENT_PAGE_CHANGED:
break;
case ACC.EVENT_SECTION_CHANGED:
break;
case ACC.EVENT_ACTION_CHANGED:
break;
case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED:
OS.g_object_notify(atkHandle, ATK.end_index);
break;
case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED:
OS.g_object_notify(atkHandle, ATK.number_of_anchors);
break;
case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED:
OS.g_object_notify(atkHandle, ATK.selected_link);
break;
case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED:
OS.g_object_notify(atkHandle, ATK.start_index);
break;
case ACC.EVENT_HYPERLINK_ACTIVATED:
OS.g_signal_emit_by_name (atkHandle, ATK.link_activated);
break;
case ACC.EVENT_HYPERTEXT_LINK_SELECTED:
if (!(eventData instanceof Integer)) break;
int index = ((Integer)eventData).intValue();
OS.g_signal_emit_by_name (atkHandle, ATK.link_selected, index);
break;
case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_hypertext_nlinks);
break;
case ACC.EVENT_ATTRIBUTE_CHANGED:
long gType = OS.G_OBJECT_TYPE(atkHandle);
if (gType == GTK.GTK_TYPE_TEXT_VIEW_ACCESSIBLE()) break;
OS.g_signal_emit_by_name (atkHandle, ATK.attributes_changed);
break;
case ACC.EVENT_TABLE_CAPTION_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_table_caption_object);
break;
case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_table_column_description);
break;
case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_table_column_header);
break;
case ACC.EVENT_TABLE_CHANGED: {
if (!(eventData instanceof int[])) break;
int[] array = (int[])eventData;
int type = array[0];
int rowStart = array[1];
int rowCount = array[2];
int columnStart = array[3];
int columnCount = array[4];
switch (type) {
case ACC.DELETE:
if (rowCount > 0) OS.g_signal_emit_by_name (atkHandle, ATK.row_deleted, rowStart, rowCount);
if (columnCount > 0) OS.g_signal_emit_by_name (atkHandle, ATK.column_deleted, columnStart, columnCount);
break;
case ACC.INSERT:
if (rowCount > 0) OS.g_signal_emit_by_name (atkHandle, ATK.row_inserted, rowStart, rowCount);
if (columnCount > 0) OS.g_signal_emit_by_name (atkHandle, ATK.column_inserted, columnStart, columnCount);
break;
}
break;
}
case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_table_row_description);
break;
case ACC.EVENT_TABLE_ROW_HEADER_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_table_row_header);
break;
case ACC.EVENT_TABLE_SUMMARY_CHANGED:
OS.g_object_notify(atkHandle, ATK.accessible_table_summary);
break;
case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED:
OS.g_signal_emit_by_name (atkHandle, ATK.text_attributes_changed);
break;
case ACC.EVENT_TEXT_CARET_MOVED:
case ACC.EVENT_TEXT_COLUMN_CHANGED: {
int offset = 0;
List listeners = accessible.accessibleTextExtendedListeners;
int length = size(listeners);
AccessibleTextEvent e = new AccessibleTextEvent (accessible);
if (length > 0) {
for (int i = 0; i < length; i++) {
AccessibleTextListener listener = listeners.get(i);
listener.getCaretOffset (e);
}
} else {
List listeners2 = accessible.accessibleTextListeners;
length = size(listeners2);
if (length > 0) {
e.childID = id;
for (int i = 0; i < length; i++) {
AccessibleTextListener listener = listeners2.get(i);
listener.getCaretOffset (e);
}
}
}
offset = e.offset;
OS.g_signal_emit_by_name (atkHandle, ATK.text_caret_moved, offset);
break;
}
case ACC.EVENT_TEXT_CHANGED: {
if (!(eventData instanceof Object[])) break;
Object[] data = (Object[])eventData;
int type = ((Integer)data[0]).intValue();
int start = ((Integer)data[1]).intValue();
int end = ((Integer)data[2]).intValue();
switch (type) {
case ACC.DELETE:
OS.g_signal_emit_by_name (atkHandle, ATK.text_changed_delete, start, end -start);
break;
case ACC.INSERT:
OS.g_signal_emit_by_name (atkHandle, ATK.text_changed_insert, start, end -start);
break;
}
break;
}
}
}
void sendEvent(int event, Object eventData, int childID) {
updateChildren ();
AccessibleObject accObject = getChildByID (childID);
if (accObject != null) {
accObject.sendEvent(event, eventData);
}
}
void setFocus (int childID) {
updateChildren ();
AccessibleObject accObject = getChildByID (childID);
if (accObject != null) {
OS.g_signal_emit_by_name (accObject.atkHandle, ATK.focus_event, 1, 0);
ATK.atk_object_notify_state_change(accObject.atkHandle, ATK.ATK_STATE_FOCUSED, true);
}
}
void textCaretMoved(int index) {
OS.g_signal_emit_by_name (atkHandle, ATK.text_caret_moved, index);
}
void textChanged(int type, int startIndex, int length) {
if (type == ACC.TEXT_DELETE) {
OS.g_signal_emit_by_name (atkHandle, ATK.text_changed_delete, startIndex, length);
} else {
OS.g_signal_emit_by_name (atkHandle, ATK.text_changed_insert, startIndex, length);
}
}
void textSelectionChanged() {
OS.g_signal_emit_by_name (atkHandle, ATK.text_selection_changed);
}
void updateChildren () {
List listeners = accessible.accessibleControlListeners;
int length = size(listeners);
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = id;
for (int i = 0; i < length; i++) {
AccessibleControlListener listener = listeners.get (i);
listener.getChildren (event);
}
Object[] children = event.children;
AccessibleObject[] oldChildren = this.children;
int count = children != null ? children.length : 0;
AccessibleObject[] newChildren = new AccessibleObject[count];
for (int i = 0; i < count; i++) {
Object child = children [i];
AccessibleObject object = null;
// Widgets where the children are Integers: CTable, BarChart, and CTabFolder
if (child instanceof Integer) {
int id = ((Integer)child).intValue();
object = oldChildren != null && i < oldChildren.length ? oldChildren [i] : null;
if (object == null || object.id != id) {
event = new AccessibleControlEvent (accessible);
event.childID = id;
for (int j = 0; j < length; j++) {
AccessibleControlListener listener = listeners.get (j);
listener.getChild (event);
}
if (event.accessible != null) {
object = event.accessible.getAccessibleObject();
if (object != null) OS.g_object_ref(object.atkHandle);
} else {
long type = OS.G_OBJECT_TYPE (accessible.getControlHandle());
long widget = accessible.getControlHandle();
object = new AccessibleObject(type, widget, accessible, true);
}
object.id = id;
} else {
OS.g_object_ref(object.atkHandle);
}
} else if (child instanceof Accessible) {
object = ((Accessible)child).getAccessibleObject();
if (object != null) OS.g_object_ref(object.atkHandle);
}
if (object != null) {
object.index = i;
object.parent = this;
newChildren[i] = object;
}
}
if (oldChildren != null) {
for (int i = 0; i < oldChildren.length; i++) {
AccessibleObject object = oldChildren [i];
if (object != null) OS.g_object_unref(object.atkHandle);
}
}
this.children = newChildren;
}
}