AXElements 1.0.0.beta4 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/History.markdown +7 -0
- data/README.markdown +41 -29
- data/Rakefile +1 -6
- data/lib/accessibility/dsl.rb +17 -15
- data/lib/accessibility/pretty_printer.rb +40 -12
- data/lib/accessibility/system_info.rb +2 -0
- data/lib/accessibility/text_highlighter.rb +73 -0
- data/lib/accessibility/translator.rb +1 -0
- data/lib/accessibility/version.rb +1 -1
- data/lib/accessibility.rb +13 -114
- data/lib/ax/application.rb +54 -42
- data/lib/ax/element.rb +27 -7
- data/lib/ax/scroll_area.rb +1 -0
- data/lib/ax/systemwide.rb +5 -4
- data/lib/ax/text_area.rb +16 -0
- data/lib/ax/text_field.rb +10 -0
- data/lib/ax_elements/mri.rb +36 -1
- data/rakelib/ci.rake +9 -0
- data/rakelib/doc.rake +4 -13
- data/rakelib/ext.rake +1 -57
- data/rakelib/gem.rake +7 -23
- data/rakelib/test.rake +10 -17
- data/test/helper.rb +15 -18
- data/test/integration/accessibility/test_dsl.rb +9 -3
- data/test/integration/ax/test_application.rb +1 -1
- data/test/integration/ax/test_text_area.rb +62 -0
- data/test/integration/ax/test_text_field.rb +49 -0
- data/test/sanity/accessibility/test_dsl.rb +1 -0
- data/test/sanity/accessibility/test_errors.rb +1 -1
- data/test/sanity/accessibility/test_pretty_printer.rb +6 -1
- data/test/sanity/accessibility/test_qualifier.rb +1 -1
- data/test/sanity/accessibility/test_system_info.rb +109 -0
- data/test/sanity/accessibility/test_translator.rb +1 -1
- data/test/sanity/accessibility/test_version.rb +2 -2
- data/test/sanity/ax_elements/test_nsarray_compat.rb +1 -1
- data/test/sanity/ax_elements/test_nsobject_inspect.rb +1 -1
- data/test/sanity/test_ax_elements.rb +1 -1
- metadata +34 -59
- data/ext/accessibility/key_coder/extconf.rb +0 -22
- data/ext/accessibility/key_coder/key_coder.c +0 -123
- data/lib/accessibility/string.rb +0 -502
- data/test/sanity/accessibility/test_string.rb +0 -238
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test/integration/helper'
|
2
|
+
|
3
|
+
class TestAXTextField < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def search_field
|
6
|
+
@field ||= app.main_window.search_field
|
7
|
+
end
|
8
|
+
|
9
|
+
def setup
|
10
|
+
search_field.value = 'The cake is a lie!'
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
search_field.value = ''
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
# @group Tests
|
19
|
+
|
20
|
+
def test_highlight_text_regexp
|
21
|
+
[
|
22
|
+
/cake/,
|
23
|
+
/The/,
|
24
|
+
/e!/,
|
25
|
+
/a/
|
26
|
+
].each do |expected|
|
27
|
+
search_field.highlight_text expected
|
28
|
+
actual = search_field.selected_text
|
29
|
+
expected = search_field.value
|
30
|
+
assert_equal expected, actual, expected
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_highlight_text_string
|
35
|
+
expected = 'is a'
|
36
|
+
search_field.highlight_text expected
|
37
|
+
actual = search_field.selected_text
|
38
|
+
assert_equal expected, actual
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_highlight_text_range
|
42
|
+
range = 5..10
|
43
|
+
expected = search_field.value[range]
|
44
|
+
search_field.highlight_text range
|
45
|
+
actual = search_field.selected_text
|
46
|
+
assert_equal expected, actual
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -66,6 +66,8 @@ class TestAccessibilityPrettyPrinter < MiniTest::Unit::TestCase
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def test_position
|
69
|
+
@attributes = [:position]
|
70
|
+
|
69
71
|
@attribute = CGPoint.new
|
70
72
|
assert_match /\(0\.0, 0\.0\)/, pp_position
|
71
73
|
|
@@ -75,11 +77,14 @@ class TestAccessibilityPrettyPrinter < MiniTest::Unit::TestCase
|
|
75
77
|
|
76
78
|
# this sometimes happens, even though it shouldn't
|
77
79
|
def test_position_is_nil
|
78
|
-
@
|
80
|
+
@attributes = [:position]
|
81
|
+
@attribute = nil
|
79
82
|
assert_equal EMPTY_STRING, pp_position
|
80
83
|
end
|
81
84
|
|
82
85
|
def test_children_pluralizes_properly
|
86
|
+
@attributes = [:children]
|
87
|
+
|
83
88
|
[[2, /2 children/ ],
|
84
89
|
[9001, /9001 children/],
|
85
90
|
[3.14, /3.14 children/],
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
require 'accessibility/system_info'
|
3
|
+
|
4
|
+
class TestAcessibilitySystemInfo < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def test_name
|
7
|
+
name = Accessibility::SystemInfo.name
|
8
|
+
assert_kind_of String, name
|
9
|
+
refute_empty name
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_hostnames
|
13
|
+
names = Accessibility::SystemInfo.hostnames
|
14
|
+
assert_kind_of Array, names
|
15
|
+
assert_kind_of String, names.first
|
16
|
+
names.each { |name| refute_empty name }
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_hostname
|
20
|
+
name = Accessibility::SystemInfo.hostname
|
21
|
+
assert_kind_of String, name
|
22
|
+
refute_empty name
|
23
|
+
assert_includes Accessibility::SystemInfo.hostnames, name
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_addresses
|
27
|
+
addresses = Accessibility::SystemInfo.addresses
|
28
|
+
assert_kind_of Array, addresses
|
29
|
+
assert_kind_of String, addresses.first
|
30
|
+
addresses.each { |addr| refute_empty addr }
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_ipv4_addresses
|
34
|
+
addresses = Accessibility::SystemInfo.ipv4_addresses
|
35
|
+
assert_kind_of Array, addresses
|
36
|
+
assert_kind_of String, addresses.first, "Do you have IPv4 disabled?"
|
37
|
+
home = addresses.find { |addr| addr.match(/127.0.0.1/) }
|
38
|
+
refute_nil home
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_ipv6_addresses
|
42
|
+
addresses = Accessibility::SystemInfo.ipv6_addresses
|
43
|
+
assert_kind_of Array, addresses
|
44
|
+
assert_kind_of String, addresses.first, "Do you have IPv6 disabled?"
|
45
|
+
home = addresses.find { |addr| addr.match(/::1/) }
|
46
|
+
refute_nil home
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_model
|
50
|
+
model = Accessibility::SystemInfo.model
|
51
|
+
assert_kind_of String, model
|
52
|
+
refute_empty model
|
53
|
+
# this assuming that all Macs have Mac in the model name
|
54
|
+
assert_match /Mac/, model
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_osx_version
|
58
|
+
version = Accessibility::SystemInfo.osx_version
|
59
|
+
assert_kind_of String, version
|
60
|
+
refute_empty version
|
61
|
+
assert_match /^Version 10\.\d+\.\d+ \(Build [\dA-Z]+\)$/, version
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_uptime
|
65
|
+
time = Accessibility::SystemInfo.uptime
|
66
|
+
assert_kind_of Float, time
|
67
|
+
assert time > 0.0
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_num_processors
|
71
|
+
procs = Accessibility::SystemInfo.num_processors
|
72
|
+
assert_kind_of Fixnum, procs
|
73
|
+
assert procs > 0
|
74
|
+
assert_equal Accessibility::SystemInfo.number_of_processors, procs
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_num_active_processors
|
78
|
+
procs = Accessibility::SystemInfo.num_active_processors
|
79
|
+
assert_kind_of Fixnum, procs
|
80
|
+
assert procs > 0
|
81
|
+
assert_equal Accessibility::SystemInfo.number_of_active_processors, procs
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_total_ram
|
85
|
+
ram = Accessibility::SystemInfo.total_ram
|
86
|
+
assert_kind_of Fixnum, ram
|
87
|
+
assert ram > 2.gigabytes # everyone has more than 2GB of RAM these days...right?
|
88
|
+
assert_equal Accessibility::SystemInfo.ram, ram
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_battery_state
|
92
|
+
state = Accessibility::SystemInfo.battery_state
|
93
|
+
assert_kind_of Symbol, state
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_battery_charge_level
|
97
|
+
level = Accessibility::SystemInfo.battery_level
|
98
|
+
assert_kind_of Float, level
|
99
|
+
assert level <= 1.0 && level >= -1.0
|
100
|
+
assert_equal Accessibility::SystemInfo.battery_charge_level, level
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_battery_life_estimate
|
104
|
+
est = Accessibility::SystemInfo.battery_life_estimate
|
105
|
+
assert_kind_of Fixnum, est
|
106
|
+
assert est >= -1
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'test/
|
1
|
+
require 'test/helper'
|
2
2
|
require 'accessibility/version'
|
3
3
|
|
4
4
|
class TestAccessibilityVersion < MiniTest::Unit::TestCase
|
@@ -9,7 +9,7 @@ class TestAccessibilityVersion < MiniTest::Unit::TestCase
|
|
9
9
|
|
10
10
|
def test_version_method
|
11
11
|
assert_match Accessibility::VERSION, Accessibility.version
|
12
|
-
assert_match Accessibility::
|
12
|
+
assert_match Accessibility::CODE_NAME, Accessibility.version
|
13
13
|
end
|
14
14
|
|
15
15
|
end
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: AXElements
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease: 6
|
4
|
+
version: 6.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Mark Rada
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-11-26 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: mouse
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: screen_recorder
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: accessibility_core
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,70 +48,46 @@ dependencies:
|
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: 0.4.1
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
56
|
+
name: accessibility_keyboard
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - ~>
|
68
60
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
61
|
+
version: 1.0.0
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 3.2.11
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: yard
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ~>
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: 0.8.3
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
65
|
requirements:
|
91
66
|
- - ~>
|
92
67
|
- !ruby/object:Gem::Version
|
93
|
-
version: 0.
|
68
|
+
version: 1.0.0
|
94
69
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
70
|
+
name: activesupport
|
96
71
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
72
|
requirements:
|
99
73
|
- - ~>
|
100
74
|
- !ruby/object:Gem::Version
|
101
|
-
version: 0.
|
102
|
-
type: :
|
75
|
+
version: 4.0.1
|
76
|
+
type: :runtime
|
103
77
|
prerelease: false
|
104
78
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
79
|
requirements:
|
107
80
|
- - ~>
|
108
81
|
- !ruby/object:Gem::Version
|
109
|
-
version: 0.
|
110
|
-
description:
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
'
|
82
|
+
version: 4.0.1
|
83
|
+
description: |
|
84
|
+
AXElements is a UI automation library built on top of various OS X
|
85
|
+
frameworks. You can use AXElements to write functional tests for
|
86
|
+
Cocoa apps, script UI interactions, or even to build higher level
|
87
|
+
tools such as screen readers.
|
117
88
|
email: mrada@marketcircle.com
|
118
89
|
executables: []
|
119
|
-
extensions:
|
120
|
-
- ext/accessibility/key_coder/extconf.rb
|
90
|
+
extensions: []
|
121
91
|
extra_rdoc_files: []
|
122
92
|
files:
|
123
93
|
- lib/accessibility/dsl.rb
|
@@ -127,8 +97,8 @@ files:
|
|
127
97
|
- lib/accessibility/graph.rb
|
128
98
|
- lib/accessibility/pretty_printer.rb
|
129
99
|
- lib/accessibility/qualifier.rb
|
130
|
-
- lib/accessibility/string.rb
|
131
100
|
- lib/accessibility/system_info.rb
|
101
|
+
- lib/accessibility/text_highlighter.rb
|
132
102
|
- lib/accessibility/translator.rb
|
133
103
|
- lib/accessibility/version.rb
|
134
104
|
- lib/accessibility.rb
|
@@ -142,6 +112,8 @@ files:
|
|
142
112
|
- lib/ax/scroll_area.rb
|
143
113
|
- lib/ax/static_text.rb
|
144
114
|
- lib/ax/systemwide.rb
|
115
|
+
- lib/ax/text_area.rb
|
116
|
+
- lib/ax/text_field.rb
|
145
117
|
- lib/ax_elements/active_support_selections.rb
|
146
118
|
- lib/ax_elements/awesome_print.rb
|
147
119
|
- lib/ax_elements/exception_workaround.rb
|
@@ -149,8 +121,7 @@ files:
|
|
149
121
|
- lib/ax_elements/nsarray_compat.rb
|
150
122
|
- lib/ax_elements.rb
|
151
123
|
- lib/AXElements.rb
|
152
|
-
-
|
153
|
-
- ext/accessibility/key_coder/key_coder.c
|
124
|
+
- rakelib/ci.rake
|
154
125
|
- rakelib/doc.rake
|
155
126
|
- rakelib/ext.rake
|
156
127
|
- rakelib/gem.rake
|
@@ -168,13 +139,15 @@ files:
|
|
168
139
|
- test/integration/ax/test_element.rb
|
169
140
|
- test/integration/ax/test_menu.rb
|
170
141
|
- test/integration/ax/test_row.rb
|
142
|
+
- test/integration/ax/test_text_area.rb
|
143
|
+
- test/integration/ax/test_text_field.rb
|
171
144
|
- test/integration/ax_elements/test_nsarray_compat.rb
|
172
145
|
- test/sanity/accessibility/test_dsl.rb
|
173
146
|
- test/sanity/accessibility/test_errors.rb
|
174
147
|
- test/sanity/accessibility/test_factory.rb
|
175
148
|
- test/sanity/accessibility/test_pretty_printer.rb
|
176
149
|
- test/sanity/accessibility/test_qualifier.rb
|
177
|
-
- test/sanity/accessibility/
|
150
|
+
- test/sanity/accessibility/test_system_info.rb
|
178
151
|
- test/sanity/accessibility/test_translator.rb
|
179
152
|
- test/sanity/accessibility/test_version.rb
|
180
153
|
- test/sanity/ax/test_application.rb
|
@@ -185,31 +158,30 @@ files:
|
|
185
158
|
- test/sanity/test_accessibility.rb
|
186
159
|
- test/sanity/test_ax_elements.rb
|
187
160
|
- test/helper.rb
|
188
|
-
homepage: http://
|
161
|
+
homepage: http://axelements.com
|
189
162
|
licenses:
|
190
163
|
- BSD 3-clause
|
164
|
+
metadata: {}
|
191
165
|
post_install_message:
|
192
166
|
rdoc_options: []
|
193
167
|
require_paths:
|
194
168
|
- lib
|
195
169
|
required_ruby_version: !ruby/object:Gem::Requirement
|
196
|
-
none: false
|
197
170
|
requirements:
|
198
|
-
- -
|
171
|
+
- - '>='
|
199
172
|
- !ruby/object:Gem::Version
|
200
173
|
version: '0'
|
201
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
|
-
none: false
|
203
175
|
requirements:
|
204
|
-
- -
|
176
|
+
- - '>='
|
205
177
|
- !ruby/object:Gem::Version
|
206
|
-
version:
|
178
|
+
version: '0'
|
207
179
|
requirements: []
|
208
180
|
rubyforge_project:
|
209
|
-
rubygems_version: 1.
|
181
|
+
rubygems_version: 2.1.11
|
210
182
|
signing_key:
|
211
|
-
specification_version:
|
212
|
-
summary:
|
183
|
+
specification_version: 4
|
184
|
+
summary: UI Automation for OS X
|
213
185
|
test_files:
|
214
186
|
- test/integration/accessibility/test_dsl.rb
|
215
187
|
- test/integration/accessibility/test_enumerators.rb
|
@@ -220,13 +192,15 @@ test_files:
|
|
220
192
|
- test/integration/ax/test_element.rb
|
221
193
|
- test/integration/ax/test_menu.rb
|
222
194
|
- test/integration/ax/test_row.rb
|
195
|
+
- test/integration/ax/test_text_area.rb
|
196
|
+
- test/integration/ax/test_text_field.rb
|
223
197
|
- test/integration/ax_elements/test_nsarray_compat.rb
|
224
198
|
- test/sanity/accessibility/test_dsl.rb
|
225
199
|
- test/sanity/accessibility/test_errors.rb
|
226
200
|
- test/sanity/accessibility/test_factory.rb
|
227
201
|
- test/sanity/accessibility/test_pretty_printer.rb
|
228
202
|
- test/sanity/accessibility/test_qualifier.rb
|
229
|
-
- test/sanity/accessibility/
|
203
|
+
- test/sanity/accessibility/test_system_info.rb
|
230
204
|
- test/sanity/accessibility/test_translator.rb
|
231
205
|
- test/sanity/accessibility/test_version.rb
|
232
206
|
- test/sanity/ax/test_application.rb
|
@@ -237,3 +211,4 @@ test_files:
|
|
237
211
|
- test/sanity/test_accessibility.rb
|
238
212
|
- test/sanity/test_ax_elements.rb
|
239
213
|
- test/helper.rb
|
214
|
+
has_rdoc: yard
|
@@ -1,22 +0,0 @@
|
|
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
|
-
raise "Clang not installed. Cannot build C extension"
|
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')
|
@@ -1,123 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* key_coder.c
|
3
|
-
* KeyCoder
|
4
|
-
*
|
5
|
-
* Created by Mark Rada on 11-07-27.
|
6
|
-
* Copyright 2011-2012 Marketcircle Incorporated. All rights reserved.
|
7
|
-
*/
|
8
|
-
|
9
|
-
|
10
|
-
#import <Cocoa/Cocoa.h>
|
11
|
-
#import <Carbon/Carbon.h>
|
12
|
-
#import <ApplicationServices/ApplicationServices.h>
|
13
|
-
|
14
|
-
#include "ruby.h"
|
15
|
-
|
16
|
-
|
17
|
-
/*
|
18
|
-
* Generate the mapping of characters to key codes for keys that can be
|
19
|
-
* remapped based on keyboard layout. Changing the keyboard layout at
|
20
|
-
* runtime will cause the returned hash to be different.
|
21
|
-
*
|
22
|
-
* @example
|
23
|
-
*
|
24
|
-
* KeyCoder.dynamic_mapping => { "a" => 0, "b" => 24, ... }
|
25
|
-
*
|
26
|
-
* @return [Hash{String=>Number}]
|
27
|
-
*/
|
28
|
-
|
29
|
-
static
|
30
|
-
VALUE
|
31
|
-
keycoder_dynamic_mapping()
|
32
|
-
{
|
33
|
-
|
34
|
-
VALUE map = rb_hash_new();
|
35
|
-
|
36
|
-
#ifdef NOT_MACRUBY
|
37
|
-
@autoreleasepool {
|
38
|
-
#endif
|
39
|
-
|
40
|
-
TISInputSourceRef keyboard = TISCopyCurrentKeyboardLayoutInputSource();
|
41
|
-
CFDataRef layout_data = (CFDataRef)TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
|
42
|
-
const UCKeyboardLayout* layout = (const UCKeyboardLayout*)CFDataGetBytePtr(layout_data);
|
43
|
-
|
44
|
-
void (^key_coder)(int) = ^(int key_code) {
|
45
|
-
UniChar string[255];
|
46
|
-
UniCharCount string_length = 0;
|
47
|
-
UInt32 dead_key_state = 0;
|
48
|
-
UCKeyTranslate(
|
49
|
-
layout,
|
50
|
-
key_code,
|
51
|
-
kUCKeyActionDown,
|
52
|
-
0,
|
53
|
-
LMGetKbdType(), // kb type
|
54
|
-
0, // OptionBits keyTranslateOptions,
|
55
|
-
&dead_key_state,
|
56
|
-
255,
|
57
|
-
&string_length,
|
58
|
-
string
|
59
|
-
);
|
60
|
-
|
61
|
-
NSString* nsstring = [NSString stringWithCharacters:string length:string_length];
|
62
|
-
rb_hash_aset(map, rb_str_new_cstr([nsstring UTF8String]), INT2FIX(key_code));
|
63
|
-
};
|
64
|
-
|
65
|
-
// skip 65-92 since they are hard coded and do not change
|
66
|
-
for (int key_code = 0; key_code < 65; key_code++)
|
67
|
-
key_coder(key_code);
|
68
|
-
for (int key_code = 93; key_code < 127; key_code++)
|
69
|
-
key_coder(key_code);
|
70
|
-
|
71
|
-
#ifdef NOT_MACRUBY
|
72
|
-
CFRelease(keyboard);
|
73
|
-
}; // Close the autorelease pool
|
74
|
-
#else
|
75
|
-
CFMakeCollectable(keyboard);
|
76
|
-
#endif
|
77
|
-
|
78
|
-
return map;
|
79
|
-
}
|
80
|
-
|
81
|
-
|
82
|
-
/*
|
83
|
-
* Post the given event to the system and return `true`. This method
|
84
|
-
* will also add a small (9000 microsecond) delay after posting to
|
85
|
-
* ensure that keyboard actions do not go too fast.
|
86
|
-
*
|
87
|
-
* @example
|
88
|
-
*
|
89
|
-
* KeyCoder.post_event [0, true] -> true
|
90
|
-
*
|
91
|
-
* @param [Array(Number, Boolean)]
|
92
|
-
* @return [true]
|
93
|
-
*/
|
94
|
-
|
95
|
-
static
|
96
|
-
VALUE
|
97
|
-
keycoder_post_event(VALUE self, VALUE event)
|
98
|
-
{
|
99
|
-
VALUE code = rb_ary_entry(event, 0);
|
100
|
-
VALUE state = rb_ary_entry(event, 1);
|
101
|
-
|
102
|
-
CGEventRef event_ref = CGEventCreateKeyboardEvent(NULL, FIX2LONG(code), state);
|
103
|
-
CGEventPost(kCGHIDEventTap, event_ref);
|
104
|
-
|
105
|
-
usleep(9000); // 9000 is a magic number
|
106
|
-
return Qtrue;
|
107
|
-
}
|
108
|
-
|
109
|
-
|
110
|
-
void
|
111
|
-
Init_key_coder()
|
112
|
-
{
|
113
|
-
/*
|
114
|
-
* Document-class: KeyCoder
|
115
|
-
*
|
116
|
-
* Class that encapsulates some low level work for finding key code mappings
|
117
|
-
* and posting keyboard events to the system.
|
118
|
-
*
|
119
|
-
*/
|
120
|
-
VALUE cKeyCoder = rb_define_class("KeyCoder", rb_cObject);
|
121
|
-
rb_define_singleton_method(cKeyCoder, "dynamic_mapping", keycoder_dynamic_mapping, 0);
|
122
|
-
rb_define_singleton_method(cKeyCoder, "post_event", keycoder_post_event, 1);
|
123
|
-
}
|