Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyriar committed Jan 28, 2018
1 parent 0bdf1e8 commit 646813a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 9 deletions.
74 changes: 68 additions & 6 deletions src/AccessibilityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,27 @@ export class AccessibilityManager implements IDisposable {
this._rowElements = null;
}

public get isNavigatingRows(): boolean {
return this._rowElements.indexOf(<HTMLElement>document.activeElement) >= 0;
}

private _onBoundaryFocus(e: FocusEvent, position: BoundaryPosition): void {
const boundaryElement = <HTMLElement>e.target;
const beforeBoundaryElement = this._rowElements[position === BoundaryPosition.Top ? 1 : this._rowElements.length - 2];

// Don't scroll when the last focused item was not the second row (focus is going the other
// direction)
if (e.relatedTarget !== beforeBoundaryElement) {
return;
}

// Don't scroll if the buffer top has reached the end in that direction
const posInSet = boundaryElement.getAttribute('aria-posinset');
const lastRowPos = position === BoundaryPosition.Top ? '1' : `${this._terminal.buffer.lines.length}`;
if (posInSet === lastRowPos) {
return;
}

// Don't scroll when the last focused item was not the second row (focus is going the other
// direction)
if (e.relatedTarget !== beforeBoundaryElement) {
return;
}

// Remove old boundary element from array
let topBoundaryElement: HTMLElement;
let bottomBoundaryElement: HTMLElement;
Expand Down Expand Up @@ -163,6 +167,64 @@ export class AccessibilityManager implements IDisposable {
e.stopImmediatePropagation();
}

/**
* Moves the focus of the terminal relatively by a number of rows.
* @param amount The amount of rows to scroll
*/
public moveRowFocus(amount: number): void {
console.log('moveRowFocus', amount);
// Do nothing if not navigating rows or the amount to navigate is 0
if (!this.isNavigatingRows || amount === 0) {
return;
}

// Find and validate the new absolute row position
const buffer = this._terminal.buffer;
const oldRelativeRow = this._rowElements.indexOf(<HTMLElement>document.activeElement);
const oldAbsoluteRow = buffer.ydisp + oldRelativeRow;
const newAbsoluteRow = Math.max(Math.min(oldAbsoluteRow + amount, buffer.lines.length - 1), 0);
if (oldAbsoluteRow === newAbsoluteRow) {
return;
}

// Find the new relative row, this cannot be on a boundary element unless the focused row is the
// top-most or bottom-most row in the buffer.
let newRelativeRow: number;
if (newAbsoluteRow === 0) {
newRelativeRow = 0;
} else if (newAbsoluteRow === buffer.lines.length - 1) {
newRelativeRow = this._terminal.rows - 1;
} else {
newRelativeRow = Math.max(Math.min(oldRelativeRow + amount, this._terminal.rows - 2), 1);
}

// Find the new viewport position
let newYDisp: number;
if (newAbsoluteRow === 0) {
// Start of buffer
newYDisp = 0;
} else if (newAbsoluteRow === buffer.lines.length - 1) {
// End of buffer
newYDisp = buffer.lines.length - 1 - this._terminal.rows;
} else if (newAbsoluteRow > buffer.ydisp && newAbsoluteRow < buffer.ydisp + this._terminal.rows - 1) {
// No scrolling necessary
newYDisp = buffer.ydisp;
} else if (newAbsoluteRow < oldAbsoluteRow) {
// Scrolling up needed
newYDisp = newAbsoluteRow - 1;
} else { // if (newAbsoluteRow > oldAbsoluteRow)
// Scrolling down needed
newYDisp = newAbsoluteRow + this._terminal.rows - 2;
}

// Perform scroll
const scrollAmount = newYDisp - buffer.ydisp;
this._terminal.scrollLines(scrollAmount);

// Focus new row
this._rowElements[newRelativeRow].focus();
}

private _onResize(cols: number, rows: number): void {
// Remove bottom boundary listener
this._rowElements[this._rowElements.length - 1].removeEventListener('focus', this._bottomBoundaryFocusListener);
Expand Down
20 changes: 17 additions & 3 deletions src/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1187,26 +1187,40 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.refresh(0, this.rows - 1);
}

/**
* Scrolls the viewport by a number of rows when not navigating rows. When
* navigating rows, move focus relatively by a number of rows.
* @param amount The number of lines to scroll.
*/
private _accessibilityAwareScrollLines(amount: number): void {
console.log('_accessibilityAwareScrollLines');
if (this.options.screenReaderMode && this._accessibilityManager.isNavigatingRows) {
this._accessibilityManager.moveRowFocus(amount);
} else {
this.scrollLines(amount);
}
}

/**
* Scroll the display of the terminal by a number of pages.
* @param {number} pageCount The number of pages to scroll (negative scrolls up).
*/
public scrollPages(pageCount: number): void {
this.scrollLines(pageCount * (this.rows - 1));
this._accessibilityAwareScrollLines(pageCount * (this.rows - 1));
}

/**
* Scrolls the display of the terminal to the top.
*/
public scrollToTop(): void {
this.scrollLines(-this.buffer.ydisp);
this._accessibilityAwareScrollLines(-this.buffer.ydisp);
}

/**
* Scrolls the display of the terminal to the bottom.
*/
public scrollToBottom(): void {
this.scrollLines(this.buffer.ybase - this.buffer.ydisp);
this._accessibilityAwareScrollLines(this.buffer.ybase - this.buffer.ydisp);
}

/**
Expand Down

0 comments on commit 646813a

Please sign in to comment.