accessibility_bridge 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.yardopts +9 -0
- data/History.markdown +5 -0
- data/README.markdown +39 -0
- data/Rakefile +51 -0
- data/ext/accessibility/bridge/bridge.c +490 -0
- data/ext/accessibility/bridge/extconf.rb +22 -0
- data/lib/accessibility/bridge.rb +33 -0
- data/lib/accessibility/bridge/common.rb +57 -0
- data/lib/accessibility/bridge/macruby.rb +185 -0
- data/lib/accessibility/bridge/mri.rb +121 -0
- data/lib/accessibility/bridge/version.rb +6 -0
- data/test/helper.rb +19 -0
- metadata +120 -0
data/.yardopts
ADDED
data/History.markdown
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# accessibility\_bridge
|
2
|
+
|
3
|
+
Bare minimum bridging for MRI to easily use Cocoa objects. The intended
|
4
|
+
use for this code is as a support for other gems that require some
|
5
|
+
bridging to Cocoa stuff.
|
6
|
+
|
7
|
+
This was extracted from the
|
8
|
+
[accessibility\_core](https://github.com/AXElements/accessibility_core)
|
9
|
+
project and is a work-in-progress.
|
10
|
+
|
11
|
+
|
12
|
+
## Copyright
|
13
|
+
|
14
|
+
Copyright (c)2012, Mark Rada
|
15
|
+
All rights reserved.
|
16
|
+
|
17
|
+
Redistribution and use in source and binary forms, with or without
|
18
|
+
modification, are permitted provided that the following conditions are met:
|
19
|
+
|
20
|
+
* Redistributions of source code must retain the above copyright
|
21
|
+
notice, this list of conditions and the following disclaimer.
|
22
|
+
* Redistributions in binary form must reproduce the above copyright
|
23
|
+
notice, this list of conditions and the following disclaimer in the
|
24
|
+
documentation and/or other materials provided with the distribution.
|
25
|
+
* Neither the name of Mark Rada nor the names of its
|
26
|
+
contributors may be used to endorse or promote products derived
|
27
|
+
from this software without specific prior written permission.
|
28
|
+
|
29
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
32
|
+
DISCLAIMED. IN NO EVENT SHALL Mark Rada BE LIABLE FOR ANY
|
33
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
34
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
35
|
+
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
36
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
37
|
+
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
38
|
+
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
39
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
task :default => :test
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
CLEAN.include '*.plist', '*.gch'
|
5
|
+
|
6
|
+
desc 'Run the Clang static analyzer'
|
7
|
+
task :analyze do
|
8
|
+
sh "clang --analyze ext/accessibility/bridge/bridge.c"
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Startup an IRb console with accessibility-core loaded'
|
12
|
+
task :console => [:compile] do
|
13
|
+
sh 'irb -Ilib -raccessibility/bridge'
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Build the test fixture'
|
17
|
+
task :fixture do
|
18
|
+
sh 'cd test/AXElementsTester && xcodebuild'
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new do |t|
|
23
|
+
t.libs << '.'
|
24
|
+
t.pattern = 'test/*_test.rb'
|
25
|
+
end
|
26
|
+
task :test => :compile
|
27
|
+
|
28
|
+
|
29
|
+
# Gem stuff
|
30
|
+
|
31
|
+
require 'rubygems/package_task'
|
32
|
+
SPEC = Gem::Specification.load('accessibility_bridge.gemspec')
|
33
|
+
|
34
|
+
Gem::PackageTask.new(SPEC) { }
|
35
|
+
|
36
|
+
desc 'Build and install gem (not including deps)'
|
37
|
+
task :install => :gem do
|
38
|
+
require 'rubygems/installer'
|
39
|
+
Gem::Installer.new("pkg/#{SPEC.file_name}").install
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# C extensions!
|
44
|
+
|
45
|
+
require 'rake/extensiontask'
|
46
|
+
|
47
|
+
Rake::ExtensionTask.new('bridge', SPEC) do |ext|
|
48
|
+
ext.ext_dir = 'ext/accessibility/bridge'
|
49
|
+
ext.lib_dir = 'lib/accessibility'
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,490 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#import <Cocoa/Cocoa.h>
|
3
|
+
|
4
|
+
#ifndef ACCESSIBILITY_BRIDGE
|
5
|
+
#define ACCESSIBILITY_BRIDGE 1
|
6
|
+
|
7
|
+
#ifdef NOT_MACRUBY
|
8
|
+
|
9
|
+
VALUE rb_mAccessibility;
|
10
|
+
VALUE rb_cElement;
|
11
|
+
VALUE rb_cCGPoint;
|
12
|
+
VALUE rb_cCGSize;
|
13
|
+
VALUE rb_cCGRect;
|
14
|
+
VALUE rb_mURI; // URI module
|
15
|
+
VALUE rb_cURI; // URI::Generic class
|
16
|
+
|
17
|
+
ID sel_x;
|
18
|
+
ID sel_y;
|
19
|
+
ID sel_width;
|
20
|
+
ID sel_height;
|
21
|
+
ID sel_origin;
|
22
|
+
ID sel_size;
|
23
|
+
ID sel_to_point;
|
24
|
+
ID sel_to_size;
|
25
|
+
ID sel_to_rect;
|
26
|
+
ID sel_to_s;
|
27
|
+
ID sel_parse;
|
28
|
+
|
29
|
+
|
30
|
+
#define WRAP_ARRAY(wrapper) do { \
|
31
|
+
CFIndex length = CFArrayGetCount(array); \
|
32
|
+
VALUE ary = rb_ary_new2(length); \
|
33
|
+
\
|
34
|
+
for (CFIndex idx = 0; idx < length; idx++) \
|
35
|
+
rb_ary_store( \
|
36
|
+
ary, \
|
37
|
+
idx, \
|
38
|
+
wrapper(CFArrayGetValueAtIndex(array, idx)) \
|
39
|
+
); \
|
40
|
+
return ary; \
|
41
|
+
} while (false);
|
42
|
+
|
43
|
+
|
44
|
+
VALUE
|
45
|
+
wrap_unknown(CFTypeRef obj)
|
46
|
+
{
|
47
|
+
// TODO: this will leak, can we use something like alloca?
|
48
|
+
CFStringRef description = CFCopyDescription(obj);
|
49
|
+
rb_raise(
|
50
|
+
rb_eRuntimeError,
|
51
|
+
"accessibility-core doesn't know how to wrap `%s` objects yet",
|
52
|
+
CFStringGetCStringPtr(description, kCFStringEncodingMacRoman)
|
53
|
+
);
|
54
|
+
return Qnil; // unreachable
|
55
|
+
}
|
56
|
+
|
57
|
+
CFTypeRef
|
58
|
+
unwrap_unknown(VALUE obj)
|
59
|
+
{
|
60
|
+
obj = rb_funcall(obj, sel_to_s, 0);
|
61
|
+
rb_raise(
|
62
|
+
rb_eRuntimeError,
|
63
|
+
"accessibility-core doesn't know how to unwrap `%s'",
|
64
|
+
StringValuePtr(obj)
|
65
|
+
);
|
66
|
+
return NULL; // unreachable
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
VALUE
|
71
|
+
wrap_point(CGPoint point)
|
72
|
+
{
|
73
|
+
return rb_struct_new(rb_cCGPoint, DBL2NUM(point.x), DBL2NUM(point.y));
|
74
|
+
}
|
75
|
+
|
76
|
+
CGPoint
|
77
|
+
unwrap_point(VALUE point)
|
78
|
+
{
|
79
|
+
point = rb_funcall(point, sel_to_point, 0);
|
80
|
+
double x = NUM2DBL(rb_struct_getmember(point, sel_x));
|
81
|
+
double y = NUM2DBL(rb_struct_getmember(point, sel_y));
|
82
|
+
return CGPointMake(x, y);
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
VALUE
|
87
|
+
wrap_size(CGSize size)
|
88
|
+
{
|
89
|
+
return rb_struct_new(rb_cCGSize, DBL2NUM(size.width), DBL2NUM(size.height));
|
90
|
+
}
|
91
|
+
|
92
|
+
CGSize
|
93
|
+
unwrap_size(VALUE size)
|
94
|
+
{
|
95
|
+
size = rb_funcall(size, sel_to_size, 0);
|
96
|
+
double width = NUM2DBL(rb_struct_getmember(size, sel_width));
|
97
|
+
double height = NUM2DBL(rb_struct_getmember(size, sel_height));
|
98
|
+
return CGSizeMake(width, height);
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
VALUE
|
103
|
+
wrap_rect(CGRect rect)
|
104
|
+
{
|
105
|
+
VALUE point = wrap_point(rect.origin);
|
106
|
+
VALUE size = wrap_size(rect.size);
|
107
|
+
return rb_struct_new(rb_cCGRect, point, size);
|
108
|
+
}
|
109
|
+
|
110
|
+
CGRect
|
111
|
+
unwrap_rect(VALUE rect)
|
112
|
+
{
|
113
|
+
rect = rb_funcall(rect, sel_to_rect, 0);
|
114
|
+
CGPoint origin = unwrap_point(rb_struct_getmember(rect, sel_origin));
|
115
|
+
CGSize size = unwrap_size(rb_struct_getmember(rect, sel_size));
|
116
|
+
return CGRectMake(origin.x, origin.y, size.width, size.height);
|
117
|
+
}
|
118
|
+
|
119
|
+
|
120
|
+
VALUE
|
121
|
+
convert_cf_range(CFRange range)
|
122
|
+
{
|
123
|
+
CFIndex end_index = range.location + range.length;
|
124
|
+
if (range.length != 0)
|
125
|
+
end_index -= 1;
|
126
|
+
return rb_range_new(INT2FIX(range.location), INT2FIX(end_index), 0);
|
127
|
+
}
|
128
|
+
|
129
|
+
CFRange
|
130
|
+
convert_rb_range(VALUE range)
|
131
|
+
{
|
132
|
+
VALUE b, e;
|
133
|
+
int exclusive;
|
134
|
+
|
135
|
+
rb_range_values(range, &b, &e, &exclusive);
|
136
|
+
|
137
|
+
int begin = NUM2INT(b);
|
138
|
+
int end = NUM2INT(e);
|
139
|
+
|
140
|
+
if (begin < 0 || end < 0)
|
141
|
+
// We don't know what the max length of the range will be, so we
|
142
|
+
// can't count backwards.
|
143
|
+
rb_raise(
|
144
|
+
rb_eArgError,
|
145
|
+
"negative values are not allowed in ranges " \
|
146
|
+
"that are converted to CFRange structures."
|
147
|
+
);
|
148
|
+
|
149
|
+
int length = exclusive ? end-begin : end-begin + 1;
|
150
|
+
return CFRangeMake(begin, length);
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
#define WRAP_VALUE(type, cookie, wrapper) do { \
|
155
|
+
type st; \
|
156
|
+
AXValueGetValue(value, cookie, &st); \
|
157
|
+
return wrapper(st); \
|
158
|
+
} while (0); \
|
159
|
+
|
160
|
+
VALUE wrap_value_point(AXValueRef value) { WRAP_VALUE(CGPoint, kAXValueCGPointType, wrap_point) }
|
161
|
+
VALUE wrap_value_size(AXValueRef value) { WRAP_VALUE(CGSize, kAXValueCGSizeType, wrap_size) }
|
162
|
+
VALUE wrap_value_rect(AXValueRef value) { WRAP_VALUE(CGRect, kAXValueCGRectType, wrap_rect) }
|
163
|
+
VALUE wrap_value_range(AXValueRef value) { WRAP_VALUE(CFRange, kAXValueCFRangeType, convert_cf_range) }
|
164
|
+
VALUE wrap_value_error(AXValueRef value) { WRAP_VALUE(AXError, kAXValueAXErrorType, INT2NUM) }
|
165
|
+
|
166
|
+
#define UNWRAP_VALUE(type, value, unwrapper) do { \
|
167
|
+
type st = unwrapper(val); \
|
168
|
+
return AXValueCreate(value, &st); \
|
169
|
+
} while(0);
|
170
|
+
|
171
|
+
AXValueRef unwrap_value_point(VALUE val) { UNWRAP_VALUE(CGPoint, kAXValueCGPointType, unwrap_point) }
|
172
|
+
AXValueRef unwrap_value_size(VALUE val) { UNWRAP_VALUE(CGSize, kAXValueCGSizeType, unwrap_size) }
|
173
|
+
AXValueRef unwrap_value_rect(VALUE val) { UNWRAP_VALUE(CGRect, kAXValueCGRectType, unwrap_rect) }
|
174
|
+
AXValueRef unwrap_value_range(VALUE val) { UNWRAP_VALUE(CFRange, kAXValueCFRangeType, convert_rb_range) }
|
175
|
+
|
176
|
+
|
177
|
+
VALUE
|
178
|
+
wrap_value(AXValueRef value)
|
179
|
+
{
|
180
|
+
switch (AXValueGetType(value))
|
181
|
+
{
|
182
|
+
case kAXValueIllegalType:
|
183
|
+
// TODO better error message
|
184
|
+
rb_raise(rb_eArgError, "herped when you should have derped");
|
185
|
+
case kAXValueCGPointType:
|
186
|
+
return wrap_value_point(value);
|
187
|
+
case kAXValueCGSizeType:
|
188
|
+
return wrap_value_size(value);
|
189
|
+
case kAXValueCGRectType:
|
190
|
+
return wrap_value_rect(value);
|
191
|
+
case kAXValueCFRangeType:
|
192
|
+
return wrap_value_range(value);
|
193
|
+
case kAXValueAXErrorType:
|
194
|
+
return wrap_value_error(value);
|
195
|
+
default:
|
196
|
+
// TODO better error message
|
197
|
+
rb_raise(
|
198
|
+
rb_eRuntimeError,
|
199
|
+
"Could not wrap You've found a bug in something...not sure who to blame"
|
200
|
+
);
|
201
|
+
}
|
202
|
+
|
203
|
+
return Qnil; // unreachable
|
204
|
+
}
|
205
|
+
|
206
|
+
AXValueRef
|
207
|
+
unwrap_value(VALUE value)
|
208
|
+
{
|
209
|
+
VALUE type = CLASS_OF(value);
|
210
|
+
if (type == rb_cCGPoint)
|
211
|
+
return unwrap_value_point(value);
|
212
|
+
else if (type == rb_cCGSize)
|
213
|
+
return unwrap_value_size(value);
|
214
|
+
else if (type == rb_cCGRect)
|
215
|
+
return unwrap_value_rect(value);
|
216
|
+
else if (type == rb_cRange)
|
217
|
+
return unwrap_value_range(value);
|
218
|
+
|
219
|
+
rb_raise(rb_eArgError, "could not wrap %s", rb_class2name(type));
|
220
|
+
return NULL; // unreachable
|
221
|
+
}
|
222
|
+
|
223
|
+
VALUE wrap_array_values(CFArrayRef array) { WRAP_ARRAY(wrap_value) }
|
224
|
+
|
225
|
+
|
226
|
+
static
|
227
|
+
void
|
228
|
+
ref_finalizer(void* obj)
|
229
|
+
{
|
230
|
+
CFRelease((CFTypeRef)obj);
|
231
|
+
}
|
232
|
+
|
233
|
+
VALUE
|
234
|
+
wrap_ref(AXUIElementRef ref)
|
235
|
+
{
|
236
|
+
return Data_Wrap_Struct(rb_cElement, NULL, ref_finalizer, (void*)ref);
|
237
|
+
}
|
238
|
+
|
239
|
+
AXUIElementRef
|
240
|
+
unwrap_ref(VALUE obj)
|
241
|
+
{
|
242
|
+
AXUIElementRef* ref;
|
243
|
+
Data_Get_Struct(obj, AXUIElementRef, ref);
|
244
|
+
// TODO we should return *ref? but that seems to fuck things up...
|
245
|
+
return (AXUIElementRef)ref;
|
246
|
+
}
|
247
|
+
|
248
|
+
VALUE wrap_array_refs(CFArrayRef array) { WRAP_ARRAY(wrap_ref) }
|
249
|
+
|
250
|
+
|
251
|
+
VALUE
|
252
|
+
wrap_string(CFStringRef string)
|
253
|
+
{
|
254
|
+
// flying by the seat of our pants here, this hasn't failed yet
|
255
|
+
// but probably will one day when I'm not looking
|
256
|
+
const char* name = CFStringGetCStringPtr(string, kCFStringEncodingMacRoman);
|
257
|
+
if (name)
|
258
|
+
return rb_str_new(name, CFStringGetLength(string));
|
259
|
+
else
|
260
|
+
// use rb_external_str_new() ? assume always UTF-8?
|
261
|
+
rb_raise(rb_eRuntimeError, "NEED TO IMPLEMNET STRING COPYING");
|
262
|
+
|
263
|
+
return Qnil; // unreachable
|
264
|
+
}
|
265
|
+
|
266
|
+
CFStringRef
|
267
|
+
unwrap_string(VALUE string)
|
268
|
+
{
|
269
|
+
return CFStringCreateWithCStringNoCopy(
|
270
|
+
NULL,
|
271
|
+
StringValueCStr(string),
|
272
|
+
0,
|
273
|
+
kCFAllocatorNull
|
274
|
+
);
|
275
|
+
/* return CFStringCreateWithCString( */
|
276
|
+
/* NULL, */
|
277
|
+
/* StringValuePtr(string), */
|
278
|
+
/* kCFStringEncodingUTF8 */
|
279
|
+
/* ); */
|
280
|
+
}
|
281
|
+
|
282
|
+
VALUE wrap_array_strings(CFArrayRef array) { WRAP_ARRAY(wrap_string) }
|
283
|
+
|
284
|
+
|
285
|
+
#define WRAP_NUM(type, cookie, macro) do { \
|
286
|
+
type value; \
|
287
|
+
if (CFNumberGetValue(num, cookie, &value)) \
|
288
|
+
return macro(value); \
|
289
|
+
rb_raise(rb_eRuntimeError, "I goofed wrapping a number"); \
|
290
|
+
return Qnil; \
|
291
|
+
} while(0);
|
292
|
+
|
293
|
+
VALUE wrap_long(CFNumberRef num) { WRAP_NUM(long, kCFNumberLongType, LONG2FIX) }
|
294
|
+
VALUE wrap_long_long(CFNumberRef num) { WRAP_NUM(long long, kCFNumberLongLongType, LL2NUM) }
|
295
|
+
VALUE wrap_float(CFNumberRef num) { WRAP_NUM(double, kCFNumberDoubleType, DBL2NUM) }
|
296
|
+
|
297
|
+
#define UNWRAP_NUM(type, cookie, macro) do { \
|
298
|
+
type base = macro(num); \
|
299
|
+
return CFNumberCreate(NULL, cookie, &base); \
|
300
|
+
} while(0);
|
301
|
+
|
302
|
+
CFNumberRef unwrap_long(VALUE num) { UNWRAP_NUM(long, kCFNumberLongType, NUM2LONG) }
|
303
|
+
CFNumberRef unwrap_long_long(VALUE num) { UNWRAP_NUM(long long, kCFNumberLongLongType, NUM2LL) }
|
304
|
+
CFNumberRef unwrap_float(VALUE num) { UNWRAP_NUM(double, kCFNumberDoubleType, NUM2DBL) }
|
305
|
+
|
306
|
+
VALUE
|
307
|
+
wrap_number(CFNumberRef number)
|
308
|
+
{
|
309
|
+
switch (CFNumberGetType(number))
|
310
|
+
{
|
311
|
+
case kCFNumberSInt8Type:
|
312
|
+
case kCFNumberSInt16Type:
|
313
|
+
case kCFNumberSInt32Type:
|
314
|
+
case kCFNumberSInt64Type:
|
315
|
+
return wrap_long(number);
|
316
|
+
case kCFNumberFloat32Type:
|
317
|
+
case kCFNumberFloat64Type:
|
318
|
+
return wrap_float(number);
|
319
|
+
case kCFNumberCharType:
|
320
|
+
case kCFNumberShortType:
|
321
|
+
case kCFNumberIntType:
|
322
|
+
case kCFNumberLongType:
|
323
|
+
return wrap_long(number);
|
324
|
+
case kCFNumberLongLongType:
|
325
|
+
return wrap_long_long(number);
|
326
|
+
case kCFNumberFloatType:
|
327
|
+
case kCFNumberDoubleType:
|
328
|
+
return wrap_float(number);
|
329
|
+
case kCFNumberCFIndexType:
|
330
|
+
case kCFNumberNSIntegerType:
|
331
|
+
return wrap_long(number);
|
332
|
+
case kCFNumberCGFloatType: // == kCFNumberMaxType
|
333
|
+
return wrap_float(number);
|
334
|
+
default:
|
335
|
+
return INT2NUM(0); // unreachable unless system goofed
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
CFNumberRef
|
340
|
+
unwrap_number(VALUE number)
|
341
|
+
{
|
342
|
+
switch (TYPE(number))
|
343
|
+
{
|
344
|
+
case T_FIXNUM:
|
345
|
+
return unwrap_long(number);
|
346
|
+
case T_FLOAT:
|
347
|
+
return unwrap_float(number);
|
348
|
+
default:
|
349
|
+
rb_raise(
|
350
|
+
rb_eRuntimeError,
|
351
|
+
"wrapping %s is not supported; log a bug?",
|
352
|
+
rb_string_value_cstr(&number)
|
353
|
+
);
|
354
|
+
return kCFNumberNegativeInfinity; // unreachable
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
VALUE wrap_array_numbers(CFArrayRef array) { WRAP_ARRAY(wrap_number) }
|
359
|
+
|
360
|
+
|
361
|
+
VALUE
|
362
|
+
wrap_url(CFURLRef url)
|
363
|
+
{
|
364
|
+
return rb_funcall(rb_mURI, sel_parse, 1, wrap_string(CFURLGetString(url)));
|
365
|
+
}
|
366
|
+
|
367
|
+
CFURLRef
|
368
|
+
unwrap_url(VALUE url)
|
369
|
+
{
|
370
|
+
url = rb_funcall(url, sel_to_s, 0);
|
371
|
+
CFStringRef string = CFStringCreateWithCString(
|
372
|
+
NULL,
|
373
|
+
StringValuePtr(url),
|
374
|
+
kCFStringEncodingUTF8
|
375
|
+
);
|
376
|
+
CFURLRef url_ref = CFURLCreateWithString(NULL, string, NULL);
|
377
|
+
CFRelease(string);
|
378
|
+
return url_ref;
|
379
|
+
}
|
380
|
+
|
381
|
+
VALUE wrap_array_urls(CFArrayRef array) { WRAP_ARRAY(wrap_url) }
|
382
|
+
|
383
|
+
VALUE
|
384
|
+
wrap_date(CFDateRef date)
|
385
|
+
{
|
386
|
+
NSTimeInterval time = [(NSDate*)date timeIntervalSince1970];
|
387
|
+
return rb_time_new((time_t)time, 0);
|
388
|
+
}
|
389
|
+
|
390
|
+
CFDateRef
|
391
|
+
unwrap_date(VALUE date)
|
392
|
+
{
|
393
|
+
struct timeval t = rb_time_timeval(date);
|
394
|
+
NSDate* ns_date = [NSDate dateWithTimeIntervalSince1970:t.tv_sec];
|
395
|
+
return (CFDateRef)ns_date;
|
396
|
+
}
|
397
|
+
|
398
|
+
VALUE wrap_array_dates(CFArrayRef array) { WRAP_ARRAY(wrap_date) }
|
399
|
+
|
400
|
+
|
401
|
+
VALUE
|
402
|
+
wrap_boolean(CFBooleanRef bool_val)
|
403
|
+
{
|
404
|
+
return (CFBooleanGetValue(bool_val) ? Qtrue : Qfalse);
|
405
|
+
}
|
406
|
+
|
407
|
+
CFBooleanRef
|
408
|
+
unwrap_boolean(VALUE bool_val)
|
409
|
+
{
|
410
|
+
return (bool_val == Qtrue ? kCFBooleanTrue : kCFBooleanFalse);
|
411
|
+
}
|
412
|
+
|
413
|
+
VALUE wrap_array_booleans(CFArrayRef array) { WRAP_ARRAY(wrap_boolean) }
|
414
|
+
|
415
|
+
|
416
|
+
VALUE
|
417
|
+
wrap_array(CFArrayRef array)
|
418
|
+
{
|
419
|
+
CFTypeRef obj = CFArrayGetValueAtIndex(array, 0);
|
420
|
+
CFTypeID di = CFGetTypeID(obj);
|
421
|
+
if (di == AXUIElementGetTypeID()) return wrap_array_refs(array);
|
422
|
+
else if (di == AXValueGetTypeID()) return wrap_array_values(array);
|
423
|
+
else if (di == CFStringGetTypeID()) return wrap_array_strings(array);
|
424
|
+
else if (di == CFNumberGetTypeID()) return wrap_array_numbers(array);
|
425
|
+
else if (di == CFBooleanGetTypeID()) return wrap_array_booleans(array);
|
426
|
+
else if (di == CFURLGetTypeID()) return wrap_array_urls(array);
|
427
|
+
else if (di == CFDateGetTypeID()) return wrap_array_dates(array);
|
428
|
+
else return wrap_unknown(obj);
|
429
|
+
}
|
430
|
+
|
431
|
+
VALUE
|
432
|
+
to_ruby(CFTypeRef obj)
|
433
|
+
{
|
434
|
+
CFTypeID di = CFGetTypeID(obj);
|
435
|
+
if (di == CFArrayGetTypeID()) return wrap_array(obj);
|
436
|
+
else if (di == AXUIElementGetTypeID()) return wrap_ref(obj);
|
437
|
+
else if (di == AXValueGetTypeID()) return wrap_value(obj);
|
438
|
+
else if (di == CFStringGetTypeID()) return wrap_string(obj);
|
439
|
+
else if (di == CFNumberGetTypeID()) return wrap_number(obj);
|
440
|
+
else if (di == CFBooleanGetTypeID()) return wrap_boolean(obj);
|
441
|
+
else if (di == CFURLGetTypeID()) return wrap_url(obj);
|
442
|
+
else if (di == CFDateGetTypeID()) return wrap_date(obj);
|
443
|
+
else return wrap_unknown(obj);
|
444
|
+
}
|
445
|
+
|
446
|
+
CFTypeRef
|
447
|
+
to_ax(VALUE obj)
|
448
|
+
{
|
449
|
+
// TODO we can better optimize this when running under MacRuby
|
450
|
+
VALUE type = CLASS_OF(obj);
|
451
|
+
if (type == rb_cElement) return unwrap_ref(obj);
|
452
|
+
else if (type == rb_cString) return unwrap_string(obj);
|
453
|
+
else if (type == rb_cStruct) return unwrap_value(obj);
|
454
|
+
else if (type == rb_cRange) return unwrap_value(obj);
|
455
|
+
else if (type == rb_cFixnum) return unwrap_number(obj);
|
456
|
+
else if (type == rb_cFloat) return unwrap_number(obj);
|
457
|
+
else if (type == rb_cTime) return unwrap_date(obj);
|
458
|
+
else if (type == rb_cURI) return unwrap_url(obj);
|
459
|
+
else if (obj == Qtrue || obj == Qfalse) return unwrap_boolean(obj);
|
460
|
+
else return unwrap_unknown(obj);
|
461
|
+
}
|
462
|
+
|
463
|
+
#endif
|
464
|
+
|
465
|
+
|
466
|
+
void
|
467
|
+
Init_bridge()
|
468
|
+
{
|
469
|
+
#ifdef NOT_MACRUBY
|
470
|
+
sel_x = rb_intern("x");
|
471
|
+
sel_y = rb_intern("y");
|
472
|
+
sel_width = rb_intern("width");
|
473
|
+
sel_height = rb_intern("height");
|
474
|
+
sel_origin = rb_intern("origin");
|
475
|
+
sel_size = rb_intern("size");
|
476
|
+
sel_to_point = rb_intern("to_point");
|
477
|
+
sel_to_size = rb_intern("to_size");
|
478
|
+
sel_to_rect = rb_intern("to_rect");
|
479
|
+
sel_to_s = rb_intern("to_s");
|
480
|
+
sel_parse = rb_intern("parse");
|
481
|
+
|
482
|
+
rb_cCGPoint = rb_const_get(rb_cObject, rb_intern("CGPoint"));
|
483
|
+
rb_cCGSize = rb_const_get(rb_cObject, rb_intern("CGSize"));
|
484
|
+
rb_cCGRect = rb_const_get(rb_cObject, rb_intern("CGRect"));
|
485
|
+
rb_mURI = rb_const_get(rb_cObject, rb_intern("URI"));
|
486
|
+
rb_cURI = rb_const_get(rb_mURI, rb_intern("Generic"));
|
487
|
+
#endif
|
488
|
+
}
|
489
|
+
|
490
|
+
#endif
|
@@ -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'
|
data/test/helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/pride'
|
3
|
+
require 'accessibility/bridge'
|
4
|
+
|
5
|
+
class MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def rand_nums count, range = 1_000
|
8
|
+
Array.new count do
|
9
|
+
rand range
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def rand_floats count, range = 1_000.0
|
14
|
+
Array.new count do
|
15
|
+
rand * range
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: accessibility_bridge
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mark Rada
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: yard
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.3
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.8.3
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: kramdown
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.14.1
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.14.1
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake-compiler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.8.1
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.8.1
|
62
|
+
description: ! 'accessibility_bridge is a wrapper around various bits of Cocoa
|
63
|
+
|
64
|
+
so that the various accessibility projects can run on CRuby.
|
65
|
+
|
66
|
+
|
67
|
+
Originally extracted from the AXElements project.
|
68
|
+
|
69
|
+
'
|
70
|
+
email: markrada26@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions:
|
73
|
+
- ext/accessibility/bridge/extconf.rb
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- lib/accessibility/bridge/common.rb
|
77
|
+
- lib/accessibility/bridge/macruby.rb
|
78
|
+
- lib/accessibility/bridge/mri.rb
|
79
|
+
- lib/accessibility/bridge/version.rb
|
80
|
+
- lib/accessibility/bridge.rb
|
81
|
+
- ext/accessibility/bridge/bridge.c
|
82
|
+
- ext/accessibility/bridge/extconf.rb
|
83
|
+
- Rakefile
|
84
|
+
- README.markdown
|
85
|
+
- History.markdown
|
86
|
+
- .yardopts
|
87
|
+
- test/helper.rb
|
88
|
+
homepage: http://github.com/AXElements/accessibility_bridge
|
89
|
+
licenses:
|
90
|
+
- BSD 3-clause
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
hash: -1210497514143783933
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
hash: -1210497514143783933
|
113
|
+
requirements: []
|
114
|
+
rubyforge_project:
|
115
|
+
rubygems_version: 1.8.24
|
116
|
+
signing_key:
|
117
|
+
specification_version: 3
|
118
|
+
summary: A library for bridging into Cocoa on OSX
|
119
|
+
test_files:
|
120
|
+
- test/helper.rb
|