Implement a basic passthrough mode
* [ ] Doesn't immediately stop a frame when passthrough mode is entered. * [ ] Exiting passthrough will leave us in a torn state * [ ] Pretty sure that's the wrong place to put that flag Otherwise this was scary easy
This commit is contained in:
parent
5074335392
commit
f5939ebd61
|
@ -397,3 +397,14 @@ void VtIo::_ShutdownIfNeeded()
|
|||
ServiceLocator::RundownAndExit(ERROR_BROKEN_PIPE);
|
||||
}
|
||||
}
|
||||
|
||||
void VtIo::SetPassthroughMode(const bool enable)
|
||||
{
|
||||
_pVtRenderEngine->SetPassthroughMode(enable);
|
||||
}
|
||||
void VtIo::PassthroughString(std::wstring_view view)
|
||||
{
|
||||
std::wstring wstr{ view };
|
||||
// LOG_IF_FAILED(_pVtRenderEngine->WriteTerminalW(wstr));
|
||||
_pVtRenderEngine->PassthroughString(wstr);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ namespace Microsoft::Console::VirtualTerminal
|
|||
void CloseInput() override;
|
||||
void CloseOutput() override;
|
||||
|
||||
void SetPassthroughMode(const bool enable);
|
||||
void PassthroughString(std::wstring_view view);
|
||||
|
||||
private:
|
||||
// After CreateIoHandlers is called, these will be invalid.
|
||||
wil::unique_hfile _hInput;
|
||||
|
|
|
@ -941,6 +941,16 @@ using Microsoft::Console::VirtualTerminal::StateMachine;
|
|||
const DWORD dwFlags,
|
||||
_Inout_opt_ PSHORT const psScrollY)
|
||||
{
|
||||
if (WI_IsFlagSet(screenInfo.OutputMode, ENABLE_PASSTHROUGH_MODE))
|
||||
{
|
||||
const size_t BufferSize = *pcb;
|
||||
const size_t cch = BufferSize / sizeof(WCHAR);
|
||||
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.GetVtIo()->PassthroughString({ pwchRealUnicode, cch });
|
||||
*pcb += BufferSize;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!WI_IsFlagSet(screenInfo.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING) ||
|
||||
!WI_IsFlagSet(screenInfo.OutputMode, ENABLE_PROCESSED_OUTPUT))
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define VALID_TEXT_ATTRIBUTES (FG_ATTRS | BG_ATTRS | META_ATTRS)
|
||||
|
||||
#define INPUT_MODES (ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT)
|
||||
#define OUTPUT_MODES (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN | ENABLE_LVB_GRID_WORLDWIDE)
|
||||
#define OUTPUT_MODES (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN | ENABLE_LVB_GRID_WORLDWIDE | ENABLE_PASSTHROUGH_MODE)
|
||||
#define PRIVATE_MODES (ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE | ENABLE_AUTO_POSITION | ENABLE_EXTENDED_FLAGS)
|
||||
|
||||
using namespace Microsoft::Console::Types;
|
||||
|
@ -394,7 +394,14 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
|||
|
||||
SCREEN_INFORMATION& screenInfo = context.GetActiveBuffer();
|
||||
const DWORD dwOldMode = screenInfo.OutputMode;
|
||||
const DWORD dwNewMode = mode;
|
||||
DWORD preprocessNewMode = mode;
|
||||
|
||||
if (!gci.IsInVtIoMode() &&
|
||||
(WI_IsFlagSet(preprocessNewMode, ENABLE_PASSTHROUGH_MODE)))
|
||||
{
|
||||
WI_ClearFlag(preprocessNewMode, ENABLE_PASSTHROUGH_MODE);
|
||||
}
|
||||
const DWORD dwNewMode = preprocessNewMode;
|
||||
|
||||
screenInfo.OutputMode = dwNewMode;
|
||||
|
||||
|
@ -413,6 +420,22 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
|||
screenInfo.SetDefaultVtTabStops();
|
||||
}
|
||||
|
||||
if (gci.IsInVtIoMode())
|
||||
{
|
||||
// if we're moving from passthrough on->off
|
||||
if (WI_IsFlagClear(dwNewMode, ENABLE_PASSTHROUGH_MODE) &&
|
||||
WI_IsFlagSet(dwOldMode, ENABLE_PASSTHROUGH_MODE))
|
||||
{
|
||||
gci.GetVtIo()->SetPassthroughMode(false);
|
||||
}
|
||||
// if we're moving from passthrough off->on
|
||||
else if (WI_IsFlagSet(dwNewMode, ENABLE_PASSTHROUGH_MODE) &&
|
||||
WI_IsFlagClear(dwOldMode, ENABLE_PASSTHROUGH_MODE))
|
||||
{
|
||||
gci.GetVtIo()->SetPassthroughMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
gci.SetVirtTermLevel(WI_IsFlagSet(dwNewMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING) ? 1 : 0);
|
||||
gci.SetAutomaticReturnOnNewline(WI_IsFlagSet(screenInfo.OutputMode, DISABLE_NEWLINE_AUTO_RETURN) ? false : true);
|
||||
gci.SetGridRenderingAllowedWorldwide(WI_IsFlagSet(screenInfo.OutputMode, ENABLE_LVB_GRID_WORLDWIDE));
|
||||
|
|
|
@ -71,6 +71,9 @@ Revision History:
|
|||
#define CONSOLE_SUSPENDED (CONSOLE_OUTPUT_SUSPENDED)
|
||||
// clang-format on
|
||||
|
||||
// ENABLE_LVB_GRID_WORLDWIDE is 0x0010
|
||||
#define ENABLE_PASSTHROUGH_MODE 0x0020
|
||||
|
||||
class COOKED_READ_DATA;
|
||||
class CommandHistory;
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@ using namespace Microsoft::Console::Types;
|
|||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
if (_passthroughMode)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// If there's nothing to do, quick return
|
||||
bool somethingToDo = _fInvalidRectUsed ||
|
||||
|
|
|
@ -417,3 +417,14 @@ HRESULT VtEngine::RequestCursor() noexcept
|
|||
RETURN_IF_FAILED(_Flush());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void VtEngine::SetPassthroughMode(const bool enable)
|
||||
{
|
||||
_passthroughMode = enable;
|
||||
}
|
||||
|
||||
void VtEngine::PassthroughString(const std::wstring& wstr)
|
||||
{
|
||||
LOG_IF_FAILED(WriteTerminalW(wstr));
|
||||
LOG_IF_FAILED(_Flush());
|
||||
}
|
||||
|
|
|
@ -95,6 +95,9 @@ namespace Microsoft::Console::Render
|
|||
|
||||
void SetTerminalOwner(Microsoft::Console::ITerminalOwner* const terminalOwner);
|
||||
|
||||
void SetPassthroughMode(const bool enable);
|
||||
void PassthroughString(const std::wstring& wstr);
|
||||
|
||||
protected:
|
||||
wil::unique_hfile _hFile;
|
||||
std::string _buffer;
|
||||
|
@ -133,6 +136,8 @@ namespace Microsoft::Console::Render
|
|||
|
||||
Microsoft::Console::VirtualTerminal::RenderTracing _trace;
|
||||
|
||||
bool _passthroughMode{ false };
|
||||
|
||||
[[nodiscard]] HRESULT _Write(std::string_view const str) noexcept;
|
||||
[[nodiscard]] HRESULT _WriteFormattedString(const std::string* const pFormat, ...) noexcept;
|
||||
[[nodiscard]] HRESULT _Flush() noexcept;
|
||||
|
|
|
@ -2,9 +2,77 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#include <windows.h>
|
||||
#include <wil\Common.h>
|
||||
#include <wil\result.h>
|
||||
#include <wil\resource.h>
|
||||
#include <wil\wistd_functional.h>
|
||||
#include <wil\wistd_memory.h>
|
||||
#include <stdlib.h> /* srand, rand */
|
||||
#include <time.h> /* time */
|
||||
#include <conio.h>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
#define ENABLE_PASSTHROUGH_MODE 0x0020
|
||||
|
||||
std::string csi(std::string seq)
|
||||
{
|
||||
std::string fullSeq = "\x1b[";
|
||||
fullSeq += seq;
|
||||
return fullSeq;
|
||||
}
|
||||
|
||||
std::string osc(std::string seq)
|
||||
{
|
||||
std::string fullSeq = "\x1b]";
|
||||
fullSeq += seq;
|
||||
fullSeq += "\x7";
|
||||
return fullSeq;
|
||||
}
|
||||
|
||||
// This wmain exists for help in writing scratch programs while debugging.
|
||||
int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/)
|
||||
{
|
||||
wprintf(L"Attempting to start passthrough mode...\n");
|
||||
auto hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
DWORD dwMode = 0;
|
||||
THROW_LAST_ERROR_IF(!GetConsoleMode(hOut, &dwMode));
|
||||
|
||||
wprintf(L"Original Mode: 0x%x\n", dwMode);
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
dwMode |= DISABLE_NEWLINE_AUTO_RETURN;
|
||||
dwMode |= ENABLE_PASSTHROUGH_MODE;
|
||||
|
||||
wprintf(L"Requested Mode: 0x%x\n", dwMode);
|
||||
THROW_LAST_ERROR_IF(!SetConsoleMode(hOut, dwMode));
|
||||
|
||||
DWORD roundtripMode = 0;
|
||||
THROW_LAST_ERROR_IF(!GetConsoleMode(hOut, &roundtripMode));
|
||||
wprintf(L"Rountripped Mode: 0x%x\n", dwMode);
|
||||
|
||||
if (roundtripMode != dwMode)
|
||||
{
|
||||
wprintf(L"Mode did not rountrip\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintf(L"Mode rountripped successfully\n");
|
||||
}
|
||||
|
||||
wprintf(L"Press a key to continue\n");
|
||||
_getch();
|
||||
|
||||
wprintf(L"We're going to write some VT straight to the terminal\n");
|
||||
|
||||
printf(csi("31m").c_str());
|
||||
printf(osc("0;Title:foo").c_str());
|
||||
wprintf(L"Press a key to continue\n");
|
||||
_getch();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
5
tools/bzcon.cmd
Normal file
5
tools/bzcon.cmd
Normal file
|
@ -0,0 +1,5 @@
|
|||
@echo off
|
||||
|
||||
"%msbuild%" Openconsole.sln /t:Conhost\Host_EXE /m /p:Configuration=Debug /p:Platform=%ARCH%
|
||||
|
||||
:eof
|
24
tools/scratch.cmd
Normal file
24
tools/scratch.cmd
Normal file
|
@ -0,0 +1,24 @@
|
|||
@echo off
|
||||
|
||||
rem openvt - launch the vtterm binary
|
||||
rem Runs the VtPipeTerm.exe binary generated by the build in the debug directory.
|
||||
rem Passes any args along.
|
||||
|
||||
setlocal
|
||||
set _last_build=%OPENCON%\bin\%ARCH%\%_LAST_BUILD_CONF%
|
||||
|
||||
if not exist %_last_build%\scratch.exe (
|
||||
echo Could not locate the scratch.exe in %_last_build%. Double check that it has been built and try again.
|
||||
goto :eof
|
||||
)
|
||||
|
||||
set _r=%random%
|
||||
set copy_dir=OpenConsole\%_r%
|
||||
rem Generate a unique name, so that we can debug multiple revisions of the binary at the same time if needed.
|
||||
|
||||
(xcopy /Y %_last_build%\OpenConsole.exe %TEMP%\%copy_dir%\conhost.exe*) > nul
|
||||
(xcopy /Y %_last_build%\console.dll %TEMP%\%copy_dir%\console.dll*) > nul
|
||||
(xcopy /Y %_last_build%\scratch.exe %TEMP%\%copy_dir%\scratch.exe*) > nul
|
||||
|
||||
echo Launching %TEMP%\%copy_dir%\scratch.exe...
|
||||
%TEMP%\%copy_dir%\scratch.exe
|
Loading…
Reference in a new issue