accessibility_core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +9 -0
- data/History.markdown +36 -0
- data/README.markdown +66 -0
- data/Rakefile +72 -0
- data/ext/accessibility/bridge/ext/accessibility/bridge/bridge.c +490 -0
- data/ext/accessibility/bridge/ext/accessibility/bridge/extconf.rb +22 -0
- data/ext/accessibility/bridge/lib/accessibility/bridge.rb +33 -0
- data/ext/accessibility/bridge/lib/accessibility/bridge/common.rb +57 -0
- data/ext/accessibility/bridge/lib/accessibility/bridge/macruby.rb +185 -0
- data/ext/accessibility/bridge/lib/accessibility/bridge/mri.rb +121 -0
- data/ext/accessibility/bridge/lib/accessibility/bridge/version.rb +6 -0
- data/ext/accessibility/bridge/test/array_test.rb +31 -0
- data/ext/accessibility/bridge/test/boxed_test.rb +23 -0
- data/ext/accessibility/bridge/test/cfrange_test.rb +21 -0
- data/ext/accessibility/bridge/test/cgpoint_test.rb +54 -0
- data/ext/accessibility/bridge/test/cgrect_test.rb +60 -0
- data/ext/accessibility/bridge/test/cgsize_test.rb +54 -0
- data/ext/accessibility/bridge/test/helper.rb +19 -0
- data/ext/accessibility/bridge/test/nsstring_test.rb +22 -0
- data/ext/accessibility/bridge/test/nsurl_test.rb +17 -0
- data/ext/accessibility/bridge/test/object_test.rb +19 -0
- data/ext/accessibility/bridge/test/range_test.rb +16 -0
- data/ext/accessibility/bridge/test/string_test.rb +35 -0
- data/ext/accessibility/bridge/test/uri_test.rb +15 -0
- data/ext/accessibility/core/bridge.h +1 -0
- data/ext/accessibility/core/core.c +705 -0
- data/ext/accessibility/core/extconf.rb +22 -0
- data/ext/accessibility/highlighter/extconf.rb +22 -0
- data/ext/accessibility/highlighter/highlighter.c +7 -0
- data/lib/accessibility/core.rb +12 -0
- data/lib/accessibility/core/core_ext/common.rb +57 -0
- data/lib/accessibility/core/core_ext/macruby.rb +140 -0
- data/lib/accessibility/core/core_ext/mri.rb +121 -0
- data/lib/accessibility/core/macruby.rb +858 -0
- data/lib/accessibility/core/version.rb +6 -0
- data/test/helper.rb +48 -0
- metadata +158 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
$CFLAGS << ' -std=c99 -Wall -Werror -pedantic -ObjC'
|
4
|
+
$LIBS << ' -framework CoreFoundation -framework ApplicationServices -framework Cocoa'
|
5
|
+
$LIBS << ' -framework CoreGraphics' unless `sw_vers -productVersion`.to_f == 10.7
|
6
|
+
|
7
|
+
if RUBY_ENGINE == 'macruby'
|
8
|
+
$CFLAGS << ' -fobjc-gc'
|
9
|
+
else
|
10
|
+
unless RbConfig::CONFIG["CC"].match /clang/
|
11
|
+
clang = `which clang`.chomp
|
12
|
+
if clang.empty?
|
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/bridge'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'accessibility/bridge/version'
|
2
|
+
|
3
|
+
if RUBY_ENGINE == 'macruby'
|
4
|
+
|
5
|
+
##
|
6
|
+
# Whether or not we are running on MacRuby
|
7
|
+
def on_macruby?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
framework 'Cocoa'
|
12
|
+
|
13
|
+
# A workaround that guarantees that `CGPoint` is defined
|
14
|
+
unless defined? MOUNTAIN_LION_APPKIT_VERSION
|
15
|
+
MOUNTAIN_LION_APPKIT_VERSION = 1187
|
16
|
+
end
|
17
|
+
|
18
|
+
if NSAppKitVersionNumber >= MOUNTAIN_LION_APPKIT_VERSION
|
19
|
+
framework '/System/Library/Frameworks/CoreGraphics.framework'
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'accessibility/bridge/macruby'
|
23
|
+
|
24
|
+
else
|
25
|
+
|
26
|
+
def on_macruby?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'accessibility/bridge/mri'
|
31
|
+
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class CGPoint
|
2
|
+
##
|
3
|
+
# Returns the receiver, since the receiver is already a {CGPoint}
|
4
|
+
#
|
5
|
+
# @return [CGPoint]
|
6
|
+
def to_point
|
7
|
+
self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class CGSize
|
12
|
+
##
|
13
|
+
# Returns the receiver, since the receiver is already a {CGSize}
|
14
|
+
#
|
15
|
+
# @return [CGSize]
|
16
|
+
def to_size
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class CGRect
|
22
|
+
##
|
23
|
+
# Returns the receiver, since the receiver is already a {CGRect}
|
24
|
+
#
|
25
|
+
# @return [CGRect]
|
26
|
+
def to_rect
|
27
|
+
self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# accessibility-core extensions to `Array`
|
33
|
+
class Array
|
34
|
+
##
|
35
|
+
# Coerce the first two elements of the receiver into a {CGPoint}
|
36
|
+
#
|
37
|
+
# @return [CGPoint]
|
38
|
+
def to_point
|
39
|
+
CGPoint.new self[0], self[1]
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Coerce the first two elements of the receiver into a {CGSize}
|
44
|
+
#
|
45
|
+
# @return [CGSize]
|
46
|
+
def to_size
|
47
|
+
CGSize.new self[0], self[1]
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Coerce the first four elements of the receiver into a {CGRect}
|
52
|
+
#
|
53
|
+
# @return [CGRect]
|
54
|
+
def to_rect
|
55
|
+
CGRect.new CGPoint.new(self[0], self[1]), CGSize.new(self[2], self[3])
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'accessibility/bridge/common'
|
2
|
+
|
3
|
+
##
|
4
|
+
# accessibility-core extensions for `NSURL`
|
5
|
+
class NSURL
|
6
|
+
##
|
7
|
+
# Return the reciver, for the receiver is already a URL object
|
8
|
+
#
|
9
|
+
# @return [NSURL]
|
10
|
+
def to_url
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
# because printing is easier this way
|
15
|
+
alias_method :to_s, :inspect
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# accessibility-core extensions for `NSString`
|
20
|
+
class NSString
|
21
|
+
##
|
22
|
+
# Create an NSURL using the receiver as the initialization string
|
23
|
+
#
|
24
|
+
# If the receiver is not a valid URL then `nil` will be returned.
|
25
|
+
#
|
26
|
+
# This exists because of
|
27
|
+
# [rdar://11207662](http://openradar.appspot.com/11207662).
|
28
|
+
#
|
29
|
+
# @return [NSURL,nil]
|
30
|
+
def to_url
|
31
|
+
NSURL.URLWithString self
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# `accessibility-core` extensions for `NSObject`
|
37
|
+
class NSObject
|
38
|
+
##
|
39
|
+
# Return an object safe for passing to AXAPI
|
40
|
+
def to_ax
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Return a usable object from an AXAPI pointer
|
46
|
+
def to_ruby
|
47
|
+
self
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# `accessibility-core` extensions for `CFRange`
|
53
|
+
class CFRange
|
54
|
+
##
|
55
|
+
# Convert the {CFRange} to a Ruby {Range} object
|
56
|
+
#
|
57
|
+
# @return [Range]
|
58
|
+
def to_ruby
|
59
|
+
Range.new location, (location + length - 1)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# `accessibility-core` extensions for `Range`
|
65
|
+
class Range
|
66
|
+
# @return [AXValueRef]
|
67
|
+
def to_ax
|
68
|
+
raise ArgumentError, "can't convert negative index" if last < 0 || first < 0
|
69
|
+
length = if exclude_end?
|
70
|
+
last - first
|
71
|
+
else
|
72
|
+
last - first + 1
|
73
|
+
end
|
74
|
+
CFRange.new(first, length).to_ax
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# AXElements extensions to the `Boxed` class
|
80
|
+
#
|
81
|
+
# The `Boxed` class is simply an abstract base class for structs that
|
82
|
+
# MacRuby can use via bridge support.
|
83
|
+
class Boxed
|
84
|
+
##
|
85
|
+
# Returns the number that AXAPI uses in order to know how to wrap
|
86
|
+
# a struct.
|
87
|
+
#
|
88
|
+
# @return [Number]
|
89
|
+
def self.ax_value
|
90
|
+
raise NotImplementedError, "#{inspect}:#{self.class} cannot be wrapped"
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Create an `AXValueRef` from the `Boxed` instance. This will only
|
95
|
+
# work if for the most common boxed types, you will need to check
|
96
|
+
# the AXAPI documentation for an up to date list.
|
97
|
+
#
|
98
|
+
# @example
|
99
|
+
#
|
100
|
+
# CGPoint.new(12, 34).to_ax # => #<AXValueRef:0x455678e2>
|
101
|
+
# CGSize.new(56, 78).to_ax # => #<AXValueRef:0x555678e2>
|
102
|
+
#
|
103
|
+
# @return [AXValueRef]
|
104
|
+
def to_ax
|
105
|
+
klass = self.class
|
106
|
+
ptr = Pointer.new klass.type
|
107
|
+
ptr.assign self
|
108
|
+
AXValueCreate(klass.ax_value, ptr)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# `accessibility-core` extensions for `CFRange`'s metaclass
|
113
|
+
class << CFRange
|
114
|
+
# (see Boxed.ax_value)
|
115
|
+
def ax_value; KAXValueCFRangeType end
|
116
|
+
end
|
117
|
+
# `accessibility-core` extensions for `CGSize`'s metaclass
|
118
|
+
class << CGSize
|
119
|
+
# (see Boxed.ax_value)
|
120
|
+
def ax_value; KAXValueCGSizeType end
|
121
|
+
end
|
122
|
+
# `accessibility-core` extensions for `CGRect`'s metaclass
|
123
|
+
class << CGRect
|
124
|
+
# (see Boxed.ax_value)
|
125
|
+
def ax_value; KAXValueCGRectType end
|
126
|
+
end
|
127
|
+
# `accessibility-core` extensions for `CGPoint`'s metaclass
|
128
|
+
class << CGPoint
|
129
|
+
# (see Boxed.ax_value)
|
130
|
+
def ax_value; KAXValueCGPointType end
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Mixin for the special hidden class in MacRuby that represents `AXValueRef`
|
135
|
+
#
|
136
|
+
# This module adds a `#to_ruby` method that actually unwraps the object from
|
137
|
+
# the `AXValueRef` to some sort of {Boxed} object, such as a {CGPoint} or a
|
138
|
+
# {Range}.
|
139
|
+
module ValueWrapper
|
140
|
+
|
141
|
+
|
142
|
+
##
|
143
|
+
# Map of type encodings used for unwrapping structs wrapped in an `AXValueRef`
|
144
|
+
#
|
145
|
+
# The list is order sensitive, which is why we unshift nil, but
|
146
|
+
# should probably be more rigorously defined at runtime.
|
147
|
+
#
|
148
|
+
# @return [String,nil]
|
149
|
+
BOX_TYPES = [CGPoint, CGSize, CGRect, CFRange].map!(&:type).unshift(nil)
|
150
|
+
|
151
|
+
##
|
152
|
+
# Unwrap an `AXValueRef` into the `Boxed` instance that it is supposed
|
153
|
+
# to be. This will only work for the most common boxed types, you will
|
154
|
+
# need to check the AXAPI documentation for an up to date list.
|
155
|
+
#
|
156
|
+
# @example
|
157
|
+
#
|
158
|
+
# wrapped_point.to_ruby # => #<CGPoint x=44.3 y=99.0>
|
159
|
+
# wrapped_range.to_ruby # => #<CFRange begin=7 length=100>
|
160
|
+
# wrapped_thing.to_ruby # => wrapped_thing
|
161
|
+
#
|
162
|
+
# @return [Boxed]
|
163
|
+
def to_ruby
|
164
|
+
type = AXValueGetType(self)
|
165
|
+
return self if type.zero?
|
166
|
+
|
167
|
+
ptr = Pointer.new BOX_TYPES[type]
|
168
|
+
AXValueGetValue(self, type, ptr)
|
169
|
+
ptr.value.to_ruby
|
170
|
+
end
|
171
|
+
|
172
|
+
# hack to find the __NSCFType class and mix things in
|
173
|
+
klass = AXUIElementCreateSystemWide().class
|
174
|
+
klass.send :include, self
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
##
|
179
|
+
# `accessibility-core` extensions to `NSArray`
|
180
|
+
class NSArray
|
181
|
+
# @return [Array]
|
182
|
+
def to_ruby
|
183
|
+
map do |obj| obj.to_ruby end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
##
|
2
|
+
# A structure that contains a point in a two-dimensional coordinate system
|
3
|
+
CGPoint = Struct.new(:x, :y) do
|
4
|
+
|
5
|
+
# @param x [Number]
|
6
|
+
# @param y [Number]
|
7
|
+
def initialize x = 0.0, y = 0.0
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
# @!attribute [rw] x
|
12
|
+
# The `x` co-ordinate of the screen point
|
13
|
+
# @return [Number]
|
14
|
+
|
15
|
+
# @!attribute [rw] y
|
16
|
+
# The `y` co-ordinate of the screen point
|
17
|
+
# @return [Number]
|
18
|
+
|
19
|
+
##
|
20
|
+
# Return a nice string representation of the point
|
21
|
+
#
|
22
|
+
# Overrides `Object#inspect` to more closely mimic MacRuby `Boxed#inspect`.
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
def inspect
|
26
|
+
"#<CGPoint x=#{self.x.to_f} y=#{self.y.to_f}>"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
##
|
33
|
+
# A structure that contains the size of a rectangle in a 2D co-ordinate system
|
34
|
+
CGSize = Struct.new(:width, :height) do
|
35
|
+
|
36
|
+
# @param width [Number]
|
37
|
+
# @param height [Number]
|
38
|
+
def initialize width = 0.0, height = 0.0
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
# @!attribute [rw] width
|
43
|
+
# The `width` of the box
|
44
|
+
# @return [Number]
|
45
|
+
|
46
|
+
# @!attribute [rw] height
|
47
|
+
# The `heighth` of the box
|
48
|
+
# @return [Number]
|
49
|
+
|
50
|
+
##
|
51
|
+
# Return a nice string representation of the size
|
52
|
+
#
|
53
|
+
# Overrides `Object#inspect` to more closely mimic MacRuby `Boxed#inspect`.
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
def inspect
|
57
|
+
"#<CGSize width=#{self.width.to_f} height=#{self.height.to_f}>"
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
##
|
64
|
+
# Complete definition of a rectangle in a 2D coordinate system
|
65
|
+
CGRect = Struct.new(:origin, :size) do
|
66
|
+
|
67
|
+
# @param origin [CGPoint,#to_point]
|
68
|
+
# @param size [CGSize,#to_size]
|
69
|
+
def initialize origin = CGPoint.new, size = CGSize.new
|
70
|
+
super(origin.to_point, size.to_size)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @!attribute [rw] origin
|
74
|
+
# The `origin` point
|
75
|
+
# @return [CGPoint,#to_point]
|
76
|
+
|
77
|
+
# @!attribute [rw] size
|
78
|
+
# The `size` of the rectangle
|
79
|
+
# @return [CGSize,#to_size]
|
80
|
+
|
81
|
+
##
|
82
|
+
# Return a nice string representation of the rectangle
|
83
|
+
#
|
84
|
+
# Overrides `Object#inspect` to more closely mimic MacRuby `Boxed#inspect`.
|
85
|
+
#
|
86
|
+
# @return [String]
|
87
|
+
def inspect
|
88
|
+
"#<CGRect origin=#{self.origin.inspect} size=#{self.size.inspect}>"
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
require 'uri'
|
95
|
+
|
96
|
+
##
|
97
|
+
# `accessibility-core` extensions to the `URI` family of classes
|
98
|
+
class URI::Generic
|
99
|
+
##
|
100
|
+
# Returns the receiver (since the receiver is already a `URI` object)
|
101
|
+
#
|
102
|
+
# @return [URI::Generic]
|
103
|
+
def to_url
|
104
|
+
self
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# `accessibility-core` extensions to the `String` class
|
110
|
+
class String
|
111
|
+
##
|
112
|
+
# Parse the receiver into a `URI` object
|
113
|
+
#
|
114
|
+
# @return [URI::Generic]
|
115
|
+
def to_url
|
116
|
+
URI.parse self
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
require 'accessibility/bridge/common'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class ArrayTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def test_to_point
|
6
|
+
x, y = rand_nums 2
|
7
|
+
p = [x, y].to_point
|
8
|
+
assert_kind_of CGPoint, p
|
9
|
+
assert_equal x, p.x
|
10
|
+
assert_equal y, p.y
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_to_size
|
14
|
+
w, h = rand_nums 2
|
15
|
+
s = [w, h].to_size
|
16
|
+
assert_kind_of CGSize, s
|
17
|
+
assert_equal w, s.width
|
18
|
+
assert_equal h, s.height
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_to_rect
|
22
|
+
x, y, w, h = rand_nums 4
|
23
|
+
r = [x, y, w, h].to_rect
|
24
|
+
assert_kind_of CGRect, r
|
25
|
+
assert_equal x, r.origin.x
|
26
|
+
assert_equal y, r.origin.y
|
27
|
+
assert_equal w, r.size.width
|
28
|
+
assert_equal h, r.size.height
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|