Feature: Web remote terminal (xterm.js + mobile UX polish)

This commit is contained in:
yuanyuanxiang
2026-05-14 23:57:48 +02:00
parent 5d9554780f
commit 5a92c3306f
11 changed files with 953 additions and 8 deletions

View File

@@ -4587,6 +4587,12 @@ BOOL CALLBACK CMy2015RemoteDlg::OfflineProc(CONTEXT_OBJECT* ContextObject)
if (!g_2015RemoteDlg || g_2015RemoteDlg->isClosed)
return FALSE;
// Web 终端的 shell 子上下文断开:通知 WebService 清理 session含通知前端
// 在 RemoveFromHostList 之前做,避免 ctx 被释放后 WebService 还持有悬空指针。
if (WebService().IsRunning() && WebService().IsTerminalContext(ContextObject)) {
WebService().OnTerminalClosed(ContextObject);
}
SOCKET nSocket = ContextObject->sClientSocket;
CDialogBase* p = (CDialogBase*)ContextObject->hDlg;
@@ -4918,6 +4924,19 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
unsigned cmd = ContextObject->InDeCompressedBuffer.GetBYTE(0);
LPBYTE szBuffer = ContextObject->InDeCompressedBuffer.GetBuffer();
unsigned len = ContextObject->InDeCompressedBuffer.GetBufferLen();
// ===== Web 终端的 shell 子上下文:被 WebService 接管时,所有数据走 OnTerminalData =====
// 这里覆盖一个特殊路径Web 接管的 shell 子上下文不开 MFC 对话框hDlg 一直为 NULL
// 因此每个数据包都会走到这个 MessageHandle。我们把字节直接转发给 WebService。
if (WebService().IsRunning() && WebService().IsTerminalContext(ContextObject)) {
if (len == 1 && cmd == TOKEN_TERMINAL_CLOSE) {
WebService().OnTerminalClosed(ContextObject);
} else {
WebService().OnTerminalData(ContextObject, szBuffer, len);
}
return;
}
// 【L】主机上下线和授权
// 【x】对话框相关功能
switch (cmd) {
@@ -5676,11 +5695,25 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
g_2015RemoteDlg->SendMessage(WM_OPENTALKDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_SHELL_START: { // Windows 远程终端
case TOKEN_SHELL_START: { // Windows 老 cmd 管道终端
// 如果是 Web 触发的 term_open把 shell 子上下文交给 WebService 而不是开 MFC dialog
uint64_t devId = ContextObject->GetClientID();
if (WebService().IsRunning() && WebService().IsTermPending(devId)) {
WebService().RegisterTerminalContext(devId, ContextObject, /*isPty*/false);
// hDlg 留 NULL后续数据继续走 MessageHandle 顶部的 IsTerminalContext 分支
break;
}
g_2015RemoteDlg->SendMessage(WM_OPENSHELLDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_TERMINAL_START: { // Linux PTY 终端 (WebView2 + xterm.js)
case TOKEN_TERMINAL_START: { // 现代 PTY 终端 (Linux/macOS/Windows ConPTY)
// 同上Web 触发优先级最高,直接 WebService 接管
uint64_t devId = ContextObject->GetClientID();
if (WebService().IsRunning() && WebService().IsTermPending(devId)) {
WebService().RegisterTerminalContext(devId, ContextObject, /*isPty*/true);
break;
}
// 三个前置条件,缺任何一个都回退到经典终端,并把原因贴到信息列表。
// SYSTEM 场景WebView2 不支持 LocalSystem token会出现"窗口能弹但页面空白"
// 显式拦截一次,避免用户误以为是 bug。