accessibility_core 0.1.2 → 0.3.1

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.
Files changed (42) hide show
  1. data/.yardopts +2 -0
  2. data/History.markdown +33 -0
  3. data/README.markdown +11 -0
  4. data/Rakefile +18 -49
  5. data/ext/accessibility/bridge/{ext/accessibility/bridge/bridge.c → bridge.c} +136 -56
  6. data/ext/accessibility/bridge/bridge.h +132 -0
  7. data/ext/accessibility/bridge/{ext/accessibility/bridge/extconf.rb → extconf.rb} +1 -1
  8. data/ext/accessibility/core/core.c +21 -3
  9. data/ext/accessibility/core/extconf.rb +7 -1
  10. data/ext/accessibility/extras/extconf.rb +28 -0
  11. data/ext/accessibility/extras/extras.c +842 -0
  12. data/ext/accessibility/extras/extras.h +1 -0
  13. data/ext/accessibility/highlighter/extconf.rb +9 -2
  14. data/ext/accessibility/highlighter/highlighter.c +291 -1
  15. data/{ext/accessibility/bridge/lib → lib}/accessibility/bridge.rb +3 -3
  16. data/{ext/accessibility/bridge/lib → lib}/accessibility/bridge/common.rb +0 -0
  17. data/{ext/accessibility/bridge/lib → lib}/accessibility/bridge/macruby.rb +17 -0
  18. data/{ext/accessibility/bridge/lib → lib}/accessibility/bridge/mri.rb +10 -7
  19. data/lib/accessibility/core.rb +1 -1
  20. data/lib/accessibility/core/macruby.rb +1 -1
  21. data/lib/accessibility/core/version.rb +1 -1
  22. data/lib/accessibility/extras.rb +5 -0
  23. data/lib/accessibility/extras/common.rb +19 -0
  24. data/lib/accessibility/highlighter.rb +8 -0
  25. data/lib/accessibility/highlighter/macruby.rb +85 -0
  26. data/test/helper.rb +18 -28
  27. metadata +33 -56
  28. data/ext/accessibility/bridge/lib/accessibility/bridge/version.rb +0 -6
  29. data/ext/accessibility/bridge/test/array_test.rb +0 -31
  30. data/ext/accessibility/bridge/test/boxed_test.rb +0 -23
  31. data/ext/accessibility/bridge/test/cfrange_test.rb +0 -21
  32. data/ext/accessibility/bridge/test/cgpoint_test.rb +0 -54
  33. data/ext/accessibility/bridge/test/cgrect_test.rb +0 -60
  34. data/ext/accessibility/bridge/test/cgsize_test.rb +0 -54
  35. data/ext/accessibility/bridge/test/helper.rb +0 -19
  36. data/ext/accessibility/bridge/test/nsstring_test.rb +0 -22
  37. data/ext/accessibility/bridge/test/nsurl_test.rb +0 -17
  38. data/ext/accessibility/bridge/test/object_test.rb +0 -19
  39. data/ext/accessibility/bridge/test/range_test.rb +0 -16
  40. data/ext/accessibility/bridge/test/string_test.rb +0 -35
  41. data/ext/accessibility/bridge/test/uri_test.rb +0 -15
  42. data/ext/accessibility/core/bridge.h +0 -1
@@ -0,0 +1,132 @@
1
+ #include "ruby.h"
2
+ #import <Cocoa/Cocoa.h>
3
+
4
+
5
+ // these functions are available on MacRuby as well as MRI
6
+ void spin(double seconds);
7
+
8
+ // initialize all the dynamic data (e.g. class pointers)
9
+ void Init_bridge();
10
+
11
+
12
+ #ifdef NOT_MACRUBY
13
+
14
+ extern VALUE rb_mAccessibility;
15
+ extern VALUE rb_cElement;
16
+ extern VALUE rb_cCGPoint;
17
+ extern VALUE rb_cCGSize;
18
+ extern VALUE rb_cCGRect;
19
+ extern VALUE rb_mURI; // URI module
20
+ extern VALUE rb_cURI; // URI::Generic class
21
+ extern VALUE rb_cScreen;
22
+
23
+ extern ID sel_x;
24
+ extern ID sel_y;
25
+ extern ID sel_width;
26
+ extern ID sel_height;
27
+ extern ID sel_origin;
28
+ extern ID sel_size;
29
+ extern ID sel_to_point;
30
+ extern ID sel_to_size;
31
+ extern ID sel_to_rect;
32
+ extern ID sel_to_s;
33
+ extern ID sel_parse;
34
+
35
+
36
+ #define WRAP_ARRAY(wrapper) do { \
37
+ CFIndex length = CFArrayGetCount(array); \
38
+ VALUE ary = rb_ary_new2(length); \
39
+ \
40
+ for (CFIndex idx = 0; idx < length; idx++) \
41
+ rb_ary_store( \
42
+ ary, \
43
+ idx, \
44
+ wrapper(CFArrayGetValueAtIndex(array, idx)) \
45
+ ); \
46
+ return ary; \
47
+ } while (false);
48
+
49
+
50
+ void cf_finalizer(void* obj);
51
+ void objc_finalizer(void* obj);
52
+
53
+ VALUE wrap_unknown(CFTypeRef obj);
54
+ CFTypeRef unwrap_unknown(VALUE obj);
55
+
56
+ VALUE wrap_point(CGPoint point);
57
+ CGPoint unwrap_point(VALUE point);
58
+
59
+ VALUE wrap_size(CGSize size);
60
+ CGSize unwrap_size(VALUE size);
61
+
62
+ VALUE wrap_rect(CGRect rect);
63
+ VALUE coerce_to_rect(VALUE obj);
64
+ CGRect unwrap_rect(VALUE rect);
65
+
66
+ VALUE convert_cf_range(CFRange range);
67
+ CFRange convert_rb_range(VALUE range);
68
+
69
+ VALUE wrap_value_point(AXValueRef value);
70
+ VALUE wrap_value_size(AXValueRef value);
71
+ VALUE wrap_value_rect(AXValueRef value);
72
+ VALUE wrap_value_range(AXValueRef value);
73
+ VALUE wrap_value_error(AXValueRef value);
74
+ VALUE wrap_value(AXValueRef value);
75
+ VALUE wrap_array_values(CFArrayRef array);
76
+
77
+ AXValueRef unwrap_value_point(VALUE val);
78
+ AXValueRef unwrap_value_size(VALUE val);
79
+ AXValueRef unwrap_value_rect(VALUE val);
80
+ AXValueRef unwrap_value_range(VALUE val);
81
+ AXValueRef unwrap_value(VALUE value);
82
+
83
+ VALUE wrap_ref(AXUIElementRef ref);
84
+ VALUE wrap_array_refs(CFArrayRef array);
85
+ AXUIElementRef unwrap_ref(VALUE obj);
86
+
87
+ VALUE wrap_string(CFStringRef string);
88
+ VALUE wrap_nsstring(NSString* string);
89
+ VALUE wrap_array_strings(CFArrayRef array);
90
+ VALUE wrap_array_nsstrings(NSArray* ary);
91
+ CFStringRef unwrap_string(VALUE string);
92
+ NSString* unwrap_nsstring(VALUE string);
93
+
94
+ VALUE wrap_long(CFNumberRef num);
95
+ VALUE wrap_long_long(CFNumberRef num);
96
+ VALUE wrap_float(CFNumberRef num);
97
+ // Generic CFNumber wrapper, use it if you do not
98
+ // know the primitive type of number
99
+ VALUE wrap_number(CFNumberRef number);
100
+ VALUE wrap_array_numbers(CFArrayRef array);
101
+
102
+ CFNumberRef unwrap_long(VALUE num);
103
+ CFNumberRef unwrap_long_long(VALUE num);
104
+ CFNumberRef unwrap_float(VALUE num);
105
+ CFNumberRef unwrap_number(VALUE number);
106
+
107
+ VALUE wrap_url(CFURLRef url);
108
+ VALUE wrap_nsurl(NSURL* url);
109
+ CFURLRef unwrap_url(VALUE url);
110
+ VALUE wrap_array_urls(CFArrayRef array);
111
+
112
+ VALUE wrap_date(CFDateRef date);
113
+ VALUE wrap_nsdate(NSDate* date);
114
+ VALUE wrap_array_dates(CFArrayRef array);
115
+ CFDateRef unwrap_date(VALUE date);
116
+
117
+ VALUE wrap_boolean(CFBooleanRef bool_val);
118
+ VALUE wrap_array_booleans(CFArrayRef array);
119
+ CFBooleanRef unwrap_boolean(VALUE bool_val);
120
+
121
+ // this function assumes that arrays are homogeneous;
122
+ // which is usually the case coming from the CF world
123
+ VALUE wrap_array(CFArrayRef array);
124
+
125
+ VALUE to_ruby(CFTypeRef obj);
126
+ CFTypeRef to_ax(VALUE obj);
127
+
128
+ VALUE wrap_screen(NSScreen* screen);
129
+ VALUE wrap_array_screens(CFArrayRef array);
130
+ NSScreen* unwrap_screen(VALUE screen);
131
+
132
+ #endif
@@ -19,4 +19,4 @@ else
19
19
  $CFLAGS << ' -DNOT_MACRUBY'
20
20
  end
21
21
 
22
- create_makefile 'accessibility/bridge'
22
+ create_makefile 'accessibility/bridge/bridge'
@@ -3,7 +3,7 @@
3
3
  #ifdef NOT_MACRUBY /* This entire extension is pointless when running on MacRuby */
4
4
 
5
5
  #import <Cocoa/Cocoa.h>
6
- #include "bridge.h"
6
+ #include "../bridge/bridge.h"
7
7
 
8
8
 
9
9
  static ID ivar_attrs;
@@ -613,7 +613,7 @@ rb_acore_element_at(VALUE self, VALUE point)
613
613
  else
614
614
  return Qnil;
615
615
  default:
616
- return handle_error(self, code); // point, nil, nil
616
+ return handle_error(self, code);
617
617
  }
618
618
  }
619
619
 
@@ -633,6 +633,8 @@ rb_acore_equality(VALUE self, VALUE other)
633
633
  void
634
634
  Init_core()
635
635
  {
636
+ Init_bridge();
637
+
636
638
  #ifdef NOT_MACRUBY
637
639
  if (!AXAPIEnabled())
638
640
  rb_raise(
@@ -645,7 +647,23 @@ Init_core()
645
647
  "------------------------------------------------------------------------\n"
646
648
  );
647
649
 
648
- Init_bridge();
650
+ // bs that needs to be initialized from the bridge.c import
651
+ sel_x = rb_intern("x");
652
+ sel_y = rb_intern("y");
653
+ sel_width = rb_intern("width");
654
+ sel_height = rb_intern("height");
655
+ sel_origin = rb_intern("origin");
656
+ sel_size = rb_intern("size");
657
+ sel_to_point = rb_intern("to_point");
658
+ sel_to_size = rb_intern("to_size");
659
+ sel_to_s = rb_intern("to_s");
660
+
661
+ rb_mAccessibility = rb_const_get(rb_cObject, rb_intern("Accessibility"));
662
+ rb_cElement = rb_define_class_under(rb_mAccessibility, "Element", rb_cObject);
663
+ rb_cCGPoint = rb_const_get(rb_cObject, rb_intern("CGPoint"));
664
+ rb_cCGSize = rb_const_get(rb_cObject, rb_intern("CGSize"));
665
+ rb_cCGRect = rb_const_get(rb_cObject, rb_intern("CGRect"));
666
+
649
667
 
650
668
  // these should be defined by now
651
669
  rb_mAccessibility = rb_const_get(rb_cObject, rb_intern("Accessibility"));
@@ -19,4 +19,10 @@ else
19
19
  $CFLAGS << ' -DNOT_MACRUBY'
20
20
  end
21
21
 
22
- create_makefile 'accessibility/core'
22
+ create_makefile 'accessibility/core/core'
23
+
24
+ # modify the bugger so we can depend on bridge.h properly
25
+ makefile = File.read 'Makefile'
26
+ makefile.gsub! '$(DLLIB): $(OBJS) Makefile', '$(DLLIB): $(OBJS) Makefile ../bridge/bridge.o'
27
+ makefile.gsub! '$(Q) $(LDSHARED) -o $@', '$(Q) $(LDSHARED) -o $@ ../bridge/bridge.o'
28
+ File.open('Makefile', 'w') { |f| f.write makefile }
@@ -0,0 +1,28 @@
1
+ require 'mkmf'
2
+
3
+ $CFLAGS << ' -std=c99 -Wall -Werror -pedantic -ObjC'
4
+ $LIBS << ' -framework CoreFoundation -framework Cocoa -framework IOKit'
5
+
6
+ if RUBY_ENGINE == 'macruby'
7
+ $CFLAGS << ' -fobjc-gc'
8
+ $CFLAGS.sub! /-Werror/, '' # :(
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/extras/extras'
23
+
24
+ # modify the bugger so we can depend on bridge.h properly
25
+ makefile = File.read 'Makefile'
26
+ makefile.gsub! '$(DLLIB): $(OBJS) Makefile', '$(DLLIB): $(OBJS) Makefile ../bridge/bridge.o'
27
+ makefile.gsub! '$(Q) $(LDSHARED) -o $@', '$(Q) $(LDSHARED) -o $@ ../bridge/bridge.o'
28
+ File.open('Makefile', 'w') { |f| f.write makefile }
@@ -0,0 +1,842 @@
1
+ #include "ruby.h"
2
+
3
+ #include "../bridge/bridge.h"
4
+
5
+ #import <IOKit/IOKitlib.h>
6
+ #import <IOKit/ps/IOPowerSources.h>
7
+ #import <IOKit/ps/IOPSKeys.h>
8
+ #import <IOKit/pwr_mgt/IOPMLib.h>
9
+ #import <IOKit/hidsystem/IOHIDShared.h>
10
+
11
+ static VALUE rb_mBattery;
12
+ #ifndef NOT_MACRUBY
13
+ static VALUE rb_cScreen;
14
+ #endif
15
+
16
+ static VALUE battery_not_installed;
17
+ static VALUE battery_charged;
18
+ static VALUE battery_charging;
19
+ static VALUE battery_discharging;
20
+
21
+ static io_connect_t screen_connection = MACH_PORT_NULL;
22
+
23
+
24
+ #ifdef NOT_MACRUBY
25
+
26
+ #import <Cocoa/Cocoa.h>
27
+
28
+ static VALUE rb_cRunningApp;
29
+ static VALUE rb_cWorkspace;
30
+ static VALUE rb_cProcInfo;
31
+ static VALUE rb_cHost;
32
+
33
+ static VALUE key_opts;
34
+ //static VALUE key_event_params;
35
+ //static VALUE key_launch_id;
36
+
37
+
38
+ static
39
+ VALUE
40
+ wrap_app(NSRunningApplication* app)
41
+ {
42
+ return Data_Wrap_Struct(rb_cRunningApp, NULL, objc_finalizer, (void*)app);
43
+ }
44
+
45
+ static
46
+ NSRunningApplication*
47
+ unwrap_app(VALUE app)
48
+ {
49
+ NSRunningApplication* running_app;
50
+ Data_Get_Struct(app, NSRunningApplication, running_app);
51
+ return running_app;
52
+ }
53
+
54
+ static VALUE wrap_array_apps(NSArray* ary)
55
+ {
56
+ CFArrayRef array = (CFArrayRef)ary;
57
+ WRAP_ARRAY(wrap_app);
58
+ }
59
+
60
+
61
+ static
62
+ VALUE
63
+ rb_running_app_with_pid(VALUE self, VALUE pid)
64
+ {
65
+ NSRunningApplication* app = [NSRunningApplication
66
+ runningApplicationWithProcessIdentifier:NUM2PIDT(pid)];
67
+ if (app)
68
+ return wrap_app(app);
69
+ return Qnil; // ruby behaviour would be to raise, but we want "drop-in" compat
70
+ }
71
+
72
+ static
73
+ VALUE
74
+ rb_running_app_with_bundle_id(VALUE self, VALUE bundle_id)
75
+ {
76
+ return wrap_array_apps([NSRunningApplication
77
+ runningApplicationsWithBundleIdentifier:unwrap_nsstring(bundle_id)]);
78
+ }
79
+
80
+ static
81
+ VALUE
82
+ rb_running_app_current_app(VALUE self)
83
+ {
84
+ NSRunningApplication* app = [NSRunningApplication currentApplication];
85
+ if (app)
86
+ return wrap_app(app);
87
+ return Qnil;
88
+ }
89
+
90
+ static
91
+ VALUE
92
+ rb_running_app_drop_nuke(VALUE self)
93
+ {
94
+ [NSRunningApplication terminateAutomaticallyTerminableApplications];
95
+ return rb_cRunningApp; // return this to be MacRuby compatible
96
+ }
97
+
98
+
99
+ static
100
+ VALUE
101
+ rb_running_app_is_active(VALUE self)
102
+ {
103
+ return unwrap_app(self).isActive ? Qtrue : Qfalse;
104
+ }
105
+
106
+ static
107
+ VALUE
108
+ rb_running_app_activate(VALUE self, VALUE options)
109
+ {
110
+ return ([unwrap_app(self) activateWithOptions:FIX2INT(options)] ? Qtrue : Qfalse);
111
+ }
112
+
113
+ static
114
+ VALUE
115
+ rb_running_app_activation_policy(VALUE self)
116
+ {
117
+ return INT2FIX(unwrap_app(self).activationPolicy);
118
+ }
119
+
120
+ static
121
+ VALUE
122
+ rb_running_app_hide(VALUE self)
123
+ {
124
+ return ([unwrap_app(self) hide] ? Qtrue : Qfalse);
125
+ }
126
+
127
+ static
128
+ VALUE
129
+ rb_running_app_unhide(VALUE self)
130
+ {
131
+ return ([unwrap_app(self) unhide] ? Qtrue : Qfalse);
132
+ }
133
+
134
+ static
135
+ VALUE
136
+ rb_running_app_is_hidden(VALUE self)
137
+ {
138
+ return (unwrap_app(self).isHidden ? Qtrue : Qfalse);
139
+ }
140
+
141
+ static
142
+ VALUE
143
+ rb_running_app_localized_name(VALUE self)
144
+ {
145
+ NSString* string = [unwrap_app(self) localizedName];
146
+ VALUE str = Qnil;
147
+ if (string)
148
+ str = wrap_nsstring(string);
149
+ [string release];
150
+ return str;
151
+ }
152
+
153
+ static
154
+ VALUE
155
+ rb_running_app_bundle_id(VALUE self)
156
+ {
157
+ NSString* name = [unwrap_app(self) bundleIdentifier];
158
+ if (name)
159
+ return wrap_nsstring(name);
160
+ return Qnil;
161
+ }
162
+
163
+ static
164
+ VALUE
165
+ rb_running_app_bundle_url(VALUE self)
166
+ {
167
+ NSURL* url = [unwrap_app(self) bundleURL];
168
+ VALUE rburl = Qnil;
169
+ if (url)
170
+ rburl = wrap_nsurl(url);
171
+ [url release];
172
+ return rburl;
173
+ }
174
+
175
+ static
176
+ VALUE
177
+ rb_running_app_executable_arch(VALUE self)
178
+ {
179
+ return INT2FIX(unwrap_app(self).executableArchitecture);
180
+ }
181
+
182
+ static
183
+ VALUE
184
+ rb_running_app_executable_url(VALUE self)
185
+ {
186
+ return wrap_nsurl(unwrap_app(self).executableURL);
187
+ }
188
+
189
+ static
190
+ VALUE
191
+ rb_running_app_launch_date(VALUE self)
192
+ {
193
+ return wrap_nsdate(unwrap_app(self).launchDate);
194
+ }
195
+
196
+ static
197
+ VALUE
198
+ rb_running_app_is_launched(VALUE self)
199
+ {
200
+ return (unwrap_app(self).isFinishedLaunching ? Qtrue : Qfalse);
201
+ }
202
+
203
+ static
204
+ VALUE
205
+ rb_running_app_pid(VALUE self)
206
+ {
207
+ return PIDT2NUM(unwrap_app(self).processIdentifier);
208
+ }
209
+
210
+ static
211
+ VALUE
212
+ rb_running_app_owns_menu_bar(VALUE self)
213
+ {
214
+ return (unwrap_app(self).ownsMenuBar ? Qtrue : Qfalse);
215
+ }
216
+
217
+ static
218
+ VALUE
219
+ rb_running_app_force_terminate(VALUE self)
220
+ {
221
+ return ([unwrap_app(self) forceTerminate] ? Qtrue : Qfalse);
222
+ }
223
+
224
+ static
225
+ VALUE
226
+ rb_running_app_terminate(VALUE self)
227
+ {
228
+ return ([unwrap_app(self) terminate] ? Qtrue : Qfalse);
229
+ }
230
+
231
+ static
232
+ VALUE
233
+ rb_running_app_is_terminated(VALUE self)
234
+ {
235
+ return (unwrap_app(self).isTerminated ? Qtrue : Qfalse);
236
+ }
237
+
238
+ static
239
+ VALUE
240
+ rb_running_app_equality(VALUE self, VALUE other)
241
+ {
242
+ if (CLASS_OF(other) == rb_cRunningApp)
243
+ if ([unwrap_app(self) isEqual:unwrap_app(other)])
244
+ return Qtrue;
245
+ return Qfalse;
246
+ }
247
+
248
+
249
+ static
250
+ VALUE
251
+ rb_workspace_shared(VALUE self)
252
+ {
253
+ return self;
254
+ }
255
+
256
+
257
+ static
258
+ VALUE
259
+ rb_workspace_running_apps(VALUE self)
260
+ {
261
+ NSArray* apps = [[NSWorkspace sharedWorkspace] runningApplications];
262
+ VALUE rb_apps = wrap_array_apps(apps);
263
+ [apps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
264
+ [obj retain];
265
+ }];
266
+ [apps release];
267
+ return rb_apps;
268
+ }
269
+
270
+ static
271
+ VALUE
272
+ rb_workspace_frontmost_app(VALUE self)
273
+ {
274
+ return wrap_app([[NSWorkspace sharedWorkspace] frontmostApplication]);
275
+ }
276
+
277
+ static
278
+ VALUE
279
+ rb_workspace_menu_bar_owner(VALUE self)
280
+ {
281
+ return wrap_app([[NSWorkspace sharedWorkspace] menuBarOwningApplication]);
282
+ }
283
+
284
+ static
285
+ VALUE
286
+ rb_workspace_find(VALUE self, VALUE query)
287
+ {
288
+ BOOL result =
289
+ [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:unwrap_nsstring(query)];
290
+ return (result ? Qtrue : Qfalse);
291
+ }
292
+
293
+ /*
294
+ * @todo One thing we want to look into is using Launch Services instead of
295
+ * NSWorkspace for app launching. The reason is that we will avoid the
296
+ * problem launching new apps that have not been registered yet. But the
297
+ * big thing is that we can get the PSN for the application, which will
298
+ * allow for more directed input using CGEvents and it also gives us a
299
+ * data structure to wait on that indicates when the app has properly
300
+ * started up.
301
+ *
302
+ * The `additonalEventParamDescriptor` option is not supported by the bridge rigt now
303
+ */
304
+ static
305
+ VALUE
306
+ rb_workspace_launch(VALUE self, VALUE bundle_id, VALUE opts)
307
+ {
308
+ NSString* identifier = unwrap_nsstring(bundle_id);
309
+ NSWorkspaceLaunchOptions options = NUM2INT(rb_hash_lookup(opts, key_opts));
310
+
311
+ BOOL result = [[NSWorkspace sharedWorkspace]
312
+ launchAppWithBundleIdentifier:identifier
313
+ options:options
314
+ additionalEventParamDescriptor:nil
315
+ launchIdentifier:nil];
316
+
317
+ [identifier release];
318
+ return result ? Qtrue : Qfalse;
319
+ }
320
+
321
+
322
+ static
323
+ VALUE
324
+ rb_procinfo_self(VALUE self)
325
+ {
326
+ return self;
327
+ }
328
+
329
+ static
330
+ VALUE
331
+ rb_procinfo_os_version(VALUE self)
332
+ {
333
+ NSString* value = [[NSProcessInfo processInfo] operatingSystemVersionString];
334
+ VALUE obj = wrap_nsstring(value);
335
+ [value release];
336
+ return obj;
337
+ }
338
+
339
+ static
340
+ VALUE
341
+ rb_procinfo_sys_uptime(VALUE self)
342
+ {
343
+ return DBL2NUM([[NSProcessInfo processInfo] systemUptime]);
344
+ }
345
+
346
+ static
347
+ VALUE
348
+ rb_procinfo_cpu_count(VALUE self)
349
+ {
350
+ return INT2FIX([[NSProcessInfo processInfo] processorCount]);
351
+ }
352
+
353
+ static
354
+ VALUE
355
+ rb_procinfo_active_cpus(VALUE self)
356
+ {
357
+ return INT2FIX([[NSProcessInfo processInfo] activeProcessorCount]);
358
+ }
359
+
360
+ static
361
+ VALUE
362
+ rb_procinfo_total_ram(VALUE self)
363
+ {
364
+ return ULL2NUM([[NSProcessInfo processInfo] physicalMemory]);
365
+ }
366
+
367
+
368
+ static
369
+ VALUE
370
+ rb_host_self(VALUE self)
371
+ {
372
+ return self; // hack
373
+ }
374
+
375
+ static
376
+ VALUE
377
+ rb_host_names(VALUE self)
378
+ {
379
+ NSArray* nsnames = [[NSHost currentHost] names];
380
+ VALUE rbnames = wrap_array_nsstrings(nsnames);
381
+ [nsnames release];
382
+ return rbnames;
383
+ }
384
+
385
+ static
386
+ VALUE
387
+ rb_host_addresses(VALUE self)
388
+ {
389
+ NSArray* nsaddrs = [[NSHost currentHost] addresses];
390
+ VALUE rbaddrs = wrap_array_nsstrings(nsaddrs);
391
+ [nsaddrs release];
392
+ return rbaddrs;
393
+ }
394
+
395
+ static
396
+ VALUE
397
+ rb_host_localized_name(VALUE self)
398
+ {
399
+ NSString* name = [[NSHost currentHost] localizedName];
400
+ VALUE rb_name = wrap_nsstring(name);
401
+ [name release];
402
+ return rb_name;
403
+ }
404
+
405
+
406
+ VALUE
407
+ wrap_screen(NSScreen* screen)
408
+ {
409
+ return Data_Wrap_Struct(rb_cScreen, NULL, NULL, (void*)screen);
410
+ }
411
+
412
+ VALUE wrap_array_screens(CFArrayRef array) { WRAP_ARRAY(wrap_screen); }
413
+
414
+ NSScreen*
415
+ unwrap_screen(VALUE screen)
416
+ {
417
+ NSScreen* ns_screen;
418
+ Data_Get_Struct(screen, NSScreen, ns_screen);
419
+ return ns_screen;
420
+ }
421
+
422
+ static
423
+ VALUE
424
+ rb_screen_main(VALUE self)
425
+ {
426
+ return wrap_screen([NSScreen mainScreen]);
427
+ }
428
+
429
+ static
430
+ VALUE
431
+ rb_screen_screens(VALUE self)
432
+ {
433
+ return wrap_array_screens((CFArrayRef)[NSScreen screens]);
434
+ }
435
+
436
+ static
437
+ VALUE
438
+ rb_screen_frame(VALUE self)
439
+ {
440
+ return wrap_rect([unwrap_screen(self) frame]);
441
+ }
442
+
443
+ #endif
444
+
445
+
446
+ static
447
+ VALUE
448
+ #ifdef NOT_MACRUBY
449
+ rb_screen_wake(VALUE self)
450
+ #else
451
+ rb_screen_wake(VALUE self, SEL sel)
452
+ #endif
453
+ {
454
+ // don't bother if we are awake
455
+ if (!CGDisplayIsAsleep(CGMainDisplayID()))
456
+ return Qtrue;
457
+
458
+ if (screen_connection == MACH_PORT_NULL) {
459
+ io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
460
+ if (service != MACH_PORT_NULL) {
461
+ IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &screen_connection);
462
+ IOObjectRelease(service);
463
+ }
464
+ else { // give up
465
+ return Qfalse;
466
+ }
467
+ }
468
+
469
+ CGPoint mouse = [NSEvent mouseLocation];
470
+ IOGPoint point = { mouse.x, mouse.y };
471
+ unsigned int flags = (unsigned int)[NSEvent modifierFlags];
472
+ NXEventData data;
473
+
474
+ IOHIDPostEvent(screen_connection, NX_FLAGSCHANGED, point, &data, kNXEventDataVersion, flags, 0);
475
+
476
+ // spin rims while we wait for the screen to fully wake up
477
+ spin(1);
478
+
479
+ return Qtrue;
480
+ }
481
+
482
+
483
+
484
+
485
+ // Find and return the dictionary that has the battery info
486
+ static
487
+ CFDictionaryRef
488
+ battery_info()
489
+ {
490
+ CFTypeRef psource_info = IOPSCopyPowerSourcesInfo();
491
+ CFArrayRef psources = IOPSCopyPowerSourcesList(psource_info);
492
+
493
+ // constant global strings (like ruby symbols, or lisp atoms, NXAtom, etc)
494
+ // so we do not need to release it later (unless you really want to)
495
+ CFStringRef type_key = CFSTR(kIOPSTypeKey);
496
+ CFStringRef battery_key = CFSTR(kIOPSInternalBatteryType);
497
+
498
+ CFIndex length = CFArrayGetCount(psources);
499
+ for (CFIndex i = 0; i < length; i++) {
500
+
501
+ CFTypeRef psource = CFArrayGetValueAtIndex(psources, i);
502
+ CFDictionaryRef source_info = IOPSGetPowerSourceDescription(psource_info, psource);
503
+ CFRetain(source_info);
504
+
505
+ if (CFEqual(CFDictionaryGetValue(source_info, type_key), battery_key)) {
506
+ CFRelease(psources);
507
+ CFRelease(psource_info);
508
+ return source_info;
509
+ }
510
+ else {
511
+ CFRelease(source_info);
512
+ }
513
+ }
514
+
515
+ CFRelease(psources);
516
+ CFRelease(psource_info);
517
+ return NULL;
518
+ }
519
+
520
+ /*
521
+ * Returns the current battery state
522
+ *
523
+ * The state will be one of:
524
+ *
525
+ * - `:not_installed`
526
+ * - `:charged`
527
+ * - `:charging`
528
+ * - `:discharging`
529
+ *
530
+ * @return [Symbol]
531
+ */
532
+ static
533
+ VALUE
534
+ rb_battery_state(VALUE self)
535
+ {
536
+ // constant global strings (like ruby symbols, or lisp atoms, NXAtom, etc)
537
+ // so we do not need to release it later (unless you really want to)
538
+ CFStringRef charged_key = CFSTR(kIOPSIsChargedKey);
539
+ CFStringRef charging_key = CFSTR(kIOPSIsChargingKey);
540
+
541
+ VALUE state = battery_not_installed;
542
+ CFDictionaryRef info = battery_info();
543
+
544
+ if (info) {
545
+ if (CFDictionaryGetValue(info, charged_key) == kCFBooleanTrue)
546
+ state = battery_charged;
547
+ else if (CFDictionaryGetValue(info, charging_key) == kCFBooleanTrue)
548
+ state = battery_charging;
549
+ else
550
+ state = battery_discharging;
551
+
552
+ CFRelease(info);
553
+ }
554
+
555
+ return state;
556
+ }
557
+
558
+ /*
559
+ * Returns the batteries charge level as a percentage from 0 to 1
560
+ *
561
+ * A special value of `-1.0` is returned when there is no battery present.
562
+ *
563
+ * @return [Float]
564
+ */
565
+ static
566
+ VALUE
567
+ rb_battery_level(VALUE self)
568
+ {
569
+ // constant global strings (like ruby symbols, or lisp atoms, NXAtom, etc)
570
+ // so we do not need to release it later (unless you really want to)
571
+ CFStringRef capacity_key = CFSTR(kIOPSCurrentCapacityKey);
572
+ CFStringRef max_capacity_key = CFSTR(kIOPSMaxCapacityKey);
573
+
574
+ double level = -1.0;
575
+ CFDictionaryRef info = battery_info();
576
+
577
+ if (info) {
578
+ CFNumberRef current_cap = CFDictionaryGetValue(info, capacity_key);
579
+ CFNumberRef max_cap = CFDictionaryGetValue(info, max_capacity_key);
580
+
581
+ if (current_cap && max_cap) {
582
+ int current = 0;
583
+ int max = 0;
584
+
585
+ CFNumberGetValue(current_cap, kCFNumberIntType, &current);
586
+ CFNumberGetValue(max_cap, kCFNumberIntType, &max);
587
+
588
+ level = ((double)current)/((double)max);
589
+ }
590
+
591
+ CFRelease(info);
592
+ }
593
+
594
+ return DBL2NUM(level);
595
+ }
596
+
597
+
598
+ /*
599
+ * Returns the estimated number of minutes until the battery is fully discharged
600
+ *
601
+ * A special value of `-1` indicates that the value is currently being
602
+ * estimated and you should try again later.
603
+ *
604
+ * A special value of `0` indicates that the battery is not discharging,
605
+ * which usually means that the battery does not exist or is in a
606
+ * charging/charged state.
607
+ *
608
+ * @return [Fixnum]
609
+ */
610
+ static
611
+ VALUE
612
+ rb_battery_time_to_empty(VALUE self)
613
+ {
614
+ CFStringRef ttempty_key = CFSTR(kIOPSTimeToEmptyKey);
615
+ int time = -1;
616
+ CFDictionaryRef info = battery_info();
617
+
618
+ if (info) {
619
+ CFNumberRef current_time = CFDictionaryGetValue(info, ttempty_key);
620
+ if (current_time)
621
+ CFNumberGetValue(current_time, kCFNumberIntType, &time);
622
+
623
+ CFRelease(info);
624
+ }
625
+
626
+ if (time)
627
+ return INT2FIX(time);
628
+ else
629
+ return INT2FIX(0);
630
+ }
631
+
632
+
633
+ /*
634
+ * Returns the estimated number of minutes until the battery is fully charged
635
+ *
636
+ * A special value of `-1` indicates that the value is currently being
637
+ * estimated and you should try again later.
638
+ *
639
+ * @return [Fixnum]
640
+ */
641
+ static
642
+ VALUE
643
+ rb_battery_time_full_charge(VALUE self)
644
+ {
645
+ CFStringRef ttfull_key = CFSTR(kIOPSTimeToFullChargeKey);
646
+ int time = -1;
647
+ CFDictionaryRef info = battery_info();
648
+
649
+ if (info) {
650
+ CFNumberRef current_time = CFDictionaryGetValue(info, ttfull_key);
651
+ if (current_time)
652
+ CFNumberGetValue(current_time, kCFNumberIntType, &time);
653
+
654
+ CFRelease(info);
655
+ }
656
+
657
+ return INT2FIX(time);
658
+ }
659
+
660
+
661
+
662
+
663
+ void
664
+ Init_extras()
665
+ {
666
+ Init_bridge();
667
+
668
+ // force Ruby to be registered as an app with the system
669
+ [NSApplication sharedApplication];
670
+
671
+ #ifdef NOT_MACRUBY
672
+
673
+ /*
674
+ * Document-class: NSRunningApplication
675
+ *
676
+ * A 99% drop-in replacement for Cocoa's `NSWorkspace` class on MRI and other
677
+ * non-MacRuby rubies.
678
+ *
679
+ * See [Apple's Developer Reference](https://developer.apple.com/library/mac/#documentation/AppKit/Reference/NSRunningApplication_Class/Reference/Reference.html)
680
+ * for documentation on the methods in this class.
681
+ */
682
+ rb_cRunningApp = rb_define_class("NSRunningApplication", rb_cObject);
683
+
684
+ rb_define_singleton_method(rb_cRunningApp, "runningApplicationWithProcessIdentifier", rb_running_app_with_pid, 1);
685
+ rb_define_singleton_method(rb_cRunningApp, "runningApplicationsWithBundleIdentifier", rb_running_app_with_bundle_id, 1);
686
+ rb_define_singleton_method(rb_cRunningApp, "currentApplication", rb_running_app_current_app, 0);
687
+ rb_define_singleton_method(rb_cRunningApp, "terminateAutomaticallyTerminableApplications", rb_running_app_drop_nuke, 0);
688
+
689
+ rb_define_method(rb_cRunningApp, "active?", rb_running_app_is_active, 0);
690
+ rb_define_method(rb_cRunningApp, "activateWithOptions", rb_running_app_activate, 1);
691
+ rb_define_method(rb_cRunningApp, "activationPolicy", rb_running_app_activation_policy, 0);
692
+ rb_define_method(rb_cRunningApp, "hide", rb_running_app_hide, 0);
693
+ rb_define_method(rb_cRunningApp, "unhide", rb_running_app_unhide, 0);
694
+ rb_define_method(rb_cRunningApp, "hidden?", rb_running_app_is_hidden, 0);
695
+ rb_define_method(rb_cRunningApp, "localizedName", rb_running_app_localized_name, 0);
696
+ //rb_define_method(rb_cRunningApp, "icon", rb_running_app_icon, 0);
697
+ rb_define_method(rb_cRunningApp, "bundleIdentifier", rb_running_app_bundle_id, 0);
698
+ rb_define_method(rb_cRunningApp, "bundleURL", rb_running_app_bundle_url, 0);
699
+ rb_define_method(rb_cRunningApp, "executableArchitecture", rb_running_app_executable_arch, 0);
700
+ rb_define_method(rb_cRunningApp, "executableURL", rb_running_app_executable_url, 0);
701
+ rb_define_method(rb_cRunningApp, "launchDate", rb_running_app_launch_date, 0);
702
+ rb_define_method(rb_cRunningApp, "finishedLaunching?", rb_running_app_is_launched, 0);
703
+ rb_define_method(rb_cRunningApp, "processIdentifier", rb_running_app_pid, 0);
704
+ rb_define_method(rb_cRunningApp, "ownsMenuBar", rb_running_app_owns_menu_bar, 0);
705
+ rb_define_alias(rb_cRunningApp, "ownsMenuBar?", "ownsMenuBar");
706
+ rb_define_method(rb_cRunningApp, "forceTerminate", rb_running_app_force_terminate, 0);
707
+ rb_define_method(rb_cRunningApp, "terminate", rb_running_app_terminate, 0);
708
+ rb_define_method(rb_cRunningApp, "terminated?", rb_running_app_is_terminated, 0);
709
+ rb_define_method(rb_cRunningApp, "==", rb_running_app_equality, 1);
710
+
711
+ // Technically these are global constants, but in MacRuby you can still access them from any
712
+ // namespace. So, we will try by first adding them to the NSRunningApplication namespae only
713
+ #define RUNNING_APP_CONST(str, val) rb_define_const(rb_cRunningApp, str, INT2FIX(val));
714
+ if (!rb_const_defined_at(rb_cRunningApp, rb_intern("NSApplicationActivateAllWindows"))) {
715
+ RUNNING_APP_CONST("NSApplicationActivateAllWindows", NSApplicationActivateAllWindows);
716
+ RUNNING_APP_CONST("NSApplicationActivateIgnoringOtherApps", NSApplicationActivateIgnoringOtherApps);
717
+
718
+ RUNNING_APP_CONST("NSBundleExecutableArchitectureI386", NSBundleExecutableArchitectureI386);
719
+ RUNNING_APP_CONST("NSBundleExecutableArchitecturePPC", NSBundleExecutableArchitecturePPC);
720
+ RUNNING_APP_CONST("NSBundleExecutableArchitectureX86_64", NSBundleExecutableArchitectureX86_64);
721
+ RUNNING_APP_CONST("NSBundleExecutableArchitecturePPC64", NSBundleExecutableArchitecturePPC64);
722
+ }
723
+
724
+
725
+ /*
726
+ * Document-class: NSWorkspace
727
+ *
728
+ * A subset of Cocoa's `NSWorkspace` class.
729
+ *
730
+ * See [Apple's Developer Reference](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/Reference/Reference.html)
731
+ * for documentation on the methods available in this class.
732
+ */
733
+ rb_cWorkspace = rb_define_class("NSWorkspace", rb_cObject);
734
+
735
+ rb_define_singleton_method(rb_cWorkspace, "runningApplications", rb_workspace_running_apps, 0);
736
+ rb_define_singleton_method(rb_cWorkspace, "sharedWorkspace", rb_workspace_shared, 0);
737
+ rb_define_singleton_method(rb_cWorkspace, "frontmostApplication", rb_workspace_frontmost_app, 0);
738
+ rb_define_singleton_method(rb_cWorkspace, "menuBarOwningApplication", rb_workspace_menu_bar_owner, 0);
739
+ rb_define_singleton_method(rb_cWorkspace, "showSearchResultsForQueryString", rb_workspace_find, 1);
740
+ rb_define_singleton_method(rb_cWorkspace, "launchAppWithBundleIdentifier", rb_workspace_launch, 2);
741
+
742
+ key_opts = ID2SYM(rb_intern("options"));
743
+ // key_event_params = ID2SYM(rb_intern("additionalEventParamDescriptor"));
744
+ // key_launch_id = ID2SYM(rb_intern("launchIdentifier"));
745
+
746
+ #define WORKSPACE_CONST(str, val) rb_define_const(rb_cWorkspace, str, INT2FIX(val));
747
+ if (!rb_const_defined_at(rb_cWorkspace, rb_intern("NSWorkspaceLaunchAndPrint"))) {
748
+ WORKSPACE_CONST("NSWorkspaceLaunchAndPrint", NSWorkspaceLaunchAndPrint);
749
+ WORKSPACE_CONST("NSWorkspaceLaunchInhibitingBackgroundOnly", NSWorkspaceLaunchInhibitingBackgroundOnly);
750
+ WORKSPACE_CONST("NSWorkspaceLaunchWithoutAddingToRecents", NSWorkspaceLaunchWithoutAddingToRecents);
751
+ WORKSPACE_CONST("NSWorkspaceLaunchWithoutActivation", NSWorkspaceLaunchWithoutActivation);
752
+ WORKSPACE_CONST("NSWorkspaceLaunchAsync", NSWorkspaceLaunchAsync);
753
+ WORKSPACE_CONST("NSWorkspaceLaunchAllowingClassicStartup", NSWorkspaceLaunchAllowingClassicStartup);
754
+ WORKSPACE_CONST("NSWorkspaceLaunchPreferringClassic", NSWorkspaceLaunchPreferringClassic);
755
+ WORKSPACE_CONST("NSWorkspaceLaunchNewInstance", NSWorkspaceLaunchNewInstance);
756
+ WORKSPACE_CONST("NSWorkspaceLaunchAndHide", NSWorkspaceLaunchAndHide);
757
+ WORKSPACE_CONST("NSWorkspaceLaunchAndHideOthers", NSWorkspaceLaunchAndHideOthers);
758
+ WORKSPACE_CONST("NSWorkspaceLaunchDefault", NSWorkspaceLaunchDefault);
759
+ }
760
+
761
+
762
+ /*
763
+ * Document-class: NSProcessInfo
764
+ *
765
+ * A subset of Cocoa's `NSProcessInfo` class. Methods that might be
766
+ * useful to have been bridged.
767
+ *
768
+ * See [Apple's Developer Reference](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSProcessInfo_Class/Reference/Reference.html)
769
+ * for documentation on the methods available in this class.
770
+ */
771
+ rb_cProcInfo = rb_define_class("NSProcessInfo", rb_cObject);
772
+
773
+ rb_define_singleton_method(rb_cProcInfo, "processInfo", rb_procinfo_self, 0);
774
+ rb_define_singleton_method(rb_cProcInfo, "operatingSystemVersionString", rb_procinfo_os_version, 0);
775
+ rb_define_singleton_method(rb_cProcInfo, "systemUptime", rb_procinfo_sys_uptime, 0);
776
+ rb_define_singleton_method(rb_cProcInfo, "processorCount", rb_procinfo_cpu_count, 0);
777
+ rb_define_singleton_method(rb_cProcInfo, "activeProcessorCount", rb_procinfo_active_cpus, 0);
778
+ rb_define_singleton_method(rb_cProcInfo, "physicalMemory", rb_procinfo_total_ram, 0);
779
+
780
+
781
+ /*
782
+ * Document-class: NSHost
783
+ *
784
+ * A large subset of Cocoa's `NSHost` class. Methods that might be
785
+ * useful to have have been bridged.
786
+ *
787
+ * See [Apple's Developer Reference](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSHost_Class/Reference/Reference.html)
788
+ * for documentation on the methods available in this class.
789
+ */
790
+ rb_cHost = rb_define_class("NSHost", rb_cObject);
791
+
792
+ rb_define_singleton_method(rb_cHost, "currentHost", rb_host_self, 0);
793
+ rb_define_singleton_method(rb_cHost, "names", rb_host_names, 0);
794
+ rb_define_singleton_method(rb_cHost, "addresses", rb_host_addresses, 0);
795
+ rb_define_singleton_method(rb_cHost, "localizedName", rb_host_localized_name, 0);
796
+ #endif
797
+
798
+
799
+ /*
800
+ * Document-class: NSScreen
801
+ *
802
+ * A small subset of Cocoa's `NSScreen` class. Methods that might be
803
+ * useful to have have been bridged.
804
+ *
805
+ * See [Apple's Developer Reference](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSScreen_Class/Reference/Reference.html)
806
+ * for documentation on the methods available in this class.
807
+ */
808
+ rb_cScreen = rb_define_class("NSScreen", rb_cObject);
809
+
810
+ #ifdef NOT_MACRUBY
811
+ rb_define_singleton_method(rb_cScreen, "mainScreen", rb_screen_main, 0);
812
+ rb_define_singleton_method(rb_cScreen, "screens", rb_screen_screens, 0);
813
+ rb_define_singleton_method(rb_cScreen, "wakeup", rb_screen_wake, 0); // our custom method
814
+ rb_define_method( rb_cScreen, "frame", rb_screen_frame, 0);
815
+ #else
816
+ rb_objc_define_method(*(VALUE*)rb_cScreen, "wakeup", rb_screen_wake, 0);
817
+ #endif
818
+
819
+
820
+ /*
821
+ * Document-module: Battery
822
+ *
823
+ * Utility methods for getting information about the system battery
824
+ * (if present).
825
+ */
826
+ rb_mBattery = rb_define_module("Battery");
827
+ rb_extend_object(rb_mBattery, rb_mBattery);
828
+
829
+ battery_not_installed = ID2SYM(rb_intern("not_installed"));
830
+ battery_charged = ID2SYM(rb_intern("charged"));
831
+ battery_charging = ID2SYM(rb_intern("charging"));
832
+ battery_discharging = ID2SYM(rb_intern("discharging"));
833
+
834
+ rb_define_method(rb_mBattery, "state", rb_battery_state, 0);
835
+ rb_define_method(rb_mBattery, "level", rb_battery_level, 0);
836
+ rb_define_method(rb_mBattery, "time_to_discharged", rb_battery_time_to_empty, 0);
837
+ rb_define_method(rb_mBattery, "time_to_charged", rb_battery_time_full_charge, 0);
838
+
839
+ rb_define_alias(rb_mBattery, "charge_level", "level");
840
+ rb_define_alias(rb_mBattery, "time_to_empty", "time_to_discharged");
841
+ rb_define_alias(rb_mBattery, "time_to_full_charge", "time_to_charged");
842
+ }