From e869f842e3be31e440df7f811ea471a7093cf120 Mon Sep 17 00:00:00 2001 From: BDisp Date: Thu, 11 Sep 2025 20:49:25 +0100 Subject: [PATCH] Fixes #4241. v2net driver isn't suspending on Unix platforms (#4242) Co-authored-by: Tig --- .../Drivers/CursesDriver/CursesDriver.cs | 81 ------------------ Terminal.Gui/Drivers/CursesDriver/Platform.cs | 83 +++++++++++++++++++ .../Drivers/V2/ConsoleDriverFacade.cs | 31 ++++++- 3 files changed, 113 insertions(+), 82 deletions(-) create mode 100644 Terminal.Gui/Drivers/CursesDriver/Platform.cs diff --git a/Terminal.Gui/Drivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/Drivers/CursesDriver/CursesDriver.cs index 885478975..09dd1e692 100644 --- a/Terminal.Gui/Drivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/Drivers/CursesDriver/CursesDriver.cs @@ -1082,84 +1082,3 @@ internal class CursesDriver : ConsoleDriver /// public override void WriteRaw (string ansi) { _mainLoopDriver?.WriteRaw (ansi); } } - -// TODO: One type per file - move to another file -internal static class Platform -{ - private static int _suspendSignal; - - /// Suspends the process by sending SIGTSTP to itself - /// True if the suspension was successful. - public static bool Suspend () - { - int signal = GetSuspendSignal (); - - if (signal == -1) - { - return false; - } - - killpg (0, signal); - - return true; - } - - private static int GetSuspendSignal () - { - if (_suspendSignal != 0) - { - return _suspendSignal; - } - - nint buf = Marshal.AllocHGlobal (8192); - - if (uname (buf) != 0) - { - Marshal.FreeHGlobal (buf); - _suspendSignal = -1; - - return _suspendSignal; - } - - try - { - switch (Marshal.PtrToStringAnsi (buf)) - { - case "Darwin": - case "DragonFly": - case "FreeBSD": - case "NetBSD": - case "OpenBSD": - _suspendSignal = 18; - - break; - case "Linux": - // TODO: should fetch the machine name and - // if it is MIPS return 24 - _suspendSignal = 20; - - break; - case "Solaris": - _suspendSignal = 24; - - break; - default: - _suspendSignal = -1; - - break; - } - - return _suspendSignal; - } - finally - { - Marshal.FreeHGlobal (buf); - } - } - - [DllImport ("libc")] - private static extern int killpg (int pgrp, int pid); - - [DllImport ("libc")] - private static extern int uname (nint buf); -} \ No newline at end of file diff --git a/Terminal.Gui/Drivers/CursesDriver/Platform.cs b/Terminal.Gui/Drivers/CursesDriver/Platform.cs new file mode 100644 index 000000000..4b14ba053 --- /dev/null +++ b/Terminal.Gui/Drivers/CursesDriver/Platform.cs @@ -0,0 +1,83 @@ +using System.Runtime.InteropServices; + +namespace Terminal.Gui.Drivers; + +internal static class Platform +{ + private static int _suspendSignal; + + /// Suspends the process by sending SIGTSTP to itself + /// True if the suspension was successful. + public static bool Suspend () + { + int signal = GetSuspendSignal (); + + if (signal == -1) + { + return false; + } + + killpg (0, signal); + + return true; + } + + private static int GetSuspendSignal () + { + if (_suspendSignal != 0) + { + return _suspendSignal; + } + + nint buf = Marshal.AllocHGlobal (8192); + + if (uname (buf) != 0) + { + Marshal.FreeHGlobal (buf); + _suspendSignal = -1; + + return _suspendSignal; + } + + try + { + switch (Marshal.PtrToStringAnsi (buf)) + { + case "Darwin": + case "DragonFly": + case "FreeBSD": + case "NetBSD": + case "OpenBSD": + _suspendSignal = 18; + + break; + case "Linux": + // TODO: should fetch the machine name and + // if it is MIPS return 24 + _suspendSignal = 20; + + break; + case "Solaris": + _suspendSignal = 24; + + break; + default: + _suspendSignal = -1; + + break; + } + + return _suspendSignal; + } + finally + { + Marshal.FreeHGlobal (buf); + } + } + + [DllImport ("libc")] + private static extern int killpg (int pgrp, int pid); + + [DllImport ("libc")] + private static extern int uname (nint buf); +} \ No newline at end of file diff --git a/Terminal.Gui/Drivers/V2/ConsoleDriverFacade.cs b/Terminal.Gui/Drivers/V2/ConsoleDriverFacade.cs index c57f67841..bef8893a0 100644 --- a/Terminal.Gui/Drivers/V2/ConsoleDriverFacade.cs +++ b/Terminal.Gui/Drivers/V2/ConsoleDriverFacade.cs @@ -326,7 +326,36 @@ internal class ConsoleDriverFacade : IConsoleDriver, IConsoleDriverFacade } /// - public void Suspend () { } + public void Suspend () + { + if (Environment.OSVersion.Platform != PlatformID.Unix) + { + return; + } + + Console.Out.Write (EscSeqUtils.CSI_DisableMouseEvents); + + if (!ConsoleDriver.RunningUnitTests) + { + Console.ResetColor (); + Console.Clear (); + + //Disable alternative screen buffer. + Console.Out.Write (EscSeqUtils.CSI_RestoreCursorAndRestoreAltBufferWithBackscroll); + + //Set cursor key to cursor. + Console.Out.Write (EscSeqUtils.CSI_ShowCursor); + + Platform.Suspend (); + + //Enable alternative screen buffer. + Console.Out.Write (EscSeqUtils.CSI_SaveCursorAndActivateAltBufferNoBackscroll); + + Application.LayoutAndDraw (); + } + + Console.Out.Write (EscSeqUtils.CSI_EnableMouseEvents); + } /// /// Sets the position of the terminal cursor to and