4
@author: Eitan Isaacson <eitan@ascender.com>
5
@author: Nagappan Alagappan <nagappan@gmail.com>
6
@copyright: Copyright (c) 2009 Eitan Isaacson
7
@copyright: Copyright (c) 2009 Nagappan Alagappan
10
http://ldtp.freedesktop.org
12
This file may be distributed and/or modified under the terms of the GNU General
13
Public License version 2 as published by the Free Software Foundation. This file
14
is distributed without any warranty; without even the implied warranty of
15
merchantability or fitness for a particular purpose.
17
See "COPYING" in the source distribution for more information.
19
Headers in this file shall remain intact.
22
from pyatspi import findDescendant, Registry
25
from utils import Utils
26
from constants import abbreviated_roles
27
from waiters import ObjectExistsWaiter, GuiExistsWaiter, \
28
GuiNotExistsWaiter, ObjectNotExistsWaiter, NullWaiter, \
29
MaximizeWindow, MinimizeWindow, UnmaximizeWindow, UnminimizeWindow, \
30
ActivateWindow, CloseWindow
31
from server_exception import LdtpServerException
37
from fnmatch import translate as glob_trans
41
from mouse import Mouse
42
from table import Table
43
from value import Value
44
from generic import Generic
45
from combo_box import ComboBox
46
from page_tab_list import PageTabList
48
class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList,
49
Text, Mouse, Generic, Value):
56
self._get_all_state_names()
57
# Window up time and onwindowcreate events
58
self._events = ["window:create", "window:destroy"]
59
# User registered events
60
self._registered_events = []
61
pyatspi.Registry.registerEventListener(self._event_cb, *self._events)
64
pyatspi.Registry.deregisterEventListener(self._event_cb, *self._events)
65
pyatspi.Registry.deregisterEventListener(self._registered_event_cb,
66
*self._registered_events)
68
def _registered_event_cb(self, event):
69
if event and event.source and event.type:
70
abbrev_role, abbrev_name = self._ldtpize_accessible(event.source)
71
window_name = u'%s%s' % (abbrev_role, abbrev_name)
72
self._callback_event.append(u"%s-%s" % (event.type, window_name))
74
def _event_cb(self, event):
75
if event and event.type == "window:create":
76
for window in self._callback:
77
if event and event.source and window and \
78
self._match_name_to_acc(window, event.source):
79
self._callback_event.append(u"onwindowcreate-%s" % window)
80
abbrev_role, abbrev_name = self._ldtpize_accessible(event.source)
81
win_name = u'%s%s' % (abbrev_role, abbrev_name)
82
self._window_uptime[win_name] = [event.source_name,
83
time.strftime("%Y %m %d %H %M %S")]
84
elif event and event.type == "window:destroy":
85
abbrev_role, abbrev_name = self._ldtpize_accessible(event.source)
86
win_name = u'%s%s' % (abbrev_role, abbrev_name)
87
if win_name in self._window_uptime:
88
self._window_uptime[win_name].append( \
89
time.strftime("%Y %m %d %H %M %S"))
93
Get all accessibility application name that are currently running
95
@return: list of appliction name of string type on success.
99
for app in self._list_apps():
100
if app.name != '<unknown>':
101
app_list.append(app.name)
104
def getwindowlist(self):
106
Get all accessibility window that are currently open
108
@return: list of window names in LDTP format of string type on success.
113
for gui in self._list_guis():
114
window_name = self._ldtpize_accessible(gui)
115
if window_name[1] == '':
116
if window_name[0] in window_type:
117
window_type[window_name[0]] += 1
119
window_type[window_name[0]] = 0
120
tmp_name = '%d' % window_type[window_name[0]]
122
tmp_name = window_name[1]
123
w_name = window_name = '%s%s' % (window_name[0], tmp_name)
125
while window_name in window_list:
126
window_name = '%s%d' % (w_name, index)
128
window_list.append(window_name)
134
def _get_all_state_names(self):
136
This is used by client internally to populate all states
139
for state in pyatspi.STATE_VALUE_TO_NAME.keys():
140
self._states[state.__repr__()] = state
143
def launchapp(self, cmd, args=[], delay = 5, env = 1):
147
@param cmdline: Command line string to execute.
148
@type cmdline: string
149
@param args: Arguments to the application
151
@param delay: Delay after the application is launched
153
@param env: GNOME accessibility environment to be set or not
156
@return: PID of new process
159
@raise LdtpServerException: When command fails
161
os.environ['NO_GAIL'] = '0'
162
os.environ['NO_AT_BRIDGE'] = '0'
164
os.environ['GTK_MODULES'] = 'gail:atk-bridge'
165
os.environ['GNOME_ACCESSIBILITY'] = '1'
167
process = subprocess.Popen([cmd]+args, close_fds = True)
168
# Let us wait so that the application launches
170
time.sleep(int(delay))
174
raise LdtpServerException(str(e))
175
os.environ['NO_GAIL'] = '1'
176
os.environ['NO_AT_BRIDGE'] = '1'
179
def poll_events(self):
181
Poll for any registered events or window create events
187
if not self._callback_event:
190
return self._callback_event.pop()
192
def windowuptime(self, window_name):
196
@param window_name: Window name to look for, either full name,
197
LDTP's name convention, or a Unix glob.
198
@type window_name: string
200
@return: "starttime - endtime" in string format
201
ex: '2010 01 12 14 21 13 - 2010 01 12 14 23 05'
205
if window_name in self._window_uptime and \
206
len(self._window_uptime[window_name]) == 3:
207
return '%s-%s' % (self._window_uptime[window_name][1],
208
self._window_uptime[window_name][2])
209
for window in self._window_uptime:
210
if re.match(glob_trans(window_name), window,
211
re.M | re.U | re.L) or \
212
re.match(glob_trans(window_name),
213
self._window_uptime[window][0],
215
return '%s-%s' % (self._window_uptime[window][1],
216
self._window_uptime[window][2])
219
def onwindowcreate(self, window_name):
221
Raise event on window create
223
@param window_name: Window name to look for, either full name,
224
LDTP's name convention, or a Unix glob.
225
@type window_name: string
227
@return: 1 if registration was successful, 0 if not.
231
self._callback[window_name] = window_name
235
def removecallback(self, window_name):
237
Remove callback of window create
239
@param window_name: Window name to look for, either full name,
240
LDTP's name convention, or a Unix glob.
241
@type window_name: string
243
@return: 1 if remove was successful, 0 if not.
247
if window_name in self._callback:
248
del self._callback[window_name]
252
def registerevent(self, event_name):
254
Register at-spi event
256
@param event_name: Event name in at-spi format.
257
@type event_name: string
259
@return: 1 if registration was successful, 0 if not.
263
pyatspi.Registry.deregisterEventListener( \
264
self._registered_event_cb, *self._registered_events)
265
self._registered_events.append(event_name)
266
pyatspi.Registry.registerEventListener(self._registered_event_cb,
267
*self._registered_events)
271
def removeevent(self, event_name):
273
Remove callback of registered event
275
@param event_name: Event name in at-spi format.
276
@type event_name: string
278
@return: 1 if remove was successful, 0 if not.
282
for event in self._registered_events:
283
if event_name == event:
284
pyatspi.Registry.deregisterEventListener( \
285
self._registered_event_cb, *self._registered_events)
286
self._registered_events.remove(event)
287
pyatspi.Registry.registerEventListener( \
288
self._registered_event_cb, *self._registered_events)
293
def objectexist(self, window_name, object_name):
295
Checks whether a window or component exists.
297
@param window_name: Window name to look for, either full name,
298
LDTP's name convention, or a Unix glob.
299
@type window_name: string
300
@param object_name: Object name to look for, either full name,
301
LDTP's name convention, or a Unix glob.
302
@type object_name: string
304
@return: 1 if GUI was found, 0 if not.
307
return self.guiexist(window_name, object_name)
309
def maximizewindow(self, window_name = None):
311
Maximize a window using wnck
313
@param window_name: Window name to look for, either full name,
314
LDTP's name convention, or a Unix glob.
315
@type window_name: string
317
@return: 1 if window maximized, 0 if not.
320
waiter = MaximizeWindow(window_name)
322
return int(waiter.run())
324
def minimizewindow(self, window_name = None):
326
Minimize a window using wnck
328
@param window_name: Window name to look for, either full name,
329
LDTP's name convention, or a Unix glob.
330
@type window_name: string
332
@return: 1 if window minimized, 0 if not.
335
waiter = MinimizeWindow(window_name)
337
return int(waiter.run())
339
def unmaximizewindow(self, window_name = None):
341
Unmaximize a window using wnck
343
@param window_name: Window name to look for, either full name,
344
LDTP's name convention, or a Unix glob.
345
@type window_name: string
347
@return: 1 if window unmaximized, 0 if not.
350
waiter = UnmaximizeWindow(window_name)
352
return int(waiter.run())
354
def unminimizewindow(self, window_name = None):
356
Unminimize a window using wnck
358
@param window_name: Window name to look for, either full name,
359
LDTP's name convention, or a Unix glob.
360
@type window_name: string
362
@return: 1 if window unminimized, 0 if not.
365
waiter = UnminimizeWindow(window_name)
367
return int(waiter.run())
369
def activatewindow(self, window_name):
371
Activate a window using wnck
373
@param window_name: Window name to look for, either full name,
374
LDTP's name convention, or a Unix glob.
375
@type window_name: string
377
@return: 1 if window unminimized, 0 if not.
380
waiter = ActivateWindow(window_name)
382
return int(waiter.run())
384
def closewindow(self, window_name = None):
386
Close a window using wnck
388
@param window_name: Window name to look for, either full name,
389
LDTP's name convention, or a Unix glob.
390
@type window_name: string
392
@return: 1 if window unminimized, 0 if not.
395
waiter = CloseWindow(window_name)
397
return int(waiter.run())
399
def guiexist(self, window_name, object_name=''):
401
Checks whether a window or component exists.
403
@param window_name: Window name to look for, either full name,
404
LDTP's name convention, or a Unix glob.
405
@type window_name: string
406
@param object_name: Object name to look for, either full name,
407
LDTP's name convention, or a Unix glob.
408
@type object_name: string
410
@return: 1 if GUI was found, 0 if not.
414
waiter = ObjectExistsWaiter(window_name, object_name, 0)
416
waiter = GuiExistsWaiter(window_name, 0)
418
return int(waiter.run())
420
def waittillguiexist(self, window_name, object_name='', guiTimeOut=30):
422
Wait till a window or component exists.
424
@param window_name: Window name to look for, either full name,
425
LDTP's name convention, or a Unix glob.
426
@type window_name: string
427
@param object_name: Object name to look for, either full name,
428
LDTP's name convention, or a Unix glob.
429
@type object_name: string
430
@param guiTimeOut: Wait timeout in seconds
431
@type guiTimeOut: integer
433
@return: 1 if GUI was found, 0 if not.
437
waiter = ObjectExistsWaiter(window_name, object_name, guiTimeOut)
439
waiter = GuiExistsWaiter(window_name, guiTimeOut)
441
return int(waiter.run())
443
def waittillguinotexist(self, window_name, object_name='', guiTimeOut=30):
445
Wait till a window does not exist.
447
@param window_name: Window name to look for, either full name,
448
LDTP's name convention, or a Unix glob.
449
@type window_name: string
450
@param object_name: Object name to look for, either full name,
451
LDTP's name convention, or a Unix glob.
452
@type object_name: string
453
@param guiTimeOut: Wait timeout in seconds
454
@type guiTimeOut: integer
456
@return: 1 if GUI has gone away, 0 if not.
461
ObjectNotExistsWaiter(window_name, object_name, guiTimeOut)
463
waiter = GuiNotExistsWaiter(window_name, guiTimeOut)
465
return int(waiter.run())
467
def getobjectsize(self, window_name, object_name):
471
@param window_name: Window name to look for, either full name,
472
LDTP's name convention, or a Unix glob.
473
@type window_name: string
474
@param object_name: Object name to look for, either full name,
475
LDTP's name convention, or a Unix glob. Or menu heirarchy
476
@type object_name: string
478
@return: x, y, width, height on success.
481
obj = self._get_object(window_name, object_name)
483
_coordinates = self._get_size(obj)
484
return [_coordinates.x, _coordinates.y, \
485
_coordinates.width, _coordinates.height]
487
def getallstates(self, window_name, object_name):
489
Get all states of given object
491
@param window_name: Window name to look for, either full name,
492
LDTP's name convention, or a Unix glob.
493
@type window_name: string
494
@param object_name: Object name to look for, either full name,
495
LDTP's name convention, or a Unix glob.
496
@type object_name: string
498
@return: list of integers on success.
501
if re.search(';', object_name):
502
obj = self._get_menu_hierarchy(window_name, object_name)
504
obj = self._get_object(window_name, object_name)
506
_state = obj.getState()
507
_current_state = _state.getStates()
509
for state in _current_state:
510
_obj_states.append(state.real)
514
def hasstate(self, window_name, object_name, state):
518
@param window_name: Window name to look for, either full name,
519
LDTP's name convention, or a Unix glob.
520
@type window_name: string
521
@param object_name: Object name to look for, either full name,
522
LDTP's name convention, or a Unix glob.
523
@type object_name: string
525
@return: 1 on success.
529
if re.search(';', object_name):
530
obj = self._get_menu_hierarchy(window_name, object_name)
532
obj = self._get_object(window_name, object_name)
534
_state = obj.getState()
535
_obj_state = _state.getStates()
536
state = 'STATE_%s' % state.upper()
537
if state in self._states and \
538
self._states[state] in _obj_state:
544
def grabfocus(self, window_name, object_name):
548
@param window_name: Window name to look for, either full name,
549
LDTP's name convention, or a Unix glob.
550
@type window_name: string
551
@param object_name: Object name to look for, either full name,
552
LDTP's name convention, or a Unix glob.
553
@type object_name: string
555
@return: 1 on success.
558
obj = self._get_object(window_name, object_name)
559
self._grab_focus(obj)
563
def click(self, window_name, object_name):
567
@param window_name: Window name to look for, either full name,
568
LDTP's name convention, or a Unix glob.
569
@type window_name: string
570
@param object_name: Object name to look for, either full name,
571
LDTP's name convention, or a Unix glob.
572
@type object_name: string
574
@return: 1 on success.
577
obj = self._get_object(window_name, object_name)
578
self._grab_focus(obj)
580
if obj.getRole() == pyatspi.ROLE_TOGGLE_BUTTON:
581
self._click_object(obj, '(click|activate)')
582
elif obj.getRole() == pyatspi.ROLE_COMBO_BOX:
583
self._click_object(obj, '(click|press)')
585
self._click_object(obj)
589
def press(self, window_name, object_name):
593
@param window_name: Window name to look for, either full name,
594
LDTP's name convention, or a Unix glob.
595
@type window_name: string
596
@param object_name: Object name to look for, either full name,
597
LDTP's name convention, or a Unix glob.
598
@type object_name: string
600
@return: 1 on success.
603
obj = self._get_object(window_name, object_name)
604
self._grab_focus(obj)
606
self._click_object(obj, 'press')
610
def check(self, window_name, object_name):
614
@param window_name: Window name to look for, either full name,
615
LDTP's name convention, or a Unix glob.
616
@type window_name: string
617
@param object_name: Object name to look for, either full name,
618
LDTP's name convention, or a Unix glob.
619
@type object_name: string
621
@return: 1 on success.
624
obj = self._get_object(window_name, object_name)
625
self._grab_focus(obj)
627
if self._check_state(obj, pyatspi.STATE_CHECKED) == False:
628
self._click_object(obj)
632
def uncheck(self, window_name, object_name):
636
@param window_name: Window name to look for, either full name,
637
LDTP's name convention, or a Unix glob.
638
@type window_name: string
639
@param object_name: Object name to look for, either full name,
640
LDTP's name convention, or a Unix glob.
641
@type object_name: string
643
@return: 1 on success.
646
obj = self._get_object(window_name, object_name)
647
self._grab_focus(obj)
649
if self._check_state(obj, pyatspi.STATE_CHECKED):
650
self._click_object(obj)
654
def verifytoggled(self, window_name, object_name):
656
Verify toggle item toggled.
658
@param window_name: Window name to look for, either full name,
659
LDTP's name convention, or a Unix glob.
660
@type window_name: string
661
@param object_name: Object name to look for, either full name,
662
LDTP's name convention, or a Unix glob.
663
@type object_name: string
665
@return: 1 on success 0 on failure.
668
return self.verifycheck(window_name, object_name)
670
def verifycheck(self, window_name, object_name):
674
@param window_name: Window name to look for, either full name,
675
LDTP's name convention, or a Unix glob.
676
@type window_name: string
677
@param object_name: Object name to look for, either full name,
678
LDTP's name convention, or a Unix glob.
679
@type object_name: string
681
@return: 1 on success 0 on failure.
685
obj = self._get_object(window_name, object_name)
687
return int(self._check_state(obj, pyatspi.STATE_CHECKED))
691
def verifyuncheck(self, window_name, object_name):
695
@param window_name: Window name to look for, either full name,
696
LDTP's name convention, or a Unix glob.
697
@type window_name: string
698
@param object_name: Object name to look for, either full name,
699
LDTP's name convention, or a Unix glob.
700
@type object_name: string
702
@return: 1 on success 0 on failure.
706
obj = self._get_object(window_name, object_name)
708
return int(not self._check_state(obj, pyatspi.STATE_CHECKED))
712
def stateenabled(self, window_name, object_name):
714
Check whether an object state is enabled or not
716
@param window_name: Window name to look for, either full name,
717
LDTP's name convention, or a Unix glob.
718
@type window_name: string
719
@param object_name: Object name to look for, either full name,
720
LDTP's name convention, or a Unix glob.
721
@type object_name: string
723
@return: 1 on success 0 on failure.
727
obj = self._get_object(window_name, object_name)
729
return int(self._check_state(obj, pyatspi.STATE_ENABLED))
733
def getobjectlist(self, window_name):
735
Get list of items in given GUI.
737
@param window_name: Window name to look for, either full name,
738
LDTP's name convention, or a Unix glob.
739
@type window_name: string
741
@return: list of items in LDTP naming convention.
745
gui = self._get_window_handle(window_name)
747
raise LdtpServerException('Unable to find window "%s"' % \
749
for name, obj, obj_index in self._appmap_pairs(gui):
750
obj_list.append(name)
753
def getobjectinfo(self, window_name, object_name):
755
Get object properties.
757
@param window_name: Window name to look for, either full name,
758
LDTP's name convention, or a Unix glob.
759
@type window_name: string
760
@param object_name: Object name to look for, either full name,
761
LDTP's name convention, or a Unix glob.
762
@type object_name: string
764
@return: list of properties
767
obj = self._get_object(window_name, object_name)
770
['child_index', 'key', 'obj_index', 'parent', 'class', \
771
'children', 'label', 'label_by']
775
def getobjectproperty(self, window_name, object_name, prop):
777
Get object property value.
779
@param window_name: Window name to look for, either full name,
780
LDTP's name convention, or a Unix glob.
781
@type window_name: string
782
@param object_name: Object name to look for, either full name,
783
LDTP's name convention, or a Unix glob.
784
@type object_name: string
785
@param prop: property name.
788
@return: list of properties
791
if prop == 'child_index':
792
obj = self._get_object(window_name, object_name)
793
return obj.getIndexInParent()
795
obj = self._get_object(window_name, object_name) # A sanity check.
796
return object_name # For now, we only match exact names anyway.
797
elif prop == 'label':
798
obj = self._get_object(window_name, object_name) # A sanity check.
800
elif prop == 'obj_index':
802
for gui in self._list_guis():
803
if self._match_name_to_acc(window_name, gui):
804
for name, obj, obj_index in self._appmap_pairs(gui):
806
role_count[role] = role_count.get(role, 0) + 1
807
if name == object_name:
810
raise LdtpServerException(
811
'Unable to find object name in application map')
812
elif prop == 'parent':
814
for gui in self._list_guis():
815
if self._match_name_to_acc(window_name, gui):
816
for name, obj, obj_index in self._appmap_pairs(gui):
817
if name == object_name:
818
for pname, pobj in cached_list:
819
if obj in pobj: # avoid double link issues
821
_parent = self._ldtpize_accessible(obj.parent)
822
return '%s%s' % (_parent[0], _parent[1])
823
cached_list.insert(0, (name, obj))
825
raise LdtpServerException(
826
'Unable to find object name in application map')
827
elif prop == 'class':
828
obj = self._get_object(window_name, object_name)
829
return obj.getRoleName().replace(' ', '_')
830
elif prop == 'children':
832
obj = self._get_object(window_name, object_name)
833
for gui in self._list_guis():
834
if self._match_name_to_acc(window_name, gui):
835
for name, child, obj_index in self._appmap_pairs(gui):
837
children.append(name)
839
return ' '.join(children)
841
raise LdtpServerException('Unknown property "%s" in %s' % \
844
def getchild(self, window_name, child_name='', role='', first=False):
846
Gets the list of object available in the window, which matches
847
component name or role name or both.
849
@param window_name: Window name to look for, either full name,
850
LDTP's name convention, or a Unix glob.
851
@type window_name: string
852
@param child_name: Child name to search for.
853
@type child_name: string
854
@param role: role name to search for, or an empty string for wildcard.
857
@return: list of matched children names
861
for gui in self._list_guis():
862
if self._match_name_to_acc(window_name, gui):
863
for name, obj, obj_index in self._appmap_pairs(gui):
864
if child_name and role:
865
if obj.getRoleName() == role and \
866
(child_name == name or \
867
self._match_name_to_acc(child_name, obj)):
870
if obj.getRoleName() == role:
873
if child_name == name or \
874
self._match_name_to_acc(child_name, obj):
877
#print matches, first
878
if matches and first:
879
# Return once we have a match
883
raise LdtpServerException('Could not find a child.')
887
def remap(self, window_name):
889
For backwards compatability, does not do anything since we are entirely
892
@param window_name: Window name to look for, either full name,
893
LDTP's name convention, or a Unix glob.
894
@type window_name: string
901
def wait(self, timeout=5):
903
Wait a given amount of seconds.
905
@param timeout: Wait timeout in seconds
906
@type timeout: integer
911
waiter = NullWaiter(1, timeout)
915
def getstatusbartext(self, window_name, object_name):
919
@param window_name: Window name to type in, either full name,
920
LDTP's name convention, or a Unix glob.
921
@type window_name: string
922
@param object_name: Object name to type in, either full name,
923
LDTP's name convention, or a Unix glob.
924
@type object_name: string
926
@return: text on success.
929
return self.gettextvalue(window_name, object_name)
931
def setlocale(self, locale_str):
933
Set the locale to the given value.
935
@param locale_str: locale to set to.
936
@type locale_str: string
941
locale.setlocale(locale.LC_ALL, locale_str)
944
def getwindowsize (self, window_name):
948
@param window_name: Window name to get size of.
949
@type window_name: string
951
@return: list of dimensions [x, y, w, h]
955
for gui in self._list_guis():
956
if self._match_name_to_acc(window_name, gui):
957
size = self._get_size(gui)
958
return [size.x, size.y, size.width, size.height]
960
raise LdtpServerException('Window does not exist')