mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-30 20:25:40 +01:00
Because we're no longer using document.execCommand('paste'), we don't need a textarea anymore
This commit is contained in:
@@ -30,7 +30,6 @@ import { EditContext } from './editContextFactory.js';
|
||||
import { IAccessibilityService } from '../../../../../platform/accessibility/common/accessibility.js';
|
||||
import { NativeEditContextRegistry } from './nativeEditContextRegistry.js';
|
||||
import { IEditorAriaOptions } from '../../../editorBrowser.js';
|
||||
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
|
||||
import { isHighSurrogate, isLowSurrogate } from '../../../../../base/common/strings.js';
|
||||
|
||||
// Corresponds to classes in nativeEditContext.css
|
||||
@@ -51,7 +50,6 @@ interface ITextUpdateEvent {
|
||||
export class NativeEditContext extends AbstractEditContext {
|
||||
|
||||
// Text area used to handle paste events
|
||||
private readonly _textArea: FastDomNode<HTMLTextAreaElement>;
|
||||
public readonly domNode: FastDomNode<HTMLDivElement>;
|
||||
private readonly _editContext: EditContext;
|
||||
private readonly _screenReaderSupport: ScreenReaderSupport;
|
||||
@@ -79,15 +77,11 @@ export class NativeEditContext extends AbstractEditContext {
|
||||
private readonly _visibleRangeProvider: IVisibleRangeProvider,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService,
|
||||
@IClipboardService private readonly _clipboardService: IClipboardService,
|
||||
) {
|
||||
super(context);
|
||||
|
||||
this.domNode = new FastDomNode(document.createElement('div'));
|
||||
this.domNode.setClassName(`native-edit-context`);
|
||||
this._textArea = new FastDomNode(document.createElement('textarea'));
|
||||
this._textArea.setClassName('native-edit-context-textarea');
|
||||
this._textArea.setAttribute('tabindex', '-1');
|
||||
this.domNode.setAttribute('autocorrect', 'off');
|
||||
this.domNode.setAttribute('autocapitalize', 'off');
|
||||
this.domNode.setAttribute('autocomplete', 'off');
|
||||
@@ -96,7 +90,6 @@ export class NativeEditContext extends AbstractEditContext {
|
||||
this._updateDomAttributes();
|
||||
|
||||
overflowGuardContainer.appendChild(this.domNode);
|
||||
overflowGuardContainer.appendChild(this._textArea);
|
||||
this._parent = overflowGuardContainer.domNode;
|
||||
|
||||
this._selectionChangeListener = this._register(new MutableDisposable());
|
||||
@@ -183,31 +176,6 @@ export class NativeEditContext extends AbstractEditContext {
|
||||
// Emits ViewCompositionEndEvent which can be depended on by ViewEventHandlers
|
||||
this._context.viewModel.onCompositionEnd();
|
||||
}));
|
||||
this._register(addDisposableListener(this._textArea.domNode, 'paste', (e) => {
|
||||
// Pretend here we touched the text area, as the `paste` event will most likely
|
||||
// result in a `selectionchange` event which we want to ignore
|
||||
this._screenReaderSupport.setIgnoreSelectionChangeTime('onPaste');
|
||||
e.preventDefault();
|
||||
if (!e.clipboardData) {
|
||||
return;
|
||||
}
|
||||
let [text, metadata] = ClipboardEventUtils.getTextData(e.clipboardData);
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
|
||||
let pasteOnNewLine = false;
|
||||
let multicursorText: string[] | null = null;
|
||||
let mode: string | null = null;
|
||||
if (metadata) {
|
||||
const options = this._context.configuration.options;
|
||||
const emptySelectionClipboard = options.get(EditorOption.emptySelectionClipboard);
|
||||
pasteOnNewLine = emptySelectionClipboard && !!metadata.isFromEmptySelection;
|
||||
multicursorText = typeof metadata.multicursorText !== 'undefined' ? metadata.multicursorText : null;
|
||||
mode = metadata.mode;
|
||||
}
|
||||
viewController.paste(text, pasteOnNewLine, multicursorText, mode);
|
||||
}));
|
||||
this._register(NativeEditContextRegistry.register(ownerID, this));
|
||||
}
|
||||
|
||||
@@ -217,7 +185,6 @@ export class NativeEditContext extends AbstractEditContext {
|
||||
// Force blue the dom node so can write in pane with no native edit context after disposal
|
||||
this.domNode.domNode.blur();
|
||||
this.domNode.domNode.remove();
|
||||
this._textArea.domNode.remove();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -285,26 +252,8 @@ export class NativeEditContext extends AbstractEditContext {
|
||||
return true;
|
||||
}
|
||||
|
||||
public triggerPaste(): Promise<void> | undefined {
|
||||
public onWillPaste(): void {
|
||||
this._onWillPaste();
|
||||
// pause focus tracking because we don't want to react to focus/blur
|
||||
// events while pasting since we move the focus to the textarea
|
||||
this._focusTracker.pause();
|
||||
|
||||
// Since we can not call execCommand('paste') on a dom node with edit context set
|
||||
// we added a hidden text area that receives the paste execution
|
||||
this._textArea.focus();
|
||||
const triggerPaste = this._clipboardService.triggerPaste();
|
||||
if (!triggerPaste) {
|
||||
this.domNode.domNode.focus();
|
||||
this._focusTracker.resume(); // resume focus tracking
|
||||
return undefined;
|
||||
}
|
||||
return triggerPaste.then(() => {
|
||||
this._textArea.domNode.textContent = '';
|
||||
this.domNode.domNode.focus();
|
||||
this._focusTracker.resume(); // resume focus tracking
|
||||
});
|
||||
}
|
||||
|
||||
private _onWillPaste(): void {
|
||||
|
||||
@@ -15,7 +15,6 @@ export interface ITypeData {
|
||||
|
||||
export class FocusTracker extends Disposable {
|
||||
private _isFocused: boolean = false;
|
||||
private _isPaused: boolean = false;
|
||||
|
||||
constructor(
|
||||
private readonly _domNode: HTMLElement,
|
||||
@@ -23,31 +22,16 @@ export class FocusTracker extends Disposable {
|
||||
) {
|
||||
super();
|
||||
this._register(addDisposableListener(this._domNode, 'focus', () => {
|
||||
if (this._isPaused) {
|
||||
return;
|
||||
}
|
||||
// Here we don't trust the browser and instead we check
|
||||
// that the active element is the one we are tracking
|
||||
// (this happens when cmd+tab is used to switch apps)
|
||||
this.refreshFocusState();
|
||||
}));
|
||||
this._register(addDisposableListener(this._domNode, 'blur', () => {
|
||||
if (this._isPaused) {
|
||||
return;
|
||||
}
|
||||
this._handleFocusedChanged(false);
|
||||
}));
|
||||
}
|
||||
|
||||
public pause(): void {
|
||||
this._isPaused = true;
|
||||
}
|
||||
|
||||
public resume(): void {
|
||||
this._isPaused = false;
|
||||
this.refreshFocusState();
|
||||
}
|
||||
|
||||
private _handleFocusedChanged(focused: boolean): void {
|
||||
if (this._isFocused === focused) {
|
||||
return;
|
||||
|
||||
@@ -238,21 +238,15 @@ if (PasteAction) {
|
||||
if (experimentalEditContextEnabled) {
|
||||
const nativeEditContext = NativeEditContextRegistry.get(focusedEditor.getId());
|
||||
if (nativeEditContext) {
|
||||
const triggerPaste = nativeEditContext.triggerPaste();
|
||||
if (triggerPaste) {
|
||||
return triggerPaste.then(async () => {
|
||||
return CopyPasteController.get(focusedEditor)?.finishedPaste() ?? Promise.resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const triggerPaste = clipboardService.triggerPaste();
|
||||
if (triggerPaste) {
|
||||
return triggerPaste.then(async () => {
|
||||
return CopyPasteController.get(focusedEditor)?.finishedPaste() ?? Promise.resolve();
|
||||
});
|
||||
nativeEditContext.onWillPaste();
|
||||
}
|
||||
}
|
||||
const triggerPaste = clipboardService.triggerPaste();
|
||||
if (triggerPaste) {
|
||||
return triggerPaste.then(async () => {
|
||||
return CopyPasteController.get(focusedEditor)?.finishedPaste() ?? Promise.resolve();
|
||||
});
|
||||
}
|
||||
if (platform.isWeb) {
|
||||
// Use the clipboard service if document.execCommand('paste') was not successful
|
||||
return (async () => {
|
||||
|
||||
Reference in New Issue
Block a user