macos 0.1.1 → 0.1.3
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.
- checksums.yaml +4 -4
- data/Gemfile +9 -6
- data/README.md +30 -4
- data/bin/demo +14 -0
- data/lib/macos/cg/event_tap_location.rb +12 -0
- data/lib/macos/cg/event_type.rb +22 -0
- data/lib/macos/cg/mouse_button.rb +12 -0
- data/lib/macos/cg/point.rb +12 -0
- data/lib/macos/cg/rect.rb +12 -0
- data/lib/macos/cg/size.rb +12 -0
- data/lib/macos/display.rb +39 -0
- data/lib/macos/keyboard.rb +13 -0
- data/lib/macos/library.rb +21 -0
- data/lib/macos/mouse.rb +99 -0
- data/lib/macos/version.rb +2 -2
- data/lib/macos.rb +30 -5
- metadata +44 -8
- data/lib/macos/screen.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5f7eea4e2dd2200b9cf31edba5eeafb649c61f04c3ce97977e3b2b9eb7ac9ab
|
4
|
+
data.tar.gz: 3a57005b465e9751bf0390fc077a916be95665b8e9b67dc3d2e550063bbd3d57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5bbc37912e6e9e726c4d0f8e0b5315d2a5b1a79ad3d68e4399d575127e88b20b8adb4a1c7081ebf124a0fdb5cab274138882cfdcc6e0b49fa2dc87589dd8663
|
7
|
+
data.tar.gz: 2324a3f60635e949c2d90ab30705a91047edbf78b4dbe7b12c8684783d54a8282c74e33fcae98f37be8cbe825b7fcd15b85046872239dbc3005dee8d9c3b1cdc
|
data/Gemfile
CHANGED
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
# Specify your gem's dependencies in macos.gemspec
|
6
5
|
gemspec
|
7
6
|
|
8
|
-
gem "rake"
|
9
|
-
|
10
|
-
gem "
|
11
|
-
|
12
|
-
gem "rubocop"
|
7
|
+
gem "rake"
|
8
|
+
gem "rspec"
|
9
|
+
gem "rspec_junit_formatter"
|
10
|
+
gem "rubocop"
|
11
|
+
gem "rubocop-basic"
|
12
|
+
gem "rubocop-rake"
|
13
|
+
gem "rubocop-rspec"
|
14
|
+
gem "simplecov"
|
15
|
+
gem "yard"
|
data/README.md
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
# MacOS
|
1
|
+
# MacOS
|
2
|
+
|
3
|
+
[](https://github.com/ksylvest/macos/blob/main/LICENSE)
|
4
|
+
[](https://rubygems.org/gems/macos)
|
5
|
+
[](https://github.com/ksylvest/macos)
|
6
|
+
[](https://macos.ksylvest.com)
|
7
|
+
[](https://circleci.com/gh/ksylvest/macos)
|
2
8
|
|
3
9
|
A library for interacting with your Mac through ruby.
|
4
10
|
|
@@ -10,13 +16,33 @@ gem install macos
|
|
10
16
|
|
11
17
|
## Usage
|
12
18
|
|
13
|
-
###
|
19
|
+
### Mouse
|
14
20
|
|
15
21
|
```ruby
|
16
22
|
require 'macos'
|
17
23
|
|
18
|
-
|
19
|
-
|
24
|
+
mouse = MacOS.mouse
|
25
|
+
|
26
|
+
mouse.move(x: 0, y: 0)
|
27
|
+
position = mouse.position
|
28
|
+
puts "#{position.x},#{position.y}"
|
29
|
+
|
30
|
+
mouse.move(x: 2, y: 3)
|
31
|
+
position = mouse.position
|
32
|
+
puts "#{position.x},#{position.y}"
|
33
|
+
```
|
34
|
+
|
35
|
+
### Display
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require 'macos'
|
39
|
+
|
40
|
+
display = MacOS.display
|
41
|
+
bounds = display.bounds
|
42
|
+
|
43
|
+
puts "#{bounds.width}×#{bounds.height}"
|
44
|
+
|
45
|
+
display.capture do |tempfile|
|
20
46
|
# ...
|
21
47
|
end
|
22
48
|
```
|
data/bin/demo
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MacOS
|
4
|
+
module CG
|
5
|
+
# https://developer.apple.com/documentation/coregraphics/cgeventtaplocation
|
6
|
+
module EventTapLocation
|
7
|
+
HID_EVENT_TAP = 0 # https://developer.apple.com/documentation/coregraphics/cgeventtaplocation/cghideventtap
|
8
|
+
SESSSION_EVENT_TAP = 1 # https://developer.apple.com/documentation/coregraphics/cgeventtaplocation/sessioneventtap
|
9
|
+
ANNOTATED_SESSION_EVENT_TAP = 2 # https://developer.apple.com/documentation/coregraphics/cgeventtaplocation/annotatedsessioneventtap
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MacOS
|
4
|
+
module CG
|
5
|
+
# https://developer.apple.com/documentation/coregraphics/cgeventtype
|
6
|
+
module EventType
|
7
|
+
NULL = 0 # https://developer.apple.com/documentation/coregraphics/cgeventtype/null
|
8
|
+
LEFT_MOUSE_DOWN = 1 # https://developer.apple.com/documentation/coregraphics/cgeventtype/leftmousedown
|
9
|
+
LEFT_MOUSE_UP = 2 # https://developer.apple.com/documentation/coregraphics/cgeventtype/leftmouseup
|
10
|
+
RIGHT_MOUSE_DOWN = 3 # https://developer.apple.com/documentation/coregraphics/cgeventtype/rightmousedown
|
11
|
+
RIGHT_MOUSE_UP = 4 # https://developer.apple.com/documentation/coregraphics/cgeventtype/rightmouseup
|
12
|
+
MOUSE_MOVED = 5 # https://developer.apple.com/documentation/coregraphics/cgeventtype/mousemoved
|
13
|
+
LEFT_MOUSE_DRAGGED = 6 # https://developer.apple.com/documentation/coregraphics/cgeventtype/leftmousedragged
|
14
|
+
RIGHT_MOUSE_DRAGGED = 7 # https://developer.apple.com/documentation/coregraphics/cgeventtype/rightmousedragged
|
15
|
+
KEY_DOWN = 10 # https://developer.apple.com/documentation/coregraphics/cgeventtype/keydown
|
16
|
+
KEY_UP = 11 # https://developer.apple.com/documentation/coregraphics/cgeventtype/keyup
|
17
|
+
OTHER_MOUSE_DOWN = 25 # https://developer.apple.com/documentation/coregraphics/cgeventtype/othermousedown
|
18
|
+
OTHER_MOUSE_UP = 26 # https://developer.apple.com/documentation/coregraphics/cgeventtype/othermouseup
|
19
|
+
OTHER_MOUSE_DRAGGED = 27 # https://developer.apple.com/documentation/coregraphics/cgeventtype/othermousedragged
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MacOS
|
4
|
+
module CG
|
5
|
+
# https://developer.apple.com/documentation/coregraphics/cgmousebutton
|
6
|
+
module MouseButton
|
7
|
+
LEFT = 0 # https://developer.apple.com/documentation/coregraphics/cgmousebutton/left
|
8
|
+
RIGHT = 1 # https://developer.apple.com/documentation/coregraphics/cgmousebutton/right
|
9
|
+
CENTER = 2 # https://developer.apple.com/documentation/coregraphics/cgmousebutton/center
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MacOS
|
4
|
+
# Simulates a macOS display.
|
5
|
+
class Display
|
6
|
+
Size = Struct.new(:width, :height)
|
7
|
+
|
8
|
+
def self.main
|
9
|
+
id = Library.CGMainDisplayID
|
10
|
+
new(id:)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @param id [Integer
|
14
|
+
def initialize(id:)
|
15
|
+
@id = id
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Size]
|
19
|
+
def bounds
|
20
|
+
bounds = Library.CGDisplayBounds(@id)
|
21
|
+
|
22
|
+
width = Integer(bounds[:size][:width])
|
23
|
+
height = Integer(bounds[:size][:height])
|
24
|
+
|
25
|
+
Size.new(width, height)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @yield [tempfile]
|
29
|
+
# @yieldparam tempfile [Tempfile]
|
30
|
+
def capture
|
31
|
+
tempfile = Tempfile.new(["screenshot", ".png"])
|
32
|
+
system("screencapture -o -x #{tempfile.path}")
|
33
|
+
yield tempfile
|
34
|
+
ensure
|
35
|
+
tempfile.close
|
36
|
+
tempfile.unlink
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ffi"
|
4
|
+
|
5
|
+
module MacOS
|
6
|
+
# https://developer.apple.com/documentation/coregraphics
|
7
|
+
module Library
|
8
|
+
extend ::FFI::Library
|
9
|
+
ffi_lib "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics"
|
10
|
+
|
11
|
+
attach_function :CGEventCreate, %i[pointer], :pointer
|
12
|
+
attach_function :CGEventGetLocation, %i[pointer], CG::Point.by_value
|
13
|
+
attach_function :CFRelease, %i[pointer], :void
|
14
|
+
attach_function :CGEventCreateMouseEvent, [:pointer, :uint32, CG::Point.by_value, :uint32], :pointer
|
15
|
+
attach_function :CGEventPost, %i[uint32 pointer], :void
|
16
|
+
attach_function :CGWarpMouseCursorPosition, [CG::Point.by_value], :pointer
|
17
|
+
attach_function :CGEventCreateKeyboardEvent, %i[pointer uint16 bool bool], :pointer
|
18
|
+
attach_function :CGMainDisplayID, [], :uint32
|
19
|
+
attach_function :CGDisplayBounds, [:uint32], CG::Rect.by_value
|
20
|
+
end
|
21
|
+
end
|
data/lib/macos/mouse.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MacOS
|
4
|
+
# Simulates a macOS mouse.
|
5
|
+
class Mouse
|
6
|
+
Position = Data.define(:x, :y)
|
7
|
+
|
8
|
+
# @return [Position]
|
9
|
+
def position
|
10
|
+
event = Library.CGEventCreate(nil)
|
11
|
+
position = Library.CGEventGetLocation(event)
|
12
|
+
Library.CFRelease(event)
|
13
|
+
|
14
|
+
x = position[:x]
|
15
|
+
y = position[:y]
|
16
|
+
|
17
|
+
Position.new(x, y)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param type [Integer] e.g. `MacOS::CG::EventType::MOUSE_MOVED`
|
21
|
+
# @param x [Float]
|
22
|
+
# @param y [Float]
|
23
|
+
# @param button [Integer] e.g. `MacOS::CG::MouseButton::LEFT` / `MacOS::CG::MouseButton::RIGHT` / etc.
|
24
|
+
def trigger(type:, x:, y:, button: 0)
|
25
|
+
position = CG::Point.new
|
26
|
+
position[:x] = x
|
27
|
+
position[:y] = y
|
28
|
+
event = Library.CGEventCreateMouseEvent(nil, type, position, button)
|
29
|
+
Library.CGEventPost(CG::EventTapLocation::HID_EVENT_TAP, event)
|
30
|
+
Library.CFRelease(event)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param x [Float]
|
34
|
+
# @param y [Float]
|
35
|
+
def move(x:, y:)
|
36
|
+
position = CG::Point.new
|
37
|
+
position[:x] = x
|
38
|
+
position[:y] = y
|
39
|
+
Library.CGWarpMouseCursorPosition(position)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param x [Float]
|
43
|
+
# @param y [Float]
|
44
|
+
def left_down(x:, y:)
|
45
|
+
trigger(type: CG::EventType::LEFT_MOUSE_DOWN, x:, y:, button: CG::MouseButton::LEFT)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param x [Float]
|
49
|
+
# @param y [Float]
|
50
|
+
def left_up(x:, y:)
|
51
|
+
trigger(type: CG::EventType::LEFT_MOUSE_UP, x:, y:, button: CG::MouseButton::LEFT)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param x [Float]
|
55
|
+
# @param y [Float]
|
56
|
+
def left_click(x:, y:)
|
57
|
+
left_down(x:, y:)
|
58
|
+
left_up(x:, y:)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param x [Float]
|
62
|
+
# @param y [Float]
|
63
|
+
def right_down(x:, y:)
|
64
|
+
trigger(type: CG::EventType::RIGHT_MOUSE_DOWN, x:, y:, button: CG::MouseButton::RIGHT)
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param x [Float]
|
68
|
+
# @param y [Float]
|
69
|
+
def right_up(x:, y:)
|
70
|
+
trigger(type: CG::EventType::RIGHT_MOUSE_UP, x:, y:, button: CG::MouseButton::RIGHT)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @param x [Float]
|
74
|
+
# @param y [Float]
|
75
|
+
def right_click(x:, y:)
|
76
|
+
right_down(x:, y:)
|
77
|
+
right_up(x:, y:)
|
78
|
+
end
|
79
|
+
|
80
|
+
# @param x [Float]
|
81
|
+
# @param y [Float]
|
82
|
+
def middle_down(x:, y:)
|
83
|
+
trigger(type: CG::EventType::OTHER_MOUSE_DOWN, x:, y:, button: CG::MouseButton::CENTER)
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param x [Float]
|
87
|
+
# @param y [Float]
|
88
|
+
def middle_up(x:, y:)
|
89
|
+
trigger(type: CG::EventType::OTHER_MOUSE_UP, x:, y:, button: CG::MouseButton::CENTER)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param x [Float]
|
93
|
+
# @param y [Float]
|
94
|
+
def middle_click(x:, y:)
|
95
|
+
middle_down(x:, y:)
|
96
|
+
middle_up(x:, y:)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/macos/version.rb
CHANGED
data/lib/macos.rb
CHANGED
@@ -1,16 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "fiddle"
|
4
|
+
require "zeitwerk"
|
4
5
|
|
5
6
|
loader = Zeitwerk::Loader.for_gem
|
6
|
-
loader.inflector.inflect
|
7
|
+
loader.inflector.inflect "cg" => "CG"
|
8
|
+
loader.inflector.inflect "macos" => "MacOS"
|
7
9
|
loader.setup
|
8
10
|
|
11
|
+
# Interacts with macOS.
|
9
12
|
module MacOS
|
10
13
|
class Error < StandardError; end
|
11
14
|
|
12
|
-
# @
|
13
|
-
|
14
|
-
|
15
|
+
# @example
|
16
|
+
# MacOS.keyboard.type('Hello, World!')
|
17
|
+
# MacOS.keyboard.key_down('a')
|
18
|
+
# MacOS.keyboard.key_up('a')
|
19
|
+
#
|
20
|
+
# @return [MacOS::Keyboard]
|
21
|
+
def self.keyboard
|
22
|
+
Keyboard.new
|
23
|
+
end
|
24
|
+
|
25
|
+
# @example
|
26
|
+
# mouse = MacOS.mouse
|
27
|
+
# mouse.move(x: 4, y: 8)
|
28
|
+
# position = mouse.position
|
29
|
+
# mouse.left_click(x: position.x, y: position.y)
|
30
|
+
# mouse.right_click(x: position.x, y: position.y)
|
31
|
+
#
|
32
|
+
# @return [MacOS::Mouse]
|
33
|
+
def self.mouse
|
34
|
+
Mouse.new
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [MacOS::Display]
|
38
|
+
def self.display
|
39
|
+
Display.main
|
15
40
|
end
|
16
41
|
end
|
metadata
CHANGED
@@ -1,15 +1,42 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: macos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Sylvestre
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: ffi
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: fiddle
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
13
40
|
- !ruby/object:Gem::Dependency
|
14
41
|
name: zeitwerk
|
15
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,9 +61,19 @@ files:
|
|
34
61
|
- Gemfile
|
35
62
|
- README.md
|
36
63
|
- bin/console
|
64
|
+
- bin/demo
|
37
65
|
- bin/setup
|
38
66
|
- lib/macos.rb
|
39
|
-
- lib/macos/
|
67
|
+
- lib/macos/cg/event_tap_location.rb
|
68
|
+
- lib/macos/cg/event_type.rb
|
69
|
+
- lib/macos/cg/mouse_button.rb
|
70
|
+
- lib/macos/cg/point.rb
|
71
|
+
- lib/macos/cg/rect.rb
|
72
|
+
- lib/macos/cg/size.rb
|
73
|
+
- lib/macos/display.rb
|
74
|
+
- lib/macos/keyboard.rb
|
75
|
+
- lib/macos/library.rb
|
76
|
+
- lib/macos/mouse.rb
|
40
77
|
- lib/macos/version.rb
|
41
78
|
homepage: https://github.com/ksylvest/macos
|
42
79
|
licenses:
|
@@ -44,8 +81,8 @@ licenses:
|
|
44
81
|
metadata:
|
45
82
|
homepage_uri: https://github.com/ksylvest/macos
|
46
83
|
source_code_uri: https://github.com/ksylvest/macos
|
47
|
-
changelog_uri: https://github.com/ksylvest/macos
|
48
|
-
|
84
|
+
changelog_uri: https://github.com/ksylvest/macos/releases
|
85
|
+
rubygems_mfa_required: 'true'
|
49
86
|
rdoc_options: []
|
50
87
|
require_paths:
|
51
88
|
- lib
|
@@ -60,8 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
97
|
- !ruby/object:Gem::Version
|
61
98
|
version: '0'
|
62
99
|
requirements: []
|
63
|
-
rubygems_version: 3.
|
64
|
-
signing_key:
|
100
|
+
rubygems_version: 3.6.7
|
65
101
|
specification_version: 4
|
66
102
|
summary: An interface with macOS.
|
67
103
|
test_files: []
|
data/lib/macos/screen.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
module MacOS
|
2
|
-
module Screen
|
3
|
-
# @yield [tempfile]
|
4
|
-
# @yieldparam tempfile [Tempfile]
|
5
|
-
def capture
|
6
|
-
tempfile = Tempfile.new(['screenshot', '.png'])
|
7
|
-
system("screencapture -o -x #{tempfile.path}")
|
8
|
-
yield tempfile
|
9
|
-
ensure
|
10
|
-
tempfile.close
|
11
|
-
tempfile.unlink
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|