macos 0.1.4 → 0.1.8

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: 906112e5154c3bb3b289accad6e1a4d74e43bcc69056848a7300cf0f01dc3eeb
4
+ data.tar.gz: 3f2b011e2877d7880e9eed8cf75a9aeff04a63ba206bda21984466a6647e1a3d
5
5
  SHA512:
6
- metadata.gz: 00aea0fa47b5dc3363fd3be123288ab12277429d0af9cd7db45066a9bc431421a3c966ab3d04401b6aa510a641378b1b58107577952a763b0b8f0e218956393f
7
- data.tar.gz: 9530f04a0e57b4b22b78c46266ea9079f4e138c6238f8ac503764e72f106f281fd6ac7d9ccb1bc91f18cd81ee59fd4f2126e50e886bbbec75c52269469280970
6
+ metadata.gz: '09002ddfa40a57fe51bb99705f4e62b5df2467c07561bd29f9238aac5d4a9954cc4bf31567b1dbcadc91bdf6a1a65e742024cc61c2f4f4f77b1f660050e605df'
7
+ data.tar.gz: ba769566717499722b25de6b9a2f4fbdced6db31bc1de5860523ed1dcfa9189377a2d1b54e0f1e878a695c13b2002f1fb8d88b3af2b5dccc2972db18fbff3541
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,29 @@
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
 
10
+ # @!attr_accessor :id
11
+ # # @return [Integer]
12
+ attr_accessor :id
13
+
8
14
  def self.main
9
- id = Library.CGMainDisplayID
15
+ id = Library::CoreGraphics.CGMainDisplayID
10
16
  new(id:)
11
17
  end
12
18
 
13
19
  # @param id [Integer
14
- def initialize(id:)
20
+ def initialize(id: 0)
15
21
  @id = id
16
22
  end
17
23
 
18
24
  # @return [Size]
19
25
  def bounds
20
- bounds = Library.CGDisplayBounds(@id)
26
+ bounds = Library::CoreGraphics.CGDisplayBounds(@id)
21
27
 
22
28
  width = Integer(bounds[:size][:width])
23
29
  height = Integer(bounds[:size][:height])
@@ -25,12 +31,39 @@ module MacOS
25
31
  Size.new(width, height)
26
32
  end
27
33
 
28
- # @yield [tempfile]
29
- # @yieldparam tempfile [Tempfile]
30
- def screenshot
34
+ # @retrun [Integer]
35
+ def wide
36
+ Library::CoreGraphics.CGDisplayPixelsWide(@id)
37
+ end
38
+
39
+ # @retrun [Integer]
40
+ def high
41
+ Library::CoreGraphics.CGDisplayPixelsHigh(@id)
42
+ end
43
+
44
+ # @yield [file]
45
+ # @yieldparam file [File]
46
+ def screenshot(&)
31
47
  tempfile = Tempfile.new(["screenshot", ".png"])
32
- system("screencapture -o -x #{tempfile.path}")
33
- yield tempfile
48
+
49
+ image = Library::CoreGraphics.CGDisplayCreateImage(@id)
50
+
51
+ encoding = Library::CoreFoundation::ENCODING_UTF8
52
+ path = Library::CoreFoundation.CFStringCreateWithCString(nil, tempfile.path, encoding)
53
+ url = Library::CoreFoundation.CFURLCreateWithFileSystemPath(nil, path, 0, false)
54
+ uti = Library::CoreFoundation.CFStringCreateWithCString(nil, "public.png", encoding)
55
+
56
+ dest = Library::ImageIO.CGImageDestinationCreateWithURL(url, uti, 1, nil)
57
+ Library::ImageIO.CGImageDestinationAddImage(dest, image, nil)
58
+ Library::ImageIO.CGImageDestinationFinalize(dest)
59
+
60
+ Library::CoreGraphics.CFRelease(image)
61
+ Library::CoreFoundation.CFRelease(path)
62
+ Library::CoreFoundation.CFRelease(url)
63
+ Library::CoreFoundation.CFRelease(uti)
64
+ Library::CoreFoundation.CFRelease(dest)
65
+
66
+ File.open(tempfile.path, "rb", &)
34
67
  ensure
35
68
  tempfile.close
36
69
  tempfile.unlink
@@ -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.downcase, 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,233 @@
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
+ "space" => KEY_CODE_SPACE,
190
+ " " => KEY_CODE_SPACE,
191
+ "escape" => KEY_CODE_ESCAPE,
192
+ "backspace" => KEY_CODE_DELETE,
193
+ "delete" => KEY_CODE_DELETE,
194
+ "command" => KEY_CODE_COMMAND,
195
+ "cmd" => KEY_CODE_COMMAND,
196
+ "⌘" => KEY_CODE_COMMAND,
197
+ "option" => KEY_CODE_OPTION,
198
+ "control" => KEY_CODE_CONTROL,
199
+ "shift" => KEY_CODE_SHIFT,
200
+ "function" => KEY_CODE_FUNCTION,
201
+ "left" => KEY_CODE_LEFT,
202
+ "right" => KEY_CODE_RIGHT,
203
+ "up" => KEY_CODE_UP,
204
+ "down" => KEY_CODE_DOWN,
205
+ "←" => KEY_CODE_LEFT,
206
+ "→" => KEY_CODE_RIGHT,
207
+ "↑" => KEY_CODE_UP,
208
+ "↓" => KEY_CODE_DOWN,
209
+ "tab" => KEY_CODE_TAB,
210
+ "\t" => KEY_CODE_TAB,
211
+ "return" => KEY_CODE_RETURN,
212
+ "enter" => KEY_CODE_RETURN,
213
+ "\n" => KEY_CODE_RETURN,
214
+ }.freeze
215
+
216
+ # @param key [String]
217
+ # @raise [ArgumentError]
218
+ #
219
+ # @return [Integer]
220
+ def self.find(key)
221
+ MAPPING[key] || raise(ArgumentError, "unsupported key=#{key.inspect}")
222
+ end
223
+
224
+ # @param key [String]
225
+ #
226
+ # @return [Boolean]
227
+ def self.shifted?(key)
228
+ SHIFTED.include?(key)
229
+ end
230
+ end
231
+ end
232
+ end
233
+ 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,52 @@
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
+ attach_function :CGDisplayPixelsWide, %i[CGDirectDisplayID], :size_t
49
+ attach_function :CGDisplayPixelsHigh, %i[CGDirectDisplayID], :size_t
50
+ end
51
+ end
52
+ 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.8"
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.8
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