Fix mobile terminal touch scrolling (#1450)
* Fix mobile terminal touch scrolling * Fix bot comments --------- Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
This commit is contained in:
committed by
GitHub
co-authored by
Konstantin Zolin
parent
4055bf397e
commit
c2ca844402
@@ -65,6 +65,14 @@ type FitAddonWithObserveResize = FitAddon & {
|
|||||||
observeResize?: () => void;
|
observeResize?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type RendererWithScrollbar = {
|
||||||
|
renderScrollbar?: (...args: unknown[]) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TerminalWithRenderer = {
|
||||||
|
renderer?: RendererWithScrollbar;
|
||||||
|
};
|
||||||
|
|
||||||
interface TerminalViewportProps {
|
interface TerminalViewportProps {
|
||||||
sessionKey: string;
|
sessionKey: string;
|
||||||
chunks: TerminalChunk[];
|
chunks: TerminalChunk[];
|
||||||
@@ -787,7 +795,9 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
container.addEventListener('pointercancel', handlePointerUp, listenerOptions);
|
container.addEventListener('pointercancel', handlePointerUp, listenerOptions);
|
||||||
|
|
||||||
const previousTouchAction = container.style.touchAction;
|
const previousTouchAction = container.style.touchAction;
|
||||||
container.style.touchAction = 'manipulation';
|
const previousOverscrollBehaviorY = container.style.overscrollBehaviorY;
|
||||||
|
container.style.touchAction = 'none';
|
||||||
|
container.style.overscrollBehaviorY = 'contain';
|
||||||
|
|
||||||
touchScrollCleanupRef.current = () => {
|
touchScrollCleanupRef.current = () => {
|
||||||
stopKinetic();
|
stopKinetic();
|
||||||
@@ -801,6 +811,7 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
container.removeEventListener('pointerup', handlePointerUp, listenerOptions);
|
container.removeEventListener('pointerup', handlePointerUp, listenerOptions);
|
||||||
container.removeEventListener('pointercancel', handlePointerUp, listenerOptions);
|
container.removeEventListener('pointercancel', handlePointerUp, listenerOptions);
|
||||||
container.style.touchAction = previousTouchAction;
|
container.style.touchAction = previousTouchAction;
|
||||||
|
container.style.overscrollBehaviorY = previousOverscrollBehaviorY;
|
||||||
};
|
};
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -942,7 +953,9 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
container.addEventListener('touchcancel', handleTouchEnd as unknown as EventListener, listenerOptions);
|
container.addEventListener('touchcancel', handleTouchEnd as unknown as EventListener, listenerOptions);
|
||||||
|
|
||||||
const previousTouchAction = container.style.touchAction;
|
const previousTouchAction = container.style.touchAction;
|
||||||
container.style.touchAction = 'manipulation';
|
const previousOverscrollBehaviorY = container.style.overscrollBehaviorY;
|
||||||
|
container.style.touchAction = 'none';
|
||||||
|
container.style.overscrollBehaviorY = 'contain';
|
||||||
|
|
||||||
touchScrollCleanupRef.current = () => {
|
touchScrollCleanupRef.current = () => {
|
||||||
stopKinetic();
|
stopKinetic();
|
||||||
@@ -956,6 +969,7 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
container.removeEventListener('touchend', handleTouchEnd as unknown as EventListener, listenerOptions);
|
container.removeEventListener('touchend', handleTouchEnd as unknown as EventListener, listenerOptions);
|
||||||
container.removeEventListener('touchcancel', handleTouchEnd as unknown as EventListener, listenerOptions);
|
container.removeEventListener('touchcancel', handleTouchEnd as unknown as EventListener, listenerOptions);
|
||||||
container.style.touchAction = previousTouchAction;
|
container.style.touchAction = previousTouchAction;
|
||||||
|
container.style.overscrollBehaviorY = previousOverscrollBehaviorY;
|
||||||
};
|
};
|
||||||
}, [enableTouchScroll, useHiddenInputOverlay, focusHiddenInput, fontSize]);
|
}, [enableTouchScroll, useHiddenInputOverlay, focusHiddenInput, fontSize]);
|
||||||
|
|
||||||
@@ -966,6 +980,7 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
let localTextareaObserver: MutationObserver | null = null;
|
let localTextareaObserver: MutationObserver | null = null;
|
||||||
let localDisposables: Array<{ dispose: () => void }> = [];
|
let localDisposables: Array<{ dispose: () => void }> = [];
|
||||||
let restorePatchedScrollToBottom: (() => void) | null = null;
|
let restorePatchedScrollToBottom: (() => void) | null = null;
|
||||||
|
let restorePatchedScrollbar: (() => void) | null = null;
|
||||||
let restoreContainerFocus: (() => void) | null = null;
|
let restoreContainerFocus: (() => void) | null = null;
|
||||||
|
|
||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
@@ -1064,6 +1079,18 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
|
|
||||||
terminal.loadAddon(fitAddon);
|
terminal.loadAddon(fitAddon);
|
||||||
terminal.open(container);
|
terminal.open(container);
|
||||||
|
if (enableTouchScroll) {
|
||||||
|
const renderer = (terminal as unknown as TerminalWithRenderer).renderer;
|
||||||
|
if (renderer && typeof renderer.renderScrollbar === 'function') {
|
||||||
|
const originalRenderScrollbar = renderer.renderScrollbar.bind(renderer);
|
||||||
|
renderer.renderScrollbar = () => {};
|
||||||
|
restorePatchedScrollbar = () => {
|
||||||
|
renderer.renderScrollbar = originalRenderScrollbar;
|
||||||
|
};
|
||||||
|
} else if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.warn('[TerminalViewport] Ghostty renderer scrollbar hook is unavailable; touch scrollbar suppression may need an update.');
|
||||||
|
}
|
||||||
|
}
|
||||||
bumpTerminalReady();
|
bumpTerminalReady();
|
||||||
cursorBlinkStateRef.current = false;
|
cursorBlinkStateRef.current = false;
|
||||||
|
|
||||||
@@ -1158,6 +1185,8 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
localDisposables.forEach((disposable) => disposable.dispose());
|
localDisposables.forEach((disposable) => disposable.dispose());
|
||||||
restorePatchedScrollToBottom?.();
|
restorePatchedScrollToBottom?.();
|
||||||
restorePatchedScrollToBottom = null;
|
restorePatchedScrollToBottom = null;
|
||||||
|
restorePatchedScrollbar?.();
|
||||||
|
restorePatchedScrollbar = null;
|
||||||
if (localTerminalTextarea) {
|
if (localTerminalTextarea) {
|
||||||
localTerminalTextarea.removeEventListener('focus', handleTerminalTextareaFocus);
|
localTerminalTextarea.removeEventListener('focus', handleTerminalTextareaFocus);
|
||||||
localTerminalTextarea.removeEventListener('blur', handleTerminalTextareaBlur);
|
localTerminalTextarea.removeEventListener('blur', handleTerminalTextareaBlur);
|
||||||
|
|||||||
Reference in New Issue
Block a user