input.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.keypadLocation = exports.Touchscreen = exports.Mouse = exports.Keyboard = void 0;
  6. var _utils = require("../utils");
  7. var keyboardLayout = _interopRequireWildcard(require("./usKeyboardLayout"));
  8. function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
  9. function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  10. /**
  11. * Copyright (c) Microsoft Corporation.
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License");
  14. * you may not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS,
  21. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. */
  25. const keypadLocation = exports.keypadLocation = keyboardLayout.keypadLocation;
  26. const kModifiers = ['Alt', 'Control', 'Meta', 'Shift'];
  27. class Keyboard {
  28. constructor(raw, page) {
  29. this._pressedModifiers = new Set();
  30. this._pressedKeys = new Set();
  31. this._raw = void 0;
  32. this._page = void 0;
  33. this._raw = raw;
  34. this._page = page;
  35. }
  36. async down(key) {
  37. const description = this._keyDescriptionForString(key);
  38. const autoRepeat = this._pressedKeys.has(description.code);
  39. this._pressedKeys.add(description.code);
  40. if (kModifiers.includes(description.key)) this._pressedModifiers.add(description.key);
  41. const text = description.text;
  42. await this._raw.keydown(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location, autoRepeat, text);
  43. }
  44. _keyDescriptionForString(keyString) {
  45. let description = usKeyboardLayout.get(keyString);
  46. (0, _utils.assert)(description, `Unknown key: "${keyString}"`);
  47. const shift = this._pressedModifiers.has('Shift');
  48. description = shift && description.shifted ? description.shifted : description;
  49. // if any modifiers besides shift are pressed, no text should be sent
  50. if (this._pressedModifiers.size > 1 || !this._pressedModifiers.has('Shift') && this._pressedModifiers.size === 1) return {
  51. ...description,
  52. text: ''
  53. };
  54. return description;
  55. }
  56. async up(key) {
  57. const description = this._keyDescriptionForString(key);
  58. if (kModifiers.includes(description.key)) this._pressedModifiers.delete(description.key);
  59. this._pressedKeys.delete(description.code);
  60. await this._raw.keyup(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location);
  61. }
  62. async insertText(text) {
  63. await this._raw.sendText(text);
  64. }
  65. async type(text, options) {
  66. const delay = options && options.delay || undefined;
  67. for (const char of text) {
  68. if (usKeyboardLayout.has(char)) {
  69. await this.press(char, {
  70. delay
  71. });
  72. } else {
  73. if (delay) await new Promise(f => setTimeout(f, delay));
  74. await this.insertText(char);
  75. }
  76. }
  77. }
  78. async press(key, options = {}) {
  79. function split(keyString) {
  80. const keys = [];
  81. let building = '';
  82. for (const char of keyString) {
  83. if (char === '+' && building) {
  84. keys.push(building);
  85. building = '';
  86. } else {
  87. building += char;
  88. }
  89. }
  90. keys.push(building);
  91. return keys;
  92. }
  93. const tokens = split(key);
  94. key = tokens[tokens.length - 1];
  95. for (let i = 0; i < tokens.length - 1; ++i) await this.down(tokens[i]);
  96. await this.down(key);
  97. if (options.delay) await new Promise(f => setTimeout(f, options.delay));
  98. await this.up(key);
  99. for (let i = tokens.length - 2; i >= 0; --i) await this.up(tokens[i]);
  100. }
  101. async _ensureModifiers(modifiers) {
  102. for (const modifier of modifiers) {
  103. if (!kModifiers.includes(modifier)) throw new Error('Unknown modifier ' + modifier);
  104. }
  105. const restore = Array.from(this._pressedModifiers);
  106. for (const key of kModifiers) {
  107. const needDown = modifiers.includes(key);
  108. const isDown = this._pressedModifiers.has(key);
  109. if (needDown && !isDown) await this.down(key);else if (!needDown && isDown) await this.up(key);
  110. }
  111. return restore;
  112. }
  113. _modifiers() {
  114. return this._pressedModifiers;
  115. }
  116. }
  117. exports.Keyboard = Keyboard;
  118. class Mouse {
  119. constructor(raw, page) {
  120. this._keyboard = void 0;
  121. this._x = 0;
  122. this._y = 0;
  123. this._lastButton = 'none';
  124. this._buttons = new Set();
  125. this._raw = void 0;
  126. this._page = void 0;
  127. this._raw = raw;
  128. this._page = page;
  129. this._keyboard = this._page.keyboard;
  130. }
  131. async move(x, y, options = {}, metadata) {
  132. if (metadata) metadata.point = {
  133. x,
  134. y
  135. };
  136. const {
  137. steps = 1
  138. } = options;
  139. const fromX = this._x;
  140. const fromY = this._y;
  141. this._x = x;
  142. this._y = y;
  143. for (let i = 1; i <= steps; i++) {
  144. const middleX = fromX + (x - fromX) * (i / steps);
  145. const middleY = fromY + (y - fromY) * (i / steps);
  146. await this._raw.move(middleX, middleY, this._lastButton, this._buttons, this._keyboard._modifiers(), !!options.forClick);
  147. }
  148. }
  149. async down(options = {}, metadata) {
  150. if (metadata) metadata.point = {
  151. x: this._x,
  152. y: this._y
  153. };
  154. const {
  155. button = 'left',
  156. clickCount = 1
  157. } = options;
  158. this._lastButton = button;
  159. this._buttons.add(button);
  160. await this._raw.down(this._x, this._y, this._lastButton, this._buttons, this._keyboard._modifiers(), clickCount);
  161. }
  162. async up(options = {}, metadata) {
  163. if (metadata) metadata.point = {
  164. x: this._x,
  165. y: this._y
  166. };
  167. const {
  168. button = 'left',
  169. clickCount = 1
  170. } = options;
  171. this._lastButton = 'none';
  172. this._buttons.delete(button);
  173. await this._raw.up(this._x, this._y, button, this._buttons, this._keyboard._modifiers(), clickCount);
  174. }
  175. async click(x, y, options = {}, metadata) {
  176. if (metadata) metadata.point = {
  177. x: this._x,
  178. y: this._y
  179. };
  180. const {
  181. delay = null,
  182. clickCount = 1
  183. } = options;
  184. if (delay) {
  185. this.move(x, y, {
  186. forClick: true
  187. });
  188. for (let cc = 1; cc <= clickCount; ++cc) {
  189. await this.down({
  190. ...options,
  191. clickCount: cc
  192. });
  193. await new Promise(f => setTimeout(f, delay));
  194. await this.up({
  195. ...options,
  196. clickCount: cc
  197. });
  198. if (cc < clickCount) await new Promise(f => setTimeout(f, delay));
  199. }
  200. } else {
  201. const promises = [];
  202. promises.push(this.move(x, y, {
  203. forClick: true
  204. }));
  205. for (let cc = 1; cc <= clickCount; ++cc) {
  206. promises.push(this.down({
  207. ...options,
  208. clickCount: cc
  209. }));
  210. promises.push(this.up({
  211. ...options,
  212. clickCount: cc
  213. }));
  214. }
  215. await Promise.all(promises);
  216. }
  217. }
  218. async dblclick(x, y, options = {}) {
  219. await this.click(x, y, {
  220. ...options,
  221. clickCount: 2
  222. });
  223. }
  224. async wheel(deltaX, deltaY) {
  225. await this._raw.wheel(this._x, this._y, this._buttons, this._keyboard._modifiers(), deltaX, deltaY);
  226. }
  227. }
  228. exports.Mouse = Mouse;
  229. const aliases = new Map([['ShiftLeft', ['Shift']], ['ControlLeft', ['Control']], ['AltLeft', ['Alt']], ['MetaLeft', ['Meta']], ['Enter', ['\n', '\r']]]);
  230. const usKeyboardLayout = buildLayoutClosure(keyboardLayout.USKeyboardLayout);
  231. function buildLayoutClosure(layout) {
  232. const result = new Map();
  233. for (const code in layout) {
  234. const definition = layout[code];
  235. const description = {
  236. key: definition.key || '',
  237. keyCode: definition.keyCode || 0,
  238. keyCodeWithoutLocation: definition.keyCodeWithoutLocation || definition.keyCode || 0,
  239. code,
  240. text: definition.text || '',
  241. location: definition.location || 0
  242. };
  243. if (definition.key.length === 1) description.text = description.key;
  244. // Generate shifted definition.
  245. let shiftedDescription;
  246. if (definition.shiftKey) {
  247. (0, _utils.assert)(definition.shiftKey.length === 1);
  248. shiftedDescription = {
  249. ...description
  250. };
  251. shiftedDescription.key = definition.shiftKey;
  252. shiftedDescription.text = definition.shiftKey;
  253. if (definition.shiftKeyCode) shiftedDescription.keyCode = definition.shiftKeyCode;
  254. }
  255. // Map from code: Digit3 -> { ... descrption, shifted }
  256. result.set(code, {
  257. ...description,
  258. shifted: shiftedDescription
  259. });
  260. // Map from aliases: Shift -> non-shiftable definition
  261. if (aliases.has(code)) {
  262. for (const alias of aliases.get(code)) result.set(alias, description);
  263. }
  264. // Do not use numpad when converting keys to codes.
  265. if (definition.location) continue;
  266. // Map from key, no shifted
  267. if (description.key.length === 1) result.set(description.key, description);
  268. // Map from shiftKey, no shifted
  269. if (shiftedDescription) result.set(shiftedDescription.key, {
  270. ...shiftedDescription,
  271. shifted: undefined
  272. });
  273. }
  274. return result;
  275. }
  276. class Touchscreen {
  277. constructor(raw, page) {
  278. this._raw = void 0;
  279. this._page = void 0;
  280. this._raw = raw;
  281. this._page = page;
  282. }
  283. async tap(x, y, metadata) {
  284. if (metadata) metadata.point = {
  285. x,
  286. y
  287. };
  288. if (!this._page._browserContext._options.hasTouch) throw new Error('hasTouch must be enabled on the browser context before using the touchscreen.');
  289. await this._raw.tap(x, y, this._page.keyboard._modifiers());
  290. }
  291. }
  292. exports.Touchscreen = Touchscreen;