Skip to content

Commit

Permalink
Merge pull request #4913 from Tyriar/tyriar/wheel_handlers
Browse files Browse the repository at this point in the history
addCustomWheelEventHandler API
  • Loading branch information
Tyriar committed Dec 12, 2023
2 parents b4226bc + 88ba66d commit 1f15c47
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 10 deletions.
23 changes: 13 additions & 10 deletions src/browser/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { addDisposableDomListener } from 'browser/Lifecycle';
import { Linkifier2 } from 'browser/Linkifier2';
import * as Strings from 'browser/LocalizableStrings';
import { OscLinkProvider } from 'browser/OscLinkProvider';
import { CharacterJoinerHandler, CustomKeyEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal, IViewport } from 'browser/Types';
import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal, IViewport } from 'browser/Types';
import { Viewport } from 'browser/Viewport';
import { BufferDecorationRenderer } from 'browser/decorations/BufferDecorationRenderer';
import { OverviewRulerRenderer } from 'browser/decorations/OverviewRulerRenderer';
Expand Down Expand Up @@ -74,6 +74,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
public browser: IBrowser = Browser as any;

private _customKeyEventHandler: CustomKeyEventHandler | undefined;
private _customWheelEventHandler: CustomWheelEventHandler | undefined;

// browser services
private _decorationService: DecorationService;
Expand Down Expand Up @@ -633,6 +634,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
break;
case 'wheel':
if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
return false;
}
const amount = self.viewport!.getLinesScrolled(ev as WheelEvent);

if (amount === 0) {
Expand Down Expand Up @@ -792,6 +796,10 @@ export class Terminal extends CoreTerminal implements ITerminal {
// do nothing, if app side handles wheel itself
if (requestedEvents.wheel) return;

if (this._customWheelEventHandler && this._customWheelEventHandler(ev) === false) {
return false;
}

if (!this.buffer.hasScrollback) {
// Convert wheel events into up/down events when the buffer does not have scrollback, this
// enables scrolling in apps hosted in the alt buffer such as vim or tmux.
Expand Down Expand Up @@ -878,19 +886,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
paste(data, this.textarea!, this.coreService, this.optionsService);
}

/**
* Attaches a custom key event handler which is run before keys are processed,
* giving consumers of xterm.js ultimate control as to what keys should be
* processed by the terminal and what keys should not.
* @param customKeyEventHandler The custom KeyboardEvent handler to attach.
* This is a function that takes a KeyboardEvent, allowing consumers to stop
* propagation and/or prevent the default action. The function returns whether
* the event should be processed by xterm.js.
*/
public attachCustomKeyEventHandler(customKeyEventHandler: CustomKeyEventHandler): void {
this._customKeyEventHandler = customKeyEventHandler;
}

public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
this._customWheelEventHandler = customWheelEventHandler;
}

public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
return this.linkifier2.registerLinkProvider(linkProvider);
}
Expand Down
3 changes: 3 additions & 0 deletions src/browser/TestUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ export class MockTerminal implements ITerminal {
public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {
throw new Error('Method not implemented.');
}
public attachCustomWheelEventHandler(customWheelEventHandler: (event: WheelEvent) => boolean): void {
throw new Error('Method not implemented.');
}
public registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise<boolean>): IDisposable {
throw new Error('Method not implemented.');
}
Expand Down
1 change: 1 addition & 0 deletions src/browser/Types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface ITerminal extends InternalPassthroughApis, ICoreTerminal {
}

export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
export type CustomWheelEventHandler = (event: WheelEvent) => boolean;

export type LineData = CharData[];

Expand Down
3 changes: 3 additions & 0 deletions src/browser/public/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ export class Terminal extends Disposable implements ITerminalApi {
public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {
this._core.attachCustomKeyEventHandler(customKeyEventHandler);
}
public attachCustomWheelEventHandler(customWheelEventHandler: (event: WheelEvent) => boolean): void {
this._core.attachCustomWheelEventHandler(customWheelEventHandler);
}
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
return this._core.registerLinkProvider(linkProvider);
}
Expand Down
1 change: 1 addition & 0 deletions test/playwright/TestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type TerminalProxyCustomOverrides = 'buffer' | (
'options' |
'open' |
'attachCustomKeyEventHandler' |
'attachCustomWheelEventHandler' |
'registerLinkProvider' |
'registerCharacterJoiner' |
'deregisterCharacterJoiner' |
Expand Down
22 changes: 22 additions & 0 deletions typings/xterm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,28 @@ declare module '@xterm/xterm' {
*/
attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void;

/**
* Attaches a custom wheel event handler which is run before keys are
* processed, giving consumers of xterm.js control over whether to proceed
* or cancel terminal wheel events.
* @param customMouseEventHandler The custom WheelEvent handler to attach.
* This is a function that takes a WheelEvent, allowing consumers to stop
* propagation and/or prevent the default action. The function returns
* whether the event should be processed by xterm.js.
*
* @example A handler that prevents all wheel events while ctrl is held from
* being processed.
* ```ts
* term.attachCustomKeyEventHandler(ev => {
* if (ev.ctrlKey) {
* return false;
* }
* return true;
* });
* ```
*/
attachCustomWheelEventHandler(customWheelEventHandler: (event: WheelEvent) => boolean): void;

/**
* Registers a link provider, allowing a custom parser to be used to match
* and handle links. Multiple link providers can be used, they will be asked
Expand Down

0 comments on commit 1f15c47

Please sign in to comment.