From 64fc0f335a7c209102397043d527422b787f0181 Mon Sep 17 00:00:00 2001 From: sawka Date: Wed, 24 Aug 2022 19:00:03 -0700 Subject: [PATCH] fix overscroll behavior in xterm.js terminal and deal with focus in a better way. restore scrollbars for terminals. scroll focused terminals into view. --- src/main.tsx | 47 +++++++++++++++++++++++++++++++++++------------ src/model.ts | 7 +++---- src/sh2.less | 35 ++++++++++++++++++++++++++++++----- src/term.ts | 9 +++++++-- 4 files changed, 75 insertions(+), 23 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index f85ac1f1d..64508bac3 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -273,6 +273,16 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width ); } + + @boundMethod + clickTermBlock(e : any, handler : string) { + let {sw, line} = this.props; + let model = GlobalModel; + let termWrap = sw.getTermWrap(line.cmdid); + if (termWrap != null) { + termWrap.terminal.focus(); + } + } render() { let {sw, line, width} = this.props; @@ -325,6 +335,9 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width
+ +
+
(loading)
@@ -348,11 +361,11 @@ class Line extends React.Component<{sw : ScreenWindow, line : LineType, width : } @mobxReact.observer -class CmdInput extends React.Component<{}, {}> { +class TextAreaInput extends React.Component<{}, {}> { lastTab : boolean = false; lastHistoryUpDown : boolean = false; lastTabCurLine : mobx.IObservableValue = mobx.observable.box(null); - + componentDidMount() { let input = document.getElementById("main-cmd-input"); if (input != null) { @@ -464,6 +477,23 @@ class CmdInput extends React.Component<{}, {}> { model.submitRawCommand(commandStr, true); } + render() { + let model = GlobalModel; + let inputModel = model.inputModel; + let curLine = inputModel.getCurLine(); + let numLines = curLine.split("\n").length; + let displayLines = numLines; + if (displayLines > 5) { + displayLines = 5; + } + return ( + + ); + } +} + +@mobxReact.observer +class CmdInput extends React.Component<{}, {}> { getAfterSlash(s : string) : string { if (s.startsWith("^/")) { return s.substr(1); @@ -479,14 +509,8 @@ class CmdInput extends React.Component<{}, {}> { } render() { + console.log("render CmdInput"); let model = GlobalModel; - let inputModel = model.inputModel; - let curLine = inputModel.getCurLine(); - let numLines = curLine.split("\n").length; - let displayLines = numLines; - if (displayLines > 5) { - displayLines = 5; - } let win = GlobalModel.getActiveWindow(); let ri : RemoteInstanceType = null; let rptr : RemotePtrType = null; @@ -494,7 +518,6 @@ class CmdInput extends React.Component<{}, {}> { ri = win.getCurRemoteInstance(); rptr = win.curRemote.get(); } - console.log("cmd-input remote", ri); let remote : RemoteType = null; let remoteState : RemoteStateType = null; if (ri != null) { @@ -559,7 +582,7 @@ class CmdInput extends React.Component<{}, {}> {
{remoteStr}
- +
@@ -601,7 +624,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> { if (sw && sw.shouldFollow.get() != atBottom) { mobx.action(() => sw.shouldFollow.set(atBottom))(); } - // console.log("scroll-handler>", atBottom, target.scrollTop, target.scrollHeight); + // console.log("scroll-handler (sw)>", atBottom, target.scrollTop, target.scrollHeight, event); } componentDidMount() { diff --git a/src/model.ts b/src/model.ts index ca138691f..49f366d91 100644 --- a/src/model.ts +++ b/src/model.ts @@ -885,10 +885,6 @@ class Model { return; } termWrap.terminal.focus(); - let lineElem = document.getElementById("line-" + getLineId(switchLine)); - if (lineElem != null) { - lineElem.scrollIntoView({block: "nearest"}); - } console.log("arrow-up", this.getFocusedLine(), "=>", switchLine); } @@ -995,6 +991,9 @@ class Model { this.updateCmd(lineMsg.cmd); } } + else if ("cmd" in update) { + this.updateCmd(update.cmd); + } if ("window" in update) { let winMsg : WindowUpdateType = update; this.updateWindow(winMsg.window, false); diff --git a/src/sh2.less b/src/sh2.less index 88a0d781e..321b40464 100644 --- a/src/sh2.less +++ b/src/sh2.less @@ -313,6 +313,7 @@ html, body, #main { .line.line-cmd { flex-direction: column; + scroll-margin-bottom: 20px; .avatar { cursor: pointer; @@ -343,10 +344,7 @@ html, body, #main { align-self: flex-start; &.focus { - /* box-shadow: -8px 0 12px -5px #aaa; */ - /* box-shadow: 0 0 0 4px hsl(0, 0%, 20%);*/ - /* filter:drop-shadow(3px 3px 10px #555); */ - box-shadow: 0 0 4px 4px rgba(255, 255, 255, 0.3); + box-shadow: 0 0 3px 3px rgba(255, 255, 255, 0.3); } } } @@ -470,6 +468,33 @@ html, body, #main { body .xterm .xterm-viewport { overflow-y: auto; + width: calc(100% + 5px); +} + +.terminal-wrapper { + position: relative; + + .term-block { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: transparent; + z-index: 10; + /* background-color: rgba(50, 50, 240, 0.05); */ + } +} + +.terminal-wrapper.focus .xterm { + .xterm-screen { + overflow-y: scroll; + overscroll-behavior: contain; + } + + .xterm-viewport { + overscroll-behavior: contain; + } } .cmd-input-info, .xterm-viewport { @@ -489,7 +514,7 @@ body .xterm .xterm-viewport { } .lines { - background-color: black; + /* background-color: rgba(50, 50, 240, 0.05); */ display: flex; flex-direction: column; height: 80vh; diff --git a/src/term.ts b/src/term.ts index 3240606c3..92e75bd21 100644 --- a/src/term.ts +++ b/src/term.ts @@ -64,7 +64,7 @@ class TermWrap { this.usedRows = mobx.observable.box(termOpts.rows); } let cols = termOpts.cols; - let maxCols = Math.trunc((winSize.width - 25) / DefaultCellWidth); + let maxCols = Math.trunc((winSize.width - 25) / DefaultCellWidth) - 1; if (maxCols > cols) { cols = maxCols; } @@ -105,6 +105,12 @@ class TermWrap { mobx.action(() => { this.isFocused.set(focus); })(); + if (this.connectedElem != null) { + let lineElem = this.connectedElem.closest(".line"); + if (lineElem != null) { + lineElem.scrollIntoView({behavior: "smooth", block: "nearest"}); + } + } } getTermUsedRows() : number { @@ -200,7 +206,6 @@ class TermWrap { this.dataUpdates.push({data: data, pos: pos}); return; } - console.log("pty-update", this.cmdId, this.ptyPos, data.length); if (pos > this.ptyPos) { throw new Error(sprintf("invalid pty-update, data-pos[%d] does not match term-pos[%d] cmdid[%s]", pos, this.ptyPos, this.cmdId)); }