chore: move Mouse to common input with RawMouseImpl per vendor (#73)

This commit is contained in:
Dmitry Gozman 2019-11-26 07:52:55 -08:00 committed by Pavel Feldman
parent cc9b58878b
commit 432116ba80
10 changed files with 168 additions and 227 deletions

View File

@ -69,69 +69,42 @@ export class RawKeyboardImpl implements input.RawKeyboard {
}
}
export class Mouse implements input.MouseOperations {
export class RawMouseImpl implements input.RawMouse {
private _client: CDPSession;
private _keyboard: input.Keyboard;
private _x = 0;
private _y = 0;
private _button: 'none' | input.Button = 'none';
constructor(client: CDPSession, keyboard: input.Keyboard) {
constructor(client: CDPSession) {
this._client = client;
this._keyboard = keyboard;
}
async move(x: number, y: number, options: { steps?: number; } = {}) {
const {steps = 1} = options;
const fromX = this._x, fromY = this._y;
this._x = x;
this._y = y;
for (let i = 1; i <= steps; i++) {
await this._client.send('Input.dispatchMouseEvent', {
type: 'mouseMoved',
button: this._button,
x: fromX + (this._x - fromX) * (i / steps),
y: fromY + (this._y - fromY) * (i / steps),
modifiers: toModifiersMask(this._keyboard._modifiers())
});
}
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', {
type: 'mouseMoved',
button,
x,
y,
modifiers: toModifiersMask(modifiers)
});
}
async down(options: { button?: input.Button; clickCount?: number; } = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = button;
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', {
type: 'mousePressed',
button,
x: this._x,
y: this._y,
modifiers: toModifiersMask(this._keyboard._modifiers()),
x,
y,
modifiers: toModifiersMask(modifiers),
clickCount
});
}
async up(options: { button?: input.Button; clickCount?: number; } = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = 'none';
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', {
type: 'mouseReleased',
button,
x: this._x,
y: this._y,
modifiers: toModifiersMask(this._keyboard._modifiers()),
x,
y,
modifiers: toModifiersMask(modifiers),
clickCount
});
}
async click(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).click(x, y, options);
}
async dblclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).dblclick(x, y, options);
}
async tripleclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).tripleclick(x, y, options);
}
}

View File

@ -36,7 +36,7 @@ import { PDF } from './features/pdf';
import { Workers } from './features/workers';
import { Frame } from './Frame';
import { FrameManager, FrameManagerEvents } from './FrameManager';
import { Mouse, RawKeyboardImpl } from './Input';
import { RawMouseImpl, RawKeyboardImpl } from './Input';
import { createJSHandle, ElementHandle, JSHandle } from './JSHandle';
import { NetworkManagerEvents, Response } from './NetworkManager';
import { Protocol } from './protocol';
@ -62,7 +62,7 @@ export class Page extends EventEmitter {
_client: CDPSession;
private _target: Target;
private _keyboard: input.Keyboard;
private _mouse: Mouse;
private _mouse: input.Mouse;
private _timeoutSettings: TimeoutSettings;
private _frameManager: FrameManager;
private _emulationManager: EmulationManager;
@ -94,7 +94,7 @@ export class Page extends EventEmitter {
this._client = client;
this._target = target;
this._keyboard = new input.Keyboard(new RawKeyboardImpl(client));
this._mouse = new Mouse(client, this._keyboard);
this._mouse = new input.Mouse(new RawMouseImpl(client), this._keyboard);
this._timeoutSettings = new TimeoutSettings();
this.accessibility = new Accessibility(client);
this._frameManager = new FrameManager(client, this, ignoreHTTPSErrors, this._timeoutSettings);
@ -680,7 +680,7 @@ export class Page extends EventEmitter {
return this._closed;
}
get mouse(): Mouse {
get mouse(): input.Mouse {
return this._mouse;
}

View File

@ -17,8 +17,7 @@ export { PDF } from './features/pdf';
export { Permissions } from './features/permissions';
export { Worker, Workers } from './features/workers';
export { Frame } from './Frame';
export { Mouse } from './Input';
export { Keyboard } from '../input';
export { Keyboard, Mouse } from '../input';
export { ElementHandle, JSHandle } from './JSHandle';
export { Request, Response } from './NetworkManager';
export { ConsoleMessage, FileChooser, Page } from './Page';

View File

@ -31,6 +31,26 @@ function toModifiersMask(modifiers: Set<input.Modifier>): number {
return mask;
}
function toButtonNumber(button: input.Button): number {
if (button === 'left')
return 0;
if (button === 'middle')
return 1;
if (button === 'right')
return 2;
}
function toButtonsMask(buttons: Set<input.Button>): number {
let mask = 0;
if (buttons.has('left'))
mask |= 1;
if (buttons.has('right'))
mask |= 2;
if (buttons.has('middle'))
mask |= 4;
return mask;
}
export class RawKeyboardImpl implements input.RawKeyboard {
private _client: JugglerSession;
@ -73,100 +93,45 @@ export class RawKeyboardImpl implements input.RawKeyboard {
}
}
export class Mouse implements input.MouseOperations {
_client: JugglerSession;
_keyboard: input.Keyboard;
_x: number;
_y: number;
_buttons: number;
export class RawMouseImpl implements input.RawMouse {
private _client: JugglerSession;
constructor(client: JugglerSession, keyboard: input.Keyboard) {
constructor(client: JugglerSession) {
this._client = client;
this._keyboard = keyboard;
this._x = 0;
this._y = 0;
this._buttons = 0;
}
async move(x: number, y: number, options: { steps?: number; } | undefined = {}) {
const {steps = 1} = options;
const fromX = this._x, fromY = this._y;
this._x = x;
this._y = y;
for (let i = 1; i <= steps; i++) {
await this._client.send('Page.dispatchMouseEvent', {
type: 'mousemove',
button: 0,
x: fromX + (this._x - fromX) * (i / steps),
y: fromY + (this._y - fromY) * (i / steps),
modifiers: toModifiersMask(this._keyboard._modifiers()),
buttons: this._buttons,
});
}
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> {
await this._client.send('Page.dispatchMouseEvent', {
type: 'mousemove',
button: 0,
buttons: toButtonsMask(buttons),
x,
y,
modifiers: toModifiersMask(modifiers)
});
}
async down(options: { button?: string; clickCount?: number; } | undefined = {}) {
const {
button = 'left',
clickCount = 1
} = options;
if (button === 'left')
this._buttons |= 1;
if (button === 'right')
this._buttons |= 2;
if (button === 'middle')
this._buttons |= 4;
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
await this._client.send('Page.dispatchMouseEvent', {
type: 'mousedown',
button: this._buttonNameToButton(button),
x: this._x,
y: this._y,
modifiers: toModifiersMask(this._keyboard._modifiers()),
clickCount,
buttons: this._buttons,
button: toButtonNumber(button),
buttons: toButtonsMask(buttons),
x,
y,
modifiers: toModifiersMask(modifiers),
clickCount
});
}
_buttonNameToButton(buttonName: string): number {
if (buttonName === 'left')
return 0;
if (buttonName === 'middle')
return 1;
if (buttonName === 'right')
return 2;
}
async up(options: { button?: string; clickCount?: number; } | undefined = {}) {
const {
button = 'left',
clickCount = 1
} = options;
if (button === 'left')
this._buttons &= ~1;
if (button === 'right')
this._buttons &= ~2;
if (button === 'middle')
this._buttons &= ~4;
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
await this._client.send('Page.dispatchMouseEvent', {
type: 'mouseup',
button: this._buttonNameToButton(button),
x: this._x,
y: this._y,
modifiers: toModifiersMask(this._keyboard._modifiers()),
clickCount: clickCount,
buttons: this._buttons,
button: toButtonNumber(button),
buttons: toButtonsMask(buttons),
x,
y,
modifiers: toModifiersMask(modifiers),
clickCount
});
}
async click(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).click(x, y, options);
}
async dblclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).dblclick(x, y, options);
}
async tripleclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).tripleclick(x, y, options);
}
}

View File

@ -11,7 +11,7 @@ import { Events } from './events';
import { Accessibility } from './features/accessibility';
import { Interception } from './features/interception';
import { FrameManager, FrameManagerEvents, normalizeWaitUntil, Frame } from './FrameManager';
import { Mouse, RawKeyboardImpl } from './Input';
import { RawMouseImpl, RawKeyboardImpl } from './Input';
import { createHandle, ElementHandle, JSHandle } from './JSHandle';
import { NavigationWatchdog } from './NavigationWatchdog';
import { NetworkManager, NetworkManagerEvents, Request, Response } from './NetworkManager';
@ -25,7 +25,7 @@ export class Page extends EventEmitter {
private _session: JugglerSession;
private _target: Target;
private _keyboard: input.Keyboard;
private _mouse: Mouse;
private _mouse: input.Mouse;
readonly accessibility: Accessibility;
readonly interception: Interception;
private _closed: boolean;
@ -60,7 +60,7 @@ export class Page extends EventEmitter {
this._session = session;
this._target = target;
this._keyboard = new input.Keyboard(new RawKeyboardImpl(session));
this._mouse = new Mouse(session, this._keyboard);
this._mouse = new input.Mouse(new RawMouseImpl(session), this._keyboard);
this.accessibility = new Accessibility(session);
this._closed = false;
this._pageBindings = new Map();
@ -348,7 +348,7 @@ export class Page extends EventEmitter {
return this._keyboard;
}
get mouse(){
get mouse(): input.Mouse {
return this._mouse;
}

View File

@ -10,8 +10,7 @@ export { Accessibility } from './features/accessibility';
export { Interception } from './features/interception';
export { Permissions } from './features/permissions';
export { Frame } from './FrameManager';
export { Mouse } from './Input';
export { Keyboard } from '../input';
export { Mouse, Keyboard } from '../input';
export { ElementHandle, JSHandle } from './JSHandle';
export { Request, Response } from './NetworkManager';
export { ConsoleMessage, Page } from './Page';

View File

@ -172,33 +172,66 @@ export class Keyboard {
}
}
export interface MouseOperations {
move(x: number, y: number, options?: { steps?: number; }): Promise<void>;
down(options?: { button?: Button; clickCount?: number; }): Promise<void>;
up(options?: { button?: Button; clickCount?: number; }): Promise<void>;
export interface RawMouse {
move(x: number, y: number, button: Button | 'none', buttons: Set<Button>, modifiers: Set<Modifier>): Promise<void>;
down(x: number, y: number, button: Button, buttons: Set<Button>, modifiers: Set<Modifier>, clickCount: number): Promise<void>;
up(x: number, y: number, button: Button, buttons: Set<Button>, modifiers: Set<Modifier>, clickCount: number): Promise<void>;
}
export class MouseClicker {
private _operations: MouseOperations;
export class Mouse {
private _raw: RawMouse;
private _keyboard: Keyboard;
private _x = 0;
private _y = 0;
private _lastButton: 'none' | Button = 'none';
private _buttons = new Set<Button>();
constructor(operations: MouseOperations) {
this._operations = operations;
constructor(raw: RawMouse, keyboard: Keyboard) {
this._raw = raw;
this._keyboard = keyboard;
}
async move(x: number, y: number, options: { steps?: number } = {}) {
const { steps = 1 } = options;
const fromX = this._x;
const fromY = this._y;
this._x = x;
this._y = y;
for (let i = 1; i <= steps; i++) {
const middleX = fromX + (x - fromX) * (i / steps);
const middleY = fromY + (y - fromY) * (i / steps);
await this._raw.move(middleX, middleY, this._lastButton, this._buttons, this._keyboard._modifiers());
}
}
async down(options: { button?: Button, clickCount?: number } = {}) {
const { button = 'left', clickCount = 1 } = options;
this._lastButton = button;
this._buttons.add(button);
await this._raw.down(this._x, this._y, this._lastButton, this._buttons, this._keyboard._modifiers(), clickCount);
}
async up(options: { button?: Button, clickCount?: number } = {}) {
const { button = 'left', clickCount = 1 } = options;
this._lastButton = 'none';
this._buttons.delete(button);
await this._raw.up(this._x, this._y, button, this._buttons, this._keyboard._modifiers(), clickCount);
}
async click(x: number, y: number, options: ClickOptions = {}) {
const {delay = null} = options;
if (delay !== null) {
await Promise.all([
this._operations.move(x, y),
this._operations.down(options),
this.move(x, y),
this.down(options),
]);
await new Promise(f => setTimeout(f, delay));
await this._operations.up(options);
await this.up(options);
} else {
await Promise.all([
this._operations.move(x, y),
this._operations.down(options),
this._operations.up(options),
this.move(x, y),
this.down(options),
this.up(options),
]);
}
}
@ -206,21 +239,21 @@ export class MouseClicker {
async dblclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this._operations.move(x, y);
await this._operations.down({ ...options, clickCount: 1 });
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 1 });
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.down({ ...options, clickCount: 2 });
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 2 });
await this.up({ ...options, clickCount: 2 });
} else {
await Promise.all([
this._operations.move(x, y),
this._operations.down({ ...options, clickCount: 1 }),
this._operations.up({ ...options, clickCount: 1 }),
this._operations.down({ ...options, clickCount: 2 }),
this._operations.up({ ...options, clickCount: 2 }),
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
]);
}
}
@ -228,27 +261,27 @@ export class MouseClicker {
async tripleclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this._operations.move(x, y);
await this._operations.down({ ...options, clickCount: 1 });
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 1 });
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.down({ ...options, clickCount: 2 });
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 2 });
await this.up({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this._operations.down({ ...options, clickCount: 3 });
await this.down({ ...options, clickCount: 3 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 3 });
await this.up({ ...options, clickCount: 3 });
} else {
await Promise.all([
this._operations.move(x, y),
this._operations.down({ ...options, clickCount: 1 }),
this._operations.up({ ...options, clickCount: 1 }),
this._operations.down({ ...options, clickCount: 2 }),
this._operations.up({ ...options, clickCount: 2 }),
this._operations.down({ ...options, clickCount: 3 }),
this._operations.up({ ...options, clickCount: 3 }),
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
this.down({ ...options, clickCount: 3 }),
this.up({ ...options, clickCount: 3 }),
]);
}
}

View File

@ -69,69 +69,42 @@ export class RawKeyboardImpl implements input.RawKeyboard {
}
}
export class Mouse implements input.MouseOperations {
export class RawMouseImpl implements input.RawMouse {
private _client: TargetSession;
private _keyboard: input.Keyboard;
private _x = 0;
private _y = 0;
private _button: 'none' | input.Button = 'none';
constructor(client: TargetSession, keyboard: input.Keyboard) {
constructor(client: TargetSession) {
this._client = client;
this._keyboard = keyboard;
}
async move(x: number, y: number, options: { steps?: number; } = {}) {
const {steps = 1} = options;
const fromX = this._x, fromY = this._y;
this._x = x;
this._y = y;
for (let i = 1; i <= steps; i++) {
await this._client.send('Input.dispatchMouseEvent', {
type: 'move',
button: this._button,
x: fromX + (this._x - fromX) * (i / steps),
y: fromY + (this._y - fromY) * (i / steps),
modifiers: toModifiersMask(this._keyboard._modifiers())
});
}
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', {
type: 'move',
button,
x,
y,
modifiers: toModifiersMask(modifiers)
});
}
async down(options: { button?: input.Button; clickCount?: number; } = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = button;
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', {
type: 'down',
button,
x: this._x,
y: this._y,
modifiers: toModifiersMask(this._keyboard._modifiers()),
x,
y,
modifiers: toModifiersMask(modifiers),
clickCount
});
}
async up(options: { button?: input.Button; clickCount?: number; } = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = 'none';
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', {
type: 'up',
button,
x: this._x,
y: this._y,
modifiers: toModifiersMask(this._keyboard._modifiers()),
x,
y,
modifiers: toModifiersMask(modifiers),
clickCount
});
}
async click(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).click(x, y, options);
}
async dblclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).dblclick(x, y, options);
}
async tripleclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).tripleclick(x, y, options);
}
}

View File

@ -25,7 +25,7 @@ import { Browser, BrowserContext } from './Browser';
import { TargetSession, TargetSessionEvents } from './Connection';
import { Events } from './events';
import { Frame, FrameManager, FrameManagerEvents } from './FrameManager';
import { RawKeyboardImpl, Mouse } from './Input';
import { RawKeyboardImpl, RawMouseImpl } from './Input';
import { createJSHandle, ElementHandle, JSHandle } from './JSHandle';
import { NetworkManagerEvents, Response } from './NetworkManager';
import { Protocol } from './protocol';
@ -46,7 +46,7 @@ export class Page extends EventEmitter {
private _session: TargetSession;
private _target: Target;
private _keyboard: input.Keyboard;
private _mouse: Mouse;
private _mouse: input.Mouse;
private _timeoutSettings: TimeoutSettings;
private _frameManager: FrameManager;
private _bootstrapScripts: string[] = [];
@ -69,7 +69,7 @@ export class Page extends EventEmitter {
constructor(session: TargetSession, target: Target, screenshotTaskQueue: TaskQueue) {
super();
this._keyboard = new input.Keyboard(new RawKeyboardImpl(session));
this._mouse = new Mouse(session, this._keyboard);
this._mouse = new input.Mouse(new RawMouseImpl(session), this._keyboard);
this._timeoutSettings = new TimeoutSettings();
this._frameManager = new FrameManager(session, this, this._timeoutSettings);
@ -441,7 +441,7 @@ export class Page extends EventEmitter {
return this._closed;
}
get mouse(): Mouse {
get mouse(): input.Mouse {
return this._mouse;
}

View File

@ -6,8 +6,7 @@ export { Browser, BrowserContext } from './Browser';
export { BrowserFetcher } from './BrowserFetcher';
export { ExecutionContext } from './ExecutionContext';
export { Frame } from './FrameManager';
export { Mouse } from './Input';
export { Keyboard } from '../input';
export { Mouse, Keyboard } from '../input';
export { ElementHandle, JSHandle } from './JSHandle';
export { Request, Response } from './NetworkManager';
export { ConsoleMessage, Page } from './Page';