mouse 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.markdown +6 -0
- data/README.markdown +50 -1
- data/Rakefile +6 -5
- data/ext/mouse/mouse.c +250 -49
- data/ext/mouse/mouser.c +15 -14
- data/ext/mouse/mouser.h +2 -9
- data/lib/mouse/version.rb +1 -1
- data/lib/mouse.rb +13 -2
- data/test/helper.rb +1 -0
- metadata +2 -8
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
|
-
|
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 => :
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
66
|
+
rb_mouse_move_to(int argc, VALUE *argv, VALUE self)
|
65
67
|
{
|
66
|
-
|
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
|
87
|
+
* @param (see #move_to)
|
74
88
|
* @return [CGPoint]
|
75
89
|
*/
|
76
90
|
static
|
77
91
|
VALUE
|
78
|
-
rb_mouse_drag_to(VALUE
|
92
|
+
rb_mouse_drag_to(int argc, VALUE *argv, VALUE self)
|
79
93
|
{
|
80
|
-
|
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
|
128
|
+
rb_mouse_scroll(int argc, VALUE *argv, VALUE self)
|
95
129
|
{
|
96
|
-
|
97
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
295
|
+
rb_mouse_arbitrary_click(int argc, VALUE *argv, VALUE self)
|
181
296
|
{
|
182
|
-
|
183
|
-
|
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
|
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
|
-
|
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
|
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(
|
217
|
-
|
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
|
-
|
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
|
-
|
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
|
-
*
|
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,
|
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,
|
284
|
-
rb_define_method(rb_mMouse, "click_up", rb_mouse_click_up,
|
285
|
-
rb_define_method(rb_mMouse, "click", rb_mouse_click,
|
286
|
-
rb_define_method(rb_mMouse, "secondary_click", rb_mouse_secondary_click,
|
287
|
-
rb_define_method(rb_mMouse, "
|
288
|
-
rb_define_method(rb_mMouse, "
|
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,
|
291
|
-
rb_define_method(rb_mMouse, "triple_click", rb_mouse_triple_click,
|
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 =
|
13
|
-
static const uint_t QUANTUM = 1000000 /
|
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) ((
|
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
|
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
|
-
|
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,
|
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(
|
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,
|
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,
|
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
|
-
|
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
|
-
|
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,
|
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,
|
30
|
-
void mouse_scroll3(size_t amount,
|
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
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
|
-
|
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
|
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
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:
|
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-
|
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
|