diff options
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk')
3 files changed, 2221 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/Accessible.java b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/Accessible.java new file mode 100644 index 0000000000..6a2a5d57ed --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/Accessible.java @@ -0,0 +1,395 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.accessibility; + + +import java.util.*; +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.widgets.*; + +/** + * Instances of this class provide a bridge between application + * code and assistive technology clients. Many platforms provide + * default accessible behavior for most widgets, and this class + * allows that default behavior to be overridden. Applications + * can get the default Accessible object for a control by sending + * it <code>getAccessible</code>, and then add an accessible listener + * to override simple items like the name and help string, or they + * can add an accessible control listener to override complex items. + * As a rule of thumb, an application would only want to use the + * accessible control listener to implement accessibility for a + * custom control. + * + * @see Control#getAccessible + * @see AccessibleListener + * @see AccessibleEvent + * @see AccessibleControlListener + * @see AccessibleControlEvent + * @see <a href="http://www.eclipse.org/swt/snippets/#accessibility">Accessibility snippets</a> + * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> + * + * @since 2.0 + */ +public class Accessible { + Vector accessibleListeners = new Vector (); + Vector controlListeners = new Vector (); + Vector textListeners = new Vector (); + AccessibleObject accessibleObject; + Control control; + + /** + * @since 3.5 + */ + protected Accessible() { + } + + Accessible (Control control) { + super (); + this.control = control; + AccessibleFactory.registerAccessible (this); + control.addDisposeListener (new DisposeListener () { + public void widgetDisposed (DisposeEvent e) { + release (); + } + }); + } + + /** + * Adds the listener to the collection of listeners who will + * be notified when an accessible client asks for certain strings, + * such as name, description, help, or keyboard shortcut. The + * listener is notified by sending it one of the messages defined + * in the <code>AccessibleListener</code> interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for a name, description, help, or keyboard shortcut string + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @see AccessibleListener + * @see #removeAccessibleListener + */ + public void addAccessibleListener (AccessibleListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + accessibleListeners.addElement (listener); + } + + /** + * Adds the listener to the collection of listeners who will + * be notified when an accessible client asks for custom control + * specific information. The listener is notified by sending it + * one of the messages defined in the <code>AccessibleControlListener</code> + * interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for custom control specific information + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @see AccessibleControlListener + * @see #removeAccessibleControlListener + */ + public void addAccessibleControlListener (AccessibleControlListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + controlListeners.addElement (listener); + } + + /** + * Adds the listener to the collection of listeners who will + * be notified when an accessible client asks for custom text control + * specific information. The listener is notified by sending it + * one of the messages defined in the <code>AccessibleTextListener</code> + * interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for custom text control specific information + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @see AccessibleTextListener + * @see #removeAccessibleTextListener + * + * @since 3.0 + */ + public void addAccessibleTextListener (AccessibleTextListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + textListeners.addElement (listener); + } + + /** + * Returns the control for this Accessible object. + * + * @return the receiver's control + * @since 3.0 + */ + public Control getControl() { + return control; + } + + /* checkWidget was copied from Widget, and rewritten to work in this package */ + void checkWidget () { + if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS); + if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED); + } + + AccessibleListener[] getAccessibleListeners () { + if (accessibleListeners == null) return null; + AccessibleListener[] result = new AccessibleListener [accessibleListeners.size ()]; + accessibleListeners.copyInto (result); + return result; + } + + int /*long*/ getControlHandle () { + return control.handle; + } + + AccessibleControlListener[] getControlListeners () { + if (controlListeners == null) return null; + AccessibleControlListener[] result = new AccessibleControlListener [controlListeners.size ()]; + controlListeners.copyInto (result); + return result; + } + + AccessibleTextListener[] getTextListeners () { + if (textListeners == null) return null; + AccessibleTextListener[] result = new AccessibleTextListener [textListeners.size ()]; + textListeners.copyInto (result); + return result; + } + + /** + * Invokes platform specific functionality to allocate a new accessible object. + * <p> + * <b>IMPORTANT:</b> This method is <em>not</em> part of the public + * API for <code>Accessible</code>. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + * </p> + * + * @param control the control to get the accessible object for + * @return the platform specific accessible object + */ + public static Accessible internal_new_Accessible (Control control) { + return new Accessible (control); + } + + /* isValidThread was copied from Widget, and rewritten to work in this package */ + boolean isValidThread () { + return control.getDisplay ().getThread () == Thread.currentThread (); + } + + void release () { + AccessibleFactory.unregisterAccessible (Accessible.this); + if (accessibleObject != null) { + accessibleObject.release (); + accessibleObject = null; + } + } + /** + * Removes the listener from the collection of listeners who will + * be notified when an accessible client asks for custom control + * specific information. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for custom control specific information + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @see AccessibleControlListener + * @see #addAccessibleControlListener + */ + public void removeAccessibleControlListener (AccessibleControlListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + controlListeners.removeElement (listener); + } + + /** + * Removes the listener from the collection of listeners who will + * be notified when an accessible client asks for certain strings, + * such as name, description, help, or keyboard shortcut. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for a name, description, help, or keyboard shortcut string + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @see AccessibleListener + * @see #addAccessibleListener + */ + public void removeAccessibleListener (AccessibleListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + accessibleListeners.removeElement (listener); + } + + /** + * Removes the listener from the collection of listeners who will + * be notified when an accessible client asks for custom text control + * specific information. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for custom text control specific information + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @see AccessibleTextListener + * @see #addAccessibleTextListener + * + * @since 3.0 + */ + public void removeAccessibleTextListener (AccessibleTextListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + textListeners.removeElement (listener); + } + + /** + * Sends a message to accessible clients that the child selection + * within a custom container control has changed. + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @since 3.0 + */ + public void selectionChanged () { + checkWidget (); + if (accessibleObject != null) { + accessibleObject.selectionChanged (); + } + } + + /** + * Sends a message to accessible clients indicating that the focus + * has changed within a custom control. + * + * @param childID an identifier specifying a child of the control + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + */ + public void setFocus (int childID) { + checkWidget (); + if (accessibleObject != null) { + accessibleObject.setFocus (childID); + } + } + + /** + * Sends a message to accessible clients that the text + * caret has moved within a custom control. + * + * @param index the new caret index within the control + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @since 3.0 + */ + public void textCaretMoved (int index) { + checkWidget (); + if (accessibleObject != null) { + accessibleObject.textCaretMoved (index); + } + } + + /** + * Sends a message to accessible clients that the text + * within a custom control has changed. + * + * @param type the type of change, one of <code>ACC.NOTIFY_TEXT_INSERT</code> + * or <code>ACC.NOTIFY_TEXT_DELETE</code> + * @param startIndex the text index within the control where the insertion or deletion begins + * @param length the non-negative length in characters of the insertion or deletion + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @see ACC#TEXT_INSERT + * @see ACC#TEXT_DELETE + * + * @since 3.0 + */ + public void textChanged (int type, int startIndex, int length) { + checkWidget (); + if (accessibleObject != null) { + accessibleObject.textChanged (type, startIndex, length); + } + } + + /** + * Sends a message to accessible clients that the text + * selection has changed within a custom control. + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> + * </ul> + * + * @since 3.0 + */ + public void textSelectionChanged () { + checkWidget (); + if (accessibleObject != null) { + accessibleObject.textSelectionChanged (); + } + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleFactory.java b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleFactory.java new file mode 100644 index 0000000000..c6f6300d66 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleFactory.java @@ -0,0 +1,414 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.accessibility; + + +import java.util.*; +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.accessibility.gtk.*; +import org.eclipse.swt.internal.gtk.*; +import org.eclipse.swt.*; + +class AccessibleFactory { + int /*long*/ handle; + int /*long*/ objectParentType; + int /*long*/ widgetTypeName; + Callback atkObjectFactoryCB_create_accessible; + Callback gTypeInfo_base_init_factory; + Hashtable accessibles = new Hashtable (9); + + static final Hashtable Types = new Hashtable (9); + static final Hashtable Factories = new Hashtable (9); + static final int /*long*/ DefaultParentType = OS.g_type_from_name (Converter.wcsToMbcs (null, "GtkAccessible", true)); //$NON-NLS-1$ + static final byte[] FACTORY_PARENTTYPENAME = Converter.wcsToMbcs (null, "AtkObjectFactory", true); //$NON-NLS-1$ + static final byte[] SWT_TYPE_PREFIX = Converter.wcsToMbcs (null, "SWT", false); //$NON-NLS-1$ + static final byte[] CHILD_TYPENAME = Converter.wcsToMbcs (null, "Child", false); //$NON-NLS-1$ + static final byte[] FACTORY_TYPENAME = Converter.wcsToMbcs (null, "SWTFactory", true); //$NON-NLS-1$ + static final int[] actionRoles = { + ACC.ROLE_CHECKBUTTON, ACC.ROLE_COMBOBOX, ACC.ROLE_LINK, + ACC.ROLE_MENUITEM, ACC.ROLE_PUSHBUTTON, ACC.ROLE_RADIOBUTTON, + ACC.ROLE_SPLITBUTTON, + }; + static final int[] hypertextRoles = {ACC.ROLE_LINK}; + static final int[] selectionRoles = { + ACC.ROLE_LIST, ACC.ROLE_TABFOLDER, ACC.ROLE_TABLE, ACC.ROLE_TREE, + }; + static final int[] textRoles = { + ACC.ROLE_COMBOBOX, ACC.ROLE_LINK, ACC.ROLE_LABEL, ACC.ROLE_TEXT, + }; + + /* AT callbacks*/ + static final Callback AtkActionCB_get_keybinding; + static final Callback AtkActionCB_get_name; + static final Callback AtkComponentCB_get_extents; + static final Callback AtkComponentCB_get_position; + static final Callback AtkComponentCB_get_size; + static final Callback AtkComponentCB_ref_accessible_at_point; + static final Callback AtkHypertextCB_get_link; + static final Callback AtkHypertextCB_get_n_links; + static final Callback AtkHypertextCB_get_link_index; + static final Callback AtkObjectCB_get_description; + static final Callback AtkObjectCB_get_index_in_parent; + static final Callback AtkObjectCB_get_n_children; + static final Callback AtkObjectCB_get_name; + static final Callback AtkObjectCB_get_parent; + static final Callback AtkObjectCB_get_role; + static final Callback AtkObjectCB_ref_child; + static final Callback AtkObjectCB_ref_state_set; + static final Callback AtkSelectionCB_is_child_selected; + static final Callback AtkSelectionCB_ref_selection; + static final Callback AtkTextCB_get_caret_offset; + static final Callback AtkTextCB_get_n_selections; + static final Callback AtkTextCB_get_selection; + static final Callback AtkTextCB_get_text; + static final Callback AtkTextCB_get_text_after_offset; + static final Callback AtkTextCB_get_text_at_offset; + static final Callback AtkTextCB_get_text_before_offset; + static final Callback AtkTextCB_get_character_at_offset; + static final Callback AtkTextCB_get_character_count; + static final Callback GObjectClass_finalize; + /* interface initialization callbacks */ + static final Callback InitActionIfaceCB; + static final Callback InitComponentIfaceCB; + static final Callback InitHypertextIfaceCB; + static final Callback GTypeInfo_base_init_type; + static final Callback InitSelectionIfaceCB; + static final Callback InitTextIfaceCB; + /* interface definitions */ + static int /*long*/ ObjectIfaceDefinition; + static final int /*long*/ ActionIfaceDefinition; + static final int /*long*/ ComponentIfaceDefinition; + static final int /*long*/ HypertextIfaceDefinition; + static final int /*long*/ SelectionIfaceDefinition; + static final int /*long*/ TextIfaceDefinition; + static { + AtkActionCB_get_keybinding = newCallback (AccessibleObject.class, "atkAction_get_keybinding", 2); //$NON-NLS-1$ + AtkActionCB_get_name = newCallback (AccessibleObject.class, "atkAction_get_name", 2); //$NON-NLS-1$ + AtkComponentCB_get_extents = newCallback (AccessibleObject.class, "atkComponent_get_extents", 6); //$NON-NLS-1$ + AtkComponentCB_get_position = newCallback (AccessibleObject.class, "atkComponent_get_position", 4); //$NON-NLS-1$ + AtkComponentCB_get_size = newCallback (AccessibleObject.class, "atkComponent_get_size", 4); //$NON-NLS-1$ + AtkComponentCB_ref_accessible_at_point = newCallback (AccessibleObject.class, "atkComponent_ref_accessible_at_point", 4); //$NON-NLS-1$ + AtkHypertextCB_get_link = newCallback (AccessibleObject.class, "atkHypertext_get_link", 2); //$NON-NLS-1$ + AtkHypertextCB_get_n_links = newCallback (AccessibleObject.class, "atkHypertext_get_n_links", 1); //$NON-NLS-1$ + AtkHypertextCB_get_link_index = newCallback (AccessibleObject.class, "atkHypertext_get_link_index", 2); //$NON-NLS-1$ + AtkObjectCB_get_name = newCallback (AccessibleObject.class, "atkObject_get_name", 1); //$NON-NLS-1$ + AtkObjectCB_get_description = newCallback (AccessibleObject.class, "atkObject_get_description", 1); //$NON-NLS-1$ + AtkObjectCB_get_n_children = newCallback (AccessibleObject.class, "atkObject_get_n_children", 1); //$NON-NLS-1$ + AtkObjectCB_get_role = newCallback (AccessibleObject.class, "atkObject_get_role", 1); //$NON-NLS-1$ + AtkObjectCB_get_parent = newCallback (AccessibleObject.class, "atkObject_get_parent", 1); //$NON-NLS-1$ + AtkObjectCB_ref_state_set = newCallback (AccessibleObject.class, "atkObject_ref_state_set", 1); //$NON-NLS-1$ + AtkObjectCB_get_index_in_parent = newCallback (AccessibleObject.class, "atkObject_get_index_in_parent", 1); //$NON-NLS-1$ + AtkObjectCB_ref_child = newCallback (AccessibleObject.class, "atkObject_ref_child", 2); //$NON-NLS-1$ + AtkSelectionCB_is_child_selected = newCallback (AccessibleObject.class, "atkSelection_is_child_selected", 2); //$NON-NLS-1$ + AtkSelectionCB_ref_selection = newCallback (AccessibleObject.class, "atkSelection_ref_selection", 2); //$NON-NLS-1$ + AtkTextCB_get_caret_offset = newCallback (AccessibleObject.class, "atkText_get_caret_offset", 1); //$NON-NLS-1$ + AtkTextCB_get_n_selections = newCallback (AccessibleObject.class, "atkText_get_n_selections", 1); //$NON-NLS-1$ + AtkTextCB_get_selection = newCallback (AccessibleObject.class, "atkText_get_selection", 4); //$NON-NLS-1$ + AtkTextCB_get_text = newCallback (AccessibleObject.class, "atkText_get_text", 3); //$NON-NLS-1$ + AtkTextCB_get_text_after_offset = newCallback (AccessibleObject.class, "atkText_get_text_after_offset", 5); //$NON-NLS-1$ + AtkTextCB_get_text_at_offset = newCallback ( AccessibleObject.class, "atkText_get_text_at_offset", 5); //$NON-NLS-1$ + AtkTextCB_get_text_before_offset = newCallback (AccessibleObject.class, "atkText_get_text_before_offset", 5); //$NON-NLS-1$ + AtkTextCB_get_character_at_offset = newCallback (AccessibleObject.class, "atkText_get_character_at_offset", 2); //$NON-NLS-1$ + AtkTextCB_get_character_count = newCallback (AccessibleObject.class, "atkText_get_character_count", 1); //$NON-NLS-1$ + GObjectClass_finalize = newCallback (AccessibleObject.class, "gObjectClass_finalize", 1); //$NON-NLS-1$ + GTypeInfo_base_init_type = newCallback (AccessibleFactory.class, "gTypeInfo_base_init_type", 1); //$NON-NLS-1$ + /* Action interface */ + InitActionIfaceCB = newCallback (AccessibleFactory.class, "initActionIfaceCB", 1); //$NON-NLS-1$ + GInterfaceInfo interfaceInfo = new GInterfaceInfo (); + interfaceInfo.interface_init = InitActionIfaceCB.getAddress (); + ActionIfaceDefinition = OS.g_malloc (GInterfaceInfo.sizeof); + OS.memmove (ActionIfaceDefinition, interfaceInfo, GInterfaceInfo.sizeof); + /* Component interface */ + InitComponentIfaceCB = newCallback (AccessibleFactory.class, "initComponentIfaceCB", 1); //$NON-NLS-1$ + interfaceInfo = new GInterfaceInfo (); + interfaceInfo.interface_init = InitComponentIfaceCB.getAddress (); + ComponentIfaceDefinition = OS.g_malloc (GInterfaceInfo.sizeof); + OS.memmove (ComponentIfaceDefinition, interfaceInfo, GInterfaceInfo.sizeof); + /* Hypertext interface */ + InitHypertextIfaceCB = newCallback (AccessibleFactory.class, "initHypertextIfaceCB", 1); //$NON-NLS-1$ + interfaceInfo = new GInterfaceInfo (); + interfaceInfo.interface_init = InitHypertextIfaceCB.getAddress (); + HypertextIfaceDefinition = OS.g_malloc (GInterfaceInfo.sizeof); + OS.memmove (HypertextIfaceDefinition, interfaceInfo, GInterfaceInfo.sizeof); + /* Selection interface */ + InitSelectionIfaceCB = newCallback (AccessibleFactory.class, "initSelectionIfaceCB", 1); //$NON-NLS-1$ + interfaceInfo = new GInterfaceInfo (); + interfaceInfo.interface_init = InitSelectionIfaceCB.getAddress (); + SelectionIfaceDefinition = OS.g_malloc (GInterfaceInfo.sizeof); + OS.memmove (SelectionIfaceDefinition, interfaceInfo, GInterfaceInfo.sizeof); + /* Text interface */ + InitTextIfaceCB = newCallback (AccessibleFactory.class, "initTextIfaceCB", 1); //$NON-NLS-1$ + interfaceInfo = new GInterfaceInfo (); + interfaceInfo.interface_init = InitTextIfaceCB.getAddress (); + TextIfaceDefinition = OS.g_malloc (GInterfaceInfo.sizeof); + OS.memmove (TextIfaceDefinition, interfaceInfo, GInterfaceInfo.sizeof); + } + + static private Callback newCallback (Object object, String method, int argCount) { + Callback callback = new Callback (object, method, argCount); + if (callback.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); + return callback; + } + + private AccessibleFactory (int /*long*/ widgetType) { + super (); + widgetTypeName = OS.g_type_name (widgetType); + int widgetTypeNameLength = OS.strlen (widgetTypeName) + 1; + byte[] buffer = new byte [widgetTypeNameLength]; + OS.memmove (buffer, widgetTypeName, widgetTypeNameLength); + byte[] factoryName = new byte [FACTORY_TYPENAME.length + widgetTypeNameLength - 1]; + System.arraycopy (FACTORY_TYPENAME, 0, factoryName, 0, FACTORY_TYPENAME.length); + System.arraycopy (buffer, 0, factoryName, FACTORY_TYPENAME.length - 1, widgetTypeNameLength); + if (OS.g_type_from_name (factoryName) == 0) { + /* register the factory */ + int /*long*/ registry = ATK.atk_get_default_registry (); + int /*long*/ previousFactory = ATK.atk_registry_get_factory (registry, widgetType); + objectParentType = ATK.atk_object_factory_get_accessible_type (previousFactory); + if (objectParentType == 0) objectParentType = DefaultParentType; + int /*long*/ factoryParentType = OS.g_type_from_name (FACTORY_PARENTTYPENAME); + gTypeInfo_base_init_factory = new Callback (this, "gTypeInfo_base_init_factory", 1); //$NON-NLS-1$ + int /*long*/ address = gTypeInfo_base_init_factory.getAddress (); + if (address == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); + GTypeInfo typeInfo = new GTypeInfo (); + typeInfo.base_init = address; + typeInfo.class_size = (short)ATK.AtkObjectFactoryClass_sizeof (); + typeInfo.instance_size = (short)ATK.AtkObjectFactory_sizeof (); + int /*long*/ info = OS.g_malloc (GTypeInfo.sizeof); + OS.memmove (info, typeInfo, GTypeInfo.sizeof); + int /*long*/ swtFactoryType = OS.g_type_register_static (factoryParentType, factoryName, info, 0); + ATK.atk_registry_set_factory_type (registry, widgetType, swtFactoryType); + handle = ATK.atk_registry_get_factory (registry, widgetType); + } + } + + void addAccessible (Accessible accessible) { + int /*long*/ controlHandle = accessible.getControlHandle (); + accessibles.put (new LONG (controlHandle), accessible); + ATK.atk_object_factory_create_accessible (handle, controlHandle); + } + + int /*long*/ atkObjectFactory_create_accessible (int /*long*/ widget) { + Accessible accessible = (Accessible) accessibles.get (new LONG (widget)); + if (accessible == null) { + /* + * we don't care about this control, so create it with the parent's + * type so that its accessibility callbacks will not pass though here + */ + int /*long*/ result = OS.g_object_new (objectParentType, 0); + ATK.atk_object_initialize (result, widget); + return result; + } + /* if an atk object has already been created for this widget then just return it */ + if (accessible.accessibleObject != null) { + return accessible.accessibleObject.handle; + } + int typeNameLength = OS.strlen (widgetTypeName); + byte[] buffer = new byte [typeNameLength]; + OS.memmove (buffer, widgetTypeName, typeNameLength); + int /*long*/ type = getType (buffer, accessible, objectParentType, ACC.CHILDID_SELF); + AccessibleObject object = new AccessibleObject (type, widget, accessible, objectParentType, false); + accessible.accessibleObject = object; + return object.handle; + } + + static int /*long*/ getChildType (Accessible accessible, int childIndex) { + return getType (CHILD_TYPENAME, accessible, DefaultParentType, childIndex); + } + + static int /*long*/ getDefaultParentType () { + return DefaultParentType; + } + + static int /*long*/ getType (byte[] widgetTypeName, Accessible accessible, int /*long*/ parentType, int childId) { + AccessibleControlEvent event = new AccessibleControlEvent (accessible); + event.childID = childId; + AccessibleControlListener[] listeners = accessible.getControlListeners (); + for (int i = 0; i < listeners.length; i++) { + listeners [i].getRole (event); + } + boolean action = false, hypertext = false, selection = false, text = false; + if (event.detail != 0) { /* a role was specified */ + for (int i = 0; i < actionRoles.length; i++) { + if (event.detail == actionRoles [i]) { + action = true; + break; + } + } + for (int i = 0; i < hypertextRoles.length; i++) { + if (event.detail == hypertextRoles [i]) { + hypertext = true; + break; + } + } + for (int i = 0; i < selectionRoles.length; i++) { + if (event.detail == selectionRoles [i]) { + selection = true; + break; + } + } + for (int i = 0; i < textRoles.length; i++) { + if (event.detail == textRoles [i]) { + text = true; + break; + } + } + } else { + action = hypertext = selection = text = true; + } + String swtTypeName = new String (SWT_TYPE_PREFIX); + swtTypeName += new String (widgetTypeName); + if (action) swtTypeName += "Action"; //$NON-NLS-1$ + if (hypertext) swtTypeName += "Hypertext"; //$NON-NLS-1$ + if (selection) swtTypeName += "Selection"; //$NON-NLS-1$ + if (text) swtTypeName += "Text"; //$NON-NLS-1$ + + int /*long*/ type = 0; + LONG typeInt = (LONG)Types.get (swtTypeName); + if (typeInt != null) { + type = typeInt.value; + } else { + /* define the type */ + int /*long*/ queryPtr = OS.g_malloc (GTypeQuery.sizeof); + OS.g_type_query (parentType, queryPtr); + GTypeQuery query = new GTypeQuery (); + OS.memmove (query, queryPtr, GTypeQuery.sizeof); + OS.g_free (queryPtr); + GTypeInfo typeInfo = new GTypeInfo (); + typeInfo.base_init = GTypeInfo_base_init_type.getAddress (); + typeInfo.class_size = (short) query.class_size; + typeInfo.instance_size = (short) query.instance_size; + ObjectIfaceDefinition = OS.g_malloc (GTypeInfo.sizeof); + OS.memmove (ObjectIfaceDefinition, typeInfo, GTypeInfo.sizeof); + byte[] nameBytes = Converter.wcsToMbcs(null, swtTypeName, true); + type = OS.g_type_register_static (parentType, nameBytes, ObjectIfaceDefinition, 0); + OS.g_type_add_interface_static (type, AccessibleObject.ATK_COMPONENT_TYPE, ComponentIfaceDefinition); + if (action) OS.g_type_add_interface_static (type, AccessibleObject.ATK_ACTION_TYPE, ActionIfaceDefinition); + if (hypertext) OS.g_type_add_interface_static (type, AccessibleObject.ATK_HYPERTEXT_TYPE, HypertextIfaceDefinition); + if (selection) OS.g_type_add_interface_static (type, AccessibleObject.ATK_SELECTION_TYPE, SelectionIfaceDefinition); + if (text) OS.g_type_add_interface_static (type, AccessibleObject.ATK_TEXT_TYPE, TextIfaceDefinition); + Types.put (swtTypeName, new LONG (type)); + } + return type; + } + + int /*long*/ gTypeInfo_base_init_factory (int /*long*/ klass) { + int /*long*/ atkObjectFactoryClass = ATK.ATK_OBJECT_FACTORY_CLASS (klass); + AtkObjectFactoryClass objectFactoryClassStruct = new AtkObjectFactoryClass (); + ATK.memmove (objectFactoryClassStruct, atkObjectFactoryClass); + atkObjectFactoryCB_create_accessible = new Callback (this, "atkObjectFactory_create_accessible", 1); //$NON-NLS-1$ + int /*long*/ address = atkObjectFactoryCB_create_accessible.getAddress (); + if (address == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); + objectFactoryClassStruct.create_accessible = address; + ATK.memmove (atkObjectFactoryClass, objectFactoryClassStruct); + return 0; + } + + static int /*long*/ gTypeInfo_base_init_type (int /*long*/ klass) { + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, klass); + objectClass.get_name = AtkObjectCB_get_name.getAddress (); + objectClass.get_description = AtkObjectCB_get_description.getAddress (); + objectClass.get_n_children = AtkObjectCB_get_n_children.getAddress (); + objectClass.get_role = AtkObjectCB_get_role.getAddress (); + objectClass.get_parent = AtkObjectCB_get_parent.getAddress (); + objectClass.ref_state_set = AtkObjectCB_ref_state_set.getAddress (); + objectClass.get_index_in_parent = AtkObjectCB_get_index_in_parent.getAddress (); + objectClass.ref_child = AtkObjectCB_ref_child.getAddress (); + int /*long*/ gObjectClass = OS.G_OBJECT_CLASS (klass); + GObjectClass objectClassStruct = new GObjectClass (); + OS.memmove (objectClassStruct, gObjectClass); + objectClassStruct.finalize = GObjectClass_finalize.getAddress (); + OS.memmove (gObjectClass, objectClassStruct); + ATK.memmove (klass, objectClass); + return 0; + } + + static int /*long*/ initActionIfaceCB (int /*long*/ iface) { + AtkActionIface actionIface = new AtkActionIface (); + ATK.memmove (actionIface, iface); + actionIface.get_keybinding = AtkActionCB_get_keybinding.getAddress (); + actionIface.get_name = AtkActionCB_get_name.getAddress (); + ATK.memmove (iface, actionIface); + return 0; + } + + static int /*long*/ initComponentIfaceCB (int /*long*/ iface) { + AtkComponentIface componentIface = new AtkComponentIface (); + ATK.memmove (componentIface, iface); + componentIface.get_extents = AtkComponentCB_get_extents.getAddress (); + componentIface.get_position = AtkComponentCB_get_position.getAddress (); + componentIface.get_size = AtkComponentCB_get_size.getAddress (); + componentIface.ref_accessible_at_point = AtkComponentCB_ref_accessible_at_point.getAddress (); + ATK.memmove (iface, componentIface); + return 0; + } + + static int /*long*/ initHypertextIfaceCB (int /*long*/ iface) { + AtkHypertextIface hypertextIface = new AtkHypertextIface (); + ATK.memmove (hypertextIface, iface); + hypertextIface.get_link = AtkHypertextCB_get_link.getAddress (); + hypertextIface.get_link_index = AtkHypertextCB_get_link_index.getAddress (); + hypertextIface.get_n_links = AtkHypertextCB_get_n_links.getAddress (); + ATK.memmove (iface, hypertextIface); + return 0; + } + + static int /*long*/ initSelectionIfaceCB (int /*long*/ iface) { + AtkSelectionIface selectionIface = new AtkSelectionIface (); + ATK.memmove (selectionIface, iface); + selectionIface.is_child_selected = AtkSelectionCB_is_child_selected.getAddress (); + selectionIface.ref_selection = AtkSelectionCB_ref_selection.getAddress (); + ATK.memmove (iface, selectionIface); + return 0; + } + + static int /*long*/ initTextIfaceCB (int /*long*/ iface) { + AtkTextIface textInterface = new AtkTextIface (); + ATK.memmove (textInterface, iface); + textInterface.get_caret_offset = AtkTextCB_get_caret_offset.getAddress (); + textInterface.get_character_at_offset = AtkTextCB_get_character_at_offset.getAddress (); + textInterface.get_character_count = AtkTextCB_get_character_count.getAddress (); + textInterface.get_n_selections = AtkTextCB_get_n_selections.getAddress (); + textInterface.get_selection = AtkTextCB_get_selection.getAddress (); + textInterface.get_text = AtkTextCB_get_text.getAddress (); + textInterface.get_text_after_offset = AtkTextCB_get_text_after_offset.getAddress (); + textInterface.get_text_at_offset = AtkTextCB_get_text_at_offset.getAddress (); + textInterface.get_text_before_offset = AtkTextCB_get_text_before_offset.getAddress (); + ATK.memmove (iface, textInterface); + return 0; + } + + static void registerAccessible (Accessible accessible) { + /* If DefaultParentType is 0 then OS accessibility is not active */ + if (DefaultParentType == 0) return; + int /*long*/ controlHandle = accessible.getControlHandle (); + int /*long*/ widgetType = OS.G_OBJECT_TYPE (controlHandle); + AccessibleFactory factory = (AccessibleFactory) Factories.get (new LONG (widgetType)); + if (factory == null) { + factory = new AccessibleFactory (widgetType); + Factories.put (new LONG (widgetType), factory); + } + factory.addAccessible (accessible); + } + + void removeAccessible (Accessible accessible) { + accessibles.remove (new LONG (accessible.getControlHandle ())); + } + + static void unregisterAccessible (Accessible accessible) { + int /*long*/ controlHandle = accessible.getControlHandle (); + int /*long*/ widgetType = OS.G_OBJECT_TYPE (controlHandle); + AccessibleFactory factory = (AccessibleFactory) Factories.get (new LONG (widgetType)); + if (factory != null) { + factory.removeAccessible (accessible); + } + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java new file mode 100644 index 0000000000..00b05d5394 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/gtk/org/eclipse/swt/accessibility/AccessibleObject.java @@ -0,0 +1,1412 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.accessibility; + + +import java.util.*; +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.accessibility.gtk.*; +import org.eclipse.swt.internal.gtk.*; +import org.eclipse.swt.widgets.*; + +class AccessibleObject { + int /*long*/ handle; + int /*long*/ parentType; + int index = -1, id = ACC.CHILDID_SELF; + Accessible accessible; + AccessibleObject parent; + Hashtable children = new Hashtable (9); + /* + * 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 int /*long*/ actionNamePtr = -1; + static int /*long*/ descriptionPtr = -1; + static int /*long*/ keybindingPtr = -1; + static int /*long*/ namePtr = -1; + static final Hashtable AccessibleObjects = new Hashtable (9); + static final int /*long*/ ATK_ACTION_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkAction", true)); + static final int /*long*/ ATK_COMPONENT_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkComponent", true)); + static final int /*long*/ ATK_HYPERTEXT_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkHypertext", true)); + static final int /*long*/ ATK_SELECTION_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkSelection", true)); + static final int /*long*/ ATK_TEXT_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkText", true)); + static final boolean DEBUG = Display.DEBUG; + + AccessibleObject (int /*long*/ type, int /*long*/ widget, Accessible accessible, int /*long*/ parentType, boolean isLightweight) { + super (); + handle = ATK.g_object_new (type, 0); + this.parentType = parentType; + ATK.atk_object_initialize (handle, widget); + this.accessible = accessible; + this.isLightweight = isLightweight; + AccessibleObjects.put (new LONG (handle), this); + if (DEBUG) System.out.println("new AccessibleObject: " + handle); + } + + void addChild (AccessibleObject child) { + children.put (new LONG (child.handle), child); + child.setParent (this); + } + + static int /*long*/ atkAction_get_keybinding (int /*long*/ atkObject, int /*long*/ index) { + if (DEBUG) System.out.println ("-->atkAction_get_keybinding"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + if (ATK.g_type_is_a (object.parentType, ATK_ACTION_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_ACTION_GET_IFACE (object.handle)); + AtkActionIface actionIface = new AtkActionIface (); + ATK.memmove (actionIface, superType); + if (actionIface.get_keybinding != 0) { + parentResult = ATK.call (actionIface.get_keybinding, object.handle, index); + } + } + AccessibleListener[] listeners = object.getAccessibleListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleEvent event = new AccessibleEvent (object.accessible); + event.childID = object.id; + if (parentResult != 0) { + int length = OS.strlen (parentResult); + byte [] buffer = new byte [length]; + OS.memmove (buffer, parentResult, length); + event.result = new String (Converter.mbcsToWcs (null, buffer)); + } + for (int i = 0; i < listeners.length; i++) { + listeners [i].getKeyboardShortcut (event); + } + if (event.result == null) return parentResult; + if (keybindingPtr != -1) OS.g_free (keybindingPtr); + byte[] name = Converter.wcsToMbcs (null, event.result, true); + keybindingPtr = OS.g_malloc (name.length); + OS.memmove (keybindingPtr, name, name.length); + return keybindingPtr; + } + + static int /*long*/ atkAction_get_name (int /*long*/ atkObject, int /*long*/ index) { + if (DEBUG) System.out.println ("-->atkAction_get_name"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + if (ATK.g_type_is_a (object.parentType, ATK_ACTION_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_ACTION_GET_IFACE (object.handle)); + AtkActionIface actionIface = new AtkActionIface (); + ATK.memmove (actionIface, superType); + if (actionIface.get_name != 0) { + parentResult = ATK.call (actionIface.get_name, object.handle, index); + } + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + if (parentResult != 0) { + int length = OS.strlen (parentResult); + byte [] buffer = new byte [length]; + OS.memmove (buffer, parentResult, length); + event.result = new String (Converter.mbcsToWcs (null, buffer)); + } + for (int i = 0; i < listeners.length; i++) { + listeners [i].getDefaultAction (event); + } + if (event.result == null) return parentResult; + if (actionNamePtr != -1) OS.g_free (actionNamePtr); + byte[] name = Converter.wcsToMbcs (null, event.result, true); + actionNamePtr = OS.g_malloc (name.length); + OS.memmove (actionNamePtr, name, name.length); + return actionNamePtr; + } + + static int /*long*/ atkComponent_get_extents (int /*long*/ atkObject, int /*long*/ x, int /*long*/ y, int /*long*/ width, int /*long*/ height, int /*long*/ coord_type) { + if (DEBUG) System.out.println ("-->atkComponent_get_extents"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + OS.memmove (x, new int[] {0}, 4); + OS.memmove (y, new int[] {0}, 4); + OS.memmove (width, new int[] {0}, 4); + OS.memmove (height, new int[] {0}, 4); + if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle)); + AtkComponentIface componentIface = new AtkComponentIface (); + ATK.memmove (componentIface, superType); + if (componentIface.get_extents != 0) { + ATK.call (componentIface.get_extents, object.handle, x, y, width, height, coord_type); + } + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return 0; + + int[] parentX = new int [1], parentY = new int [1]; + int[] parentWidth = new int [1], parentHeight = new int [1]; + OS.memmove (parentX, x, 4); + OS.memmove (parentY, y, 4); + OS.memmove (parentWidth, width, 4); + OS.memmove (parentHeight, height, 4); + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + event.x = parentX [0]; event.y = parentY [0]; + event.width = parentWidth [0]; event.height = parentHeight [0]; + if (coord_type == ATK.ATK_XY_WINDOW) { + /* translate control -> display, for filling in event to be dispatched */ + int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle); + GtkAccessible gtkAccessible = new GtkAccessible (); + ATK.memmove (gtkAccessible, gtkAccessibleHandle); + int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget); + int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel); + int[] topWindowX = new int [1], topWindowY = new int [1]; + OS.gdk_window_get_origin (window, topWindowX, topWindowY); + event.x += topWindowX [0]; + event.y += topWindowY [0]; + } + for (int i = 0; i < listeners.length; i++) { + listeners [i].getLocation (event); + } + if (coord_type == ATK.ATK_XY_WINDOW) { + /* translate display -> control, for answering to the OS */ + int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle); + GtkAccessible gtkAccessible = new GtkAccessible (); + ATK.memmove (gtkAccessible, gtkAccessibleHandle); + int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget); + int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel); + int[] topWindowX = new int [1], topWindowY = new int [1]; + OS.gdk_window_get_origin (window, topWindowX, topWindowY); + event.x -= topWindowX [0]; + event.y -= topWindowY [0]; + } + OS.memmove (x, new int[] {event.x}, 4); + OS.memmove (y, new int[] {event.y}, 4); + OS.memmove (width, new int[] {event.width}, 4); + OS.memmove (height, new int[] {event.height}, 4); + return 0; + } + + static int /*long*/ atkComponent_get_position (int /*long*/ atkObject, int /*long*/ x, int /*long*/ y, int /*long*/ coord_type) { + if (DEBUG) System.out.println ("-->atkComponent_get_position, object: " + atkObject + " x: " + x + " y: " + y + " coord: " + coord_type); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + OS.memmove (x, new int[] {0}, 4); + OS.memmove (y, new int[] {0}, 4); + if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle)); + AtkComponentIface componentIface = new AtkComponentIface (); + ATK.memmove (componentIface, superType); + if (componentIface.get_extents != 0) { + ATK.call (componentIface.get_position, object.handle, x, y, coord_type); + } + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return 0; + + int[] parentX = new int [1], parentY = new int [1]; + OS.memmove (parentX, x, 4); + OS.memmove (parentY, y, 4); + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + event.x = parentX [0]; event.y = parentY [0]; + if (coord_type == ATK.ATK_XY_WINDOW) { + /* translate control -> display, for filling in event to be dispatched */ + int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle); + GtkAccessible gtkAccessible = new GtkAccessible (); + ATK.memmove (gtkAccessible, gtkAccessibleHandle); + int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget); + int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel); + int[] topWindowX = new int [1], topWindowY = new int [1]; + OS.gdk_window_get_origin (window, topWindowX, topWindowY); + event.x += topWindowX [0]; + event.y += topWindowY [0]; + } + for (int i = 0; i < listeners.length; i++) { + listeners [i].getLocation (event); + } + if (coord_type == ATK.ATK_XY_WINDOW) { + /* translate display -> control, for answering to the OS */ + int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle); + GtkAccessible gtkAccessible = new GtkAccessible (); + ATK.memmove (gtkAccessible, gtkAccessibleHandle); + int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget); + int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel); + int[] topWindowX = new int [1], topWindowY = new int [1]; + OS.gdk_window_get_origin (window, topWindowX, topWindowY); + event.x -= topWindowX [0]; + event.y -= topWindowY [0]; + } + OS.memmove (x, new int[] {event.x}, 4); + OS.memmove (y, new int[] {event.y}, 4); + return 0; + } + + static int /*long*/ atkComponent_get_size (int /*long*/ atkObject, int /*long*/ width, int /*long*/ height, int /*long*/ coord_type) { + if (DEBUG) System.out.println ("-->atkComponent_get_size"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + OS.memmove (width, new int[] {0}, 4); + OS.memmove (height, new int[] {0}, 4); + if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle)); + AtkComponentIface componentIface = new AtkComponentIface (); + ATK.memmove (componentIface, superType); + if (componentIface.get_extents != 0) { + ATK.call (componentIface.get_size, object.handle, width, height, coord_type); + } + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return 0; + + int[] parentWidth = new int [1], parentHeight = new int [1]; + OS.memmove (parentWidth, width, 4); + OS.memmove (parentHeight, height, 4); + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + event.width = parentWidth [0]; event.height = parentHeight [0]; + for (int i = 0; i < listeners.length; i++) { + listeners [i].getLocation (event); + } + OS.memmove (width, new int[] {event.width}, 4); + OS.memmove (height, new int[] {event.height}, 4); + return 0; + } + + static int /*long*/ atkComponent_ref_accessible_at_point (int /*long*/ atkObject, int /*long*/ x, int /*long*/ y, int /*long*/ coord_type) { + if (DEBUG) System.out.println ("-->atkComponent_ref_accessible_at_point"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle)); + AtkComponentIface componentIface = new AtkComponentIface (); + ATK.memmove (componentIface, superType); + if (componentIface.ref_accessible_at_point != 0) { + parentResult = ATK.call (componentIface.ref_accessible_at_point, object.handle, x, y, coord_type); + } + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + event.x = (int)/*64*/x; event.y = (int)/*64*/y; + if (coord_type == ATK.ATK_XY_WINDOW) { + /* translate control -> display, for filling in the event to be dispatched */ + int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle); + GtkAccessible gtkAccessible = new GtkAccessible (); + ATK.memmove (gtkAccessible, gtkAccessibleHandle); + int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget); + int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel); + int[] topWindowX = new int [1], topWindowY = new int [1]; + OS.gdk_window_get_origin (window, topWindowX, topWindowY); + event.x += topWindowX [0]; + event.y += topWindowY [0]; + } + for (int i = 0; i < listeners.length; i++) { + listeners [i].getChildAtPoint (event); + } + if (event.childID == object.id) event.childID = ACC.CHILDID_SELF; + AccessibleObject accObj = object.getChildByID (event.childID); + if (accObj != null) { + if (parentResult > 0) OS.g_object_unref (parentResult); + OS.g_object_ref (accObj.handle); + return accObj.handle; + } + return parentResult; + } + + static int /*long*/ atkHypertext_get_link (int /*long*/ atkObject, int /*long*/ link_index) { + if (DEBUG) System.out.println ("-->atkHypertext_get_link"); + return 0; + } + + static int /*long*/ atkHypertext_get_n_links (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkHypertext_get_n_links"); + return 0; /* read hyperlink's name */ + } + + static int /*long*/ atkHypertext_get_link_index (int /*long*/ atkObject, int /*long*/ char_index) { + if (DEBUG) System.out.println ("-->atkHypertext_get_link_index"); + return 0; + } + + static int /*long*/ atkObject_get_description (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkObject_get_description"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.get_description != 0) { + parentResult = ATK.call (objectClass.get_description, object.handle); + } + AccessibleListener[] listeners = object.getAccessibleListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleEvent event = new AccessibleEvent (object.accessible); + event.childID = object.id; + if (parentResult != 0) { + int length = OS.strlen (parentResult); + byte [] buffer = new byte [length]; + OS.memmove (buffer, parentResult, length); + event.result = new String (Converter.mbcsToWcs (null, buffer)); + } + for (int i = 0; i < listeners.length; i++) { + listeners [i].getDescription (event); + } + if (event.result == null) return parentResult; + if (descriptionPtr != -1) OS.g_free (descriptionPtr); + byte[] name = Converter.wcsToMbcs (null, event.result, true); + descriptionPtr = OS.g_malloc (name.length); + OS.memmove (descriptionPtr, name, name.length); + return descriptionPtr; + } + + static int /*long*/ atkObject_get_name (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkObject_get_name: " + atkObject); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.get_name != 0) { + parentResult = ATK.call (objectClass.get_name, object.handle); + } + AccessibleListener[] listeners = object.getAccessibleListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleEvent event = new AccessibleEvent (object.accessible); + event.childID = object.id; + if (parentResult != 0) { + int length = OS.strlen (parentResult); + byte [] buffer = new byte [length]; + OS.memmove (buffer, parentResult, length); + event.result = new String (Converter.mbcsToWcs (null, buffer)); + } + for (int i = 0; i < listeners.length; i++) { + listeners [i].getName (event); + } + if (event.result == null) return parentResult; + if (namePtr != -1) OS.g_free (namePtr); + byte[] name = Converter.wcsToMbcs (null, event.result, true); + namePtr = OS.g_malloc (name.length); + OS.memmove (namePtr, name, name.length); + return namePtr; + } + + static int /*long*/ atkObject_get_n_children (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkObject_get_n_children: " + atkObject); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.get_n_children != 0) { + parentResult = ATK.call (objectClass.get_n_children, object.handle); + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + event.detail = (int)/*64*/parentResult; + for (int i = 0; i < listeners.length; i++) { + listeners [i].getChildCount (event); + } + return event.detail; + } + + static int /*long*/ atkObject_get_index_in_parent (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkObjectCB_get_index_in_parent. "); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + if (object.index != -1) return object.index; + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.get_index_in_parent == 0) return 0; + return ATK.call (objectClass.get_index_in_parent,object. handle); + } + + static int /*long*/ atkObject_get_parent (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkObject_get_parent: " + atkObject); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + if (object.parent != null) return object.parent.handle; + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.get_parent == 0) return 0; + return ATK.call (objectClass.get_parent, object.handle); + } + + static int /*long*/ atkObject_get_role (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkObject_get_role: " + atkObject); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + if (object.getAccessibleListeners ().length != 0) { + AccessibleControlListener[] listeners = object.getControlListeners (); + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + event.detail = -1; + for (int i = 0; i < listeners.length; i++) { + listeners [i].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_LIST; + case ACC.ROLE_TABLECELL: return ATK.ATK_ROLE_LIST_ITEM; + 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; + } + } + } + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.get_role == 0) return 0; + return ATK.call (objectClass.get_role, object.handle); + } + + static int /*long*/ atkObject_ref_child (int /*long*/ atkObject, int /*long*/ index) { + if (DEBUG) System.out.println ("-->atkObject_ref_child: " + index + " of: " + atkObject); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + object.updateChildren (); + AccessibleObject accObject = object.getChildByIndex ((int)/*64*/index); + if (accObject != null) { + OS.g_object_ref (accObject.handle); + return accObject.handle; + } + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.ref_child == 0) return 0; + return ATK.call (objectClass.ref_child, object.handle, index); + } + + static int /*long*/ atkObject_ref_state_set (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkObject_ref_state_set"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkObjectClass objectClass = new AtkObjectClass (); + ATK.memmove (objectClass, superType); + if (objectClass.ref_state_set != 0) { + parentResult = ATK.call (objectClass.ref_state_set, object.handle); + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return parentResult; + + int /*long*/ set = parentResult; + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + event.detail = -1; + for (int i = 0; i < listeners.length; i++) { + listeners [i].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); + /* Note: STATE_COLLAPSED, STATE_LINKED and STATE_NORMAL have no ATK equivalents */ + } + return set; + } + + static int /*long*/ atkSelection_is_child_selected (int /*long*/ atkObject, int /*long*/ index) { + if (DEBUG) System.out.println ("-->atkSelection_is_child_selected"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + if (ATK.g_type_is_a (object.parentType, ATK_SELECTION_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_SELECTION_GET_IFACE (object.handle)); + AtkSelectionIface selectionIface = new AtkSelectionIface (); + ATK.memmove (selectionIface, superType); + if (selectionIface.is_child_selected != 0) { + parentResult = ATK.call (selectionIface.is_child_selected, object.handle, index); + } + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + for (int i = 0; i < listeners.length; i++) { + listeners [i].getSelection (event); + } + AccessibleObject accessibleObject = object.getChildByID (event.childID); + if (accessibleObject != null) { + return accessibleObject.index == index ? 1 : 0; + } + return parentResult; + } + + static int /*long*/ atkSelection_ref_selection (int /*long*/ atkObject, int /*long*/ index) { + if (DEBUG) System.out.println ("-->atkSelection_ref_selection"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + if (ATK.g_type_is_a (object.parentType, ATK_SELECTION_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_SELECTION_GET_IFACE (object.handle)); + AtkSelectionIface selectionIface = new AtkSelectionIface (); + ATK.memmove (selectionIface, superType); + if (selectionIface.ref_selection != 0) { + parentResult = ATK.call (selectionIface.ref_selection, object.handle, index); + } + } + AccessibleControlListener[] listeners = object.getControlListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleControlEvent event = new AccessibleControlEvent (object.accessible); + event.childID = object.id; + for (int i = 0; i < listeners.length; i++) { + listeners [i].getSelection (event); + } + AccessibleObject accObj = object.getChildByID (event.childID); + if (accObj != null) { + if (parentResult > 0) OS.g_object_unref (parentResult); + OS.g_object_ref (accObj.handle); + return accObj.handle; + } + return parentResult; + } + + static int /*long*/ atkText_get_caret_offset (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkText_get_caret_offset"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle)); + AtkTextIface textIface = new AtkTextIface (); + ATK.memmove (textIface, superType); + if (textIface.get_caret_offset != 0) { + parentResult = ATK.call (textIface.get_caret_offset, object.handle); + } + } + AccessibleTextListener[] listeners = object.getTextListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleTextEvent event = new AccessibleTextEvent (object.accessible); + event.childID = object.id; + event.offset = (int)/*64*/parentResult; + for (int i = 0; i < listeners.length; i++) { + listeners [i].getCaretOffset (event); + } + return event.offset; + } + + static int /*long*/ atkText_get_character_at_offset (int /*long*/ atkObject, int /*long*/ offset) { + if (DEBUG) System.out.println ("-->atkText_get_character_at_offset"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + String text = object.getText (); + if (text != null) return text.charAt ((int)/*64*/offset); // TODO + if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) { + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkTextIface textIface = new AtkTextIface (); + ATK.memmove (textIface, superType); + if (textIface.get_character_at_offset != 0) { + return ATK.call (textIface.get_character_at_offset, object.handle, offset); + } + } + return 0; + } + + static int /*long*/ atkText_get_character_count (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkText_get_character_count"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + String text = object.getText (); + if (text != null) return text.length (); + if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) { + int /*long*/ superType = ATK.g_type_class_peek (object.parentType); + AtkTextIface textIface = new AtkTextIface (); + ATK.memmove (textIface, superType); + if (textIface.get_character_count != 0) { + return ATK.call (textIface.get_character_count, object.handle); + } + } + return 0; + } + + static int /*long*/ atkText_get_n_selections (int /*long*/ atkObject) { + if (DEBUG) System.out.println ("-->atkText_get_n_selections"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int /*long*/ parentResult = 0; + if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle)); + AtkTextIface textIface = new AtkTextIface (); + ATK.memmove (textIface, superType); + if (textIface.get_n_selections != 0) { + parentResult = ATK.call (textIface.get_n_selections, object.handle); + } + } + AccessibleTextListener[] listeners = object.getTextListeners (); + if (listeners.length == 0) return parentResult; + + AccessibleTextEvent event = new AccessibleTextEvent (object.accessible); + event.childID = object.id; + for (int i = 0; i < listeners.length; i++) { + listeners [i].getSelectionRange (event); + } + return event.length == 0 ? parentResult : 1; + } + + static int /*long*/ atkText_get_selection (int /*long*/ atkObject, int /*long*/ selection_num, int /*long*/ start_offset, int /*long*/ end_offset) { + if (DEBUG) System.out.println ("-->atkText_get_selection"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + OS.memmove (start_offset, new int[] {0}, 4); + OS.memmove (end_offset, new int[] {0}, 4); + if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle)); + AtkTextIface textIface = new AtkTextIface (); + ATK.memmove (textIface, superType); + if (textIface.get_selection != 0) { + ATK.call (textIface.get_selection, object.handle, selection_num, start_offset, end_offset); + } + } + AccessibleTextListener[] listeners = object.getTextListeners (); + if (listeners.length == 0) return 0; + + AccessibleTextEvent event = new AccessibleTextEvent (object.accessible); + event.childID = object.id; + int[] parentStart = new int [1]; + int[] parentEnd = new int [1]; + OS.memmove (parentStart, start_offset, 4); + OS.memmove (parentEnd, end_offset, 4); + event.offset = parentStart [0]; + event.length = parentEnd [0] - parentStart [0]; + for (int i = 0; i < listeners.length; i++) { + listeners [i].getSelectionRange (event); + } + OS.memmove (start_offset, new int[] {event.offset}, 4); + OS.memmove (end_offset, new int[] {event.offset + event.length}, 4); + return 0; + } + + static int /*long*/ atkText_get_text (int /*long*/ atkObject, int /*long*/ start_offset, int /*long*/ end_offset) { + if (DEBUG) System.out.println ("-->atkText_get_text: " + start_offset + "," + end_offset); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + String text = object.getText (); + if (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)/*64*/start_offset, (int)/*64*/end_offset); + byte[] bytes = Converter.wcsToMbcs (null, text, true); + int /*long*/ result = OS.g_malloc (bytes.length); + OS.memmove (result, bytes, bytes.length); + return result; + } + return 0; + } + + static int /*long*/ atkText_get_text_after_offset (int /*long*/ atkObject, int /*long*/ offset_value, int /*long*/ boundary_type, int /*long*/ start_offset, int /*long*/ end_offset) { + if (DEBUG) System.out.println ("-->atkText_get_text_after_offset"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int offset = (int)/*64*/offset_value; + String text = object.getText (); + if (text.length () > 0) { + int length = text.length (); + offset = Math.min (offset, length - 1); + int startBounds = offset; + int endBounds = offset; + switch ((int)/*64*/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)/*64*/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; + } + } + OS.memmove (start_offset, new int[] {startBounds}, 4); + OS.memmove (end_offset, new int[] {endBounds}, 4); + text = text.substring (startBounds, endBounds); + byte[] bytes = Converter.wcsToMbcs (null, text, true); + int /*long*/ result = OS.g_malloc (bytes.length); + OS.memmove (result, bytes, bytes.length); + return result; + } + return 0; + } + + static int /*long*/ atkText_get_text_at_offset (int /*long*/ atkObject, int /*long*/ offset_value, int /*long*/ boundary_type, int /*long*/ start_offset, int /*long*/ end_offset) { + if (DEBUG) System.out.println ("-->atkText_get_text_at_offset: " + offset_value + " start: " + start_offset + " end: " + end_offset); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int offset = (int)/*64*/offset_value; + String text = object.getText (); + if (text.length () > 0) { + int length = text.length (); + offset = Math.min (offset, length - 1); + int startBounds = offset; + int endBounds = offset; + switch ((int)/*64*/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); + } + } + OS.memmove (start_offset, new int[] {startBounds}, 4); + OS.memmove (end_offset, new int[] {endBounds}, 4); + text = text.substring (startBounds, endBounds); + byte[] bytes = Converter.wcsToMbcs (null, text, true); + int /*long*/ result = OS.g_malloc (bytes.length); + OS.memmove (result, bytes, bytes.length); + return result; + } + return 0; + } + + static int /*long*/ atkText_get_text_before_offset (int /*long*/ atkObject, int /*long*/ offset_value, int /*long*/ boundary_type, int /*long*/ start_offset, int /*long*/ end_offset) { + if (DEBUG) System.out.println ("-->atkText_get_text_before_offset"); + AccessibleObject object = getAccessibleObject (atkObject); + if (object == null) return 0; + int offset = (int)/*64*/offset_value; + String text = object.getText (); + if (text.length () > 0) { + int length = text.length (); + offset = Math.min (offset, length - 1); + int startBounds = offset; + int endBounds = offset; + switch ((int)/*64*/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; + } + } + OS.memmove (start_offset, new int[] {startBounds}, 4); + OS.memmove (end_offset, new int[] {endBounds}, 4); + text = text.substring (startBounds, endBounds); + byte[] bytes = Converter.wcsToMbcs (null, text, true); + int /*long*/ result = OS.g_malloc (bytes.length); + OS.memmove (result, bytes, bytes.length); + return result; + } + return 0; + } + + AccessibleListener[] getAccessibleListeners () { + if (accessible == null) return new AccessibleListener [0]; + AccessibleListener[] result = accessible.getAccessibleListeners (); + return result != null ? result : new AccessibleListener [0]; + } + + static AccessibleObject getAccessibleObject (int /*long*/ atkObject) { + return (AccessibleObject)AccessibleObjects.get (new LONG (atkObject)); + } + + AccessibleObject getChildByHandle (int /*long*/ handle) { + return (AccessibleObject) children.get (new LONG (handle)); + } + + AccessibleObject getChildByID (int childId) { + if (childId == ACC.CHILDID_SELF) return this; + Enumeration elements = children.elements (); + while (elements.hasMoreElements ()) { + AccessibleObject object = (AccessibleObject) elements.nextElement (); + if (object.id == childId) return object; + } + return null; + } + + AccessibleObject getChildByIndex (int childIndex) { + Enumeration elements = children.elements (); + while (elements.hasMoreElements ()) { + AccessibleObject object = (AccessibleObject) elements.nextElement (); + if (object.index == childIndex) return object; + } + return null; + } + + AccessibleControlListener[] getControlListeners () { + if (accessible == null) return new AccessibleControlListener [0]; + AccessibleControlListener[] result = accessible.getControlListeners (); + return result != null ? result : new AccessibleControlListener [0]; + } + + String getText () { + int /*long*/ parentResult = 0; + String parentText = ""; //$NON-NLS-1$ + if (ATK.g_type_is_a (parentType, ATK_TEXT_TYPE)) { + int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (handle)); + AtkTextIface textIface = new AtkTextIface (); + ATK.memmove (textIface, superType); + int /*long*/ characterCount = 0; + if (textIface.get_character_count != 0) { + characterCount = ATK.call (textIface.get_character_count, handle); + } + if (characterCount > 0 && textIface.get_text != 0) { + parentResult = ATK.call (textIface.get_text, handle, 0, characterCount); + if (parentResult != 0) { + int length = OS.strlen (parentResult); + byte [] buffer = new byte [length]; + OS.memmove (buffer, parentResult, length); + parentText = new String (Converter.mbcsToWcs (null, buffer)); + } + } + } + AccessibleControlListener[] controlListeners = getControlListeners (); + if (controlListeners.length == 0) return parentText; + AccessibleControlEvent event = new AccessibleControlEvent (accessible); + event.childID = id; + event.result = parentText; + for (int i = 0; i < controlListeners.length; i++) { + controlListeners [i].getValue (event); + } + return event.result; + } + + AccessibleTextListener[] getTextListeners () { + if (accessible == null) return new AccessibleTextListener [0]; + AccessibleTextListener[] result = accessible.getTextListeners (); + return result != null ? result : new AccessibleTextListener [0]; + } + + static int /*long*/ gObjectClass_finalize (int /*long*/ atkObject) { + int /*long*/ superType = ATK.g_type_class_peek_parent (ATK.G_OBJECT_GET_CLASS (atkObject)); + int /*long*/ gObjectClass = ATK.G_OBJECT_CLASS (superType); + GObjectClass objectClassStruct = new GObjectClass (); + ATK.memmove (objectClassStruct, gObjectClass); + ATK.call (objectClassStruct.finalize, atkObject); + AccessibleObject object = getAccessibleObject (atkObject); + if (object != null) { + AccessibleObjects.remove (new LONG (atkObject)); + object.release (); + } + return 0; + } + + 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 release () { + if (DEBUG) System.out.println("AccessibleObject.release: " + handle); + accessible = null; + Enumeration elements = children.elements (); + while (elements.hasMoreElements ()) { + AccessibleObject child = (AccessibleObject) elements.nextElement (); + if (child.isLightweight) OS.g_object_unref (child.handle); + } + if (parent != null) parent.removeChild (this, false); + } + + void removeChild (AccessibleObject child, boolean unref) { + children.remove (new LONG (child.handle)); + if (unref && child.isLightweight) OS.g_object_unref (child.handle); + } + + void selectionChanged () { + OS.g_signal_emit_by_name (handle, ATK.selection_changed); + } + + void setFocus (int childID) { + updateChildren (); + AccessibleObject accObject = getChildByID (childID); + if (accObject != null) { + ATK.atk_focus_tracker_notify (accObject.handle); + } + } + + void setParent (AccessibleObject parent) { + this.parent = parent; + } + + void textCaretMoved(int index) { + OS.g_signal_emit_by_name (handle, ATK.text_caret_moved, index); + } + + void textChanged(int type, int startIndex, int length) { + if (type == ACC.TEXT_DELETE) { + OS.g_signal_emit_by_name (handle, ATK.text_changed_delete, startIndex, length); + } else { + OS.g_signal_emit_by_name (handle, ATK.text_changed_insert, startIndex, length); + } + } + + void textSelectionChanged() { + OS.g_signal_emit_by_name (handle, ATK.text_selection_changed); + } + + void updateChildren () { + if (isLightweight) return; + AccessibleControlListener[] listeners = getControlListeners (); + if (listeners.length == 0) return; + + AccessibleControlEvent event = new AccessibleControlEvent (accessible); + for (int i = 0; i < listeners.length; i++) { + listeners [i].getChildren (event); + } + if (event.children != null && event.children.length > 0) { + Vector idsToKeep = new Vector (children.size ()); + if (event.children [0] instanceof Integer) { + /* an array of child id's (Integers) was answered */ + int /*long*/ parentType = AccessibleFactory.getDefaultParentType (); + for (int i = 0; i < event.children.length; i++) { + AccessibleObject object = getChildByIndex (i); + if (object == null) { + int /*long*/ childType = AccessibleFactory.getChildType (accessible, i); + object = new AccessibleObject (childType, 0, accessible, parentType, true); + AccessibleObjects.put (new LONG (object.handle), object); + addChild (object); + object.index = i; + } + try { + object.id = ((Integer)event.children[i]).intValue (); + } catch (ClassCastException e) { + /* a non-ID value was given so don't set the ID */ + } + idsToKeep.addElement (new LONG (object.handle)); + } + } else { + /* an array of Accessible children was answered */ + int childIndex = 0; + for (int i = 0; i < event.children.length; i++) { + AccessibleObject object = null; + try { + object = ((Accessible)event.children [i]).accessibleObject; + } catch (ClassCastException e) { + /* a non-Accessible value was given so nothing to do here */ + } + if (object != null) { + object.index = childIndex++; + idsToKeep.addElement (new LONG (object.handle)); + } + } + } + /* remove old children that were not provided as children anymore */ + Enumeration ids = children.keys (); + while (ids.hasMoreElements ()) { + LONG id = (LONG)ids.nextElement (); + if (!idsToKeep.contains (id)) { + AccessibleObject object = (AccessibleObject) children.get (id); + removeChild (object, true); + } + } + } + } +} |