AXElements 0.7.8 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.yardopts +1 -10
  2. data/README.markdown +7 -14
  3. data/ext/accessibility/key_coder/key_coder.c +7 -0
  4. data/lib/AXElements.rb +0 -2
  5. data/lib/accessibility/core.rb +180 -123
  6. data/lib/accessibility/dsl.rb +310 -191
  7. data/lib/accessibility/enumerators.rb +9 -8
  8. data/lib/accessibility/errors.rb +7 -8
  9. data/lib/accessibility/factory.rb +16 -9
  10. data/lib/accessibility/graph.rb +68 -22
  11. data/lib/accessibility/highlighter.rb +86 -0
  12. data/lib/accessibility/pp_inspector.rb +4 -4
  13. data/lib/accessibility/qualifier.rb +11 -9
  14. data/lib/accessibility/string.rb +12 -4
  15. data/lib/accessibility/translator.rb +19 -10
  16. data/lib/accessibility/version.rb +3 -1
  17. data/lib/accessibility.rb +42 -17
  18. data/lib/ax/application.rb +90 -30
  19. data/lib/ax/button.rb +5 -2
  20. data/lib/ax/element.rb +133 -149
  21. data/lib/ax/pop_up_button.rb +12 -0
  22. data/lib/ax/radio_button.rb +5 -2
  23. data/lib/ax/row.rb +2 -2
  24. data/lib/ax/static_text.rb +5 -2
  25. data/lib/ax/systemwide.rb +24 -12
  26. data/lib/ax_elements/awesome_print.rb +13 -0
  27. data/lib/ax_elements/exception_workaround.rb +5 -0
  28. data/lib/ax_elements/nsarray_compat.rb +1 -0
  29. data/lib/ax_elements.rb +2 -1
  30. data/lib/minitest/ax_elements.rb +60 -4
  31. data/lib/mouse.rb +47 -20
  32. data/lib/rspec/expectations/ax_elements.rb +180 -88
  33. data/rakelib/doc.rake +7 -0
  34. data/test/helper.rb +2 -1
  35. data/test/integration/accessibility/test_dsl.rb +126 -18
  36. data/test/integration/accessibility/test_errors.rb +1 -1
  37. data/test/integration/ax/test_element.rb +17 -0
  38. data/test/integration/minitest/test_ax_elements.rb +33 -38
  39. data/test/integration/rspec/expectations/test_ax_elements.rb +68 -19
  40. data/test/sanity/accessibility/test_core.rb +45 -37
  41. data/test/sanity/accessibility/test_highlighter.rb +56 -0
  42. data/test/sanity/ax/test_application.rb +8 -0
  43. data/test/sanity/ax/test_element.rb +7 -3
  44. data/test/sanity/minitest/test_ax_elements.rb +2 -0
  45. data/test/sanity/rspec/expectations/test_ax_elements.rb +3 -0
  46. data/test/sanity/test_accessibility.rb +9 -0
  47. data/test/sanity/test_mouse.rb +2 -2
  48. metadata +11 -38
  49. data/docs/AccessibilityTips.markdown +0 -119
  50. data/docs/Acting.markdown +0 -340
  51. data/docs/Debugging.markdown +0 -165
  52. data/docs/Inspecting.markdown +0 -261
  53. data/docs/KeyboardEvents.markdown +0 -122
  54. data/docs/NewBehaviour.markdown +0 -151
  55. data/docs/Notifications.markdown +0 -271
  56. data/docs/Searching.markdown +0 -250
  57. data/docs/TestingExtensions.markdown +0 -52
  58. data/docs/images/all_the_buttons.jpg +0 -0
  59. data/docs/images/next_version.png +0 -0
  60. data/docs/images/ui_hierarchy.dot +0 -34
  61. data/docs/images/ui_hierarchy.png +0 -0
  62. data/lib/accessibility/debug.rb +0 -164
  63. data/test/integration/accessibility/test_debug.rb +0 -44
  64. data/test/sanity/accessibility/test_debug.rb +0 -63
@@ -1,165 +0,0 @@
1
- # Debugging
2
-
3
- This document includes instructions on using AXElements' built in
4
- tools to help you debug issues with your scripts, or in cases where
5
- you might find a bug in AXElements itself or MacRuby.
6
-
7
- ## Visibility
8
-
9
- Sometimes an object that should be visible to accessibility does not
10
- show up. Sometimes it will be invisible to the Accessibility Inspector
11
- and sometimes it will be invisible to AXElements. This is because the
12
- inspector uses hit testing to find objects and AXElements uses the
13
- `children` and `parent` attributes (usually). Depending on which part
14
- of the accessibility protocol is not being implemented correctly, one
15
- or both tools might fail to work.
16
-
17
- Fortunately, failures in the accessibility API are few and far
18
- between. The one big,
19
- [known issue](http://openradar.appspot.com/6832098) is with menu bar
20
- items; you cannot work around this issue without hacking into private
21
- Apple APIs. Specifically, you would need to override built in
22
- accessibility methods in the class that implement the user interface
23
- for NSStatusItem, which is a private class; or you could build your
24
- status bar item as an NSMenuExtra, which is another private class. You
25
- can find more tips on augmenting accessibility for apps in the
26
- {file:docs/AccessibilityTips.markdown Accessibility Tips} document.
27
-
28
- ## Trees
29
-
30
- Sometimes you need to see the big picture, the whole UI tree at
31
- once or at least be able to see the root of the hierarchy from where
32
- you are. For these troubling cases AXElements provides a few tools.
33
-
34
- ### Text Tree
35
-
36
- Printing a text tree is similar to how a UI dump works with
37
- accessibility on iOS. AXElements does improve a bit on its iOS
38
- equivalent. Simply using the Accessibility Inspector does not give you
39
- a good picture of the whole tree and with complicated structures it is
40
- easy to make mistakes navigating the UI tree.
41
-
42
- The text tree comes formatted for you, and you can simply print it out
43
- to the console. The output uses indentation to indicate how far down
44
- the tree each element is, and the first element up the tree with one
45
- indentation level less will always be the parent for an element.
46
-
47
- Printing out a text tree in the console is very easy. First you generate
48
- the text dump and then you print it out:
49
-
50
- puts Accessibility.dump(app)
51
-
52
- This method is useful when you are having difficulties with
53
- search. Sometimes when searching you will end up finding the wrong
54
- element because your search query was ambiguous and you didn't
55
- know at the time. Printing out a dump can often be all the help you
56
- need in order to identify your problem.
57
-
58
- However, if the standard `#inspect` isn't doing it for you, you can
59
- perform your own inspection every element in a tree yourself using the
60
- built in enumerators. Searches use the {Accessibility::BFEnumerator},
61
- but the text tree dump method uses {Accessibility::DFEnumerator}.
62
-
63
- ### Dot Graph
64
-
65
- For super fancy text trees, AXElements can generate dot graphs for
66
- consumption by [Graphviz](http://www.graphviz.org/). In this case, you
67
- want to call {Accessibility.graph} and pass the root of the tree you
68
- want to have turned into a dot graph; you will get a string back that
69
- you will then need to give to Graphviz in order to generate the visual
70
- graph.
71
-
72
- File.open('graph.dot', 'w') do |file|
73
- app = Accessibility.application_with_name 'Terminal'
74
- file.write Accessibility.graph(app.window)
75
- end
76
- `dot graph.dot -Tpng > graph.png`
77
- `open graph.png`
78
-
79
- ### Text Tree Won't Print?
80
-
81
- AXElements isn't perfect and it is possible that an edge case slipped
82
- between the cracks. However, it's also possible that the problem is
83
- actually how accessibility information is being vended out.
84
-
85
- As an example, Radar #10040865 is a ticket that I filed with Apple
86
- where they broke accessibility with search fields. The effect to
87
- AXElements was that you could not search through the menu bar causing
88
- a text dump to fail in a very difficult to trace manner.
89
-
90
- In these cases you will need to use your deductive reasoning to figure
91
- out where the problem is coming from. Fortunately, I have provided
92
- some tools to help you along the way.
93
-
94
- ## All The Way Up
95
-
96
- Sometimes you don't need a whole tree to be printed out. Sometimes
97
- just seeing the path from an element to the top level element is
98
- enough. {Accessibility.path} is your friend in this case, it will
99
- provide you with an array of UI element objects, each successive
100
- element will be the parent of the previous element. This is almost
101
- like the view that the Accessibility Inspector provides.
102
-
103
- ## Custom Exceptions
104
-
105
- AXElements provides some customized exceptions in the OO layer that
106
- should help give you much better hints at what went wrong when you
107
- have a problem.
108
-
109
- Custom exceptions have been created to help identify the point of
110
- failure that would have caused a more cryptic exception to have been
111
- raised instead. These custom exceptions also capture more metadata
112
- about the problem that occurred which should give good hints as to what
113
- went wrong.
114
-
115
- ### Search Failures
116
-
117
- An {AX::Element::SearchFailure `SearchFailure`} will occur when you
118
- perform an implicit search that fails to find anything.
119
-
120
- In cases where implicit searches are chained, which happens frequently
121
- with deep UI hierarchies, if one of the searches were to fail then you
122
- would receive a `NoMethodError` about something having
123
- failed. Sometimes the failure would happen because the search returned
124
- `nil`, and of course `nil` would not respond to another search, though
125
- this problem was easy to identify if you are familiar with the
126
- AXElements source code; in other cases the failure would occur
127
- somewhere in the search {Accessibility::Qualifier qualifier} or in the
128
- {Accessibility::BFEnumerator enumerator}, and it was not always clear why.
129
-
130
- The other feature of a search failure is that the exception message
131
- will include an element back trace using {Accessibility.path}. This is
132
- meant to give a hint about why the search failed.
133
-
134
- ### Attribute Not Writable
135
-
136
- You will receive {AX::Element::ReadOnlyAttribute `ReadOnlyAttribute`}
137
- exceptions only when you try to set an attribute that is not
138
- writable. Again, this was originally designed to more easily identify the
139
- point of failure when you try to write to an attribute that you should
140
- not write to.
141
-
142
- Specifically, `set_focus` is called by methods internally by
143
- AXElements and at one time it was causing some problems when elements
144
- were unexpectedly not allowing their `focused` attribute to be
145
- written.
146
-
147
- ## Logging
148
-
149
- The core level of AXElements has logging in every case that an error
150
- code is returned. Though, it can show false positives because of
151
- hiccups in the accessibility API or implementation that an app
152
- provides; so it turned off by default. This feature is also going away
153
- in favour of more intelligent error handling in the core wrapper.
154
-
155
- When weird bugs are occuring, possibly even crashing MacRuby, you
156
- should try turning on the logs and then trying the script again. You
157
- might see some tell tale logs printed out right before the crash. You
158
- can turn on logging right after you load AXElements, like so:
159
-
160
- require 'ax_elements'
161
- Accessibility.log.level = Logger::DEBUG
162
-
163
- The standard log levels are available, the full set is available
164
- [here](http://rdoc.info/stdlib/logger/1.9.2/Logger/Severity). `Logger::DEBUG`
165
- will turn on all logs.
@@ -1,261 +0,0 @@
1
- # Inspecting The User Interface
2
-
3
- When it comes to inspecting the user interface there are _many_ nooks
4
- and crannies that are interesting to talk about. This document covers
5
- the core concepts that you will need to understand before you can
6
- begin discovering them yourself.
7
-
8
- ## The UI Tree
9
-
10
- The first most important thing to understand is that accessibility
11
- exposes the user interface as a hierarchy of user interface
12
- tokens. Each token references a GUI element on screen, either
13
- something literal like a button, or something structural like a group
14
- of buttons. The organization of the hierarchy should make sense to
15
- human beings since it is designed to be used by the disabled, so it
16
- does not nescesarrily match the underlying organization of views and
17
- can be completely arbitrary. That being said, most apps will use the
18
- defaults provided by AppKit and "Just Work"™ the way you would
19
- expect.
20
-
21
- Throughout this documentation I will refer to tokens as if they were
22
- the object themselves unless otherwise noted. It's much easier Each
23
- token object knows who its parent object is, and knows about any
24
- children objects that it may have. thus creating a tree structure. At
25
- least this is the theory, but there are, on occasion, some hiccups
26
- since accessibility is a protocol to which multiple parties have to
27
- conform.
28
-
29
- A sample hierarchy might start with the application, which has a menu
30
- bar as one of its children and the menu bar has menu bar items, each
31
- menu bar item has a menu and each menu has menu items; some menu items
32
- have another menu as its child which then leads to more menu items and
33
- so on. This hierarchy is much easier to understand once visualized:
34
-
35
- ![Example GUI Hierarchy](images/ui_hierarchy.png)
36
-
37
- This example is meant to be instructive, the menu bar is one of the
38
- more complicated hierarchies to navigate and many other nodes in the
39
- hierarchy have been left out. The good news is that AXElements has
40
- techniques and patterns for simplifying navigation, so don't get
41
- scared off just yet. The point here is that each menu item knows which
42
- menu is its parent, and each menu knows which menu item or menu bar
43
- item is its parent, and the menu bar knows that which application is
44
- its parent. But who is the parent of the application? It turns out
45
- that that is a trick question, an application does not have a
46
- parent. An application is the entry point for the UI hierarchy, it
47
- will be the place where a script usually starts and application
48
- objects can be created using the {Accessibility} singleton
49
- methods. You can create the object for an application that is already
50
- running using {Accessibility.application_with_name} like so:
51
-
52
- app = Accessibility.application_with_name = 'Finder'
53
-
54
- ### Accessibility Inspector
55
-
56
- To quickly navigate through the UI tree, Apple has provided a tool,
57
- the Accessibility Inspector, as part of the Developer Tools. The
58
- inspector will come in handy when you are writing scripts using
59
- AXElements, though there are some potential pitfalls that will be
60
- discussed later.
61
-
62
- Once you install the Developer Tools, the inspector can be found in
63
- `/Developer/Applications/Utilities/Accessibility Tools/`. It is worth
64
- playing around with the inspector to get a feel for what the
65
- accessibility APIs offer; but keep in mind that the inspector is a
66
- dumb interface to the accessibility APIs.
67
-
68
- ## Attributes
69
-
70
- Each item in the GUI tree has attributes; buttons have a title,
71
- sliders have a value, etc.. Pointers to the parent and chilrden nodes
72
- are also attributes. Programmatically, you can get a list of
73
- attributes that an object has by asking nicely. AXElements exposes
74
- this API via {AX::Element#attributes}. {AX::Element} actually acts as
75
- the abstract base class for all objects, encapsulating everything that
76
- the accessibility APIs offer.
77
-
78
- ### Accessing Attributes
79
-
80
- Every attribute can be accessed as a method of the UI object. The
81
- method name will always be the
82
- [snake_case](http://en.wikipedia.org/wiki/Letter_case) version of the
83
- attribute name without the prefix.
84
-
85
- Some examples:
86
-
87
- - `AXChildren` would become `children`
88
- - `AXMainWindow` would become `main_window`
89
- - `AXIsApplicationRunning` would become `application_running?`
90
-
91
- The last case is special because we consider "`Is`" to be part of the
92
- prefix and the method name has a "`?`" at the end. This is to follow
93
- Ruby conventions of putting "`?`" at the end of the method name if the
94
- method is a predicate. There will be more details about these rules in
95
- other tutorial documents, but this is really something that should be
96
- abstracted away. This detail is not hidden right now becaues the
97
- Accessibility Inspector does not hide the information and you still
98
- need to understand it in order to use the inspector with AXElements.
99
-
100
- #### Example
101
-
102
- We can demonstrate how this all comes together with a small
103
- example. In the terminal, you can start up a console session of
104
- AXElements by loading `ax_elements` in `macirb` or by navigating to
105
- the AXElements repository and running the `console` task if you have a
106
- clone. Then you can try the following code, one line at a time:
107
-
108
- app = Accessibility.application_with_name 'Terminal'
109
- window = app.main_window
110
- title = window.title
111
- puts "The window's title is '#{title}'"
112
-
113
- In the first line, we are creating the object for the application. As
114
- mentioned earlier, you will usually start navigating the UI tree from
115
- the application object. Giving the name of the application is the
116
- easiest way to create an application object but requires the
117
- application to already be running.
118
-
119
- On the second line we use the application object and ask it for the
120
- value of the `main_window` attribute. This will return to us another
121
- UI object, this time for the window. You will also notice that the
122
- console printed out some extra information about the window, such as
123
- the title of the window and its position (in flipped
124
- coordinates). Each UI element has implemented the `#inspect` method in
125
- such a way as to provide users with a succinct but useful way to
126
- identify the UI element on the screen, and `macirb` is designed to
127
- happily print that information out for each statement that you enter.
128
-
129
- On the third line, we ask the window for it's `title`, and it gives
130
- us back a string which we then print out on the fourth line. Notice
131
- that the title of the window was also printed by the console as part
132
- of the `#inspect` output that `macirb` asks to print out.
133
-
134
- ### Inspect Output
135
-
136
- Using `#inspect` is a great way to see the important details of a UI
137
- element, it shows the values of the most important attributes so that
138
- you can quickly identify which element it really is on screen, but not
139
- so many details that it becomes a pain. A typical example of
140
- `#inspect` output looks like this:
141
-
142
- #<AX::StandardWindow "AXElementsTester" (1584.0, 184.0) 17 children focused[✘]>
143
-
144
- That output includes all the pieces that you will normally see from
145
- `#inspect`, but you may see less or more depending on the UI element
146
- that is being inspected. As is the norm in Ruby, you will always at
147
- least get the name of the class; then AXElements will try to include a
148
- piece of identifying information such as the `title`, then you have
149
- numbers in parentheses which are the screen coordinates for the
150
- object, then you have the number of children, and then check boxes for
151
- boolean attributes. Aside from the class name, the other pieces of
152
- information will only be included if they are relevant, and certain
153
- objects will also include other information.
154
-
155
- The values shown by `#inspect` are pieced together using helper
156
- methods from the {Accessibility::PPInspector} module. {AX::Element}
157
- implements a generic implementation with
158
- {AX::Element#inspect}. However, the generic `#inspect` may not always
159
- choose the best attributes to show. An example would be
160
- {AX::Application#inspect}, which overrides the generic `inspect` so
161
- that the process identifier for the application is also included. In
162
- other cases, the screen co-ordinates or whether the element is enabled
163
- may not be relevant, so you can override the method in the specific
164
- subclass to not include those attributes and/or include other
165
- attributes. The key idea is to make `#inspect` helpful when exploring
166
- a UI through the console or when debugging a script.
167
-
168
- ## Accessing Children
169
-
170
- Following first principles shown in the example from above you might
171
- be led to believe that in order to navigate around the UI tree you
172
- will have to write code that looks something like this:
173
-
174
- app.main_window.children.find do |child|
175
- child.class == AX::Button && child.title == 'Add'
176
- end
177
-
178
- However, AXElements provides a way to specify what you want that is
179
- much more convenient to use. Behold:
180
-
181
- app.main_window.button(title: 'Add')
182
-
183
- This is quite the simplification! If we break it down, you see that
184
- the method name is the class of the object you want, and then if you
185
- need to be more specific you can pass key-value pairs where the key
186
- is an attribute and the value is the expected value. The above example
187
- says "find a button with the title of 'Add'".
188
-
189
- You can use as many or as few key-value pairs as you need in order to
190
- find the element that you are looking for. If you do not specify any
191
- key-value pairs, then the first object with the correct class will be
192
- chosen. The {file:docs/Searching.markdown Searching Tutorial} goes
193
- into more depth on how key-value pairs are used to specify which
194
- object you want.
195
-
196
- ## Parameterized Attributes
197
-
198
- There is a special type of attribute that is called the parameterized
199
- attribute. The difference from a regular attribute is that you need to
200
- supply a parameter. An example of this would look like this:
201
-
202
- static_text.string_for_range CFRange.new(0,5)
203
-
204
- The method name suggests that you need to provide a range and in
205
- return you will be given part of the string that corresponds to the
206
- range. Of course, this example is quite contrived since string slicing
207
- is so trivial in Ruby (but this parameterized attribute actually exists).
208
-
209
- Parameterized attributes are different enough from regular attributes
210
- that Apple does not want them mixing together and producing
211
- offspring. AXElements is a bit progressive, but still keeps the list
212
- of parameterized attributes separate from attributes; you can get a
213
- list of parameterized attributes for an object with
214
- {AX::Element#param_attributes}. Similarly, you have probably already
215
- noticed that parameterized attributes have their own section in the
216
- Accessibility Inspector and that many objectss do not have any
217
- parameterized attributes.
218
-
219
- In my experience, parameterized attributes have not been very useful,
220
- but I haven't looked hard enough and am still looking for a good
221
- example to put in this section of the tutorial.
222
-
223
- ## Explicit Attribute Access
224
-
225
- In cases where you know what you want is going to be an attribute, you
226
- can get better performance from accessing attributes by calling
227
- {AX::Element#attribute} and passing the attribute name.
228
-
229
- app.attribute(:main_window)
230
-
231
- Similarly, for parameterized attributes, you need to call
232
- {AX::Element#param_attribute} and pass the attribute name and
233
- parameter as parameters to that method.
234
-
235
- app.param_attribute(:string_for_range, CFRange.new(0,5))
236
-
237
- These methods are exposed so that other library classes can achieve
238
- better performance; but you should avoid using them regularly. These
239
- APIs may be hidden in the future in order to enforce the DSL usage.
240
-
241
- ## Adding Accessibility Attributes
242
-
243
- You can add custom attributes to objects, or even inject or hide
244
- objects from the UI hierarchy. It is simply a matter of
245
- overriding/implementing methods from the
246
- [NSAccessibility](http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Protocols/NSAccessibility_Protocol/Reference/Reference.html)
247
- protocol where needed.
248
-
249
- You should peruse the {file:docs/AccessibilityTips.markdown Accessibility Tips}
250
- documentation before making nontrivial changes. There are a couple of
251
- guidelines you need to be aware of in order to make sure things remain
252
- compatible with AXElements.
253
-
254
- ## Next Steps
255
-
256
- You may want to play with what you have learnt so far, see if you can
257
- find bugs and then fix them, or perhaps add missing features. ;)
258
-
259
- From here the next logical step would be to figure out how to trigger
260
- some sort of action and then inspect the UI for changes; for that
261
- topic you should read the {file:docs/Acting.markdown Acting Tutorial}.
@@ -1,122 +0,0 @@
1
- # Keyboard Events
2
-
3
- Keyboard events are a system provided by Apple that allows you to
4
- simulate keyboard input. The API for this in the `ApplicationServices`
5
- framework, but there is an analogue in the `Acessibility` APIs which
6
- has the additional option of directing the input to a specific application.
7
-
8
- Using accessibility actions and setting attributes you can already
9
- perform most of the interactions that would be possible with the
10
- keyboard simulation. However, there are some things that you will need
11
- to, or it will just make more sense to, simulate keyboard input. For
12
- example, to make use of hot keys you would have to add extra actions
13
- or attributes to a control in the application; that would be more
14
- work, possibly prone to error, than simply simulating the hot key from
15
- outside the application. In other situations you may specifically want
16
- to test out keyboard navigation and so actions would not be a good
17
- substitute. It may be that the APIs that AXElements provides for
18
- typing just make more sense when writing tests or scripts.
19
-
20
- ## Typing with the DSL
21
-
22
- The {Accessibility::DSL} mix-in exposes keyboard events through the
23
- `type` method. A simple example would look like this:
24
-
25
- type "Hello, #{ENV['USER']}! How are you today?\n"
26
-
27
- And watch your computer come to life! The `type` command takes an
28
- additional optional parameter that we'll get to later. The first
29
- parameter is just a string that you want AXElements to type out. How
30
- to format the string should be obvious for the most part, but some
31
- things like the command key and arrows might not be so obvious.
32
-
33
- ## Formatting Strings
34
-
35
- Letters and numbers should be written just as you would for any other
36
- string. Any of the standard symbols can also be plainly added to a
37
- string that you want to have typed. Here are some examples:
38
-
39
- type "UPPER CASE LETTERS"
40
- type "lower case letters"
41
- type "1337 message @/\/|) 57|_||=|="
42
- type "A proper sentence can be typed out (all at once)."
43
-
44
- ### Regular Escape Sequences
45
-
46
- Things like newlines and tabs should be formatted just like they would
47
- in a regular string. That is, normal string escape sequences should
48
- "just work" with AXElements. Here are some more examples:
49
-
50
- type "Have a bad \b\b\b\b\b good day!"
51
- type "First line.\nSecond line."
52
- type "I \t like \t to \t use \t tabs \t a \t lot."
53
- type "Explicit\sSpaces."
54
-
55
- ### Custom Escape Sequences
56
-
57
- Unfortunately, there is no built in escape sequence for deleting to
58
- the right or pressing command keys like `F1`. AXElements defines some
59
- extra escape sequences in order to easily represent the remaining
60
- keys.
61
-
62
- These custom escape sequences __shoud start with two `\` characters__,
63
- as in this example:
64
-
65
- type "\\F1"
66
-
67
- A custom escape sequence __should terminate with a space or the end of
68
- the string__, as in this example:
69
-
70
- type "\\PAGEDOWN notice the space afterwards\\PAGEUP but not before"
71
-
72
- The full list of supported custom escape sequences is listed in
73
- {Accessibility::StringParser::CUSTOM}. Some escapes have an alias,
74
- such as the right arrow key which can be escaped as `"\\RIGHT"` or as
75
- `"\\->"`.
76
-
77
- ### Hot Keys
78
-
79
- To support pressing multiple keys at the same time (i.e. hot keys), you
80
- must start with the custom escape sequence for the combination and
81
- instead of ending with a space you should put a `+` character to chain
82
- the next key. The entire sequence should be ended with a space or
83
- nil. Some common examples are opening a file or quitting an
84
- application:
85
-
86
- type "\\COMMAND+o"
87
- type "\\CONTROL+a Typing at the start of the line"
88
- type "\\COMMAND+\\SHIFT+s"
89
-
90
- You might also note that `CMD+SHIFT+s` could also be:
91
-
92
- type "\\COMMAND+S"
93
-
94
- Since a capital `S` will cause the shift key to be held down.
95
-
96
- One caveat with hot keys is that you cannot use `"\\COMMAND+ "` to
97
- represent command and space combination, you will need to use
98
- `"\\COMMAND+\s"` instead.
99
-
100
- ## Protips
101
-
102
- In order make sure that certain sequences of characters are properly
103
- escaped, it is recommended to simply always use double quoted
104
- strings.
105
-
106
- ### Posting To A Specific Application
107
-
108
- The second argument to the `type` command can be an {AX::Application}
109
- object. If you do not include the argument, the events will be posted
110
- to the system, which usually means the application that currently is
111
- active. Note that you cannot be more specific than the application
112
- that you want to send the events to, within the application, the
113
- control that has keyboard focus will receive the events.
114
-
115
- ### Changing Typing Speed
116
-
117
- You can set the typing speed at load time by setting the environment
118
- variable `KEY_RATE`. See {Accessibility::Core::KEY\_RATE} for details on
119
- possible values. An example of using it would be:
120
-
121
- KEY_RATE=SLOW irb -rubygems -rax_elements
122
- KEY_RATE=0.25 rspec gui_spec.rb