2
0
Эх сурвалжийг харах

Refactor SixelSupportDetector for cleaner reading

tznind 10 сар өмнө
parent
commit
61667fbf86

+ 94 - 48
Terminal.Gui/Drawing/SixelSupportDetector.cs

@@ -1,5 +1,4 @@
 using System.Text.RegularExpressions;
-using Microsoft.CodeAnalysis;
 
 namespace Terminal.Gui;
 
@@ -20,68 +19,115 @@ public class SixelSupportDetector
     {
         var result = new SixelSupportResult ();
 
-        result.IsSupported =
-            AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_SendDeviceAttributes, out AnsiEscapeSequenceResponse darResponse)
-                ? darResponse.Response.Split (';').Contains ("4")
-                : false;
+        result.IsSupported = IsSixelSupportedByDar ();
 
         if (result.IsSupported)
         {
-            // Expect something like:
-            //<esc>[6;20;10t
+            if (TryGetResolutionDirectly (out var res))
+            {
+                result.Resolution = res;
+            }
+            else if(TryComputeResolution(out res))
+            {
+                result.Resolution = res;
+            }
+
+            result.SupportsTransparency = IsWindowsTerminal () || IsXtermWithTransparency ();
+        }
 
-            bool gotResolutionDirectly = false;
+        return result;
+    }
 
-            if (AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_RequestSixelResolution, out var resolution))
-            {
-                // Terminal supports directly responding with resolution
-                var match = Regex.Match (resolution.Response, @"\[\d+;(\d+);(\d+)t$");
 
-                if (match.Success)
+    private bool TryGetResolutionDirectly (out Size resolution)
+    {
+        // Expect something like:
+        //<esc>[6;20;10t
+
+        if (AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_RequestSixelResolution, out var response))
+        {
+            // Terminal supports directly responding with resolution
+            var match = Regex.Match (response.Response, @"\[\d+;(\d+);(\d+)t$");
+
+            if (match.Success)
+            {
+                if (int.TryParse (match.Groups [1].Value, out var ry) &&
+                    int.TryParse (match.Groups [2].Value, out var rx))
                 {
-                    if (int.TryParse (match.Groups [1].Value, out var ry) &&
-                        int.TryParse (match.Groups [2].Value, out var rx))
-                    {
-                        result.Resolution = new Size (rx, ry);
-                        gotResolutionDirectly = true;
-                    }
+                    resolution = new Size (rx, ry);
+
+                    return true;
                 }
             }
+        }
+
+        resolution = default;
+        return false;
+    }
+
 
-            if (!gotResolutionDirectly)
+    private bool TryComputeResolution (out Size resolution)
+    {
+        // Fallback to window size in pixels and characters
+        if (AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_RequestWindowSizeInPixels, out var pixelSizeResponse)
+            && AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_ReportTerminalSizeInChars, out var charSizeResponse))
+        {
+            // Example [4;600;1200t
+            var pixelMatch = Regex.Match (pixelSizeResponse.Response, @"\[\d+;(\d+);(\d+)t$");
+
+            // Example [8;30;120t
+            var charMatch = Regex.Match (charSizeResponse.Response, @"\[\d+;(\d+);(\d+)t$");
+
+            if (pixelMatch.Success && charMatch.Success)
             {
-                // Fallback to window size in pixels and characters
-                if (AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_RequestWindowSizeInPixels, out var pixelSizeResponse) &&
-                    AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_ReportTerminalSizeInChars, out var charSizeResponse))
+                // Extract pixel dimensions
+                if (int.TryParse (pixelMatch.Groups [1].Value, out var pixelHeight)
+                    && int.TryParse (pixelMatch.Groups [2].Value, out var pixelWidth)
+                    &&
+
+                    // Extract character dimensions
+                    int.TryParse (charMatch.Groups [1].Value, out var charHeight)
+                    && int.TryParse (charMatch.Groups [2].Value, out var charWidth)
+                    && charWidth != 0
+                    && charHeight != 0) // Avoid divide by zero
                 {
-                    // Example [4;600;1200t
-                    var pixelMatch = Regex.Match (pixelSizeResponse.Response, @"\[\d+;(\d+);(\d+)t$");
-
-                    // Example [8;30;120t
-                    var charMatch = Regex.Match (charSizeResponse.Response, @"\[\d+;(\d+);(\d+)t$");
-
-                    if (pixelMatch.Success && charMatch.Success)
-                    {
-                        // Extract pixel dimensions
-                        if (int.TryParse (pixelMatch.Groups [1].Value, out var pixelHeight) &&
-                            int.TryParse (pixelMatch.Groups [2].Value, out var pixelWidth) &&
-                            // Extract character dimensions
-                            int.TryParse (charMatch.Groups [1].Value, out var charHeight) &&
-                            int.TryParse (charMatch.Groups [2].Value, out var charWidth) &&
-                            charWidth != 0 && charHeight != 0) // Avoid divide by zero
-                        {
-                            // Calculate the character cell size in pixels
-                            var cellWidth = (int)Math.Round ((double)pixelWidth / charWidth);
-                            var cellHeight = (int)Math.Round ((double)pixelHeight / charHeight);
-
-                            // Set the resolution based on the character cell size
-                            result.Resolution = new Size (cellWidth, cellHeight);
-                        }
-                    }
+                    // Calculate the character cell size in pixels
+                    var cellWidth = (int)Math.Round ((double)pixelWidth / charWidth);
+                    var cellHeight = (int)Math.Round ((double)pixelHeight / charHeight);
+
+                    // Set the resolution based on the character cell size
+                    resolution = new Size (cellWidth, cellHeight);
+
+                    return true;
                 }
             }
         }
 
-        return result;
+        resolution = default;
+        return false;
+    }
+    private bool IsSixelSupportedByDar ()
+    {
+        return AnsiEscapeSequenceRequest.TryExecuteAnsiRequest (EscSeqUtils.CSI_SendDeviceAttributes, out AnsiEscapeSequenceResponse darResponse)
+            ? darResponse.Response.Split (';').Contains ("4")
+            : false;
+    }
+
+    private bool IsWindowsTerminal ()
+    {
+        return  !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable ("WT_SESSION"));;
+    }
+    private bool IsXtermWithTransparency ()
+    {
+        // Check if running in real xterm (XTERM_VERSION is more reliable than TERM)
+        var xtermVersionStr = Environment.GetEnvironmentVariable ("XTERM_VERSION");
+
+        // If XTERM_VERSION exists, we are in a real xterm
+        if (!string.IsNullOrWhiteSpace (xtermVersionStr) && int.TryParse (xtermVersionStr, out var xtermVersion) && xtermVersion >= 370)
+        {
+            return true;
+        }
+
+        return false;
     }
 }

+ 7 - 1
Terminal.Gui/Drawing/SixelSupportResult.cs

@@ -8,7 +8,7 @@
 public class SixelSupportResult
 {
     /// <summary>
-    ///     Whether the current driver supports sixel graphic format.
+    ///     Whether the terminal supports sixel graphic format.
     ///     Defaults to false.
     /// </summary>
     public bool IsSupported { get; set; }
@@ -24,4 +24,10 @@ public class SixelSupportResult
     ///     to 256.
     /// </summary>
     public int MaxPaletteColors { get; set; } = 256;
+
+    /// <summary>
+    ///     Whether the terminal supports transparent background sixels.
+    ///     Defaults to false
+    /// </summary>
+    public bool SupportsTransparency { get; set; }
 }