3 # Gcalctool Automated Tests
7 # Copyright (c) 1987-2007 Sun Microsystems, Inc.
11 """Gcalctool Automated Tests. This standalone script talks
12 directly with the AT-SPI Registry via its IDL interfaces.
14 It's based on the Orca tool play_keystrokes.py.
16 It will read gcalctool test calculations (read from standard input)
17 and generate keyboard events for the gcalctool application.
19 To perform the gcalctool automated tests, follow these steps:
21 1) Run the runtests.py script in a terminal window.
22 Results are written to standard output. For example:
24 runtests.py > output.txt
26 2) Start the play_keystrokes.py script in a terminal window.
27 The input file should be provided on standard input. For example:
29 play_keystrokes.py < input.txt
33 4) Give focus to gcalctool.
35 That's it! The tests will now be automatically run and automatically
36 terminate when the last line from the input file is read.
47 ORBit
.load_typelib("Accessibility")
48 ORBit
.CORBA
.ORB_init()
51 import Accessibility__POA
56 registry
= bonobo
.get_object("OAFIID:Accessibility_Registry:1.0",
57 "Accessibility/Registry")
59 applicationName
= "gcalctool"
67 ########################################################################
69 # Event listener class for global events #
71 ########################################################################
73 class EventListener(Accessibility__POA
.EventListener
):
74 """Registers a callback directly with the AT-SPI Registry for the
75 given event type. Most users of this module will not use this
76 class directly, but will instead use the addEventListener method.
79 def __init__(self
, registry
, callback
, eventType
):
80 self
.registry
= registry
81 self
.callback
= callback
82 self
.eventType
= eventType
89 def queryInterface(self
, repo_id
):
91 if repo_id
== "IDL:Accessibility/EventListener:1.0":
96 self
._default
_POA
().the_POAManager
.activate()
97 self
.registry
.registerGlobalEventListener(self
._this
(),
99 self
.__registered
= True
100 return self
.__registered
102 def deregister(self
):
103 if not self
.__registered
:
105 self
.registry
.deregisterGlobalEventListener(self
._this
(),
107 self
.__registered
= False
109 def notifyEvent(self
, event
):
116 ########################################################################
118 # Testing functions. #
120 ########################################################################
123 """Starts event notification with the AT-SPI Registry. This method
124 only returns after 'stop' has been called.
131 """Stop event notification with the AT-SPI Registry.
137 def registerEventListener(callback
, eventType
):
138 """Registers the given eventType and callback with the Registry.
141 - callback: function to call with an AT-SPI event instance
142 - eventType: string representing the type of event
145 listener
= EventListener(registry
, callback
, eventType
)
146 listeners
.append(listener
)
149 def shutdownAndExit(signum
=None, frame
=None):
153 def isApplication(event
, appName
):
154 """Check to see if this event is for the desired application, by
155 getting the component at the top of the object hierarchy (which
156 should have a role of "application", and comparing its name against
160 - event: the event to process
161 - appName: the application name to test against
164 parent
= event
.source
166 if parent
.getRoleName() == "application":
168 parent
= parent
.parent
169 if parent
and parent
.name
== appName
:
175 def getKeycode(keysym
):
176 """Converts an XKeysym string (e.g., 'KP_Enter') to a keycode that
177 should match the event.hw_code for key events.
180 - keysym: a string that is a valid representation of an XKeysym.
182 Returns an integer representing a key code that should match the
183 event.hw_code for key events.
187 sys
.stderr
.write("getKeycode: keysym: %s\n" % keysym
)
189 if not keycodeCache
.has_key(keysym
):
190 keymap
= gtk
.gdk
.keymap_get_default()
191 entries
= keymap
.get_entries_for_keyval(
192 gtk
.gdk
.keyval_from_name(keysym
))
194 keycodeCache
[keysym
] = entries
[0][0]
196 keycodeCache
[keysym
] = 0
197 return keycodeCache
[keysym
]
200 def generateEvents(d
, hw_code
):
201 """Converts an XKeysym event string to its hardware code and generates
202 two keyboard events (pressed and released) for it.
205 - d: a handle to the Registry device event controller
206 - hw_code: the hardware key code.
210 sys
.stderr
.write("generateEvents: hw_code: %d\n" % hw_code
)
211 d
.generateKeyboardEvent(hw_code
, "", 0)
212 d
.generateKeyboardEvent(hw_code
, "", 1)
215 def sendKey(d
, token
):
216 """Converts an XKeysym event string to its hardware code and generates
217 two keyboard events (pressed and released) for it. Look for tokens
218 starting with "Control-" and "Alt-" and send two sets of events.
221 - d: a handle to the Registry device event controller
222 - token: an XKeysym string containing the event type.
226 sys
.stderr
.write("sendKey: token: %s\n" % token
)
228 if token
.startswith("Control-"):
229 generateEvents(d
, getKeycode("Control_L"))
230 generateEvents(d
, getKeycode(token
[len(token
)-1]))
232 elif token
.startswith("Alt-"):
233 generateEvents(d
, getKeycode("Alt_L"))
234 generateEvents(d
, getKeycode(token
[len(token
)-1]))
237 generateEvents(d
, getKeycode(token
))
240 def readAndSendInput():
241 """Keep reading a line of text from standard input (which contains
242 a single gcalctool test), until all lines have been read. Comment
243 (lines starting with "#") and blank lines are thrown away. For each
244 remaining line, it splits it into tokens, each of which is an XKeysym
245 event type. Two keyboard events are generated from each of these
246 ("pressed" and "released") until a Return event token has been found.
247 After that has been sent, a pair of Delete events are generated to
248 clear the display before the next line is read from standard input.
250 Note that this routine throws a EOFError exception when there is no
254 d
= registry
.getDeviceEventController()
258 if (len(line
) == 0) or (line
[0] == '#'):
261 tokens
= line
.split()
262 for i
in range(0, len(tokens
)):
263 sendKey(d
, tokens
[i
])
265 sys
.stderr
.write("readAndSendInput: sleeping...\n")
269 sys
.stderr
.write("readAndSendInput: waking...\n")
271 if tokens
[i
] == "Return":
275 def notifyEvent(event
):
276 if event
.type == "focus:":
277 if isApplication(event
, applicationName
):
278 sys
.stderr
.write("Starting keyboard event generation.\n")
285 sys
.stderr
.write("Completing keyboard event generation.\n")
290 for eventType
in eventTypes
:
291 registerEventListener(notifyEvent
, eventType
)
295 if __name__
== "__main__":
297 signal
.signal(signal
.SIGINT
, shutdownAndExit
)
298 signal
.signal(signal
.SIGQUIT
, shutdownAndExit
)