3
3
All the classes here are intended to be single-instance, except for Action.
5
5
__author__ = 'Zack Cerza <zcerza@redhat.com>'
6
##############################################################################
8
# WARNING: Here There Be Dragons (TM) #
10
# If you don't understand how to use this API, you almost certainly don't #
11
# want to read the code first. We make use of some very non-intuitive #
12
# features of Python in order to make the API very simplistic. Therefore, #
13
# you should probably only read this code if you're already familiar with #
14
# some of Python's advanced features. You have been warned. ;) #
16
##############################################################################
8
from predicate import GenericPredicate, IsADialogNamed
19
from predicate import GenericPredicate, IsADialogNamed, IsAnApplicationNamed
9
20
from config import config
10
22
from time import sleep
12
24
#FocusError = "FocusError: %s not found"
13
25
class FocusError(Exception):
30
errors.warn('The requested object was not found')
16
32
ENOARGS = "At least one argument is needed"
20
The base for every class in the module. Does nothing special, really.
22
def __getattr__ (self, name):
23
# Fold all the Node's AT-SPI properties into the Focus object.
24
try: return getattr(self.node, name)
25
except AttributeError: raise AttributeError, name
27
def __setattr__ (self, name, value):
28
# Fold all the Node's AT-SPI properties into the Focus object.
30
self.__dict__[name] = value
32
try: setattr(self.node, name, value)
33
except AttributeError: raise AttributeError, name
36
The base for every class in the module. Does nothing special, really.
40
def __getattr__ (self, name):
41
# Fold all the Node's AT-SPI properties into the Focus object.
42
try: return getattr(self.node, name)
43
except AttributeError:
44
raise AttributeError, name
46
def __setattr__ (self, name, value):
47
# Fold all the Node's AT-SPI properties into the Focus object.
49
self.__dict__[name] = value
51
try: setattr(self.node, name, value)
52
except AttributeError:
53
raise AttributeError, name
35
55
class FocusApplication (FocusBase):
37
Keeps track of which application is currently focused.
40
def __call__ (self, name = '', description = ''):
42
If name or description are specified, search for an application that matches and refocus on it.
44
if not name and not description:
45
raise TypeError, ENOARGS
46
# search for an application.
48
for app in self.desktop.children:
49
nameMatch = app.name == name
50
descriptionMatch = app.description == description
51
if nameMatch and descriptionMatch:
52
FocusApplication.node = app
53
FocusDialog.node = None
54
FocusWidget.node = None
57
if not matched: raise FocusError, name
57
Keeps track of which application is currently focused.
60
def __call__ (self, name):
62
Search for an application that matches and refocus on the given name.
65
predicate = IsAnApplicationNamed(name)
66
app = self.desktop.findChild(predicate, recursive = False, retry = False)
67
except tree.SearchError, desc:
68
if config.fatalErrors: raise FocusError, name
73
FocusApplication.node = app
74
FocusDialog.node = None
75
FocusWidget.node = None
59
77
class FocusDesktop (FocusBase):
61
This isn't used yet, and may never be used.
79
This isn't used yet, and may never be used.
65
83
class FocusDialog (FocusBase):
67
Keeps track of which dialog is currently focused.
69
def __call__ (self, name = '', description = ''):
71
If name or description are specified, search for a dialog that matches and refocus on it.
73
if not name and not description:
74
raise TypeError, ENOARGS
77
result = FocusApplication.node.findChild(IsADialogNamed(name), requireResult=False, recursive = False)
78
except AttributeError: pass
80
FocusDialog.node = result
81
FocusWidget.node = None
82
else: raise FocusError, name
85
Keeps track of which dialog is currently focused.
87
def __call__ (self, name):
89
Search for a dialog that matches the given name and refocus on it.
92
predicate = IsADialogNamed(name)
94
result = FocusApplication.node.findChild(predicate, requireResult=False, recursive = False)
95
except AttributeError: pass
97
FocusDialog.node = result
98
FocusWidget.node = None
100
if config.fatalErrors: raise FocusError, predicate.debugName
84
105
class FocusWidget (FocusBase):
86
Keeps track of which widget is currently focused.
88
def __call__ (self, name = '', roleName = '', description = ''):
90
If name, roleName or description are specified, search for a widget that matches and refocus on it.
92
if not name and not roleName and not description:
93
raise TypeError, ENOARGS
95
# search for a widget.
98
result = FocusWidget.node.findChild(GenericPredicate(name = name, roleName = roleName, description = description), requireResult = False, retry = False)
99
except AttributeError: pass
100
if result: FocusWidget.node = result
103
result = FocusDialog.node.findChild(GenericPredicate(name = name, roleName = roleName, description = description), requireResult = False, retry = False)
104
except AttributeError: pass
105
if result: FocusWidget.node = result
108
result = FocusApplication.node.findChild(GenericPredicate(name = name, roleName = roleName, description = description), requireResult = False, retry = False)
109
if result: FocusWidget.node = result
110
except AttributeError: raise FocusError, name
113
FocusWidget.node = result
114
raise FocusError, name
107
Keeps track of which widget is currently focused.
109
def __call__ (self, name = '', roleName = '', description = ''):
111
If name, roleName or description are specified, search for a widget that matches and refocus on it.
113
if not name and not roleName and not description:
114
raise TypeError, ENOARGS
116
# search for a widget.
118
predicate = GenericPredicate(name = name, roleName = roleName, description = description)
120
result = FocusWidget.node.findChild(predicate, requireResult = False, retry = False)
121
except AttributeError: pass
122
if result: FocusWidget.node = result
125
result = FocusDialog.node.findChild(predicate, requireResult = False, retry = False)
126
except AttributeError: pass
127
if result: FocusWidget.node = result
130
result = FocusApplication.node.findChild(predicate, requireResult = False, retry = False)
131
if result: FocusWidget.node = result
132
except AttributeError:
133
if config.fatalErrors: raise FocusError, name
139
FocusWidget.node = result
140
if config.fatalErrors: raise FocusError, predicate.debugName
116
145
class Focus (FocusBase):
118
The container class for the focused application, dialog and widget.
121
def __getattr__ (self, name):
122
raise AttributeError, name
123
def __setattr__(self, name, value):
124
if name in ('application', 'dialog', 'widget'):
125
self.__dict__[name] = value
127
raise AttributeError, name
130
application = FocusApplication()
131
app = application # shortcut :)
132
dialog = FocusDialog()
133
widget = FocusWidget()
135
def button (self, name):
137
A shortcut to self.widget(name, roleName = 'push button')
139
self.widget(name = name, roleName = 'push button')
141
def frame (self, name):
143
A shortcut to self.widget(name, roleName = 'frame')
145
self.widget(name = name, roleName = 'frame')
147
def icon (self, name):
149
A shortcut to self.widget(name, roleName = 'icon')
151
self.widget(name = name, roleName = 'icon')
153
def menu (self, name):
155
A shortcut to self.widget(name, roleName = 'menu')
157
self.widget(name = name, roleName = 'menu')
159
def menuItem (self, name):
161
A shortcut to self.widget(name, roleName = 'menu item')
163
self.widget(name = name, roleName = 'menu item')
165
def table (self, name = ''):
167
A shortcut to self.widget(name, roleName 'table')
169
self.widget(name = name, roleName = 'table')
171
def tableCell (self, name = ''):
173
A shortcut to self.widget(name, roleName 'table cell')
175
self.widget(name = name, roleName = 'table cell')
177
def text (self, name = ''):
179
A shortcut to self.widget(name, roleName = 'text')
181
self.widget(name = name, roleName = 'text')
183
def window (self, name):
185
A shortcut to self.widget(name, roleName = 'window')
187
self.widget(name = name, roleName = 'window')
147
The container class for the focused application, dialog and widget.
150
def __getattr__ (self, name):
151
raise AttributeError, name
152
def __setattr__(self, name, value):
153
if name in ('application', 'dialog', 'widget'):
154
self.__dict__[name] = value
156
raise AttributeError, name
159
application = FocusApplication()
160
app = application # shortcut :)
161
dialog = FocusDialog()
162
widget = FocusWidget()
164
def button (self, name):
166
A shortcut to self.widget(name, roleName = 'push button')
168
self.widget(name = name, roleName = 'push button')
170
def frame (self, name):
172
A shortcut to self.widget(name, roleName = 'frame')
174
self.widget(name = name, roleName = 'frame')
176
def icon (self, name):
178
A shortcut to self.widget(name, roleName = 'icon')
180
self.widget(name = name, roleName = 'icon')
182
def menu (self, name):
184
A shortcut to self.widget(name, roleName = 'menu')
186
self.widget(name = name, roleName = 'menu')
188
def menuItem (self, name):
190
A shortcut to self.widget(name, roleName = 'menu item')
192
self.widget(name = name, roleName = 'menu item')
194
def table (self, name = ''):
196
A shortcut to self.widget(name, roleName 'table')
198
self.widget(name = name, roleName = 'table')
200
def tableCell (self, name = ''):
202
A shortcut to self.widget(name, roleName 'table cell')
204
self.widget(name = name, roleName = 'table cell')
206
def text (self, name = ''):
208
A shortcut to self.widget(name, roleName = 'text')
210
self.widget(name = name, roleName = 'text')
212
def window (self, name):
214
A shortcut to self.widget(name, roleName = 'window')
216
self.widget(name = name, roleName = 'window')
189
218
class Action (FocusWidget):
191
Aids in executing AT-SPI actions, refocusing the widget if necessary.
193
def __init__ (self, action):
195
action is a string with the same name as the AT-SPI action you wish to execute using this class.
199
def __call__ (self, name = '', roleName = '', description = '', delay = config.actionDelay):
201
If name, roleName or description are specified, first search for a widget that matches and refocus on it.
202
Then execute the action.
204
if name or roleName or description:
205
FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
206
self.node.doAction(self.action)
209
def __getattr__ (self, attr):
210
return getattr(FocusWidget.node, attr)
212
def __setattr__ (self, attr, value):
214
self.__dict__[attr] = value
215
else: setattr(FocusWidget, attr, value)
217
def button (self, name):
219
A shortcut to self(name, roleName = 'push button')
221
self.__call__(name = name, roleName = 'push button')
223
def menu (self, name):
225
A shortcut to self(name, roleName = 'menu')
227
self.__call__(name = name, roleName = 'menu')
229
def menuItem (self, name):
231
A shortcut to self(name, roleName = 'menu item')
233
self.__call__(name = name, roleName = 'menu item')
235
def table (self, name = ''):
237
A shortcut to self(name, roleName 'table')
239
self.__call__(name = name, roleName = 'table')
241
def tableCell (self, name = ''):
243
A shortcut to self(name, roleName 'table cell')
245
self.__call__(name = name, roleName = 'table cell')
247
def text (self, name = ''):
249
A shortcut to self(name, roleName = 'text')
251
self.__call__(name = name, roleName = 'text')
220
Aids in executing AT-SPI actions, refocusing the widget if necessary.
222
def __init__ (self, action):
224
action is a string with the same name as the AT-SPI action you wish to execute using this class.
228
def __call__ (self, name = '', roleName = '', description = '', delay = config.actionDelay):
230
If name, roleName or description are specified, first search for a widget that matches and refocus on it.
231
Then execute the action.
233
if name or roleName or description:
234
FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
235
self.node.doAction(self.action)
238
def __getattr__ (self, attr):
239
return getattr(FocusWidget.node, attr)
241
def __setattr__ (self, attr, value):
243
self.__dict__[attr] = value
244
else: setattr(FocusWidget, attr, value)
246
def button (self, name):
248
A shortcut to self(name, roleName = 'push button')
250
self.__call__(name = name, roleName = 'push button')
252
def menu (self, name):
254
A shortcut to self(name, roleName = 'menu')
256
self.__call__(name = name, roleName = 'menu')
258
def menuItem (self, name):
260
A shortcut to self(name, roleName = 'menu item')
262
self.__call__(name = name, roleName = 'menu item')
264
def table (self, name = ''):
266
A shortcut to self(name, roleName 'table')
268
self.__call__(name = name, roleName = 'table')
270
def tableCell (self, name = ''):
272
A shortcut to self(name, roleName 'table cell')
274
self.__call__(name = name, roleName = 'table cell')
276
def text (self, name = ''):
278
A shortcut to self(name, roleName = 'text')
280
self.__call__(name = name, roleName = 'text')
253
282
class Click (Action):
255
A special case of Action, Click will eventually handle raw mouse events.
261
Action.__init__(self, 'click')
263
def __call__ (self, name = '', roleName = '', description = '', raw = False, button = primary, delay = config.actionDelay):
265
If coords or button are specified, execute a raw mouse event. If not, just pass the rest of the arguments to Action.
268
# We're doing a raw mouse click
269
FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
270
Click.node.rawClick(button)
273
Action.__call__(self, name = name, roleName = roleName, description = description, delay = delay)
284
A special case of Action, Click will eventually handle raw mouse events.
290
Action.__init__(self, 'click')
292
def __call__ (self, name = '', roleName = '', description = '', raw = False, button = primary, delay = config.actionDelay):
294
If coords or button are specified, execute a raw mouse event. If not, just pass the rest of the arguments to Action.
297
# We're doing a raw mouse click
298
FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
299
Click.node.rawClick(button)
302
Action.__call__(self, name = name, roleName = roleName, description = description, delay = delay)
304
class Select (Action):
306
Aids in selecting and deselecting widgets, i.e. page tabs
309
deselect = 'deselect'
310
def __init__(self, action):
312
action must be 'select' or 'deselect'.
314
if action not in (self.select, self.deselect):
315
raise ValueError, action
316
Action.__init__(self, action)
318
def __call__ (self, name = '', roleName = '', description = '', delay = config.actionDelay):
320
If name, roleName or description are specified, first search for a widget that matches and refocus on it.
321
Then execute the action.
323
if name or roleName or description:
324
FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
325
func = getattr(self.node, self.action)
330
if focus.widget.node:
331
focus.widget.node.typeText(text)
333
rawinput.typeText(text)
336
if focus.widget.node:
337
focus.widget.node.keyCombo(combo)
339
rawinput.keyCombo(combo)
275
341
def run(application, arguments = '', appName = ''):
276
from utils import run as utilsRun
277
utilsRun(application + arguments, appName = appName)
278
focus.application(application)
342
from utils import run as utilsRun
343
utilsRun(application + arguments, appName = appName)
344
focus.application(application)
283
348
activate = Action('activate')
284
349
openItem = Action('open')
285
350
menu = Action('menu')
351
select = Select(Select.select)
352
deselect = Select(Select.deselect)