Skip to content

Commit

Permalink
[terminal] Always open terminal links on touchevents
Browse files Browse the repository at this point in the history
e.g. when tapping a link on iPad.

Signed-off-by: Jan Keromnes <[email protected]>
  • Loading branch information
jankeromnes committed Jan 13, 2020
1 parent f11045a commit dbfef2a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## v0.15.0

- [terminal] always open terminal links on touchevents (e.g. when tapping a link on iPad)

Breaking changes:

- [task] renamed method `getStrigifiedTaskSchema()` has been renamed to `getStringifiedTaskSchema()` [#6780](https://github.com/eclipse-theia/theia/pull/6780)
Expand Down
28 changes: 25 additions & 3 deletions packages/terminal/src/browser/terminal-linkmatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,18 @@ export abstract class AbstractCmdClickTerminalContribution implements TerminalCo
const validate = this.getValidate(terminalWidget);
const wrappedHandler = (event: MouseEvent, match: string) => {
event.preventDefault();
if (this.isCommandPressed(event)) {
if (this.isCommandPressed(event) || this.wasTouchEvent(event, terminalWidget.lastTouchEndEvent)) {
handler(event, match);
} else {
term.focus();
}
};
const matcherId = term.registerLinkMatcher(regexp, wrappedHandler, {
willLinkActivate: (event: MouseEvent, uri: string) => this.isCommandPressed(event),
willLinkActivate: (event: MouseEvent, uri: string) => this.isCommandPressed(event) || this.wasTouchEvent(event, terminalWidget.lastTouchEndEvent),
tooltipCallback: (event: MouseEvent, uri: string) => {
terminalWidget.showHoverMessage(event.clientX, event.clientY, this.getHoverMessage());
if (!this.wasTouchEvent(event, terminalWidget.lastTouchEndEvent)) {
terminalWidget.showHoverMessage(event.clientX, event.clientY, this.getHoverMessage());
}
},
leaveCallback: (event: MouseEvent, uri: string) => {
terminalWidget.hideHover();
Expand All @@ -64,6 +66,26 @@ export abstract class AbstractCmdClickTerminalContribution implements TerminalCo
return isOSX ? event.metaKey : event.ctrlKey;
}

protected wasTouchEvent(event: MouseEvent, lastTouchEnd: TouchEvent | undefined): boolean {
if (!lastTouchEnd) {
return false;
}
if ((event.timeStamp - lastTouchEnd.timeStamp) > 400) {
// A 'touchend' event typically precedes a matching 'click' event by 50ms.
return false;
}
if (Math.abs(event.pageX - (lastTouchEnd as unknown as MouseEvent).pageX) > 5) {
// Matching 'touchend' and 'click' events typically have the same page coordinates,
// plus or minus 1 pixel.
return false;
}
if (Math.abs(event.pageY - (lastTouchEnd as unknown as MouseEvent).pageY) > 5) {
return false;
}
// We have a match! This link was tapped.
return true;
}

protected getHoverMessage(): string {
if (isOSX) {
return 'Cmd + click to follow link';
Expand Down
15 changes: 15 additions & 0 deletions packages/terminal/src/browser/terminal-widget-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
protected closeOnDispose = true;
protected waitForConnection: Deferred<MessageConnection> | undefined;
protected hoverMessage: HTMLDivElement;
protected lastTouchEnd: TouchEvent | undefined;

@inject(WorkspaceService) protected readonly workspaceService: WorkspaceService;
@inject(WebSocketConnectionProvider) protected readonly webSocketConnectionProvider: WebSocketConnectionProvider;
Expand Down Expand Up @@ -173,6 +174,16 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
this.toDispose.push(this.onTermDidClose);
this.toDispose.push(this.onDidOpenEmitter);

const touchEndListener = (event: TouchEvent) => {
if (this.node.contains(event.target as Node)) {
this.lastTouchEnd = event;
}
};
document.addEventListener('touchend', touchEndListener, { passive: true });
this.onDispose(() => {
document.removeEventListener('touchend', touchEndListener);
});

this.toDispose.push(this.term.onSelectionChange(() => {
if (this.copyOnSelection) {
this.copyOnSelectionHandler.copy(this.term.getSelection());
Expand Down Expand Up @@ -229,6 +240,10 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
return this.shellTerminalServer.getProcessId(this.terminalId);
}

get lastTouchEndEvent(): TouchEvent | undefined {
return this.lastTouchEnd;
}

onDispose(onDispose: () => void): void {
this.toDispose.push(Disposable.create(onDispose));
}
Expand Down

0 comments on commit dbfef2a

Please sign in to comment.