Qt: Make win32 console less garbage

This commit is contained in:
Connor McLaughlin 2022-05-03 14:06:04 +10:00 committed by refractionpcsx2
parent 4543ddbcc2
commit 8751a2d330
2 changed files with 119 additions and 46 deletions

View File

@ -486,7 +486,11 @@ void QtHost::HookSignals()
static bool s_debugger_attached = false; static bool s_debugger_attached = false;
static bool s_console_handle_set = false; static bool s_console_handle_set = false;
static HANDLE s_console_handle = nullptr; static bool s_console_allocated = false;
static HANDLE s_console_handle = INVALID_HANDLE_VALUE;
static HANDLE s_old_console_stdin = NULL;
static HANDLE s_old_console_stdout = NULL;
static HANDLE s_old_console_stderr = NULL;
static void __concall ConsoleWinQt_SetTitle(const wxString& title) static void __concall ConsoleWinQt_SetTitle(const wxString& title)
{ {
@ -498,31 +502,33 @@ static void __concall ConsoleWinQt_DoSetColor(ConsoleColors color)
if (!s_console_handle) if (!s_console_handle)
return; return;
static constexpr WORD colors[ConsoleColors_Count] = { static constexpr wchar_t colors[][ConsoleColors_Count] = {
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // default L"\033[0m", // default
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // black L"\033[30m\033[1m", // black
FOREGROUND_GREEN, // green L"\033[32m", // green
FOREGROUND_RED, // red L"\033[31m", // red
FOREGROUND_BLUE, // blue L"\033[34m", // blue
FOREGROUND_RED | FOREGROUND_BLUE, // magenta L"\033[35m", // magenta
FOREGROUND_RED | FOREGROUND_GREEN, // orange L"\033[35m", // orange (FIXME)
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // gray L"\033[37m", // gray
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // cyan L"\033[36m", // cyan
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, // yellow L"\033[33m", // yellow
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, // white L"\033[37m", // white
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // strong black L"\033[30m\033[1m", // strong black
FOREGROUND_RED | FOREGROUND_INTENSITY, // strong red L"\033[31m\033[1m", // strong red
FOREGROUND_GREEN | FOREGROUND_INTENSITY, // strong green L"\033[32m\033[1m", // strong green
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // strong blue L"\033[34m\033[1m", // strong blue
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, // strong magenta L"\033[35m\033[1m", // strong magenta
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, // strong orange L"\033[35m\033[1m", // strong orange (FIXME)
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // strong gray L"\033[37m\033[1m", // strong gray
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // strong cyan L"\033[36m\033[1m", // strong cyan
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, // strong yellow L"\033[33m\033[1m", // strong yellow
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, // strong white L"\033[37m\033[1m", // strong white
}; };
SetConsoleTextAttribute(s_console_handle, colors[static_cast<u32>(color)]); const wchar_t* colortext = colors[static_cast<u32>(color)];
DWORD written;
WriteConsoleW(s_console_handle, colortext, std::wcslen(colortext), &written, nullptr);
} }
static void __concall ConsoleWinQt_Newline() static void __concall ConsoleWinQt_Newline()
@ -586,41 +592,61 @@ static BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
return TRUE; return TRUE;
} }
#endif static bool EnableVirtualTerminalProcessing(HANDLE hConsole)
void QtHost::UpdateLogging()
{ {
// TODO: Make this an actual option. if (hConsole == INVALID_HANDLE_VALUE)
const bool system_console_enabled = QtHost::GetBaseBoolSettingValue("Logging", "EnableSystemConsole", false); return false;
const bool any_logging_sinks = system_console_enabled; DWORD old_mode;
DevConWriterEnabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableVerbose", false); if (!GetConsoleMode(hConsole, &old_mode))
SysConsole.eeConsole.Enabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableEEConsole", true); return false;
SysConsole.iopConsole.Enabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableIOPConsole", true);
#ifdef _WIN32 // already enabled?
if (system_console_enabled) if (old_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
return true;
return SetConsoleMode(hConsole, old_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
}
static void SetSystemConsoleEnabled(bool enabled)
{
if (enabled)
{ {
s_debugger_attached = IsDebuggerPresent(); s_debugger_attached = IsDebuggerPresent();
if (!s_console_handle_set) if (!s_console_handle_set)
{ {
s_old_console_stdin = GetStdHandle(STD_INPUT_HANDLE);
s_old_console_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
s_old_console_stderr = GetStdHandle(STD_ERROR_HANDLE);
bool handle_valid = (GetConsoleWindow() != NULL); bool handle_valid = (GetConsoleWindow() != NULL);
if (!handle_valid) if (!handle_valid)
{ {
AllocConsole(); s_console_allocated = AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole();
handle_valid = (freopen("CONIN$", "r", stdin) != nullptr); handle_valid = (GetConsoleWindow() != NULL);
handle_valid = (freopen("CONOUT$", "w", stdout) != nullptr);
handle_valid = (freopen("CONOUT$", "w", stderr) != nullptr);
} }
if (handle_valid) if (handle_valid)
{ {
s_console_handle = GetStdHandle(STD_OUTPUT_HANDLE); s_console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (s_console_handle != INVALID_HANDLE_VALUE)
{
s_console_handle_set = true; s_console_handle_set = true;
// This gets us unix-style coloured output.
EnableVirtualTerminalProcessing(GetStdHandle(STD_OUTPUT_HANDLE));
EnableVirtualTerminalProcessing(GetStdHandle(STD_ERROR_HANDLE));
// Redirect stdout/stderr.
std::FILE* fp;
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);
}
} }
} }
if (!s_console_handle && !s_debugger_attached) if (!s_console_handle_set && !s_debugger_attached)
{ {
Console_SetActiveHandler(ConsoleWriter_Null); Console_SetActiveHandler(ConsoleWriter_Null);
SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE); SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
@ -635,17 +661,61 @@ void QtHost::UpdateLogging()
{ {
Console_SetActiveHandler(ConsoleWriter_Null); Console_SetActiveHandler(ConsoleWriter_Null);
SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE); SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
if (s_console_handle_set)
{
s_console_handle_set = false;
// redirect stdout/stderr back to null.
std::FILE* fp;
freopen_s(&fp, "NUL:", "w", stderr);
freopen_s(&fp, "NUL:", "w", stdout);
freopen_s(&fp, "NUL:", "w", stdin);
// release console and restore state
SetStdHandle(STD_INPUT_HANDLE, s_old_console_stdin);
SetStdHandle(STD_OUTPUT_HANDLE, s_old_console_stdout);
SetStdHandle(STD_ERROR_HANDLE, s_old_console_stderr);
s_old_console_stdin = NULL;
s_old_console_stdout = NULL;
s_old_console_stderr = NULL;
if (s_console_allocated)
{
s_console_allocated = false;
FreeConsole();
} }
}
}
}
#else #else
if (system_console_enabled)
// Unix doesn't need any special handling for console.
static void SetSystemConsoleEnabled(bool enabled)
{ {
if (enabled)
Console_SetActiveHandler(ConsoleWriter_Stdout); Console_SetActiveHandler(ConsoleWriter_Stdout);
}
else else
{
Console_SetActiveHandler(ConsoleWriter_Null); Console_SetActiveHandler(ConsoleWriter_Null);
} }
#endif #endif
void QtHost::InitializeEarlyConsole()
{
SetSystemConsoleEnabled(true);
}
void QtHost::UpdateLogging()
{
const bool system_console_enabled = QtHost::GetBaseBoolSettingValue("Logging", "EnableSystemConsole", false);
const bool any_logging_sinks = system_console_enabled;
DevConWriterEnabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableVerbose", false);
SysConsole.eeConsole.Enabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableEEConsole", true);
SysConsole.iopConsole.Enabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableIOPConsole", true);
SetSystemConsoleEnabled(system_console_enabled);
} }
#include <wx/module.h> #include <wx/module.h>

View File

@ -42,6 +42,9 @@ namespace QtHost
void UpdateFolders(); void UpdateFolders();
void UpdateLogging(); void UpdateLogging();
/// Initializes early console logging (for printing command line arguments).
void InitializeEarlyConsole();
/// Executes a function on the UI thread. /// Executes a function on the UI thread.
void RunOnUIThread(const std::function<void()>& func, bool block = false); void RunOnUIThread(const std::function<void()>& func, bool block = false);