Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Studying the issue #228104 #228227

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions src/vs/base/browser/ui/inputbox/inputBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const unthemedInboxStyles: IInputBoxStyles = {
export class InputBox extends Widget {
private contextViewProvider?: IContextViewProvider;
element: HTMLElement;
// protected input: HTMLDivElement;
protected input: HTMLInputElement;
private actionbar?: ActionBar;
private readonly options: IInputOptions;
Expand Down Expand Up @@ -142,6 +143,7 @@ export class InputBox extends Widget {
const tagName = this.options.flexibleHeight ? 'textarea' : 'input';

const wrapper = dom.append(this.element, $('.ibwrapper'));
// this.input = dom.append(wrapper, document.createElement('div'));
this.input = dom.append(wrapper, $(tagName + '.input.empty'));
this.input.setAttribute('autocorrect', 'off');
this.input.setAttribute('autocapitalize', 'off');
Expand Down Expand Up @@ -196,6 +198,11 @@ export class InputBox extends Widget {
this.setTooltip(this.tooltip);
}

// const editContext = new EditContext();
// this.input.editContext = editContext;
// this._register(editContextAddDisposableListener(editContext, 'textupdate', (e) => {
// console.log('text update e : ', e);
// }));
this.oninput(this.input, () => this.onValueChange());
this.onblur(this.input, () => this.onBlur());
this.onfocus(this.input, () => this.onFocus());
Expand All @@ -214,13 +221,16 @@ export class InputBox extends Widget {
}

protected onBlur(): void {
console.log('onBlur of InputBox');
this._hideMessage();
if (this.options.showPlaceholderOnFocus) {
this.input.setAttribute('placeholder', '');
}
}

protected onFocus(): void {
console.log('onFocus of InputBox');
// console.log(document.activeElement);
this._showMessage();
if (this.options.showPlaceholderOnFocus) {
this.input.setAttribute('placeholder', this.placeholder || '');
Expand Down Expand Up @@ -259,23 +269,27 @@ export class InputBox extends Widget {
return this.mirror;
}

// public get inputElement(): HTMLDivElement {
// return this.input;
// }

public get inputElement(): HTMLInputElement {
return this.input;
}

public get value(): string {
return this.input.value;
return this.input.value; // textContent ?? '';
}

public set value(newValue: string) {
if (this.input.value !== newValue) {
this.input.value = newValue;
if (this.input.value !== newValue) { // textContent
this.input.value = newValue; // textContent
this.onValueChange();
}
}

public get step(): string {
return this.input.step;
return this.input.step; // '';
}

public set step(newValue: string) {
Expand Down Expand Up @@ -311,6 +325,7 @@ export class InputBox extends Widget {

public isSelectionAtEnd(): boolean {
return this.input.selectionEnd === this.input.value.length && this.input.selectionStart === this.input.selectionEnd;
// return false;
}

public getSelection(): IRange | null {
Expand All @@ -323,6 +338,7 @@ export class InputBox extends Widget {
start: selectionStart,
end: selectionEnd,
};
// return null
}

public enable(): void {
Expand Down Expand Up @@ -534,6 +550,7 @@ export class InputBox extends Widget {
}

private onValueChange(): void {
console.log('onValueChange');
this._onDidChange.fire(this.value);

this.validate();
Expand Down Expand Up @@ -698,6 +715,7 @@ export class HistoryInputBox extends InputBox implements IHistoryNavigationWidge
}

override dispose() {
console.log('dispose');
super.dispose();
if (this.observer) {
this.observer.disconnect();
Expand Down Expand Up @@ -780,11 +798,13 @@ export class HistoryInputBox extends InputBox implements IHistoryNavigationWidge
}

protected override onBlur(): void {
console.log('onBlur of HistoryInputBox: ');
super.onBlur();
this._onDidBlur.fire();
}

protected override onFocus(): void {
console.log('onFocus');
super.onFocus();
this._onDidFocus.fire();
}
Expand Down
15 changes: 12 additions & 3 deletions src/vs/base/browser/ui/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,24 @@ export abstract class Widget extends Disposable {
}

protected oninput(domNode: HTMLElement, listener: (e: Event) => void): void {
this._register(dom.addDisposableListener(domNode, dom.EventType.INPUT, listener));
this._register(dom.addDisposableListener(domNode, dom.EventType.INPUT, (e) => {
console.log('on input for domNode : ', domNode);
listener(e);
}));
}

protected onblur(domNode: HTMLElement, listener: (e: Event) => void): void {
this._register(dom.addDisposableListener(domNode, dom.EventType.BLUR, listener));
this._register(dom.addDisposableListener(domNode, dom.EventType.BLUR, (e) => {
console.log('on blur for domNode : ', domNode);
listener(e);
}));
}

protected onfocus(domNode: HTMLElement, listener: (e: Event) => void): void {
this._register(dom.addDisposableListener(domNode, dom.EventType.FOCUS, listener));
this._register(dom.addDisposableListener(domNode, dom.EventType.FOCUS, (e) => {
console.log('on focus for domNode : ', domNode);
listener(e);
}));
}

protected onchange(domNode: HTMLElement, listener: (e: Event) => void): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import './nativeEditContext.css';
import { isFirefox } from '../../../../../base/browser/browser.js';
import { addDisposableListener } from '../../../../../base/browser/dom.js';
import { addDisposableListener, getActiveWindow } from '../../../../../base/browser/dom.js';
import { FastDomNode } from '../../../../../base/browser/fastDomNode.js';
import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js';
import { KeyCode } from '../../../../../base/common/keyCodes.js';
Expand All @@ -21,7 +21,7 @@ import { RestrictedRenderingContext, RenderingContext } from '../../../view/rend
import { ViewController } from '../../../view/viewController.js';
import { ClipboardStoredMetadata, getDataToCopy, InMemoryClipboardMetadataManager } from '../clipboardUtils.js';
import { AbstractEditContext } from '../editContextUtils.js';
import { editContextAddDisposableListener, FocusTracker, ITypeData } from './nativeEditContextUtils.js';
import { editContextAddDisposableListener, FocusTracker, ITypeData, NATIVE_EDIT_CONTEXT_CLASSNAME } from './nativeEditContextUtils.js';
import { ScreenReaderSupport } from './screenReaderSupport.js';
import { Range } from '../../../../common/core/range.js';
import { Selection } from '../../../../common/core/selection.js';
Expand Down Expand Up @@ -50,13 +50,26 @@ export class NativeEditContext extends AbstractEditContext {
@IInstantiationService instantiationService: IInstantiationService,
@IClipboardService clipboardService: IClipboardService,
) {

console.log('native edit context constructor');
super(context);

this.domNode = new FastDomNode(document.createElement('div'));
this.domNode.setClassName(`native-edit-context`);
this.domNode.setClassName(NATIVE_EDIT_CONTEXT_CLASSNAME);
this._updateDomAttributes();

this._focusTracker = this._register(new FocusTracker(this.domNode.domNode, (newFocusValue: boolean) => this._context.viewModel.setHasFocus(newFocusValue)));
this._focusTracker = this._register(new FocusTracker(this.domNode.domNode, (newFocusValue: boolean) => {
console.log('this._context.viewModel.model.getValue() : ', this._context.viewModel.model.getValue());
console.log('setHasFocus, newFocusValue : ', newFocusValue);
this._context.viewModel.setHasFocus(newFocusValue);

console.log('document.activeElement ', document.activeElement);
// Need to remove the range in the document so can't anymore type
if (!newFocusValue) {
this.domNode.domNode.blur();
this._screenReaderSupport.removeRanges();
}
}));

this._editContext = new EditContext();
this.domNode.domNode.editContext = this._editContext;
Expand Down Expand Up @@ -90,6 +103,28 @@ export class NativeEditContext extends AbstractEditContext {
this._register(editContextAddDisposableListener(this._editContext, 'textformatupdate', (e) => this._handleTextFormatUpdate(e)));
this._register(editContextAddDisposableListener(this._editContext, 'characterboundsupdate', (e) => this._updateCharacterBounds()));
this._register(editContextAddDisposableListener(this._editContext, 'textupdate', (e) => {
console.log('text update, e : ', e);
console.log('this._domNode.domNode : ', this.domNode.domNode);
console.log('document.activeElement : ', document.activeElement);
console.log('equal : ', this.domNode.domNode === document.activeElement);
console.log('this._editContext : ', this._editContext);
const attachedElements = this._editContext.attachedElements();
console.log('attachedElements : ', attachedElements);
for (const attachedElement of attachedElements) {
console.log('attachedElement : ', attachedElement);
}

// Looks like the edit context events are sent even if the dom node is not focused?
console.log('removedRanges');
const activeDocument = getActiveWindow().document;
const activeDocumentSelection = activeDocument.getSelection();
if (activeDocumentSelection) {
const rangeCount = activeDocumentSelection.rangeCount;
for (let i = 0; i < rangeCount; i++) {
const range = activeDocumentSelection.getRangeAt(i);
console.log('range : ', range);
}
}
const compositionRangeWithinEditor = this._compositionRangeWithinEditor;
if (compositionRangeWithinEditor) {
const position = this._context.viewModel.getPrimaryCursorState().modelState.position;
Expand Down Expand Up @@ -125,8 +160,11 @@ export class NativeEditContext extends AbstractEditContext {
// --- Public methods ---

public override dispose(): void {
console.log('dispose');
super.dispose();
this.domNode.domNode.remove();
this._context.viewModel.setHasFocus(false);
console.log('after set has focus false');
}

public appendTo(overflowGuardContainer: FastDomNode<HTMLElement>): void {
Expand Down Expand Up @@ -176,7 +214,9 @@ export class NativeEditContext extends AbstractEditContext {

public focus(): void { this._focusTracker.focus(); }

public refreshFocusState(): void { }
public refreshFocusState(): void {
// this._focusTracker.refreshFocusState();
}

// --- Private methods ---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import { addDisposableListener } from '../../../../../base/browser/dom.js';
import { IDisposable, Disposable } from '../../../../../base/common/lifecycle.js';

export const NATIVE_EDIT_CONTEXT_CLASSNAME = `native-edit-context`;

export interface ITypeData {
text: string;
replacePrevCharCnt: number;
Expand All @@ -21,19 +23,37 @@ export class FocusTracker extends Disposable {
private readonly _onFocusChange: (newFocusValue: boolean) => void,
) {
super();
this._register(addDisposableListener(this._domNode, 'focus', () => this._handleFocusedChanged(true)));
this._register(addDisposableListener(this._domNode, 'blur', () => this._handleFocusedChanged(false)));
this._register(addDisposableListener(this._domNode, 'focus', () => { console.log('focus'); this._handleFocusedChanged(true); }));
this._register(addDisposableListener(this._domNode, 'blur', () => { console.log('blur'); this._handleFocusedChanged(false); }));
}

private _handleFocusedChanged(focused: boolean): void {
console.log('_handleFocusedChanged, focused : ', focused);
if (this._isFocused === focused) {
return;
}
this._isFocused = focused;
this._onFocusChange(this._isFocused);
}

public refreshFocusState(): void {
// console.log('refreshFocusState');
// const shadowRoot = getShadowRoot(this._domNode);
// console.log('shadowRoot : ', shadowRoot);
// let hasFocus: boolean;
// if (shadowRoot) {
// hasFocus = shadowRoot.activeElement === this._domNode;
// } else if (this._domNode.isConnected) {
// hasFocus = getActiveElement() === this._domNode;
// } else {
// hasFocus = false;
// }
// console.log('hasFocus : ', hasFocus);
// this._onFocusChange(hasFocus);

}
public focus(): void {
console.log('focus inside of FocusTracker');
this._domNode.focus();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ViewContext } from '../../../../common/viewModel/viewContext.js';
import { applyFontInfo } from '../../../config/domFontInfo.js';
import { RestrictedRenderingContext, RenderingContext } from '../../../view/renderingContext.js';
import { ariaLabelForScreenReaderContent, ISimpleModel, newlinecount, PagedScreenReaderStrategy, ScreenReaderContentState } from '../screenReaderUtils.js';
import { NATIVE_EDIT_CONTEXT_CLASSNAME } from './nativeEditContextUtils.js';

export class ScreenReaderSupport {

Expand All @@ -32,6 +33,8 @@ export class ScreenReaderSupport {
private _primarySelection: Selection = new Selection(1, 1, 1, 1);
private _screenReaderContentState: ScreenReaderContentState | undefined;

private _screenReaderContentRange: globalThis.Range | undefined;

constructor(
private readonly _domNode: FastDomNode<HTMLElement>,
private readonly _context: ViewContext,
Expand Down Expand Up @@ -150,13 +153,53 @@ export class ScreenReaderSupport {
return;
}
const focusedElement = getActiveWindow().document.activeElement;
const range = new globalThis.Range();
range.setStart(textContent, selectionOffsetStart);
range.setEnd(textContent, selectionOffsetEnd);
this._screenReaderContentRange = new globalThis.Range();
this._screenReaderContentRange.setStart(textContent, selectionOffsetStart);
this._screenReaderContentRange.setEnd(textContent, selectionOffsetEnd);
activeDocumentSelection.removeAllRanges();
activeDocumentSelection.addRange(range);
activeDocumentSelection.addRange(this._screenReaderContentRange);
if (isHTMLElement(focusedElement)) {
focusedElement.focus();
}
}

public removeRanges(): void {
console.log('removeRanges');
const activeDocument = getActiveWindow().document;
const activeDocumentSelection = activeDocument.getSelection();
if (!activeDocumentSelection) {
return;
}
const rangeCount = activeDocumentSelection.rangeCount;
for (let i = 0; i < rangeCount; i++) {
const range = activeDocumentSelection.getRangeAt(i);
console.log('i');
console.log('this._screenReaderContentRange : ', this._screenReaderContentRange);
console.log('range : ', range);
console.log('range.startContainer : ', range.startContainer);
console.log('range.endContainer : ', range.endContainer);
const isSameRange = this._screenReaderContentRange === range;
console.log('isSameRange : ', isSameRange);
if (isSameRange) {
console.log('removeRange');
activeDocumentSelection.removeRange(range);
}
const rangeStartContainer = range.startContainer;
const rangeEndContainer = range.endContainer;
console.log('rangeStartContainer : ', rangeStartContainer);
console.log('rangeEndContainer : ', rangeEndContainer);
if (isHTMLElement(rangeStartContainer) && rangeStartContainer.classList.contains(NATIVE_EDIT_CONTEXT_CLASSNAME)
&& isHTMLElement(rangeEndContainer) && rangeEndContainer.classList.contains(NATIVE_EDIT_CONTEXT_CLASSNAME)) {
console.log('removeRange');
activeDocumentSelection.removeRange(range);
}
}

console.log('after removal');
const rangeCount2 = activeDocumentSelection.rangeCount;
for (let i = 0; i < rangeCount2; i++) {
const range = activeDocumentSelection.getRangeAt(i);
console.log('range : ', range);
}
}
}
Loading
Loading