AXElements 0.6.0beta2 → 0.7.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -2
- data/README.markdown +152 -88
- data/Rakefile +8 -103
- data/docs/Debugging.markdown +9 -2
- data/docs/KeyboardEvents.markdown +114 -49
- data/docs/Setting.markdown +1 -0
- data/docs/images/next_version.png +0 -0
- data/ext/accessibility/key_coder/extconf.rb +22 -0
- data/ext/accessibility/key_coder/key_coder.c +113 -0
- data/lib/AXElements.rb +2 -0
- data/lib/accessibility/core.rb +897 -0
- data/lib/accessibility/debug.rb +168 -0
- data/lib/accessibility/dsl.rb +697 -0
- data/lib/accessibility/enumerators.rb +104 -0
- data/lib/accessibility/errors.rb +32 -0
- data/lib/accessibility/factory.rb +153 -0
- data/lib/accessibility/graph.rb +150 -0
- data/lib/{ax_elements/inspector.rb → accessibility/pp_inspector.rb} +39 -28
- data/lib/accessibility/qualifier.rb +158 -0
- data/lib/accessibility/string.rb +494 -0
- data/lib/accessibility/translator.rb +178 -0
- data/lib/accessibility/version.rb +7 -0
- data/lib/accessibility.rb +79 -0
- data/lib/ax/application.rb +234 -0
- data/lib/{ax_elements/elements → ax}/button.rb +2 -0
- data/lib/ax/element.rb +518 -0
- data/lib/{ax_elements/elements → ax}/radio_button.rb +2 -0
- data/lib/ax/row.rb +37 -0
- data/lib/{ax_elements/elements → ax}/static_text.rb +2 -0
- data/lib/ax/systemwide.rb +86 -0
- data/lib/ax_elements/awesome_print.rb +25 -0
- data/lib/ax_elements/exception_workaround.rb +8 -0
- data/lib/ax_elements/nsarray_compat.rb +64 -0
- data/lib/ax_elements/vendor/inflection_data.rb +65 -0
- data/lib/ax_elements/vendor/inflections.rb +172 -0
- data/lib/ax_elements/vendor/inflector.rb +306 -0
- data/lib/ax_elements.rb +14 -25
- data/lib/minitest/ax_elements.rb +112 -12
- data/lib/mouse.rb +72 -46
- data/lib/rspec/expectations/ax_elements.rb +133 -6
- data/rakelib/doc.rake +13 -0
- data/rakelib/ext.rake +61 -0
- data/rakelib/gem.rake +28 -0
- data/rakelib/test.rake +53 -0
- data/test/helper.rb +11 -97
- data/test/integration/accessibility/test_core.rb +18 -0
- data/test/integration/accessibility/test_debug.rb +44 -0
- data/test/integration/accessibility/test_dsl.rb +225 -0
- data/test/integration/accessibility/test_enumerators.rb +122 -0
- data/test/integration/accessibility/test_errors.rb +38 -0
- data/test/integration/accessibility/test_notifications.rb +22 -0
- data/test/integration/accessibility/test_qualifier.rb +148 -0
- data/test/integration/ax/test_application.rb +56 -0
- data/test/integration/ax/test_element.rb +46 -0
- data/test/integration/ax/test_row.rb +23 -0
- data/test/integration/ax_elements/test_nsarray_compat.rb +43 -0
- data/test/integration/minitest/test_ax_elements.rb +98 -0
- data/test/integration/rspec/expectations/test_ax_elements.rb +58 -0
- data/test/integration/test_mouse.rb +35 -0
- data/test/sanity/accessibility/test_core.rb +553 -0
- data/test/sanity/accessibility/test_debug.rb +63 -0
- data/test/sanity/accessibility/test_dsl.rb +75 -0
- data/test/sanity/accessibility/test_errors.rb +10 -0
- data/test/sanity/accessibility/test_factory.rb +88 -0
- data/test/sanity/accessibility/test_pp_inspector.rb +110 -0
- data/test/sanity/accessibility/test_qualifier.rb +13 -0
- data/test/sanity/accessibility/test_string.rb +238 -0
- data/test/sanity/accessibility/test_translator.rb +145 -0
- data/test/sanity/ax/test_application.rb +90 -0
- data/test/sanity/ax/test_element.rb +80 -0
- data/test/sanity/ax/test_systemwide.rb +66 -0
- data/test/sanity/ax_elements/test_nsarray_compat.rb +16 -0
- data/test/sanity/ax_elements/test_nsobject_inspect.rb +11 -0
- data/test/sanity/minitest/test_ax_elements.rb +15 -0
- data/test/sanity/rspec/expectations/test_ax_elements.rb +12 -0
- data/test/sanity/test_ax_elements.rb +10 -0
- data/test/sanity/test_mouse.rb +19 -0
- metadata +111 -93
- data/LICENSE.txt +0 -25
- data/ext/key_coder/extconf.rb +0 -6
- data/ext/key_coder/key_coder.m +0 -77
- data/lib/ax_elements/accessibility/enumerators.rb +0 -104
- data/lib/ax_elements/accessibility/graph.rb +0 -118
- data/lib/ax_elements/accessibility/language.rb +0 -347
- data/lib/ax_elements/accessibility/qualifier.rb +0 -73
- data/lib/ax_elements/accessibility.rb +0 -166
- data/lib/ax_elements/core.rb +0 -541
- data/lib/ax_elements/element.rb +0 -593
- data/lib/ax_elements/elements/application.rb +0 -88
- data/lib/ax_elements/elements/row.rb +0 -30
- data/lib/ax_elements/elements/systemwide.rb +0 -46
- data/lib/ax_elements/macruby_extensions.rb +0 -255
- data/lib/ax_elements/notification.rb +0 -37
- data/lib/ax_elements/version.rb +0 -9
- data/test/elements/test_application.rb +0 -72
- data/test/elements/test_row.rb +0 -27
- data/test/elements/test_systemwide.rb +0 -38
- data/test/test_accessibility.rb +0 -127
- data/test/test_blankness.rb +0 -26
- data/test/test_core.rb +0 -448
- data/test/test_element.rb +0 -939
- data/test/test_enumerators.rb +0 -81
- data/test/test_inspector.rb +0 -130
- data/test/test_language.rb +0 -157
- data/test/test_macruby_extensions.rb +0 -303
- data/test/test_mouse.rb +0 -5
- data/test/test_search_semantics.rb +0 -143
data/.yardopts
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
--asset docs/images:images
|
7
7
|
--readme README.markdown
|
8
8
|
lib/**/*.rb
|
9
|
-
ext
|
9
|
+
ext/**/*{.m,.c}
|
10
10
|
-
|
11
11
|
docs/Inspecting.markdown
|
12
12
|
docs/Acting.markdown
|
@@ -17,4 +17,3 @@ docs/Debugging.markdown
|
|
17
17
|
docs/NewBehaviour.markdown
|
18
18
|
docs/AccessibilityTips.markdown
|
19
19
|
docs/TestingExtensions.markdown
|
20
|
-
LICENSE.txt
|
data/README.markdown
CHANGED
@@ -9,58 +9,141 @@ GUI manipulation, whether it be finding controls on the screen,
|
|
9
9
|
typing, clicking, or other ways in which a user can interact with the
|
10
10
|
computer.
|
11
11
|
|
12
|
+
|
13
|
+
## Demo
|
14
|
+
|
15
|
+
Perhaps you want to do something with the finder. This example opens a
|
16
|
+
new Finder window, finds Activity Monitor, and then opens the application
|
17
|
+
from a quick look window:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'rubygems'
|
21
|
+
require 'ax_elements'
|
22
|
+
|
23
|
+
finder = app_with_bundle_identifier 'com.apple.finder'
|
24
|
+
set_focus finder # bring to the front so you can see it happening
|
25
|
+
|
26
|
+
type "\\COMMAND+n"
|
27
|
+
sleep 1 # this is so you can see it happen in "slow motion"
|
28
|
+
|
29
|
+
window = finder.main_window
|
30
|
+
click window.outline.row(static_text: { value: 'Applications' })
|
31
|
+
|
32
|
+
utilities = window.row(text_field: { filename: 'Utilities' })
|
33
|
+
scroll_to utilities
|
34
|
+
double_click utilities
|
35
|
+
|
36
|
+
activity_monitor = window.text_field( filename: /Activity Monitor/ )
|
37
|
+
scroll_to activity_monitor
|
38
|
+
click activity_monitor
|
39
|
+
type " " # type a space, which should bring up quick look
|
40
|
+
sleep 1
|
41
|
+
|
42
|
+
click finder.quick_look.button(id: 'QLControlOpen')
|
43
|
+
```
|
44
|
+
|
45
|
+
A simpler example would be changing the system volume by moving the
|
46
|
+
slider in the menu bar (unless you've hidden it):
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'rubygems'
|
50
|
+
require 'ax_elements'
|
51
|
+
|
52
|
+
ui = app_with_bundle_id 'com.apple.systemuiserver'
|
53
|
+
volume = ui.menu_extra(description: 'system sound volume')
|
54
|
+
|
55
|
+
click volume
|
56
|
+
15.times { decrement volume.slider }
|
57
|
+
15.times { increment volume.slider }
|
58
|
+
```
|
59
|
+
|
60
|
+
|
12
61
|
## Getting Setup
|
13
62
|
|
14
63
|
You need to have the OS X developer tools installed in build and
|
15
64
|
install AXElements (sorry). Go ahead and install the tools now if you
|
16
|
-
haven't done that yet, I'll wait.
|
17
|
-
|
18
|
-
|
19
|
-
latest release should be sufficient, but nightly builds are usually
|
20
|
-
safe as well. If you are on Snow Leopard, you will also need to
|
21
|
-
install the
|
65
|
+
haven't done that yet, I'll wait. Once you have the developer tools,
|
66
|
+
you should install MacRuby, the latest nightly build is required. If you
|
67
|
+
are on Snow Leopard, you will also need to install the
|
22
68
|
[Bridge Support Preview](http://www.macruby.org/blog/2010/10/08/bridgesupport-preview.html).
|
23
69
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
70
|
+
Then you can install AXElements. You can install AXElements via
|
71
|
+
rubygems:
|
72
|
+
|
73
|
+
```bash
|
74
|
+
gem install AXElements
|
75
|
+
```
|
76
|
+
|
77
|
+
Or you can install from source:
|
28
78
|
|
29
|
-
|
79
|
+
```bash
|
80
|
+
cd ~/Documents # or where you want to put the AXElements code
|
81
|
+
git clone git://github.com/Marketcircle/AXElements
|
82
|
+
cd AXElements
|
83
|
+
rake install
|
84
|
+
```
|
30
85
|
|
31
|
-
|
32
|
-
|
33
|
-
`rake` in the documentation. Also, remember that if you are not using
|
34
|
-
RVM with MacRuby but still have RVM installed then you will need to
|
35
|
-
disable RVM like so:
|
86
|
+
AXElements has no gem dependencies, so you can try it out in `macirb` at
|
87
|
+
this point:
|
36
88
|
|
89
|
+
```bash
|
90
|
+
rake console
|
91
|
+
```
|
92
|
+
|
93
|
+
__NOTE__: If you are not using RVM, then you should use `macrake`
|
94
|
+
instead of `rake`, and do so for any other references to `rake` in the
|
95
|
+
documentation. You may also need to add `sudo` to your command when you
|
96
|
+
install the gem. Also, remember that if you are not using RVM with
|
97
|
+
MacRuby but still have RVM installed then you will need to disable RVM
|
98
|
+
like so:
|
99
|
+
|
100
|
+
```bash
|
37
101
|
rvm use system
|
102
|
+
```
|
38
103
|
|
39
|
-
Once you are setup, you can start looking through the tutorial
|
40
|
-
documentation to show you how to use AXElements. The first tutorial is
|
41
|
-
the {file:docs/Inspecting.markdown Inspecting tutorial}. The full list
|
42
|
-
of topics include:
|
43
104
|
|
44
|
-
|
45
|
-
* {file:docs/Acting.markdown Acting}
|
46
|
-
* {file:docs/Searching.markdown Searching}
|
47
|
-
* {file:docs/Notifications.markdown Notifications}
|
48
|
-
* {file:docs/KeyboardEvents.markdown Keyboard}
|
49
|
-
* {file:docs/Debugging.markdown Debugging}
|
50
|
-
* {file:docs/NewBehaviour.markdown Adding Behaviour To AXElements}
|
51
|
-
* {file:docs/AccessibilityTips.markdown Making Your Apps More Accessibile}
|
52
|
-
* {file:docs/TestingExtensions.markdown Test Suite Extensions for RSpec, Minitest, etc.}
|
105
|
+
## Getting Started
|
53
106
|
|
54
|
-
|
107
|
+
The
|
108
|
+
[documentation](http://rdoc.info/github/Marketcircle/AXElements/master/frames)
|
109
|
+
is the best place to get started, it includes tutorials to help you get
|
110
|
+
started as well the API documentation (API docs are broken right now due
|
111
|
+
to incompatabilities between MacRuby and YARD). The starting tutorial is the
|
112
|
+
[Inspecting Tutorial](docs/Inspecting.markdown).
|
55
113
|
|
56
|
-
|
57
|
-
|
58
|
-
documentation
|
59
|
-
|
114
|
+
Documentation is hosted by rdoc.info, but you can also generate it yourself
|
115
|
+
using YARD. Documentation is stored in the `docs/` directory, but the
|
116
|
+
documentation includes a number of cross references and even some
|
117
|
+
pictures so you will lose a lot of the quality if you view them as
|
118
|
+
plain text.
|
60
119
|
|
61
120
|
Though it is not required, you may want to read Apple's
|
62
121
|
[Accessibility Overview](http://developer.apple.com/library/mac/#documentation/Accessibility/Conceptual/AccessibilityMacOSX/OSXAXModel/OSXAXmodel.html)
|
63
|
-
as a primer on some the
|
122
|
+
as a primer on some the rationale for the accessibility APIs as well
|
123
|
+
as the technical underpinnings of AXElements.
|
124
|
+
|
125
|
+
|
126
|
+
## Development
|
127
|
+
|
128
|
+
Development of a stable release of AXElements is under way! The main
|
129
|
+
focus is an overall refactoring to create a more robust core, end user
|
130
|
+
features will become more consistent, and performance will
|
131
|
+
increase. Documentation will be overhauled and more examples will be
|
132
|
+
added. It will be magical, so we're code naming the next version
|
133
|
+
"Clefairy".
|
134
|
+
|
135
|
+
![The Moon](https://github.com/Marketcircle/AXElements/raw/master/docs/images/next_version.png)
|
136
|
+
|
137
|
+
Proper releases to rubygems will be made as milestones are reached.
|
138
|
+
|
139
|
+
### Road Map
|
140
|
+
|
141
|
+
There are still a bunch of things that could be done to improve
|
142
|
+
AXElements. Some of the higher level tasks are outlined in various
|
143
|
+
[Github Issues](http://github.com/Marketcircle/AXElements/issues).
|
144
|
+
Smaller items are peppered through the code base and marked with `@todo`
|
145
|
+
tags.
|
146
|
+
|
64
147
|
|
65
148
|
## Test Suite
|
66
149
|
|
@@ -68,18 +151,18 @@ Before starting development on your machine, you should run the test
|
|
68
151
|
suite and make sure things are kosher. The nature of this library
|
69
152
|
requires that the tests take over your computer while they run. The
|
70
153
|
tests aren't programmed to do anything destructive, but if you
|
71
|
-
interfere with them then something could go wrong.
|
72
|
-
|
73
|
-
To run the tests you simply need to run the `test` task:
|
154
|
+
interfere with them then something could go wrong. To run the tests
|
155
|
+
you simply need to run the `test` task:
|
74
156
|
|
75
157
|
rake test
|
76
158
|
|
77
|
-
__NOTE__:
|
159
|
+
__NOTE__: There may be some tests are dependent on Accessibility
|
78
160
|
features that are new in OS X Lion which will cause test failures on
|
79
161
|
OS X Snow Leopard. If you have any issues then you should look at the
|
80
|
-
output to find hints at what went wrong and/or log a bug.
|
81
|
-
support Snow Leopard as long as MacRuby does, but I do not
|
82
|
-
access to a Snow Leopard machine to verify that things still
|
162
|
+
output to find hints at what went wrong and/or log a bug. AXElements
|
163
|
+
will support Snow Leopard for as long as MacRuby does, but I do not
|
164
|
+
have easy access to a Snow Leopard machine to verify that things still
|
165
|
+
work.
|
83
166
|
|
84
167
|
### Benchmarks
|
85
168
|
|
@@ -89,46 +172,6 @@ disabled by default. In order to enable them you need to set the
|
|
89
172
|
|
90
173
|
BENCH=1 rake test
|
91
174
|
|
92
|
-
Benchmarks only exist for code that is known to be slow. I'm keeping
|
93
|
-
tabs on slow code so that I be confident about getting depressed when
|
94
|
-
it gets slower. Though, there is still room for improved performance
|
95
|
-
as well.
|
96
|
-
|
97
|
-
## Road Map
|
98
|
-
|
99
|
-
There are still a bunch of things that could be done to improve
|
100
|
-
AXElements. The README only contains an idealized outline of some of
|
101
|
-
the high-level items that should get done in the next couple of
|
102
|
-
releases. Smaller items are peppered through the code base and marked
|
103
|
-
with `@todo` tags.
|
104
|
-
|
105
|
-
### 0.7 (or maybe 1.0)
|
106
|
-
|
107
|
-
- Pre-loading AX hierarchy and attribute cache from
|
108
|
-
`/System/Library/Accessibility/AccessibilityDefinitions.plist`
|
109
|
-
+ Not available on Snow Leopard, so it will have to wait anyways
|
110
|
-
+ Probably inccurs too much overhead at boot time right now
|
111
|
-
- Make a decision about NSArray#method_missing
|
112
|
-
- Merge notifications with actions as they are commonly combined
|
113
|
-
+ But how?
|
114
|
-
- Rewrite core module to handle errors more gracefully
|
115
|
-
- Mouse module cleanup and regression testing
|
116
|
-
- Test suite deduplication cleanup and better isolation
|
117
|
-
- Performance tweaks
|
118
|
-
- The OO abstraction leaks in a few places, code needs to be
|
119
|
-
refactored without hurting performance too much
|
120
|
-
- Test framework helpers
|
121
|
-
+ Minitest
|
122
|
-
+ RSpec
|
123
|
-
- Thread Safety
|
124
|
-
+ Only if it becomes an issue, otherwise it might be better to
|
125
|
-
forget thread safey to simplify and optimize existing code
|
126
|
-
|
127
|
-
### Future
|
128
|
-
|
129
|
-
- Screenshot taking and diff'ing abilities for those rare cases when
|
130
|
-
you need it
|
131
|
-
- Address Book helpers, and other friends
|
132
175
|
|
133
176
|
## Contributing to AXElements
|
134
177
|
|
@@ -140,11 +183,32 @@ with `@todo` tags.
|
|
140
183
|
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
141
184
|
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
142
185
|
|
143
|
-
## Copyright
|
144
|
-
|
145
|
-
Copyright (c) 2010-2011 Marketcircle Incorporated. All rights
|
146
|
-
reserved.
|
147
186
|
|
148
|
-
|
149
|
-
{file:LICENSE.txt LICENSE.txt} for further details.
|
187
|
+
## Copyright
|
150
188
|
|
189
|
+
Copyright (c) 2010-2012, Marketcircle Inc.
|
190
|
+
All rights reserved.
|
191
|
+
|
192
|
+
Redistribution and use in source and binary forms, with or without
|
193
|
+
modification, are permitted provided that the following conditions are met:
|
194
|
+
|
195
|
+
* Redistributions of source code must retain the above copyright
|
196
|
+
notice, this list of conditions and the following disclaimer.
|
197
|
+
* Redistributions in binary form must reproduce the above copyright
|
198
|
+
notice, this list of conditions and the following disclaimer in the
|
199
|
+
documentation and/or other materials provided with the distribution.
|
200
|
+
* Neither the name of Marketcircle Inc. nor the names of its
|
201
|
+
contributors may be used to endorse or promote products derived
|
202
|
+
from this software without specific prior written permission.
|
203
|
+
|
204
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
205
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
206
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
207
|
+
DISCLAIMED. IN NO EVENT SHALL Marketcircle Inc. BE LIABLE FOR ANY
|
208
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
209
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
210
|
+
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
211
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
212
|
+
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
213
|
+
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
214
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Rakefile
CHANGED
@@ -1,109 +1,14 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
|
-
task :default => :
|
4
|
-
task :clean => :clobber
|
5
|
-
|
6
|
-
def safe_require path, name
|
7
|
-
require path
|
8
|
-
yield
|
9
|
-
rescue LoadError => e
|
10
|
-
$stderr.puts "It seems as though you do not have #{name} installed."
|
11
|
-
command = ENV['RUBY_VERSION'] ? 'gem' : 'sudo macgem'
|
12
|
-
$stderr.puts "You can install it by running `#{command} install #{name}`."
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
## Documentation
|
17
|
-
|
18
|
-
safe_require 'yard', 'yard' do
|
19
|
-
YARD::Rake::YardocTask.new
|
20
|
-
end
|
21
|
-
|
22
|
-
desc 'Generate Graphviz object graph'
|
23
|
-
task :garden => :yard do
|
24
|
-
sh 'yard graph --full --dependencies --dot="-Tpng:quartz" -f docs/images/AX.dot'
|
25
|
-
end
|
26
|
-
|
27
|
-
## Console
|
28
|
-
|
29
|
-
desc 'Start up irb with AXElements loaded'
|
30
|
-
task :console => :ext do
|
31
|
-
irb = ENV['RUBY_VERSION'] ? 'irb' : 'macirb'
|
32
|
-
sh "#{irb} -Ilib -Iext/key_coder -rubygems -rax_elements"
|
33
|
-
end
|
34
|
-
|
35
|
-
## Compilation
|
36
|
-
|
37
|
-
require 'rake/compiletask'
|
38
|
-
Rake::CompileTask.new
|
39
|
-
|
40
|
-
desc 'Compile C extensions'
|
41
|
-
task :ext do
|
42
|
-
Dir.chdir 'ext/key_coder' do
|
43
|
-
break if File.exists?('key_coder.bundle') && File.mtime('key_coder.bundle') > File.mtime('key_coder.m')
|
44
|
-
ruby 'extconf.rb'
|
45
|
-
sh 'make'
|
46
|
-
end
|
47
|
-
end
|
3
|
+
task :default => :test
|
48
4
|
|
49
|
-
desc '
|
50
|
-
task :
|
51
|
-
|
52
|
-
['Makefile', 'key_coder.o', 'key_coder.bundle'].each do |file|
|
53
|
-
$stdout.puts "rm ext/key_coder/#{file}"
|
54
|
-
rm file
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
5
|
+
desc 'Remove all generated files'
|
6
|
+
task :clean => :clobber
|
7
|
+
desc 'Remove all generated files'
|
58
8
|
task :clobber => :clobber_ext
|
59
9
|
|
60
|
-
|
61
|
-
|
62
|
-
desc 'Open the fixture app'
|
63
|
-
task :run_fixture => :fixture do
|
64
|
-
sh 'open test/fixture/Release/AXElementsTester.app'
|
65
|
-
end
|
66
|
-
|
67
|
-
desc 'Build the test fixture'
|
68
|
-
task :fixture do
|
69
|
-
sh 'cd test/AXElementsTester && xcodebuild'
|
70
|
-
end
|
71
|
-
|
72
|
-
require 'rake/testtask'
|
73
|
-
Rake::TestTask.new do |t|
|
74
|
-
t.libs << 'test' << 'ext/key_coder'
|
75
|
-
t.pattern = 'test/**/test_*.rb'
|
76
|
-
t.ruby_opts = ['-rhelper']
|
77
|
-
t.verbose = true
|
78
|
-
end
|
79
|
-
task :test => [:ext, :fixture]
|
80
|
-
|
81
|
-
## Gem Packaging
|
82
|
-
require 'rubygems/dependency_installer'
|
83
|
-
require 'rake/gempackagetask'
|
84
|
-
|
85
|
-
spec = Gem::Specification.load('AXElements.gemspec')
|
86
|
-
|
87
|
-
Rake::GemPackageTask.new(spec) { }
|
88
|
-
|
89
|
-
# This only installs this gem, it does not take deps into consideration
|
90
|
-
desc 'Build gem and install it'
|
91
|
-
task :install => :gem do
|
92
|
-
Gem::Installer.new("pkg/#{spec.file_name}").install
|
93
|
-
end
|
94
|
-
|
95
|
-
desc 'Install dependencies for a test node'
|
96
|
-
task :setup_node do
|
97
|
-
spec.runtime_dependencies.each do |dep|
|
98
|
-
puts "Installing #{dep.name}"
|
99
|
-
Gem::DependencyInstaller.new.install(dep.name, dep.requirement)
|
100
|
-
end
|
101
|
-
end
|
10
|
+
desc 'Compile C extensions'
|
11
|
+
task :ext => 'ext:key_coder'
|
102
12
|
|
103
|
-
desc '
|
104
|
-
task :
|
105
|
-
spec.development_dependencies.each do |dep|
|
106
|
-
puts "Installing #{dep.name}"
|
107
|
-
Gem::DependencyInstaller.new.install(dep.name, dep.requirement)
|
108
|
-
end
|
109
|
-
end
|
13
|
+
desc 'Run all tests'
|
14
|
+
task :test => ['test:sanity', 'test:integration', 'test:cruby']
|
data/docs/Debugging.markdown
CHANGED
@@ -69,6 +69,13 @@ want to have turned into a dot graph; you will get a string back that
|
|
69
69
|
you will then need to give to Graphviz in order to generate the visual
|
70
70
|
graph.
|
71
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
|
+
|
72
79
|
### Text Tree Won't Print?
|
73
80
|
|
74
81
|
AXElements isn't perfect and it is possible that an edge case slipped
|
@@ -81,8 +88,8 @@ AXElements was that you could not search through the menu bar causing
|
|
81
88
|
a text dump to fail in a very difficult to trace manner.
|
82
89
|
|
83
90
|
In these cases you will need to use your deductive reasoning to figure
|
84
|
-
out where the problem is coming from. Fortunately,
|
85
|
-
tools to help you along the way.
|
91
|
+
out where the problem is coming from. Fortunately, I have provided
|
92
|
+
some tools to help you along the way.
|
86
93
|
|
87
94
|
## All The Way Up
|
88
95
|
|
@@ -1,57 +1,122 @@
|
|
1
1
|
# Keyboard Events
|
2
2
|
|
3
|
-
|
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.
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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.
|
9
19
|
|
10
|
-
|
11
|
-
navigation or hotkey activation.
|
20
|
+
## Typing with the DSL
|
12
21
|
|
13
|
-
The DSL exposes
|
14
|
-
would look like this:
|
22
|
+
The {Accessibility::DSL} mix-in exposes keyboard events through the
|
23
|
+
`type` method. A simple example would look like this:
|
15
24
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
19
101
|
|
20
102
|
In order make sure that certain sequences of characters are properly
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
to
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
<table style="1px solid black">
|
42
|
-
<tr><td>Key</td><td>Escape Sequence</td></tr>
|
43
|
-
<tr><td>Delete Backwards (Backspace)</td><td>`\b`</td></tr>
|
44
|
-
<tr><td>Enter</td><td>`\n` or `\r`</td></tr>
|
45
|
-
<tr><td>Control</td><td>`\^`</td></tr>
|
46
|
-
<tr><td>Command</td><td>`\C`</td></tr>
|
47
|
-
<tr><td>Option/Alt</td><td>`\O`</td></tr>
|
48
|
-
<tr><td>Tab</td><td>`\t`</td></tr>
|
49
|
-
<tr><td>Escape</td><td>`\e`</td></tr>
|
50
|
-
<tr><td>Space</td><td>` `</td></tr>
|
51
|
-
<tr><td>Scroll To Top</td><td>`\x01`</td></tr>
|
52
|
-
<tr><td>Scroll To Bottom</td><td>`\x04`</td></tr>
|
53
|
-
<tr><td>Page Down</td><td>`\f`</td></tr>
|
54
|
-
<tr><td>Left Arrow</td><td>`\\<->`</td></tr>
|
55
|
-
<tr><td>Right Arrow</td><td>`\\->`</td></tr>
|
56
|
-
<tr><td>Down Arrow</td><td>`\DOWN`</td></tr>
|
57
|
-
</table>
|
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
|
@@ -0,0 +1 @@
|
|
1
|
+
You can use ruby ranges, but there is one caveat, which is that negative ranges will have to be converted ahead of time by the programmer, but only if you are using Core directly. If you are using an AX::Element derived class then it will Just Work™.
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
$CFLAGS << ' -std=c99 -Wall -Werror -ObjC'
|
4
|
+
$LIBS << ' -framework Cocoa -framework Carbon -framework ApplicationServices'
|
5
|
+
|
6
|
+
if RUBY_ENGINE == 'macruby'
|
7
|
+
$CFLAGS << ' -fobjc-gc'
|
8
|
+
else
|
9
|
+
unless RbConfig::CONFIG["CC"].match /clang/
|
10
|
+
clang = `which clang`.chomp
|
11
|
+
if clang.empty?
|
12
|
+
$stdout.puts "Clang not installed. Cannot build C extension"
|
13
|
+
exit 1
|
14
|
+
else
|
15
|
+
RbConfig::MAKEFILE_CONFIG["CC"] = clang
|
16
|
+
RbConfig::MAKEFILE_CONFIG["CXX"] = clang
|
17
|
+
end
|
18
|
+
end
|
19
|
+
$CFLAGS << ' -DNOT_MACRUBY'
|
20
|
+
end
|
21
|
+
|
22
|
+
create_makefile('accessibility/key_coder')
|