From: Mark Doffman Date: Tue, 29 Jul 2008 15:00:16 +0000 (+0100) Subject: 2008-07-29 Mark Doffman X-Git-Tag: AT_SPI2_ATK_2_12_0~618 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9f1e72aa346b872b32ffad45a5fe48515a4822e9;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git 2008-07-29 Mark Doffman * pyatspi/base.py pyatspi/cache.py pyatspi/desktop.py Refactor so that Desktop and Accessible classes can use same base proxy with different caches. * pyatspi/event.py pyatspi/registry.py Add code needed from CORBA pyatspi * .gitignore Ignore *.pyc files. --- diff --git a/.gitignore b/.gitignore index 91540a4..d8b2346 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.pyc ChangeLog Makefile.in aclocal.m4 diff --git a/pyatspi/base.py b/pyatspi/base.py index 8f23713..0060ea0 100644 --- a/pyatspi/base.py +++ b/pyatspi/base.py @@ -12,27 +12,33 @@ #along with this program; if not, write to the Free Software #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -from weakref import ref +from weakref import proxy from dbus.proxies import Interface, ProxyObject from dbus.exceptions import * -from factory import interfaceFactory - class AccessibleObjectNoLongerExists(Exception): pass #------------------------------------------------------------------------------ -class Enum(object): +class Enum(int): def __str__(self): return self._enum_lookup(int(self)) #------------------------------------------------------------------------------ -class BaseProxyMeta(type): - def __init__(cls): - type.__init__(cls) +class BaseProxy(Interface): + """ + The base D-Bus proxy for a remote object that implements one or more + of the AT-SPI interfaces. + + This class must be further specialised as the cache stores are different + for Desktop objects and other Accessible objects. + """ + + def __new__(cls, *args, **kwargs): + Interface.__new__(cls, *args, **kwargs) queryable_interfaces = { 'Accessible':ATSPI_ACCESSIBLE, @@ -59,32 +65,19 @@ class BaseProxyMeta(type): return self.queryInterface(object, queryable_interfaces[interface]) setattr(cls, name, new_query) -#------------------------------------------------------------------------------ - -class BaseProxy(Interface): - """ - A D-Bus proxy for a remote object that implements one or more of the AT-SPI - Accessibility interfaces. - """ - - __metaclass__ = BaseProxyMeta - - def __init__(self, busobject, cache, app, path, interface): + def __init__(self, obj, cache, path, interface): """ Create a D-Bus Proxy for an ATSPI interface. - busobject - The D-Bus proxy object this interface uses for D-Bus calls. - cache - The accessible cache that this object is owned by. + obj - The D-Bus proxy object this interface uses for D-Bus calls. + cache - Cache storing data for this object. path - The object path of the remote object. - app - The bus name of the application this object belongs to. interface - The name of the ATSPI interface that this proxy implements. """ - Interface.__init__(self, busobject, interface) - - self._cache = cache + Interface.__init__(self, obj, interface) + self._cobj = ref(cache) self._path = path - self._app = app self._pgetter = self.get_dbus_method("Get", dbus_interface="org.freedesktop.DBus.Properties") self._psetter = self.get_dbus_method("Set", dbus_interface="org.freedesktop.DBus.Properties") @@ -104,6 +97,12 @@ class BaseProxy(Interface): raise LookupError(e) @property + def _cache(self): + c = self._cobj() + if not c: + raise AccessibleObjectNoLongerExits("Application has been removed") + + @property def _data(self): try: data = self._cache._objects[self._path] @@ -117,7 +116,7 @@ class BaseProxy(Interface): def queryInterface(self, interface): if interface in self._data.interfaces: - return interfaceFactory(self._obj, self._cache, self._app, self._path, interface) + return self._cache.proxyFactory(self._path, interface, dbus_obj=self._obj) else: raise NotImplementedError( "%s not supported by accessible object at path %s" diff --git a/pyatspi/cache.py b/pyatspi/cache.py index a707ceb..14c959a 100644 --- a/pyatspi/cache.py +++ b/pyatspi/cache.py @@ -15,11 +15,6 @@ from base import AccessibleObjectNoLongerExists from factory import interfaceFactory -ATSPI_DEVICE_EVENT_CONTROLLER = 'org.freedesktop.atspi.DeviceEventController' -ATSPI_DEVICE_EVENT_LISTENER = 'org.freedesktop.atspi.DeviceEventListener' -ATSPI_REGISTRY = 'org.freedesktop.atspi.Registry' -ATSPI_TREE = 'org.freedesktop.atspi.Tree' - #------------------------------------------------------------------------------ class _CacheData(object): @@ -47,141 +42,155 @@ class _CacheData(object): #------------------------------------------------------------------------------ -class ApplicationCache(object): +class BaseCache(object): """ - Caches the bus names of all applications. + Base object for the Desktop, Accessible and Application caches. - Makes calls and recieves updates from the registry - daemon to keep the cache up to date. + Abstracts common initialization. """ - _UPDATE_SIGNAL = 'updateApplications' - _REGISTRY_PATH = '/org/freedesktop/atspi/registry' - def __init__(self, connection, busName): + def __init__(self, connection, bus_name): """ - Create a cache for application caches. - BusName -> ApplicationCache + Creates a cache. + + connection - DBus connection. + busName - Name of DBus connection where cache interface resides. """ self._connection = connection - self._busName = busName + self._bus_name = bus_name - registryObject = connection.get_object(busName, self._REGISTRY_PATH) - registryInterface = dbus.Interface(registryObject, ATSPI_REGISTRY) + obj = connection.get_object(bus_name, self._PATH) + itf = dbus.Interface(obj, self._INTERFACE) - self._applications = {} + self._objects = {} - self._updateApplications(registryInterface.getApplications()) + getMethod = itf.get_dbus_method(self._GET_METHOD) + self._updateObjects(getMethod) - #Connect to update signal - self._signalMatch = self.registryInterface.connect_to_signal(self._UPDATE_SIGNAL, - self._updateHandler) + self._signalMatch = itf.connect_to_signal(self._UPDATE_SIGNAL, self._updateHandler) - def _updateApplications(self, names): - """ - Updates the application cache from an - array of dbus bus names. - """ - for name in names: - if name not in self._applications: - self._applications[name] = AccessibleCache(self._connection, - self._busName, - self._treePath) + def _updateHandler(self, updates): + update, remove = updates + self._removeObjects(update) + self._updateObjects(remove) - def _removeApplications(self, names): - """ - Removes application caches given by names. + def _updateObjects(self, objects): + for data in objects: + #First element is the object path. + path = data[0] + if path in self._objects: + cachedata = self._objects[path] + cachedata.update(data) + else: + self._objects[path] = _CacheData(data) + + def _removeObjects(self, paths): + for path in paths: + del(self._objects[path]) + + + def getAccessible(self, path, interface, dbus_object=None): """ - for name in names: - del(self._applications[name]) + Gets a client side proxy for the accessible object found + at the path. - def _updateHandler(self, updates): - update, remove = updates - self._removeApplications(update) - self._updateApplications(remove) + path - The D-Bus path of the remote object. + interface - The interface that the accessible object should support. + dbus_object=None - The D-Bus proxy object backing this interface. + """ + if path in self._objects: + if not dbus_object: + dbus_object = self._connection.get_object(self._bus_name, path, introspect=False) + return interfaceFactory(proxy, self, path, interface) + else: + raise AccessibleObjectNoLongerExists, "D-Bus reference not found in cache" #------------------------------------------------------------------------------ -class AccessibleCache(object): +class AccessibleCache(BaseCache): """ - Caches data for a collection of accessible object proxies. + There is one accessible cache per application. + For each application the accessible cache stores + data on every accessible object within the app. - Makes calls and recieves updates from applications - to update the cache of accessible object data. + It also acts as the factory for creating client + side proxies for these accessible objects. """ + _PATH = '/org/freedesktop/atspi/tree' + _INTERFACE = 'org.freedesktop.atspi.Tree' + _GET_METHOD = 'getTree' _UPDATE_SIGNAL = 'updateTree' - _TREE_PATH = '/org/freedesktop/atspi/tree' + def __init__(self, connection, bus_name): + BaseCache.__init__(self, connection, bus_name) - def __init__(self, connection, busName): - """ - Creates a cache for accessible object data. + obj = connection.get_object(_self.bus_name, self._PATH) + itf = dbus.Interface(obj, self._INTERFACE) - All accessible object proxies are created and accessed through this cache. + self._root = itf.getRoot() - connection - DBus connection. - busName - DBus bus name where accessible tree resides. + def getRootAccessible(self): """ - self._connection = connection - self._busName = busName + Gets the accessible object at the root of the tree. + """ + return self.getAccessible(self._root) - treeObject = connection.get_object(busName, self._TREE_PATH) - treeInterface = dbus.Interface(treeObject, ATSPI_TREE) +#------------------------------------------------------------------------------ - self._objects = {} +class DesktopCache(BaseCache): + """ + Cache of desktop objects obtained from the registry. - self._root = treeObject.getRoot() - self._updateObjects(treeInterface.getTree()) + The desktop interface on the registry object is the + same as that of the general tree interface on the + applications. - #Connect to update signal - self._signalMatch = treeInterface.connect_to_signal(self._UPDATE_SIGNAL, - self._updateHandler) + The difference is that the children data refers to + bus names of the applications rather than the object + paths of particular accessible objects within an application. + """ - def getRootAccessible(self): - """ - Gets the accessible object at the root of the tree. - """ - return self.getAccessible(self._root) + _PATH = '/org/freedesktop/atspi/registry' + _INTERFACE = 'org.freedesktop.atspi.Registry' + _GET_METHOD = 'getDesktops' + _UPDATE_SIGNAL = 'updateDesktops' + + def __init__(self, connection, bus_name): + self._app_cache = ApplicationCache(connection, bus_name) - def getAccessible(self, path): - """ - Gets a D-Bus proxy object for the given object path. - The object that is returned implements the accessible - interface. + def getApplication(self, name): + try: + self._app_cache[name].getRootAccessible() + except KeyError: + raise AccessibleObjectNoLongerExists("Application no longer exists") - path - The D-Bus path of the remote object. - """ - if path in self._objects: - proxy = self._connection.get_object(self._busName, path, introspect=False) - return interfaceFactory(proxy, self, self._busName, path, ATSPI_ACCESSIBLE) - else: - raise AccessibleObjectNoLongerExists, "D-Bus reference not found in cache" +#------------------------------------------------------------------------------ - def _updateObjects(self, objects): - """ - Updates the object cache from an - array of accessible object cache data. - """ - for data in objects: - #First element is the object path. - path = data[0] - if path in self._objects: - cachedata = self._objects[path] - cachedata.update(data) - else: - self._objects[path] = _CacheData(data) +class ApplicationCache(object): + """ + Holds a mapping of bus names of each accessible application + to the applications accessible cache. - def _removeObjects(self, paths): - """ - Removes the object data from the cache. - """ - for path in paths: - del(self._objects[path]) + Makes calls and recieves updates from the registry + daemon to keep the cache up to date. + """ - def _updateHandler(self, updates): - update, remove = updates - self._removeObjects(update) - self._updateObjects(remove) + _PATH = '/org/freedesktop/atspi/registry' + _INTERFACE = 'org.freedesktop.atspi.Registry' + _GET_METHOD = 'getApplications' + _UPDATE_SIGNAL = 'updateApplications' + + def _updateApplications(self, names): + for name in names: + if name not in self._applications: + self._applications[name] = AccessibleCache(self._connection, + self._busName, + self._treePath) + + def _removeApplications(self, names): + for name in names: + del(self._applications[name]) #END--------------------------------------------------------------------------- diff --git a/pyatspi/constants.py b/pyatspi/constants.py index 430bcab..ccef0fb 100644 --- a/pyatspi/constants.py +++ b/pyatspi/constants.py @@ -39,6 +39,12 @@ MOUSE_B3D = 'b3d' MOUSE_ABS = 'abs' MOUSE_REL = 'rel' +# events that clear cached properties +CACHE_EVENTS = ['object:property-change:accessible-name', + 'object:property-change:accessible-description', + 'object:property-change:accessible-role', + 'object:property-change:accessible-parent'] + # Dictionary used to correct the bug of not being able to register for all the # subevents given only an AT-SPI event class (i.e. first part of the event # name) keys are event names having subevents and values are the subevents @@ -132,3 +138,21 @@ EVENT_TREE = { 'focus' : ['focus:'] } + +import other + +# Build a dictionary mapping state values to names based on the prefix of the +# enum constants. +STATE_VALUE_TO_NAME = dict(((value, name[6:].lower().replace('_', ' ')) + for name, value + in vars(other).items() + if name.startswith('STATE_'))) + +# Build a dictionary mapping relation values to names based on the prefix of +# the enum constants. +RELATION_VALUE_TO_NAME = dict(((value, name[9:].lower().replace('_', ' ')) + for name, value + in vars(other).items() + if name.startswith('RELATION_'))) + +del other diff --git a/pyatspi/desktop.py b/pyatspi/desktop.py new file mode 100644 index 0000000..df26d7f --- /dev/null +++ b/pyatspi/desktop.py @@ -0,0 +1,207 @@ +#Copyright (C) 2008 Codethink Ltd + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License version 2 as published by the Free Software Foundation. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +#You should have received a copy of the GNU Lesser General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +from base import BaseProxy + +from accessible import Accessible + +class Desktop(Accessible): + """ + The desktop class implements the + accessible interface, but uses a different + method to access its chilren and to obtain cached + data. + + This is because application caches are separate + and the children of the desktop are applications. + The child access must get the root accessible + of the application cache that is accessed. + + The data is accessed from the desktop cache. + """ + + @property + def _data(self): + try: + data = self._cache._objects[self._path] + except KeyError, ReferenceError: + raise AccessibleObjectNoLongerExists, 'Cache data cannot be found for path %s' % (self._path,) + return data + + def getApplication(self, *args, **kwargs): + """ + Get the containing Application for this object. + @return the Application instance to which this object belongs. + """ + func = self.get_dbus_method("getApplication") + return func(*args, **kwargs) + + def getAttributes(self, *args, **kwargs): + """ + Get a list of properties applied to this object as a whole, as + an AttributeSet consisting of name-value pairs. As such these + attributes may be considered weakly-typed properties or annotations, + as distinct from the strongly-typed interface instance data declared + using the IDL "attribute" keyword. + Not all objects have explicit "name-value pair" AttributeSet + properties. + Attribute names and values may have any UTF-8 string value, however + where possible, in order to facilitate consistent use and exposure + of "attribute" properties by applications and AT clients, attribute + names and values should chosen from a publicly-specified namespace + where appropriate. + Where possible, the names and values in the name-value pairs + should be chosen from well-established attribute namespaces using + standard semantics. For example, attributes of Accessible objects + corresponding to XHTML content elements should correspond to + attribute names and values specified in the w3c XHTML specification, + at http://www.w3.org/TR/xhtml2, where such values are not already + exposed via a more strongly-typed aspect of the AT-SPI API. Metadata + names and values should be chosen from the 'Dublin Core' Metadata + namespace using Dublin Core semantics: http://dublincore.org/dcregistry/ + Similarly, relevant structural metadata should be exposed using + attribute names and values chosen from the CSS2 and WICD specification: + http://www.w3.org/TR/1998/REC-CSS2-19980512 WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). + @return : an AttributeSet encapsulating any "attribute values" + currently defined for the object. + """ + func = self.get_dbus_method("getAttributes") + return func(*args, **kwargs) + + def getChildAtIndex(self, *args, **kwargs): + """ + Get the accessible child of this object at index. + @param : index + an in parameter indicating which child is requested (zero-indexed). + @return : the 'nth' Accessible child of this object. + """ + func = self.get_dbus_method("getChildAtIndex") + return func(*args, **kwargs) + + def getIndexInParent(self, *args, **kwargs): + """ + Get the index of this object in its parent's child list. + @return : a long integer indicating this object's index in the + parent's list. + """ + func = self.get_dbus_method("getIndexInParent") + return func(*args, **kwargs) + + def getLocalizedRoleName(self, *args, **kwargs): + """ + Get a string indicating the type of UI role played by this object, + translated to the current locale. + @return : a UTF-8 string indicating the type of UI role played + by this object. + """ + func = self.get_dbus_method("getLocalizedRoleName") + return func(*args, **kwargs) + + def getRelationSet(self, *args, **kwargs): + """ + Get a set defining this object's relationship to other accessible + objects. + @return : a RelationSet defining this object's relationships. + """ + func = self.get_dbus_method("getRelationSet") + return func(*args, **kwargs) + + def getRole(self, *args, **kwargs): + """ + Get the Role indicating the type of UI role played by this object. + @return : a Role indicating the type of UI role played by this + object. + """ + func = self.get_dbus_method("getRole") + return func(*args, **kwargs) + + def getRoleName(self, *args, **kwargs): + """ + Get a string indicating the type of UI role played by this object. + @return : a UTF-8 string indicating the type of UI role played + by this object. + """ + func = self.get_dbus_method("getRoleName") + return func(*args, **kwargs) + + def getState(self, *args, **kwargs): + """ + Get the current state of the object as a StateSet. + @return : a StateSet encapsulating the currently true states + of the object. + """ + func = self.get_dbus_method("getState") + return func(*args, **kwargs) + + def isEqual(self, *args, **kwargs): + """ + Determine whether an Accessible refers to the same object as + another. This method should be used rather than brute-force comparison + of object references (i.e. "by-value" comparison), as two object + references may have different apparent values yet refer to the + same object. + @param : obj + an Accessible object reference to compare to + @return : a boolean indicating whether the two object references + point to the same object. + """ + func = self.get_dbus_method("isEqual") + return func(*args, **kwargs) + + def unimplemented(self, *args, **kwargs): + """ + /cond future expansion + """ + func = self.get_dbus_method("unimplemented") + return func(*args, **kwargs) + + def get_childCount(self): + self._pgetter(self._dbus_interface, "childCount") + def set_childCount(self, value): + self._psetter(self._dbus_interface, "childCount", value) + _childCountDoc = \ + """ + childCount: the number of children contained by this object. + """ + childCount = property(fget=get_childCount, fset=set_childCount, doc=_childCountDoc) + + def get_description(self): + self._pgetter(self._dbus_interface, "description") + def set_description(self, value): + self._psetter(self._dbus_interface, "description", value) + _descriptionDoc = \ + """ + a string describing the object in more detail than name. + """ + description = property(fget=get_description, fset=set_description, doc=_descriptionDoc) + + def get_name(self): + self._pgetter(self._dbus_interface, "name") + def set_name(self, value): + self._psetter(self._dbus_interface, "name", value) + _nameDoc = \ + """ + a (short) string representing the object's name. + """ + name = property(fget=get_name, fset=set_name, doc=_nameDoc) + + def get_parent(self): + self._pgetter(self._dbus_interface, "parent") + def set_parent(self, value): + self._psetter(self._dbus_interface, "parent", value) + _parentDoc = \ + """ + an Accessible object which is this object's containing object. + """ + parent = property(fget=get_parent, fset=set_parent, doc=_parentDoc) diff --git a/pyatspi/event.py b/pyatspi/event.py new file mode 100644 index 0000000..fc6862f --- /dev/null +++ b/pyatspi/event.py @@ -0,0 +1,229 @@ +#Copyright (C) 2008 Codethink Ltd +#copyright: Copyright (c) 2005, 2007 IBM Corporation + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License version 2 as published by the Free Software Foundation. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +#You should have received a copy of the GNU Lesser General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#Portions of this code originally licensed and copyright (c) 2005, 2007 +#IBM Corporation under the BSD license, available at +#U{http://www.opensource.org/licenses/bsd-license.php} + +#authors: Peter Parente, Mark Doffman + +import constants + +class DeviceEvent(object): + """ + Wraps an AT-SPI device event with a more Pythonic interface. Primarily adds + a consume attribute which can be used to cease propagation of a device event. + + @ivar consume: Should this event be consumed and not allowed to pass on to + observers further down the dispatch chain in this process or possibly + system wide? + @type consume: boolean + @ivar type: Kind of event, KEY_PRESSED_EVENT or KEY_RELEASED_EVENT + @type type: Accessibility.EventType + @ivar id: Serial identifier for this key event + @type id: integer + @ivar hw_code: Hardware scan code for the key + @type hw_code: integer + @ivar modifiers: Modifiers held at the time of the key event + @type modifiers: integer + @ivar timestamp: Time at which the event occurred relative to some platform + dependent starting point (e.g. XWindows start time) + @type timestamp: integer + @ivar event_string: String describing the key pressed (e.g. keysym) + @type event_string: string + @ivar is_text: Is the event representative of text to be inserted (True), or + of a control key (False)? + @type is_text: boolean + """ + def __init__(self, event): + """ + Attaches event data to this object. + + @param event: Event object + @type event: Accessibility.DeviceEvent + """ + self.consume = False + self.type = event.type + self.id = event.id + self.hw_code = event.hw_code + self.modifiers = event.modifiers + self.timestamp = event.timestamp + self.event_string = event.event_string + self.is_text = event.is_text + + def __str__(self): + """ + Builds a human readable representation of the event. + + @return: Event description + @rtype: string + """ + if self.type == constants.KEY_PRESSED_EVENT: + kind = 'pressed' + elif self.type == constants.KEY_RELEASED_EVENT: + kind = 'released' + return """\ +%s +\thw_code: %d +\tevent_string: %s +\tmodifiers: %d +\tid: %d +\ttimestamp: %d +\tis_text: %s""" % (kind, self.hw_code, self.event_string, self.modifiers, + self.id, self.timestamp, self.is_text) + +class Event(object): + """ + Wraps an AT-SPI event with a more Pythonic interface managing exceptions, + the differences in any_data across versions, and the reference counting of + accessibles provided with the event. + + @note: All unmarked attributes of this class should be considered public + readable and writable as the class is acting as a record object. + + @ivar consume: Should this event be consumed and not allowed to pass on to + observers further down the dispatch chain in this process? + @type consume: boolean + @ivar type: The type of the AT-SPI event + @type type: L{EventType} + @ivar detail1: First AT-SPI event parameter + @type detail1: integer + @ivar detail2: Second AT-SPI event parameter + @type detail2: integer + @ivar any_data: Extra AT-SPI data payload + @type any_data: object + @ivar host_application: Application owning the event source + @type host_application: Accessibility.Application + @ivar source_name: Name of the event source at the time of event dispatch + @type source_name: string + @ivar source_role: Role of the event source at the time of event dispatch + @type source_role: Accessibility.Role + @ivar source: Source of the event + @type source: Accessibility.Accessible + """ + def __init__(self, event): + """ + Extracts information from the provided event. If the event is a "normal" + event, pulls the detail1, detail2, any_data, and source values out of the + given object and stores it in this object. If the event is a device event, + key ID is stored in detail1, scan code is stored in detail2, key name, + key modifiers (e.g. ALT, CTRL, etc.), is text flag, and timestamp are + stored as a 4-tuple in any_data, and source is None (since key events are + global). + + @param event: Event from an AT-SPI callback + @type event: Accessibility.Event or Accessibility.DeviceEvent + """ + # always start out assuming no consume + self.consume = False + self.type = EventType(event.type) + self.detail1 = event.detail1 + self.detail2 = event.detail2 + # store the event source and increase the reference count since event + # sources are borrowed references; the AccessibleMixin automatically + # decrements it later + try: + event.source.ref() + except AttributeError: + pass + self.source = event.source + + # process any_data in a at-spi version independent manner + details = event.any_data.value() + try: + # see if we have a "new" any_data object which is an EventDetails struct + self.any_data = details.any_data.value() + except Exception: + # any kind of error means we have an "old" any_data object and None of + # the extra data so set them to None + self.any_data = details + self.host_application = None + self.source_name = None + self.source_role = None + else: + # the rest of the data should be here, so retrieve it + self.host_application = details.host_application + self.source_name = details.source_name + self.source_role = details.source_role + try: + # if we received an accessible, be sure to increment the ref count + self.any_data.ref() + except AttributeError: + pass + try: + # if we received a host application, be sure to increment the ref count + self.host_application.ref() + except AttributeError: + pass + + def __str__(self): + """ + Builds a human readable representation of the event including event type, + parameters, and source info. + + @return: Event description + @rtype: string + """ + return '%s(%s, %s, %s)\n\tsource: %s\n\thost_application: %s' % \ + (self.type, self.detail1, self.detail2, self.any_data, + self.source, self.host_application) + +class EventType(str): + """ + Wraps the AT-SPI event type string so its components can be accessed + individually as klass (can't use the keyword class), major, minor, and detail + (klass:major:minor:detail). + + @note: All attributes of an instance of this class should be considered + public readable as it is acting a a struct. + @ivar klass: Most general event type identifier (object, window, mouse, etc.) + @type klass: string + @ivar major: Second level event type description + @type major: string + @ivar minor: Third level event type description + @type minor: string + @ivar detail: Lowest level event type description + @type detail: string + @ivar name: Full, unparsed event name as received from AT-SPI + @type name: string + @cvar format: Names of the event string components + @type format: 4-tuple of string + """ + format = ('klass', 'major', 'minor', 'detail') + + def __init__(self, name): + """ + Parses the full AT-SPI event name into its components + (klass:major:minor:detail). If the provided event name is an integer + instead of a string, then the event is really a device event. + + @param name: Full AT-SPI event name + @type name: string + @raise AttributeError: When the given event name is not a valid string + """ + # get rid of any leading and trailing ':' separators + self.value = name.strip(':') + self.name = self.value # Backward compatability + self.klass = None + self.major = None + self.minor = None + self.detail = None + + # split type according to delimiters + split = self.value.split(':', 3) + # loop over all the components + for i in xrange(len(split)): + # store values of attributes in this object + setattr(self, self.format[i], split[i]) diff --git a/pyatspi/other.py b/pyatspi/other.py index 46d0c90..61a82e6 100644 --- a/pyatspi/other.py +++ b/pyatspi/other.py @@ -13,401 +13,7 @@ #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. from base import * - -BUTTON_PRESSED_EVENT = Accessibility.EventType(2) - -BUTTON_RELEASED_EVENT = Accessibility.EventType(3) - -KEY_PRESS = Accessibility.KeySynthType(0) - -KEY_PRESSED = Accessibility.KeyEventType(0) - -KEY_PRESSED_EVENT = Accessibility.EventType(0) - -KEY_PRESSRELEASE = Accessibility.KeySynthType(2) - -KEY_RELEASE = Accessibility.KeySynthType(1) - -KEY_RELEASED = Accessibility.KeyEventType(1) - -KEY_RELEASED_EVENT = Accessibility.EventType(1) - -KEY_STRING = Accessibility.KeySynthType(4) - -KEY_SYM = Accessibility.KeySynthType(3) - -LAYER_BACKGROUND = Accessibility.ComponentLayer(1) - -LAYER_CANVAS = Accessibility.ComponentLayer(2) - -LAYER_INVALID = Accessibility.ComponentLayer(0) - -LAYER_LAST_DEFINED = Accessibility.ComponentLayer(8) - -LAYER_MDI = Accessibility.ComponentLayer(4) - -LAYER_OVERLAY = Accessibility.ComponentLayer(6) - -LAYER_POPUP = Accessibility.ComponentLayer(5) - -LAYER_WIDGET = Accessibility.ComponentLayer(3) - -LAYER_WINDOW = Accessibility.ComponentLayer(7) - -LOCALE_TYPE_COLLATE = Accessibility.LOCALE_TYPE(1) - -LOCALE_TYPE_CTYPE = Accessibility.LOCALE_TYPE(2) - -LOCALE_TYPE_MESSAGES = Accessibility.LOCALE_TYPE(0) - -LOCALE_TYPE_MONETARY = Accessibility.LOCALE_TYPE(3) - -LOCALE_TYPE_NUMERIC = Accessibility.LOCALE_TYPE(4) - -LOCALE_TYPE_TIME = Accessibility.LOCALE_TYPE(5) - -MODIFIER_ALT = Accessibility.ModifierType(3) - -MODIFIER_CONTROL = Accessibility.ModifierType(2) - -MODIFIER_META = Accessibility.ModifierType(4) - -MODIFIER_META2 = Accessibility.ModifierType(5) - -MODIFIER_META3 = Accessibility.ModifierType(6) - -MODIFIER_NUMLOCK = Accessibility.ModifierType(7) - -MODIFIER_SHIFT = Accessibility.ModifierType(0) - -MODIFIER_SHIFTLOCK = Accessibility.ModifierType(1) - -RELATION_CONTROLLED_BY = Accessibility.RelationType(4) - -RELATION_CONTROLLER_FOR = Accessibility.RelationType(3) - -RELATION_DESCRIBED_BY = Accessibility.RelationType(17) - -RELATION_DESCRIPTION_FOR = Accessibility.RelationType(16) - -RELATION_EMBEDDED_BY = Accessibility.RelationType(13) - -RELATION_EMBEDS = Accessibility.RelationType(12) - -RELATION_EXTENDED = Accessibility.RelationType(8) - -RELATION_FLOWS_FROM = Accessibility.RelationType(10) - -RELATION_FLOWS_TO = Accessibility.RelationType(9) - -RELATION_LABELLED_BY = Accessibility.RelationType(2) - -RELATION_LABEL_FOR = Accessibility.RelationType(1) - -RELATION_LAST_DEFINED = Accessibility.RelationType(18) - -RELATION_MEMBER_OF = Accessibility.RelationType(5) - -RELATION_NODE_CHILD_OF = Accessibility.RelationType(7) - -RELATION_NULL = Accessibility.RelationType(0) - -RELATION_PARENT_WINDOW_OF = Accessibility.RelationType(15) - -RELATION_POPUP_FOR = Accessibility.RelationType(14) - -RELATION_SUBWINDOW_OF = Accessibility.RelationType(11) - -RELATION_TOOLTIP_FOR = Accessibility.RelationType(6) - -ROLE_ACCELERATOR_LABEL = Accessibility.Role(1) - -ROLE_ALERT = Accessibility.Role(2) - -ROLE_ANIMATION = Accessibility.Role(3) - -ROLE_APPLICATION = Accessibility.Role(75) - -ROLE_ARROW = Accessibility.Role(4) - -ROLE_AUTOCOMPLETE = Accessibility.Role(76) - -ROLE_CALENDAR = Accessibility.Role(5) - -ROLE_CANVAS = Accessibility.Role(6) - -ROLE_CAPTION = Accessibility.Role(81) - -ROLE_CHART = Accessibility.Role(80) - -ROLE_CHECK_BOX = Accessibility.Role(7) - -ROLE_CHECK_MENU_ITEM = Accessibility.Role(8) - -ROLE_COLOR_CHOOSER = Accessibility.Role(9) - -ROLE_COLUMN_HEADER = Accessibility.Role(10) - -ROLE_COMBO_BOX = Accessibility.Role(11) - -ROLE_DATE_EDITOR = Accessibility.Role(12) - -ROLE_DESKTOP_FRAME = Accessibility.Role(14) - -ROLE_DESKTOP_ICON = Accessibility.Role(13) - -ROLE_DIAL = Accessibility.Role(15) - -ROLE_DIALOG = Accessibility.Role(16) - -ROLE_DIRECTORY_PANE = Accessibility.Role(17) - -ROLE_DOCUMENT_FRAME = Accessibility.Role(82) - -ROLE_DRAWING_AREA = Accessibility.Role(18) - -ROLE_EDITBAR = Accessibility.Role(77) - -ROLE_EMBEDDED = Accessibility.Role(78) - -ROLE_ENTRY = Accessibility.Role(79) - -ROLE_EXTENDED = Accessibility.Role(70) - -ROLE_FILE_CHOOSER = Accessibility.Role(19) - -ROLE_FILLER = Accessibility.Role(20) - -ROLE_FOCUS_TRAVERSABLE = Accessibility.Role(21) - -ROLE_FONT_CHOOSER = Accessibility.Role(22) - -ROLE_FOOTER = Accessibility.Role(72) - -ROLE_FORM = Accessibility.Role(87) - -ROLE_FRAME = Accessibility.Role(23) - -ROLE_GLASS_PANE = Accessibility.Role(24) - -ROLE_HEADER = Accessibility.Role(71) - -ROLE_HEADING = Accessibility.Role(83) - -ROLE_HTML_CONTAINER = Accessibility.Role(25) - -ROLE_ICON = Accessibility.Role(26) - -ROLE_IMAGE = Accessibility.Role(27) - -ROLE_INPUT_METHOD_WINDOW = Accessibility.Role(89) - -ROLE_INTERNAL_FRAME = Accessibility.Role(28) - -ROLE_INVALID = Accessibility.Role(0) - -ROLE_LABEL = Accessibility.Role(29) - -ROLE_LAST_DEFINED = Accessibility.Role(90) - -ROLE_LAYERED_PANE = Accessibility.Role(30) - -ROLE_LINK = Accessibility.Role(88) - -ROLE_LIST = Accessibility.Role(31) - -ROLE_LIST_ITEM = Accessibility.Role(32) - -ROLE_MENU = Accessibility.Role(33) - -ROLE_MENU_BAR = Accessibility.Role(34) - -ROLE_MENU_ITEM = Accessibility.Role(35) - -ROLE_OPTION_PANE = Accessibility.Role(36) - -ROLE_PAGE = Accessibility.Role(84) - -ROLE_PAGE_TAB = Accessibility.Role(37) - -ROLE_PAGE_TAB_LIST = Accessibility.Role(38) - -ROLE_PANEL = Accessibility.Role(39) - -ROLE_PARAGRAPH = Accessibility.Role(73) - -ROLE_PASSWORD_TEXT = Accessibility.Role(40) - -ROLE_POPUP_MENU = Accessibility.Role(41) - -ROLE_PROGRESS_BAR = Accessibility.Role(42) - -ROLE_PUSH_BUTTON = Accessibility.Role(43) - -ROLE_RADIO_BUTTON = Accessibility.Role(44) - -ROLE_RADIO_MENU_ITEM = Accessibility.Role(45) - -ROLE_REDUNDANT_OBJECT = Accessibility.Role(86) - -ROLE_ROOT_PANE = Accessibility.Role(46) - -ROLE_ROW_HEADER = Accessibility.Role(47) - -ROLE_RULER = Accessibility.Role(74) - -ROLE_SCROLL_BAR = Accessibility.Role(48) - -ROLE_SCROLL_PANE = Accessibility.Role(49) - -ROLE_SECTION = Accessibility.Role(85) - -ROLE_SEPARATOR = Accessibility.Role(50) - -ROLE_SLIDER = Accessibility.Role(51) - -ROLE_SPIN_BUTTON = Accessibility.Role(52) - -ROLE_SPLIT_PANE = Accessibility.Role(53) - -ROLE_STATUS_BAR = Accessibility.Role(54) - -ROLE_TABLE = Accessibility.Role(55) - -ROLE_TABLE_CELL = Accessibility.Role(56) - -ROLE_TABLE_COLUMN_HEADER = Accessibility.Role(57) - -ROLE_TABLE_ROW_HEADER = Accessibility.Role(58) - -ROLE_TEAROFF_MENU_ITEM = Accessibility.Role(59) - -ROLE_TERMINAL = Accessibility.Role(60) - -ROLE_TEXT = Accessibility.Role(61) - -ROLE_TOGGLE_BUTTON = Accessibility.Role(62) - -ROLE_TOOL_BAR = Accessibility.Role(63) - -ROLE_TOOL_TIP = Accessibility.Role(64) - -ROLE_TREE = Accessibility.Role(65) - -ROLE_TREE_TABLE = Accessibility.Role(66) - -ROLE_UNKNOWN = Accessibility.Role(67) - -ROLE_VIEWPORT = Accessibility.Role(68) - -ROLE_WINDOW = Accessibility.Role(69) - -STATE_ACTIVE = Accessibility.StateType(1) - -STATE_ANIMATED = Accessibility.StateType(35) - -STATE_ARMED = Accessibility.StateType(2) - -STATE_BUSY = Accessibility.StateType(3) - -STATE_CHECKED = Accessibility.StateType(4) - -STATE_COLLAPSED = Accessibility.StateType(5) - -STATE_DEFUNCT = Accessibility.StateType(6) - -STATE_EDITABLE = Accessibility.StateType(7) - -STATE_ENABLED = Accessibility.StateType(8) - -STATE_EXPANDABLE = Accessibility.StateType(9) - -STATE_EXPANDED = Accessibility.StateType(10) - -STATE_FOCUSABLE = Accessibility.StateType(11) - -STATE_FOCUSED = Accessibility.StateType(12) - -STATE_HAS_TOOLTIP = Accessibility.StateType(13) - -STATE_HORIZONTAL = Accessibility.StateType(14) - -STATE_ICONIFIED = Accessibility.StateType(15) - -STATE_INDETERMINATE = Accessibility.StateType(32) - -STATE_INVALID = Accessibility.StateType(0) - -STATE_INVALID_ENTRY = Accessibility.StateType(36) - -STATE_IS_DEFAULT = Accessibility.StateType(39) - -STATE_LAST_DEFINED = Accessibility.StateType(41) - -STATE_MANAGES_DESCENDANTS = Accessibility.StateType(31) - -STATE_MODAL = Accessibility.StateType(16) - -STATE_MULTISELECTABLE = Accessibility.StateType(18) - -STATE_MULTI_LINE = Accessibility.StateType(17) - -STATE_OPAQUE = Accessibility.StateType(19) - -STATE_PRESSED = Accessibility.StateType(20) - -STATE_REQUIRED = Accessibility.StateType(33) - -STATE_RESIZABLE = Accessibility.StateType(21) - -STATE_SELECTABLE = Accessibility.StateType(22) - -STATE_SELECTABLE_TEXT = Accessibility.StateType(38) - -STATE_SELECTED = Accessibility.StateType(23) - -STATE_SENSITIVE = Accessibility.StateType(24) - -STATE_SHOWING = Accessibility.StateType(25) - -STATE_SINGLE_LINE = Accessibility.StateType(26) - -STATE_STALE = Accessibility.StateType(27) - -STATE_SUPPORTS_AUTOCOMPLETION = Accessibility.StateType(37) - -STATE_TRANSIENT = Accessibility.StateType(28) - -STATE_TRUNCATED = Accessibility.StateType(34) - -STATE_VERTICAL = Accessibility.StateType(29) - -STATE_VISIBLE = Accessibility.StateType(30) - -STATE_VISITED = Accessibility.StateType(40) - -TEXT_BOUNDARY_CHAR = Accessibility.TEXT_BOUNDARY_TYPE(0) - -TEXT_BOUNDARY_LINE_END = Accessibility.TEXT_BOUNDARY_TYPE(6) - -TEXT_BOUNDARY_LINE_START = Accessibility.TEXT_BOUNDARY_TYPE(5) - -TEXT_BOUNDARY_SENTENCE_END = Accessibility.TEXT_BOUNDARY_TYPE(4) - -TEXT_BOUNDARY_SENTENCE_START = Accessibility.TEXT_BOUNDARY_TYPE(3) - -TEXT_BOUNDARY_WORD_END = Accessibility.TEXT_BOUNDARY_TYPE(2) - -TEXT_BOUNDARY_WORD_START = Accessibility.TEXT_BOUNDARY_TYPE(1) - -TEXT_CLIP_BOTH = Accessibility.TEXT_CLIP_TYPE(3) - -TEXT_CLIP_MAX = Accessibility.TEXT_CLIP_TYPE(2) - -TEXT_CLIP_MIN = Accessibility.TEXT_CLIP_TYPE(1) - -TEXT_CLIP_NONE = Accessibility.TEXT_CLIP_TYPE(0) - +from accessible import * class Action(BaseProxy): @@ -618,37 +224,34 @@ class Application(Accessible): class BoundingBox(list): def __new__(cls, x, y, width, height): - list.__new__(cls, (x, y, width, height) + list.__new__(cls, (x, y, width, height)) def __init__(self, x, y, width, height): list.__init__(self, (x, y, width, height)) - x = property(fget=_get_x, fset=_set_x) def _get_x(self): return self[0] def _set_x(self, val): self[0] = val - y = property(fget=_get_y, fset=_set_y) + x = property(fget=_get_x, fset=_set_x) def _get_y(self): return self[1] def _set_y(self, val): self[1] = val - width = property(fget=_get_width, fset=_set_width) + y = property(fget=_get_y, fset=_set_y) def _get_width(self): return self[2] def _set_width(self, val): self[2] = val - height = property(fget=_get_height, fset=_set_height) + width = property(fget=_get_width, fset=_set_width) def _get_height(self): return self[3] def _set_height(self, val): self[3] = val + height = property(fget=_get_height, fset=_set_height) class Collection(BaseProxy): - - - def createMatchRule(self, *args, **kwargs): func = self.get_dbus_method("createMatchRule") return func(*args, **kwargs) @@ -692,19 +295,7 @@ class Collection(BaseProxy): def unImplemented4(self, *args, **kwargs): func = self.get_dbus_method("unImplemented4") return func(*args, **kwargs) - - MATCH_ALL = Accessibility.MatchType(1) - - MATCH_ANY = Accessibility.MatchType(2) - - MATCH_EMPTY = Accessibility.MatchType(4) - - MATCH_INVALID = Accessibility.MatchType(0) - - MATCH_LAST_DEFINED = Accessibility.MatchType(5) - - MATCH_NONE = Accessibility.MatchType(3) - + class MatchType(Enum): _enum_lookup = { 0:'MATCH_INVALID', @@ -715,23 +306,18 @@ class Collection(BaseProxy): 5:'MATCH_LAST_DEFINED', } + MATCH_ALL = MatchType(1) - SORT_ORDER_CANONICAL = Accessibility.SortOrder(1) - - SORT_ORDER_FLOW = Accessibility.SortOrder(2) - - SORT_ORDER_INVALID = Accessibility.SortOrder(0) - - SORT_ORDER_LAST_DEFINED = Accessibility.SortOrder(7) + MATCH_ANY = MatchType(2) - SORT_ORDER_REVERSE_CANONICAL = Accessibility.SortOrder(4) + MATCH_EMPTY = MatchType(4) - SORT_ORDER_REVERSE_FLOW = Accessibility.SortOrder(5) + MATCH_INVALID = MatchType(0) - SORT_ORDER_REVERSE_TAB = Accessibility.SortOrder(6) - - SORT_ORDER_TAB = Accessibility.SortOrder(3) + MATCH_LAST_DEFINED = MatchType(5) + MATCH_NONE = MatchType(3) + class SortOrder(Enum): _enum_lookup = { 0:'SORT_ORDER_INVALID', @@ -744,15 +330,22 @@ class Collection(BaseProxy): 7:'SORT_ORDER_LAST_DEFINED', } + SORT_ORDER_CANONICAL = SortOrder(1) + + SORT_ORDER_FLOW = SortOrder(2) + + SORT_ORDER_INVALID = SortOrder(0) - TREE_INORDER = Accessibility.TreeTraversalType(2) + SORT_ORDER_LAST_DEFINED = SortOrder(7) - TREE_LAST_DEFINED = Accessibility.TreeTraversalType(3) + SORT_ORDER_REVERSE_CANONICAL = SortOrder(4) - TREE_RESTRICT_CHILDREN = Accessibility.TreeTraversalType(0) + SORT_ORDER_REVERSE_FLOW = SortOrder(5) - TREE_RESTRICT_SIBLING = Accessibility.TreeTraversalType(1) + SORT_ORDER_REVERSE_TAB = SortOrder(6) + SORT_ORDER_TAB = SortOrder(3) + class TreeTraversalType(Enum): _enum_lookup = { 0:'TREE_RESTRICT_CHILDREN', @@ -760,29 +353,33 @@ class Collection(BaseProxy): 2:'TREE_INORDER', 3:'TREE_LAST_DEFINED', } - + + TREE_INORDER = TreeTraversalType(2) + + TREE_LAST_DEFINED = TreeTraversalType(3) + + TREE_RESTRICT_CHILDREN = TreeTraversalType(0) + + TREE_RESTRICT_SIBLING = TreeTraversalType(1) class Command(list): def __new__(cls, name, id): - list.__new__(cls, (name, id) + list.__new__(cls, (name, id)) def __init__(self, name, id): list.__init__(self, (name, id)) - name = property(fget=_get_name, fset=_set_name) def _get_name(self): return self[0] def _set_name(self, val): self[0] = val - id = property(fget=_get_id, fset=_set_id) + name = property(fget=_get_name, fset=_set_name) def _get_id(self): return self[1] def _set_id(self, val): self[1] = val - + id = property(fget=_get_id, fset=_set_id) class CommandListener(BaseProxy): - - """ An interface which should be implemented by assistive technologies or other clients of the Selector interface, over which notifications @@ -955,14 +552,11 @@ class ComponentLayer(Enum): class ContentStream(BaseProxy): - - """ An interface by which the requested data from a StreamableContent object may be read by the client. """ - def close(self, *args, **kwargs): """ close the stream and release associated resources. A client should @@ -1015,13 +609,7 @@ class ContentStream(BaseProxy): class NotSupported(Exception): pass - - SEEK_CURRENT = Accessibility.SeekType(1) - - SEEK_END = Accessibility.SeekType(2) - - SEEK_SET = Accessibility.SeekType(0) - + class SeekType(Enum): """ Specifies the meaning of a seek 'offset'. Not all SeekTypes are @@ -1029,93 +617,66 @@ class ContentStream(BaseProxy): some streams may not support seeking from the beginning or other types of 'backwards' seeks. """ - _enum_lookup = { 0:'SEEK_SET', 1:'SEEK_CURRENT', 2:'SEEK_END', } - -class Desktop(Accessible): + SEEK_CURRENT = SeekType(1) - """ - At the moment this is only a marker interface, it acts just like - any other Accessible. In all known implementations, the children - are all instances of Application, but this is not guaranteed - by this interface. - """ + SEEK_END = SeekType(2) + SEEK_SET = SeekType(0) + +class DeviceEvent(list): + def __new__(cls, type, id, hw_code, modifiers, timestamp, event_string, is_text): + list.__new__(cls, (type, id, hw_code, modifiers, timestamp, event_string, is_text)) + def __init__(self, type, id, hw_code, modifiers, timestamp, event_string, is_text): + list.__init__(self, (type, id, hw_code, modifiers, timestamp, event_string, is_text)) - def unImplemented2_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2_") - return func(*args, **kwargs) - - def unImplemented3_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3_") - return func(*args, **kwargs) - - def unImplemented4_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4_") - return func(*args, **kwargs) - - def unImplemented_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_") - return func(*args, **kwargs) - - -class DeviceEvent(list): - def __new__(cls, type, id, hw_code, modifiers, timestamp, event_string, is_text): - list.__new__(cls, (type, id, hw_code, modifiers, timestamp, event_string, is_text) - def __init__(self, type, id, hw_code, modifiers, timestamp, event_string, is_text): - list.__init__(self, (type, id, hw_code, modifiers, timestamp, event_string, is_text)) - - type = property(fget=_get_type, fset=_set_type) def _get_type(self): return self[0] def _set_type(self, val): self[0] = val - id = property(fget=_get_id, fset=_set_id) + type = property(fget=_get_type, fset=_set_type) def _get_id(self): return self[1] def _set_id(self, val): self[1] = val - hw_code = property(fget=_get_hw_code, fset=_set_hw_code) + id = property(fget=_get_id, fset=_set_id) def _get_hw_code(self): return self[2] def _set_hw_code(self, val): self[2] = val - modifiers = property(fget=_get_modifiers, fset=_set_modifiers) + hw_code = property(fget=_get_hw_code, fset=_set_hw_code) def _get_modifiers(self): return self[3] def _set_modifiers(self, val): self[3] = val - timestamp = property(fget=_get_timestamp, fset=_set_timestamp) + modifiers = property(fget=_get_modifiers, fset=_set_modifiers) def _get_timestamp(self): return self[4] def _set_timestamp(self, val): self[4] = val - event_string = property(fget=_get_event_string, fset=_set_event_string) + timestamp = property(fget=_get_timestamp, fset=_set_timestamp) def _get_event_string(self): return self[5] def _set_event_string(self, val): self[5] = val - is_text = property(fget=_get_is_text, fset=_set_is_text) + event_string = property(fget=_get_event_string, fset=_set_event_string) def _get_is_text(self): return self[6] def _set_is_text(self, val): self[6] = val - + is_text = property(fget=_get_is_text, fset=_set_is_text) class DeviceEventController(BaseProxy): - - """ The interface via which clients request notification of device events, and through which device events may be simulated. """ - - + def deregisterDeviceEventListener(self, *args, **kwargs): """ De-register a previously registered keyboard eventlistener. @@ -1257,8 +818,6 @@ class DeviceEventController(BaseProxy): class DeviceEventListener(BaseProxy): - - """ This interface should be implemented by AT-SPI clients who wish to make use of the DeviceEventController to receive device event @@ -1266,7 +825,6 @@ class DeviceEventListener(BaseProxy): button/motion events. """ - def notifyEvent(self, *args, **kwargs): """ Notify an interested DeviceEventListener that a DeviceEvent has @@ -1304,8 +862,6 @@ class DeviceEventListener(BaseProxy): class Document(BaseProxy): - - """ Primarily a 'tagging' interface which indicates the start of document content in the Accessibility hierarchy. Accessible objects @@ -1316,7 +872,6 @@ class Document(BaseProxy): as well. """ - def getAttributeValue(self, *args, **kwargs): """ Gets the value of a single attribute, if specified for the document @@ -1368,329 +923,441 @@ class Document(BaseProxy): func = self.get_dbus_method("unImplemented_") return func(*args, **kwargs) - -class EditableText(Text): - - +class Text(BaseProxy): """ - Derived from interface Text, EditableText provides methods for - modifying textual content of components which support editing. - EditableText also interacts with the system clipboard via copyText, - cutText, and pasteText. + The text interface should be implemented by objects which place + textual information onscreen as character strings or glyphs. + The text interface allows access to textual content, including + display attributes and semantic hints associated with runs of + text, and access to bounding box information for glyphs and substrings. + It also allows portions of textual content to be selected, if + the object's StateSet includes STATE_SELECTABLE_TEXT. + In some cases a Text object may have, as its content, an empty + string. In particular this can occur in the case of Hypertext + objects which do not display explicitly textual information onscreen, + as Hypertext is derived from the Text interface. + Typographic and semantic attributes of onscreen textual content, + for instance typeface, weight, language, and such qualities as + 'emphasis' or 'blockquote', are represented as text attributes. + Contiguous sequences of characters over which these attributes + are unchanged are referred to as "attribute runs", and are available + via Text::getAttributeRun. Where possible, implementing clients + will report textual attributes which are the same over the entire + text object, for instance those inherited from a default or document-scope + style, via getDefaultAttributes instead of reporting them explicitly + for each character. Therefore, for any span of text, the attributes + in effect are the union of the set returned by Text::getDefaultAttributes, + and the set returned at a particular character offset via Text::getAttributeRun. """ - def copyText(self, *args, **kwargs): + def addSelection(self, *args, **kwargs): """ - Copy a range of text into the system clipboard. - @param : startPos - the character offset of the first character in the range of text - being copied. - @param : endPos - the offset of the first character past the end of the range of - text being copied. + The result of calling addSelection on objects which already have + one selection present, and which do not include STATE_MULTISELECTABLE, + is undefined, other than the return value. + @return True of the selection was successfully added, False otherwise. + Selection may fail if the object does not support selection of + text (see STATE_SELECTABLE_TEXT), if the object does not support + multiple selections and a selection is already defined, or for + other reasons (for instance if the user does not have permission + to copy the text into the relevant selection buffer). """ - func = self.get_dbus_method("copyText") + func = self.get_dbus_method("addSelection") return func(*args, **kwargs) - def cutText(self, *args, **kwargs): + def getAttributeRun(self, *args, **kwargs): """ - Excise a range of text from a Text object, copying it into the - system clipboard. - @param : startPos - the character offset of the first character in the range of text - being cut. - @param : endPos - the offset of the first character past the end of the range of - text being cut. - @return True if the text was successfully cut, False otherwise. + Query a particular text object for the text attributes defined + at a given offset, obtaining the start and end of the "attribute + run" over which these attributes are currently invariant. Text + attributes are those presentational, typographic, or semantic + attributes or qualitites which apply to a range of text specifyable + by starting and ending offsets. Attributes relevant to localization + should be provided in accordance with the w3c "Internationalization + and Localization Markup Requirements", http://www.w3.org/TR/2005/WD-itsreq-20051122/ + Other text attributes should choose their names and value semantics + in accordance with relevant standards such as CSS level 2 (http://www.w3.org/TR/1998/REC-CSS2-19980512), + XHTML 1.0 (http://www.w3.org/TR/2002/REC-xhtml1-20020801), and + WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). Those attributes + from the aforementioned specifications and recommendations which + do not concern typographic, presentational, or semantic aspects + of text should be exposed via the more general Accessible::getAttributes() + API (if at all). + For example, CSS attributes which should be exposed on text (either + as default attributes, or as explicitly-set attributes when non-default + values are specified in the content view) include the Font attributes + (i.e. "css2:font-weight", "css2:font-style"), the "css2:color" + and "css2:background-color" attributes, and "css2:text-decoration" + attribute. + If includeDefaults is TRUE, then this AttributeSet should include + the default attributes as well as those which are explicitly + assigned to the attribute run in question. startOffset and endOffset + will be back-filled to indicate the start and end of the attribute + run which contains 'offset' - an attribute run is a contiguous + section of text whose attributes are homogeneous. + @param : offset + the offset of the character whose attributes will be reported. + @param : startOffset + backfilled with the starting offset of the character range over + which all text attributes match those of offset, i.e. the start + of the homogeneous attribute run including offset. + @param : endOffset + backfilled with the offset of the first character past the character + range over which all text attributes match those of offset, i.e. + the character immediately after the homogeneous attribute run + including offset. + @param : includeDefaults + if False, the call should only return those attributes which + are explicitly set on the current attribute run, omitting any + attributes which are inherited from the default values. See also + Text::getDefaultAttributes. + @return the AttributeSet defined at offset, optionally including + the 'default' attributes. """ - func = self.get_dbus_method("cutText") + func = self.get_dbus_method("getAttributeRun") return func(*args, **kwargs) - def deleteText(self, *args, **kwargs): + def getAttributeValue(self, *args, **kwargs): """ - Excise a range of text from a Text object without copying it - into the system clipboard. - @param : startPos - the character offset of the first character in the range of text - being deleted. - @param : endPos - the offset of the first character past the end of the range of - text being deleted. - @return True if the text was successfully deleted, False otherwise. + Get the string value of a named attribute at a given offset, + if defined. + @param : offset + the offset of the character for which the attribute run is to + be obtained. + @param : attributeName + the name of the attribute for which the value is to be returned, + if defined. + @param : startOffset + back-filled with the offset of the first character in the attribute + run containing the character at offset. + @param : endOffset + back-filled with the offset of the first character past the end + of the attribute run containing the character at offset. + @param : defined + back-filled with True if the attributeName has a defined value + at offset, False otherwise. + @return the value of attribute (name-value pair) corresponding + to "name", if defined. """ - func = self.get_dbus_method("deleteText") + func = self.get_dbus_method("getAttributeValue") return func(*args, **kwargs) - def insertText(self, *args, **kwargs): + def getAttributes(self, *args, **kwargs): """ - Insert new text contents into an existing text object at a given - location, while retaining the old contents. - @param : position - the character offset into the Text implementor's content at which - the new content will be inserted. - @param : text - a UTF-8 string of which length characters will be inserted into - the text object's text buffer. - @param : length - the number of characters of text to insert. If the character - count of text is less than or equal to length, the entire contents - of text will be inserted. - @return True if the text content was successfully inserted, False - otherwise. + getAttributes is deprecated in favor of getAttributeRun. + @return the attributes at offset, as a semicolon-delimited set + of colon-delimited name-value pairs. """ - func = self.get_dbus_method("insertText") + func = self.get_dbus_method("getAttributes") return func(*args, **kwargs) - def pasteText(self, *args, **kwargs): + def getBoundedRanges(self, *args, **kwargs): """ - Copy the text contents of the system clipboard, if any, into - a Text object, inserting it at a particular character offset. - @param : position - the character offset before which the text will be inserted. - @return True if the text was successfully pasted into the Text - object, False otherwise. + Return the text content within a bounding box, as a list of Range + structures. Depending on the TEXT_CLIP_TYPE parameters, glyphs + which are clipped by the bounding box (i.e. which lie partially + inside and partially outside it) may or may not be included in + the ranges returned. + @param : x + the minimum x ( i.e. leftmost) coordinate of the bounding box. + @param : y + the minimum y coordinate of the bounding box. + @param : width + the horizontal size of the bounding box. The rightmost bound + of the bounding box is (x + width); + @param : height + the vertical size of the bounding box. The maximum y value of + the bounding box is (y + height); + @param : coordType + If 0, the above coordinates are interpreted as pixels relative + to corner of the screen; if 1, the coordinates are interpreted + as pixels relative to the corner of the containing toplevel window. + @param : xClipType + determines whether text which intersects the bounding box in + the x direction is included. + @param : yClipType + determines whether text which intersects the bounding box in + the y direction is included. """ - func = self.get_dbus_method("pasteText") + func = self.get_dbus_method("getBoundedRanges") return func(*args, **kwargs) - def setAttributes(self, *args, **kwargs): + def getCharacterAtOffset(self, *args, **kwargs): """ - Apply a particular set of attributes to a range of text. - @return True if the text attributes were successfully modified, - False otherwise. + @return an unsigned long integer whose value corresponds to the + UCS-4 representation of the character at the specified text offset, + or 0 if offset is out of range. """ - func = self.get_dbus_method("setAttributes") + func = self.get_dbus_method("getCharacterAtOffset") return func(*args, **kwargs) - def setTextContents(self, *args, **kwargs): + def getCharacterExtents(self, *args, **kwargs): """ - Replace the text contents with a new string, discarding the old - contents. - @param : newContents - a UTF-8 string with which the text object's contents will be - replaced. - @return True if the text content was successfully changed, False - otherwise. + Obtain a the bounding box, as x, y, width, and height, of the + character or glyph at a particular character offset in this object's + text content. The coordinate system in which the results are + reported is specified by coordType. If an onscreen glyph corresponds + to multiple character offsets, for instance if the glyph is a + ligature, the bounding box reported will include the entire glyph + and therefore may apply to more than one character offset. + @param : offset + the character offset of the character or glyph being queried. + @param : x + the minimum horizontal coordinate of the bounding box of the + glyph representing the character at offset. + @param : y + the minimum vertical coordinate of the bounding box of the glyph + representing the character at offset. + @param : width + the horizontal extent of the bounding box of the glyph representing + the character at offset. + @param : height + the vertical extent of the bounding box of the glyph representing + the character at offset. + @param : coordType + If 0, the results will be reported in screen coordinates, i.e. + in pixels relative to the upper-left corner of the screen, with + the x axis pointing right and the y axis pointing down. If 1, + the results will be reported relative to the containing toplevel + window, with the x axis pointing right and the y axis pointing + down. """ - func = self.get_dbus_method("setTextContents") - return func(*args, **kwargs) - - def unImplemented10(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented10") + func = self.get_dbus_method("getCharacterExtents") return func(*args, **kwargs) - def unImplemented11(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented11") + def getDefaultAttributeSet(self, *args, **kwargs): + """ + Return an AttributeSet containing the text attributes which apply + to all text in the object by virtue of the default settings of + the document, view, or user agent; e.g. those attributes which + are implied rather than explicitly applied to the text object. + For instance, an object whose entire text content has been explicitly + marked as 'bold' will report the 'bold' attribute via getAttributeRun(), + whereas an object whose text weight is inspecified may report + the default or implied text weight in the default AttributeSet. + """ + func = self.get_dbus_method("getDefaultAttributeSet") return func(*args, **kwargs) - def unImplemented12(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented12") + def getDefaultAttributes(self, *args, **kwargs): + """ + Deprecated in favor of getDefaultAttributeSet. + @return the attributes which apply to the entire text content, + but which were not explicitly specified by the content creator. + """ + func = self.get_dbus_method("getDefaultAttributes") return func(*args, **kwargs) - def unImplemented5(self, *args, **kwargs): + def getNSelections(self, *args, **kwargs): """ - unImplemented: - placeholders for future expansion. Note that these are named - 'unimplemented5 and unimplemented6' to avoid conflict with placeholders - from Accessibility::Text. + Obtain the number of separate, contiguous selections in the current + Text object. Text objects which do not implement selection of + discontiguous text regions will always return '0' or '1'. Note + that "contiguous" is defined by continuity of the offsets, i.e. + a text 'selection' is defined by a start/end offset pair. In + the case of bidirectional text, this means that a continguous + selection may appear visually discontiguous, and vice-versa. + @return the number of contiguous selections in the current Text + object. """ - func = self.get_dbus_method("unImplemented5") + func = self.get_dbus_method("getNSelections") return func(*args, **kwargs) - def unImplemented6(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented6") + def getOffsetAtPoint(self, *args, **kwargs): + """ + Get the offset of the character at a given onscreen coordinate. + The coordinate system used to interpret x and y is determined + by parameter coordType. + @param : x + @param : y + @param : coordType + if 0, the input coordinates are interpreted relative to the entire + screen, if 1, they are relative to the toplevel window containing + this Text object. + @return the text offset (as an offset into the character array) + of the glyph whose onscreen bounds contain the point x,y, or + -1 if the point is outside the bounds of any glyph. + """ + func = self.get_dbus_method("getOffsetAtPoint") return func(*args, **kwargs) - def unImplemented9(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented9") + def getRangeExtents(self, *args, **kwargs): + """ + Obtain the bounding box which entirely contains a given text + range. Negative values may be returned for the bounding box parameters + in the event that all or part of the text range is offscreen + or not mapped to the screen. + @param : startOffset + the offset of the first character in the specified range. + @param : endOffset + the offset of the character immediately after the last character + in the specified range. + @param : x + an integer parameter which is back-filled with the minimum horizontal + coordinate of the resulting bounding box. + @param : y + an integer parameter which is back-filled with the minimum vertical + coordinate of the resulting bounding box. + @param : width + an integer parameter which is back-filled with the horizontal + extent of the bounding box. + @param : height + an integer parameter which is back-filled with the vertical extent + of the bounding box. + @param : coordType + If 0, the above coordinates are reported in pixels relative to + corner of the screen; if 1, the coordinates are reported relative + to the corner of the containing toplevel window. + """ + func = self.get_dbus_method("getRangeExtents") return func(*args, **kwargs) - - -class Event(list): - def __new__(cls, type, source, detail1, detail2, any_data): - list.__new__(cls, (type, source, detail1, detail2, any_data) - def __init__(self, type, source, detail1, detail2, any_data): - list.__init__(self, (type, source, detail1, detail2, any_data)) - - type = property(fget=_get_type, fset=_set_type) - def _get_type(self): - return self[0] - def _set_type(self, val): - self[0] = val - source = property(fget=_get_source, fset=_set_source) - def _get_source(self): - return self[1] - def _set_source(self, val): - self[1] = val - detail1 = property(fget=_get_detail1, fset=_set_detail1) - def _get_detail1(self): - return self[2] - def _set_detail1(self, val): - self[2] = val - detail2 = property(fget=_get_detail2, fset=_set_detail2) - def _get_detail2(self): - return self[3] - def _set_detail2(self, val): - self[3] = val - any_data = property(fget=_get_any_data, fset=_set_any_data) - def _get_any_data(self): - return self[4] - def _set_any_data(self, val): - self[4] = val - - -class EventDetails(list): - def __new__(cls, host_application, source_role, source_name, any_data): - list.__new__(cls, (host_application, source_role, source_name, any_data) - def __init__(self, host_application, source_role, source_name, any_data): - list.__init__(self, (host_application, source_role, source_name, any_data)) - - host_application = property(fget=_get_host_application, fset=_set_host_application) - def _get_host_application(self): - return self[0] - def _set_host_application(self, val): - self[0] = val - source_role = property(fget=_get_source_role, fset=_set_source_role) - def _get_source_role(self): - return self[1] - def _set_source_role(self, val): - self[1] = val - source_name = property(fget=_get_source_name, fset=_set_source_name) - def _get_source_name(self): - return self[2] - def _set_source_name(self, val): - self[2] = val - any_data = property(fget=_get_any_data, fset=_set_any_data) - def _get_any_data(self): - return self[3] - def _set_any_data(self, val): - self[3] = val - - -class EventListener(BaseProxy): - - - """ - A generic interface implemented by objects for the receipt of - event notifications. EventListener is the interface from which - Accessibility::Registry is derived, and via which clients of - the Registry receive notification of changes to an application's - user interface and content. - """ - - def notifyEvent(self, *args, **kwargs): + def getSelection(self, *args, **kwargs): """ - Synchronously notify an EventListener that an event has occurred, - by passing it an Event struct. - @param : e - The Event about which the listener is being notified. + The result of calling getSelection with an out-of-range selectionNum + (i.e. for a selection which does not exist) is not strictly defined, + but should set endOffset equal to startOffset. """ - func = self.get_dbus_method("notifyEvent") + func = self.get_dbus_method("getSelection") return func(*args, **kwargs) - def unImplemented2_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2_") + def getText(self, *args, **kwargs): + """ + Obtain all or part of the onscreen textual content of a Text + object. If endOffset is specified as "-1", then this method will + return the entire onscreen textual contents of the Text object. + @return the textual content of the current Text object beginning + startOffset (inclusive) up to but not including the character + at endOffset. + """ + func = self.get_dbus_method("getText") return func(*args, **kwargs) - def unImplemented3_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3_") + def getTextAfterOffset(self, *args, **kwargs): + """ + Obtain a subset of the text content of an object which entirely + follows offset, delimited by character, word, line, or sentence + boundaries as specified by type. The starting and ending offsets + of the resulting substring are returned in startOffset and endOffset. + By definition, if such a substring exists, startOffset must be + greater than offset. + @param : offset + the offset from which the substring search begins, and which + must lie before the returned substring. + @param : type + the text-boundary delimiter which determines whether the returned + text constitures a character, word, line, or sentence (and possibly + attendant whitespace), and whether the start or ending of such + a substring forms the boundary condition. + @param : startOffset + back-filled with the starting offset of the resulting substring, + if one exists. + @param : endOffset + back-filled with the offset of the character immediately following + the resulting substring, if one exists. + @return a string which is a substring of the text content of + the object, delimited by the specified boundary condition. + """ + func = self.get_dbus_method("getTextAfterOffset") return func(*args, **kwargs) - def unImplemented4_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4_") + def getTextAtOffset(self, *args, **kwargs): + """ + Obtain a subset of the text content of an object which includes + the specified offset, delimited by character, word, line, or + sentence boundaries as specified by type. The starting and ending + offsets of the resulting substring are returned in startOffset + and endOffset. + @param : offset + the offset from which the substring search begins, and which + must lie within the returned substring. + @param : type + the text-boundary delimiter which determines whether the returned + text constitures a character, word, line, or sentence (and possibly + attendant whitespace), and whether the start or ending of such + a substring forms the boundary condition. + @param : startOffset + back-filled with the starting offset of the resulting substring, + if one exists. + @param : endOffset + back-filled with the offset of the character immediately following + the resulting substring, if one exists. + @return a string which is a substring of the text content of + the object, delimited by the specified boundary condition. + """ + func = self.get_dbus_method("getTextAtOffset") return func(*args, **kwargs) - def unImplemented_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_") + def getTextBeforeOffset(self, *args, **kwargs): + """ + Obtain a subset of the text content of an object which entirely + precedes offset, delimited by character, word, line, or sentence + boundaries as specified by type. The starting and ending offsets + of the resulting substring are returned in startOffset and endOffset. + By definition, if such a substring exists, endOffset is less + than or equal to offset. + @param : offset + the offset from which the substring search begins. + @param : type + the text-boundary delimiter which determines whether the returned + text constitures a character, word, line, or sentence (and possibly + attendant whitespace), and whether the start or ending of such + a substring forms the boundary condition. + @param : startOffset + back-filled with the starting offset of the resulting substring, + if one exists. + @param : endOffset + back-filled with the offset of the character immediately following + the resulting substring, if one exists. + @return a string which is a substring of the text content of + the object, delimited by the specified boundary condition. + """ + func = self.get_dbus_method("getTextBeforeOffset") return func(*args, **kwargs) - - -class EventListenerMode(list): - def __new__(cls, synchronous, preemptive, global): - list.__new__(cls, (synchronous, preemptive, global) - def __init__(self, synchronous, preemptive, global): - list.__init__(self, (synchronous, preemptive, global)) - - synchronous = property(fget=_get_synchronous, fset=_set_synchronous) - def _get_synchronous(self): - return self[0] - def _set_synchronous(self, val): - self[0] = val - preemptive = property(fget=_get_preemptive, fset=_set_preemptive) - def _get_preemptive(self): - return self[1] - def _set_preemptive(self, val): - self[1] = val - global = property(fget=_get_global, fset=_set_global) - def _get_global(self): - return self[2] - def _set_global(self, val): - self[2] = val - - -class EventType(Enum): - _enum_lookup = { - 0:'KEY_PRESSED_EVENT', - 1:'KEY_RELEASED_EVENT', - 2:'BUTTON_PRESSED_EVENT', - 3:'BUTTON_RELEASED_EVENT', - } - - -class Hyperlink(BaseProxy): - - """ - Instances of Hyperlink are returned by Hypertext objects, and - are the means by which end users and clients interact with linked, - and in some cases embedded, content. Hyperlinks may have multiple - "anchors", where an anchor corresponds to a reference to a particular - resource with a corresponding resource identified (URI). Hyperlinks - may be queried for their URIs, or queried for the objects corresponding - to their anchors. The objects thus obtained are instances of - Accessible, and may be queried, and manipulated via the Action - interface. - """ - - - def getObject(self, *args, **kwargs): + def removeSelection(self, *args, **kwargs): """ - Gets the i'th object, (where i is an integer between 0 and Hyperlink::numAnchors - - 1, inclusive) associated with a Hyperlink. The objects returned - are usually actionable (i.e. they should implement Accessibility::Action), - and the available actions often include "open", "bookmark", "save - link as", etc. They may also implement Accessibility::StreamableContent, - although clients can normally use getURI to obtain a resource - locator via which the object's data may be accessed. - @return an Accessible object instance representing the Hyperlink's - ith anchor, or through which the content associated with the - ith anchor can be accessed. + Deselect the text contained in the specified selectionNum, if + such a selection exists, otherwise do nothing. Removal of a non-existant + selectionNum has no effect. + @return True if the selection was successfully removed, False + otherwise. """ - func = self.get_dbus_method("getObject") + func = self.get_dbus_method("removeSelection") return func(*args, **kwargs) - def getURI(self, *args, **kwargs): + def setCaretOffset(self, *args, **kwargs): """ - Obtain a resource locator ('URI') which can be used to access - the content to which this link "points" or is connected. - @return a string corresponding to the URI of the Hyperlink's - 'ith' anchor, if one exists, or a NIL string otherwise. + Programmatically move the text caret (visible or virtual, as + above) to a given position. + @param : offset + a long int indicating the desired character offset. Not all implementations + of Text will honor setCaretOffset requests, so the return value + below should be checked by the client. + @return TRUE if the request was carried out, or FALSE if the + caret could not be moved to the requested position. """ - func = self.get_dbus_method("getURI") + func = self.get_dbus_method("setCaretOffset") return func(*args, **kwargs) - def isValid(self, *args, **kwargs): + def setSelection(self, *args, **kwargs): """ - Check the hyperlink to see if a connection to its backing content - can be established, or if its URI is valid. - @return True if the object's content is available, or False if - the hyperlink's URI is invalid, or a connection to the resource - can not be established. + Modify an existing selection's start or ending offset. + Calling setSelection for a selectionNum that is not already defined + has no effect. The result of calling setSelection with a selectionNum + greater than 0 for objects that do not include STATE_MULTISELECTABLE + is undefined. + @param : selectionNum + indicates which of a set of non-contiguous selections to modify. + @param : startOffset + the new starting offset for the selection + @param : endOffset + the new ending offset for the selection + @return True if the selection corresponding to selectionNum is + successfully modified, False otherwise. """ - func = self.get_dbus_method("isValid") + func = self.get_dbus_method("setSelection") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -1701,345 +1368,370 @@ class Hyperlink(BaseProxy): func = self.get_dbus_method("unImplemented2") return func(*args, **kwargs) - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - - def get_endIndex(self): - self._pgetter(self._dbus_interface, "endIndex") - def set_endIndex(self, value): - self._psetter(self._dbus_interface, "endIndex", value) - _endIndexDoc = \ + def get_caretOffset(self): + self._pgetter(self._dbus_interface, "caretOffset") + def set_caretOffset(self, value): + self._psetter(self._dbus_interface, "caretOffset", value) + _caretOffsetDoc = \ """ - the ending offset within the containing Hypertext content with - which this Hyperlink is associated; that is, the offset of the - first element past the range within the Hypertext associated - with this Hyperlink. + The current offset of the text caret in the Text object. This + caret may be virtual, e.g. non-visual and notional-only, but + if an onscreen representation of the caret position is visible, + it will correspond to this offset. The caret offset is given + as a character offset, as opposed to a byte offset into a text + buffer or a column offset. """ - endIndex = property(fget=get_endIndex, fset=set_endIndex, doc=_endIndexDoc) + caretOffset = property(fget=get_caretOffset, fset=set_caretOffset, doc=_caretOffsetDoc) - def get_nAnchors(self): - self._pgetter(self._dbus_interface, "nAnchors") - def set_nAnchors(self, value): - self._psetter(self._dbus_interface, "nAnchors", value) - _nAnchorsDoc = \ + def get_characterCount(self): + self._pgetter(self._dbus_interface, "characterCount") + def set_characterCount(self, value): + self._psetter(self._dbus_interface, "characterCount", value) + _characterCountDoc = \ """ - the number of separate anchors associated with this Hyperlink + The total current number of characters in the Text object, including + whitespace and non-spacing characters. """ - nAnchors = property(fget=get_nAnchors, fset=set_nAnchors, doc=_nAnchorsDoc) + characterCount = property(fget=get_characterCount, fset=set_characterCount, doc=_characterCountDoc) - def get_startIndex(self): - self._pgetter(self._dbus_interface, "startIndex") - def set_startIndex(self, value): - self._psetter(self._dbus_interface, "startIndex", value) - _startIndexDoc = \ - """ - the starting offset within the containing Hypertext content with - which this Hyperlink is associated - """ - startIndex = property(fget=get_startIndex, fset=set_startIndex, doc=_startIndexDoc) + class Range(list): + def __new__(cls, startOffset, endOffset, content, data): + list.__new__(cls, (startOffset, endOffset, content, data)) + def __init__(self, startOffset, endOffset, content, data): + list.__init__(self, (startOffset, endOffset, content, data)) + + def _get_startOffset(self): + return self[0] + def _set_startOffset(self, val): + self[0] = val + startOffset = property(fget=_get_startOffset, fset=_set_startOffset) + def _get_endOffset(self): + return self[1] + def _set_endOffset(self, val): + self[1] = val + endOffset = property(fget=_get_endOffset, fset=_set_endOffset) + def _get_content(self): + return self[2] + def _set_content(self, val): + self[2] = val + content = property(fget=_get_content, fset=_set_content) + def _get_data(self): + return self[3] + def _set_data(self, val): + self[3] = val + data = property(fget=_get_data, fset=_set_data) -class Hypertext(BaseProxy): - - +class EditableText(Text): """ - An interface used for objects which implement linking between - multiple resource or content locations, or multiple 'markers' - within a single document. A Hypertext instance is associated - with one or more Hyperlinks, which are associated with particular - offsets within the Hypertext's included content. + Derived from interface Text, EditableText provides methods for + modifying textual content of components which support editing. + EditableText also interacts with the system clipboard via copyText, + cutText, and pasteText. """ - - def getLink(self, *args, **kwargs): - """ - Get one of the Hyperlinks associated with this Hypertext object, - by index. - @param : linkIndex - an integer from 0 to getNLinks() - 1. - @return the Hyperlink in this Hypertext object. + def copyText(self, *args, **kwargs): """ - func = self.get_dbus_method("getLink") - return func(*args, **kwargs) - - def getLinkIndex(self, *args, **kwargs): - """ - Get the hyperlink index, if any, associated with a particular - character offset in the Hypertext object. For Hypertext implementors - without textual content, all hyperlinks are associated with character - offset '0'. - @return the index of the Hyperlink associated with character - offset characterIndex, or -1 if no Hyperlink is associated with - that character offset. + Copy a range of text into the system clipboard. + @param : startPos + the character offset of the first character in the range of text + being copied. + @param : endPos + the offset of the first character past the end of the range of + text being copied. """ - func = self.get_dbus_method("getLinkIndex") + func = self.get_dbus_method("copyText") return func(*args, **kwargs) - def getNLinks(self, *args, **kwargs): + def cutText(self, *args, **kwargs): """ - Query the hypertext object for the number of Hyperlinks it contains. - @return the number of Hyperlinks associated with this Hypertext - object, as a long integer. + Excise a range of text from a Text object, copying it into the + system clipboard. + @param : startPos + the character offset of the first character in the range of text + being cut. + @param : endPos + the offset of the first character past the end of the range of + text being cut. + @return True if the text was successfully cut, False otherwise. """ - func = self.get_dbus_method("getNLinks") - return func(*args, **kwargs) - - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") + func = self.get_dbus_method("cutText") return func(*args, **kwargs) - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") + def deleteText(self, *args, **kwargs): + """ + Excise a range of text from a Text object without copying it + into the system clipboard. + @param : startPos + the character offset of the first character in the range of text + being deleted. + @param : endPos + the offset of the first character past the end of the range of + text being deleted. + @return True if the text was successfully deleted, False otherwise. + """ + func = self.get_dbus_method("deleteText") return func(*args, **kwargs) - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") + def insertText(self, *args, **kwargs): + """ + Insert new text contents into an existing text object at a given + location, while retaining the old contents. + @param : position + the character offset into the Text implementor's content at which + the new content will be inserted. + @param : text + a UTF-8 string of which length characters will be inserted into + the text object's text buffer. + @param : length + the number of characters of text to insert. If the character + count of text is less than or equal to length, the entire contents + of text will be inserted. + @return True if the text content was successfully inserted, False + otherwise. + """ + func = self.get_dbus_method("insertText") return func(*args, **kwargs) - - -class Image(BaseProxy): - - """ - An interface implemented by objects which render image data or - pictorial information to the screen. When onscreen components - include graphical information that is not purely intended to - enhance "3d effect" or visual layout, but which conveys some - semantic or informational content to the sighted user, they should - implement Image, and that semantic content should be conveyed - textually to the extent possible via the image description, as - well as the Accessible::name and Accessible::description properties. - """ - - - def getImageExtents(self, *args, **kwargs): + def pasteText(self, *args, **kwargs): """ - Obtain a bounding box which entirely contains the image contents, - as displayed on screen. The bounds returned do not account for - any viewport clipping or the fact that the image may be partially - or wholly obscured by other onscreen content. - @param : coordType - If 0, the returned bounding box position is returned relative - to the screen; if 1, the bounding box position is returned relative - to the containing window. - @return a BoundingBox enclosing the image's onscreen representation. + Copy the text contents of the system clipboard, if any, into + a Text object, inserting it at a particular character offset. + @param : position + the character offset before which the text will be inserted. + @return True if the text was successfully pasted into the Text + object, False otherwise. """ - func = self.get_dbus_method("getImageExtents") + func = self.get_dbus_method("pasteText") return func(*args, **kwargs) - def getImagePosition(self, *args, **kwargs): + def setAttributes(self, *args, **kwargs): """ - Get the coordinates of the current image position on screen. - @param : x - Back-filled with the x coordinate of the onscreen image (i.e. - the minimum x coordinate) - @param : y - Back-filled with the y coordinate of the onscreen image (i.e. - the minimum y coordinate) - @param : coordType - If 0, the returned x and y coordinates are returned relative - to the screen; if 1, they are returned relative to the containing - window. + Apply a particular set of attributes to a range of text. + @return True if the text attributes were successfully modified, + False otherwise. """ - func = self.get_dbus_method("getImagePosition") + func = self.get_dbus_method("setAttributes") return func(*args, **kwargs) - def getImageSize(self, *args, **kwargs): + def setTextContents(self, *args, **kwargs): """ - Obtain the width and height of the current onscreen view of the - image. The extents returned do not account for any viewport clipping - or the fact that the image may be partially or wholly obscured - by other onscreen content. - @param : width - Back-filled with the x extents of the onscreen image (i.e. the - image width in pixels) - @param : height - Back-filled with the y extents of the onscreen image (i.e. the - image height in pixels) + Replace the text contents with a new string, discarding the old + contents. + @param : newContents + a UTF-8 string with which the text object's contents will be + replaced. + @return True if the text content was successfully changed, False + otherwise. """ - func = self.get_dbus_method("getImageSize") + func = self.get_dbus_method("setTextContents") return func(*args, **kwargs) - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") + def unImplemented10(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented10") return func(*args, **kwargs) - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") + def unImplemented11(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented11") return func(*args, **kwargs) - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") + def unImplemented12(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented12") return func(*args, **kwargs) - def get_imageDescription(self): - self._pgetter(self._dbus_interface, "imageDescription") - def set_imageDescription(self, value): - self._psetter(self._dbus_interface, "imageDescription", value) - _imageDescriptionDoc = \ + def unImplemented5(self, *args, **kwargs): """ - A UTF-8 string providing a textual description of what is visually - depicted in the image. + unImplemented: + placeholders for future expansion. Note that these are named + 'unimplemented5 and unimplemented6' to avoid conflict with placeholders + from Accessibility::Text. """ - imageDescription = property(fget=get_imageDescription, fset=set_imageDescription, doc=_imageDescriptionDoc) + func = self.get_dbus_method("unImplemented5") + return func(*args, **kwargs) - def get_imageLocale(self): - self._pgetter(self._dbus_interface, "imageLocale") - def set_imageLocale(self, value): - self._psetter(self._dbus_interface, "imageLocale", value) - _imageLocaleDoc = \ - """ - A string corresponding to the POSIX LC_MESSAGES locale used by - the imageDescription. - """ - imageLocale = property(fget=get_imageLocale, fset=set_imageLocale, doc=_imageLocaleDoc) - + def unImplemented6(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented6") + return func(*args, **kwargs) + + def unImplemented9(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented9") + return func(*args, **kwargs) -class KeyDefinition(list): - def __new__(cls, keycode, keysym, keystring, unused): - list.__new__(cls, (keycode, keysym, keystring, unused) - def __init__(self, keycode, keysym, keystring, unused): - list.__init__(self, (keycode, keysym, keystring, unused)) +class Event(list): + def __new__(cls, type, source, detail1, detail2, any_data): + list.__new__(cls, (type, source, detail1, detail2, any_data)) + def __init__(self, type, source, detail1, detail2, any_data): + list.__init__(self, (type, source, detail1, detail2, any_data)) - keycode = property(fget=_get_keycode, fset=_set_keycode) - def _get_keycode(self): + def _get_type(self): return self[0] - def _set_keycode(self, val): + def _set_type(self, val): self[0] = val - keysym = property(fget=_get_keysym, fset=_set_keysym) - def _get_keysym(self): + type = property(fget=_get_type, fset=_set_type) + def _get_source(self): return self[1] - def _set_keysym(self, val): + def _set_source(self, val): self[1] = val - keystring = property(fget=_get_keystring, fset=_set_keystring) - def _get_keystring(self): + source = property(fget=_get_source, fset=_set_source) + def _get_detail1(self): return self[2] - def _set_keystring(self, val): + def _set_detail1(self, val): self[2] = val - unused = property(fget=_get_unused, fset=_set_unused) - def _get_unused(self): + detail1 = property(fget=_get_detail1, fset=_set_detail1) + def _get_detail2(self): return self[3] - def _set_unused(self, val): + def _set_detail2(self, val): self[3] = val + detail2 = property(fget=_get_detail2, fset=_set_detail2) + def _get_any_data(self): + return self[4] + def _set_any_data(self, val): + self[4] = val + any_data = property(fget=_get_any_data, fset=_set_any_data) -class KeyEventType(Enum): - _enum_lookup = { - 0:'KEY_PRESSED', - 1:'KEY_RELEASED', - } - - -class KeySynthType(Enum): - _enum_lookup = { - 0:'KEY_PRESS', - 1:'KEY_RELEASE', - 2:'KEY_PRESSRELEASE', - 3:'KEY_SYM', - 4:'KEY_STRING', - } - - -class LOCALE_TYPE(Enum): - _enum_lookup = { - 0:'LOCALE_TYPE_MESSAGES', - 1:'LOCALE_TYPE_COLLATE', - 2:'LOCALE_TYPE_CTYPE', - 3:'LOCALE_TYPE_MONETARY', - 4:'LOCALE_TYPE_NUMERIC', - 5:'LOCALE_TYPE_TIME', - } - +class EventDetails(list): + def __new__(cls, host_application, source_role, source_name, any_data): + list.__new__(cls, (host_application, source_role, source_name, any_data)) + def __init__(self, host_application, source_role, source_name, any_data): + list.__init__(self, (host_application, source_role, source_name, any_data)) + + def _get_host_application(self): + return self[0] + def _set_host_application(self, val): + self[0] = val + host_application = property(fget=_get_host_application, fset=_set_host_application) + def _get_source_role(self): + return self[1] + def _set_source_role(self, val): + self[1] = val + source_role = property(fget=_get_source_role, fset=_set_source_role) + def _get_source_name(self): + return self[2] + def _set_source_name(self, val): + self[2] = val + source_name = property(fget=_get_source_name, fset=_set_source_name) + def _get_any_data(self): + return self[3] + def _set_any_data(self, val): + self[3] = val + any_data = property(fget=_get_any_data, fset=_set_any_data) -class LoginHelper(BaseProxy): +class EventListener(BaseProxy): + """ + A generic interface implemented by objects for the receipt of + event notifications. EventListener is the interface from which + Accessibility::Registry is derived, and via which clients of + the Registry receive notification of changes to an application's + user interface and content. + """ + + def notifyEvent(self, *args, **kwargs): + """ + Synchronously notify an EventListener that an event has occurred, + by passing it an Event struct. + @param : e + The Event about which the listener is being notified. + """ + func = self.get_dbus_method("notifyEvent") + return func(*args, **kwargs) + def unImplemented2_(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented2_") + return func(*args, **kwargs) + + def unImplemented3_(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented3_") + return func(*args, **kwargs) + + def unImplemented4_(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented4_") + return func(*args, **kwargs) + + def unImplemented_(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented_") + return func(*args, **kwargs) + + +class EventListenerMode(list): + def __new__(cls, synchronous, preemptive, global_): + list.__new__(cls, (synchronous, preemptive, global_)) + def __init__(self, synchronous, preemptive, global_): + list.__init__(self, (synchronous, preemptive, global_)) + def _get_synchronous(self): + return self[0] + def _set_synchronous(self, val): + self[0] = val + synchronous = property(fget=_get_synchronous, fset=_set_synchronous) + def _get_preemptive(self): + return self[1] + def _set_preemptive(self, val): + self[1] = val + preemptive = property(fget=_get_preemptive, fset=_set_preemptive) + def _get_global_(self): + return self[2] + def _set_global_(self, val): + self[2] = val + global_ = property(fget=_get_global_, fset=_set_global_) + + +class EventType(Enum): + _enum_lookup = { + 0:'KEY_PRESSED_EVENT', + 1:'KEY_RELEASED_EVENT', + 2:'BUTTON_PRESSED_EVENT', + 3:'BUTTON_RELEASED_EVENT', + } + +class Hyperlink(BaseProxy): """ - An interface for use by assistive technologies by which they - can access system information and services on a 'need to know' - basis while the screen is locked, during user authentication, - or during other sensitive operations. - This interface is intended for use by assistive technologies - and related user-enabling services, and by applications and utilities - which may wish to restrict access to certain system devices and - services during security-sensitive states, e.g. when the screen - is locked or during authentication into some secure service. - Such 'applications' (for instance, screen lock dialogs and security-enabled - web browsers) use the LoginHelper client interfaces, and the - bonobo-activation query service, to query for assistive technologies - which advertise the LoginHelper service. The client then queries - these assistive technologies for their device I/O requirements, - via the getDeviceReqs call. The client may then issue the advisory - request setSafe (TRUE), which requests that the LoginHelper -implementing - service make a best-effort attempt to make itself more secure - (for instance, an onscreen keyboard might turn off word prediction, - and a screenreader may turn off keyboard echo via speech). The - return value of setSafe is an advisory indication of whether - this attempt was successful (no specific guarantees are implied). - Once the 'security sensitive' state is exited, the client should - call setSafe (FALSE). - The return values from getDeviceReqs inform the client of which - services the LoginHelper service (e. g. assistive technology) - needs in order to do its job. The client may use this information - to loosen any restrictions on access which it may currently have - in place (for instance, keyboard grabs, etc.). If it does not - do so, the likely outcome is that the end-user will experience - loss of access to the system. + Instances of Hyperlink are returned by Hypertext objects, and + are the means by which end users and clients interact with linked, + and in some cases embedded, content. Hyperlinks may have multiple + "anchors", where an anchor corresponds to a reference to a particular + resource with a corresponding resource identified (URI). Hyperlinks + may be queried for their URIs, or queried for the objects corresponding + to their anchors. The objects thus obtained are instances of + Accessible, and may be queried, and manipulated via the Action + interface. """ - - def getDeviceReqs(self, *args, **kwargs): + def getObject(self, *args, **kwargs): """ - getDeviceReqs: - Query a LoginHelper for the types of device I/O it requires, - in order to do its job. For instance, a LoginHelper which needs - to receive keyboard events will include Accessibility_LoginHelper_CORE_KEYBOARD - in this list. - @return : A sequence of LoginHelper_DeviceReq indicating the - device I/O required in order to facilitate end-user access to - the system. + Gets the i'th object, (where i is an integer between 0 and Hyperlink::numAnchors + - 1, inclusive) associated with a Hyperlink. The objects returned + are usually actionable (i.e. they should implement Accessibility::Action), + and the available actions often include "open", "bookmark", "save + link as", etc. They may also implement Accessibility::StreamableContent, + although clients can normally use getURI to obtain a resource + locator via which the object's data may be accessed. + @return an Accessible object instance representing the Hyperlink's + ith anchor, or through which the content associated with the + ith anchor can be accessed. """ - func = self.get_dbus_method("getDeviceReqs") + func = self.get_dbus_method("getObject") return func(*args, **kwargs) - def getRaiseWindows(self, *args, **kwargs): + def getURI(self, *args, **kwargs): """ - getRaiseWindows: - Get a list of window IDs that need raising on login. - @return : a sequence containing window IDS for toplevels which - need to be raised/made visible during user authentication, in - order for the LoginHelper to facilitate end-user access to the - system. + Obtain a resource locator ('URI') which can be used to access + the content to which this link "points" or is connected. + @return a string corresponding to the URI of the Hyperlink's + 'ith' anchor, if one exists, or a NIL string otherwise. """ - func = self.get_dbus_method("getRaiseWindows") + func = self.get_dbus_method("getURI") return func(*args, **kwargs) - def setSafe(self, *args, **kwargs): + def isValid(self, *args, **kwargs): """ - setSafe: - @param : safe_mode - TRUE if the client is requesting that 'safe mode' be initiated, - FALSE if the client is advising that 'safe mode' may be exited, - i.e. normal operation may be resumed. - Request a LoginHelper to enter "safe" mode, or inform LoginHelper - that "safe" mode may be exited. If safe_mode is TRUE, but the - return value is FALSE, the requesting client may wish to deny - services to the LoginHelper, for instance avoid raising its toplevels. - The return value is purely advisory, and no guarantees are intended - about what the implementing LoginHelper will do to improve security - when in "safe" mode. - @return : whether the LoginHelper is now "safe" or not. + Check the hyperlink to see if a connection to its backing content + can be established, or if its URI is valid. + @return True if the object's content is available, or False if + the hyperlink's URI is invalid, or a connection to the resource + can not be established. """ - func = self.get_dbus_method("setSafe") + func = self.get_dbus_method("isValid") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -2058,196 +1750,81 @@ class LoginHelper(BaseProxy): func = self.get_dbus_method("unImplemented4") return func(*args, **kwargs) - AUDIO_IN = Accessibility.DeviceReq(6) - - AUDIO_OUT = Accessibility.DeviceReq(5) - - CORE_KEYBOARD = Accessibility.DeviceReq(1) - - CORE_POINTER = Accessibility.DeviceReq(2) - - class DeviceReq(Enum): - _enum_lookup = { - 0:'GUI_EVENTS', - 1:'CORE_KEYBOARD', - 2:'CORE_POINTER', - 3:'EXT_INPUT', - 4:'POST_WINDOWS', - 5:'AUDIO_OUT', - 6:'AUDIO_IN', - 7:'NETWORK', - 8:'LOCALHOST', - 9:'SERIAL_OUT', - 10:'SERIAL_IN', - } - - - EXT_INPUT = Accessibility.DeviceReq(3) - - GUI_EVENTS = Accessibility.DeviceReq(0) - - LOCALHOST = Accessibility.DeviceReq(8) - - NETWORK = Accessibility.DeviceReq(7) - - POST_WINDOWS = Accessibility.DeviceReq(4) - - SERIAL_IN = Accessibility.DeviceReq(10) + def get_endIndex(self): + self._pgetter(self._dbus_interface, "endIndex") + def set_endIndex(self, value): + self._psetter(self._dbus_interface, "endIndex", value) + _endIndexDoc = \ + """ + the ending offset within the containing Hypertext content with + which this Hyperlink is associated; that is, the offset of the + first element past the range within the Hypertext associated + with this Hyperlink. + """ + endIndex = property(fget=get_endIndex, fset=set_endIndex, doc=_endIndexDoc) - SERIAL_OUT = Accessibility.DeviceReq(9) + def get_nAnchors(self): + self._pgetter(self._dbus_interface, "nAnchors") + def set_nAnchors(self, value): + self._psetter(self._dbus_interface, "nAnchors", value) + _nAnchorsDoc = \ + """ + the number of separate anchors associated with this Hyperlink + """ + nAnchors = property(fget=get_nAnchors, fset=set_nAnchors, doc=_nAnchorsDoc) - class WindowInfo(list): - def __new__(cls, winID): - list.__new__(cls, (winID) - def __init__(self, winID): - list.__init__(self, (winID)) - - winID = property(fget=_get_winID, fset=_set_winID) - def _get_winID(self): - return self[0] - def _set_winID(self, val): - self[0] = val + def get_startIndex(self): + self._pgetter(self._dbus_interface, "startIndex") + def set_startIndex(self, value): + self._psetter(self._dbus_interface, "startIndex", value) + _startIndexDoc = \ + """ + the starting offset within the containing Hypertext content with + which this Hyperlink is associated + """ + startIndex = property(fget=get_startIndex, fset=set_startIndex, doc=_startIndexDoc) -class ModifierType(Enum): - _enum_lookup = { - 0:'MODIFIER_SHIFT', - 1:'MODIFIER_SHIFTLOCK', - 2:'MODIFIER_CONTROL', - 3:'MODIFIER_ALT', - 4:'MODIFIER_META', - 5:'MODIFIER_META2', - 6:'MODIFIER_META3', - 7:'MODIFIER_NUMLOCK', - } - - -class Registry(EventListener): - - +class Hypertext(BaseProxy): """ - The Registry is a service through which applications providing - accessibility services (servers) can rendezvous with consumers - of those services (Assistive Technologies). The Registry is the - first "port of call" for accessible applications and for assistive - technologies wishing to query and interact with those applications. - The Registry service provides four basic functions to Assistive - Technology (AT) clients: - it provides a list of the applications who have registered with - the AT-SPI framework, thereby announcing their participation - in the AT-SPI framework; - it allows AT clients to register for notification of changes - in application state (at-spi Events); - it dispatches/relays said events from participating applications - to the registered listeners; - it gives access to system device events via the associated DeviceEventController - interface. - From the point of view of accessible applications (i.e. AT-SPI - service producers), the Registry is primarily a registration - and event delivery service. Applications normally only call the - registerApplication and deregisterApplication Registry methods, - and its inherited EventListener::notifyEvent method. - The Registry normally lives in its own process space; communication - via Registry and both application services and AT clients takes - place via IPC. A process space diagram illustrating the relationship - between applications, Registry, and AT is shown below. + An interface used for objects which implement linking between + multiple resource or content locations, or multiple 'markers' + within a single document. A Hypertext instance is associated + with one or more Hyperlinks, which are associated with particular + offsets within the Hypertext's included content. """ - - def deregisterApplication(self, *args, **kwargs): - """ - De-register an application previously registered with the broker. - deregisterApplication: - @param : app - a reference to the Application to be deregistered. - """ - func = self.get_dbus_method("deregisterApplication") - return func(*args, **kwargs) - - def deregisterGlobalEventListener(self, *args, **kwargs): - """ - deregisterGlobalEventListener: - @param : listener - the requesting EventListener - @param : eventName - a string indicating the type of events - Request that a previously registered client stop receiving global - notifications for events of a certain type. - """ - func = self.get_dbus_method("deregisterGlobalEventListener") - return func(*args, **kwargs) - - def deregisterGlobalEventListenerAll(self, *args, **kwargs): - """ - deregisterGlobalEventListenerAll: - @param : listener - the requesting EventListener - Request that a previously registered client stop receiving global - notifications for all events for which it was registered. - """ - func = self.get_dbus_method("deregisterGlobalEventListenerAll") - return func(*args, **kwargs) - - def getDesktop(self, *args, **kwargs): - """ - getDesktop: - : the index of the requested Desktop. - Get the nth accessible desktop. - @return a reference to the requested Desktop. - """ - func = self.get_dbus_method("getDesktop") - return func(*args, **kwargs) - - def getDesktopCount(self, *args, **kwargs): - """ - event types: "Window" "Desktop" "Window:Create" "Window:Destroy" - "Window:Iconify" "Window:Restore" "Window:Fullscreen" "Window:Resize" - "Desktop:Create" "Desktop:Destroy" "Desktop:Focus" "Desktop:Defocus" - "Desktop:Reorder" "Focus" "GtkWidget:show" "GObject:notify:" - ( not sure we should allow these last 2 forms, since they are - toolkit-specific, but they're powerful ) getDesktopCount: - Get the current number of desktops. - @return a short integer indicating the current number of Desktops. - """ - func = self.get_dbus_method("getDesktopCount") - return func(*args, **kwargs) - - def getDesktopList(self, *args, **kwargs): - """ - Get a list of accessible desktops. - @return : a sequence containing references to the Desktops. - """ - func = self.get_dbus_method("getDesktopList") - return func(*args, **kwargs) - - def getDeviceEventController(self, *args, **kwargs): + def getLink(self, *args, **kwargs): """ - Obtain an object which can be used to request device event notifications. - @return : an object implementing DeviceEventController + Get one of the Hyperlinks associated with this Hypertext object, + by index. + @param : linkIndex + an integer from 0 to getNLinks() - 1. + @return the Hyperlink in this Hypertext object. """ - func = self.get_dbus_method("getDeviceEventController") + func = self.get_dbus_method("getLink") return func(*args, **kwargs) - def registerApplication(self, *args, **kwargs): + def getLinkIndex(self, *args, **kwargs): """ - Register a new application with the accessibility broker. - @param : app - a reference to the requesting Application + Get the hyperlink index, if any, associated with a particular + character offset in the Hypertext object. For Hypertext implementors + without textual content, all hyperlinks are associated with character + offset '0'. + @return the index of the Hyperlink associated with character + offset characterIndex, or -1 if no Hyperlink is associated with + that character offset. """ - func = self.get_dbus_method("registerApplication") + func = self.get_dbus_method("getLinkIndex") return func(*args, **kwargs) - def registerGlobalEventListener(self, *args, **kwargs): + def getNLinks(self, *args, **kwargs): """ - Register a client's interest in (all) application events of a - certain type. - @param : listener - a reference to the requesting EventListener. - @param : eventName - a string which indicates the type of events about which the client - desires notification. + Query the hypertext object for the number of Hyperlinks it contains. + @return the number of Hyperlinks associated with this Hypertext + object, as a long integer. """ - func = self.get_dbus_method("registerGlobalEventListener") + func = self.get_dbus_method("getNLinks") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -2265,54 +1842,66 @@ class Registry(EventListener): def unImplemented4(self, *args, **kwargs): func = self.get_dbus_method("unImplemented4") return func(*args, **kwargs) - - def unImplemented5(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented5") - return func(*args, **kwargs) - - def unImplemented6(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented6") - return func(*args, **kwargs) -class Relation(BaseProxy): - - +class Image(BaseProxy): """ - An interface via which objects' non-hierarchical relationships - to one another are indicated. An instance of Relations represents - a "one-to-many" correspondance. + An interface implemented by objects which render image data or + pictorial information to the screen. When onscreen components + include graphical information that is not purely intended to + enhance "3d effect" or visual layout, but which conveys some + semantic or informational content to the sighted user, they should + implement Image, and that semantic content should be conveyed + textually to the extent possible via the image description, as + well as the Accessible::name and Accessible::description properties. """ - - def getNTargets(self, *args, **kwargs): - """ - @return the number of objects to which this relationship applies. - """ - func = self.get_dbus_method("getNTargets") - return func(*args, **kwargs) - - def getRelationType(self, *args, **kwargs): + def getImageExtents(self, *args, **kwargs): """ - @return the RelationType of this Relation. + Obtain a bounding box which entirely contains the image contents, + as displayed on screen. The bounds returned do not account for + any viewport clipping or the fact that the image may be partially + or wholly obscured by other onscreen content. + @param : coordType + If 0, the returned bounding box position is returned relative + to the screen; if 1, the bounding box position is returned relative + to the containing window. + @return a BoundingBox enclosing the image's onscreen representation. """ - func = self.get_dbus_method("getRelationType") + func = self.get_dbus_method("getImageExtents") return func(*args, **kwargs) - def getRelationTypeName(self, *args, **kwargs): + def getImagePosition(self, *args, **kwargs): """ - @return an unlocalized string representing the relation type. + Get the coordinates of the current image position on screen. + @param : x + Back-filled with the x coordinate of the onscreen image (i.e. + the minimum x coordinate) + @param : y + Back-filled with the y coordinate of the onscreen image (i.e. + the minimum y coordinate) + @param : coordType + If 0, the returned x and y coordinates are returned relative + to the screen; if 1, they are returned relative to the containing + window. """ - func = self.get_dbus_method("getRelationTypeName") + func = self.get_dbus_method("getImagePosition") return func(*args, **kwargs) - def getTarget(self, *args, **kwargs): + def getImageSize(self, *args, **kwargs): """ - @return an Object which is the 'nth'target of this Relation, - e.g. the Object at index i in the list of Objects having the - specified relationship to this Accessible. + Obtain the width and height of the current onscreen view of the + image. The extents returned do not account for any viewport clipping + or the fact that the image may be partially or wholly obscured + by other onscreen content. + @param : width + Back-filled with the x extents of the onscreen image (i.e. the + image width in pixels) + @param : height + Back-filled with the y extents of the onscreen image (i.e. the + image height in pixels) """ - func = self.get_dbus_method("getTarget") + func = self.get_dbus_method("getImageSize") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -2327,235 +1916,161 @@ class Relation(BaseProxy): func = self.get_dbus_method("unImplemented3") return func(*args, **kwargs) - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) + def get_imageDescription(self): + self._pgetter(self._dbus_interface, "imageDescription") + def set_imageDescription(self, value): + self._psetter(self._dbus_interface, "imageDescription", value) + _imageDescriptionDoc = \ + """ + A UTF-8 string providing a textual description of what is visually + depicted in the image. + """ + imageDescription = property(fget=get_imageDescription, fset=set_imageDescription, doc=_imageDescriptionDoc) + + def get_imageLocale(self): + self._pgetter(self._dbus_interface, "imageLocale") + def set_imageLocale(self, value): + self._psetter(self._dbus_interface, "imageLocale", value) + _imageLocaleDoc = \ + """ + A string corresponding to the POSIX LC_MESSAGES locale used by + the imageDescription. + """ + imageLocale = property(fget=get_imageLocale, fset=set_imageLocale, doc=_imageLocaleDoc) -class RelationType(Enum): - _enum_lookup = { - 0:'RELATION_NULL', - 1:'RELATION_LABEL_FOR', - 2:'RELATION_LABELLED_BY', - 3:'RELATION_CONTROLLER_FOR', - 4:'RELATION_CONTROLLED_BY', - 5:'RELATION_MEMBER_OF', - 6:'RELATION_TOOLTIP_FOR', - 7:'RELATION_NODE_CHILD_OF', - 8:'RELATION_EXTENDED', - 9:'RELATION_FLOWS_TO', - 10:'RELATION_FLOWS_FROM', - 11:'RELATION_SUBWINDOW_OF', - 12:'RELATION_EMBEDS', - 13:'RELATION_EMBEDDED_BY', - 14:'RELATION_POPUP_FOR', - 15:'RELATION_PARENT_WINDOW_OF', - 16:'RELATION_DESCRIPTION_FOR', - 17:'RELATION_DESCRIBED_BY', - 18:'RELATION_LAST_DEFINED', - } +class KeyDefinition(list): + def __new__(cls, keycode, keysym, keystring, unused): + list.__new__(cls, (keycode, keysym, keystring, unused)) + def __init__(self, keycode, keysym, keystring, unused): + list.__init__(self, (keycode, keysym, keystring, unused)) + + def _get_keycode(self): + return self[0] + def _set_keycode(self, val): + self[0] = val + keycode = property(fget=_get_keycode, fset=_set_keycode) + def _get_keysym(self): + return self[1] + def _set_keysym(self, val): + self[1] = val + keysym = property(fget=_get_keysym, fset=_set_keysym) + def _get_keystring(self): + return self[2] + def _set_keystring(self, val): + self[2] = val + keystring = property(fget=_get_keystring, fset=_set_keystring) + def _get_unused(self): + return self[3] + def _set_unused(self, val): + self[3] = val + unused = property(fget=_get_unused, fset=_set_unused) +class KeyEventType(Enum): + _enum_lookup = { + 0:'KEY_PRESSED', + 1:'KEY_RELEASED', + } -class Role(Enum): +class KeySynthType(Enum): _enum_lookup = { - 0:'ROLE_INVALID', - 1:'ROLE_ACCELERATOR_LABEL', - 2:'ROLE_ALERT', - 3:'ROLE_ANIMATION', - 4:'ROLE_ARROW', - 5:'ROLE_CALENDAR', - 6:'ROLE_CANVAS', - 7:'ROLE_CHECK_BOX', - 8:'ROLE_CHECK_MENU_ITEM', - 9:'ROLE_COLOR_CHOOSER', - 10:'ROLE_COLUMN_HEADER', - 11:'ROLE_COMBO_BOX', - 12:'ROLE_DATE_EDITOR', - 13:'ROLE_DESKTOP_ICON', - 14:'ROLE_DESKTOP_FRAME', - 15:'ROLE_DIAL', - 16:'ROLE_DIALOG', - 17:'ROLE_DIRECTORY_PANE', - 18:'ROLE_DRAWING_AREA', - 19:'ROLE_FILE_CHOOSER', - 20:'ROLE_FILLER', - 21:'ROLE_FOCUS_TRAVERSABLE', - 22:'ROLE_FONT_CHOOSER', - 23:'ROLE_FRAME', - 24:'ROLE_GLASS_PANE', - 25:'ROLE_HTML_CONTAINER', - 26:'ROLE_ICON', - 27:'ROLE_IMAGE', - 28:'ROLE_INTERNAL_FRAME', - 29:'ROLE_LABEL', - 30:'ROLE_LAYERED_PANE', - 31:'ROLE_LIST', - 32:'ROLE_LIST_ITEM', - 33:'ROLE_MENU', - 34:'ROLE_MENU_BAR', - 35:'ROLE_MENU_ITEM', - 36:'ROLE_OPTION_PANE', - 37:'ROLE_PAGE_TAB', - 38:'ROLE_PAGE_TAB_LIST', - 39:'ROLE_PANEL', - 40:'ROLE_PASSWORD_TEXT', - 41:'ROLE_POPUP_MENU', - 42:'ROLE_PROGRESS_BAR', - 43:'ROLE_PUSH_BUTTON', - 44:'ROLE_RADIO_BUTTON', - 45:'ROLE_RADIO_MENU_ITEM', - 46:'ROLE_ROOT_PANE', - 47:'ROLE_ROW_HEADER', - 48:'ROLE_SCROLL_BAR', - 49:'ROLE_SCROLL_PANE', - 50:'ROLE_SEPARATOR', - 51:'ROLE_SLIDER', - 52:'ROLE_SPIN_BUTTON', - 53:'ROLE_SPLIT_PANE', - 54:'ROLE_STATUS_BAR', - 55:'ROLE_TABLE', - 56:'ROLE_TABLE_CELL', - 57:'ROLE_TABLE_COLUMN_HEADER', - 58:'ROLE_TABLE_ROW_HEADER', - 59:'ROLE_TEAROFF_MENU_ITEM', - 60:'ROLE_TERMINAL', - 61:'ROLE_TEXT', - 62:'ROLE_TOGGLE_BUTTON', - 63:'ROLE_TOOL_BAR', - 64:'ROLE_TOOL_TIP', - 65:'ROLE_TREE', - 66:'ROLE_TREE_TABLE', - 67:'ROLE_UNKNOWN', - 68:'ROLE_VIEWPORT', - 69:'ROLE_WINDOW', - 70:'ROLE_EXTENDED', - 71:'ROLE_HEADER', - 72:'ROLE_FOOTER', - 73:'ROLE_PARAGRAPH', - 74:'ROLE_RULER', - 75:'ROLE_APPLICATION', - 76:'ROLE_AUTOCOMPLETE', - 77:'ROLE_EDITBAR', - 78:'ROLE_EMBEDDED', - 79:'ROLE_ENTRY', - 80:'ROLE_CHART', - 81:'ROLE_CAPTION', - 82:'ROLE_DOCUMENT_FRAME', - 83:'ROLE_HEADING', - 84:'ROLE_PAGE', - 85:'ROLE_SECTION', - 86:'ROLE_REDUNDANT_OBJECT', - 87:'ROLE_FORM', - 88:'ROLE_LINK', - 89:'ROLE_INPUT_METHOD_WINDOW', - 90:'ROLE_LAST_DEFINED', + 0:'KEY_PRESS', + 1:'KEY_RELEASE', + 2:'KEY_PRESSRELEASE', + 3:'KEY_SYM', + 4:'KEY_STRING', } +class LOCALE_TYPE(Enum): + _enum_lookup = { + 0:'LOCALE_TYPE_MESSAGES', + 1:'LOCALE_TYPE_COLLATE', + 2:'LOCALE_TYPE_CTYPE', + 3:'LOCALE_TYPE_MONETARY', + 4:'LOCALE_TYPE_NUMERIC', + 5:'LOCALE_TYPE_TIME', + } -class Selection(BaseProxy): - - +class LoginHelper(BaseProxy): """ - An interface which indicates that an object exposes a 'selection' - model, allowing the selection of one or more of its children. - Read-only Selection instances are possible, in which case the - interface is used to programmatically determine the selected-ness - of its children. A selected child has State::STATE_SELECTED, - and a child which may hypothetically be selected (though possibly - not programmatically selectable) has State::STATE_SELECTABLE. + An interface for use by assistive technologies by which they + can access system information and services on a 'need to know' + basis while the screen is locked, during user authentication, + or during other sensitive operations. + This interface is intended for use by assistive technologies + and related user-enabling services, and by applications and utilities + which may wish to restrict access to certain system devices and + services during security-sensitive states, e.g. when the screen + is locked or during authentication into some secure service. + Such 'applications' (for instance, screen lock dialogs and security-enabled + web browsers) use the LoginHelper client interfaces, and the + bonobo-activation query service, to query for assistive technologies + which advertise the LoginHelper service. The client then queries + these assistive technologies for their device I/O requirements, + via the getDeviceReqs call. The client may then issue the advisory + request setSafe (TRUE), which requests that the LoginHelper -implementing + service make a best-effort attempt to make itself more secure + (for instance, an onscreen keyboard might turn off word prediction, + and a screenreader may turn off keyboard echo via speech). The + return value of setSafe is an advisory indication of whether + this attempt was successful (no specific guarantees are implied). + Once the 'security sensitive' state is exited, the client should + call setSafe (FALSE). + The return values from getDeviceReqs inform the client of which + services the LoginHelper service (e. g. assistive technology) + needs in order to do its job. The client may use this information + to loosen any restrictions on access which it may currently have + in place (for instance, keyboard grabs, etc.). If it does not + do so, the likely outcome is that the end-user will experience + loss of access to the system. """ - - def clearSelection(self, *args, **kwargs): + def getDeviceReqs(self, *args, **kwargs): """ - Attempt to clear all selections (i.e. deselect all children) - of a Selection. Not all Selection implementations allow the removal - of all selections. - @return True if the selections were successfully cleared, False - otherwise. + getDeviceReqs: + Query a LoginHelper for the types of device I/O it requires, + in order to do its job. For instance, a LoginHelper which needs + to receive keyboard events will include Accessibility_LoginHelper_CORE_KEYBOARD + in this list. + @return : A sequence of LoginHelper_DeviceReq indicating the + device I/O required in order to facilitate end-user access to + the system. """ - func = self.get_dbus_method("clearSelection") + func = self.get_dbus_method("getDeviceReqs") return func(*args, **kwargs) - def deselectChild(self, *args, **kwargs): + def getRaiseWindows(self, *args, **kwargs): """ - Remove a child from the selected children list of a Selection, - if the child is currently selected. - @param : childIndex - a long integer (the zero offset index into the Accessible object's - list of children) indicating which child of the Selection is - to be selected. - @return True if the child was successfully selected, False otherwise. + getRaiseWindows: + Get a list of window IDs that need raising on login. + @return : a sequence containing window IDS for toplevels which + need to be raised/made visible during user authentication, in + order for the LoginHelper to facilitate end-user access to the + system. """ - func = self.get_dbus_method("deselectChild") + func = self.get_dbus_method("getRaiseWindows") return func(*args, **kwargs) - def deselectSelectedChild(self, *args, **kwargs): + def setSafe(self, *args, **kwargs): """ - Remove a child to the selected children list of a Selection. - @param : selectedChildIndex - a long integer indicating which of the selected children of the - Selection is to be deselected. The index is a zero-offset index - into the 'selected child list', not a zero-offset index into - the list of all children of the Selection. - @return True if the child was successfully deselected, False - otherwise. + setSafe: + @param : safe_mode + TRUE if the client is requesting that 'safe mode' be initiated, + FALSE if the client is advising that 'safe mode' may be exited, + i.e. normal operation may be resumed. + Request a LoginHelper to enter "safe" mode, or inform LoginHelper + that "safe" mode may be exited. If safe_mode is TRUE, but the + return value is FALSE, the requesting client may wish to deny + services to the LoginHelper, for instance avoid raising its toplevels. + The return value is purely advisory, and no guarantees are intended + about what the implementing LoginHelper will do to improve security + when in "safe" mode. + @return : whether the LoginHelper is now "safe" or not. """ - func = self.get_dbus_method("deselectSelectedChild") - return func(*args, **kwargs) - - def getSelectedChild(self, *args, **kwargs): - """ - Get the i-th selected Accessible child of a Selection. - @param : selectedChildIndex - a long integer indicating which of the selected children of an - object is being requested. - @return a pointer to a selected Accessible child object, specified - by selectedChildIndex. - """ - func = self.get_dbus_method("getSelectedChild") - return func(*args, **kwargs) - - def isChildSelected(self, *args, **kwargs): - """ - Determine whether a particular child of an Selection implementor - is currently selected. Note that childIndex is the zero-offset - index into the standard Accessible container's list of children. - @param : childIndex - an index into the Selection's list of children. - @return True if the specified child is currently selected, False - otherwise. - """ - func = self.get_dbus_method("isChildSelected") - return func(*args, **kwargs) - - def selectAll(self, *args, **kwargs): - """ - Attempt to select all of the children of a Selection implementor. - Not all Selection implementors support this operation (for instance, - implementations which support only "single selection" do not - support this operation). - @return True if successful, False otherwise. - """ - func = self.get_dbus_method("selectAll") - return func(*args, **kwargs) - - def selectChild(self, *args, **kwargs): - """ - Add a child to the selected children list of a Selection. - @param : childIndex - a long integer indicating which child of the Selection is to - be selected. - @return True if the child was successfully selected, False otherwise. - """ - func = self.get_dbus_method("selectChild") + func = self.get_dbus_method("setSafe") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): - """ - unImplemented: - placeholders for future expansion. - """ func = self.get_dbus_method("unImplemented") return func(*args, **kwargs) @@ -2567,88 +2082,194 @@ class Selection(BaseProxy): func = self.get_dbus_method("unImplemented3") return func(*args, **kwargs) - def get_nSelectedChildren(self): - self._pgetter(self._dbus_interface, "nSelectedChildren") - def set_nSelectedChildren(self, value): - self._psetter(self._dbus_interface, "nSelectedChildren", value) - _nSelectedChildrenDoc = \ - """ - The number of children of a Selection implementor which are currently - selected. - """ - nSelectedChildren = property(fget=get_nSelectedChildren, fset=set_nSelectedChildren, doc=_nSelectedChildrenDoc) - + def unImplemented4(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented4") + return func(*args, **kwargs) -class Selector(BaseProxy): + class DeviceReq(Enum): + _enum_lookup = { + 0:'GUI_EVENTS', + 1:'CORE_KEYBOARD', + 2:'CORE_POINTER', + 3:'EXT_INPUT', + 4:'POST_WINDOWS', + 5:'AUDIO_OUT', + 6:'AUDIO_IN', + 7:'NETWORK', + 8:'LOCALHOST', + 9:'SERIAL_OUT', + 10:'SERIAL_IN', + } + AUDIO_IN = DeviceReq(6) + AUDIO_OUT = DeviceReq(5) + + CORE_KEYBOARD = DeviceReq(1) + + CORE_POINTER = DeviceReq(2) + + EXT_INPUT = DeviceReq(3) + + GUI_EVENTS = DeviceReq(0) + + LOCALHOST = DeviceReq(8) + + NETWORK = DeviceReq(7) + + POST_WINDOWS = DeviceReq(4) + + SERIAL_IN = DeviceReq(10) + + SERIAL_OUT = DeviceReq(9) + + class WindowInfo(list): + def __new__(cls, winID): + list.__new__(cls, (winID)) + def __init__(self, winID): + list.__init__(self, (winID)) + + def _get_winID(self): + return self[0] + def _set_winID(self, val): + self[0] = val + winID = property(fget=_get_winID, fset=_set_winID) + +class ModifierType(Enum): + _enum_lookup = { + 0:'MODIFIER_SHIFT', + 1:'MODIFIER_SHIFTLOCK', + 2:'MODIFIER_CONTROL', + 3:'MODIFIER_ALT', + 4:'MODIFIER_META', + 5:'MODIFIER_META2', + 6:'MODIFIER_META3', + 7:'MODIFIER_NUMLOCK', + } + +class Registry(EventListener): """ - This interface is intended for use by assistive technologies - and related user-agents. Via this interface, an assistive technology - or user agent may expose a series of choices or selections in - textual form, which can be activated on demand by a client of - the Selector interface. - Examples of the use of this interface include voice-command and - remote-control applications, in which the user interaction is - wholly or partly delegated by the implementor to an external - agent. + The Registry is a service through which applications providing + accessibility services (servers) can rendezvous with consumers + of those services (Assistive Technologies). The Registry is the + first "port of call" for accessible applications and for assistive + technologies wishing to query and interact with those applications. + The Registry service provides four basic functions to Assistive + Technology (AT) clients: + it provides a list of the applications who have registered with + the AT-SPI framework, thereby announcing their participation + in the AT-SPI framework; + it allows AT clients to register for notification of changes + in application state (at-spi Events); + it dispatches/relays said events from participating applications + to the registered listeners; + it gives access to system device events via the associated DeviceEventController + interface. + From the point of view of accessible applications (i.e. AT-SPI + service producers), the Registry is primarily a registration + and event delivery service. Applications normally only call the + registerApplication and deregisterApplication Registry methods, + and its inherited EventListener::notifyEvent method. + The Registry normally lives in its own process space; communication + via Registry and both application services and AT clients takes + place via IPC. A process space diagram illustrating the relationship + between applications, Registry, and AT is shown below. """ + def deregisterApplication(self, *args, **kwargs): + """ + De-register an application previously registered with the broker. + deregisterApplication: + @param : app + a reference to the Application to be deregistered. + """ + func = self.get_dbus_method("deregisterApplication") + return func(*args, **kwargs) - def activateCommand(self, *args, **kwargs): + def deregisterGlobalEventListener(self, *args, **kwargs): """ - Request that the Selector invoke the specified Command. - @param : cmd - the Command to activate/invoke. - @return a CommandResult indicating whether the request was honored, - and the reason for failure if the Command could not be activated - or invoked. + deregisterGlobalEventListener: + @param : listener + the requesting EventListener + @param : eventName + a string indicating the type of events + Request that a previously registered client stop receiving global + notifications for events of a certain type. """ - func = self.get_dbus_method("activateCommand") + func = self.get_dbus_method("deregisterGlobalEventListener") return func(*args, **kwargs) - def deregisterChangeListener(self, *args, **kwargs): + def deregisterGlobalEventListenerAll(self, *args, **kwargs): """ - Tell the Selector instance to cease notifying the specified CommandListener - of changes to the command list. + deregisterGlobalEventListenerAll: @param : listener - the CommandListener to remove from the notification list. + the requesting EventListener + Request that a previously registered client stop receiving global + notifications for all events for which it was registered. """ - func = self.get_dbus_method("deregisterChangeListener") + func = self.get_dbus_method("deregisterGlobalEventListenerAll") return func(*args, **kwargs) - def getCommands(self, *args, **kwargs): + def getDesktop(self, *args, **kwargs): """ - Query the Selector for the current CommandList. - @return the currently available CommandList + getDesktop: + : the index of the requested Desktop. + Get the nth accessible desktop. + @return a reference to the requested Desktop. """ - func = self.get_dbus_method("getCommands") + func = self.get_dbus_method("getDesktop") return func(*args, **kwargs) - def refreshCommands(self, *args, **kwargs): + def getDesktopCount(self, *args, **kwargs): """ - Ask the Selector to re-calculate its CommandList. - @return TRUE if the CommandList changed. + event types: "Window" "Desktop" "Window:Create" "Window:Destroy" + "Window:Iconify" "Window:Restore" "Window:Fullscreen" "Window:Resize" + "Desktop:Create" "Desktop:Destroy" "Desktop:Focus" "Desktop:Defocus" + "Desktop:Reorder" "Focus" "GtkWidget:show" "GObject:notify:" + ( not sure we should allow these last 2 forms, since they are + toolkit-specific, but they're powerful ) getDesktopCount: + Get the current number of desktops. + @return a short integer indicating the current number of Desktops. """ - func = self.get_dbus_method("refreshCommands") + func = self.get_dbus_method("getDesktopCount") return func(*args, **kwargs) - def registerChangeListener(self, *args, **kwargs): + def getDesktopList(self, *args, **kwargs): """ - Register a :CommandListener instance for notification of changes - to the command set. - @param : listener - the CommandListener to be notified of changes. + Get a list of accessible desktops. + @return : a sequence containing references to the Desktops. """ - func = self.get_dbus_method("registerChangeListener") + func = self.get_dbus_method("getDesktopList") return func(*args, **kwargs) - def replaceCommands(self, *args, **kwargs): + def getDeviceEventController(self, *args, **kwargs): """ - @return TRUE if the replacement request was successful, FALSE - if the request could not be honored. + Obtain an object which can be used to request device event notifications. + @return : an object implementing DeviceEventController """ - func = self.get_dbus_method("replaceCommands") + func = self.get_dbus_method("getDeviceEventController") + return func(*args, **kwargs) + + def registerApplication(self, *args, **kwargs): + """ + Register a new application with the accessibility broker. + @param : app + a reference to the requesting Application + """ + func = self.get_dbus_method("registerApplication") + return func(*args, **kwargs) + + def registerGlobalEventListener(self, *args, **kwargs): + """ + Register a client's interest in (all) application events of a + certain type. + @param : listener + a reference to the requesting EventListener. + @param : eventName + a string which indicates the type of events about which the client + desires notification. + """ + func = self.get_dbus_method("registerGlobalEventListener") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -2667,102 +2288,50 @@ class Selector(BaseProxy): func = self.get_dbus_method("unImplemented4") return func(*args, **kwargs) - def get_supportsReplace(self): - self._pgetter(self._dbus_interface, "supportsReplace") - def set_supportsReplace(self, value): - self._psetter(self._dbus_interface, "supportsReplace", value) - _supportsReplaceDoc = \ - """ - This attribute is TRUE if this Selector allows its CommandList - to be specified by the client - """ - supportsReplace = property(fget=get_supportsReplace, fset=set_supportsReplace, doc=_supportsReplaceDoc) - - COMMAND_RESULT_FAILED = Accessibility.CommandResult(2) - - COMMAND_RESULT_INVALID = Accessibility.CommandResult(0) - - COMMAND_RESULT_LAST_DEFINED = Accessibility.CommandResult(4) - - COMMAND_RESULT_OBSOLETE = Accessibility.CommandResult(3) - - COMMAND_RESULT_SUCCESS = Accessibility.CommandResult(1) + def unImplemented5(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented5") + return func(*args, **kwargs) - class CommandResult(Enum): - """ - A code returned by a call to activateCommand, indicating the - result of the activation request. - """ + def unImplemented6(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented6") + return func(*args, **kwargs) - _enum_lookup = { - 0:'COMMAND_RESULT_INVALID', - 1:'COMMAND_RESULT_SUCCESS', - 2:'COMMAND_RESULT_FAILED', - 3:'COMMAND_RESULT_OBSOLETE', - 4:'COMMAND_RESULT_LAST_DEFINED', - } -class StateSet(BaseProxy): +class Relation(BaseProxy): """ - The StateSet interface encapsulates a collection of state information. - It allows comparison of state information between object instances, - and comparisons of an object's state with some hypothetical collection - of states. + An interface via which objects' non-hierarchical relationships + to one another are indicated. An instance of Relations represents + a "one-to-many" correspondance. """ - def add(self, *args, **kwargs): - """ - Add a StateType to an existing StateSet, if not already present. - """ - func = self.get_dbus_method("add") - return func(*args, **kwargs) - - def compare(self, *args, **kwargs): - """ - Compare two StateSet instances and obtain their differences. - @return a 'difference set', i.e. a StateSet consisting of those - states not shared by the two sets being compared. - """ - func = self.get_dbus_method("compare") - return func(*args, **kwargs) - - def contains(self, *args, **kwargs): + def getNTargets(self, *args, **kwargs): """ - Query a StateSet for a specific StateType. - @param : state - the StateType being queried for. - @return TRUE if the StateSet contains StateType state. + @return the number of objects to which this relationship applies. """ - func = self.get_dbus_method("contains") + func = self.get_dbus_method("getNTargets") return func(*args, **kwargs) - def equals(self, *args, **kwargs): + def getRelationType(self, *args, **kwargs): """ - Compare two statesets for equivalence. - @param : tarStateSet - the StateSet to be compared with this one. - @return TRUE if the two StateSet objects are composed of the - same StateTypes. + @return the RelationType of this Relation. """ - func = self.get_dbus_method("equals") - return func(*args, **kwargs) - - def getStates(self, *args, **kwargs): - func = self.get_dbus_method("getStates") + func = self.get_dbus_method("getRelationType") return func(*args, **kwargs) - def isEmpty(self, *args, **kwargs): + def getRelationTypeName(self, *args, **kwargs): """ - @return TRUE if the StateSet contains no states. + @return an unlocalized string representing the relation type. """ - func = self.get_dbus_method("isEmpty") + func = self.get_dbus_method("getRelationTypeName") return func(*args, **kwargs) - def remove(self, *args, **kwargs): + def getTarget(self, *args, **kwargs): """ - Remove a StateType to an existing StateSet, if it is present. + @return an Object which is the 'nth'target of this Relation, + e.g. the Object at index i in the list of Objects having the + specified relationship to this Accessible. """ - func = self.get_dbus_method("remove") + func = self.get_dbus_method("getTarget") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -2782,429 +2351,428 @@ class StateSet(BaseProxy): return func(*args, **kwargs) -class StateType(Enum): +class RelationType(Enum): _enum_lookup = { - 0:'STATE_INVALID', - 1:'STATE_ACTIVE', - 2:'STATE_ARMED', - 3:'STATE_BUSY', - 4:'STATE_CHECKED', - 5:'STATE_COLLAPSED', - 6:'STATE_DEFUNCT', - 7:'STATE_EDITABLE', - 8:'STATE_ENABLED', - 9:'STATE_EXPANDABLE', - 10:'STATE_EXPANDED', - 11:'STATE_FOCUSABLE', - 12:'STATE_FOCUSED', - 13:'STATE_HAS_TOOLTIP', - 14:'STATE_HORIZONTAL', - 15:'STATE_ICONIFIED', - 16:'STATE_MODAL', - 17:'STATE_MULTI_LINE', - 18:'STATE_MULTISELECTABLE', - 19:'STATE_OPAQUE', - 20:'STATE_PRESSED', - 21:'STATE_RESIZABLE', - 22:'STATE_SELECTABLE', - 23:'STATE_SELECTED', - 24:'STATE_SENSITIVE', - 25:'STATE_SHOWING', - 26:'STATE_SINGLE_LINE', - 27:'STATE_STALE', - 28:'STATE_TRANSIENT', - 29:'STATE_VERTICAL', - 30:'STATE_VISIBLE', - 31:'STATE_MANAGES_DESCENDANTS', - 32:'STATE_INDETERMINATE', - 33:'STATE_REQUIRED', - 34:'STATE_TRUNCATED', - 35:'STATE_ANIMATED', - 36:'STATE_INVALID_ENTRY', - 37:'STATE_SUPPORTS_AUTOCOMPLETION', - 38:'STATE_SELECTABLE_TEXT', - 39:'STATE_IS_DEFAULT', - 40:'STATE_VISITED', - 41:'STATE_LAST_DEFINED', + 0:'RELATION_NULL', + 1:'RELATION_LABEL_FOR', + 2:'RELATION_LABELLED_BY', + 3:'RELATION_CONTROLLER_FOR', + 4:'RELATION_CONTROLLED_BY', + 5:'RELATION_MEMBER_OF', + 6:'RELATION_TOOLTIP_FOR', + 7:'RELATION_NODE_CHILD_OF', + 8:'RELATION_EXTENDED', + 9:'RELATION_FLOWS_TO', + 10:'RELATION_FLOWS_FROM', + 11:'RELATION_SUBWINDOW_OF', + 12:'RELATION_EMBEDS', + 13:'RELATION_EMBEDDED_BY', + 14:'RELATION_POPUP_FOR', + 15:'RELATION_PARENT_WINDOW_OF', + 16:'RELATION_DESCRIPTION_FOR', + 17:'RELATION_DESCRIBED_BY', + 18:'RELATION_LAST_DEFINED', } +class Role(Enum): + _enum_lookup = { + 0:'ROLE_INVALID', + 1:'ROLE_ACCELERATOR_LABEL', + 2:'ROLE_ALERT', + 3:'ROLE_ANIMATION', + 4:'ROLE_ARROW', + 5:'ROLE_CALENDAR', + 6:'ROLE_CANVAS', + 7:'ROLE_CHECK_BOX', + 8:'ROLE_CHECK_MENU_ITEM', + 9:'ROLE_COLOR_CHOOSER', + 10:'ROLE_COLUMN_HEADER', + 11:'ROLE_COMBO_BOX', + 12:'ROLE_DATE_EDITOR', + 13:'ROLE_DESKTOP_ICON', + 14:'ROLE_DESKTOP_FRAME', + 15:'ROLE_DIAL', + 16:'ROLE_DIALOG', + 17:'ROLE_DIRECTORY_PANE', + 18:'ROLE_DRAWING_AREA', + 19:'ROLE_FILE_CHOOSER', + 20:'ROLE_FILLER', + 21:'ROLE_FOCUS_TRAVERSABLE', + 22:'ROLE_FONT_CHOOSER', + 23:'ROLE_FRAME', + 24:'ROLE_GLASS_PANE', + 25:'ROLE_HTML_CONTAINER', + 26:'ROLE_ICON', + 27:'ROLE_IMAGE', + 28:'ROLE_INTERNAL_FRAME', + 29:'ROLE_LABEL', + 30:'ROLE_LAYERED_PANE', + 31:'ROLE_LIST', + 32:'ROLE_LIST_ITEM', + 33:'ROLE_MENU', + 34:'ROLE_MENU_BAR', + 35:'ROLE_MENU_ITEM', + 36:'ROLE_OPTION_PANE', + 37:'ROLE_PAGE_TAB', + 38:'ROLE_PAGE_TAB_LIST', + 39:'ROLE_PANEL', + 40:'ROLE_PASSWORD_TEXT', + 41:'ROLE_POPUP_MENU', + 42:'ROLE_PROGRESS_BAR', + 43:'ROLE_PUSH_BUTTON', + 44:'ROLE_RADIO_BUTTON', + 45:'ROLE_RADIO_MENU_ITEM', + 46:'ROLE_ROOT_PANE', + 47:'ROLE_ROW_HEADER', + 48:'ROLE_SCROLL_BAR', + 49:'ROLE_SCROLL_PANE', + 50:'ROLE_SEPARATOR', + 51:'ROLE_SLIDER', + 52:'ROLE_SPIN_BUTTON', + 53:'ROLE_SPLIT_PANE', + 54:'ROLE_STATUS_BAR', + 55:'ROLE_TABLE', + 56:'ROLE_TABLE_CELL', + 57:'ROLE_TABLE_COLUMN_HEADER', + 58:'ROLE_TABLE_ROW_HEADER', + 59:'ROLE_TEAROFF_MENU_ITEM', + 60:'ROLE_TERMINAL', + 61:'ROLE_TEXT', + 62:'ROLE_TOGGLE_BUTTON', + 63:'ROLE_TOOL_BAR', + 64:'ROLE_TOOL_TIP', + 65:'ROLE_TREE', + 66:'ROLE_TREE_TABLE', + 67:'ROLE_UNKNOWN', + 68:'ROLE_VIEWPORT', + 69:'ROLE_WINDOW', + 70:'ROLE_EXTENDED', + 71:'ROLE_HEADER', + 72:'ROLE_FOOTER', + 73:'ROLE_PARAGRAPH', + 74:'ROLE_RULER', + 75:'ROLE_APPLICATION', + 76:'ROLE_AUTOCOMPLETE', + 77:'ROLE_EDITBAR', + 78:'ROLE_EMBEDDED', + 79:'ROLE_ENTRY', + 80:'ROLE_CHART', + 81:'ROLE_CAPTION', + 82:'ROLE_DOCUMENT_FRAME', + 83:'ROLE_HEADING', + 84:'ROLE_PAGE', + 85:'ROLE_SECTION', + 86:'ROLE_REDUNDANT_OBJECT', + 87:'ROLE_FORM', + 88:'ROLE_LINK', + 89:'ROLE_INPUT_METHOD_WINDOW', + 90:'ROLE_LAST_DEFINED', + } -class StreamableContent(BaseProxy): - - - """ - An interface whereby an object allows its backing content to - be streamed to clients. Negotiation of content type is allowed. - Clients may examine the backing data and transform, convert, - or parse the content in order to present it in an alternate form - to end-users. +class Selection(BaseProxy): + """ + An interface which indicates that an object exposes a 'selection' + model, allowing the selection of one or more of its children. + Read-only Selection instances are possible, in which case the + interface is used to programmatically determine the selected-ness + of its children. A selected child has State::STATE_SELECTED, + and a child which may hypothetically be selected (though possibly + not programmatically selectable) has State::STATE_SELECTABLE. """ - - def getContent(self, *args, **kwargs): + def clearSelection(self, *args, **kwargs): """ - DEPRECATED, use getStream instead. getContent: Retrieve this - object's content, in a format appropriate to a requested mimetype. - long Bonobo::Stream:seek (in long offset, in SeekType - whence) - raises (NoPermission, IOError) - void Bonobo::Stream:read (in long count, out iobuf buffer) - raises (NoPermission, IOError) - - @return a Bonobo::Stream whose mimetype matches contentType, - if available, or NIL. + Attempt to clear all selections (i.e. deselect all children) + of a Selection. Not all Selection implementations allow the removal + of all selections. + @return True if the selections were successfully cleared, False + otherwise. """ - func = self.get_dbus_method("getContent") + func = self.get_dbus_method("clearSelection") return func(*args, **kwargs) - def getContentTypes(self, *args, **kwargs): + def deselectChild(self, *args, **kwargs): """ - getContentTypes: - @return the list of available mimetypes for this object's content. + Remove a child from the selected children list of a Selection, + if the child is currently selected. + @param : childIndex + a long integer (the zero offset index into the Accessible object's + list of children) indicating which child of the Selection is + to be selected. + @return True if the child was successfully selected, False otherwise. """ - func = self.get_dbus_method("getContentTypes") + func = self.get_dbus_method("deselectChild") return func(*args, **kwargs) - def getStream(self, *args, **kwargs): + def deselectSelectedChild(self, *args, **kwargs): """ - Retrieve this object's content, in a format appropriate to a - requested mimetype, as a ContentStream instance. - @param : contentType - a string specifying the desired mimetype for the content stream. - @return a Stream whose mimetype matches contentType, if available, - or NIL. + Remove a child to the selected children list of a Selection. + @param : selectedChildIndex + a long integer indicating which of the selected children of the + Selection is to be deselected. The index is a zero-offset index + into the 'selected child list', not a zero-offset index into + the list of all children of the Selection. + @return True if the child was successfully deselected, False + otherwise. """ - func = self.get_dbus_method("getStream") + func = self.get_dbus_method("deselectSelectedChild") return func(*args, **kwargs) - def getURI(self, *args, **kwargs): + def getSelectedChild(self, *args, **kwargs): """ - Get a URI pointing to the content of the specified type, if such - a URI can be obtained. Not all streamable content providers have - URI representations. - @param : contentType - a string specifying the desired mimetype for the content stream. - If NULL, then a URI for the default content type will be returned, - if available. - @return a string which constitutes a URI for a stream of the - specified content type, or NULL if no such URI can be obtained. + Get the i-th selected Accessible child of a Selection. + @param : selectedChildIndex + a long integer indicating which of the selected children of an + object is being requested. + @return a pointer to a selected Accessible child object, specified + by selectedChildIndex. """ - func = self.get_dbus_method("getURI") + func = self.get_dbus_method("getSelectedChild") + return func(*args, **kwargs) + + def isChildSelected(self, *args, **kwargs): + """ + Determine whether a particular child of an Selection implementor + is currently selected. Note that childIndex is the zero-offset + index into the standard Accessible container's list of children. + @param : childIndex + an index into the Selection's list of children. + @return True if the specified child is currently selected, False + otherwise. + """ + func = self.get_dbus_method("isChildSelected") + return func(*args, **kwargs) + + def selectAll(self, *args, **kwargs): + """ + Attempt to select all of the children of a Selection implementor. + Not all Selection implementors support this operation (for instance, + implementations which support only "single selection" do not + support this operation). + @return True if successful, False otherwise. + """ + func = self.get_dbus_method("selectAll") + return func(*args, **kwargs) + + def selectChild(self, *args, **kwargs): + """ + Add a child to the selected children list of a Selection. + @param : childIndex + a long integer indicating which child of the Selection is to + be selected. + @return True if the child was successfully selected, False otherwise. + """ + func = self.get_dbus_method("selectChild") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): + """ + unImplemented: + placeholders for future expansion. + """ func = self.get_dbus_method("unImplemented") return func(*args, **kwargs) def unImplemented2(self, *args, **kwargs): func = self.get_dbus_method("unImplemented2") return func(*args, **kwargs) - - -class TEXT_BOUNDARY_TYPE(Enum): - _enum_lookup = { - 0:'TEXT_BOUNDARY_CHAR', - 1:'TEXT_BOUNDARY_WORD_START', - 2:'TEXT_BOUNDARY_WORD_END', - 3:'TEXT_BOUNDARY_SENTENCE_START', - 4:'TEXT_BOUNDARY_SENTENCE_END', - 5:'TEXT_BOUNDARY_LINE_START', - 6:'TEXT_BOUNDARY_LINE_END', - } - - -class TEXT_CLIP_TYPE(Enum): - _enum_lookup = { - 0:'TEXT_CLIP_NONE', - 1:'TEXT_CLIP_MIN', - 2:'TEXT_CLIP_MAX', - 3:'TEXT_CLIP_BOTH', - } - - -class Table(BaseProxy): + def unImplemented3(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented3") + return func(*args, **kwargs) + def get_nSelectedChildren(self): + self._pgetter(self._dbus_interface, "nSelectedChildren") + def set_nSelectedChildren(self, value): + self._psetter(self._dbus_interface, "nSelectedChildren", value) + _nSelectedChildrenDoc = \ + """ + The number of children of a Selection implementor which are currently + selected. + """ + nSelectedChildren = property(fget=get_nSelectedChildren, fset=set_nSelectedChildren, doc=_nSelectedChildrenDoc) + + +class Selector(BaseProxy): """ - An interface used by containers whose contained data is arranged - in a "tabular" (i.e. row-column) fashion. Tables may resemble - a two-dimensional grid, as in a spreadsheet, or may feature objects - which span multiple rows and/or columns, but whose bounds are - aligned on a row/column matrix. Thus, the Table interface may - be used to represent "spreadsheets" as well as "frames". - Objects within tables are children of the Table instance, and - they may be referenced either via a child index or via a row/column - pair. Their role may be ROLE_TABLE_CELL, but table 'cells' may - have other roles as well. These 'cells' may implement other interfaces, - such as Text, Action, Image, and Component, and should do so - as appropriate to their onscreen representation and/or behavior. + This interface is intended for use by assistive technologies + and related user-agents. Via this interface, an assistive technology + or user agent may expose a series of choices or selections in + textual form, which can be activated on demand by a client of + the Selector interface. + Examples of the use of this interface include voice-command and + remote-control applications, in which the user interaction is + wholly or partly delegated by the implementor to an external + agent. """ - - def addColumnSelection(self, *args, **kwargs): + def activateCommand(self, *args, **kwargs): """ - Select the specified column, adding it to the current column - selection, if the table's selection model permits it. - @param : column - @return True if the specified column was successfully selected, - False if not. + Request that the Selector invoke the specified Command. + @param : cmd + the Command to activate/invoke. + @return a CommandResult indicating whether the request was honored, + and the reason for failure if the Command could not be activated + or invoked. """ - func = self.get_dbus_method("addColumnSelection") + func = self.get_dbus_method("activateCommand") return func(*args, **kwargs) - def addRowSelection(self, *args, **kwargs): + def deregisterChangeListener(self, *args, **kwargs): """ - Select the specified row, adding it to the current row selection, - if the table's selection model permits it. - @param : row - @return True if the specified row was successfully selected, - False if not. + Tell the Selector instance to cease notifying the specified CommandListener + of changes to the command list. + @param : listener + the CommandListener to remove from the notification list. """ - func = self.get_dbus_method("addRowSelection") + func = self.get_dbus_method("deregisterChangeListener") return func(*args, **kwargs) - def getAccessibleAt(self, *args, **kwargs): + def getCommands(self, *args, **kwargs): """ - Get the table cell at the specified row and column indices. - @param : row - the specified table row, zero-indexed. - @param : column - the specified table column, zero-indexed. - @return an Accessible object representing the specified table - cell. + Query the Selector for the current CommandList. + @return the currently available CommandList """ - func = self.get_dbus_method("getAccessibleAt") + func = self.get_dbus_method("getCommands") return func(*args, **kwargs) - def getColumnAtIndex(self, *args, **kwargs): + def refreshCommands(self, *args, **kwargs): """ - Get the table column index occupied by the child at a particular - 1-D child index. - @param : index - the specified child index, zero-indexed. - @return a long integer indicating the first column spanned by - the child of a table, at the specified 1-D (zero-offset) index. + Ask the Selector to re-calculate its CommandList. + @return TRUE if the CommandList changed. """ - func = self.get_dbus_method("getColumnAtIndex") + func = self.get_dbus_method("refreshCommands") return func(*args, **kwargs) - def getColumnDescription(self, *args, **kwargs): + def registerChangeListener(self, *args, **kwargs): """ - Get a text description of a particular table column. This differs - from AccessibleTable_getColumnHeader, which returns an Accessible. - @param : column - the specified table column, zero-indexed. - @return a UTF-8 string describing the specified table column, - if available. + Register a :CommandListener instance for notification of changes + to the command set. + @param : listener + the CommandListener to be notified of changes. """ - func = self.get_dbus_method("getColumnDescription") + func = self.get_dbus_method("registerChangeListener") return func(*args, **kwargs) - def getColumnExtentAt(self, *args, **kwargs): + def replaceCommands(self, *args, **kwargs): """ - Get the number of columns spanned by the table cell at the specific - row and column. (some tables can have cells which span multiple - rows and/or columns). - @param : row - the specified table row, zero-indexed. - @param : column - the specified table column, zero-indexed. - @return a long integer indicating the number of columns spanned - by the specified cell. + @return TRUE if the replacement request was successful, FALSE + if the request could not be honored. """ - func = self.get_dbus_method("getColumnExtentAt") + func = self.get_dbus_method("replaceCommands") return func(*args, **kwargs) - def getColumnHeader(self, *args, **kwargs): - """ - Get the header associated with a table column, if available, - as an instance of Accessible. This differs from getColumnDescription, - which returns a string. - @param : column - the specified table column, zero-indexed. - @return an Accessible representatin of the specified table column, - if available. - """ - func = self.get_dbus_method("getColumnHeader") + def unImplemented(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented") return func(*args, **kwargs) - def getIndexAt(self, *args, **kwargs): - """ - Get the 1-D child index corresponding to the specified 2-D row - and column indices. - @param : row - the specified table row, zero-indexed. - @param : column - the specified table column, zero-indexed. - @return a long integer which serves as the index of a specified - cell in the table, in a form usable by Accessible::getChildAtIndex. - """ - func = self.get_dbus_method("getIndexAt") + def unImplemented2(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented2") return func(*args, **kwargs) - def getRowAtIndex(self, *args, **kwargs): - """ - Get the table row index occupied by the child at a particular - 1-D child index. - @param : index - the specified child index, zero-indexed. - @return a long integer indicating the first row spanned by the - child of a table, at the specified 1-D (zero-offset) index. - """ - func = self.get_dbus_method("getRowAtIndex") + def unImplemented3(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented3") return func(*args, **kwargs) - def getRowColumnExtentsAtIndex(self, *args, **kwargs): - """ - Given a child index, determine the row and column indices and - extents, and whether the cell is currently selected. If the child - at index is not a cell (for instance, if it is a summary, caption, - etc.), False is returned. - @param : index - the index of the Table child whose row/column extents are requested. - @param : row - back-filled with the first table row associated with the cell - with child index index. - @param : col - back-filled with the first table column associated with the cell - with child index index. - @param : row_extents - back-filled with the number of table rows across which child - i extends. - @param : col_extents - back-filled with the number of table columns across which child - i extends. - @param : is_selected - a boolean which is back-filled with True if the child at index - i corresponds to a selected table cell, False otherwise. - Example: If the Table child at index '6' extends across columns - 5 and 6 of row 2 of a Table instance, and is currently selected, - then retval=table::getRowColumnExtentsAtIndex(6,row,col, - row_extents, - col_extents, - is_selected); - will return True, and after the call row, col, row_extents, - col_extents, and is_selected will contain 2, 5, 1, 2, and True, - respectively. - @return True if the index is associated with a valid table cell, - False if the index does not correspond to a cell. If False is - returned, the values of the out parameters are undefined. - """ - func = self.get_dbus_method("getRowColumnExtentsAtIndex") + def unImplemented4(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented4") return func(*args, **kwargs) - def getRowDescription(self, *args, **kwargs): + def get_supportsReplace(self): + self._pgetter(self._dbus_interface, "supportsReplace") + def set_supportsReplace(self, value): + self._psetter(self._dbus_interface, "supportsReplace", value) + _supportsReplaceDoc = \ """ - Get a text description of a particular table row. This differs - from AccessibleTable_getRowHeader, which returns an Accessible. - @param : row - the specified table row, zero-indexed. - @return a UTF-8 string describing the specified table row, if - available. + This attribute is TRUE if this Selector allows its CommandList + to be specified by the client """ - func = self.get_dbus_method("getRowDescription") - return func(*args, **kwargs) - - def getRowExtentAt(self, *args, **kwargs): + supportsReplace = property(fget=get_supportsReplace, fset=set_supportsReplace, doc=_supportsReplaceDoc) + + class CommandResult(Enum): """ - Get the number of rows spanned by the table cell at the specific - row and column. (some tables can have cells which span multiple - rows and/or columns). - @param : row - the specified table row, zero-indexed. - @param : column - the specified table column, zero-indexed. - @return a long integer indicating the number of rows spanned - by the specified cell. + A code returned by a call to activateCommand, indicating the + result of the activation request. """ - func = self.get_dbus_method("getRowExtentAt") - return func(*args, **kwargs) + _enum_lookup = { + 0:'COMMAND_RESULT_INVALID', + 1:'COMMAND_RESULT_SUCCESS', + 2:'COMMAND_RESULT_FAILED', + 3:'COMMAND_RESULT_OBSOLETE', + 4:'COMMAND_RESULT_LAST_DEFINED', + } - def getRowHeader(self, *args, **kwargs): - """ - Get the header associated with a table row, if available. This - differs from getRowDescription, which returns a string. - @param : row - the specified table row, zero-indexed. - @return an Accessible representatin of the specified table row, - if available. - """ - func = self.get_dbus_method("getRowHeader") - return func(*args, **kwargs) + COMMAND_RESULT_FAILED = CommandResult(2) - def getSelectedColumns(self, *args, **kwargs): + COMMAND_RESULT_INVALID = CommandResult(0) + + COMMAND_RESULT_LAST_DEFINED = CommandResult(4) + + COMMAND_RESULT_OBSOLETE = CommandResult(3) + + COMMAND_RESULT_SUCCESS = CommandResult(1) + +class StateSet(BaseProxy): + """ + The StateSet interface encapsulates a collection of state information. + It allows comparison of state information between object instances, + and comparisons of an object's state with some hypothetical collection + of states. + """ + + def add(self, *args, **kwargs): """ - Obtain the indices of all columns which are currently selected. - @return a sequence of integers comprising the indices of columns - currently selected. + Add a StateType to an existing StateSet, if not already present. """ - func = self.get_dbus_method("getSelectedColumns") + func = self.get_dbus_method("add") return func(*args, **kwargs) - def getSelectedRows(self, *args, **kwargs): + def compare(self, *args, **kwargs): """ - Obtain the indices of all rows which are currently selected. - @return a sequence of integers comprising the indices of rows - currently selected. + Compare two StateSet instances and obtain their differences. + @return a 'difference set', i.e. a StateSet consisting of those + states not shared by the two sets being compared. """ - func = self.get_dbus_method("getSelectedRows") + func = self.get_dbus_method("compare") return func(*args, **kwargs) - def isColumnSelected(self, *args, **kwargs): + def contains(self, *args, **kwargs): """ - Determine whether a table column is selected. - @param : column - the column being queried. - @return True if the specified column is currently selected, False - if not. + Query a StateSet for a specific StateType. + @param : state + the StateType being queried for. + @return TRUE if the StateSet contains StateType state. """ - func = self.get_dbus_method("isColumnSelected") + func = self.get_dbus_method("contains") return func(*args, **kwargs) - def isRowSelected(self, *args, **kwargs): + def equals(self, *args, **kwargs): """ - Determine whether a table row is selected. - @param : row - the row being queried. - @return True if the specified row is currently selected, False - if not. + Compare two statesets for equivalence. + @param : tarStateSet + the StateSet to be compared with this one. + @return TRUE if the two StateSet objects are composed of the + same StateTypes. """ - func = self.get_dbus_method("isRowSelected") + func = self.get_dbus_method("equals") return func(*args, **kwargs) - def isSelected(self, *args, **kwargs): - """ - Determine whether the cell at a specific row and column is selected. - @param : row - a row occupied by the cell whose state is being queried. - @param : column - a column occupied by the cell whose state is being queried. - @return True if the specified cell is currently selected, False - if not. - """ - func = self.get_dbus_method("isSelected") + def getStates(self, *args, **kwargs): + func = self.get_dbus_method("getStates") return func(*args, **kwargs) - def removeColumnSelection(self, *args, **kwargs): + def isEmpty(self, *args, **kwargs): """ - Remove the specified column from current column selection, if - the table's selection model permits it. - @param : column - @return True if the specified column was successfully de-selected, - False if not. + @return TRUE if the StateSet contains no states. """ - func = self.get_dbus_method("removeColumnSelection") + func = self.get_dbus_method("isEmpty") return func(*args, **kwargs) - def removeRowSelection(self, *args, **kwargs): + def remove(self, *args, **kwargs): """ - Remove the specified row from current row selection, if the table's - selection model permits it. - @param : row - @return True if the specified row was successfully de-selected, - False if not. + Remove a StateType to an existing StateSet, if it is present. """ - func = self.get_dbus_method("removeRowSelection") + func = self.get_dbus_method("remove") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -3222,526 +2790,422 @@ class Table(BaseProxy): def unImplemented4(self, *args, **kwargs): func = self.get_dbus_method("unImplemented4") return func(*args, **kwargs) + + +class StateType(Enum): + _enum_lookup = { + 0:'STATE_INVALID', + 1:'STATE_ACTIVE', + 2:'STATE_ARMED', + 3:'STATE_BUSY', + 4:'STATE_CHECKED', + 5:'STATE_COLLAPSED', + 6:'STATE_DEFUNCT', + 7:'STATE_EDITABLE', + 8:'STATE_ENABLED', + 9:'STATE_EXPANDABLE', + 10:'STATE_EXPANDED', + 11:'STATE_FOCUSABLE', + 12:'STATE_FOCUSED', + 13:'STATE_HAS_TOOLTIP', + 14:'STATE_HORIZONTAL', + 15:'STATE_ICONIFIED', + 16:'STATE_MODAL', + 17:'STATE_MULTI_LINE', + 18:'STATE_MULTISELECTABLE', + 19:'STATE_OPAQUE', + 20:'STATE_PRESSED', + 21:'STATE_RESIZABLE', + 22:'STATE_SELECTABLE', + 23:'STATE_SELECTED', + 24:'STATE_SENSITIVE', + 25:'STATE_SHOWING', + 26:'STATE_SINGLE_LINE', + 27:'STATE_STALE', + 28:'STATE_TRANSIENT', + 29:'STATE_VERTICAL', + 30:'STATE_VISIBLE', + 31:'STATE_MANAGES_DESCENDANTS', + 32:'STATE_INDETERMINATE', + 33:'STATE_REQUIRED', + 34:'STATE_TRUNCATED', + 35:'STATE_ANIMATED', + 36:'STATE_INVALID_ENTRY', + 37:'STATE_SUPPORTS_AUTOCOMPLETION', + 38:'STATE_SELECTABLE_TEXT', + 39:'STATE_IS_DEFAULT', + 40:'STATE_VISITED', + 41:'STATE_LAST_DEFINED', + } + +class StreamableContent(BaseProxy): + """ + An interface whereby an object allows its backing content to + be streamed to clients. Negotiation of content type is allowed. + Clients may examine the backing data and transform, convert, + or parse the content in order to present it in an alternate form + to end-users. + """ - def unImplemented5(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented5") - return func(*args, **kwargs) - - def unImplemented6(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented6") - return func(*args, **kwargs) - - def unImplemented7(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented7") - return func(*args, **kwargs) - - def get_caption(self): - self._pgetter(self._dbus_interface, "caption") - def set_caption(self, value): - self._psetter(self._dbus_interface, "caption", value) - _captionDoc = \ - """ - An Accessible which represents of a caption for a Table. - """ - caption = property(fget=get_caption, fset=set_caption, doc=_captionDoc) - - def get_nColumns(self): - self._pgetter(self._dbus_interface, "nColumns") - def set_nColumns(self, value): - self._psetter(self._dbus_interface, "nColumns", value) - _nColumnsDoc = \ - """ - The total number of columns in this table (including empty columns), - exclusive of columns which are programmatically hidden. Columns - which are scrolled out of view or clipped by the current viewport - are included. - """ - nColumns = property(fget=get_nColumns, fset=set_nColumns, doc=_nColumnsDoc) - - def get_nRows(self): - self._pgetter(self._dbus_interface, "nRows") - def set_nRows(self, value): - self._psetter(self._dbus_interface, "nRows", value) - _nRowsDoc = \ + def getContent(self, *args, **kwargs): """ - The total number of rows in this table (including empty rows), - exclusive of any rows which are programmatically hidden. Rows - which are merely scrolled out of view are included. + DEPRECATED, use getStream instead. getContent: Retrieve this + object's content, in a format appropriate to a requested mimetype. + long Bonobo::Stream:seek (in long offset, in SeekType + whence) + raises (NoPermission, IOError) + void Bonobo::Stream:read (in long count, out iobuf buffer) + raises (NoPermission, IOError) + + @return a Bonobo::Stream whose mimetype matches contentType, + if available, or NIL. """ - nRows = property(fget=get_nRows, fset=set_nRows, doc=_nRowsDoc) + func = self.get_dbus_method("getContent") + return func(*args, **kwargs) - def get_nSelectedColumns(self): - self._pgetter(self._dbus_interface, "nSelectedColumns") - def set_nSelectedColumns(self, value): - self._psetter(self._dbus_interface, "nSelectedColumns", value) - _nSelectedColumnsDoc = \ + def getContentTypes(self, *args, **kwargs): """ - The number of columns currently selected. A selected column is - one in which all included cells are selected. + getContentTypes: + @return the list of available mimetypes for this object's content. """ - nSelectedColumns = property(fget=get_nSelectedColumns, fset=set_nSelectedColumns, doc=_nSelectedColumnsDoc) + func = self.get_dbus_method("getContentTypes") + return func(*args, **kwargs) - def get_nSelectedRows(self): - self._pgetter(self._dbus_interface, "nSelectedRows") - def set_nSelectedRows(self, value): - self._psetter(self._dbus_interface, "nSelectedRows", value) - _nSelectedRowsDoc = \ + def getStream(self, *args, **kwargs): """ - The number of rows currently selected. A selected row is one - in which all included cells are selected. + Retrieve this object's content, in a format appropriate to a + requested mimetype, as a ContentStream instance. + @param : contentType + a string specifying the desired mimetype for the content stream. + @return a Stream whose mimetype matches contentType, if available, + or NIL. """ - nSelectedRows = property(fget=get_nSelectedRows, fset=set_nSelectedRows, doc=_nSelectedRowsDoc) + func = self.get_dbus_method("getStream") + return func(*args, **kwargs) - def get_summary(self): - self._pgetter(self._dbus_interface, "summary") - def set_summary(self, value): - self._psetter(self._dbus_interface, "summary", value) - _summaryDoc = \ + def getURI(self, *args, **kwargs): """ - An accessible object which summarizes the contents of a Table. - This object is frequently itself a Table instance, albeit a simplified - one. + Get a URI pointing to the content of the specified type, if such + a URI can be obtained. Not all streamable content providers have + URI representations. + @param : contentType + a string specifying the desired mimetype for the content stream. + If NULL, then a URI for the default content type will be returned, + if available. + @return a string which constitutes a URI for a stream of the + specified content type, or NULL if no such URI can be obtained. """ - summary = property(fget=get_summary, fset=set_summary, doc=_summaryDoc) - - -class Text(BaseProxy): - - - """ - The text interface should be implemented by objects which place - textual information onscreen as character strings or glyphs. - The text interface allows access to textual content, including - display attributes and semantic hints associated with runs of - text, and access to bounding box information for glyphs and substrings. - It also allows portions of textual content to be selected, if - the object's StateSet includes STATE_SELECTABLE_TEXT. - In some cases a Text object may have, as its content, an empty - string. In particular this can occur in the case of Hypertext - objects which do not display explicitly textual information onscreen, - as Hypertext is derived from the Text interface. - Typographic and semantic attributes of onscreen textual content, - for instance typeface, weight, language, and such qualities as - 'emphasis' or 'blockquote', are represented as text attributes. - Contiguous sequences of characters over which these attributes - are unchanged are referred to as "attribute runs", and are available - via Text::getAttributeRun. Where possible, implementing clients - will report textual attributes which are the same over the entire - text object, for instance those inherited from a default or document-scope - style, via getDefaultAttributes instead of reporting them explicitly - for each character. Therefore, for any span of text, the attributes - in effect are the union of the set returned by Text::getDefaultAttributes, - and the set returned at a particular character offset via Text::getAttributeRun. - """ - + func = self.get_dbus_method("getURI") + return func(*args, **kwargs) - def addSelection(self, *args, **kwargs): - """ - The result of calling addSelection on objects which already have - one selection present, and which do not include STATE_MULTISELECTABLE, - is undefined, other than the return value. - @return True of the selection was successfully added, False otherwise. - Selection may fail if the object does not support selection of - text (see STATE_SELECTABLE_TEXT), if the object does not support - multiple selections and a selection is already defined, or for - other reasons (for instance if the user does not have permission - to copy the text into the relevant selection buffer). - """ - func = self.get_dbus_method("addSelection") + def unImplemented(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented") return func(*args, **kwargs) - def getAttributeRun(self, *args, **kwargs): - """ - Query a particular text object for the text attributes defined - at a given offset, obtaining the start and end of the "attribute - run" over which these attributes are currently invariant. Text - attributes are those presentational, typographic, or semantic - attributes or qualitites which apply to a range of text specifyable - by starting and ending offsets. Attributes relevant to localization - should be provided in accordance with the w3c "Internationalization - and Localization Markup Requirements", http://www.w3.org/TR/2005/WD-itsreq-20051122/ - Other text attributes should choose their names and value semantics - in accordance with relevant standards such as CSS level 2 (http://www.w3.org/TR/1998/REC-CSS2-19980512), - XHTML 1.0 (http://www.w3.org/TR/2002/REC-xhtml1-20020801), and - WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). Those attributes - from the aforementioned specifications and recommendations which - do not concern typographic, presentational, or semantic aspects - of text should be exposed via the more general Accessible::getAttributes() - API (if at all). - For example, CSS attributes which should be exposed on text (either - as default attributes, or as explicitly-set attributes when non-default - values are specified in the content view) include the Font attributes - (i.e. "css2:font-weight", "css2:font-style"), the "css2:color" - and "css2:background-color" attributes, and "css2:text-decoration" - attribute. - If includeDefaults is TRUE, then this AttributeSet should include - the default attributes as well as those which are explicitly - assigned to the attribute run in question. startOffset and endOffset - will be back-filled to indicate the start and end of the attribute - run which contains 'offset' - an attribute run is a contiguous - section of text whose attributes are homogeneous. - @param : offset - the offset of the character whose attributes will be reported. - @param : startOffset - backfilled with the starting offset of the character range over - which all text attributes match those of offset, i.e. the start - of the homogeneous attribute run including offset. - @param : endOffset - backfilled with the offset of the first character past the character - range over which all text attributes match those of offset, i.e. - the character immediately after the homogeneous attribute run - including offset. - @param : includeDefaults - if False, the call should only return those attributes which - are explicitly set on the current attribute run, omitting any - attributes which are inherited from the default values. See also - Text::getDefaultAttributes. - @return the AttributeSet defined at offset, optionally including - the 'default' attributes. - """ - func = self.get_dbus_method("getAttributeRun") + def unImplemented2(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented2") return func(*args, **kwargs) + + +class TEXT_BOUNDARY_TYPE(Enum): + _enum_lookup = { + 0:'TEXT_BOUNDARY_CHAR', + 1:'TEXT_BOUNDARY_WORD_START', + 2:'TEXT_BOUNDARY_WORD_END', + 3:'TEXT_BOUNDARY_SENTENCE_START', + 4:'TEXT_BOUNDARY_SENTENCE_END', + 5:'TEXT_BOUNDARY_LINE_START', + 6:'TEXT_BOUNDARY_LINE_END', + } + +class TEXT_CLIP_TYPE(Enum): + _enum_lookup = { + 0:'TEXT_CLIP_NONE', + 1:'TEXT_CLIP_MIN', + 2:'TEXT_CLIP_MAX', + 3:'TEXT_CLIP_BOTH', + } + +class Table(BaseProxy): + """ + An interface used by containers whose contained data is arranged + in a "tabular" (i.e. row-column) fashion. Tables may resemble + a two-dimensional grid, as in a spreadsheet, or may feature objects + which span multiple rows and/or columns, but whose bounds are + aligned on a row/column matrix. Thus, the Table interface may + be used to represent "spreadsheets" as well as "frames". + Objects within tables are children of the Table instance, and + they may be referenced either via a child index or via a row/column + pair. Their role may be ROLE_TABLE_CELL, but table 'cells' may + have other roles as well. These 'cells' may implement other interfaces, + such as Text, Action, Image, and Component, and should do so + as appropriate to their onscreen representation and/or behavior. + """ - def getAttributeValue(self, *args, **kwargs): + def addColumnSelection(self, *args, **kwargs): """ - Get the string value of a named attribute at a given offset, - if defined. - @param : offset - the offset of the character for which the attribute run is to - be obtained. - @param : attributeName - the name of the attribute for which the value is to be returned, - if defined. - @param : startOffset - back-filled with the offset of the first character in the attribute - run containing the character at offset. - @param : endOffset - back-filled with the offset of the first character past the end - of the attribute run containing the character at offset. - @param : defined - back-filled with True if the attributeName has a defined value - at offset, False otherwise. - @return the value of attribute (name-value pair) corresponding - to "name", if defined. + Select the specified column, adding it to the current column + selection, if the table's selection model permits it. + @param : column + @return True if the specified column was successfully selected, + False if not. """ - func = self.get_dbus_method("getAttributeValue") + func = self.get_dbus_method("addColumnSelection") return func(*args, **kwargs) - def getAttributes(self, *args, **kwargs): + def addRowSelection(self, *args, **kwargs): """ - getAttributes is deprecated in favor of getAttributeRun. - @return the attributes at offset, as a semicolon-delimited set - of colon-delimited name-value pairs. + Select the specified row, adding it to the current row selection, + if the table's selection model permits it. + @param : row + @return True if the specified row was successfully selected, + False if not. """ - func = self.get_dbus_method("getAttributes") + func = self.get_dbus_method("addRowSelection") return func(*args, **kwargs) - def getBoundedRanges(self, *args, **kwargs): + def getAccessibleAt(self, *args, **kwargs): """ - Return the text content within a bounding box, as a list of Range - structures. Depending on the TEXT_CLIP_TYPE parameters, glyphs - which are clipped by the bounding box (i.e. which lie partially - inside and partially outside it) may or may not be included in - the ranges returned. - @param : x - the minimum x ( i.e. leftmost) coordinate of the bounding box. - @param : y - the minimum y coordinate of the bounding box. - @param : width - the horizontal size of the bounding box. The rightmost bound - of the bounding box is (x + width); - @param : height - the vertical size of the bounding box. The maximum y value of - the bounding box is (y + height); - @param : coordType - If 0, the above coordinates are interpreted as pixels relative - to corner of the screen; if 1, the coordinates are interpreted - as pixels relative to the corner of the containing toplevel window. - @param : xClipType - determines whether text which intersects the bounding box in - the x direction is included. - @param : yClipType - determines whether text which intersects the bounding box in - the y direction is included. + Get the table cell at the specified row and column indices. + @param : row + the specified table row, zero-indexed. + @param : column + the specified table column, zero-indexed. + @return an Accessible object representing the specified table + cell. """ - func = self.get_dbus_method("getBoundedRanges") + func = self.get_dbus_method("getAccessibleAt") return func(*args, **kwargs) - def getCharacterAtOffset(self, *args, **kwargs): + def getColumnAtIndex(self, *args, **kwargs): """ - @return an unsigned long integer whose value corresponds to the - UCS-4 representation of the character at the specified text offset, - or 0 if offset is out of range. + Get the table column index occupied by the child at a particular + 1-D child index. + @param : index + the specified child index, zero-indexed. + @return a long integer indicating the first column spanned by + the child of a table, at the specified 1-D (zero-offset) index. """ - func = self.get_dbus_method("getCharacterAtOffset") + func = self.get_dbus_method("getColumnAtIndex") return func(*args, **kwargs) - def getCharacterExtents(self, *args, **kwargs): + def getColumnDescription(self, *args, **kwargs): """ - Obtain a the bounding box, as x, y, width, and height, of the - character or glyph at a particular character offset in this object's - text content. The coordinate system in which the results are - reported is specified by coordType. If an onscreen glyph corresponds - to multiple character offsets, for instance if the glyph is a - ligature, the bounding box reported will include the entire glyph - and therefore may apply to more than one character offset. - @param : offset - the character offset of the character or glyph being queried. - @param : x - the minimum horizontal coordinate of the bounding box of the - glyph representing the character at offset. - @param : y - the minimum vertical coordinate of the bounding box of the glyph - representing the character at offset. - @param : width - the horizontal extent of the bounding box of the glyph representing - the character at offset. - @param : height - the vertical extent of the bounding box of the glyph representing - the character at offset. - @param : coordType - If 0, the results will be reported in screen coordinates, i.e. - in pixels relative to the upper-left corner of the screen, with - the x axis pointing right and the y axis pointing down. If 1, - the results will be reported relative to the containing toplevel - window, with the x axis pointing right and the y axis pointing - down. + Get a text description of a particular table column. This differs + from AccessibleTable_getColumnHeader, which returns an Accessible. + @param : column + the specified table column, zero-indexed. + @return a UTF-8 string describing the specified table column, + if available. """ - func = self.get_dbus_method("getCharacterExtents") + func = self.get_dbus_method("getColumnDescription") return func(*args, **kwargs) - def getDefaultAttributeSet(self, *args, **kwargs): + def getColumnExtentAt(self, *args, **kwargs): """ - Return an AttributeSet containing the text attributes which apply - to all text in the object by virtue of the default settings of - the document, view, or user agent; e.g. those attributes which - are implied rather than explicitly applied to the text object. - For instance, an object whose entire text content has been explicitly - marked as 'bold' will report the 'bold' attribute via getAttributeRun(), - whereas an object whose text weight is inspecified may report - the default or implied text weight in the default AttributeSet. + Get the number of columns spanned by the table cell at the specific + row and column. (some tables can have cells which span multiple + rows and/or columns). + @param : row + the specified table row, zero-indexed. + @param : column + the specified table column, zero-indexed. + @return a long integer indicating the number of columns spanned + by the specified cell. """ - func = self.get_dbus_method("getDefaultAttributeSet") + func = self.get_dbus_method("getColumnExtentAt") return func(*args, **kwargs) - def getDefaultAttributes(self, *args, **kwargs): + def getColumnHeader(self, *args, **kwargs): """ - Deprecated in favor of getDefaultAttributeSet. - @return the attributes which apply to the entire text content, - but which were not explicitly specified by the content creator. + Get the header associated with a table column, if available, + as an instance of Accessible. This differs from getColumnDescription, + which returns a string. + @param : column + the specified table column, zero-indexed. + @return an Accessible representatin of the specified table column, + if available. """ - func = self.get_dbus_method("getDefaultAttributes") + func = self.get_dbus_method("getColumnHeader") return func(*args, **kwargs) - def getNSelections(self, *args, **kwargs): + def getIndexAt(self, *args, **kwargs): """ - Obtain the number of separate, contiguous selections in the current - Text object. Text objects which do not implement selection of - discontiguous text regions will always return '0' or '1'. Note - that "contiguous" is defined by continuity of the offsets, i.e. - a text 'selection' is defined by a start/end offset pair. In - the case of bidirectional text, this means that a continguous - selection may appear visually discontiguous, and vice-versa. - @return the number of contiguous selections in the current Text - object. + Get the 1-D child index corresponding to the specified 2-D row + and column indices. + @param : row + the specified table row, zero-indexed. + @param : column + the specified table column, zero-indexed. + @return a long integer which serves as the index of a specified + cell in the table, in a form usable by Accessible::getChildAtIndex. """ - func = self.get_dbus_method("getNSelections") + func = self.get_dbus_method("getIndexAt") return func(*args, **kwargs) - def getOffsetAtPoint(self, *args, **kwargs): + def getRowAtIndex(self, *args, **kwargs): """ - Get the offset of the character at a given onscreen coordinate. - The coordinate system used to interpret x and y is determined - by parameter coordType. - @param : x - @param : y - @param : coordType - if 0, the input coordinates are interpreted relative to the entire - screen, if 1, they are relative to the toplevel window containing - this Text object. - @return the text offset (as an offset into the character array) - of the glyph whose onscreen bounds contain the point x,y, or - -1 if the point is outside the bounds of any glyph. + Get the table row index occupied by the child at a particular + 1-D child index. + @param : index + the specified child index, zero-indexed. + @return a long integer indicating the first row spanned by the + child of a table, at the specified 1-D (zero-offset) index. """ - func = self.get_dbus_method("getOffsetAtPoint") + func = self.get_dbus_method("getRowAtIndex") return func(*args, **kwargs) - def getRangeExtents(self, *args, **kwargs): + def getRowColumnExtentsAtIndex(self, *args, **kwargs): """ - Obtain the bounding box which entirely contains a given text - range. Negative values may be returned for the bounding box parameters - in the event that all or part of the text range is offscreen - or not mapped to the screen. - @param : startOffset - the offset of the first character in the specified range. - @param : endOffset - the offset of the character immediately after the last character - in the specified range. - @param : x - an integer parameter which is back-filled with the minimum horizontal - coordinate of the resulting bounding box. - @param : y - an integer parameter which is back-filled with the minimum vertical - coordinate of the resulting bounding box. - @param : width - an integer parameter which is back-filled with the horizontal - extent of the bounding box. - @param : height - an integer parameter which is back-filled with the vertical extent - of the bounding box. - @param : coordType - If 0, the above coordinates are reported in pixels relative to - corner of the screen; if 1, the coordinates are reported relative - to the corner of the containing toplevel window. + Given a child index, determine the row and column indices and + extents, and whether the cell is currently selected. If the child + at index is not a cell (for instance, if it is a summary, caption, + etc.), False is returned. + @param : index + the index of the Table child whose row/column extents are requested. + @param : row + back-filled with the first table row associated with the cell + with child index index. + @param : col + back-filled with the first table column associated with the cell + with child index index. + @param : row_extents + back-filled with the number of table rows across which child + i extends. + @param : col_extents + back-filled with the number of table columns across which child + i extends. + @param : is_selected + a boolean which is back-filled with True if the child at index + i corresponds to a selected table cell, False otherwise. + Example: If the Table child at index '6' extends across columns + 5 and 6 of row 2 of a Table instance, and is currently selected, + then retval=table::getRowColumnExtentsAtIndex(6,row,col, + row_extents, + col_extents, + is_selected); + will return True, and after the call row, col, row_extents, + col_extents, and is_selected will contain 2, 5, 1, 2, and True, + respectively. + @return True if the index is associated with a valid table cell, + False if the index does not correspond to a cell. If False is + returned, the values of the out parameters are undefined. + """ + func = self.get_dbus_method("getRowColumnExtentsAtIndex") + return func(*args, **kwargs) + + def getRowDescription(self, *args, **kwargs): + """ + Get a text description of a particular table row. This differs + from AccessibleTable_getRowHeader, which returns an Accessible. + @param : row + the specified table row, zero-indexed. + @return a UTF-8 string describing the specified table row, if + available. + """ + func = self.get_dbus_method("getRowDescription") + return func(*args, **kwargs) + + def getRowExtentAt(self, *args, **kwargs): """ - func = self.get_dbus_method("getRangeExtents") + Get the number of rows spanned by the table cell at the specific + row and column. (some tables can have cells which span multiple + rows and/or columns). + @param : row + the specified table row, zero-indexed. + @param : column + the specified table column, zero-indexed. + @return a long integer indicating the number of rows spanned + by the specified cell. + """ + func = self.get_dbus_method("getRowExtentAt") return func(*args, **kwargs) - def getSelection(self, *args, **kwargs): + def getRowHeader(self, *args, **kwargs): """ - The result of calling getSelection with an out-of-range selectionNum - (i.e. for a selection which does not exist) is not strictly defined, - but should set endOffset equal to startOffset. + Get the header associated with a table row, if available. This + differs from getRowDescription, which returns a string. + @param : row + the specified table row, zero-indexed. + @return an Accessible representatin of the specified table row, + if available. """ - func = self.get_dbus_method("getSelection") + func = self.get_dbus_method("getRowHeader") return func(*args, **kwargs) - def getText(self, *args, **kwargs): + def getSelectedColumns(self, *args, **kwargs): """ - Obtain all or part of the onscreen textual content of a Text - object. If endOffset is specified as "-1", then this method will - return the entire onscreen textual contents of the Text object. - @return the textual content of the current Text object beginning - startOffset (inclusive) up to but not including the character - at endOffset. + Obtain the indices of all columns which are currently selected. + @return a sequence of integers comprising the indices of columns + currently selected. """ - func = self.get_dbus_method("getText") + func = self.get_dbus_method("getSelectedColumns") return func(*args, **kwargs) - def getTextAfterOffset(self, *args, **kwargs): + def getSelectedRows(self, *args, **kwargs): """ - Obtain a subset of the text content of an object which entirely - follows offset, delimited by character, word, line, or sentence - boundaries as specified by type. The starting and ending offsets - of the resulting substring are returned in startOffset and endOffset. - By definition, if such a substring exists, startOffset must be - greater than offset. - @param : offset - the offset from which the substring search begins, and which - must lie before the returned substring. - @param : type - the text-boundary delimiter which determines whether the returned - text constitures a character, word, line, or sentence (and possibly - attendant whitespace), and whether the start or ending of such - a substring forms the boundary condition. - @param : startOffset - back-filled with the starting offset of the resulting substring, - if one exists. - @param : endOffset - back-filled with the offset of the character immediately following - the resulting substring, if one exists. - @return a string which is a substring of the text content of - the object, delimited by the specified boundary condition. + Obtain the indices of all rows which are currently selected. + @return a sequence of integers comprising the indices of rows + currently selected. """ - func = self.get_dbus_method("getTextAfterOffset") + func = self.get_dbus_method("getSelectedRows") return func(*args, **kwargs) - def getTextAtOffset(self, *args, **kwargs): + def isColumnSelected(self, *args, **kwargs): """ - Obtain a subset of the text content of an object which includes - the specified offset, delimited by character, word, line, or - sentence boundaries as specified by type. The starting and ending - offsets of the resulting substring are returned in startOffset - and endOffset. - @param : offset - the offset from which the substring search begins, and which - must lie within the returned substring. - @param : type - the text-boundary delimiter which determines whether the returned - text constitures a character, word, line, or sentence (and possibly - attendant whitespace), and whether the start or ending of such - a substring forms the boundary condition. - @param : startOffset - back-filled with the starting offset of the resulting substring, - if one exists. - @param : endOffset - back-filled with the offset of the character immediately following - the resulting substring, if one exists. - @return a string which is a substring of the text content of - the object, delimited by the specified boundary condition. + Determine whether a table column is selected. + @param : column + the column being queried. + @return True if the specified column is currently selected, False + if not. """ - func = self.get_dbus_method("getTextAtOffset") + func = self.get_dbus_method("isColumnSelected") return func(*args, **kwargs) - def getTextBeforeOffset(self, *args, **kwargs): + def isRowSelected(self, *args, **kwargs): """ - Obtain a subset of the text content of an object which entirely - precedes offset, delimited by character, word, line, or sentence - boundaries as specified by type. The starting and ending offsets - of the resulting substring are returned in startOffset and endOffset. - By definition, if such a substring exists, endOffset is less - than or equal to offset. - @param : offset - the offset from which the substring search begins. - @param : type - the text-boundary delimiter which determines whether the returned - text constitures a character, word, line, or sentence (and possibly - attendant whitespace), and whether the start or ending of such - a substring forms the boundary condition. - @param : startOffset - back-filled with the starting offset of the resulting substring, - if one exists. - @param : endOffset - back-filled with the offset of the character immediately following - the resulting substring, if one exists. - @return a string which is a substring of the text content of - the object, delimited by the specified boundary condition. + Determine whether a table row is selected. + @param : row + the row being queried. + @return True if the specified row is currently selected, False + if not. """ - func = self.get_dbus_method("getTextBeforeOffset") + func = self.get_dbus_method("isRowSelected") return func(*args, **kwargs) - def removeSelection(self, *args, **kwargs): + def isSelected(self, *args, **kwargs): """ - Deselect the text contained in the specified selectionNum, if - such a selection exists, otherwise do nothing. Removal of a non-existant - selectionNum has no effect. - @return True if the selection was successfully removed, False - otherwise. + Determine whether the cell at a specific row and column is selected. + @param : row + a row occupied by the cell whose state is being queried. + @param : column + a column occupied by the cell whose state is being queried. + @return True if the specified cell is currently selected, False + if not. """ - func = self.get_dbus_method("removeSelection") + func = self.get_dbus_method("isSelected") return func(*args, **kwargs) - def setCaretOffset(self, *args, **kwargs): + def removeColumnSelection(self, *args, **kwargs): """ - Programmatically move the text caret (visible or virtual, as - above) to a given position. - @param : offset - a long int indicating the desired character offset. Not all implementations - of Text will honor setCaretOffset requests, so the return value - below should be checked by the client. - @return TRUE if the request was carried out, or FALSE if the - caret could not be moved to the requested position. + Remove the specified column from current column selection, if + the table's selection model permits it. + @param : column + @return True if the specified column was successfully de-selected, + False if not. """ - func = self.get_dbus_method("setCaretOffset") + func = self.get_dbus_method("removeColumnSelection") return func(*args, **kwargs) - def setSelection(self, *args, **kwargs): + def removeRowSelection(self, *args, **kwargs): """ - Modify an existing selection's start or ending offset. - Calling setSelection for a selectionNum that is not already defined - has no effect. The result of calling setSelection with a selectionNum - greater than 0 for objects that do not include STATE_MULTISELECTABLE - is undefined. - @param : selectionNum - indicates which of a set of non-contiguous selections to modify. - @param : startOffset - the new starting offset for the selection - @param : endOffset - the new ending offset for the selection - @return True if the selection corresponding to selectionNum is - successfully modified, False otherwise. + Remove the specified row from current row selection, if the table's + selection model permits it. + @param : row + @return True if the specified row was successfully de-selected, + False if not. """ - func = self.get_dbus_method("setSelection") + func = self.get_dbus_method("removeRowSelection") return func(*args, **kwargs) def unImplemented(self, *args, **kwargs): @@ -3752,63 +3216,98 @@ class Text(BaseProxy): func = self.get_dbus_method("unImplemented2") return func(*args, **kwargs) - def get_caretOffset(self): - self._pgetter(self._dbus_interface, "caretOffset") - def set_caretOffset(self, value): - self._psetter(self._dbus_interface, "caretOffset", value) - _caretOffsetDoc = \ + def unImplemented3(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented3") + return func(*args, **kwargs) + + def unImplemented4(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented4") + return func(*args, **kwargs) + + def unImplemented5(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented5") + return func(*args, **kwargs) + + def unImplemented6(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented6") + return func(*args, **kwargs) + + def unImplemented7(self, *args, **kwargs): + func = self.get_dbus_method("unImplemented7") + return func(*args, **kwargs) + + def get_caption(self): + self._pgetter(self._dbus_interface, "caption") + def set_caption(self, value): + self._psetter(self._dbus_interface, "caption", value) + _captionDoc = \ """ - The current offset of the text caret in the Text object. This - caret may be virtual, e.g. non-visual and notional-only, but - if an onscreen representation of the caret position is visible, - it will correspond to this offset. The caret offset is given - as a character offset, as opposed to a byte offset into a text - buffer or a column offset. + An Accessible which represents of a caption for a Table. + """ + caption = property(fget=get_caption, fset=set_caption, doc=_captionDoc) + + def get_nColumns(self): + self._pgetter(self._dbus_interface, "nColumns") + def set_nColumns(self, value): + self._psetter(self._dbus_interface, "nColumns", value) + _nColumnsDoc = \ + """ + The total number of columns in this table (including empty columns), + exclusive of columns which are programmatically hidden. Columns + which are scrolled out of view or clipped by the current viewport + are included. + """ + nColumns = property(fget=get_nColumns, fset=set_nColumns, doc=_nColumnsDoc) + + def get_nRows(self): + self._pgetter(self._dbus_interface, "nRows") + def set_nRows(self, value): + self._psetter(self._dbus_interface, "nRows", value) + _nRowsDoc = \ + """ + The total number of rows in this table (including empty rows), + exclusive of any rows which are programmatically hidden. Rows + which are merely scrolled out of view are included. + """ + nRows = property(fget=get_nRows, fset=set_nRows, doc=_nRowsDoc) + + def get_nSelectedColumns(self): + self._pgetter(self._dbus_interface, "nSelectedColumns") + def set_nSelectedColumns(self, value): + self._psetter(self._dbus_interface, "nSelectedColumns", value) + _nSelectedColumnsDoc = \ + """ + The number of columns currently selected. A selected column is + one in which all included cells are selected. """ - caretOffset = property(fget=get_caretOffset, fset=set_caretOffset, doc=_caretOffsetDoc) + nSelectedColumns = property(fget=get_nSelectedColumns, fset=set_nSelectedColumns, doc=_nSelectedColumnsDoc) - def get_characterCount(self): - self._pgetter(self._dbus_interface, "characterCount") - def set_characterCount(self, value): - self._psetter(self._dbus_interface, "characterCount", value) - _characterCountDoc = \ + def get_nSelectedRows(self): + self._pgetter(self._dbus_interface, "nSelectedRows") + def set_nSelectedRows(self, value): + self._psetter(self._dbus_interface, "nSelectedRows", value) + _nSelectedRowsDoc = \ """ - The total current number of characters in the Text object, including - whitespace and non-spacing characters. + The number of rows currently selected. A selected row is one + in which all included cells are selected. """ - characterCount = property(fget=get_characterCount, fset=set_characterCount, doc=_characterCountDoc) + nSelectedRows = property(fget=get_nSelectedRows, fset=set_nSelectedRows, doc=_nSelectedRowsDoc) - class Range(list): - def __new__(cls, startOffset, endOffset, content, data): - list.__new__(cls, (startOffset, endOffset, content, data) - def __init__(self, startOffset, endOffset, content, data): - list.__init__(self, (startOffset, endOffset, content, data)) - - startOffset = property(fget=_get_startOffset, fset=_set_startOffset) - def _get_startOffset(self): - return self[0] - def _set_startOffset(self, val): - self[0] = val - endOffset = property(fget=_get_endOffset, fset=_set_endOffset) - def _get_endOffset(self): - return self[1] - def _set_endOffset(self, val): - self[1] = val - content = property(fget=_get_content, fset=_set_content) - def _get_content(self): - return self[2] - def _set_content(self, val): - self[2] = val - data = property(fget=_get_data, fset=_set_data) - def _get_data(self): - return self[3] - def _set_data(self, val): - self[3] = val + def get_summary(self): + self._pgetter(self._dbus_interface, "summary") + def set_summary(self, value): + self._psetter(self._dbus_interface, "summary", value) + _summaryDoc = \ + """ + An accessible object which summarizes the contents of a Table. + This object is frequently itself a Table instance, albeit a simplified + one. + """ + summary = property(fget=get_summary, fset=set_summary, doc=_summaryDoc) + class Value(BaseProxy): - - """ An interface supporting controls which allow a one-dimensional, scalar quantity to be modified or which reflect a scalar quantity. @@ -3816,7 +3315,6 @@ class Value(BaseProxy): "read only". """ - def unImplemented(self, *args, **kwargs): func = self.get_dbus_method("unImplemented") return func(*args, **kwargs) @@ -3875,3 +3373,398 @@ class Value(BaseProxy): """ minimumValue = property(fget=get_minimumValue, fset=set_minimumValue, doc=_minimumValueDoc) +BUTTON_PRESSED_EVENT = EventType(2) + +BUTTON_RELEASED_EVENT = EventType(3) + +KEY_PRESS = KeySynthType(0) + +KEY_PRESSED = KeyEventType(0) + +KEY_PRESSED_EVENT = EventType(0) + +KEY_PRESSRELEASE = KeySynthType(2) + +KEY_RELEASE = KeySynthType(1) + +KEY_RELEASED = KeyEventType(1) + +KEY_RELEASED_EVENT = EventType(1) + +KEY_STRING = KeySynthType(4) + +KEY_SYM = KeySynthType(3) + +LAYER_BACKGROUND = ComponentLayer(1) + +LAYER_CANVAS = ComponentLayer(2) + +LAYER_INVALID = ComponentLayer(0) + +LAYER_LAST_DEFINED = ComponentLayer(8) + +LAYER_MDI = ComponentLayer(4) + +LAYER_OVERLAY = ComponentLayer(6) + +LAYER_POPUP = ComponentLayer(5) + +LAYER_WIDGET = ComponentLayer(3) + +LAYER_WINDOW = ComponentLayer(7) + +LOCALE_TYPE_COLLATE = LOCALE_TYPE(1) + +LOCALE_TYPE_CTYPE = LOCALE_TYPE(2) + +LOCALE_TYPE_MESSAGES = LOCALE_TYPE(0) + +LOCALE_TYPE_MONETARY = LOCALE_TYPE(3) + +LOCALE_TYPE_NUMERIC = LOCALE_TYPE(4) + +LOCALE_TYPE_TIME = LOCALE_TYPE(5) + +MODIFIER_ALT = ModifierType(3) + +MODIFIER_CONTROL = ModifierType(2) + +MODIFIER_META = ModifierType(4) + +MODIFIER_META2 = ModifierType(5) + +MODIFIER_META3 = ModifierType(6) + +MODIFIER_NUMLOCK = ModifierType(7) + +MODIFIER_SHIFT = ModifierType(0) + +MODIFIER_SHIFTLOCK = ModifierType(1) + +RELATION_CONTROLLED_BY = RelationType(4) + +RELATION_CONTROLLER_FOR = RelationType(3) + +RELATION_DESCRIBED_BY = RelationType(17) + +RELATION_DESCRIPTION_FOR = RelationType(16) + +RELATION_EMBEDDED_BY = RelationType(13) + +RELATION_EMBEDS = RelationType(12) + +RELATION_EXTENDED = RelationType(8) + +RELATION_FLOWS_FROM = RelationType(10) + +RELATION_FLOWS_TO = RelationType(9) + +RELATION_LABELLED_BY = RelationType(2) + +RELATION_LABEL_FOR = RelationType(1) + +RELATION_LAST_DEFINED = RelationType(18) + +RELATION_MEMBER_OF = RelationType(5) + +RELATION_NODE_CHILD_OF = RelationType(7) + +RELATION_NULL = RelationType(0) + +RELATION_PARENT_WINDOW_OF = RelationType(15) + +RELATION_POPUP_FOR = RelationType(14) + +RELATION_SUBWINDOW_OF = RelationType(11) + +RELATION_TOOLTIP_FOR = RelationType(6) + +ROLE_ACCELERATOR_LABEL = Role(1) + +ROLE_ALERT = Role(2) + +ROLE_ANIMATION = Role(3) + +ROLE_APPLICATION = Role(75) + +ROLE_ARROW = Role(4) + +ROLE_AUTOCOMPLETE = Role(76) + +ROLE_CALENDAR = Role(5) + +ROLE_CANVAS = Role(6) + +ROLE_CAPTION = Role(81) + +ROLE_CHART = Role(80) + +ROLE_CHECK_BOX = Role(7) + +ROLE_CHECK_MENU_ITEM = Role(8) + +ROLE_COLOR_CHOOSER = Role(9) + +ROLE_COLUMN_HEADER = Role(10) + +ROLE_COMBO_BOX = Role(11) + +ROLE_DATE_EDITOR = Role(12) + +ROLE_DESKTOP_FRAME = Role(14) + +ROLE_DESKTOP_ICON = Role(13) + +ROLE_DIAL = Role(15) + +ROLE_DIALOG = Role(16) + +ROLE_DIRECTORY_PANE = Role(17) + +ROLE_DOCUMENT_FRAME = Role(82) + +ROLE_DRAWING_AREA = Role(18) + +ROLE_EDITBAR = Role(77) + +ROLE_EMBEDDED = Role(78) + +ROLE_ENTRY = Role(79) + +ROLE_EXTENDED = Role(70) + +ROLE_FILE_CHOOSER = Role(19) + +ROLE_FILLER = Role(20) + +ROLE_FOCUS_TRAVERSABLE = Role(21) + +ROLE_FONT_CHOOSER = Role(22) + +ROLE_FOOTER = Role(72) + +ROLE_FORM = Role(87) + +ROLE_FRAME = Role(23) + +ROLE_GLASS_PANE = Role(24) + +ROLE_HEADER = Role(71) + +ROLE_HEADING = Role(83) + +ROLE_HTML_CONTAINER = Role(25) + +ROLE_ICON = Role(26) + +ROLE_IMAGE = Role(27) + +ROLE_INPUT_METHOD_WINDOW = Role(89) + +ROLE_INTERNAL_FRAME = Role(28) + +ROLE_INVALID = Role(0) + +ROLE_LABEL = Role(29) + +ROLE_LAST_DEFINED = Role(90) + +ROLE_LAYERED_PANE = Role(30) + +ROLE_LINK = Role(88) + +ROLE_LIST = Role(31) + +ROLE_LIST_ITEM = Role(32) + +ROLE_MENU = Role(33) + +ROLE_MENU_BAR = Role(34) + +ROLE_MENU_ITEM = Role(35) + +ROLE_OPTION_PANE = Role(36) + +ROLE_PAGE = Role(84) + +ROLE_PAGE_TAB = Role(37) + +ROLE_PAGE_TAB_LIST = Role(38) + +ROLE_PANEL = Role(39) + +ROLE_PARAGRAPH = Role(73) + +ROLE_PASSWORD_TEXT = Role(40) + +ROLE_POPUP_MENU = Role(41) + +ROLE_PROGRESS_BAR = Role(42) + +ROLE_PUSH_BUTTON = Role(43) + +ROLE_RADIO_BUTTON = Role(44) + +ROLE_RADIO_MENU_ITEM = Role(45) + +ROLE_REDUNDANT_OBJECT = Role(86) + +ROLE_ROOT_PANE = Role(46) + +ROLE_ROW_HEADER = Role(47) + +ROLE_RULER = Role(74) + +ROLE_SCROLL_BAR = Role(48) + +ROLE_SCROLL_PANE = Role(49) + +ROLE_SECTION = Role(85) + +ROLE_SEPARATOR = Role(50) + +ROLE_SLIDER = Role(51) + +ROLE_SPIN_BUTTON = Role(52) + +ROLE_SPLIT_PANE = Role(53) + +ROLE_STATUS_BAR = Role(54) + +ROLE_TABLE = Role(55) + +ROLE_TABLE_CELL = Role(56) + +ROLE_TABLE_COLUMN_HEADER = Role(57) + +ROLE_TABLE_ROW_HEADER = Role(58) + +ROLE_TEAROFF_MENU_ITEM = Role(59) + +ROLE_TERMINAL = Role(60) + +ROLE_TEXT = Role(61) + +ROLE_TOGGLE_BUTTON = Role(62) + +ROLE_TOOL_BAR = Role(63) + +ROLE_TOOL_TIP = Role(64) + +ROLE_TREE = Role(65) + +ROLE_TREE_TABLE = Role(66) + +ROLE_UNKNOWN = Role(67) + +ROLE_VIEWPORT = Role(68) + +ROLE_WINDOW = Role(69) + +STATE_ACTIVE = StateType(1) + +STATE_ANIMATED = StateType(35) + +STATE_ARMED = StateType(2) + +STATE_BUSY = StateType(3) + +STATE_CHECKED = StateType(4) + +STATE_COLLAPSED = StateType(5) + +STATE_DEFUNCT = StateType(6) + +STATE_EDITABLE = StateType(7) + +STATE_ENABLED = StateType(8) + +STATE_EXPANDABLE = StateType(9) + +STATE_EXPANDED = StateType(10) + +STATE_FOCUSABLE = StateType(11) + +STATE_FOCUSED = StateType(12) + +STATE_HAS_TOOLTIP = StateType(13) + +STATE_HORIZONTAL = StateType(14) + +STATE_ICONIFIED = StateType(15) + +STATE_INDETERMINATE = StateType(32) + +STATE_INVALID = StateType(0) + +STATE_INVALID_ENTRY = StateType(36) + +STATE_IS_DEFAULT = StateType(39) + +STATE_LAST_DEFINED = StateType(41) + +STATE_MANAGES_DESCENDANTS = StateType(31) + +STATE_MODAL = StateType(16) + +STATE_MULTISELECTABLE = StateType(18) + +STATE_MULTI_LINE = StateType(17) + +STATE_OPAQUE = StateType(19) + +STATE_PRESSED = StateType(20) + +STATE_REQUIRED = StateType(33) + +STATE_RESIZABLE = StateType(21) + +STATE_SELECTABLE = StateType(22) + +STATE_SELECTABLE_TEXT = StateType(38) + +STATE_SELECTED = StateType(23) + +STATE_SENSITIVE = StateType(24) + +STATE_SHOWING = StateType(25) + +STATE_SINGLE_LINE = StateType(26) + +STATE_STALE = StateType(27) + +STATE_SUPPORTS_AUTOCOMPLETION = StateType(37) + +STATE_TRANSIENT = StateType(28) + +STATE_TRUNCATED = StateType(34) + +STATE_VERTICAL = StateType(29) + +STATE_VISIBLE = StateType(30) + +STATE_VISITED = StateType(40) + +TEXT_BOUNDARY_CHAR = TEXT_BOUNDARY_TYPE(0) + +TEXT_BOUNDARY_LINE_END = TEXT_BOUNDARY_TYPE(6) + +TEXT_BOUNDARY_LINE_START = TEXT_BOUNDARY_TYPE(5) + +TEXT_BOUNDARY_SENTENCE_END = TEXT_BOUNDARY_TYPE(4) + +TEXT_BOUNDARY_SENTENCE_START = TEXT_BOUNDARY_TYPE(3) + +TEXT_BOUNDARY_WORD_END = TEXT_BOUNDARY_TYPE(2) + +TEXT_BOUNDARY_WORD_START = TEXT_BOUNDARY_TYPE(1) + +TEXT_CLIP_BOTH = TEXT_CLIP_TYPE(3) + +TEXT_CLIP_MAX = TEXT_CLIP_TYPE(2) + +TEXT_CLIP_MIN = TEXT_CLIP_TYPE(1) + +TEXT_CLIP_NONE = TEXT_CLIP_TYPE(0) + + diff --git a/pyatspi/registry.py b/pyatspi/registry.py new file mode 100644 index 0000000..ae6fb16 --- /dev/null +++ b/pyatspi/registry.py @@ -0,0 +1,785 @@ +#Copyright (C) 2008 Codethink Ltd +#copyright: Copyright (c) 2005, 2007 IBM Corporation + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License version 2 as published by the Free Software Foundation. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +#You should have received a copy of the GNU Lesser General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#Portions of this code originally licensed and copyright (c) 2005, 2007 +#IBM Corporation under the BSD license, available at +#U{http://www.opensource.org/licenses/bsd-license.php} + +#authors: Peter Parente, Mark Doffman + +import signal +import time +import weakref +import Queue +import traceback +import gobject +import utils +import constants +import event + +ATSPI_DEVICE_EVENT_CONTROLLER = 'org.freedesktop.atspi.DeviceEventController' +ATSPI_DEVICE_EVENT_LISTENER = 'org.freedesktop.atspi.DeviceEventListener' + +class _Observer(object): + """ + Parent class for all event observers. Dispatches all received events to the + L{Registry} that created this L{_Observer}. Provides basic reference counting + functionality needed by L{Registry} to determine when an L{_Observer} can be + released for garbage collection. + + The reference counting provided by this class is independent of the reference + counting used by CORBA. Keeping the counts separate makes it easier for the + L{Registry} to detect when an L{_Observer} can be freed in the + L{Registry._unregisterObserver} method. + + @ivar registry: Reference to the L{Registry} that created this L{_Observer} + @type registry: weakref.proxy to L{Registry} + @ivar ref_count: Reference count on this L{_Observer} + @type ref_count: integer + """ + def __init__(self, registry): + """ + Stores a reference to the creating L{Registry}. Intializes the reference + count on this object to zero. + + @param registry: The L{Registry} that created this observer + @type registry: weakref.proxy to L{Registry} + """ + self.registry = weakref.proxy(registry) + self.ref_count = 0 + + def clientRef(self): + """ + Increments the Python reference count on this L{_Observer} by one. This + method is called when a new client is registered in L{Registry} to receive + notification of an event type monitored by this L{_Observer}. + """ + self.ref_count += 1 + + def clientUnref(self): + """ + Decrements the pyatspi reference count on this L{_Observer} by one. This + method is called when a client is unregistered in L{Registry} to stop + receiving notifications of an event type monitored by this L{_Observer}. + """ + self.ref_count -= 1 + + def getClientRefCount(self): + """ + @return: Current Python reference count on this L{_Observer} + @rtype: integer + """ + return self.ref_count + + def ref(self): + """Required by CORBA. Does nothing.""" + pass + + def unref(self): + """Required by CORBA. Does nothing.""" + pass + +class _DeviceObserver(_Observer, Accessibility__POA.DeviceEventListener): + """ + Observes keyboard press and release events. + + @ivar registry: The L{Registry} that created this observer + @type registry: L{Registry} + @ivar key_set: Set of keys to monitor + @type key_set: list of integer + @ivar mask: Watch for key events while these modifiers are held + @type mask: integer + @ivar kind: Kind of events to monitor + @type kind: integer + @ivar mode: Keyboard event mode + @type mode: Accessibility.EventListenerMode + """ + def __init__(self, registry, synchronous, preemptive, global_): + """ + Creates a mode object that defines when key events will be received from + the system. Stores all other information for later registration. + + @param registry: The L{Registry} that created this observer + @type registry: L{Registry} + @param synchronous: Handle the key event synchronously? + @type synchronous: boolean + @param preemptive: Allow event to be consumed? + @type preemptive: boolean + @param global_: Watch for events on inaccessible applications too? + @type global_: boolean + """ + _Observer.__init__(self, registry) + self.mode = Accessibility.EventListenerMode() + self.mode.preemptive = preemptive + self.mode.synchronous = synchronous + self.mode._global = global_ + + def register(self, dc, key_set, mask, kind): + """ + Starts keyboard event monitoring. + + @param dc: Reference to a device controller + @type dc: Accessibility.DeviceEventController + @param key_set: Set of keys to monitor + @type key_set: list of integer + @param mask: Integer modifier mask or an iterable over multiple masks to + unapply all at once + @type mask: integer, iterable, or None + @param kind: Kind of events to monitor + @type kind: integer + """ + try: + # check if the mask is iterable + iter(mask) + except TypeError: + # register a single integer if not + dc.registerKeystrokeListener(self._this(), key_set, mask, kind, + self.mode) + else: + for m in mask: + dc.registerKeystrokeListener(self._this(), key_set, m, kind, self.mode) + + def unregister(self, dc, key_set, mask, kind): + """ + Stops keyboard event monitoring. + + @param dc: Reference to a device controller + @type dc: Accessibility.DeviceEventController + @param key_set: Set of keys to monitor + @type key_set: list of integer + @param mask: Integer modifier mask or an iterable over multiple masks to + unapply all at once + @type mask: integer, iterable, or None + @param kind: Kind of events to monitor + @type kind: integer + """ + try: + # check if the mask is iterable + iter(mask) + except TypeError: + # unregister a single integer if not + dc.deregisterKeystrokeListener(self._this(), key_set, mask, kind) + else: + for m in mask: + dc.deregisterKeystrokeListener(self._this(), key_set, m, kind) + + def queryInterface(self, repo_id): + """ + Reports that this class only implements the AT-SPI DeviceEventListener + interface. Required by AT-SPI. + + @param repo_id: Request for an interface + @type repo_id: string + @return: The underlying CORBA object for the device event listener + @rtype: Accessibility.EventListener + """ + if repo_id == utils.getInterfaceIID(Accessibility.DeviceEventListener): + return self._this() + else: + return None + + def notifyEvent(self, ev): + """ + Notifies the L{Registry} that an event has occurred. Wraps the raw event + object in our L{Event} class to support automatic ref and unref calls. An + observer can return True to indicate this event should not be allowed to pass + to other AT-SPI observers or the underlying application. + + @param ev: Keyboard event + @type ev: Accessibility.DeviceEvent + @return: Should the event be consumed (True) or allowed to pass on to other + AT-SPI observers (False)? + @rtype: boolean + """ + # wrap the device event + ev = event.DeviceEvent(ev) + return self.registry.handleDeviceEvent(ev, self) + +class _EventObserver(_Observer, Accessibility__POA.EventListener): + """ + Observes all non-keyboard AT-SPI events. Can be reused across event types. + """ + def register(self, reg, name): + """ + Starts monitoring for the given event. + + @param name: Name of the event to start monitoring + @type name: string + @param reg: Reference to the raw registry object + @type reg: Accessibility.Registry + """ + reg.registerGlobalEventListener(self._this(), name) + + def unregister(self, reg, name): + """ + Stops monitoring for the given event. + + @param name: Name of the event to stop monitoring + @type name: string + @param reg: Reference to the raw registry object + @type reg: Accessibility.Registry + """ + reg.deregisterGlobalEventListener(self._this(), name) + + def queryInterface(self, repo_id): + """ + Reports that this class only implements the AT-SPI DeviceEventListener + interface. Required by AT-SPI. + + @param repo_id: Request for an interface + @type repo_id: string + @return: The underlying CORBA object for the device event listener + @rtype: Accessibility.EventListener + """ + if repo_id == utils.getInterfaceIID(Accessibility.EventListener): + return self._this() + else: + return None + + def notifyEvent(self, ev): + """ + Notifies the L{Registry} that an event has occurred. Wraps the raw event + object in our L{Event} class to support automatic ref and unref calls. + Aborts on any exception indicating the event could not be wrapped. + + @param ev: AT-SPI event signal (anything but keyboard) + @type ev: Accessibility.Event + """ + # wrap raw event so ref counts are correct before queueing + ev = event.Event(ev) + self.registry.handleEvent(ev) + +class Registry(object): + """ + Wraps the Accessibility.Registry to provide more Pythonic registration for + events. + + This object should be treated as a singleton, but such treatment is not + enforced. You can construct another instance of this object and give it a + reference to the Accessibility.Registry singleton. Doing so is harmless and + has no point. + + @ivar async: Should event dispatch to local listeners be decoupled from event + receiving from the registry? + @type async: boolean + @ivar reg: Reference to the real, wrapped registry object + @type reg: Accessibility.Registry + @ivar dev: Reference to the device controller + @type dev: Accessibility.DeviceEventController + @ivar queue: Queue of events awaiting local dispatch + @type queue: Queue.Queue + @ivar clients: Map of event names to client listeners + @type clients: dictionary + @ivar observers: Map of event names to AT-SPI L{_Observer} objects + @type observers: dictionary + """ + def __init__(self, reg): + """ + Stores a reference to the AT-SPI registry. Gets and stores a reference + to the DeviceEventController. + + @param reg: Reference to the AT-SPI registry daemon + @type reg: Accessibility.Registry + """ + self.async = None + self.reg = reg + self.dev = self.reg.getDeviceEventController() + self.queue = Queue.Queue() + self.clients = {} + self.observers = {} + + def __call__(self): + """ + @return: This instance of the registry + @rtype: L{Registry} + """ + return self + + def start(self, async=False, gil=True): + """ + Enter the main loop to start receiving and dispatching events. + + @param async: Should event dispatch be asynchronous (decoupled) from + event receiving from the AT-SPI registry? + @type async: boolean + @param gil: Add an idle callback which releases the Python GIL for a few + milliseconds to allow other threads to run? Necessary if other threads + will be used in this process. + @type gil: boolean + """ + self.async = async + + if gil: + def releaseGIL(): + try: + time.sleep(1e-5) + except KeyboardInterrupt, e: + # store the exception for later + releaseGIL.keyboard_exception = e + self.stop() + return True + # make room for an exception if one occurs during the + releaseGIL.keyboard_exception = None + i = gobject.idle_add(releaseGIL) + + # enter the main loop + try: + bonobo.main() + finally: + # clear all observers + for name, ob in self.observers.items(): + ob.unregister(self.reg, name) + if gil: + gobject.source_remove(i) + if releaseGIL.keyboard_exception is not None: + # raise an keyboard exception we may have gotten earlier + raise releaseGIL.keyboard_exception + + def stop(self, *args): + """Quits the main loop.""" + try: + bonobo.main_quit() + except RuntimeError: + # ignore errors when quitting (probably already quitting) + pass + self.flushEvents() + + def getDesktopCount(self): + """ + Gets the number of available desktops. + + @return: Number of desktops + @rtype: integer + @raise LookupError: When the count cannot be retrieved + """ + try: + return self.reg.getDesktopCount() + except Exception: + raise LookupError + + def getDesktop(self, i): + """ + Gets a reference to the i-th desktop. + + @param i: Which desktop to get + @type i: integer + @return: Desktop reference + @rtype: Accessibility.Desktop + @raise LookupError: When the i-th desktop cannot be retrieved + """ + try: + return self.reg.getDesktop(i) + except Exception, e: + raise LookupError(e) + + def registerEventListener(self, client, *names): + """ + Registers a new client callback for the given event names. Supports + registration for all subevents if only partial event name is specified. + Do not include a trailing colon. + + For example, 'object' will register for all object events, + 'object:property-change' will register for all property change events, + and 'object:property-change:accessible-parent' will register only for the + parent property change event. + + Registered clients will not be automatically removed when the client dies. + To ensure the client is properly garbage collected, call + L{deregisterEventListener}. + + @param client: Callable to be invoked when the event occurs + @type client: callable + @param names: List of full or partial event names + @type names: list of string + """ + for name in names: + # store the callback for each specific event name + self._registerClients(client, name) + + def deregisterEventListener(self, client, *names): + """ + Unregisters an existing client callback for the given event names. Supports + unregistration for all subevents if only partial event name is specified. + Do not include a trailing colon. + + This method must be called to ensure a client registered by + L{registerEventListener} is properly garbage collected. + + @param client: Client callback to remove + @type client: callable + @param names: List of full or partial event names + @type names: list of string + @return: Were event names specified for which the given client was not + registered? + @rtype: boolean + """ + missed = False + for name in names: + # remove the callback for each specific event name + missed |= self._unregisterClients(client, name) + return missed + + def registerKeystrokeListener(self, client, key_set=[], mask=0, + kind=(constants.KEY_PRESSED_EVENT, + constants.KEY_RELEASED_EVENT), + synchronous=True, preemptive=True, + global_=False): + """ + Registers a listener for key stroke events. + + @param client: Callable to be invoked when the event occurs + @type client: callable + @param key_set: Set of hardware key codes to stop monitoring. Leave empty + to indicate all keys. + @type key_set: list of integer + @param mask: When the mask is None, the codes in the key_set will be + monitored only when no modifier is held. When the mask is an + integer, keys in the key_set will be monitored only when the modifiers in + the mask are held. When the mask is an iterable over more than one + integer, keys in the key_set will be monitored when any of the modifier + combinations in the set are held. + @type mask: integer, iterable, None + @param kind: Kind of events to watch, KEY_PRESSED_EVENT or + KEY_RELEASED_EVENT. + @type kind: list + @param synchronous: Should the callback notification be synchronous, giving + the client the chance to consume the event? + @type synchronous: boolean + @param preemptive: Should the callback be allowed to preempt / consume the + event? + @type preemptive: boolean + @param global_: Should callback occur even if an application not supporting + AT-SPI is in the foreground? (requires xevie) + @type global_: boolean + """ + try: + # see if we already have an observer for this client + ob = self.clients[client] + except KeyError: + # create a new device observer for this client + ob = _DeviceObserver(self, synchronous, preemptive, global_) + # store the observer to client mapping, and the inverse + self.clients[ob] = client + self.clients[client] = ob + if mask is None: + # None means all modifier combinations + mask = utils.allModifiers() + # register for new keystrokes on the observer + ob.register(self.dev, key_set, mask, kind) + + def deregisterKeystrokeListener(self, client, key_set=[], mask=0, + kind=(constants.KEY_PRESSED_EVENT, + constants.KEY_RELEASED_EVENT)): + """ + Deregisters a listener for key stroke events. + + @param client: Callable to be invoked when the event occurs + @type client: callable + @param key_set: Set of hardware key codes to stop monitoring. Leave empty + to indicate all keys. + @type key_set: list of integer + @param mask: When the mask is None, the codes in the key_set will be + monitored only when no modifier is held. When the mask is an + integer, keys in the key_set will be monitored only when the modifiers in + the mask are held. When the mask is an iterable over more than one + integer, keys in the key_set will be monitored when any of the modifier + combinations in the set are held. + @type mask: integer, iterable, None + @param kind: Kind of events to stop watching, KEY_PRESSED_EVENT or + KEY_RELEASED_EVENT. + @type kind: list + @raise KeyError: When the client isn't already registered for events + """ + # see if we already have an observer for this client + ob = self.clients[client] + if mask is None: + # None means all modifier combinations + mask = utils.allModifiers() + # register for new keystrokes on the observer + ob.unregister(self.dev, key_set, mask, kind) + + def generateKeyboardEvent(self, keycode, keysym, kind): + """ + Generates a keyboard event. One of the keycode or the keysym parameters + should be specified and the other should be None. The kind parameter is + required and should be one of the KEY_PRESS, KEY_RELEASE, KEY_PRESSRELEASE, + KEY_SYM, or KEY_STRING. + + @param keycode: Hardware keycode or None + @type keycode: integer + @param keysym: Symbolic key string or None + @type keysym: string + @param kind: Kind of event to synthesize + @type kind: integer + """ + if keysym is None: + self.dev.generateKeyboardEvent(keycode, '', kind) + else: + self.dev.generateKeyboardEvent(None, keysym, kind) + + def generateMouseEvent(self, x, y, name): + """ + Generates a mouse event at the given absolute x and y coordinate. The kind + of event generated is specified by the name. For example, MOUSE_B1P + (button 1 press), MOUSE_REL (relative motion), MOUSE_B3D (butten 3 + double-click). + + @param x: Horizontal coordinate, usually left-hand oriented + @type x: integer + @param y: Vertical coordinate, usually left-hand oriented + @type y: integer + @param name: Name of the event to generate + @type name: string + """ + self.dev.generateMouseEvent(x, y, name) + + def handleDeviceEvent(self, event, ob): + """ + Dispatches L{event.DeviceEvent}s to registered clients. Clients are called + in the order they were registered for the given AT-SPI event. If any + client returns True, callbacks cease for the event for clients of this registry + instance. Clients of other registry instances and clients in other processes may + be affected depending on the values of synchronous and preemptive used when invoking + L{registerKeystrokeListener}. + + @note: Asynchronous dispatch of device events is not supported. + + @param event: AT-SPI device event + @type event: L{event.DeviceEvent} + @param ob: Observer that received the event + @type ob: L{_DeviceObserver} + + @return: Should the event be consumed (True) or allowed to pass on to other + AT-SPI observers (False)? + @rtype: boolean + """ + try: + # try to get the client registered for this event type + client = self.clients[ob] + except KeyError: + # client may have unregistered recently, ignore event + return False + # make the call to the client + try: + return client(event) or event.consume + except Exception: + # print the exception, but don't let it stop notification + traceback.print_exc() + + def handleEvent(self, event): + """ + Handles an AT-SPI event by either queuing it for later dispatch when the + L{Registry.async} flag is set, or dispatching it immediately. + + @param event: AT-SPI event + @type event: L{event.Event} + """ + if self.async: + # queue for now + self.queue.put_nowait(event) + else: + # dispatch immediately + self._dispatchEvent(event) + + def _dispatchEvent(self, event): + """ + Dispatches L{event.Event}s to registered clients. Clients are called in + the order they were registered for the given AT-SPI event. If any client + returns True, callbacks cease for the event for clients of this registry + instance. Clients of other registry instances and clients in other processes + are unaffected. + + @param event: AT-SPI event + @type event: L{event.Event} + """ + et = event.type + try: + # try to get the client registered for this event type + clients = self.clients[et.name] + except KeyError: + try: + # we may not have registered for the complete subtree of events + # if our tree does not list all of a certain type (e.g. + # object:state-changed:*); try again with klass and major only + if et.detail is not None: + # Strip the 'detail' field. + clients = self.clients['%s:%s:%s' % (et.klass, et.major, et.minor)] + elif et.minor is not None: + # The event could possibly be object:state-changed:*. + clients = self.clients['%s:%s' % (et.klass, et.major)] + except KeyError: + # client may have unregistered recently, ignore event + return + # make the call to each client + consume = False + for client in clients: + try: + consume = client(event) or False + except Exception: + # print the exception, but don't let it stop notification + traceback.print_exc() + if consume or event.consume: + # don't allow further processing if a client returns True + break + + def flushEvents(self): + """ + Flushes the event queue by destroying it and recreating it. + """ + self.queue = Queue.Queue() + + def pumpQueuedEvents(self, num=-1): + """ + Provides asynch processing of events in the queue by executeing them with + _dispatchEvent() (as is done immediately when synch processing). + This method would normally be called from a main loop or idle function. + + @param num: Number of events to pump. If number is negative it pumps + the entire queue. Default is -1. + @type num: integer + @return: True if queue is not empty after events were pumped. + @rtype: boolean + """ + if num < 0: + # Dequeue as many events as currently in the queue. + num = self.queue.qsize() + for i in xrange(num): + try: + # get next waiting event + event = self.queue.get_nowait() + except Queue.Empty: + break + self._dispatchEvent(event) + + return not self.queue.empty() + + def _registerClients(self, client, name): + """ + Internal method that recursively associates a client with AT-SPI event + names. Allows a client to incompletely specify an event name in order to + register for subevents without specifying their full names manually. + + @param client: Client callback to receive event notifications + @type client: callable + @param name: Partial or full event name + @type name: string + """ + try: + # look for an event name in our event tree dictionary + events = constants.EVENT_TREE[name] + except KeyError: + # if the event name doesn't exist, it's a leaf event meaning there are + # no subtypes for that event + # add this client to the list of clients already in the dictionary + # using the event name as the key; if there are no clients yet for this + # event, insert an empty list into the dictionary before appending + # the client + et = event.EventType(name) + clients = self.clients.setdefault(et.name, []) + try: + # if this succeeds, this client is already registered for the given + # event type, so ignore the request + clients.index(client) + except ValueError: + # else register the client + clients.append(client) + self._registerObserver(name) + else: + # if the event name does exist in the tree, there are subevents for + # this event; loop through them calling this method again to get to + # the leaf events + for e in events: + self._registerClients(client, e) + + def _unregisterClients(self, client, name): + """ + Internal method that recursively unassociates a client with AT-SPI event + names. Allows a client to incompletely specify an event name in order to + unregister for subevents without specifying their full names manually. + + @param client: Client callback to receive event notifications + @type client: callable + @param name: Partial or full event name + @type name: string + """ + missed = False + try: + # look for an event name in our event tree dictionary + events = constants.EVENT_TREE[name] + except KeyError: + try: + # if the event name doesn't exist, it's a leaf event meaning there are + # no subtypes for that event + # get the list of registered clients and try to remove the one provided + et = event.EventType(name) + clients = self.clients[et.name] + clients.remove(client) + self._unregisterObserver(name) + except (ValueError, KeyError): + # ignore any exceptions indicating the client is not registered + missed = True + return missed + # if the event name does exist in the tree, there are subevents for this + # event; loop through them calling this method again to get to the leaf + # events + for e in events: + missed |= self._unregisterClients(client, e) + return missed + + def _registerObserver(self, name): + """ + Creates a new L{_Observer} to watch for events of the given type or + returns the existing observer if one is already registered. One + L{_Observer} is created for each leaf in the L{constants.EVENT_TREE} or + any event name not found in the tree. + + @param name: Raw name of the event to observe + @type name: string + @return: L{_Observer} object that is monitoring the event + @rtype: L{_Observer} + """ + et = event.EventType(name) + try: + # see if an observer already exists for this event + ob = self.observers[et.name] + except KeyError: + # build a new observer if one does not exist + ob = _EventObserver(self) + # we have to register for the raw name because it may be different from + # the parsed name determined by EventType (e.g. trailing ':' might be + # missing) + ob.register(self.reg, name) + self.observers[et.name] = ob + # increase our client ref count so we know someone new is watching for the + # event + ob.clientRef() + return ob + + def _unregisterObserver(self, name): + """ + Destroys an existing L{_Observer} for the given event type only if no + clients are registered for the events it is monitoring. + + @param name: Name of the event to observe + @type name: string + @raise KeyError: When an observer for the given event is not regist + """ + et = event.EventType(name) + # see if an observer already exists for this event + ob = self.observers[et.name] + ob.clientUnref() + if ob.getClientRefCount() == 0: + ob.unregister(self.reg, name) + del self.observers[et.name]