accessibility_core 0.1.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }