mac-robot 0.2.3 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 002b8be116c9feea37ae23ac55cc05911189dc7998108c2751a10bddb0c038bf
4
+ data.tar.gz: 4354f97d4b55d61741b99de682d1708a6aafdb737d1affaf24c92134c9334eb7
5
+ SHA512:
6
+ metadata.gz: 064d07a920fddc44e55647155c1cb26c9987878967688a233eed0036035afa702a6fa84a612216e97fced7cd940570d864196b5270aa32af50332d0eb80ae8cc
7
+ data.tar.gz: 4dc039577b578b06f705648690661931cc4c391765f76bb3b36104381244f72767302dfa229a47946f47fad4366382c33712f5395e923b5da05123942a1cd681
data/Gemfile CHANGED
@@ -6,7 +6,9 @@ source "http://rubygems.org"
6
6
  # Add dependencies to develop your gem here.
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
  group :development do
9
+ gem "rake", "< 11.0"
10
+ gem "json", "~> 2.5.1"
9
11
  gem "rspec", "~> 2.8.0"
10
12
  gem "bundler"
11
- gem "jeweler", "~> 1.8.3"
13
+ gem "jeweler", "~> 2.3.9"
12
14
  end
data/Gemfile.lock CHANGED
@@ -1,17 +1,57 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ addressable (2.4.0)
5
+ builder (3.2.4)
6
+ descendants_tracker (0.0.4)
7
+ thread_safe (~> 0.3, >= 0.3.1)
4
8
  diff-lcs (1.1.3)
5
- git (1.2.5)
6
- jeweler (1.8.3)
7
- bundler (~> 1.0)
9
+ faraday (0.9.2)
10
+ multipart-post (>= 1.2, < 3)
11
+ git (1.8.1)
12
+ rchardet (~> 1.8)
13
+ github_api (0.16.0)
14
+ addressable (~> 2.4.0)
15
+ descendants_tracker (~> 0.0.4)
16
+ faraday (~> 0.8, < 0.10)
17
+ hashie (>= 3.4)
18
+ mime-types (>= 1.16, < 3.0)
19
+ oauth2 (~> 1.0)
20
+ hashie (4.1.0)
21
+ highline (2.0.3)
22
+ jeweler (2.3.9)
23
+ builder
24
+ bundler
8
25
  git (>= 1.2.5)
26
+ github_api (~> 0.16.0)
27
+ highline (>= 1.6.15)
28
+ nokogiri (>= 1.5.10)
29
+ psych
9
30
  rake
10
31
  rdoc
11
- json (1.6.5)
12
- rake (0.9.2.2)
13
- rdoc (3.12)
14
- json (~> 1.4)
32
+ semver2
33
+ json (2.5.1)
34
+ jwt (2.2.2)
35
+ mime-types (2.99.3)
36
+ mini_portile2 (2.5.0)
37
+ multi_json (1.15.0)
38
+ multi_xml (0.6.0)
39
+ multipart-post (2.1.1)
40
+ nokogiri (1.11.3)
41
+ mini_portile2 (~> 2.5.0)
42
+ racc (~> 1.4)
43
+ oauth2 (1.4.7)
44
+ faraday (>= 0.8, < 2.0)
45
+ jwt (>= 1.0, < 3.0)
46
+ multi_json (~> 1.3)
47
+ multi_xml (~> 0.5)
48
+ rack (>= 1.2, < 3)
49
+ psych (3.3.1)
50
+ racc (1.5.2)
51
+ rack (2.2.3)
52
+ rake (10.5.0)
53
+ rchardet (1.8.0)
54
+ rdoc (6.3.0)
15
55
  rspec (2.8.0)
16
56
  rspec-core (~> 2.8.0)
17
57
  rspec-expectations (~> 2.8.0)
@@ -20,11 +60,18 @@ GEM
20
60
  rspec-expectations (2.8.0)
21
61
  diff-lcs (~> 1.1.2)
22
62
  rspec-mocks (2.8.0)
63
+ semver2 (3.4.2)
64
+ thread_safe (0.3.6)
23
65
 
24
66
  PLATFORMS
25
67
  ruby
26
68
 
27
69
  DEPENDENCIES
28
70
  bundler
29
- jeweler (~> 1.8.3)
71
+ jeweler (~> 2.3.9)
72
+ json (~> 2.5.1)
73
+ rake (< 11.0)
30
74
  rspec (~> 2.8.0)
75
+
76
+ BUNDLED WITH
77
+ 2.1.4
data/README.rdoc CHANGED
@@ -12,8 +12,13 @@ A Library to Automate User Interactions
12
12
 
13
13
  robot.mouse_press
14
14
  robot.mouse_move(250, 250)
15
+ robot.mouse_drag(100, 200)
15
16
  robot.mouse_release
16
17
 
18
+ robot.mouse_current_location # => 100, 200
19
+
20
+ robot.scroll_wheel(:x => 10, :y => -20, :z => 5)
21
+
17
22
  === Automate keyboard
18
23
 
19
24
  [0x04, 0x0e, 0x25, 0x25, 0x1f].each do |keycode|
data/Rakefile CHANGED
@@ -32,10 +32,10 @@ ext_names = %w/event_dispatcher util/
32
32
  ext_names.each do |ext_name|
33
33
  CLEAN.include Dir.glob("ext/#{ext_name}/*{.o,.log}")
34
34
  CLEAN.include "ext/#{ext_name}/Makefile"
35
- CLOBBER.include "ext/#{ext_name}/#{ext_name}.bundle"
36
- CLOBBER.include "lib/#{ext_name}.bundle"
35
+ CLOBBER.include "ext/#{ext_name}/#{ext_name}.h.bundle"
36
+ CLOBBER.include "lib/#{ext_name}.h.bundle"
37
37
 
38
- file "lib/#{ext_name}.bundle" =>
38
+ file "lib/#{ext_name}.h.bundle" =>
39
39
  Dir.glob("ext/#{ext_name}/*{.rb,.m}") do
40
40
  Dir.chdir("ext/#{ext_name}") do
41
41
  # this does essentially the same thing
@@ -43,10 +43,10 @@ ext_names.each do |ext_name|
43
43
  ruby "extconf.rb"
44
44
  sh "make"
45
45
  end
46
- cp "ext/#{ext_name}/#{ext_name}.bundle", "lib/"
46
+ cp "ext/#{ext_name}/#{ext_name}.h.bundle", "lib/"
47
47
  end
48
48
 
49
- task :spec => "lib/#{ext_name}.bundle"
49
+ task :spec => "lib/#{ext_name}.h.bundle"
50
50
  end
51
51
 
52
52
  require 'rspec/core'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.5.1
@@ -16,6 +16,8 @@ VALUE createInstance() {
16
16
  return Data_Wrap_Struct(rb_cEventDispatcher, 0, cEventDispatcher_free, obj);
17
17
  }
18
18
 
19
+ // https://developer.apple.com/library/mac/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/doc/uid/TP40003550-CH3g-C016985
20
+ // XXX: support right button and center button
19
21
  CGEventType getEventTypeFromValue(VALUE value)
20
22
  {
21
23
  const char *typeStr;
@@ -29,6 +31,8 @@ CGEventType getEventTypeFromValue(VALUE value)
29
31
  type = kCGEventLeftMouseUp;
30
32
  } else if(strcmp(typeStr, "mouse_move") == 0) {
31
33
  type = kCGEventMouseMoved;
34
+ } else if(strcmp(typeStr, "mouse_drag") == 0) {
35
+ type = kCGEventLeftMouseDragged;
32
36
  } else {
33
37
  type = kCGEventNull;
34
38
  }
@@ -36,6 +40,27 @@ CGEventType getEventTypeFromValue(VALUE value)
36
40
  return type;
37
41
  }
38
42
 
43
+ CGScrollEventUnit getScrollEventUnitFromValue(VALUE value)
44
+ {
45
+ const char *unitStr;
46
+ CGScrollEventUnit unit;
47
+
48
+ unitStr = StringValuePtr(value);
49
+
50
+ if(strncmp(unitStr, "pix", 3) == 0) {
51
+ // accepts pixel, pixels, pix
52
+ unit = kCGScrollEventUnitPixel;
53
+ } else if(strncmp(unitStr, "line", 4) == 0) {
54
+ // accepts line, lines
55
+ unit = kCGScrollEventUnitLine;
56
+ } else {
57
+ rb_warn("Given unit `%s' is invalid. pixel or line is allowed.", unitStr);
58
+ unit = kCGScrollEventUnitPixel;
59
+ }
60
+
61
+ return unit;
62
+ }
63
+
39
64
  CGMouseButton getMouseButtonFromValue(VALUE value)
40
65
  {
41
66
  // http://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html
@@ -78,6 +103,29 @@ static VALUE cEventDispatcher_dispatchMouseEvent(int argc, VALUE *argv, VALUE se
78
103
  return Qnil;
79
104
  }
80
105
 
106
+ // http://stackoverflow.com/questions/6126226/how-to-create-an-nsevent-of-type-nsscrollwheel
107
+ // wheel_cnt: 1 - Y, 2 - Y-X, 3 - Y-X-Z
108
+ static VALUE cEventDispatcher_dispatchScrollWheelEvent(int argc, VALUE *argv, VALUE self)
109
+ {
110
+ VALUE unit, wheel_cnt, scroll_y, scroll_x, scroll_z;
111
+ CGEventRef event;
112
+
113
+ rb_scan_args(argc, argv, "5", &unit, &wheel_cnt, &scroll_y, &scroll_x, &scroll_z);
114
+
115
+ event = CGEventCreateScrollWheelEvent(
116
+ NULL,
117
+ getScrollEventUnitFromValue(rb_funcall(unit, rb_intern("to_s"), 0)),
118
+ NUM2INT(wheel_cnt),
119
+ NUM2INT(scroll_y),
120
+ NUM2INT(scroll_x),
121
+ NUM2INT(scroll_z));
122
+
123
+ CGEventPost(kCGHIDEventTap, event);
124
+ CFRelease(event);
125
+
126
+ return Qnil;
127
+ }
128
+
81
129
  // http://forums.macrumors.com/showthread.php?t=780577
82
130
  static VALUE cEventDispatcher_dispatchKeyboardEvent(int argc, VALUE *argv, VALUE self)
83
131
  {
@@ -105,5 +153,6 @@ void Init_event_dispatcher(void){
105
153
  rb_cEventDispatcher = rb_define_class_under(rb_cRobot, "EventDispatcher", rb_cObject);
106
154
  rb_define_singleton_method(rb_cEventDispatcher, "new", cEventDispatcher_new, -1);
107
155
  rb_define_method(rb_cEventDispatcher, "dispatchMouseEvent", cEventDispatcher_dispatchMouseEvent, -1);
156
+ rb_define_method(rb_cEventDispatcher, "dispatchScrollWheelEvent", cEventDispatcher_dispatchScrollWheelEvent, -1);
108
157
  rb_define_method(rb_cEventDispatcher, "dispatchKeyboardEvent", cEventDispatcher_dispatchKeyboardEvent, -1);
109
158
  }
@@ -5,7 +5,7 @@ end
5
5
  require "mkmf"
6
6
 
7
7
  # Name your extension
8
- extension_name = 'event_dispatcher'
8
+ extension_name = 'event_dispatcher.h'
9
9
 
10
10
  # Set your target name
11
11
  dir_config(extension_name)
data/ext/util/extconf.rb CHANGED
@@ -5,7 +5,7 @@ end
5
5
  require "mkmf"
6
6
 
7
7
  # Name your extension
8
- extension_name = 'util'
8
+ extension_name = 'util.h'
9
9
 
10
10
  # Set your target name
11
11
  dir_config(extension_name)
data/ext/util/util.m CHANGED
@@ -47,6 +47,21 @@ static VALUE mUtil_get_display_pixel_size(int argc, VALUE *argv, VALUE self)
47
47
  return result;
48
48
  }
49
49
 
50
+ static VALUE mUtil_get_mouse_current_location(int argc, VALUE *argv, VALUE self)
51
+ {
52
+ VALUE result;
53
+ CGEventRef event;
54
+
55
+ event = CGEventCreate(NULL);
56
+ CGPoint loc = CGEventGetLocation(event);
57
+
58
+ result = rb_ary_new();
59
+ rb_ary_push(result, INT2NUM(loc.x));
60
+ rb_ary_push(result, INT2NUM(loc.y));
61
+
62
+ return result;
63
+ }
64
+
50
65
  void Init_util(void){
51
66
  VALUE rb_mMac, rb_cRobot, rb_mUtil;
52
67
 
@@ -55,4 +70,5 @@ void Init_util(void){
55
70
  rb_mUtil = rb_define_module_under(rb_cRobot, "Util");
56
71
  rb_define_singleton_method(rb_mUtil, "get_pixel_color", mUtil_get_pixel_color, -1);
57
72
  rb_define_singleton_method(rb_mUtil, "get_display_pixel_size", mUtil_get_display_pixel_size, -1);
73
+ rb_define_singleton_method(rb_mUtil, "get_mouse_current_location", mUtil_get_mouse_current_location, -1);
58
74
  }
data/lib/mac-robot.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'event_dispatcher'
2
- require 'util'
1
+ require 'event_dispatcher.h'
2
+ require 'util.h'
3
3
 
4
4
  module Mac
5
5
  class Robot
@@ -17,6 +17,7 @@ module Mac
17
17
  def initialize
18
18
  @x = 0
19
19
  @y = 0
20
+
20
21
  @state = :mouse_up
21
22
  @dispatcher = EventDispatcher.new
22
23
  end
@@ -38,6 +39,18 @@ module Mac
38
39
  mouse_event(:left, :mouse_move)
39
40
  end
40
41
 
42
+ def mouse_drag(x, y)
43
+ @x = x
44
+ @y = y
45
+
46
+ mouse_event(:left, :mouse_drag)
47
+ end
48
+
49
+ def mouse_current_location
50
+ loc = Util.get_mouse_current_location
51
+ Struct.new(:x, :y).new(*loc)
52
+ end
53
+
41
54
  def key_press(keycode)
42
55
  keyboard_event(keycode, 1)
43
56
  end
@@ -46,10 +59,28 @@ module Mac
46
59
  keyboard_event(keycode, 0)
47
60
  end
48
61
 
62
+ def scroll_wheel_line(args = {})
63
+ scroll_wheel_event(:line, *scroll_count_extract(args))
64
+ end
65
+ alias scroll_wheel scroll_wheel_line
66
+
67
+ def scroll_wheel_pixel(args = {})
68
+ scroll_wheel_event(:pixel, *scroll_count_extract(args))
69
+ end
70
+
49
71
  def get_pixel_color(x, y)
50
72
  raise OutOfResolution if x < 0 || y < 0
51
73
  raise OutOfResolution if display_pixel_size.width < x || display_pixel_size.height < y
52
74
 
75
+ # workarownd for exeption occurs when x == display_pixel_size.width
76
+ #
77
+ # *** Assertion failure in -[NSBitmapImageRep initWithCGImage:], /SourceCache/AppKit/AppKit-1265/AppKit.subproj/NSBitmapImageRep.m:1286
78
+ # An uncaught exception was raised
79
+ # Invalid parameter not satisfying: cgImage != NULL
80
+ if display_pixel_size.width == x
81
+ x = x - 0.1
82
+ end
83
+
53
84
  color = Util.get_pixel_color(x, y)
54
85
  Struct.new(:red, :green, :blue, :alpha).new(*color)
55
86
  end
@@ -64,6 +95,32 @@ module Mac
64
95
  @dispatcher.dispatchMouseEvent(@x, @y, BUTTONS[button], type)
65
96
  end
66
97
 
98
+ def scroll_wheel_event(unit, scroll_y, scroll_x = 0, scroll_z = 0)
99
+ wheel_count = 3
100
+ @dispatcher.dispatchScrollWheelEvent(unit, wheel_count, scroll_y, scroll_x, scroll_z)
101
+ end
102
+
103
+ def scroll_count_extract(args = {})
104
+ # java.awt.Robot
105
+ # http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/Robot.html#mouseWheel%28int%29
106
+ scroll_x = 0 # x > 0 => right
107
+ scroll_y = 0 # y > 0 => down
108
+ scroll_z = 0 # z > 0 => towards
109
+
110
+ args.each do |key, value|
111
+ case key
112
+ when :x
113
+ scroll_x -= value
114
+ when :y
115
+ scroll_y -= value
116
+ when :z
117
+ scroll_z -= value
118
+ end
119
+ end
120
+
121
+ return [scroll_y, scroll_x, scroll_z]
122
+ end
123
+
67
124
  def keyboard_event(keycode, keydown)
68
125
  @dispatcher.dispatchKeyboardEvent(keycode, keydown)
69
126
  end
data/mac-robot.gemspec CHANGED
Binary file
@@ -9,12 +9,24 @@ describe Mac::Robot do
9
9
  describe 'mouse event' do
10
10
  it 'should simulate mouse event' do
11
11
  subject.mouse_move(20, 0)
12
+ sleep 0.2
12
13
  subject.mouse_press(:left)
13
- subject.mouse_move(20, 250)
14
+ sleep 0.2
15
+ subject.mouse_move(20, 200)
16
+ sleep 0.2
14
17
  subject.mouse_release(:left)
15
18
  end
16
19
  end
17
20
 
21
+ describe 'scroll wheel event' do
22
+ it 'should simulate scroll wheel event' do
23
+ subject.scroll_wheel_line(:y => 10) # down 10 lines
24
+ subject.scroll_wheel(:y => -10) # up 10 lines
25
+ subject.scroll_wheel_pixel(:x => 10, :y => -20, :z => 5)
26
+ subject.scroll_wheel_pixel(:y => 20, :x => -10, :z => -5)
27
+ end
28
+ end
29
+
18
30
  describe 'keyboard event' do
19
31
  it 'should simulate keyboard event' do
20
32
  [0x04, 0x0e, 0x25, 0x25, 0x1f].each do |keycode|
@@ -44,5 +56,23 @@ describe Mac::Robot do
44
56
  }.should raise_error(Mac::Robot::OutOfResolution)
45
57
  end
46
58
  end
59
+
60
+ it 'should get color from rightmost pixel' do
61
+ display_pixel_size = subject.display_pixel_size
62
+
63
+ color = subject.get_pixel_color(display_pixel_size.width, 0)
64
+ color.red.should be_a_kind_of(Float)
65
+ color.green.should be_a_kind_of(Float)
66
+ color.blue.should be_a_kind_of(Float)
67
+ color.alpha.should be_a_kind_of(Float)
68
+ end
69
+ end
70
+
71
+ describe 'current mouse location' do
72
+ it 'should have current mouse location' do
73
+ subject.mouse_move(20, 0)
74
+ subject.mouse_current_location.x.should eql(20)
75
+ subject.mouse_current_location.y.should eql(0)
76
+ end
47
77
  end
48
78
  end
metadata CHANGED
@@ -1,64 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mac-robot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
5
- prerelease:
4
+ version: 0.5.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - youpy
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-06-17 00:00:00.000000000 Z
11
+ date: 2021-04-15 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "<"
18
+ - !ruby/object:Gem::Version
19
+ version: '11.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "<"
25
+ - !ruby/object:Gem::Version
26
+ version: '11.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.5.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.5.1
14
41
  - !ruby/object:Gem::Dependency
15
42
  name: rspec
16
43
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
44
  requirements:
19
- - - ~>
45
+ - - "~>"
20
46
  - !ruby/object:Gem::Version
21
47
  version: 2.8.0
22
48
  type: :development
23
49
  prerelease: false
24
50
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
51
  requirements:
27
- - - ~>
52
+ - - "~>"
28
53
  - !ruby/object:Gem::Version
29
54
  version: 2.8.0
30
55
  - !ruby/object:Gem::Dependency
31
56
  name: bundler
32
57
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
58
  requirements:
35
- - - ! '>='
59
+ - - ">="
36
60
  - !ruby/object:Gem::Version
37
61
  version: '0'
38
62
  type: :development
39
63
  prerelease: false
40
64
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
65
  requirements:
43
- - - ! '>='
66
+ - - ">="
44
67
  - !ruby/object:Gem::Version
45
68
  version: '0'
46
69
  - !ruby/object:Gem::Dependency
47
70
  name: jeweler
48
71
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
72
  requirements:
51
- - - ~>
73
+ - - "~>"
52
74
  - !ruby/object:Gem::Version
53
- version: 1.8.3
75
+ version: 2.3.9
54
76
  type: :development
55
77
  prerelease: false
56
78
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
79
  requirements:
59
- - - ~>
80
+ - - "~>"
60
81
  - !ruby/object:Gem::Version
61
- version: 1.8.3
82
+ version: 2.3.9
62
83
  description: A Library to Automate User Interactions
63
84
  email: youpy@buycheapviagraonlinenow.com
64
85
  executables: []
@@ -69,8 +90,8 @@ extra_rdoc_files:
69
90
  - LICENSE.txt
70
91
  - README.rdoc
71
92
  files:
72
- - .document
73
- - .rspec
93
+ - ".document"
94
+ - ".rspec"
74
95
  - Gemfile
75
96
  - Gemfile.lock
76
97
  - LICENSE.txt
@@ -91,29 +112,24 @@ files:
91
112
  homepage: http://github.com/youpy/mac-robot
92
113
  licenses:
93
114
  - MIT
94
- post_install_message:
115
+ metadata: {}
116
+ post_install_message:
95
117
  rdoc_options: []
96
118
  require_paths:
97
119
  - lib
98
120
  required_ruby_version: !ruby/object:Gem::Requirement
99
- none: false
100
121
  requirements:
101
- - - ! '>='
122
+ - - ">="
102
123
  - !ruby/object:Gem::Version
103
124
  version: '0'
104
- segments:
105
- - 0
106
- hash: 3702793379613243156
107
125
  required_rubygems_version: !ruby/object:Gem::Requirement
108
- none: false
109
126
  requirements:
110
- - - ! '>='
127
+ - - ">="
111
128
  - !ruby/object:Gem::Version
112
129
  version: '0'
113
130
  requirements: []
114
- rubyforge_project:
115
- rubygems_version: 1.8.24
116
- signing_key:
117
- specification_version: 3
131
+ rubygems_version: 3.1.6
132
+ signing_key:
133
+ specification_version: 4
118
134
  summary: A Library to Automate User Interactions
119
135
  test_files: []