Skip to content

Commit 056db45

Browse files
committed
driver: dispatchKeybindings
1 parent f53e87d commit 056db45

26 files changed

Lines changed: 132 additions & 78 deletions

File tree

src/vs/editor/standalone/browser/simpleServices.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
360360

361361
this.toDispose.push(dom.addDisposableListener(domNode, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
362362
let keyEvent = new StandardKeyboardEvent(e);
363-
let shouldPreventDefault = this._dispatch(keyEvent, keyEvent.target);
363+
let shouldPreventDefault = this.dispatchEvent(keyEvent, keyEvent.target);
364364
if (shouldPreventDefault) {
365365
keyEvent.preventDefault();
366366
}

src/vs/editor/standalone/test/browser/simpleServices.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ suite('StandaloneKeybindingService', () => {
1717

1818
class TestStandaloneKeybindingService extends StandaloneKeybindingService {
1919
public testDispatch(e: IKeyboardEvent): void {
20-
super._dispatch(e, null);
20+
super.dispatchEvent(e, null);
2121
}
2222
}
2323

src/vs/platform/driver/common/driver.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ export interface IDriver {
2323
_serviceBrand: any;
2424
getWindowIds(): TPromise<number[]>;
2525
getElements(windowId: number, selector: string): TPromise<IElement[]>;
26+
dispatchKeybinding(windowId: number, keybinding: string): TPromise<void>;
2627
}
2728
//*END
2829

2930
export interface IDriverChannel extends IChannel {
3031
call(command: 'getWindowIds'): TPromise<number[]>;
3132
call(command: 'getElements', arg: [number, string]): TPromise<IElement[]>;
33+
call(command: 'dispatchKeybinding', arg: [number, string]): TPromise<void>;
3234
call(command: string, arg: any): TPromise<any>;
3335
}
3436

@@ -40,6 +42,7 @@ export class DriverChannel implements IDriverChannel {
4042
switch (command) {
4143
case 'getWindowIds': return this.driver.getWindowIds();
4244
case 'getElements': return this.driver.getElements(arg[0], arg[1]);
45+
case 'dispatchKeybinding': return this.driver.dispatchKeybinding(arg[0], arg[1]);
4346
}
4447

4548
return undefined;
@@ -59,6 +62,10 @@ export class DriverChannelClient implements IDriver {
5962
getElements(windowId: number, selector: string): TPromise<IElement[]> {
6063
return this.channel.call('getElements', [windowId, selector]);
6164
}
65+
66+
dispatchKeybinding(windowId: number, keybinding: string): TPromise<void> {
67+
return this.channel.call('dispatchKeybinding', [windowId, keybinding]);
68+
}
6269
}
6370

6471
export interface IWindowDriverRegistry {
@@ -96,10 +103,12 @@ export class WindowDriverRegistryChannelClient implements IWindowDriverRegistry
96103

97104
export interface IWindowDriver {
98105
getElements(selector: string): TPromise<IElement[]>;
106+
dispatchKeybinding(keybinding: string): TPromise<void>;
99107
}
100108

101109
export interface IWindowDriverChannel extends IChannel {
102110
call(command: 'getElements', arg: string): TPromise<IElement[]>;
111+
call(command: 'dispatchKeybinding', arg: string): TPromise<void>;
103112
call(command: string, arg: any): TPromise<any>;
104113
}
105114

@@ -110,6 +119,7 @@ export class WindowDriverChannel implements IWindowDriverChannel {
110119
call(command: string, arg?: any): TPromise<any> {
111120
switch (command) {
112121
case 'getElements': return this.driver.getElements(arg);
122+
case 'dispatchKeybinding': return this.driver.dispatchKeybinding(arg);
113123
}
114124

115125
return undefined;
@@ -125,4 +135,8 @@ export class WindowDriverChannelClient implements IWindowDriver {
125135
getElements(selector: string): TPromise<IElement[]> {
126136
return this.channel.call('getElements', selector);
127137
}
138+
139+
dispatchKeybinding(keybinding: string): TPromise<void> {
140+
return this.channel.call('dispatchKeybinding', keybinding);
141+
}
128142
}

src/vs/platform/driver/electron-browser/driver.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,53 @@ import { TPromise } from 'vs/base/common/winjs.base';
99
import { IDisposable } from 'vs/base/common/lifecycle';
1010
import { IWindowDriver, IElement, WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/common/driver';
1111
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
12+
import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO';
13+
import { SimpleKeybinding } from 'vs/base/common/keyCodes';
14+
import { ScanCodeBinding, IMMUTABLE_KEY_CODE_TO_CODE, ScanCodeUtils } from 'vs/workbench/services/keybinding/common/scanCode';
15+
import { IKeybindingService, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
16+
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1217

1318
class WindowDriver implements IWindowDriver {
1419

20+
constructor(
21+
@IKeybindingService private keybindingService: IKeybindingService
22+
) { }
23+
24+
async dispatchKeybinding(rawKeybinding: string): TPromise<void> {
25+
const [first, second] = KeybindingIO._readUserBinding(rawKeybinding);
26+
27+
this._dispatchKeybinding(first);
28+
29+
if (second) {
30+
this._dispatchKeybinding(second);
31+
}
32+
}
33+
34+
private _dispatchKeybinding(keybinding: SimpleKeybinding | ScanCodeBinding): void {
35+
if (keybinding instanceof ScanCodeBinding) {
36+
throw new Error('ScanCodeBindings not supported');
37+
}
38+
39+
const scanCode = IMMUTABLE_KEY_CODE_TO_CODE[keybinding.keyCode];
40+
const event: IKeyboardEvent = {
41+
ctrlKey: keybinding.ctrlKey,
42+
altKey: keybinding.altKey,
43+
shiftKey: keybinding.shiftKey,
44+
metaKey: keybinding.metaKey,
45+
keyCode: keybinding.keyCode,
46+
code: ScanCodeUtils.toString(scanCode)
47+
};
48+
49+
this.keybindingService.dispatchEvent(event, document.activeElement);
50+
51+
// console.log(keybinding);
52+
53+
// const e = new KeyboardEvent('keydown', event);
54+
// console.log('dispatching', e);
55+
// document.activeElement.dispatchEvent(e);
56+
// document.activeElement.dispatchEvent(new KeyboardEvent('keyup', event));
57+
}
58+
1559
async getElements(selector: string): TPromise<IElement[]> {
1660
const query = document.querySelectorAll(selector);
1761
const result: IElement[] = [];
@@ -30,8 +74,12 @@ class WindowDriver implements IWindowDriver {
3074
}
3175
}
3276

33-
export async function registerWindowDriver(client: IPCClient, windowId: number): TPromise<IDisposable> {
34-
const windowDriver = new WindowDriver();
77+
export async function registerWindowDriver(
78+
client: IPCClient,
79+
windowId: number,
80+
instantiationService: IInstantiationService
81+
): TPromise<IDisposable> {
82+
const windowDriver = instantiationService.createInstance(WindowDriver);
3583
const windowDriverChannel = new WindowDriverChannel(windowDriver);
3684
client.registerChannel('windowDriver', windowDriverChannel);
3785

src/vs/platform/driver/electron-main/driver.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
'use strict';
77

88
import { TPromise } from 'vs/base/common/winjs.base';
9-
import { IDriver, DriverChannel, IElement, IWindowDriverChannel, WindowDriverChannelClient, IWindowDriverRegistry, WindowDriverRegistryChannel } from 'vs/platform/driver/common/driver';
9+
import { IDriver, DriverChannel, IElement, IWindowDriverChannel, WindowDriverChannelClient, IWindowDriverRegistry, WindowDriverRegistryChannel, IWindowDriver } from 'vs/platform/driver/common/driver';
1010
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
1111
import { serve as serveNet } from 'vs/base/parts/ipc/node/ipc.net';
1212
import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle';
@@ -45,11 +45,19 @@ export class Driver implements IDriver, IWindowDriverRegistry {
4545
}
4646

4747
getElements(windowId: number, selector: string): TPromise<IElement[], any> {
48+
const windowDriver = this.getWindowDriver(windowId);
49+
return windowDriver.getElements(selector);
50+
}
51+
52+
dispatchKeybinding(windowId: number, keybinding: string): TPromise<void> {
53+
const windowDriver = this.getWindowDriver(windowId);
54+
return windowDriver.dispatchKeybinding(keybinding);
55+
}
56+
57+
private getWindowDriver(windowId: number): IWindowDriver {
4858
const router = new WindowRouter(windowId);
4959
const windowDriverChannel = this.windowServer.getChannel<IWindowDriverChannel>('windowDriver', router);
50-
const windowDriver = new WindowDriverChannelClient(windowDriverChannel);
51-
52-
return windowDriver.getElements(selector);
60+
return new WindowDriverChannelClient(windowDriverChannel);
5361
}
5462
}
5563

src/vs/platform/keybinding/common/abstractKeybindingService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export abstract class AbstractKeybindingService implements IKeybindingService {
114114
return this._getResolver().resolve(contextValue, currentChord, firstPart);
115115
}
116116

117-
protected _dispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {
117+
dispatchEvent(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {
118118
let shouldPreventDefault = false;
119119

120120
const keybinding = this.resolveKeyboardEvent(e);

src/vs/platform/keybinding/common/keybinding.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,10 @@ export interface IKeybindingService {
7777
getKeybindings(): ResolvedKeybindingItem[];
7878

7979
customKeybindingsCount(): number;
80+
81+
/**
82+
* For simulation purposes (eg, smoke test)
83+
*/
84+
dispatchEvent(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean;
8085
}
8186

src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ suite('AbstractKeybindingService', () => {
7070

7171
public testDispatch(kb: number): boolean {
7272
const keybinding = createSimpleKeybinding(kb, OS);
73-
return this._dispatch({
73+
return this.dispatchEvent({
7474
ctrlKey: keybinding.ctrlKey,
7575
shiftKey: keybinding.shiftKey,
7676
altKey: keybinding.altKey,

src/vs/platform/keybinding/test/common/mockKeybindingService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,8 @@ export class MockKeybindingService implements IKeybindingService {
120120
public softDispatch(keybinding: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult {
121121
return null;
122122
}
123+
124+
dispatchEvent(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {
125+
return false;
126+
}
123127
}

src/vs/workbench/electron-browser/shell.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
9595
import { DialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
9696
import { DialogChannel } from 'vs/platform/dialogs/common/dialogIpc';
9797
import { EventType, addDisposableListener, addClass, getClientArea } from 'vs/base/browser/dom';
98-
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
9998

10099
/**
101100
* Services that we require for the Shell
@@ -140,7 +139,7 @@ export class WorkbenchShell {
140139
private configuration: IWindowConfiguration;
141140
private workbench: Workbench;
142141

143-
constructor(container: HTMLElement, coreServices: ICoreServices, mainProcessServices: ServiceCollection, mainProcessClient: IPCClient, configuration: IWindowConfiguration) {
142+
constructor(container: HTMLElement, coreServices: ICoreServices, mainProcessServices: ServiceCollection, private mainProcessClient: IPCClient, configuration: IWindowConfiguration) {
144143
this.container = container;
145144

146145
this.configuration = configuration;
@@ -156,11 +155,6 @@ export class WorkbenchShell {
156155

157156
this.toUnbind = [];
158157
this.previousErrorTime = 0;
159-
160-
if (coreServices.environmentService.driverHandle) {
161-
registerWindowDriver(mainProcessClient, configuration.windowId)
162-
.then(disposable => this.toUnbind.push(disposable));
163-
}
164158
}
165159

166160
private createContents(parent: HTMLElement): HTMLElement {
@@ -195,7 +189,7 @@ export class WorkbenchShell {
195189

196190
private createWorkbench(instantiationService: IInstantiationService, serviceCollection: ServiceCollection, parent: HTMLElement, workbenchContainer: HTMLElement): Workbench {
197191
try {
198-
const workbench = instantiationService.createInstance(Workbench, parent, workbenchContainer, this.configuration, serviceCollection, this.lifecycleService);
192+
const workbench = instantiationService.createInstance(Workbench, parent, workbenchContainer, this.configuration, serviceCollection, this.lifecycleService, this.mainProcessClient);
199193

200194
// Set lifecycle phase to `Restoring`
201195
this.lifecycleService.phase = LifecyclePhase.Restoring;

0 commit comments

Comments
 (0)