Skip to content

Commit eaf18ad

Browse files
committed
Adopt accessibilitySupportEnabled in the editor (microsoft#26730)
1 parent 2b7051e commit eaf18ad

15 files changed

Lines changed: 175 additions & 56 deletions

File tree

src/vs/base/browser/browser.ts

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,6 @@ import * as Platform from 'vs/base/common/platform';
88
import Event, { Emitter } from 'vs/base/common/event';
99
import { IDisposable } from 'vs/base/common/lifecycle';
1010

11-
export const enum AccessibilitySupport {
12-
/**
13-
* This should be the browser case where it is not known if a screen reader is attached or no.
14-
*/
15-
Unknown = 0,
16-
17-
Disabled = 1,
18-
19-
Enabled = 2
20-
}
21-
2211
class WindowManager {
2312

2413
public static INSTANCE = new WindowManager();
@@ -88,19 +77,19 @@ class WindowManager {
8877
}
8978

9079
// --- Accessibility
91-
private _accessibilitySupport = AccessibilitySupport.Unknown;
80+
private _accessibilitySupport = Platform.AccessibilitySupport.Unknown;
9281
private _onDidChangeAccessibilitySupport: Emitter<void> = new Emitter<void>();
9382

9483
public onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event;
95-
public setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void {
84+
public setAccessibilitySupport(accessibilitySupport: Platform.AccessibilitySupport): void {
9685
if (this._accessibilitySupport === accessibilitySupport) {
9786
return;
9887
}
9988

10089
this._accessibilitySupport = accessibilitySupport;
10190
this._onDidChangeAccessibilitySupport.fire();
10291
}
103-
public getAccessibilitySupport(): AccessibilitySupport {
92+
public getAccessibilitySupport(): Platform.AccessibilitySupport {
10493
return this._accessibilitySupport;
10594
}
10695

@@ -144,10 +133,10 @@ export function onDidChangeFullscreen(callback: () => void): IDisposable {
144133
return WindowManager.INSTANCE.onDidChangeFullscreen(callback);
145134
}
146135

147-
export function setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void {
136+
export function setAccessibilitySupport(accessibilitySupport: Platform.AccessibilitySupport): void {
148137
WindowManager.INSTANCE.setAccessibilitySupport(accessibilitySupport);
149138
}
150-
export function getAccessibilitySupport(): AccessibilitySupport {
139+
export function getAccessibilitySupport(): Platform.AccessibilitySupport {
151140
return WindowManager.INSTANCE.getAccessibilitySupport();
152141
}
153142
export function onDidChangeAccessibilitySupport(callback: () => void): IDisposable {

src/vs/base/common/platform.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,14 @@ export const enum OperatingSystem {
142142
Linux = 3
143143
}
144144
export const OS = (_isMacintosh ? OperatingSystem.Macintosh : (_isWindows ? OperatingSystem.Windows : OperatingSystem.Linux));
145+
146+
export const enum AccessibilitySupport {
147+
/**
148+
* This should be the browser case where it is not known if a screen reader is attached or no.
149+
*/
150+
Unknown = 0,
151+
152+
Disabled = 1,
153+
154+
Enabled = 2
155+
}

src/vs/editor/browser/config/configuration.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ export class Configuration extends CommonEditorConfiguration {
310310
}
311311

312312
this._register(browser.onDidChangeZoomLevel(_ => this._recomputeOptions()));
313+
this._register(browser.onDidChangeAccessibilitySupport(() => this._recomputeOptions()));
313314

314315
this._recomputeOptions();
315316
}
@@ -353,7 +354,8 @@ export class Configuration extends CommonEditorConfiguration {
353354
canUseTranslate3d: browser.canUseTranslate3d(),
354355
emptySelectionClipboard: browser.isWebKit,
355356
pixelRatio: browser.getPixelRatio(),
356-
zoomLevel: browser.getZoomLevel()
357+
zoomLevel: browser.getZoomLevel(),
358+
accessibilitySupport: browser.getAccessibilitySupport()
357359
};
358360
}
359361

src/vs/editor/browser/controller/textAreaHandler.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'use strict';
66

77
import 'vs/css!./textAreaHandler';
8+
import * as platform from 'vs/base/common/platform';
89
import * as browser from 'vs/base/browser/browser';
910
import { TextAreaInput, ITextAreaInputHost, IPasteData, ICompositionData } from 'vs/editor/browser/controller/textAreaInput';
1011
import { ISimpleModel, ITypeData, TextAreaState, IENarratorStrategy, NVDAPagedStrategy } from 'vs/editor/browser/controller/textAreaState';
@@ -54,6 +55,7 @@ export class TextAreaHandler extends ViewPart {
5455
private readonly _viewHelper: ITextAreaHandlerHelper;
5556

5657
private _pixelRatio: number;
58+
private _accessibilitySupport: platform.AccessibilitySupport;
5759
private _contentLeft: number;
5860
private _contentWidth: number;
5961
private _contentHeight: number;
@@ -85,6 +87,7 @@ export class TextAreaHandler extends ViewPart {
8587
const conf = this._context.configuration.editor;
8688

8789
this._pixelRatio = conf.pixelRatio;
90+
this._accessibilitySupport = conf.accessibilitySupport;
8891
this._contentLeft = conf.layoutInfo.contentLeft;
8992
this._contentWidth = conf.layoutInfo.contentWidth;
9093
this._contentHeight = conf.layoutInfo.contentHeight;
@@ -160,6 +163,11 @@ export class TextAreaHandler extends ViewPart {
160163
return TextAreaState.EMPTY;
161164
}
162165

166+
if (this._accessibilitySupport === platform.AccessibilitySupport.Disabled) {
167+
// We know for a fact that a screen reader is not attached
168+
return TextAreaState.EMPTY;
169+
}
170+
163171
const selection = this._selections[0];
164172

165173
if (this._experimentalScreenReader) {
@@ -286,6 +294,10 @@ export class TextAreaHandler extends ViewPart {
286294
if (e.pixelRatio) {
287295
this._pixelRatio = conf.pixelRatio;
288296
}
297+
if (e.accessibilitySupport) {
298+
this._accessibilitySupport = conf.accessibilitySupport;
299+
this._textAreaInput.writeScreenReaderContent('strategy changed');
300+
}
289301
if (e.emptySelectionClipboard) {
290302
this._emptySelectionClipboard = conf.emptySelectionClipboard;
291303
}
@@ -294,6 +306,7 @@ export class TextAreaHandler extends ViewPart {
294306
}
295307
public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean {
296308
this._selections = e.selections.slice(0);
309+
this._textAreaInput.writeScreenReaderContent('selection changed');
297310
return true;
298311
}
299312
public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {
@@ -333,10 +346,6 @@ export class TextAreaHandler extends ViewPart {
333346
this._textAreaInput.focusTextArea();
334347
}
335348

336-
public writeToTextArea(): void {
337-
this._textAreaInput.writeScreenReaderContent('selection changed');
338-
}
339-
340349
public setAriaActiveDescendant(id: string): void {
341350
if (id) {
342351
this.textArea.setAttribute('role', 'combobox');
@@ -356,11 +365,18 @@ export class TextAreaHandler extends ViewPart {
356365
private _primaryCursorVisibleRange: HorizontalRange = null;
357366

358367
public prepareRender(ctx: RenderingContext): void {
359-
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
360-
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(primaryCursorPosition);
368+
if (this._accessibilitySupport === platform.AccessibilitySupport.Enabled) {
369+
// Do not move the textarea with the cursor, as this generates accessibility events that might confuse screen readers
370+
// See https://github.com/Microsoft/vscode/issues/26730
371+
this._primaryCursorVisibleRange = null;
372+
} else {
373+
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
374+
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(primaryCursorPosition);
375+
}
361376
}
362377

363378
public render(ctx: RestrictedRenderingContext): void {
379+
this._textAreaInput.writeScreenReaderContent('render');
364380
this._render();
365381
}
366382

src/vs/editor/browser/view/viewImpl.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,6 @@ export class View extends ViewEventHandler {
403403

404404
if (!this.viewLines.shouldRender() && viewPartsToRender.length === 0) {
405405
// Nothing to render
406-
this._textAreaHandler.writeToTextArea();
407406
return;
408407
}
409408

@@ -413,15 +412,11 @@ export class View extends ViewEventHandler {
413412
let viewportData = new ViewportData(partialViewportData, this._context.model);
414413

415414
if (this.viewLines.shouldRender()) {
416-
this.viewLines.renderText(viewportData, () => {
417-
this._textAreaHandler.writeToTextArea();
418-
});
415+
this.viewLines.renderText(viewportData);
419416
this.viewLines.onDidRender();
420417

421418
// Rendering of viewLines might cause scroll events to occur, so collect view parts to render again
422419
viewPartsToRender = this._getViewPartsToRender();
423-
} else {
424-
this._textAreaHandler.writeToTextArea();
425420
}
426421

427422
let renderingContext = new RenderingContext(this._context.viewLayout, viewportData, this.viewLines);

src/vs/editor/browser/viewParts/lines/viewLines.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -405,17 +405,14 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
405405
throw new Error('Not supported');
406406
}
407407

408-
public renderText(viewportData: ViewportData, onAfterLinesRendered: () => void): void {
408+
public renderText(viewportData: ViewportData): void {
409409
// (1) render lines - ensures lines are in the DOM
410410
this._visibleLines.renderLines(viewportData);
411411
this._lastRenderedData.setCurrentVisibleRange(viewportData.visibleRange);
412412
this.domNode.setWidth(this._context.viewLayout.getScrollWidth());
413413
this.domNode.setHeight(Math.min(this._context.viewLayout.getScrollHeight(), 1000000));
414414

415-
// (2) execute DOM writing that forces sync layout (e.g. textArea manipulation)
416-
onAfterLinesRendered();
417-
418-
// (3) compute horizontal scroll position:
415+
// (2) compute horizontal scroll position:
419416
// - this must happen after the lines are in the DOM since it might need a line that rendered just now
420417
// - it might change `scrollWidth` and `scrollLeft`
421418
if (this._lastCursorRevealRangeHorizontallyEvent) {
@@ -440,7 +437,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
440437
});
441438
}
442439

443-
// (4) handle scrolling
440+
// (3) handle scrolling
444441
const adjustedScrollTop = this._context.viewLayout.getScrollTop() - viewportData.bigNumbersDelta;
445442
if (this._canUseTranslate3d) {
446443
let transform = 'translate3d(' + -this._context.viewLayout.getScrollLeft() + 'px, ' + -adjustedScrollTop + 'px, 0px)';

src/vs/editor/common/config/commonEditorConfig.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export interface IEnvConfiguration {
5959
emptySelectionClipboard: boolean;
6060
pixelRatio: number;
6161
zoomLevel: number;
62+
accessibilitySupport: platform.AccessibilitySupport;
6263
}
6364

6465
export abstract class CommonEditorConfiguration extends Disposable implements editorCommon.IConfiguration {
@@ -122,7 +123,8 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed
122123
canUseTranslate3d: partialEnv.canUseTranslate3d,
123124
emptySelectionClipboard: partialEnv.emptySelectionClipboard,
124125
pixelRatio: partialEnv.pixelRatio,
125-
tabFocusMode: TabFocus.getTabFocusMode()
126+
tabFocusMode: TabFocus.getTabFocusMode(),
127+
accessibilitySupport: partialEnv.accessibilitySupport
126128
};
127129
return editorOptions.InternalEditorOptionsFactory.createInternalEditorOptions(env, opts);
128130
}

0 commit comments

Comments
 (0)