puppeteer-ruby 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +71 -0
  3. data/.github/stale.yml +16 -0
  4. data/.gitignore +19 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +302 -0
  7. data/.travis.yml +7 -0
  8. data/Dockerfile +6 -0
  9. data/Gemfile +6 -0
  10. data/README.md +54 -0
  11. data/Rakefile +1 -0
  12. data/bin/console +11 -0
  13. data/bin/setup +8 -0
  14. data/docker-compose.yml +15 -0
  15. data/docs/Puppeteer.html +2020 -0
  16. data/docs/Puppeteer/AsyncAwaitBehavior.html +105 -0
  17. data/docs/Puppeteer/Browser.html +2148 -0
  18. data/docs/Puppeteer/BrowserContext.html +809 -0
  19. data/docs/Puppeteer/BrowserFetcher.html +214 -0
  20. data/docs/Puppeteer/BrowserRunner.html +914 -0
  21. data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +477 -0
  22. data/docs/Puppeteer/CDPSession.html +813 -0
  23. data/docs/Puppeteer/CDPSession/Error.html +124 -0
  24. data/docs/Puppeteer/ConcurrentRubyUtils.html +430 -0
  25. data/docs/Puppeteer/Connection.html +960 -0
  26. data/docs/Puppeteer/Connection/MessageCallback.html +434 -0
  27. data/docs/Puppeteer/Connection/ProtocolError.html +216 -0
  28. data/docs/Puppeteer/Connection/RequestDebugPrinter.html +217 -0
  29. data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +244 -0
  30. data/docs/Puppeteer/ConsoleMessage.html +565 -0
  31. data/docs/Puppeteer/ConsoleMessage/Location.html +433 -0
  32. data/docs/Puppeteer/DOMWorld.html +2219 -0
  33. data/docs/Puppeteer/DOMWorld/DetachedError.html +124 -0
  34. data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +124 -0
  35. data/docs/Puppeteer/DebugPrint.html +233 -0
  36. data/docs/Puppeteer/Device.html +470 -0
  37. data/docs/Puppeteer/Devices.html +139 -0
  38. data/docs/Puppeteer/ElementHandle.html +2542 -0
  39. data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +206 -0
  40. data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +206 -0
  41. data/docs/Puppeteer/ElementHandle/Point.html +492 -0
  42. data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +124 -0
  43. data/docs/Puppeteer/EmulationManager.html +454 -0
  44. data/docs/Puppeteer/EventCallbackable.html +433 -0
  45. data/docs/Puppeteer/EventCallbackable/EventListeners.html +435 -0
  46. data/docs/Puppeteer/ExecutionContext.html +998 -0
  47. data/docs/Puppeteer/ExecutionContext/EvaluationError.html +124 -0
  48. data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +357 -0
  49. data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +389 -0
  50. data/docs/Puppeteer/FileChooser.html +455 -0
  51. data/docs/Puppeteer/Frame.html +3677 -0
  52. data/docs/Puppeteer/FrameManager.html +2410 -0
  53. data/docs/Puppeteer/FrameManager/NavigationError.html +124 -0
  54. data/docs/Puppeteer/IfPresent.html +222 -0
  55. data/docs/Puppeteer/JSHandle.html +1352 -0
  56. data/docs/Puppeteer/Keyboard.html +1557 -0
  57. data/docs/Puppeteer/Keyboard/KeyDefinition.html +831 -0
  58. data/docs/Puppeteer/Keyboard/KeyDescription.html +603 -0
  59. data/docs/Puppeteer/Launcher.html +237 -0
  60. data/docs/Puppeteer/Launcher/Base.html +385 -0
  61. data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +124 -0
  62. data/docs/Puppeteer/Launcher/BrowserOptions.html +441 -0
  63. data/docs/Puppeteer/Launcher/Chrome.html +669 -0
  64. data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +382 -0
  65. data/docs/Puppeteer/Launcher/ChromeArgOptions.html +531 -0
  66. data/docs/Puppeteer/Launcher/LaunchOptions.html +893 -0
  67. data/docs/Puppeteer/LifecycleWatcher.html +834 -0
  68. data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +363 -0
  69. data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +206 -0
  70. data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +124 -0
  71. data/docs/Puppeteer/Mouse.html +1105 -0
  72. data/docs/Puppeteer/Mouse/Button.html +136 -0
  73. data/docs/Puppeteer/NetworkManager.html +901 -0
  74. data/docs/Puppeteer/NetworkManager/Credentials.html +385 -0
  75. data/docs/Puppeteer/Page.html +5970 -0
  76. data/docs/Puppeteer/Page/FileChooserTimeoutError.html +206 -0
  77. data/docs/Puppeteer/Page/ScreenshotOptions.html +845 -0
  78. data/docs/Puppeteer/Page/ScriptTag.html +555 -0
  79. data/docs/Puppeteer/Page/StyleTag.html +448 -0
  80. data/docs/Puppeteer/Page/TargetCrashedError.html +124 -0
  81. data/docs/Puppeteer/RemoteObject.html +1087 -0
  82. data/docs/Puppeteer/Target.html +1336 -0
  83. data/docs/Puppeteer/Target/InitializeFailure.html +124 -0
  84. data/docs/Puppeteer/Target/TargetInfo.html +729 -0
  85. data/docs/Puppeteer/TimeoutError.html +135 -0
  86. data/docs/Puppeteer/TimeoutSettings.html +496 -0
  87. data/docs/Puppeteer/TouchScreen.html +464 -0
  88. data/docs/Puppeteer/Viewport.html +837 -0
  89. data/docs/Puppeteer/WaitTask.html +637 -0
  90. data/docs/Puppeteer/WaitTask/TerminatedError.html +124 -0
  91. data/docs/Puppeteer/WaitTask/TimeoutError.html +206 -0
  92. data/docs/Puppeteer/WebSocket.html +673 -0
  93. data/docs/Puppeteer/WebSocket/DriverImpl.html +412 -0
  94. data/docs/Puppeteer/WebSocketTransport.html +600 -0
  95. data/docs/Puppeteer/WebSocktTransportError.html +124 -0
  96. data/docs/_index.html +823 -0
  97. data/docs/class_list.html +51 -0
  98. data/docs/css/common.css +1 -0
  99. data/docs/css/full_list.css +58 -0
  100. data/docs/css/style.css +496 -0
  101. data/docs/file.README.html +123 -0
  102. data/docs/file_list.html +56 -0
  103. data/docs/frames.html +17 -0
  104. data/docs/index.html +123 -0
  105. data/docs/js/app.js +314 -0
  106. data/docs/js/full_list.js +216 -0
  107. data/docs/js/jquery.js +4 -0
  108. data/docs/method_list.html +4075 -0
  109. data/docs/top-level-namespace.html +126 -0
  110. data/lib/puppeteer.rb +200 -0
  111. data/lib/puppeteer/async_await_behavior.rb +38 -0
  112. data/lib/puppeteer/browser.rb +259 -0
  113. data/lib/puppeteer/browser_context.rb +90 -0
  114. data/lib/puppeteer/browser_fetcher.rb +6 -0
  115. data/lib/puppeteer/browser_runner.rb +161 -0
  116. data/lib/puppeteer/cdp_session.rb +100 -0
  117. data/lib/puppeteer/concurrent_ruby_utils.rb +37 -0
  118. data/lib/puppeteer/connection.rb +254 -0
  119. data/lib/puppeteer/console_message.rb +24 -0
  120. data/lib/puppeteer/debug_print.rb +20 -0
  121. data/lib/puppeteer/device.rb +12 -0
  122. data/lib/puppeteer/devices.rb +885 -0
  123. data/lib/puppeteer/dom_world.rb +484 -0
  124. data/lib/puppeteer/element_handle.rb +433 -0
  125. data/lib/puppeteer/element_handle/bounding_box.rb +12 -0
  126. data/lib/puppeteer/element_handle/box_model.rb +19 -0
  127. data/lib/puppeteer/element_handle/point.rb +26 -0
  128. data/lib/puppeteer/emulation_manager.rb +46 -0
  129. data/lib/puppeteer/errors.rb +2 -0
  130. data/lib/puppeteer/event_callbackable.rb +88 -0
  131. data/lib/puppeteer/execution_context.rb +254 -0
  132. data/lib/puppeteer/file_chooser.rb +29 -0
  133. data/lib/puppeteer/frame.rb +286 -0
  134. data/lib/puppeteer/frame_manager.rb +378 -0
  135. data/lib/puppeteer/if_present.rb +18 -0
  136. data/lib/puppeteer/js_handle.rb +142 -0
  137. data/lib/puppeteer/keyboard.rb +183 -0
  138. data/lib/puppeteer/keyboard/key_description.rb +19 -0
  139. data/lib/puppeteer/keyboard/us_keyboard_layout.rb +283 -0
  140. data/lib/puppeteer/launcher.rb +25 -0
  141. data/lib/puppeteer/launcher/base.rb +48 -0
  142. data/lib/puppeteer/launcher/browser_options.rb +41 -0
  143. data/lib/puppeteer/launcher/chrome.rb +211 -0
  144. data/lib/puppeteer/launcher/chrome_arg_options.rb +49 -0
  145. data/lib/puppeteer/launcher/launch_options.rb +68 -0
  146. data/lib/puppeteer/lifecycle_watcher.rb +171 -0
  147. data/lib/puppeteer/mouse.rb +123 -0
  148. data/lib/puppeteer/network_manager.rb +122 -0
  149. data/lib/puppeteer/page.rb +1065 -0
  150. data/lib/puppeteer/page/screenshot_options.rb +78 -0
  151. data/lib/puppeteer/remote_object.rb +143 -0
  152. data/lib/puppeteer/target.rb +150 -0
  153. data/lib/puppeteer/timeout_settings.rb +15 -0
  154. data/lib/puppeteer/touch_screen.rb +43 -0
  155. data/lib/puppeteer/version.rb +3 -0
  156. data/lib/puppeteer/viewport.rb +54 -0
  157. data/lib/puppeteer/wait_task.rb +188 -0
  158. data/lib/puppeteer/web_socket.rb +122 -0
  159. data/lib/puppeteer/web_socket_transport.rb +49 -0
  160. data/puppeteer-ruby.gemspec +32 -0
  161. metadata +355 -0
@@ -0,0 +1,18 @@
1
+ module Puppeteer::IfPresent
2
+ # Similar to #try in ActiveSupport::CoreExt.
3
+ #
4
+ # Evaluate block with the target, only if target is not nil.
5
+ # Returns nil if target is nil.
6
+ #
7
+ # --------
8
+ # if_present(params['target']) do |target|
9
+ # Point.new(target['x'], target['y'])
10
+ # end
11
+ # --------
12
+ def if_present(target, &block)
13
+ raise ArgumentError.new('block must be provided for #if_present') if block.nil?
14
+ return nil if target.nil?
15
+
16
+ block.call(target)
17
+ end
18
+ end
@@ -0,0 +1,142 @@
1
+ class Puppeteer::JSHandle
2
+ using Puppeteer::AsyncAwaitBehavior
3
+
4
+ # @param context [Puppeteer::ExecutionContext]
5
+ # @param remote_object [Puppeteer::RemoteObject]
6
+ def self.create(context:, remote_object:)
7
+ frame = context.frame
8
+ if remote_object.sub_type == 'node' && frame
9
+ frame_manager = frame.frame_manager
10
+ Puppeteer::ElementHandle.new(
11
+ context: context,
12
+ client: context.client,
13
+ remote_object: remote_object,
14
+ page: frame_manager.page,
15
+ frame_manager: frame_manager,
16
+ )
17
+ else
18
+ Puppeteer::JSHandle.new(
19
+ context: context,
20
+ client: context.client,
21
+ remote_object: remote_object,
22
+ )
23
+ end
24
+ end
25
+
26
+ # @param context [Puppeteer::ExecutionContext]
27
+ # @param client [Puppeteer::CDPSession]
28
+ # @param remote_object [Puppeteer::RemoteObject]
29
+ def initialize(context:, client:, remote_object:)
30
+ @context = context
31
+ @client = client
32
+ @remote_object = remote_object
33
+ @disposed = false
34
+ end
35
+
36
+ attr_reader :context, :remote_object
37
+
38
+ # @return [Puppeteer::ExecutionContext]
39
+ def execution_context
40
+ @context
41
+ end
42
+
43
+ # @param page_function [String]
44
+ # @return [Object]
45
+ def evaluate(page_function, *args)
46
+ execution_context.evaluate(page_function, self, *args)
47
+ end
48
+
49
+ # @param page_function [String]
50
+ # @return [Future<Object>]
51
+ async def async_evaluate(page_function, *args)
52
+ evaluate(page_function, *args)
53
+ end
54
+
55
+ # @param page_function [String]
56
+ # @param args {Array<*>}
57
+ # @return [Puppeteer::JSHandle]
58
+ def evaluate_handle(page_function, *args)
59
+ execution_context.evaluate_handle(page_function, self, *args)
60
+ end
61
+
62
+ # @param page_function [String]
63
+ # @param args {Array<*>}
64
+ # @return [Future<Puppeteer::JSHandle>]
65
+ async def async_evaluate_handle(page_function, *args)
66
+ evaluate_handle(page_function, *args)
67
+ end
68
+
69
+ # /**
70
+ # * @param {string} propertyName
71
+ # * @return {!Promise<?JSHandle>}
72
+ # */
73
+ # async getProperty(propertyName) {
74
+ # const objectHandle = await this.evaluateHandle((object, propertyName) => {
75
+ # const result = {__proto__: null};
76
+ # result[propertyName] = object[propertyName];
77
+ # return result;
78
+ # }, propertyName);
79
+ # const properties = await objectHandle.getProperties();
80
+ # const result = properties.get(propertyName) || null;
81
+ # await objectHandle.dispose();
82
+ # return result;
83
+ # }
84
+
85
+ # getProperties in JavaScript.
86
+ # @return [Hash<String, JSHandle>]
87
+ def properties
88
+ response = @remote_object.properties(@client)
89
+ response['result'].each_with_object({}) do |prop, h|
90
+ next unless prop['enumerable']
91
+ h[prop['name']] = Puppeteer::JSHandle.create(
92
+ context: @context,
93
+ remote_object: Puppeteer::RemoteObject.new(prop['value']),
94
+ )
95
+ end
96
+ end
97
+
98
+ def json_value
99
+ # original logic was:
100
+ # if (this._remoteObject.objectId) {
101
+ # const response = await this._client.send('Runtime.callFunctionOn', {
102
+ # functionDeclaration: 'function() { return this; }',
103
+ # objectId: this._remoteObject.objectId,
104
+ # returnByValue: true,
105
+ # awaitPromise: true,
106
+ # });
107
+ # return helper.valueFromRemoteObject(response.result);
108
+ # }
109
+ # return helper.valueFromRemoteObject(this._remoteObject);
110
+ #
111
+ # However it would be better that RemoteObject is responsible for
112
+ # the logic `if (this._remoteObject.objectId) { ... }`.
113
+ @remote_object.evaluate_self(@client) || @remote_object.value
114
+ end
115
+
116
+ def as_element
117
+ nil
118
+ end
119
+
120
+ def dispose
121
+ return if @disposed
122
+
123
+ @disposed = true
124
+ @remote_object.release(@client)
125
+ end
126
+
127
+ def disposed?
128
+ @disposed
129
+ end
130
+
131
+ # /**
132
+ # * @override
133
+ # * @return {string}
134
+ # */
135
+ # toString() {
136
+ # if (this._remoteObject.objectId) {
137
+ # const type = this._remoteObject.subtype || this._remoteObject.type;
138
+ # return 'JSHandle@' + type;
139
+ # }
140
+ # return 'JSHandle:' + helper.valueFromRemoteObject(this._remoteObject);
141
+ # }
142
+ end
@@ -0,0 +1,183 @@
1
+ require_relative './keyboard/key_description'
2
+ require_relative './keyboard/us_keyboard_layout'
3
+
4
+ class Puppeteer::Keyboard
5
+ using Puppeteer::AsyncAwaitBehavior
6
+
7
+ # @param {!Puppeteer.CDPSession} client
8
+ def initialize(client)
9
+ @client = client
10
+ @modifiers = 0
11
+ @pressed_keys = Set.new
12
+ end
13
+
14
+ attr_reader :modifiers
15
+
16
+ # @param key [String]
17
+ # @param text [String]
18
+ def down(key, text: nil)
19
+ description = key_description_for_string(key)
20
+
21
+ auto_repeat = @pressed_keys.include?(description.code)
22
+ @pressed_keys << description.code
23
+ @modifiers |= modifier_bit(description.key)
24
+
25
+ sending_text = text || description.text
26
+ params = {
27
+ type: sending_text ? 'keyDown' : 'rawKeyDown',
28
+ modifiers: @modifiers,
29
+ windowsVirtualKeyCode: description.key_code,
30
+ code: description.code,
31
+ key: description.key,
32
+ text: sending_text,
33
+ unmodifiedText: sending_text,
34
+ autoRepeat: auto_repeat,
35
+ location: description.location,
36
+ isKeypad: description.location == 3,
37
+ }.compact
38
+ @client.send_message('Input.dispatchKeyEvent', params)
39
+ end
40
+
41
+ # @param key [String]
42
+ # @param text [String]
43
+ # @return [Future]
44
+ async def async_down(key, text: nil)
45
+ down(key, text)
46
+ end
47
+
48
+ # @param {string} key
49
+ # @return {number}
50
+ private def modifier_bit(key)
51
+ case key
52
+ when 'Alt'
53
+ 1
54
+ when 'Control'
55
+ 2
56
+ when 'Meta'
57
+ 4
58
+ when 'Shift'
59
+ 8
60
+ else
61
+ 0
62
+ end
63
+ end
64
+
65
+ # @param {string} keyString
66
+ # @return {KeyDescription}
67
+ private def key_description_for_string(key_string)
68
+ shift = (@modifiers & 8) != 0
69
+ description = {}
70
+ definition = KEY_DEFINITIONS[key_string.to_sym]
71
+ if !definition
72
+ raise ArgumentError.new("Unknown key: \"#{key_string}\"")
73
+ end
74
+
75
+ if definition.key
76
+ description[:key] = definition.key
77
+ end
78
+ if shift && definition.shift_key
79
+ description[:key] = definition.shift_key
80
+ end
81
+
82
+ description[:key_code] = definition.key_code || 0
83
+
84
+ if shift && definition.shift_key_code
85
+ description[:key_code] = definition.shift_key_code
86
+ end
87
+
88
+ if definition.code
89
+ description[:code] = definition.code
90
+ end
91
+
92
+ description[:location] = definition.location || 0
93
+
94
+ if description[:key].length == 1
95
+ description[:text] = description[:key]
96
+ end
97
+
98
+ if definition.text
99
+ description[:text] = definition.text
100
+ end
101
+ if shift && definition.shift_text
102
+ description[:text] = definition.shift_text
103
+ end
104
+
105
+ # if any modifiers besides shift are pressed, no text should be sent
106
+ if (@modifiers & ~8) != 0
107
+ description[:text] = ''
108
+ end
109
+
110
+ KeyDescription.new(**description)
111
+ end
112
+
113
+ # @param key [String]
114
+ def up(key)
115
+ description = key_description_for_string(key)
116
+
117
+ @modifiers &= ~(modifier_bit(description.key))
118
+ @pressed_keys.delete(description.code)
119
+
120
+ @client.send_message('Input.dispatchKeyEvent',
121
+ type: 'keyUp',
122
+ modifiers: @modifiers,
123
+ key: description.key,
124
+ windowsVirtualKeyCode: description.key_code,
125
+ code: description.code,
126
+ location: description.location,
127
+ )
128
+ end
129
+
130
+ # @param key [String]
131
+ # @return [Future]
132
+ async def async_up(key)
133
+ up(key)
134
+ end
135
+
136
+ # @param char [string]
137
+ def send_character(char)
138
+ @client.send_message('Input.insertText', text: char)
139
+ end
140
+
141
+ # @param char [string]
142
+ # @return [Future]
143
+ async def async_send_character(char)
144
+ send_character(char)
145
+ end
146
+
147
+ # @param text [String]
148
+ # @return [Future]
149
+ def type_text(text, delay: nil)
150
+ text.each_char do |char|
151
+ if KEY_DEFINITIONS.include?(char.to_sym)
152
+ press(char, delay: delay)
153
+ else
154
+ if delay
155
+ sleep(delay.to_i / 1000.0)
156
+ end
157
+ send_character(char)
158
+ end
159
+ end
160
+ end
161
+
162
+ # @param text [String]
163
+ # @return [Future]
164
+ async def async_type_text(text, delay: nil)
165
+ type_text(text, delay)
166
+ end
167
+
168
+ # @param key [String]
169
+ # @return [Future]
170
+ def press(key, delay: nil)
171
+ down(key)
172
+ if delay
173
+ sleep(delay.to_i / 1000.0)
174
+ end
175
+ up(key)
176
+ end
177
+
178
+ # @param key [String]
179
+ # @return [Future]
180
+ async def async_press(key, delay: nil)
181
+ press(key, delay: delay)
182
+ end
183
+ end
@@ -0,0 +1,19 @@
1
+ class Puppeteer::Keyboard
2
+ # * @typedef {Object} KeyDescription
3
+ # * @property {number} keyCode
4
+ # * @property {string} key
5
+ # * @property {string} text
6
+ # * @property {string} code
7
+ # * @property {number} location
8
+ class KeyDescription
9
+ def initialize(key_code: nil, key: nil, text: nil, code: nil, location: nil)
10
+ @key_code = key_code
11
+ @key = key
12
+ @text = text
13
+ @code = code
14
+ @location = location
15
+ end
16
+
17
+ attr_reader :key_code, :key, :text, :code, :location
18
+ end
19
+ end
@@ -0,0 +1,283 @@
1
+ class Puppeteer::Keyboard
2
+ # * @typedef {Object} KeyDefinition
3
+ # * @property {number=} keyCode
4
+ # * @property {number=} shiftKeyCode
5
+ # * @property {string=} key
6
+ # * @property {string=} shiftKey
7
+ # * @property {string=} code
8
+ # * @property {string=} text
9
+ # * @property {string=} shiftText
10
+ # * @property {number=} location
11
+ class KeyDefinition
12
+ def initialize(hash)
13
+ @key_code = hash[:keyCode]
14
+ @shift_key_code = hash[:shiftKeyCode]
15
+ @key = hash[:key]
16
+ @shift_key = hash[:shiftKey]
17
+ @code = hash[:code]
18
+ @text = hash[:text]
19
+ @shift_text = hash[:shiftText]
20
+ @location = hash[:location]
21
+ end
22
+
23
+ attr_reader :key_code, :key, :code, :text, :shift_key_code, :shift_key, :shift_text, :location
24
+ end
25
+
26
+ KEY_DEFINITIONS = {
27
+ '0': KeyDefinition.new({ 'keyCode': 48, 'key': '0', 'code': 'Digit0' }),
28
+ '1': KeyDefinition.new({ 'keyCode': 49, 'key': '1', 'code': 'Digit1' }),
29
+ '2': KeyDefinition.new({ 'keyCode': 50, 'key': '2', 'code': 'Digit2' }),
30
+ '3': KeyDefinition.new({ 'keyCode': 51, 'key': '3', 'code': 'Digit3' }),
31
+ '4': KeyDefinition.new({ 'keyCode': 52, 'key': '4', 'code': 'Digit4' }),
32
+ '5': KeyDefinition.new({ 'keyCode': 53, 'key': '5', 'code': 'Digit5' }),
33
+ '6': KeyDefinition.new({ 'keyCode': 54, 'key': '6', 'code': 'Digit6' }),
34
+ '7': KeyDefinition.new({ 'keyCode': 55, 'key': '7', 'code': 'Digit7' }),
35
+ '8': KeyDefinition.new({ 'keyCode': 56, 'key': '8', 'code': 'Digit8' }),
36
+ '9': KeyDefinition.new({ 'keyCode': 57, 'key': '9', 'code': 'Digit9' }),
37
+ 'Power': KeyDefinition.new({ 'key': 'Power', 'code': 'Power' }),
38
+ 'Eject': KeyDefinition.new({ 'key': 'Eject', 'code': 'Eject' }),
39
+ 'Abort': KeyDefinition.new({ 'keyCode': 3, 'code': 'Abort', 'key': 'Cancel' }),
40
+ 'Help': KeyDefinition.new({ 'keyCode': 6, 'code': 'Help', 'key': 'Help' }),
41
+ 'Backspace': KeyDefinition.new({ 'keyCode': 8, 'code': 'Backspace', 'key': 'Backspace' }),
42
+ 'Tab': KeyDefinition.new({ 'keyCode': 9, 'code': 'Tab', 'key': 'Tab' }),
43
+ 'Numpad5': KeyDefinition.new({ 'keyCode': 12, 'shiftKeyCode': 101, 'key': 'Clear', 'code': 'Numpad5', 'shiftKey': '5', 'location': 3 }),
44
+ 'NumpadEnter': KeyDefinition.new({ 'keyCode': 13, 'code': 'NumpadEnter', 'key': 'Enter', 'text': "\r", 'location': 3 }),
45
+ 'Enter': KeyDefinition.new({ 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': "\r" }),
46
+ "\r": KeyDefinition.new({ 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': "\r" }),
47
+ "\n": KeyDefinition.new({ 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': "\r" }),
48
+ 'ShiftLeft': KeyDefinition.new({ 'keyCode': 16, 'code': 'ShiftLeft', 'key': 'Shift', 'location': 1 }),
49
+ 'ShiftRight': KeyDefinition.new({ 'keyCode': 16, 'code': 'ShiftRight', 'key': 'Shift', 'location': 2 }),
50
+ 'ControlLeft': KeyDefinition.new({ 'keyCode': 17, 'code': 'ControlLeft', 'key': 'Control', 'location': 1 }),
51
+ 'ControlRight': KeyDefinition.new({ 'keyCode': 17, 'code': 'ControlRight', 'key': 'Control', 'location': 2 }),
52
+ 'AltLeft': KeyDefinition.new({ 'keyCode': 18, 'code': 'AltLeft', 'key': 'Alt', 'location': 1 }),
53
+ 'AltRight': KeyDefinition.new({ 'keyCode': 18, 'code': 'AltRight', 'key': 'Alt', 'location': 2 }),
54
+ 'Pause': KeyDefinition.new({ 'keyCode': 19, 'code': 'Pause', 'key': 'Pause' }),
55
+ 'CapsLock': KeyDefinition.new({ 'keyCode': 20, 'code': 'CapsLock', 'key': 'CapsLock' }),
56
+ 'Escape': KeyDefinition.new({ 'keyCode': 27, 'code': 'Escape', 'key': 'Escape' }),
57
+ 'Convert': KeyDefinition.new({ 'keyCode': 28, 'code': 'Convert', 'key': 'Convert' }),
58
+ 'NonConvert': KeyDefinition.new({ 'keyCode': 29, 'code': 'NonConvert', 'key': 'NonConvert' }),
59
+ 'Space': KeyDefinition.new({ 'keyCode': 32, 'code': 'Space', 'key': ' ' }),
60
+ 'Numpad9': KeyDefinition.new({ 'keyCode': 33, 'shiftKeyCode': 105, 'key': 'PageUp', 'code': 'Numpad9', 'shiftKey': '9', 'location': 3 }),
61
+ 'PageUp': KeyDefinition.new({ 'keyCode': 33, 'code': 'PageUp', 'key': 'PageUp' }),
62
+ 'Numpad3': KeyDefinition.new({ 'keyCode': 34, 'shiftKeyCode': 99, 'key': 'PageDown', 'code': 'Numpad3', 'shiftKey': '3', 'location': 3 }),
63
+ 'PageDown': KeyDefinition.new({ 'keyCode': 34, 'code': 'PageDown', 'key': 'PageDown' }),
64
+ 'End': KeyDefinition.new({ 'keyCode': 35, 'code': 'End', 'key': 'End' }),
65
+ 'Numpad1': KeyDefinition.new({ 'keyCode': 35, 'shiftKeyCode': 97, 'key': 'End', 'code': 'Numpad1', 'shiftKey': '1', 'location': 3 }),
66
+ 'Home': KeyDefinition.new({ 'keyCode': 36, 'code': 'Home', 'key': 'Home' }),
67
+ 'Numpad7': KeyDefinition.new({ 'keyCode': 36, 'shiftKeyCode': 103, 'key': 'Home', 'code': 'Numpad7', 'shiftKey': '7', 'location': 3 }),
68
+ 'ArrowLeft': KeyDefinition.new({ 'keyCode': 37, 'code': 'ArrowLeft', 'key': 'ArrowLeft' }),
69
+ 'Numpad4': KeyDefinition.new({ 'keyCode': 37, 'shiftKeyCode': 100, 'key': 'ArrowLeft', 'code': 'Numpad4', 'shiftKey': '4', 'location': 3 }),
70
+ 'Numpad8': KeyDefinition.new({ 'keyCode': 38, 'shiftKeyCode': 104, 'key': 'ArrowUp', 'code': 'Numpad8', 'shiftKey': '8', 'location': 3 }),
71
+ 'ArrowUp': KeyDefinition.new({ 'keyCode': 38, 'code': 'ArrowUp', 'key': 'ArrowUp' }),
72
+ 'ArrowRight': KeyDefinition.new({ 'keyCode': 39, 'code': 'ArrowRight', 'key': 'ArrowRight' }),
73
+ 'Numpad6': KeyDefinition.new({ 'keyCode': 39, 'shiftKeyCode': 102, 'key': 'ArrowRight', 'code': 'Numpad6', 'shiftKey': '6', 'location': 3 }),
74
+ 'Numpad2': KeyDefinition.new({ 'keyCode': 40, 'shiftKeyCode': 98, 'key': 'ArrowDown', 'code': 'Numpad2', 'shiftKey': '2', 'location': 3 }),
75
+ 'ArrowDown': KeyDefinition.new({ 'keyCode': 40, 'code': 'ArrowDown', 'key': 'ArrowDown' }),
76
+ 'Select': KeyDefinition.new({ 'keyCode': 41, 'code': 'Select', 'key': 'Select' }),
77
+ 'Open': KeyDefinition.new({ 'keyCode': 43, 'code': 'Open', 'key': 'Execute' }),
78
+ 'PrintScreen': KeyDefinition.new({ 'keyCode': 44, 'code': 'PrintScreen', 'key': 'PrintScreen' }),
79
+ 'Insert': KeyDefinition.new({ 'keyCode': 45, 'code': 'Insert', 'key': 'Insert' }),
80
+ 'Numpad0': KeyDefinition.new({ 'keyCode': 45, 'shiftKeyCode': 96, 'key': 'Insert', 'code': 'Numpad0', 'shiftKey': '0', 'location': 3 }),
81
+ 'Delete': KeyDefinition.new({ 'keyCode': 46, 'code': 'Delete', 'key': 'Delete' }),
82
+ 'NumpadDecimal': KeyDefinition.new({ 'keyCode': 46, 'shiftKeyCode': 110, 'code': 'NumpadDecimal', 'key': '\u0000', 'shiftKey': '.', 'location': 3 }),
83
+ 'Digit0': KeyDefinition.new({ 'keyCode': 48, 'code': 'Digit0', 'shiftKey': ')', 'key': '0' }),
84
+ 'Digit1': KeyDefinition.new({ 'keyCode': 49, 'code': 'Digit1', 'shiftKey': '!', 'key': '1' }),
85
+ 'Digit2': KeyDefinition.new({ 'keyCode': 50, 'code': 'Digit2', 'shiftKey': '@', 'key': '2' }),
86
+ 'Digit3': KeyDefinition.new({ 'keyCode': 51, 'code': 'Digit3', 'shiftKey': '#', 'key': '3' }),
87
+ 'Digit4': KeyDefinition.new({ 'keyCode': 52, 'code': 'Digit4', 'shiftKey': '$', 'key': '4' }),
88
+ 'Digit5': KeyDefinition.new({ 'keyCode': 53, 'code': 'Digit5', 'shiftKey': '%', 'key': '5' }),
89
+ 'Digit6': KeyDefinition.new({ 'keyCode': 54, 'code': 'Digit6', 'shiftKey': '^', 'key': '6' }),
90
+ 'Digit7': KeyDefinition.new({ 'keyCode': 55, 'code': 'Digit7', 'shiftKey': '&', 'key': '7' }),
91
+ 'Digit8': KeyDefinition.new({ 'keyCode': 56, 'code': 'Digit8', 'shiftKey': '*', 'key': '8' }),
92
+ 'Digit9': KeyDefinition.new({ 'keyCode': 57, 'code': 'Digit9', 'shiftKey': '\(', 'key': '9' }),
93
+ 'KeyA': KeyDefinition.new({ 'keyCode': 65, 'code': 'KeyA', 'shiftKey': 'A', 'key': 'a' }),
94
+ 'KeyB': KeyDefinition.new({ 'keyCode': 66, 'code': 'KeyB', 'shiftKey': 'B', 'key': 'b' }),
95
+ 'KeyC': KeyDefinition.new({ 'keyCode': 67, 'code': 'KeyC', 'shiftKey': 'C', 'key': 'c' }),
96
+ 'KeyD': KeyDefinition.new({ 'keyCode': 68, 'code': 'KeyD', 'shiftKey': 'D', 'key': 'd' }),
97
+ 'KeyE': KeyDefinition.new({ 'keyCode': 69, 'code': 'KeyE', 'shiftKey': 'E', 'key': 'e' }),
98
+ 'KeyF': KeyDefinition.new({ 'keyCode': 70, 'code': 'KeyF', 'shiftKey': 'F', 'key': 'f' }),
99
+ 'KeyG': KeyDefinition.new({ 'keyCode': 71, 'code': 'KeyG', 'shiftKey': 'G', 'key': 'g' }),
100
+ 'KeyH': KeyDefinition.new({ 'keyCode': 72, 'code': 'KeyH', 'shiftKey': 'H', 'key': 'h' }),
101
+ 'KeyI': KeyDefinition.new({ 'keyCode': 73, 'code': 'KeyI', 'shiftKey': 'I', 'key': 'i' }),
102
+ 'KeyJ': KeyDefinition.new({ 'keyCode': 74, 'code': 'KeyJ', 'shiftKey': 'J', 'key': 'j' }),
103
+ 'KeyK': KeyDefinition.new({ 'keyCode': 75, 'code': 'KeyK', 'shiftKey': 'K', 'key': 'k' }),
104
+ 'KeyL': KeyDefinition.new({ 'keyCode': 76, 'code': 'KeyL', 'shiftKey': 'L', 'key': 'l' }),
105
+ 'KeyM': KeyDefinition.new({ 'keyCode': 77, 'code': 'KeyM', 'shiftKey': 'M', 'key': 'm' }),
106
+ 'KeyN': KeyDefinition.new({ 'keyCode': 78, 'code': 'KeyN', 'shiftKey': 'N', 'key': 'n' }),
107
+ 'KeyO': KeyDefinition.new({ 'keyCode': 79, 'code': 'KeyO', 'shiftKey': 'O', 'key': 'o' }),
108
+ 'KeyP': KeyDefinition.new({ 'keyCode': 80, 'code': 'KeyP', 'shiftKey': 'P', 'key': 'p' }),
109
+ 'KeyQ': KeyDefinition.new({ 'keyCode': 81, 'code': 'KeyQ', 'shiftKey': 'Q', 'key': 'q' }),
110
+ 'KeyR': KeyDefinition.new({ 'keyCode': 82, 'code': 'KeyR', 'shiftKey': 'R', 'key': 'r' }),
111
+ 'KeyS': KeyDefinition.new({ 'keyCode': 83, 'code': 'KeyS', 'shiftKey': 'S', 'key': 's' }),
112
+ 'KeyT': KeyDefinition.new({ 'keyCode': 84, 'code': 'KeyT', 'shiftKey': 'T', 'key': 't' }),
113
+ 'KeyU': KeyDefinition.new({ 'keyCode': 85, 'code': 'KeyU', 'shiftKey': 'U', 'key': 'u' }),
114
+ 'KeyV': KeyDefinition.new({ 'keyCode': 86, 'code': 'KeyV', 'shiftKey': 'V', 'key': 'v' }),
115
+ 'KeyW': KeyDefinition.new({ 'keyCode': 87, 'code': 'KeyW', 'shiftKey': 'W', 'key': 'w' }),
116
+ 'KeyX': KeyDefinition.new({ 'keyCode': 88, 'code': 'KeyX', 'shiftKey': 'X', 'key': 'x' }),
117
+ 'KeyY': KeyDefinition.new({ 'keyCode': 89, 'code': 'KeyY', 'shiftKey': 'Y', 'key': 'y' }),
118
+ 'KeyZ': KeyDefinition.new({ 'keyCode': 90, 'code': 'KeyZ', 'shiftKey': 'Z', 'key': 'z' }),
119
+ 'MetaLeft': KeyDefinition.new({ 'keyCode': 91, 'code': 'MetaLeft', 'key': 'Meta', 'location': 1 }),
120
+ 'MetaRight': KeyDefinition.new({ 'keyCode': 92, 'code': 'MetaRight', 'key': 'Meta', 'location': 2 }),
121
+ 'ContextMenu': KeyDefinition.new({ 'keyCode': 93, 'code': 'ContextMenu', 'key': 'ContextMenu' }),
122
+ 'NumpadMultiply': KeyDefinition.new({ 'keyCode': 106, 'code': 'NumpadMultiply', 'key': '*', 'location': 3 }),
123
+ 'NumpadAdd': KeyDefinition.new({ 'keyCode': 107, 'code': 'NumpadAdd', 'key': '+', 'location': 3 }),
124
+ 'NumpadSubtract': KeyDefinition.new({ 'keyCode': 109, 'code': 'NumpadSubtract', 'key': '-', 'location': 3 }),
125
+ 'NumpadDivide': KeyDefinition.new({ 'keyCode': 111, 'code': 'NumpadDivide', 'key': '/', 'location': 3 }),
126
+ 'F1': KeyDefinition.new({ 'keyCode': 112, 'code': 'F1', 'key': 'F1' }),
127
+ 'F2': KeyDefinition.new({ 'keyCode': 113, 'code': 'F2', 'key': 'F2' }),
128
+ 'F3': KeyDefinition.new({ 'keyCode': 114, 'code': 'F3', 'key': 'F3' }),
129
+ 'F4': KeyDefinition.new({ 'keyCode': 115, 'code': 'F4', 'key': 'F4' }),
130
+ 'F5': KeyDefinition.new({ 'keyCode': 116, 'code': 'F5', 'key': 'F5' }),
131
+ 'F6': KeyDefinition.new({ 'keyCode': 117, 'code': 'F6', 'key': 'F6' }),
132
+ 'F7': KeyDefinition.new({ 'keyCode': 118, 'code': 'F7', 'key': 'F7' }),
133
+ 'F8': KeyDefinition.new({ 'keyCode': 119, 'code': 'F8', 'key': 'F8' }),
134
+ 'F9': KeyDefinition.new({ 'keyCode': 120, 'code': 'F9', 'key': 'F9' }),
135
+ 'F10': KeyDefinition.new({ 'keyCode': 121, 'code': 'F10', 'key': 'F10' }),
136
+ 'F11': KeyDefinition.new({ 'keyCode': 122, 'code': 'F11', 'key': 'F11' }),
137
+ 'F12': KeyDefinition.new({ 'keyCode': 123, 'code': 'F12', 'key': 'F12' }),
138
+ 'F13': KeyDefinition.new({ 'keyCode': 124, 'code': 'F13', 'key': 'F13' }),
139
+ 'F14': KeyDefinition.new({ 'keyCode': 125, 'code': 'F14', 'key': 'F14' }),
140
+ 'F15': KeyDefinition.new({ 'keyCode': 126, 'code': 'F15', 'key': 'F15' }),
141
+ 'F16': KeyDefinition.new({ 'keyCode': 127, 'code': 'F16', 'key': 'F16' }),
142
+ 'F17': KeyDefinition.new({ 'keyCode': 128, 'code': 'F17', 'key': 'F17' }),
143
+ 'F18': KeyDefinition.new({ 'keyCode': 129, 'code': 'F18', 'key': 'F18' }),
144
+ 'F19': KeyDefinition.new({ 'keyCode': 130, 'code': 'F19', 'key': 'F19' }),
145
+ 'F20': KeyDefinition.new({ 'keyCode': 131, 'code': 'F20', 'key': 'F20' }),
146
+ 'F21': KeyDefinition.new({ 'keyCode': 132, 'code': 'F21', 'key': 'F21' }),
147
+ 'F22': KeyDefinition.new({ 'keyCode': 133, 'code': 'F22', 'key': 'F22' }),
148
+ 'F23': KeyDefinition.new({ 'keyCode': 134, 'code': 'F23', 'key': 'F23' }),
149
+ 'F24': KeyDefinition.new({ 'keyCode': 135, 'code': 'F24', 'key': 'F24' }),
150
+ 'NumLock': KeyDefinition.new({ 'keyCode': 144, 'code': 'NumLock', 'key': 'NumLock' }),
151
+ 'ScrollLock': KeyDefinition.new({ 'keyCode': 145, 'code': 'ScrollLock', 'key': 'ScrollLock' }),
152
+ 'AudioVolumeMute': KeyDefinition.new({ 'keyCode': 173, 'code': 'AudioVolumeMute', 'key': 'AudioVolumeMute' }),
153
+ 'AudioVolumeDown': KeyDefinition.new({ 'keyCode': 174, 'code': 'AudioVolumeDown', 'key': 'AudioVolumeDown' }),
154
+ 'AudioVolumeUp': KeyDefinition.new({ 'keyCode': 175, 'code': 'AudioVolumeUp', 'key': 'AudioVolumeUp' }),
155
+ 'MediaTrackNext': KeyDefinition.new({ 'keyCode': 176, 'code': 'MediaTrackNext', 'key': 'MediaTrackNext' }),
156
+ 'MediaTrackPrevious': KeyDefinition.new({ 'keyCode': 177, 'code': 'MediaTrackPrevious', 'key': 'MediaTrackPrevious' }),
157
+ 'MediaStop': KeyDefinition.new({ 'keyCode': 178, 'code': 'MediaStop', 'key': 'MediaStop' }),
158
+ 'MediaPlayPause': KeyDefinition.new({ 'keyCode': 179, 'code': 'MediaPlayPause', 'key': 'MediaPlayPause' }),
159
+ 'Semicolon': KeyDefinition.new({ 'keyCode': 186, 'code': 'Semicolon', 'shiftKey': ':', 'key': ';' }),
160
+ 'Equal': KeyDefinition.new({ 'keyCode': 187, 'code': 'Equal', 'shiftKey': '+', 'key': '=' }),
161
+ 'NumpadEqual': KeyDefinition.new({ 'keyCode': 187, 'code': 'NumpadEqual', 'key': '=', 'location': 3 }),
162
+ 'Comma': KeyDefinition.new({ 'keyCode': 188, 'code': 'Comma', 'shiftKey': '\<', 'key': ',' }),
163
+ 'Minus': KeyDefinition.new({ 'keyCode': 189, 'code': 'Minus', 'shiftKey': '_', 'key': '-' }),
164
+ 'Period': KeyDefinition.new({ 'keyCode': 190, 'code': 'Period', 'shiftKey': '>', 'key': '.' }),
165
+ 'Slash': KeyDefinition.new({ 'keyCode': 191, 'code': 'Slash', 'shiftKey': '?', 'key': '/' }),
166
+ 'Backquote': KeyDefinition.new({ 'keyCode': 192, 'code': 'Backquote', 'shiftKey': '~', 'key': '`' }),
167
+ 'BracketLeft': KeyDefinition.new({ 'keyCode': 219, 'code': 'BracketLeft', 'shiftKey': '{', 'key': '[' }),
168
+ 'Backslash': KeyDefinition.new({ 'keyCode': 220, 'code': 'Backslash', 'shiftKey': '|', 'key': '\\' }),
169
+ 'BracketRight': KeyDefinition.new({ 'keyCode': 221, 'code': 'BracketRight', 'shiftKey': '}', 'key': ']' }),
170
+ 'Quote': KeyDefinition.new({ 'keyCode': 222, 'code': 'Quote', 'shiftKey': '"', 'key': '\'' }),
171
+ 'AltGraph': KeyDefinition.new({ 'keyCode': 225, 'code': 'AltGraph', 'key': 'AltGraph' }),
172
+ 'Props': KeyDefinition.new({ 'keyCode': 247, 'code': 'Props', 'key': 'CrSel' }),
173
+ 'Cancel': KeyDefinition.new({ 'keyCode': 3, 'key': 'Cancel', 'code': 'Abort' }),
174
+ 'Clear': KeyDefinition.new({ 'keyCode': 12, 'key': 'Clear', 'code': 'Numpad5', 'location': 3 }),
175
+ 'Shift': KeyDefinition.new({ 'keyCode': 16, 'key': 'Shift', 'code': 'ShiftLeft', 'location': 1 }),
176
+ 'Control': KeyDefinition.new({ 'keyCode': 17, 'key': 'Control', 'code': 'ControlLeft', 'location': 1 }),
177
+ 'Alt': KeyDefinition.new({ 'keyCode': 18, 'key': 'Alt', 'code': 'AltLeft', 'location': 1 }),
178
+ 'Accept': KeyDefinition.new({ 'keyCode': 30, 'key': 'Accept' }),
179
+ 'ModeChange': KeyDefinition.new({ 'keyCode': 31, 'key': 'ModeChange' }),
180
+ ' ': KeyDefinition.new({ 'keyCode': 32, 'key': ' ', 'code': 'Space' }),
181
+ 'Print': KeyDefinition.new({ 'keyCode': 42, 'key': 'Print' }),
182
+ 'Execute': KeyDefinition.new({ 'keyCode': 43, 'key': 'Execute', 'code': 'Open' }),
183
+ '\u0000': KeyDefinition.new({ 'keyCode': 46, 'key': '\u0000', 'code': 'NumpadDecimal', 'location': 3 }),
184
+ 'a': KeyDefinition.new({ 'keyCode': 65, 'key': 'a', 'code': 'KeyA' }),
185
+ 'b': KeyDefinition.new({ 'keyCode': 66, 'key': 'b', 'code': 'KeyB' }),
186
+ 'c': KeyDefinition.new({ 'keyCode': 67, 'key': 'c', 'code': 'KeyC' }),
187
+ 'd': KeyDefinition.new({ 'keyCode': 68, 'key': 'd', 'code': 'KeyD' }),
188
+ 'e': KeyDefinition.new({ 'keyCode': 69, 'key': 'e', 'code': 'KeyE' }),
189
+ 'f': KeyDefinition.new({ 'keyCode': 70, 'key': 'f', 'code': 'KeyF' }),
190
+ 'g': KeyDefinition.new({ 'keyCode': 71, 'key': 'g', 'code': 'KeyG' }),
191
+ 'h': KeyDefinition.new({ 'keyCode': 72, 'key': 'h', 'code': 'KeyH' }),
192
+ 'i': KeyDefinition.new({ 'keyCode': 73, 'key': 'i', 'code': 'KeyI' }),
193
+ 'j': KeyDefinition.new({ 'keyCode': 74, 'key': 'j', 'code': 'KeyJ' }),
194
+ 'k': KeyDefinition.new({ 'keyCode': 75, 'key': 'k', 'code': 'KeyK' }),
195
+ 'l': KeyDefinition.new({ 'keyCode': 76, 'key': 'l', 'code': 'KeyL' }),
196
+ 'm': KeyDefinition.new({ 'keyCode': 77, 'key': 'm', 'code': 'KeyM' }),
197
+ 'n': KeyDefinition.new({ 'keyCode': 78, 'key': 'n', 'code': 'KeyN' }),
198
+ 'o': KeyDefinition.new({ 'keyCode': 79, 'key': 'o', 'code': 'KeyO' }),
199
+ 'p': KeyDefinition.new({ 'keyCode': 80, 'key': 'p', 'code': 'KeyP' }),
200
+ 'q': KeyDefinition.new({ 'keyCode': 81, 'key': 'q', 'code': 'KeyQ' }),
201
+ 'r': KeyDefinition.new({ 'keyCode': 82, 'key': 'r', 'code': 'KeyR' }),
202
+ 's': KeyDefinition.new({ 'keyCode': 83, 'key': 's', 'code': 'KeyS' }),
203
+ 't': KeyDefinition.new({ 'keyCode': 84, 'key': 't', 'code': 'KeyT' }),
204
+ 'u': KeyDefinition.new({ 'keyCode': 85, 'key': 'u', 'code': 'KeyU' }),
205
+ 'v': KeyDefinition.new({ 'keyCode': 86, 'key': 'v', 'code': 'KeyV' }),
206
+ 'w': KeyDefinition.new({ 'keyCode': 87, 'key': 'w', 'code': 'KeyW' }),
207
+ 'x': KeyDefinition.new({ 'keyCode': 88, 'key': 'x', 'code': 'KeyX' }),
208
+ 'y': KeyDefinition.new({ 'keyCode': 89, 'key': 'y', 'code': 'KeyY' }),
209
+ 'z': KeyDefinition.new({ 'keyCode': 90, 'key': 'z', 'code': 'KeyZ' }),
210
+ 'Meta': KeyDefinition.new({ 'keyCode': 91, 'key': 'Meta', 'code': 'MetaLeft', 'location': 1 }),
211
+ '*': KeyDefinition.new({ 'keyCode': 106, 'key': '*', 'code': 'NumpadMultiply', 'location': 3 }),
212
+ '+': KeyDefinition.new({ 'keyCode': 107, 'key': '+', 'code': 'NumpadAdd', 'location': 3 }),
213
+ '-': KeyDefinition.new({ 'keyCode': 109, 'key': '-', 'code': 'NumpadSubtract', 'location': 3 }),
214
+ '/': KeyDefinition.new({ 'keyCode': 111, 'key': '/', 'code': 'NumpadDivide', 'location': 3 }),
215
+ ';': KeyDefinition.new({ 'keyCode': 186, 'key': ';', 'code': 'Semicolon' }),
216
+ '=': KeyDefinition.new({ 'keyCode': 187, 'key': '=', 'code': 'Equal' }),
217
+ ',': KeyDefinition.new({ 'keyCode': 188, 'key': ',', 'code': 'Comma' }),
218
+ '.': KeyDefinition.new({ 'keyCode': 190, 'key': '.', 'code': 'Period' }),
219
+ '`': KeyDefinition.new({ 'keyCode': 192, 'key': '`', 'code': 'Backquote' }),
220
+ '[': KeyDefinition.new({ 'keyCode': 219, 'key': '[', 'code': 'BracketLeft' }),
221
+ '\\': KeyDefinition.new({ 'keyCode': 220, 'key': '\\', 'code': 'Backslash' }),
222
+ ']': KeyDefinition.new({ 'keyCode': 221, 'key': ']', 'code': 'BracketRight' }),
223
+ '\'': KeyDefinition.new({ 'keyCode': 222, 'key': '\'', 'code': 'Quote' }),
224
+ 'Attn': KeyDefinition.new({ 'keyCode': 246, 'key': 'Attn' }),
225
+ 'CrSel': KeyDefinition.new({ 'keyCode': 247, 'key': 'CrSel', 'code': 'Props' }),
226
+ 'ExSel': KeyDefinition.new({ 'keyCode': 248, 'key': 'ExSel' }),
227
+ 'EraseEof': KeyDefinition.new({ 'keyCode': 249, 'key': 'EraseEof' }),
228
+ 'Play': KeyDefinition.new({ 'keyCode': 250, 'key': 'Play' }),
229
+ 'ZoomOut': KeyDefinition.new({ 'keyCode': 251, 'key': 'ZoomOut' }),
230
+ ')': KeyDefinition.new({ 'keyCode': 48, 'key': ')', 'code': 'Digit0' }),
231
+ '!': KeyDefinition.new({ 'keyCode': 49, 'key': '!', 'code': 'Digit1' }),
232
+ '@': KeyDefinition.new({ 'keyCode': 50, 'key': '@', 'code': 'Digit2' }),
233
+ '#': KeyDefinition.new({ 'keyCode': 51, 'key': '#', 'code': 'Digit3' }),
234
+ '$': KeyDefinition.new({ 'keyCode': 52, 'key': '$', 'code': 'Digit4' }),
235
+ '%': KeyDefinition.new({ 'keyCode': 53, 'key': '%', 'code': 'Digit5' }),
236
+ '^': KeyDefinition.new({ 'keyCode': 54, 'key': '^', 'code': 'Digit6' }),
237
+ '&': KeyDefinition.new({ 'keyCode': 55, 'key': '&', 'code': 'Digit7' }),
238
+ '(': KeyDefinition.new({ 'keyCode': 57, 'key': '\(', 'code': 'Digit9' }),
239
+ 'A': KeyDefinition.new({ 'keyCode': 65, 'key': 'A', 'code': 'KeyA' }),
240
+ 'B': KeyDefinition.new({ 'keyCode': 66, 'key': 'B', 'code': 'KeyB' }),
241
+ 'C': KeyDefinition.new({ 'keyCode': 67, 'key': 'C', 'code': 'KeyC' }),
242
+ 'D': KeyDefinition.new({ 'keyCode': 68, 'key': 'D', 'code': 'KeyD' }),
243
+ 'E': KeyDefinition.new({ 'keyCode': 69, 'key': 'E', 'code': 'KeyE' }),
244
+ 'F': KeyDefinition.new({ 'keyCode': 70, 'key': 'F', 'code': 'KeyF' }),
245
+ 'G': KeyDefinition.new({ 'keyCode': 71, 'key': 'G', 'code': 'KeyG' }),
246
+ 'H': KeyDefinition.new({ 'keyCode': 72, 'key': 'H', 'code': 'KeyH' }),
247
+ 'I': KeyDefinition.new({ 'keyCode': 73, 'key': 'I', 'code': 'KeyI' }),
248
+ 'J': KeyDefinition.new({ 'keyCode': 74, 'key': 'J', 'code': 'KeyJ' }),
249
+ 'K': KeyDefinition.new({ 'keyCode': 75, 'key': 'K', 'code': 'KeyK' }),
250
+ 'L': KeyDefinition.new({ 'keyCode': 76, 'key': 'L', 'code': 'KeyL' }),
251
+ 'M': KeyDefinition.new({ 'keyCode': 77, 'key': 'M', 'code': 'KeyM' }),
252
+ 'N': KeyDefinition.new({ 'keyCode': 78, 'key': 'N', 'code': 'KeyN' }),
253
+ 'O': KeyDefinition.new({ 'keyCode': 79, 'key': 'O', 'code': 'KeyO' }),
254
+ 'P': KeyDefinition.new({ 'keyCode': 80, 'key': 'P', 'code': 'KeyP' }),
255
+ 'Q': KeyDefinition.new({ 'keyCode': 81, 'key': 'Q', 'code': 'KeyQ' }),
256
+ 'R': KeyDefinition.new({ 'keyCode': 82, 'key': 'R', 'code': 'KeyR' }),
257
+ 'S': KeyDefinition.new({ 'keyCode': 83, 'key': 'S', 'code': 'KeyS' }),
258
+ 'T': KeyDefinition.new({ 'keyCode': 84, 'key': 'T', 'code': 'KeyT' }),
259
+ 'U': KeyDefinition.new({ 'keyCode': 85, 'key': 'U', 'code': 'KeyU' }),
260
+ 'V': KeyDefinition.new({ 'keyCode': 86, 'key': 'V', 'code': 'KeyV' }),
261
+ 'W': KeyDefinition.new({ 'keyCode': 87, 'key': 'W', 'code': 'KeyW' }),
262
+ 'X': KeyDefinition.new({ 'keyCode': 88, 'key': 'X', 'code': 'KeyX' }),
263
+ 'Y': KeyDefinition.new({ 'keyCode': 89, 'key': 'Y', 'code': 'KeyY' }),
264
+ 'Z': KeyDefinition.new({ 'keyCode': 90, 'key': 'Z', 'code': 'KeyZ' }),
265
+ ':': KeyDefinition.new({ 'keyCode': 186, 'key': ':', 'code': 'Semicolon' }),
266
+ '<': KeyDefinition.new({ 'keyCode': 188, 'key': '\<', 'code': 'Comma' }),
267
+ '_': KeyDefinition.new({ 'keyCode': 189, 'key': '_', 'code': 'Minus' }),
268
+ '>': KeyDefinition.new({ 'keyCode': 190, 'key': '>', 'code': 'Period' }),
269
+ '?': KeyDefinition.new({ 'keyCode': 191, 'key': '?', 'code': 'Slash' }),
270
+ '~': KeyDefinition.new({ 'keyCode': 192, 'key': '~', 'code': 'Backquote' }),
271
+ '{': KeyDefinition.new({ 'keyCode': 219, 'key': '{', 'code': 'BracketLeft' }),
272
+ '|': KeyDefinition.new({ 'keyCode': 220, 'key': '|', 'code': 'Backslash' }),
273
+ '}': KeyDefinition.new({ 'keyCode': 221, 'key': '}', 'code': 'BracketRight' }),
274
+ '"': KeyDefinition.new({ 'keyCode': 222, 'key': '"', 'code': 'Quote' }),
275
+ 'SoftLeft': KeyDefinition.new({ 'key': 'SoftLeft', 'code': 'SoftLeft', 'location': 4 }),
276
+ 'SoftRight': KeyDefinition.new({ 'key': 'SoftRight', 'code': 'SoftRight', 'location': 4 }),
277
+ 'Camera': KeyDefinition.new({ 'keyCode': 44, 'key': 'Camera', 'code': 'Camera', 'location': 4 }),
278
+ 'Call': KeyDefinition.new({ 'key': 'Call', 'code': 'Call', 'location': 4 }),
279
+ 'EndCall': KeyDefinition.new({ 'keyCode': 95, 'key': 'EndCall', 'code': 'EndCall', 'location': 4 }),
280
+ 'VolumeDown': KeyDefinition.new({ 'keyCode': 182, 'key': 'VolumeDown', 'code': 'VolumeDown', 'location': 4 }),
281
+ 'VolumeUp': KeyDefinition.new({ 'keyCode': 183, 'key': 'VolumeUp', 'code': 'VolumeUp', 'location': 4 }),
282
+ }
283
+ end