1 #Copyright (C) 2008 Codethink Ltd
2 #copyright: Copyright (c) 2005, 2007 IBM Corporation
4 #This library is free software; you can redistribute it and/or
5 #modify it under the terms of the GNU Lesser General Public
6 #License version 2 as published by the Free Software Foundation.
8 #This program is distributed in the hope that it will be useful,
9 #but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 #GNU General Public License for more details.
12 #You should have received a copy of the GNU Lesser General Public License
13 #along with this program; if not, write to the Free Software
14 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 #Portions of this code originally licensed and copyright (c) 2005, 2007
17 #IBM Corporation under the BSD license, available at
18 #U{http://www.opensource.org/licenses/bsd-license.php}
20 #authors: Peter Parente, Mark Doffman
22 #TODO Re-implement and import the stateset server
24 def getInterfaceIID(obj):
26 Gets the ID of an interface class or object in string format for use in
29 @param obj: Class representing an AT-SPI interface or instance
31 @return: IID for the interface
33 @raise AttributeError: When the parameter does not provide typecode info
35 WARNING!! DEPRECATED!!
37 In current D-Bus version of pyatspi this simply returns a null string.
41 def getInterfaceName(obj):
43 Gets the human readable name of an interface class or object in string
46 @param obj: Class representing an AT-SPI interface or instance
48 @return: Name of the interface
50 @raise AttributeError: When the parameter does not provide typecode info
52 return obj._dbus_interface.lstrip("org.freedesktop.atspi.")
54 # we're importing here to avoid cyclic importants; constants relies on the
58 def listInterfaces(obj):
60 Gets a list of the names of all interfaces supported by this object. The
61 names are the short-hand interface names like "Accessible" and "Component",
62 not the full interface identifiers.
64 @param obj: Arbitrary object to query for all accessibility related
65 interfaces. Must provide a queryInterface method.
67 @return: Set of supported interface names
69 @raise AttributeError: If the object provide does not implement
72 return [itf.lstrip("org.freedesktop.atspi.") for itf in obj.interfaces]
74 def stringToConst(prefix, suffix):
76 Maps a string name to an AT-SPI constant. The rules for the mapping are as
78 - The prefix is captalized and has an _ appended to it.
79 - All spaces in the suffix are mapped to the _ character.
80 - All alpha characters in the suffix are mapped to their uppercase.
82 The resulting name is used with getattr to look up a constant with that name
83 in the L{constants} module. If such a constant does not exist, the string
84 suffix is returned instead.
86 This method allows strings to be used to refer to roles, relations, etc.
87 without direct access to the constants. It also supports the future expansion
88 of roles, relations, etc. by allowing arbitrary strings which may or may not
89 map to the current standard set of roles, relations, etc., but may still
90 match some non-standard role, relation, etc. being reported by an
93 @param prefix: Prefix of the constant name such as role, relation, state,
96 @param suffix: Name of the role, relation, etc. to use to lookup the constant
98 @return: The matching constant value
101 name = prefix.upper()+'_'+suffix.upper().replace(' ', '_')
102 return getattr(constants, name, suffix)
104 def stateToString(value):
106 Converts a state value to a string based on the name of the state constant in
107 the L{constants} module that has the given value.
109 @param value: An AT-SPI state
110 @type value: Accessibility.StateType
111 @return: Human readable, untranslated name of the state
114 return constants.STATE_VALUE_TO_NAME.get(value)
116 def relationToString(value):
118 Converts a relation value to a string based on the name of the state constant
119 in the L{constants} module that has the given value.
121 @param value: An AT-SPI relation
122 @type value: Accessibility.RelationType
123 @return: Human readable, untranslated name of the relation
126 return constants.RELATION_VALUE_TO_NAME.get(value)
130 Generates all possible keyboard modifiers for use with
131 L{registry.Registry.registerKeystrokeListener}.
134 while mask <= (1 << constants.MODIFIER_NUMLOCK):
138 def findDescendant(acc, pred, breadth_first=False):
140 Searches for a descendant node satisfying the given predicate starting at
141 this node. The search is performed in depth-first order by default or
142 in breadth first order if breadth_first is True. For example,
144 my_win = findDescendant(lambda x: x.name == 'My Window')
146 will search all descendants of x until one is located with the name 'My
147 Window' or all nodes are exausted. Calls L{_findDescendantDepth} or
148 L{_findDescendantBreadth} to start the recursive search.
150 @param acc: Root accessible of the search
151 @type acc: Accessibility.Accessible
152 @param pred: Search predicate returning True if accessible matches the
153 search criteria or False otherwise
155 @param breadth_first: Search breadth first (True) or depth first (False)?
156 @type breadth_first: boolean
157 @return: Accessible matching the criteria or None if not found
158 @rtype: Accessibility.Accessible or None
161 return _findDescendantBreadth(acc, pred)
165 ret = _findDescendantDepth(acc, pred)
168 if ret is not None: return ret
170 def _findDescendantBreadth(acc, pred):
172 Internal function for locating one descendant. Called by L{findDescendant} to
175 @param acc: Root accessible of the search
176 @type acc: Accessibility.Accessible
177 @param pred: Search predicate returning True if accessible matches the
178 search criteria or False otherwise
180 @return: Matching node or None to keep searching
181 @rtype: Accessibility.Accessible or None
185 if pred(child): return child
190 ret = _findDescendantBreadth(child, pred)
193 if ret is not None: return ret
195 def _findDescendantDepth(acc, pred):
197 Internal function for locating one descendant. Called by L{findDescendant} to
200 @param acc: Root accessible of the search
201 @type acc: Accessibility.Accessible
202 @param pred: Search predicate returning True if accessible matches the
203 search criteria or False otherwise
205 @return: Matching node or None to keep searching
206 @rtype: Accessibility.Accessible or None
209 if pred(acc): return acc
214 ret = _findDescendantDepth(child, pred)
217 if ret is not None: return ret
219 def findAllDescendants(acc, pred):
221 Searches for all descendant nodes satisfying the given predicate starting at
222 this node. Does an in-order traversal. For example,
224 pred = lambda x: x.getRole() == pyatspi.ROLE_PUSH_BUTTON
225 buttons = pyatspi.findAllDescendants(node, pred)
227 will locate all push button descendants of node.
229 @param acc: Root accessible of the search
230 @type acc: Accessibility.Accessible
231 @param pred: Search predicate returning True if accessible matches the
232 search criteria or False otherwise
234 @return: All nodes matching the search criteria
238 _findAllDescendants(acc, pred, matches)
241 def _findAllDescendants(acc, pred, matches):
243 Internal method for collecting all descendants. Reuses the same matches
244 list so a new one does not need to be built on each recursive step.
248 if pred(child): matches.append(child)
251 _findAllDescendants(child, pred, matches)
253 def findAncestor(acc, pred):
255 Searches for an ancestor satisfying the given predicate. Note that the
256 AT-SPI hierarchy is not always doubly linked. Node A may consider node B its
257 child, but B is not guaranteed to have node A as its parent (i.e. its parent
258 may be set to None). This means some searches may never make it all the way
259 up the hierarchy to the desktop level.
261 @param acc: Starting accessible object
262 @type acc: Accessibility.Accessible
263 @param pred: Search predicate returning True if accessible matches the
264 search criteria or False otherwise
266 @return: Node matching the criteria or None if not found
267 @rtype: Accessibility.Accessible
270 # guard against bad start condition
273 if acc.parent is None:
274 # stop if there is no parent and we haven't returned yet
277 if pred(acc.parent): return acc.parent
285 Gets the path from the application ancestor to the given accessible in
286 terms of its child index at each level.
288 @param acc: Target accessible
289 @type acc: Accessibility.Accessible
290 @return: Path to the target
291 @rtype: list of integer
292 @raise LookupError: When the application accessible cannot be reached
296 if acc.parent is None:
300 path.append(acc.getIndexInParent())