mouse 0.1.0 → 1.0.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/History.markdown CHANGED
@@ -1,3 +1,9 @@
1
+ # 1.0.0 - Port Completed
2
+
3
+ * Added optional `point` argument to all `Mouse` click methods
4
+ * Added duration argument to all `Mouse` methods that are animated
5
+ * Fix differences between MRI CGPoint and MacRuby CGPoint
6
+
1
7
  # 0.1.0 - The basic API
2
8
 
3
9
  * Fixed animation timing (sleep(3) type coercion issue)
data/README.markdown CHANGED
@@ -4,9 +4,58 @@ A port of mouse.rb from [AXElements](http://github.com/Marketcircle/AXElements),
4
4
  but cleaned up and rewritten in C to be more portable across languages and
5
5
  runtimes.
6
6
 
7
+ By itself, the `mouse` gem is not that useful; but in combination
8
+ with a gem for discovering the positions of things (like buttons) on
9
+ the screen, this gem is very powerful and can be used for tasks such
10
+ as automated functional
11
+ testing; this is the purpose of the
12
+ [AXElements](http://github.com/Marketcircle/AXElements) project.
13
+
14
+ [Documentation](http://rdoc.info/gems/mouse/frames)
15
+
16
+
7
17
  ## Examples
8
18
 
9
- TODO :P
19
+ require 'mouse'
20
+
21
+ Mouse.current_position # => #<CGPoint x=873.2 y=345.0>
22
+
23
+ # positions can be given as a an array with two points, or a CGPoint
24
+ Mouse.move_to [10, 10]
25
+ Mouse.move_to CGPoint.new(10, 10)
26
+
27
+ # optionally specify how long it should take the mouse to move
28
+ Mouse.move_to [800, 300], 0.2
29
+
30
+ Mouse.click
31
+ Mouse.double_click
32
+ Mouse.triple_click
33
+
34
+ # secondary_click and right_click are aliases to the same method
35
+ Mouse.secondary_click
36
+ Mouse.right_click
37
+
38
+ # positive number scrolls up, negative number scrolls down
39
+ Mouse.scroll 10
40
+ Mouse.scroll -10
41
+
42
+ # optionally specify units for scroll amount, :pixel or :line
43
+ Mouse.scroll 10, :pixels
44
+ Mouse.scroll -10, :pixels
45
+
46
+ See the [Mouse Documentation](http://rdoc.info/gems/mouse/Mouse) for
47
+ more details.
48
+
49
+ You may have noticed that when you ask the mouse to move to a specific
50
+ location that it may not end up at the exact co-ordinates, but it will
51
+ be close (distance of less than 1). This is by design, but that may
52
+ change in the future if there are enough complaints.
53
+
54
+
55
+ ## TODO
56
+
57
+ * Support for mouse gestures
58
+ * Make animation duration accurate (currently naiveté has a bit of error)
10
59
 
11
60
  ## Copyright
12
61
 
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- task :default => :install
1
+ task :default => :test
2
2
 
3
3
  require 'rake/clean'
4
4
  CLEAN.include '*.plist', '*.gch'
@@ -13,11 +13,12 @@ task :console => [:compile] do
13
13
  sh 'irb -Ilib -rmouse'
14
14
  end
15
15
 
16
- desc 'Run tests'
17
- task :test do
18
- # @todo
19
- ruby 'test/helper.rb'
16
+ require 'rake/testtask'
17
+ Rake::TestTask.new do |t|
18
+ t.libs << '.'
19
+ t.pattern = 'test/*_test.rb'
20
20
  end
21
+ task :test => :compile
21
22
 
22
23
 
23
24
  # Gem stuff
data/ext/mouse/mouse.c CHANGED
@@ -8,6 +8,7 @@ static ID sel_y;
8
8
  static ID sel_to_point;
9
9
  static ID sel_to_i;
10
10
  static ID sel_new;
11
+ static ID unit_pixel;
11
12
 
12
13
  #define CURRENT_POSITION rb_mouse_wrap_point(mouse_current_position())
13
14
 
@@ -57,109 +58,219 @@ rb_mouse_current_position(VALUE self)
57
58
  * Move the mouse cursor to the given co-ordinates
58
59
  *
59
60
  * @param point [CGPoint,Array(Number,Number),#to_point]
61
+ * @param duration [Number] animation time, in seconds (__optional__)
60
62
  * @return [CGPoint]
61
63
  */
62
64
  static
63
65
  VALUE
64
- rb_mouse_move_to(VALUE self, VALUE point)
66
+ rb_mouse_move_to(int argc, VALUE *argv, VALUE self)
65
67
  {
66
- mouse_move_to(rb_mouse_unwrap_point(point));
68
+ switch (argc)
69
+ {
70
+ case 0:
71
+ rb_raise(rb_eArgError, "move_to requires at least a one arg");
72
+ break;
73
+ case 1:
74
+ mouse_move_to(rb_mouse_unwrap_point(argv[0]));
75
+ break;
76
+ case 2:
77
+ default:
78
+ mouse_move_to2(rb_mouse_unwrap_point(argv[0]), NUM2DBL(argv[1]));
79
+ }
80
+
67
81
  return CURRENT_POSITION;
68
82
  }
69
83
 
70
84
  /*
71
85
  * Drag the mouse cursor to the given co-ordinates
72
86
  *
73
- * @param point [CGPoint,Array(Number,Number),#to_point]
87
+ * @param (see #move_to)
74
88
  * @return [CGPoint]
75
89
  */
76
90
  static
77
91
  VALUE
78
- rb_mouse_drag_to(VALUE self, VALUE point)
92
+ rb_mouse_drag_to(int argc, VALUE *argv, VALUE self)
79
93
  {
80
- mouse_drag_to(rb_mouse_unwrap_point(point));
94
+ switch (argc)
95
+ {
96
+ case 0:
97
+ rb_raise(rb_eArgError, "drag_to requires at least a one arg");
98
+ break;
99
+ case 1:
100
+ mouse_drag_to(rb_mouse_unwrap_point(argv[0]));
101
+ break;
102
+ case 2:
103
+ default:
104
+ mouse_drag_to2(rb_mouse_unwrap_point(argv[0]), NUM2DBL(argv[1]));
105
+ }
106
+
81
107
  return CURRENT_POSITION;
82
108
  }
83
109
 
84
110
  /*
111
+ * @note Scrolling by `:pixel` may not actually be by real pixels, but instead
112
+ * correspond to Cocoa co-ords (I don't have a retina display, so I haven't
113
+ * checked it out yet).
114
+ *
85
115
  * Generate `amount` scroll events at the current cursor position
86
116
  *
87
- * Returns number of lines scrolled.
117
+ * Returns number of lines scrolled. A positive `amount` will scroll up
118
+ * and a negative `amount` will scroll down.
119
+ *
120
+ * An invalid type of `units` will default to `:line`.
88
121
  *
89
122
  * @param amount [Number]
123
+ * @param units [Symbol] `:pixel` or `:line` (_default_: `:line` ) (__optional__)
90
124
  * @return [Number]
91
125
  */
92
126
  static
93
127
  VALUE
94
- rb_mouse_scroll(VALUE self, VALUE amount)
128
+ rb_mouse_scroll(int argc, VALUE *argv, VALUE self)
95
129
  {
96
- amount = rb_funcall(amount, sel_to_i, 0);
97
- mouse_scroll(NUM2SIZET(amount));
130
+ if (argc == 0 || argc > 3)
131
+ rb_raise(rb_eArgError, "scroll requires 1..3 arguments, you gave %d", argc);
132
+
133
+ VALUE amount = rb_funcall(argv[0], sel_to_i, 0);
134
+ size_t amt = NUM2SIZET(amount);
135
+
136
+ if (argc == 1)
137
+ mouse_scroll(NUM2SIZET(amt));
138
+
139
+ ID units = rb_to_id(argv[1]);
140
+
141
+ if (argc == 2) {
142
+ if (units == unit_pixel)
143
+ mouse_scroll2(amt, kCGScrollEventUnitPixel);
144
+ else
145
+ mouse_scroll2(amt, kCGScrollEventUnitLine);
146
+ }
147
+
148
+ if (argc == 3) {
149
+ double duration = NUM2DBL(argv[2]);
150
+
151
+ if (units == unit_pixel)
152
+ mouse_scroll3(amt, kCGScrollEventUnitPixel, duration);
153
+ else
154
+ mouse_scroll3(amt, kCGScrollEventUnitLine, duration);
155
+ }
156
+
98
157
  return amount;
99
158
  }
100
159
 
101
160
  /*
102
- * Generate the down click part of a click event at the current position
161
+ * Generate the down click part of a click event
103
162
  *
104
163
  * This might be useful in concert with {Mouse.click_up} if you want
105
164
  * to inject some behaviour between the down and up click events.
106
165
  *
166
+ * You can optionally specify a point to click; the mouse cursor will
167
+ * instantly jump to the given point.
168
+ *
169
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
107
170
  * @return [CGPoint]
108
171
  */
109
172
  static
110
173
  VALUE
111
- rb_mouse_click_down(VALUE self)
174
+ rb_mouse_click_down(int argc, VALUE *argv, VALUE self)
112
175
  {
113
- mouse_click_down();
176
+ switch (argc)
177
+ {
178
+ case 0:
179
+ mouse_click_down();
180
+ break;
181
+ case 1:
182
+ default:
183
+ mouse_click_down2(rb_mouse_unwrap_point(argv[0]));
184
+ }
185
+
114
186
  return CURRENT_POSITION;
115
187
  }
116
188
 
117
189
  /*
118
- * Generate the up click part of a click event at the current position
190
+ * Generate the up click part of a click event
119
191
  *
120
192
  * This might be useful in concert with {Mouse.click_down} if you want
121
193
  * to inject some behaviour between the down and up click events.
122
194
  *
195
+ * You can optionally specify a point to click; the mouse cursor will
196
+ * instantly jump to the given point.
197
+ *
198
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
123
199
  * @return [CGPoint]
124
200
  */
125
201
  static
126
202
  VALUE
127
- rb_mouse_click_up(VALUE self)
203
+ rb_mouse_click_up(int argc, VALUE *argv, VALUE self)
128
204
  {
129
- mouse_click_up();
205
+ switch (argc)
206
+ {
207
+ case 0:
208
+ mouse_click_up();
209
+ break;
210
+ case 1:
211
+ default:
212
+ mouse_click_up(rb_mouse_unwrap_point(argv[0]));
213
+ }
214
+
130
215
  return CURRENT_POSITION;
131
216
  }
132
217
 
133
218
  /*
134
- * Generate a regular click event at the current mouse position
219
+ * Generate a regular click event (both up and down events)
220
+ *
221
+ * You can optionally specify a point to click; the mouse cursor will
222
+ * instantly jump to the given point.
135
223
  *
224
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
136
225
  * @return [CGPoint]
137
226
  */
138
227
  static
139
228
  VALUE
140
- rb_mouse_click(VALUE self)
229
+ rb_mouse_click(int argc, VALUE *argv, VALUE self)
141
230
  {
142
- mouse_click();
231
+ switch (argc)
232
+ {
233
+ case 0:
234
+ mouse_click();
235
+ break;
236
+ case 1:
237
+ default:
238
+ mouse_click2(rb_mouse_unwrap_point(argv[0]));
239
+ }
240
+
143
241
  return CURRENT_POSITION;
144
242
  }
145
243
 
146
244
  /*
147
- * Generate a secondary click at the current mouse position
245
+ * Generate a secondary click (both down and up events)
148
246
  *
149
247
  * Secondary click is often referred to as "right click".
150
248
  *
249
+ * You can optionally specify a point to click; the mouse cursor will
250
+ * instantly jump to the given point.
251
+ *
252
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
151
253
  * @return [CGPoint]
152
254
  */
153
255
  static
154
256
  VALUE
155
- rb_mouse_secondary_click(VALUE self)
257
+ rb_mouse_secondary_click(int argc, VALUE *argv, VALUE self)
156
258
  {
157
- mouse_secondary_click();
259
+ switch (argc)
260
+ {
261
+ case 0:
262
+ mouse_secondary_click();
263
+ break;
264
+ case 1:
265
+ default:
266
+ mouse_secondary_click2(rb_mouse_unwrap_point(argv[0]));
267
+ }
268
+
158
269
  return CURRENT_POSITION;
159
270
  }
160
271
 
161
272
  /*
162
- * Generate a click using an arbitrary mouse button at the current position
273
+ * Generate a click using an arbitrary mouse button (down and up events)
163
274
  *
164
275
  * Numbers are used to map the mouse buttons. At the time of writing,
165
276
  * the documented values are:
@@ -172,30 +283,62 @@ rb_mouse_secondary_click(VALUE self)
172
283
  * to figure out. See the `CGMouseButton` enum in the reference
173
284
  * documentation for the most up to date list.
174
285
  *
286
+ * You can optionally specify a point to click; the mouse cursor will
287
+ * instantly jump to the given point.
288
+ *
175
289
  * @param button [Number,#to_i]
290
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
176
291
  * @return [CGPoint]
177
292
  */
178
293
  static
179
294
  VALUE
180
- rb_mouse_arbitrary_click(VALUE self, VALUE button)
295
+ rb_mouse_arbitrary_click(int argc, VALUE *argv, VALUE self)
181
296
  {
182
- button = rb_funcall(button, sel_to_i, 0);
183
- mouse_arbitrary_click(NUM2UINT(button));
297
+ if (argc == 0) {
298
+ rb_raise(rb_eArgError, "arbitrary_click requires at least one arg");
299
+ return Qnil;
300
+ }
301
+
302
+ uint_t button = NUM2INT(rb_funcall(argv[0], sel_to_i, 0));
303
+
304
+ switch (argc)
305
+ {
306
+ case 1:
307
+ mouse_arbitrary_click(button);
308
+ break;
309
+ case 2:
310
+ default:
311
+ mouse_arbitrary_click2(button, rb_mouse_unwrap_point(argv[1]));
312
+ }
313
+
184
314
  return CURRENT_POSITION;
185
315
  }
186
316
 
187
317
  /*
188
- * Generate a click event for the middle mouse button at the current position
318
+ * Generate a click event for the middle mouse button (down and up events)
189
319
  *
190
320
  * It doesn't matter if you don't have a middle mouse button.
191
321
  *
322
+ * You can optionally specify a point to click; the mouse cursor will
323
+ * instantly jump to the given point.
324
+ *
325
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
192
326
  * @return [CGPoint]
193
327
  */
194
328
  static
195
329
  VALUE
196
- rb_mouse_middle_click(VALUE self)
330
+ rb_mouse_middle_click(int argc, VALUE *argv, VALUE self)
197
331
  {
198
- mouse_middle_click();
332
+ switch (argc)
333
+ {
334
+ case 0:
335
+ mouse_middle_click();
336
+ break;
337
+ case 1:
338
+ default:
339
+ mouse_middle_click(rb_mouse_unwrap_point(argv[0]));
340
+ }
341
+
199
342
  return CURRENT_POSITION;
200
343
  }
201
344
 
@@ -205,16 +348,36 @@ rb_mouse_middle_click(VALUE self)
205
348
  * Unlike {Mouse.double_click} and {Mouse.triple_click} this will generate
206
349
  * a single event with the given number of clicks.
207
350
  *
351
+ * You can optionally specify a point to click; the mouse cursor will
352
+ * instantly jump to the given point.
353
+ *
208
354
  * @param num_clicks [Number,#to_i]
355
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
209
356
  * @return [CGPoint]
210
357
  */
211
358
  static
212
359
  VALUE
213
- rb_mouse_multi_click(VALUE self, VALUE num_clicks)
360
+ rb_mouse_multi_click(int argc, VALUE *argv, VALUE self)
214
361
  {
362
+
363
+ if (argc == 0) {
364
+ rb_raise(rb_eArgError, "multi_click requires at least one arg");
365
+ return Qnil;
366
+ }
367
+
215
368
  // TODO: there has got to be a more idiomatic way to do this coercion
216
- num_clicks = rb_funcall(num_clicks, sel_to_i, 0);
217
- mouse_multi_click(NUM2SIZET(num_clicks));
369
+ size_t num_clicks = NUM2SIZET(rb_funcall(argv[0], sel_to_i, 0));
370
+
371
+ switch (argc)
372
+ {
373
+ case 1:
374
+ mouse_multi_click(num_clicks);
375
+ break;
376
+ case 2:
377
+ default:
378
+ mouse_multi_click2(num_clicks, rb_mouse_unwrap_point(argv[1]));
379
+ }
380
+
218
381
  return CURRENT_POSITION;
219
382
  }
220
383
 
@@ -225,13 +388,26 @@ rb_mouse_multi_click(VALUE self, VALUE num_clicks)
225
388
  * Apps seem to respond more consistently to this behaviour since that is
226
389
  * how a human would have to generate a double click event.
227
390
  *
391
+ * You can optionally specify a point to click; the mouse cursor will
392
+ * instantly jump to the given point.
393
+ *
394
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
228
395
  * @return [CGPoint]
229
396
  */
230
397
  static
231
398
  VALUE
232
- rb_mouse_double_click(VALUE self)
399
+ rb_mouse_double_click(int argc, VALUE *argv, VALUE self)
233
400
  {
234
- mouse_double_click();
401
+ switch (argc)
402
+ {
403
+ case 0:
404
+ mouse_double_click();
405
+ break;
406
+ case 1:
407
+ default:
408
+ mouse_double_click2(rb_mouse_unwrap_point(argv[0]));
409
+ }
410
+
235
411
  return CURRENT_POSITION;
236
412
  }
237
413
 
@@ -243,13 +419,26 @@ rb_mouse_double_click(VALUE self)
243
419
  * this behaviour since that is how a human would have to generate a
244
420
  * triple click event.
245
421
  *
422
+ * You can optionally specify a point to click; the mouse cursor will
423
+ * instantly jump to the given point.
424
+ *
425
+ * @param point [CGPoint] (_default_: {#current_position}) (__optional__)
246
426
  * @return [CGPoint]
247
427
  */
248
428
  static
249
429
  VALUE
250
- rb_mouse_triple_click(VALUE self)
430
+ rb_mouse_triple_click(int argc, VALUE *argv, VALUE self)
251
431
  {
252
- mouse_triple_click();
432
+ switch (argc)
433
+ {
434
+ case 0:
435
+ mouse_triple_click();
436
+ break;
437
+ case 1:
438
+ default:
439
+ mouse_triple_click2(rb_mouse_unwrap_point(argv[0]));
440
+ }
441
+
253
442
  return CURRENT_POSITION;
254
443
  }
255
444
 
@@ -265,10 +454,20 @@ Init_mouse()
265
454
  sel_to_i = rb_intern("to_i");
266
455
  sel_new = rb_intern("new");
267
456
 
457
+ unit_pixel = rb_intern("pixel");
458
+
268
459
  /*
269
460
  * Document-module: Mouse
270
461
  *
271
- * Herp Derp TODO
462
+ * A module with methods that "tap" into the system input methods.
463
+ * This is done by wrapping wrapping around the CoreGraphics event
464
+ * taps API provided by OS X.
465
+ *
466
+ * The module provides a simple Ruby interface to performing mouse
467
+ * interactions such as moving and clicking.
468
+ *
469
+ * This module can be used in a stand alone fashion or you can mix
470
+ * it into another class.
272
471
  *
273
472
  * [Reference](http://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html)
274
473
  */
@@ -276,17 +475,19 @@ Init_mouse()
276
475
 
277
476
  rb_funcall(rb_mMouse, rb_intern("extend"), 1, rb_mMouse);
278
477
 
279
- rb_define_method(rb_mMouse, "current_position", rb_mouse_current_position, 0);
280
- rb_define_method(rb_mMouse, "move_to", rb_mouse_move_to, 1);
281
- rb_define_method(rb_mMouse, "drag_to", rb_mouse_drag_to, 1);
282
- rb_define_method(rb_mMouse, "scroll", rb_mouse_scroll, 1);
283
- rb_define_method(rb_mMouse, "click_down", rb_mouse_click_down, 0);
284
- rb_define_method(rb_mMouse, "click_up", rb_mouse_click_up, 0);
285
- rb_define_method(rb_mMouse, "click", rb_mouse_click, 0);
286
- rb_define_method(rb_mMouse, "secondary_click", rb_mouse_secondary_click, 0);
287
- rb_define_method(rb_mMouse, "arbitrary_click", rb_mouse_arbitrary_click, 1);
288
- rb_define_method(rb_mMouse, "middle_click", rb_mouse_middle_click, 0);
289
- rb_define_method(rb_mMouse, "multi_click", rb_mouse_multi_click, 1);
290
- rb_define_method(rb_mMouse, "double_click", rb_mouse_double_click, 0);
291
- rb_define_method(rb_mMouse, "triple_click", rb_mouse_triple_click, 0);
478
+ rb_define_method(rb_mMouse, "current_position", rb_mouse_current_position, 0);
479
+ rb_define_method(rb_mMouse, "move_to", rb_mouse_move_to, -1);
480
+ rb_define_method(rb_mMouse, "drag_to", rb_mouse_drag_to, -1);
481
+ rb_define_method(rb_mMouse, "scroll", rb_mouse_scroll, -1);
482
+ rb_define_method(rb_mMouse, "click_down", rb_mouse_click_down, -1);
483
+ rb_define_method(rb_mMouse, "click_up", rb_mouse_click_up, -1);
484
+ rb_define_method(rb_mMouse, "click", rb_mouse_click, -1);
485
+ rb_define_method(rb_mMouse, "secondary_click", rb_mouse_secondary_click, -1);
486
+ rb_define_method(rb_mMouse, "middle_click", rb_mouse_middle_click, -1);
487
+ rb_define_method(rb_mMouse, "arbitrary_click", rb_mouse_arbitrary_click, -1);
488
+ rb_define_method(rb_mMouse, "multi_click", rb_mouse_multi_click, -1);
489
+ rb_define_method(rb_mMouse, "double_click", rb_mouse_double_click, -1);
490
+ rb_define_method(rb_mMouse, "triple_click", rb_mouse_triple_click, -1);
491
+
492
+ rb_define_alias(rb_mMouse, "right_click", "secondary_click");
292
493
  }
data/ext/mouse/mouser.c CHANGED
@@ -9,15 +9,15 @@
9
9
  #include <ApplicationServices/ApplicationServices.h>
10
10
  #include "mouser.h"
11
11
 
12
- static const uint_t FPS = 120;
13
- static const uint_t QUANTUM = 1000000 / 120; // should be FPS, but GCC sucks
12
+ static const uint_t FPS = 240;
13
+ static const uint_t QUANTUM = 1000000 / 240; // should be FPS, but GCC sucks
14
14
  static const double DEFAULT_DURATION = 0.2; // seconds
15
15
 
16
16
  #define NEW_EVENT(type,point,button) CGEventCreateMouseEvent(nil,type,point,button)
17
17
  #define POST(event) CGEventPost(kCGHIDEventTap, event)
18
18
  #define CHANGE(event,type) CGEventSetType(event, type)
19
19
 
20
- #define CLOSE_ENOUGH(a,b) ((pow(a.x-b.x,2)+pow(a.y-b.y,2)) <= 1.0)
20
+ #define CLOSE_ENOUGH(a,b) ((abs(a.x - b.x) < 1.0) && (abs(a.y - b.y) < 1.0))
21
21
  #define NOW (CFDateCreate(nil,CFAbsoluteTimeGetCurrent()))
22
22
 
23
23
  #ifdef NOT_MACRUBY
@@ -62,7 +62,7 @@ mouse_animate(
62
62
  )
63
63
  {
64
64
  CFDateRef current_time = NULL;
65
- CGPoint current_point = start_point;
65
+ CGPoint current_point = start_point;
66
66
  double xstep = (end_point.x - start_point.x) / (duration * FPS);
67
67
  double ystep = (end_point.y - start_point.y) / (duration * FPS);
68
68
  CFDateRef start = NOW;
@@ -79,8 +79,11 @@ mouse_animate(
79
79
 
80
80
  mouse_sleep(1);
81
81
  current_time = NOW;
82
- if (CFDateGetTimeIntervalSinceDate(NOW, start) > 5.0)
82
+
83
+ // this is a safety
84
+ if (CFDateGetTimeIntervalSinceDate(NOW, start) > (duration + 1))
83
85
  break;
86
+
84
87
  RELEASE(current_time);
85
88
  current_time = NULL;
86
89
 
@@ -145,7 +148,7 @@ mouse_drag_to(CGPoint point)
145
148
 
146
149
 
147
150
  void
148
- mouse_scroll3(size_t amount, enum MouseMovementUnit units, double duration)
151
+ mouse_scroll3(size_t amount, CGScrollEventUnit units, double duration)
149
152
  {
150
153
  size_t steps = round(FPS * duration);
151
154
  double current = 0.0;
@@ -156,13 +159,13 @@ mouse_scroll3(size_t amount, enum MouseMovementUnit units, double duration)
156
159
  done = (double)(step+1) / (double)steps;
157
160
  scroll = round((done - current) * amount);
158
161
  POSTRELEASE(CGEventCreateScrollWheelEvent(nil, units, 1, scroll));
159
- mouse_sleep(1);
162
+ mouse_sleep(2);
160
163
  current += (double)scroll / (double)amount;
161
164
  }
162
165
  }
163
166
 
164
167
  void
165
- mouse_scroll2(size_t amount, enum MouseMovementUnit units)
168
+ mouse_scroll2(size_t amount, CGScrollEventUnit units)
166
169
  {
167
170
  mouse_scroll3(amount, units, DEFAULT_DURATION);
168
171
  }
@@ -170,7 +173,7 @@ mouse_scroll2(size_t amount, enum MouseMovementUnit units)
170
173
  void
171
174
  mouse_scroll(size_t amount)
172
175
  {
173
- mouse_scroll2(amount, kMouseScrollByLine);
176
+ mouse_scroll2(amount, kCGScrollEventUnitLine);
174
177
  }
175
178
 
176
179
 
@@ -184,8 +187,7 @@ mouse_click_down3(CGPoint point, uint_t sleep_quanta)
184
187
  void
185
188
  mouse_click_down2(CGPoint point)
186
189
  {
187
- // TODO: replace constant 12 with something more abstract
188
- mouse_click_down3(point, 12);
190
+ mouse_click_down3(point, FPS / 10);
189
191
  }
190
192
 
191
193
  void
@@ -240,8 +242,7 @@ mouse_secondary_click3(CGPoint point, uint_t sleep_quanta)
240
242
  void
241
243
  mouse_secondary_click2(CGPoint point)
242
244
  {
243
- // TODO: replace constant 12 with something more abstract
244
- mouse_secondary_click3(point, 12);
245
+ mouse_secondary_click3(point, FPS / 10);
245
246
  }
246
247
 
247
248
  void
@@ -268,7 +269,7 @@ mouse_arbitrary_click3(CGEventMouseSubtype button, CGPoint point, uint_t sleep_q
268
269
  void
269
270
  mouse_arbitrary_click2(CGEventMouseSubtype button, CGPoint point)
270
271
  {
271
- mouse_arbitrary_click3(button, point, 12);
272
+ mouse_arbitrary_click3(button, point, FPS / 10);
272
273
  }
273
274
 
274
275
  void
data/ext/mouse/mouser.h CHANGED
@@ -10,13 +10,6 @@
10
10
 
11
11
  typedef unsigned int uint_t;
12
12
 
13
- enum MouseMovementUnit {
14
- kMouseScrollByLine = kCGScrollEventUnitLine,
15
- // TODO: might not be real pixels, might be Cocoa co-ords, need to investigate
16
- kMouseScrollByPixel = kCGScrollEventUnitPixel
17
- };
18
-
19
-
20
13
  CGPoint mouse_current_position();
21
14
 
22
15
  void mouse_move_to(CGPoint point);
@@ -26,8 +19,8 @@ void mouse_drag_to(CGPoint point);
26
19
  void mouse_drag_to2(CGPoint point, double duration);
27
20
 
28
21
  void mouse_scroll(size_t amount);
29
- void mouse_scroll2(size_t amount, enum MouseMovementUnit units);
30
- void mouse_scroll3(size_t amount, enum MouseMovementUnit units, double duration);
22
+ void mouse_scroll2(size_t amount, CGScrollEventUnit units);
23
+ void mouse_scroll3(size_t amount, CGScrollEventUnit units, double duration);
31
24
 
32
25
  void mouse_click_down();
33
26
  void mouse_click_down2(CGPoint point);
data/lib/mouse/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Mouse
2
- VERSION = '0.1.0'
2
+ VERSION = '1.0.0'
3
3
  end
4
4
 
data/lib/mouse.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  if RUBY_ENGINE == 'macruby'
2
2
 
3
+ framework 'AppKit'
4
+
3
5
  # A workaround that guarantees that `CGPoint` is defined
4
- framework '/System/Library/Frameworks/CoreGraphics.framework'
6
+ MOUNTAIN_LION_APPKIT_VERSION = 1187
7
+ if NSAppKitVersionNumber >= MOUNTAIN_LION_APPKIT_VERSION
8
+ framework '/System/Library/Frameworks/CoreGraphics.framework'
9
+ end
5
10
 
6
11
  else
7
12
 
@@ -9,6 +14,12 @@ else
9
14
  # A structure that contains a point in a two-dimensional coordinate system
10
15
  class CGPoint < Struct.new(:x, :y)
11
16
 
17
+ # @param x [Number]
18
+ # @param y [Number]
19
+ def initialize x = 0.0, y = 0.0
20
+ super
21
+ end
22
+
12
23
  # @!attribute [rw] x
13
24
  # The `x` co-ordinate of the screen point
14
25
  # @return [Number]
@@ -24,7 +35,7 @@ else
24
35
  #
25
36
  # @return [String]
26
37
  def inspect
27
- "#<CGPoint x=#{self[:x]} y=#{self[:y]}>"
38
+ "#<CGPoint x=#{self.x.to_f} y=#{self.y.to_f}>"
28
39
  end
29
40
 
30
41
  end
data/test/helper.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  require 'minitest/autorun'
2
+ require 'mouse'
2
3
 
3
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mouse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-03 00:00:00.000000000 Z
12
+ date: 2012-12-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yard
@@ -98,18 +98,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
98
  - - ! '>='
99
99
  - !ruby/object:Gem::Version
100
100
  version: '0'
101
- segments:
102
- - 0
103
- hash: 1024147063034037924
104
101
  required_rubygems_version: !ruby/object:Gem::Requirement
105
102
  none: false
106
103
  requirements:
107
104
  - - ! '>='
108
105
  - !ruby/object:Gem::Version
109
106
  version: '0'
110
- segments:
111
- - 0
112
- hash: 1024147063034037924
113
107
  requirements: []
114
108
  rubyforge_project:
115
109
  rubygems_version: 1.8.24