macos 0.1.4 → 0.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a108d88ec5b706a9bc9839ded07b08849a2a232cb74ec9f9ec9e50f23f84734d
4
- data.tar.gz: f55c8d91de3341d0d709a59cd921c96f4690dce88a0dd7568af617e084682c4e
3
+ metadata.gz: bf5821a0d9cb6f49c609d0f04404516616827d6638cfbdeb1f0f8aff0d971511
4
+ data.tar.gz: cb023c3393ed3cab754e83d25d6499c2d14ff9ba580a4338e785e0dbaf74a6d9
5
5
  SHA512:
6
- metadata.gz: 00aea0fa47b5dc3363fd3be123288ab12277429d0af9cd7db45066a9bc431421a3c966ab3d04401b6aa510a641378b1b58107577952a763b0b8f0e218956393f
7
- data.tar.gz: 9530f04a0e57b4b22b78c46266ea9079f4e138c6238f8ac503764e72f106f281fd6ac7d9ccb1bc91f18cd81ee59fd4f2126e50e886bbbec75c52269469280970
6
+ metadata.gz: 8df71d32c14d10495fbdb6fda286d0a61149125513dda133b5c736968a2dcea6ec4e76362f7284741704394f7eec7e98ffa6b8aac146906cfadb3741ab4fdaf6
7
+ data.tar.gz: 43dcd007db945422d82bd5e66e489becb2171c309420f9f78da91d17b0f88d912e0722bf040844cf4f6a3440686b6f7caee4990397f7b6744d9efc21afa6a1a9
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
+ gem "irb"
7
8
  gem "rake"
8
9
  gem "rspec"
9
10
  gem "rspec_junit_formatter"
data/lib/macos/display.rb CHANGED
@@ -1,23 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "tempfile"
4
+
3
5
  module MacOS
4
6
  # Simulates a macOS display.
5
7
  class Display
6
8
  Size = Struct.new(:width, :height)
7
9
 
8
10
  def self.main
9
- id = Library.CGMainDisplayID
11
+ id = Library::CoreGraphics.CGMainDisplayID
10
12
  new(id:)
11
13
  end
12
14
 
13
15
  # @param id [Integer
14
- def initialize(id:)
16
+ def initialize(id: 0)
15
17
  @id = id
16
18
  end
17
19
 
18
20
  # @return [Size]
19
21
  def bounds
20
- bounds = Library.CGDisplayBounds(@id)
22
+ bounds = Library::CoreGraphics.CGDisplayBounds(@id)
21
23
 
22
24
  width = Integer(bounds[:size][:width])
23
25
  height = Integer(bounds[:size][:height])
@@ -29,7 +31,23 @@ module MacOS
29
31
  # @yieldparam tempfile [Tempfile]
30
32
  def screenshot
31
33
  tempfile = Tempfile.new(["screenshot", ".png"])
32
- system("screencapture -o -x #{tempfile.path}")
34
+ image = Library::CoreGraphics.CGDisplayCreateImage(@id)
35
+
36
+ encoding = Library::CoreFoundation::ENCODING_UTF8
37
+ path = Library::CoreFoundation.CFStringCreateWithCString(nil, tempfile.path, encoding)
38
+ url = Library::CoreFoundation.CFURLCreateWithFileSystemPath(nil, path, 0, false)
39
+ uti = Library::CoreFoundation.CFStringCreateWithCString(nil, "public.png", encoding)
40
+
41
+ dest = Library::ImageIO.CGImageDestinationCreateWithURL(url, uti, 1, nil)
42
+ Library::ImageIO.CGImageDestinationAddImage(dest, image, nil)
43
+ Library::ImageIO.CGImageDestinationFinalize(dest)
44
+
45
+ Library::CoreGraphics.CFRelease(image)
46
+ Library::CoreFoundation.CFRelease(path)
47
+ Library::CoreFoundation.CFRelease(url)
48
+ Library::CoreFoundation.CFRelease(uti)
49
+ Library::CoreFoundation.CFRelease(dest)
50
+
33
51
  yield tempfile
34
52
  ensure
35
53
  tempfile.close
@@ -3,11 +3,73 @@
3
3
  module MacOS
4
4
  # Simulates a macOS keyboard.
5
5
  class Keyboard
6
+ MILISECOND = 0.001
7
+
8
+ # @param text [String]
6
9
  def type(text)
7
10
  text.chars.each do |character|
8
- key_down(character)
9
- key_up(character)
11
+ mask = 0
12
+ mask |= Library::CoreGraphics::EventFlags::MASK_SHIFT if Library::CoreGraphics::KeyCode.shifted?(character)
13
+ key(character, mask:)
14
+ end
15
+ end
16
+
17
+ # @example
18
+ # keyboard.keys("a")
19
+ # keyboard.keys("b")
20
+ # keyboard.keys("c")
21
+ # keyboard.keys("command+shift+s")
22
+ # keyboard.keys("comand+shift+tab")
23
+ #
24
+ # @param text [String] e.g. "a", "b", "command+shift+s" or ""
25
+ def keys(text)
26
+ mask = 0
27
+ options = text.split("+")
28
+ key = options.pop
29
+
30
+ options.each do |option|
31
+ mask |= Library::CoreGraphics::EventFlags.find(option)
10
32
  end
33
+
34
+ key(key, mask:)
35
+ end
36
+
37
+ # @example
38
+ # keyboard.key("s", mask: Library::CoreGraphics::EventFlags::MASK_COMMAND)
39
+ #
40
+ # @param character [String] a character to be pressed then released
41
+ # @param mask [Integer] a bitmask of event flags (e.g. Library::CoreGraphics::EventFlags::MASK_SHIFT)
42
+ def key(character, mask: 0)
43
+ key_down(character, mask:)
44
+ key_up(character, mask:)
45
+ end
46
+
47
+ # @example
48
+ # keyboard.key_down("c", mask: Library::CoreGraphics::EventFlags::MASK_COMMAND)
49
+ #
50
+ # @param character [String] a character to be typed
51
+ # @param mask [Integer] a bitmask of event flags (e.g. Library::CoreGraphics::EventFlags::MASK_SHIFT)
52
+ def key_down(character, mask: 0)
53
+ code = Library::CoreGraphics::KeyCode.find(character)
54
+ event = Library::CoreGraphics.CGEventCreateKeyboardEvent(nil, code, true)
55
+ Library::CoreGraphics.CGEventSetFlags(event, mask) unless mask.zero?
56
+ Library::CoreGraphics.CGEventPost(Library::CoreGraphics::EventTapLocation::HID_EVENT_TAP, event)
57
+ Library::CoreGraphics.CFRelease(event)
58
+ sleep(MILISECOND)
59
+ end
60
+
61
+ # @example
62
+ # keyboard.key_up("c", mask: Library::CoreGraphics::EventFlags::MASK_COMMAND)
63
+ #
64
+ # @param character [String] a character to be released
65
+ # @param mask [Integer] a bitmask of event flags (e.g. Library::CoreGraphics::EventFlags::MASK_SHIFT)
66
+ def key_up(character, mask: 0)
67
+ code = Library::CoreGraphics::KeyCode.find(character)
68
+ event = Library::CoreGraphics.CGEventCreateKeyboardEvent(nil, code, false)
69
+ Library::CoreGraphics.CGEventSetFlags(event, mask) unless mask.zero?
70
+ Library::CoreGraphics.CGEventPost(Library::CoreGraphics::EventTapLocation::HID_EVENT_TAP, event)
71
+ Library::CoreGraphics.CFRelease(event)
72
+ sleep(MILISECOND)
11
73
  end
12
74
  end
13
75
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi"
4
+
5
+ module MacOS
6
+ module Library
7
+ # https://developer.apple.com/documentation/corefoundation
8
+ module CoreFoundation
9
+ extend ::FFI::Library
10
+ ENCODING_UTF8 = 0x08000100
11
+
12
+ ffi_lib "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"
13
+
14
+ typedef :pointer, :CFStringRef
15
+ typedef :long, :CFIndex
16
+ typedef :CFIndex, :CFURLPathStyle
17
+
18
+ attach_function :CFStringCreateWithCString, %i[pointer string int], :pointer
19
+ attach_function :CFURLCreateWithFileSystemPath, %i[pointer CFStringRef CFURLPathStyle bool], :pointer
20
+ attach_function :CFRelease, %i[pointer], :void
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MacOS
4
+ module Library
5
+ module CoreGraphics
6
+ # https://developer.apple.com/documentation/coregraphics/cgeventflags
7
+ module EventFlags
8
+ MASK_SHIFT = 0x00020000 # https://developer.apple.com/documentation/coregraphics/cgeventflags/maskshift
9
+ MASK_CONTROL = 0x00040000 # https://developer.apple.com/documentation/coregraphics/cgeventflags/maskcontrol
10
+ MASK_ALTERNATE = 0x00080000 # https://developer.apple.com/documentation/coregraphics/cgeventflags/maskalternate
11
+ MASK_COMMAND = 0x00100000 # https://developer.apple.com/documentation/coregraphics/cgeventflags/maskcommand
12
+ MASK_HELP = 0x00400000 # https://developer.apple.com/documentation/coregraphics/cgeventflags/maskhelp
13
+
14
+ MAPPING = {
15
+ "shift" => MASK_SHIFT,
16
+ "control" => MASK_CONTROL,
17
+ "ctrl" => MASK_CONTROL,
18
+ "option" => MASK_ALTERNATE,
19
+ "opt" => MASK_ALTERNATE,
20
+ "alt" => MASK_ALTERNATE,
21
+ "command" => MASK_COMMAND,
22
+ "cmd" => MASK_COMMAND,
23
+ "help" => MASK_HELP,
24
+ }.freeze
25
+
26
+ # @param modifier [String]
27
+ #
28
+ # @raise [ArgumentError]
29
+ #
30
+ # @return [Integer]
31
+ def self.find(modifier)
32
+ MAPPING[modifier] || raise(ArgumentError, "unsupported modifier=#{modifier.inspect}")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MacOS
4
+ module Library
5
+ module CoreGraphics
6
+ # https://developer.apple.com/documentation/coregraphics/cgeventtaplocation
7
+ module EventTapLocation
8
+ HID_EVENT_TAP = 0 # https://developer.apple.com/documentation/coregraphics/cgeventtaplocation/cghideventtap
9
+ SESSSION_EVENT_TAP = 1 # https://developer.apple.com/documentation/coregraphics/cgeventtaplocation/sessioneventtap
10
+ ANNOTATED_SESSION_EVENT_TAP = 2 # https://developer.apple.com/documentation/coregraphics/cgeventtaplocation/annotatedsessioneventtap
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MacOS
4
+ module Library
5
+ module CoreGraphics
6
+ # https://developer.apple.com/documentation/coregraphics/cgeventtype
7
+ module EventType
8
+ NULL = 0 # https://developer.apple.com/documentation/coregraphics/cgeventtype/null
9
+ LEFT_MOUSE_DOWN = 1 # https://developer.apple.com/documentation/coregraphics/cgeventtype/leftmousedown
10
+ LEFT_MOUSE_UP = 2 # https://developer.apple.com/documentation/coregraphics/cgeventtype/leftmouseup
11
+ RIGHT_MOUSE_DOWN = 3 # https://developer.apple.com/documentation/coregraphics/cgeventtype/rightmousedown
12
+ RIGHT_MOUSE_UP = 4 # https://developer.apple.com/documentation/coregraphics/cgeventtype/rightmouseup
13
+ MOUSE_MOVED = 5 # https://developer.apple.com/documentation/coregraphics/cgeventtype/mousemoved
14
+ LEFT_MOUSE_DRAGGED = 6 # https://developer.apple.com/documentation/coregraphics/cgeventtype/leftmousedragged
15
+ RIGHT_MOUSE_DRAGGED = 7 # https://developer.apple.com/documentation/coregraphics/cgeventtype/rightmousedragged
16
+ KEY_DOWN = 10 # https://developer.apple.com/documentation/coregraphics/cgeventtype/keydown
17
+ KEY_UP = 11 # https://developer.apple.com/documentation/coregraphics/cgeventtype/keyup
18
+ OTHER_MOUSE_DOWN = 25 # https://developer.apple.com/documentation/coregraphics/cgeventtype/othermousedown
19
+ OTHER_MOUSE_UP = 26 # https://developer.apple.com/documentation/coregraphics/cgeventtype/othermouseup
20
+ OTHER_MOUSE_DRAGGED = 27 # https://developer.apple.com/documentation/coregraphics/cgeventtype/othermousedragged
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MacOS
4
+ module Library
5
+ module CoreGraphics
6
+ # https://developer.apple.com/documentation/coregraphics/cgkeycode
7
+ module KeyCode
8
+ SHIFTED = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+{}|:\"<>?~`"
9
+
10
+ KEY_CODE_A = 0
11
+ KEY_CODE_B = 11
12
+ KEY_CODE_C = 8
13
+ KEY_CODE_D = 2
14
+ KEY_CODE_E = 14
15
+ KEY_CODE_F = 3
16
+ KEY_CODE_G = 5
17
+ KEY_CODE_H = 4
18
+ KEY_CODE_I = 34
19
+ KEY_CODE_J = 38
20
+ KEY_CODE_K = 40
21
+ KEY_CODE_L = 37
22
+ KEY_CODE_M = 46
23
+ KEY_CODE_N = 45
24
+ KEY_CODE_O = 31
25
+ KEY_CODE_P = 35
26
+ KEY_CODE_Q = 12
27
+ KEY_CODE_R = 15
28
+ KEY_CODE_S = 1
29
+ KEY_CODE_T = 17
30
+ KEY_CODE_U = 32
31
+ KEY_CODE_V = 9
32
+ KEY_CODE_W = 13
33
+ KEY_CODE_X = 7
34
+ KEY_CODE_Y = 16
35
+ KEY_CODE_Z = 6
36
+
37
+ KEY_CODE_0 = 29
38
+ KEY_CODE_1 = 18
39
+ KEY_CODE_2 = 19
40
+ KEY_CODE_3 = 20
41
+ KEY_CODE_4 = 21
42
+ KEY_CODE_5 = 23
43
+ KEY_CODE_6 = 22
44
+ KEY_CODE_7 = 26
45
+ KEY_CODE_8 = 28
46
+ KEY_CODE_9 = 25
47
+
48
+ KEY_CODE_TILDE = 30
49
+ KEY_CODE_BACKTICK = 30
50
+
51
+ KEY_CODE_EXCLAMATION = 18
52
+ KEY_CODE_AMPERSAT = 19
53
+ KEY_CODE_HASH = 20
54
+ KEY_CODE_DOLLAR = 21
55
+ KEY_CODE_PERCENT = 23
56
+ KEY_CODE_CARET = 22
57
+ KEY_CODE_AMPERSAND = 26
58
+ KEY_CODE_ASTERISK = 28
59
+ KEY_CODE_LPARENTHESIS = 25
60
+ KEY_CODE_RPARENTHESIS = 29
61
+ KEY_CODE_MINUS = 27
62
+ KEY_CODE_UNDERSCORE = 27
63
+ KEY_CODE_EQUAL = 24
64
+ KEY_CODE_PLUS = 24
65
+
66
+ KEY_CODE_LBRACKET = 33
67
+ KEY_CODE_RBRACKET = 30
68
+ KEY_CODE_BACKSLASH = 42
69
+ KEY_CODE_SEMICOLON = 41
70
+ KEY_CODE_LBRACE = 33
71
+ KEY_CODE_RBRACE = 30
72
+ KEY_CODE_PIPE = 42
73
+ KEY_CODE_COLON = 41
74
+ KEY_CODE_QUOTE = 39
75
+ KEY_CODE_QUOTATION = 39
76
+ KEY_CODE_COMMA = 43
77
+ KEY_CODE_PERIOD = 47
78
+ KEY_CODE_SLASH = 44
79
+ KEY_CODE_LT = 43
80
+ KEY_CODE_GT = 47
81
+ KEY_CODE_TAB = 48
82
+ KEY_CODE_ESCAPE = 53
83
+ KEY_CODE_RETURN = 36
84
+ KEY_CODE_DELETE = 51
85
+ KEY_CODE_SPACE = 49
86
+ KEY_CODE_LEFT = 123
87
+ KEY_CODE_RIGHT = 124
88
+ KEY_CODE_DOWN = 125
89
+ KEY_CODE_UP = 126
90
+ KEY_CODE_SHIFT = 56
91
+ KEY_CODE_CONTROL = 59
92
+ KEY_CODE_OPTION = 58
93
+ KEY_CODE_COMMAND = 55
94
+ KEY_CODE_FUNCTION = 63
95
+
96
+ MAPPING = {
97
+ "a" => KEY_CODE_A,
98
+ "A" => KEY_CODE_A,
99
+ "b" => KEY_CODE_B,
100
+ "B" => KEY_CODE_B,
101
+ "c" => KEY_CODE_C,
102
+ "C" => KEY_CODE_C,
103
+ "d" => KEY_CODE_D,
104
+ "D" => KEY_CODE_D,
105
+ "e" => KEY_CODE_E,
106
+ "E" => KEY_CODE_E,
107
+ "f" => KEY_CODE_F,
108
+ "F" => KEY_CODE_F,
109
+ "g" => KEY_CODE_G,
110
+ "G" => KEY_CODE_G,
111
+ "h" => KEY_CODE_H,
112
+ "H" => KEY_CODE_H,
113
+ "i" => KEY_CODE_I,
114
+ "I" => KEY_CODE_I,
115
+ "j" => KEY_CODE_J,
116
+ "J" => KEY_CODE_J,
117
+ "k" => KEY_CODE_K,
118
+ "K" => KEY_CODE_K,
119
+ "l" => KEY_CODE_L,
120
+ "L" => KEY_CODE_L,
121
+ "m" => KEY_CODE_M,
122
+ "M" => KEY_CODE_M,
123
+ "n" => KEY_CODE_N,
124
+ "N" => KEY_CODE_N,
125
+ "o" => KEY_CODE_O,
126
+ "O" => KEY_CODE_O,
127
+ "p" => KEY_CODE_P,
128
+ "P" => KEY_CODE_P,
129
+ "q" => KEY_CODE_Q,
130
+ "Q" => KEY_CODE_Q,
131
+ "r" => KEY_CODE_R,
132
+ "R" => KEY_CODE_R,
133
+ "s" => KEY_CODE_S,
134
+ "S" => KEY_CODE_S,
135
+ "t" => KEY_CODE_T,
136
+ "T" => KEY_CODE_T,
137
+ "u" => KEY_CODE_U,
138
+ "U" => KEY_CODE_U,
139
+ "v" => KEY_CODE_V,
140
+ "V" => KEY_CODE_V,
141
+ "w" => KEY_CODE_W,
142
+ "W" => KEY_CODE_W,
143
+ "x" => KEY_CODE_X,
144
+ "X" => KEY_CODE_X,
145
+ "y" => KEY_CODE_Y,
146
+ "Y" => KEY_CODE_Y,
147
+ "z" => KEY_CODE_Z,
148
+ "Z" => KEY_CODE_Z,
149
+ "1" => KEY_CODE_1,
150
+ "2" => KEY_CODE_2,
151
+ "3" => KEY_CODE_3,
152
+ "4" => KEY_CODE_4,
153
+ "5" => KEY_CODE_5,
154
+ "6" => KEY_CODE_6,
155
+ "7" => KEY_CODE_7,
156
+ "8" => KEY_CODE_8,
157
+ "9" => KEY_CODE_9,
158
+ "0" => KEY_CODE_0,
159
+ "~" => KEY_CODE_TILDE,
160
+ "`" => KEY_CODE_BACKTICK,
161
+ "!" => KEY_CODE_EXCLAMATION,
162
+ "@" => KEY_CODE_AMPERSAT,
163
+ "#" => KEY_CODE_HASH,
164
+ "$" => KEY_CODE_DOLLAR,
165
+ "%" => KEY_CODE_PERCENT,
166
+ "^" => KEY_CODE_CARET,
167
+ "&" => KEY_CODE_AMPERSAND,
168
+ "*" => KEY_CODE_ASTERISK,
169
+ "(" => KEY_CODE_LPARENTHESIS,
170
+ ")" => KEY_CODE_RPARENTHESIS,
171
+ "=" => KEY_CODE_EQUAL,
172
+ "-" => KEY_CODE_MINUS,
173
+ "+" => KEY_CODE_PLUS,
174
+ "_" => KEY_CODE_UNDERSCORE,
175
+ "[" => KEY_CODE_LBRACKET,
176
+ "]" => KEY_CODE_RBRACKET,
177
+ "<" => KEY_CODE_LT,
178
+ ">" => KEY_CODE_GT,
179
+ "{" => KEY_CODE_LBRACE,
180
+ "}" => KEY_CODE_RBRACE,
181
+ "|" => KEY_CODE_PIPE,
182
+ ":" => KEY_CODE_COLON,
183
+ "'" => KEY_CODE_QUOTE,
184
+ "\"" => KEY_CODE_QUOTATION,
185
+ "," => KEY_CODE_COMMA,
186
+ "." => KEY_CODE_PERIOD,
187
+ "/" => KEY_CODE_SLASH,
188
+ "\\" => KEY_CODE_BACKSLASH,
189
+ " " => KEY_CODE_SPACE,
190
+ "escape" => KEY_CODE_ESCAPE,
191
+ "backspace" => KEY_CODE_DELETE,
192
+ "delete" => KEY_CODE_DELETE,
193
+ "command" => KEY_CODE_COMMAND,
194
+ "option" => KEY_CODE_OPTION,
195
+ "control" => KEY_CODE_CONTROL,
196
+ "shift" => KEY_CODE_SHIFT,
197
+ "function" => KEY_CODE_FUNCTION,
198
+ "left" => KEY_CODE_LEFT,
199
+ "right" => KEY_CODE_RIGHT,
200
+ "up" => KEY_CODE_UP,
201
+ "down" => KEY_CODE_DOWN,
202
+ "←" => KEY_CODE_LEFT,
203
+ "→" => KEY_CODE_RIGHT,
204
+ "↑" => KEY_CODE_UP,
205
+ "↓" => KEY_CODE_DOWN,
206
+ "tab" => KEY_CODE_TAB,
207
+ "\t" => KEY_CODE_TAB,
208
+ "return" => KEY_CODE_RETURN,
209
+ "enter" => KEY_CODE_RETURN,
210
+ "\n" => KEY_CODE_RETURN,
211
+ }.freeze
212
+
213
+ # @param key [String]
214
+ # @raise [ArgumentError]
215
+ #
216
+ # @return [Integer]
217
+ def self.find(key)
218
+ MAPPING[key] || raise(ArgumentError, "unsupported key=#{key.inspect}")
219
+ end
220
+
221
+ # @param key [String]
222
+ #
223
+ # @return [Boolean]
224
+ def self.shifted?(key)
225
+ SHIFTED.include?(key)
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MacOS
4
+ module Library
5
+ module CoreGraphics
6
+ # https://developer.apple.com/documentation/coregraphics/cgmousebutton
7
+ module MouseButton
8
+ LEFT = 0 # https://developer.apple.com/documentation/coregraphics/cgmousebutton/left
9
+ RIGHT = 1 # https://developer.apple.com/documentation/coregraphics/cgmousebutton/right
10
+ CENTER = 2 # https://developer.apple.com/documentation/coregraphics/cgmousebutton/center
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi"
4
+
5
+ module MacOS
6
+ module Library
7
+ # https://developer.apple.com/documentation/coregraphics
8
+ module CoreGraphics
9
+ extend ::FFI::Library
10
+ ffi_lib "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics"
11
+
12
+ # https://developer.apple.com/documentation/corefoundation/cgpoint
13
+ class CGPoint < FFI::Struct
14
+ layout :x, :double, :y, :double
15
+ end
16
+
17
+ # https://developer.apple.com/documentation/corefoundation/cgsize
18
+ class CGSize < FFI::Struct
19
+ layout :width, :double, :height, :double
20
+ end
21
+
22
+ # https://developer.apple.com/documentation/corefoundation/cgrect
23
+ class CGRect < FFI::Struct
24
+ layout :origin, CGPoint, :size, CGSize
25
+ end
26
+
27
+ typedef :pointer, :CGError
28
+ typedef :pointer, :CGEventRef
29
+ typedef :pointer, :CGImageRef
30
+ typedef :uint16, :CGKeyCode
31
+ typedef :uint32, :CGDirectDisplayID
32
+ typedef :uint32, :CGEventFlags
33
+ typedef :uint32, :CGEventTapLocation
34
+ typedef :uint32, :CGEventType
35
+ typedef :uint32, :CGMouseButton
36
+
37
+ attach_function :CFRelease, %i[pointer], :void
38
+ attach_function :CGEventCreate, %i[pointer], :CGEventRef
39
+ attach_function :CGEventGetLocation, %i[pointer], CGPoint.by_value
40
+ attach_function :CGEventCreateMouseEvent, [:pointer, :CGEventType, CGPoint.by_value, :CGMouseButton], :CGEventRef
41
+ attach_function :CGEventCreateKeyboardEvent, %i[pointer CGKeyCode bool], :CGEventRef
42
+ attach_function :CGEventSetFlags, %i[CGEventRef CGEventFlags], :void
43
+ attach_function :CGEventPost, %i[CGEventTapLocation CGEventRef], :void
44
+ attach_function :CGWarpMouseCursorPosition, [CGPoint.by_value], :CGError
45
+ attach_function :CGMainDisplayID, [], :CGDirectDisplayID
46
+ attach_function :CGDisplayBounds, %i[CGDirectDisplayID], CGRect.by_value
47
+ attach_function :CGDisplayCreateImage, %i[CGDirectDisplayID], :CGImageRef
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi"
4
+
5
+ module MacOS
6
+ module Library
7
+ # https://developer.apple.com/documentation/corefoundation
8
+ module ImageIO
9
+ extend FFI::Library
10
+ ffi_lib "/System/Library/Frameworks/ImageIO.framework/ImageIO"
11
+
12
+ attach_function :CGImageDestinationCreateWithURL, %i[pointer pointer size_t pointer], :pointer
13
+ attach_function :CGImageDestinationAddImage, %i[pointer pointer pointer], :void
14
+ attach_function :CGImageDestinationFinalize, %i[pointer], :bool
15
+ attach_function :CFRelease, %i[pointer], :void
16
+ end
17
+ end
18
+ end
data/lib/macos/mouse.rb CHANGED
@@ -7,9 +7,9 @@ module MacOS
7
7
 
8
8
  # @return [Position]
9
9
  def position
10
- event = Library.CGEventCreate(nil)
11
- position = Library.CGEventGetLocation(event)
12
- Library.CFRelease(event)
10
+ event = Library::CoreGraphics.CGEventCreate(nil)
11
+ position = Library::CoreGraphics.CGEventGetLocation(event)
12
+ Library::CoreGraphics.CFRelease(event)
13
13
 
14
14
  x = position[:x]
15
15
  y = position[:y]
@@ -17,80 +17,94 @@ module MacOS
17
17
  Position.new(x, y)
18
18
  end
19
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.
20
+ # @param type [Integer] e.g. `MacOS::Library::CoreGraphicsEventType::MOUSE_MOVED`
21
+ # @param x [Integer]
22
+ # @param y [Integer]
23
+ # @param button [Integer] e.g. `MacOS::Library::CoreGraphicsMouseButton::MIDDLE`
24
24
  def trigger(type:, x:, y:, button: 0)
25
- position = CG::Point.new
25
+ position = Library::CoreGraphics::CGPoint.new
26
26
  position[:x] = x
27
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)
28
+
29
+ event = Library::CoreGraphics.CGEventCreateMouseEvent(nil, type, position, button)
30
+
31
+ Library::CoreGraphics.CGEventPost(Library::CoreGraphics::EventTapLocation::HID_EVENT_TAP, event)
32
+ Library::CoreGraphics.CFRelease(event)
31
33
  end
32
34
 
33
- # @param x [Float]
34
- # @param y [Float]
35
+ # @param x [Integer]
36
+ # @param y [Integer]
35
37
  def move(x:, y:)
36
- position = CG::Point.new
38
+ position = Library::CoreGraphics::CGPoint.new
37
39
  position[:x] = x
38
40
  position[:y] = y
39
- Library.CGWarpMouseCursorPosition(position)
41
+ Library::CoreGraphics.CGWarpMouseCursorPosition(position)
40
42
  end
41
43
 
42
- # @param x [Float]
43
- # @param y [Float]
44
+ # @param x [Integer]
45
+ # @param y [Integer]
44
46
  def left_down(x:, y:)
45
- trigger(type: CG::EventType::LEFT_MOUSE_DOWN, x:, y:, button: CG::MouseButton::LEFT)
47
+ trigger(x:, y:,
48
+ type: Library::CoreGraphics::EventType::LEFT_MOUSE_DOWN,
49
+ button: Library::CoreGraphics::MouseButton::LEFT)
46
50
  end
47
51
 
48
- # @param x [Float]
49
- # @param y [Float]
52
+ # @param x [Integer]
53
+ # @param y [Integer]
50
54
  def left_up(x:, y:)
51
- trigger(type: CG::EventType::LEFT_MOUSE_UP, x:, y:, button: CG::MouseButton::LEFT)
55
+ trigger(x:, y:,
56
+ type: Library::CoreGraphics::EventType::LEFT_MOUSE_UP,
57
+ button: Library::CoreGraphics::MouseButton::LEFT)
52
58
  end
53
59
 
54
- # @param x [Float]
55
- # @param y [Float]
60
+ # @param x [Integer]
61
+ # @param y [Integer]
56
62
  def left_click(x:, y:)
57
63
  left_down(x:, y:)
58
64
  left_up(x:, y:)
59
65
  end
60
66
 
61
- # @param x [Float]
62
- # @param y [Float]
67
+ # @param x [Integer]
68
+ # @param y [Integer]
63
69
  def right_down(x:, y:)
64
- trigger(type: CG::EventType::RIGHT_MOUSE_DOWN, x:, y:, button: CG::MouseButton::RIGHT)
70
+ trigger(x:, y:,
71
+ type: Library::CoreGraphics::EventType::RIGHT_MOUSE_DOWN,
72
+ button: Library::CoreGraphics::MouseButton::RIGHT)
65
73
  end
66
74
 
67
- # @param x [Float]
68
- # @param y [Float]
75
+ # @param x [Integer]
76
+ # @param y [Integer]
69
77
  def right_up(x:, y:)
70
- trigger(type: CG::EventType::RIGHT_MOUSE_UP, x:, y:, button: CG::MouseButton::RIGHT)
78
+ trigger(x:, y:,
79
+ type: Library::CoreGraphics::EventType::RIGHT_MOUSE_UP,
80
+ button: Library::CoreGraphics::MouseButton::RIGHT)
71
81
  end
72
82
 
73
- # @param x [Float]
74
- # @param y [Float]
83
+ # @param x [Integer]
84
+ # @param y [Integer]
75
85
  def right_click(x:, y:)
76
86
  right_down(x:, y:)
77
87
  right_up(x:, y:)
78
88
  end
79
89
 
80
- # @param x [Float]
81
- # @param y [Float]
90
+ # @param x [Integer]
91
+ # @param y [Integer]
82
92
  def middle_down(x:, y:)
83
- trigger(type: CG::EventType::OTHER_MOUSE_DOWN, x:, y:, button: CG::MouseButton::CENTER)
93
+ trigger(x:, y:,
94
+ type: Library::CoreGraphics::EventType::OTHER_MOUSE_DOWN,
95
+ button: Library::CoreGraphics::MouseButton::CENTER)
84
96
  end
85
97
 
86
- # @param x [Float]
87
- # @param y [Float]
98
+ # @param x [Integer]
99
+ # @param y [Integer]
88
100
  def middle_up(x:, y:)
89
- trigger(type: CG::EventType::OTHER_MOUSE_UP, x:, y:, button: CG::MouseButton::CENTER)
101
+ trigger(x:, y:,
102
+ type: Library::CoreGraphics::EventType::OTHER_MOUSE_UP,
103
+ button: Library::CoreGraphics::MouseButton::CENTER)
90
104
  end
91
105
 
92
- # @param x [Float]
93
- # @param y [Float]
106
+ # @param x [Integer]
107
+ # @param y [Integer]
94
108
  def middle_click(x:, y:)
95
109
  middle_down(x:, y:)
96
110
  middle_up(x:, y:)
data/lib/macos/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MacOS
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.6"
5
5
  end
data/lib/macos.rb CHANGED
@@ -4,8 +4,8 @@ require "fiddle"
4
4
  require "zeitwerk"
5
5
 
6
6
  loader = Zeitwerk::Loader.for_gem
7
- loader.inflector.inflect "cg" => "CG"
8
7
  loader.inflector.inflect "macos" => "MacOS"
8
+ loader.inflector.inflect "image_io" => "ImageIO"
9
9
  loader.setup
10
10
 
11
11
  # Interacts with macOS.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: macos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
@@ -64,15 +64,16 @@ files:
64
64
  - bin/demo
65
65
  - bin/setup
66
66
  - lib/macos.rb
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
67
  - lib/macos/display.rb
74
68
  - lib/macos/keyboard.rb
75
- - lib/macos/library.rb
69
+ - lib/macos/library/core_foundation.rb
70
+ - lib/macos/library/core_graphics.rb
71
+ - lib/macos/library/core_graphics/event_flags.rb
72
+ - lib/macos/library/core_graphics/event_tap_location.rb
73
+ - lib/macos/library/core_graphics/event_type.rb
74
+ - lib/macos/library/core_graphics/key_code.rb
75
+ - lib/macos/library/core_graphics/mouse_button.rb
76
+ - lib/macos/library/image_io.rb
76
77
  - lib/macos/mouse.rb
77
78
  - lib/macos/version.rb
78
79
  homepage: https://github.com/ksylvest/macos
@@ -1,12 +0,0 @@
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
@@ -1,22 +0,0 @@
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
@@ -1,12 +0,0 @@
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
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "ffi"
4
-
5
- module MacOS
6
- module CG
7
- # https://developer.apple.com/documentation/corefoundation/cgpoint
8
- class Point < FFI::Struct
9
- layout :x, :double, :y, :double
10
- end
11
- end
12
- end
data/lib/macos/cg/rect.rb DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "ffi"
4
-
5
- module MacOS
6
- module CG
7
- # https://developer.apple.com/documentation/corefoundation/cgrect
8
- class Rect < FFI::Struct
9
- layout :origin, MacOS::CG::Point, :size, MacOS::CG::Size
10
- end
11
- end
12
- end
data/lib/macos/cg/size.rb DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "ffi"
4
-
5
- module MacOS
6
- module CG
7
- # https://developer.apple.com/documentation/corefoundation/cgsize
8
- class Size < FFI::Struct
9
- layout :width, :double, :height, :double
10
- end
11
- end
12
- end
data/lib/macos/library.rb DELETED
@@ -1,21 +0,0 @@
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