mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-09 00:05:28 +01:00
aux window - improve popup block situation
This commit is contained in:
committed by
Benjamin Pasero
parent
315279f5c7
commit
eb0575e464
@@ -82,6 +82,10 @@
|
||||
"name": "vs/workbench/services/assignment",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/services/auxiliaryWindow",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/contrib/extensions",
|
||||
"project": "vscode-workbench"
|
||||
|
||||
@@ -2448,7 +2448,7 @@ export class ExperimentalMoveEditorIntoNewWindowAction extends Action2 {
|
||||
return;
|
||||
}
|
||||
|
||||
const auxiliaryEditorPart = editorGroupService.createAuxiliaryEditorPart();
|
||||
const auxiliaryEditorPart = await editorGroupService.createAuxiliaryEditorPart();
|
||||
|
||||
activeEditorPane.group.moveEditor(activeEditorPane.input, auxiliaryEditorPart.activeGroup);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ export class EditorParts extends Disposable implements IEditorGroupsService, IEd
|
||||
|
||||
//#region Auxiliary Editor Parts
|
||||
|
||||
createAuxiliaryEditorPart(options?: { position?: IRectangle }): IAuxiliaryEditorPart {
|
||||
async createAuxiliaryEditorPart(options?: { position?: IRectangle }): Promise<IAuxiliaryEditorPart> {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const auxiliaryWindow = disposables.add(this.auxiliaryWindowService.open(options));
|
||||
const auxiliaryWindow = disposables.add(await this.auxiliaryWindowService.open(options));
|
||||
disposables.add(Event.once(auxiliaryWindow.onDidClose)(() => disposables.dispose()));
|
||||
|
||||
const partContainer = document.createElement('div');
|
||||
|
||||
@@ -378,7 +378,7 @@ export class ExperimentalSplitWindowAction extends Action2 {
|
||||
}, { targetWindowId: activeWindowId });
|
||||
|
||||
// Then create a new window next to the active window
|
||||
const auxiliaryEditorPart = editorGroupService.createAuxiliaryEditorPart({
|
||||
const auxiliaryEditorPart = await editorGroupService.createAuxiliaryEditorPart({
|
||||
position: {
|
||||
x: activeWindow.screen.availWidth / 2,
|
||||
y: 0,
|
||||
|
||||
@@ -3,16 +3,18 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Dimension, EventHelper, EventType, addDisposableListener, copyAttributes, getClientArea, position, registerWindow, size, trackAttributes } from 'vs/base/browser/dom';
|
||||
import { Dimension, EventHelper, EventType, addDisposableListener, copyAttributes, getActiveWindow, getClientArea, position, registerWindow, size, trackAttributes } from 'vs/base/browser/dom';
|
||||
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { IRectangle } from 'vs/platform/window/common/window';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
||||
export const IAuxiliaryWindowService = createDecorator<IAuxiliaryWindowService>('auxiliaryWindowService');
|
||||
|
||||
@@ -20,7 +22,7 @@ export interface IAuxiliaryWindowService {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
open(options?: { position?: IRectangle }): IAuxiliaryWindow;
|
||||
open(options?: { position?: IRectangle }): Promise<IAuxiliaryWindow>;
|
||||
}
|
||||
|
||||
export interface IAuxiliaryWindow extends IDisposable {
|
||||
@@ -39,14 +41,21 @@ export class BrowserAuxiliaryWindowService implements IAuxiliaryWindowService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private static readonly DEFAULT_SIZE = { width: 800, height: 600 };
|
||||
|
||||
constructor(
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
|
||||
@IDialogService private readonly dialogService: IDialogService
|
||||
) { }
|
||||
|
||||
open(options?: { position?: IRectangle }): IAuxiliaryWindow {
|
||||
async open(options?: { position?: IRectangle }): Promise<IAuxiliaryWindow> {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const auxiliaryWindow = this.doOpen(options);
|
||||
const auxiliaryWindow = await this.doOpen(options);
|
||||
if (!auxiliaryWindow) {
|
||||
throw new Error(localize('unableToOpenWindowError', "Unable to open a new window."));
|
||||
}
|
||||
|
||||
disposables.add(registerWindow(auxiliaryWindow));
|
||||
disposables.add(toDisposable(() => auxiliaryWindow.close()));
|
||||
|
||||
@@ -61,15 +70,35 @@ export class BrowserAuxiliaryWindowService implements IAuxiliaryWindowService {
|
||||
};
|
||||
}
|
||||
|
||||
private doOpen(options?: { position?: IRectangle }): AuxiliaryWindow {
|
||||
let auxiliaryWindow: Window | null;
|
||||
if (options?.position) {
|
||||
auxiliaryWindow = window.open('about:blank', undefined, `left=${options.position.x},top=${options.position.y},width=${options.position.width},height=${options.position.height}`);
|
||||
} else {
|
||||
auxiliaryWindow = window.open('about:blank');
|
||||
private async doOpen(options?: { position?: IRectangle }): Promise<AuxiliaryWindow | undefined> {
|
||||
let position: IRectangle | undefined = options?.position;
|
||||
if (!position) {
|
||||
const activeWindow = getActiveWindow();
|
||||
position = {
|
||||
x: activeWindow.screen.availWidth / 2 - BrowserAuxiliaryWindowService.DEFAULT_SIZE.width / 2,
|
||||
y: activeWindow.screen.availHeight / 2 - BrowserAuxiliaryWindowService.DEFAULT_SIZE.height / 2,
|
||||
width: BrowserAuxiliaryWindowService.DEFAULT_SIZE.width,
|
||||
height: BrowserAuxiliaryWindowService.DEFAULT_SIZE.height
|
||||
};
|
||||
}
|
||||
|
||||
return assertIsDefined(auxiliaryWindow).window as AuxiliaryWindow;
|
||||
const auxiliaryWindow = window.open('about:blank', undefined, `popup=yes,left=${position.x},top=${position.y},width=${position.width},height=${position.height}`);
|
||||
if (!auxiliaryWindow && isWeb) {
|
||||
return (await this.dialogService.prompt({
|
||||
type: Severity.Warning,
|
||||
message: localize('unableToOpenWindow', "The browser interrupted the opening of a new window. Press 'Retry' to try again."),
|
||||
detail: localize('unableToOpenWindowDetail', "To avoid this problem in the future, please ensure to allow popups for this website."),
|
||||
buttons: [
|
||||
{
|
||||
label: localize({ key: 'retry', comment: ['&& denotes a mnemonic'] }, "&&Retry"),
|
||||
run: () => this.doOpen(options)
|
||||
}
|
||||
],
|
||||
cancelButton: true
|
||||
})).result;
|
||||
}
|
||||
|
||||
return auxiliaryWindow?.window;
|
||||
}
|
||||
|
||||
protected create(auxiliaryWindow: AuxiliaryWindow, disposables: DisposableStore) {
|
||||
|
||||
+4
-2
@@ -12,6 +12,7 @@ import { IWindowsConfiguration } from 'vs/platform/window/common/window';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { INativeHostService } from 'vs/platform/native/common/native';
|
||||
import { DeferredPromise } from 'vs/base/common/async';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
|
||||
type AuxiliaryWindow = BaseAuxiliaryWindow & {
|
||||
readonly vscodeWindowId: Promise<number>;
|
||||
@@ -30,9 +31,10 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService
|
||||
constructor(
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService,
|
||||
@IDialogService dialogService: IDialogService
|
||||
) {
|
||||
super(layoutService);
|
||||
super(layoutService, dialogService);
|
||||
}
|
||||
|
||||
protected override create(auxiliaryWindow: AuxiliaryWindow, disposables: DisposableStore) {
|
||||
|
||||
@@ -482,7 +482,7 @@ export interface IEditorGroupsService extends IEditorGroupsContainer {
|
||||
* Opens a new window with a full editor part instantiated
|
||||
* in there at the optional position on screen.
|
||||
*/
|
||||
createAuxiliaryEditorPart(options?: { position?: IRectangle }): IAuxiliaryEditorPart;
|
||||
createAuxiliaryEditorPart(options?: { position?: IRectangle }): Promise<IAuxiliaryEditorPart>;
|
||||
}
|
||||
|
||||
export const enum OpenEditorContext {
|
||||
|
||||
@@ -869,7 +869,7 @@ export class TestEditorGroupsService implements IEditorGroupsService {
|
||||
readonly activePart = this;
|
||||
readonly mainPart = this;
|
||||
registerEditorPart(part: any): IDisposable { return Disposable.None; }
|
||||
createAuxiliaryEditorPart(): IAuxiliaryEditorPart { throw new Error('Method not implemented.'); }
|
||||
createAuxiliaryEditorPart(): Promise<IAuxiliaryEditorPart> { throw new Error('Method not implemented.'); }
|
||||
}
|
||||
|
||||
export class TestEditorGroupView implements IEditorGroupView {
|
||||
@@ -1753,7 +1753,7 @@ export class TestEditorPart extends MainEditorPart implements IEditorGroupsServi
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
createAuxiliaryEditorPart(): IAuxiliaryEditorPart {
|
||||
createAuxiliaryEditorPart(): Promise<IAuxiliaryEditorPart> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user