User/oneblue/initial tty size (#13786)

* Save state

* Pass in the terminal size when creating a WSLA process
This commit is contained in:
Blue 2025-11-26 19:33:17 +00:00 committed by GitHub
parent 256e637795
commit 315cc27a5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 30 additions and 11 deletions

View File

@ -1666,10 +1666,8 @@ struct WSLA_TTY_RELAY
int32_t TtyInput;
int32_t TtyOutput;
int32_t TtyControl;
uint32_t Rows;
uint32_t Columns;
PRETTY_PRINT(FIELD(Header), FIELD(TtyMaster), FIELD(TtyInput), FIELD(TtyOutput), FIELD(TtyControl), FIELD(Rows), FIELD(Columns));
PRETTY_PRINT(FIELD(Header), FIELD(TtyMaster), FIELD(TtyInput), FIELD(TtyOutput), FIELD(TtyControl));
};
struct WSLA_ACCEPT

View File

@ -48,6 +48,12 @@ void WSLAProcessLauncher::AddFd(WSLA_PROCESS_FD Fd)
m_fds.push_back(Fd);
}
void WSLAProcessLauncher::SetTtySize(ULONG Rows, ULONG Columns)
{
m_rows = Rows;
m_columns = Columns;
}
std::tuple<WSLA_PROCESS_OPTIONS, std::vector<const char*>, std::vector<const char*>> WSLAProcessLauncher::CreateProcessOptions()
{
std::vector<const char*> commandLine;
@ -64,6 +70,8 @@ std::tuple<WSLA_PROCESS_OPTIONS, std::vector<const char*>, std::vector<const cha
options.FdsCount = static_cast<DWORD>(m_fds.size());
options.Environment = environment.data();
options.EnvironmentCount = static_cast<DWORD>(environment.size());
options.TtyColumns = m_columns;
options.TtyRows = m_rows;
return std::make_tuple(options, std::move(commandLine), std::move(environment));
}

View File

@ -82,6 +82,7 @@ public:
ProcessFlags Flags = ProcessFlags::Stdout | ProcessFlags::Stderr);
void AddFd(WSLA_PROCESS_FD Fd);
void SetTtySize(ULONG Rows, ULONG Columns);
// TODO: Add overloads for IWSLAContainer once implemented.
ClientRunningWSLAProcess Launch(IWSLASession& Session);
@ -95,6 +96,8 @@ protected:
std::string m_executable;
std::vector<std::string> m_arguments;
std::vector<std::string> m_environment;
DWORD m_rows = 0;
DWORD m_columns = 0;
};
} // namespace wsl::windows::common

View File

@ -1606,17 +1606,23 @@ int WslaShell(_In_ std::wstring_view commandLine)
THROW_HR_IF(E_FAIL, initProcess.WaitAndCaptureOutput().Code != 0);
}
// Get the terminal size.
HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE Stdin = GetStdHandle(STD_INPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFOEX Info{};
Info.cbSize = sizeof(Info);
THROW_IF_WIN32_BOOL_FALSE(::GetConsoleScreenBufferInfoEx(Stdout, &Info));
wsl::windows::common::WSLAProcessLauncher launcher{shell, {shell}, {"TERM=xterm-256color"}, ProcessFlags::None};
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 0, .Type = WSLAFdTypeTerminalInput});
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 1, .Type = WSLAFdTypeTerminalOutput});
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 2, .Type = WSLAFdTypeTerminalControl});
launcher.SetTtySize(Info.srWindow.Bottom - Info.srWindow.Top + 1, Info.srWindow.Right - Info.srWindow.Left + 1);
auto process = launcher.Launch(*session);
// Configure console for interactive usage.
HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE Stdin = GetStdHandle(STD_INPUT_HANDLE);
{
DWORD OutputMode{};
THROW_LAST_ERROR_IF(!::GetConsoleMode(Stdout, &OutputMode));

View File

@ -727,7 +727,8 @@ std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::For
return Fork(m_initChannel, Type);
}
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::Fork(wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type)
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::Fork(
wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type, ULONG TtyRows, ULONG TtyColumns)
{
uint32_t port{};
int32_t pid{};
@ -737,8 +738,8 @@ std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::For
WSLA_FORK message;
message.ForkType = Type;
message.TtyColumns = 80;
message.TtyRows = 80;
message.TtyColumns = static_cast<uint16_t>(TtyColumns);
message.TtyRows = static_cast<uint16_t>(TtyRows);
const auto& response = Channel.Transaction(message);
port = response.Port;
pid = response.Pid;
@ -857,7 +858,7 @@ Microsoft::WRL::ComPtr<WSLAProcess> WSLAVirtualMachine::CreateLinuxProcess(_In_
// If this is an interactive tty, we need a relay process
if (interactiveTty)
{
auto [grandChildPid, ptyMaster, grandChildChannel] = Fork(childChannel, WSLA_FORK::Pty);
auto [grandChildPid, ptyMaster, grandChildChannel] = Fork(childChannel, WSLA_FORK::Pty, Options.TtyRows, Options.TtyColumns);
WSLA_TTY_RELAY relayMessage{};
relayMessage.TtyMaster = ptyMaster;
relayMessage.TtyInput = ttyInput->Fd;

View File

@ -82,7 +82,8 @@ private:
void OnCrash(_In_ const HCS_EVENT* Event);
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> Fork(enum WSLA_FORK::ForkType Type);
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> Fork(wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type);
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> Fork(
wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type, ULONG TtyRows = 0, ULONG TtyColumns = 0);
int32_t ExpectClosedChannelOrError(wsl::shared::SocketChannel& Channel);
ConnectedSocket ConnectSocket(wsl::shared::SocketChannel& Channel, int32_t Fd);

View File

@ -112,6 +112,8 @@ struct WSLA_PROCESS_OPTIONS
ULONG EnvironmentCount;
[unique, size_is(FdsCount)] WSLA_PROCESS_FD *Fds;
int FdsCount;
ULONG TtyRows; // Only needed when tty fd's are passed.
ULONG TtyColumns;
};
struct WSLA_VOLUME