Commit e857d27e authored by nextime's avatar nextime

Fix terminal dimensions calculation at startup and resize

- Calculate terminal dimensions after initial fit to container
- Store initial dimensions for use during connection
- Use calculated dimensions for both startup and resize events
- Ensure proper terminal sizing for applications like top
- Handle browser window resize to update remote terminal dynamically
parent dc3db4b2
...@@ -86,10 +86,36 @@ function connect() { ...@@ -86,10 +86,36 @@ function connect() {
} }
// Initial fit after a short delay to ensure DOM is ready // Initial fit after a short delay to ensure DOM is ready
setTimeout(fitTerminal, 100); setTimeout(() => {
fitTerminal();
// Fit on window resize // Calculate dimensions after initial fit
window.addEventListener('resize', fitTerminal); const initialDimensions = fitAddon.proposeDimensions();
term._initialCols = initialDimensions.cols || 80;
term._initialRows = initialDimensions.rows || 24;
}, 100);
// Fit on window resize and update backend terminal size
window.addEventListener('resize', () => {
fitTerminal();
// Update terminal size on backend if connected
if (connected && requestId) {
const newDimensions = fitAddon.proposeDimensions();
const newCols = newDimensions.cols || 80;
const newRows = newDimensions.rows || 24;
fetch('/terminal/{{ client_id }}/resize', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'request_id=' + encodeURIComponent(requestId) +
'&cols=' + encodeURIComponent(newCols) +
'&rows=' + encodeURIComponent(newRows)
}).catch(error => {
console.error('Resize error:', error);
});
}
});
term.focus(); term.focus();
} }
...@@ -101,13 +127,19 @@ function connect() { ...@@ -101,13 +127,19 @@ function connect() {
document.getElementById('disconnectBtn').disabled = false; document.getElementById('disconnectBtn').disabled = false;
document.getElementById('sshUsername').disabled = true; document.getElementById('sshUsername').disabled = true;
// Send connect request // Use calculated dimensions (either from initial fit or current)
const cols = term._initialCols || fitAddon.proposeDimensions().cols || 80;
const rows = term._initialRows || fitAddon.proposeDimensions().rows || 24;
// Send connect request with terminal dimensions
fetch('/terminal/{{ client_id }}/connect', { fetch('/terminal/{{ client_id }}/connect', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}, },
body: 'username=' + encodeURIComponent(username) body: 'username=' + encodeURIComponent(username) +
'&cols=' + encodeURIComponent(cols) +
'&rows=' + encodeURIComponent(rows)
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
......
...@@ -283,6 +283,8 @@ def logos_files(filename): ...@@ -283,6 +283,8 @@ def logos_files(filename):
@login_required @login_required
def connect_terminal(client_id): def connect_terminal(client_id):
username = request.form.get('username', 'root') username = request.form.get('username', 'root')
cols = int(request.form.get('cols', 80))
rows = int(request.form.get('rows', 24))
request_id = str(uuid.uuid4()) request_id = str(uuid.uuid4())
# Force echo mode before launching wsssh # Force echo mode before launching wsssh
command = ['sh', '-c', f'stty echo && wsssh -p {args.port} {username}@{client_id}.{args.domain}'] command = ['sh', '-c', f'stty echo && wsssh -p {args.port} {username}@{client_id}.{args.domain}']
...@@ -301,7 +303,7 @@ def connect_terminal(client_id): ...@@ -301,7 +303,7 @@ def connect_terminal(client_id):
# Set terminal size to match xterm.js dimensions # Set terminal size to match xterm.js dimensions
import struct import struct
winsize = struct.pack('HHHH', 24, 80, 0, 0) winsize = struct.pack('HHHH', rows, cols, 0, 0)
try: try:
fcntl.ioctl(0, termios.TIOCSWINSZ, winsize) fcntl.ioctl(0, termios.TIOCSWINSZ, winsize)
except (OSError, AttributeError): except (OSError, AttributeError):
...@@ -320,7 +322,7 @@ def connect_terminal(client_id): ...@@ -320,7 +322,7 @@ def connect_terminal(client_id):
stdout=slave, stdout=slave,
stderr=slave, stderr=slave,
preexec_fn=set_controlling_terminal, preexec_fn=set_controlling_terminal,
env=dict(os.environ, TERM='xterm', COLUMNS='80', LINES='24') env=dict(os.environ, TERM='xterm', COLUMNS=str(cols), LINES=str(rows))
) )
os.close(slave) os.close(slave)
...@@ -405,6 +407,36 @@ def disconnect_terminal(client_id): ...@@ -405,6 +407,36 @@ def disconnect_terminal(client_id):
del active_terminals[request_id] del active_terminals[request_id]
return 'OK' return 'OK'
@app.route('/terminal/<client_id>/resize', methods=['POST'])
@login_required
def resize_terminal(client_id):
request_id = request.form.get('request_id')
cols = int(request.form.get('cols', 80))
rows = int(request.form.get('rows', 24))
if request_id in active_terminals:
proc = active_terminals[request_id]['proc']
master = active_terminals[request_id]['master']
if proc.poll() is None:
# Update terminal size
import struct
winsize = struct.pack('HHHH', rows, cols, 0, 0)
try:
fcntl.ioctl(master, termios.TIOCSWINSZ, winsize)
# Also try to update the process's controlling terminal
fcntl.ioctl(0, termios.TIOCSWINSZ, winsize)
except (OSError, AttributeError):
pass
# Send SIGWINCH to notify the process of size change
try:
os.kill(proc.pid, signal.SIGWINCH)
except (OSError, ProcessLookupError):
pass
return 'OK'
async def handle_websocket(websocket, path=None): async def handle_websocket(websocket, path=None):
try: try:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment