DPI 规范化处理与单元测试完善 对 StarClient.Linux.cs 中 DPI 获取流程增加 NormalizeDpi 规范化方法,统一过滤异常和规整格式。新增 TryParseDpi 辅助解析。补充 DpiNormalizeTests 单元测试,覆盖异常与合法场景,提升健壮性。智能大石头 authored at 2026-01-05 14:38:19
diff --git a/ClientTest/DpiNormalizeTests.cs b/ClientTest/DpiNormalizeTests.cs
new file mode 100644
index 0000000..b8bf2db
--- /dev/null
+++ b/ClientTest/DpiNormalizeTests.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Reflection;
+using Stardust;
+using Xunit;
+
+namespace ClientTest;
+
+public class DpiNormalizeTests
+{
+ private static String? Normalize(String? dpi)
+ {
+ var mi = typeof(StarClient).GetMethod("NormalizeDpi", BindingFlags.NonPublic | BindingFlags.Static);
+ Assert.NotNull(mi);
+
+ return (String?)mi.Invoke(null, [dpi]);
+ }
+
+ [Theory(DisplayName = "DPI 规范化:过滤异常值")]
+ [InlineData(null)]
+ [InlineData("")]
+ [InlineData("0*96")]
+ [InlineData("96*0")]
+ [InlineData("3072*3072")]
+ [InlineData("9999*96")]
+ public void NormalizeDpi_FilterInvalid(String? dpi)
+ {
+ var rs = Normalize(dpi);
+ Assert.Null(rs);
+ }
+
+ [Theory(DisplayName = "DPI 规范化:保留或规整合法值")]
+ [InlineData("96*96", "96*96")]
+ [InlineData("96x96", "96*96")]
+ [InlineData("120*120", "120*120")]
+ [InlineData("96*97", "96*96")]
+ public void NormalizeDpi_NormalizeValid(String input, String expected)
+ {
+ var rs = Normalize(input);
+ Assert.Equal(expected, rs);
+ }
+}
diff --git a/Stardust/StarClient.Linux.cs b/Stardust/StarClient.Linux.cs
index 3850b81..7c07bf6 100644
--- a/Stardust/StarClient.Linux.cs
+++ b/Stardust/StarClient.Linux.cs
@@ -368,19 +368,55 @@ public partial class StarClient
// 方式1:通过 xdpyinfo 获取 DPI
if (di.Dpi.IsNullOrEmpty())
- di.Dpi = GetDpiByXdpyinfo();
+ di.Dpi = NormalizeDpi(GetDpiByXdpyinfo());
// 方式2:通过 xrdb 获取 Xft.dpi 设置
if (di.Dpi.IsNullOrEmpty())
- di.Dpi = GetDpiByXrdb();
+ di.Dpi = NormalizeDpi(GetDpiByXrdb());
// 方式3:通过 GNOME/KDE 配置获取缩放比例推算 DPI
if (di.Dpi.IsNullOrEmpty())
- di.Dpi = GetDpiByGSettings();
+ di.Dpi = NormalizeDpi(GetDpiByGSettings());
}
catch { }
}
+ private static String? NormalizeDpi(String? dpi)
+ {
+ if (!TryParseDpi(dpi, out var dx, out var dy)) return null;
+
+ // DPI 极值通常是采集/解析异常(如 CentOS 7.6 出现 3072*3072)
+ // 常见 DPI:96/120/144/192/240/288 等,此处给一个宽松上限
+ if (dx <= 0 || dy <= 0) return null;
+ if (dx > 1000 || dy > 1000) return null;
+
+ // 保持存储格式一致:x*y
+ if (dx == dy) return $"{dx}*{dy}";
+
+ // 少数环境会出现非等比例值(取平均更贴近 UI 缩放感知)
+ var d = (Int32)Math.Round((dx + dy) / 2d);
+ if (d <= 0 || d > 1000) return null;
+
+ return $"{d}*{d}";
+ }
+
+ private static Boolean TryParseDpi(String? text, out Int32 dpiX, out Int32 dpiY)
+ {
+ dpiX = 0;
+ dpiY = 0;
+
+ if (text.IsNullOrEmpty()) return false;
+
+ // 允许 "96*96" 或 "96x96"
+ var m = Regex.Match(text.Trim(), @"^(\d+)\s*[*xX]\s*(\d+)$");
+ if (!m.Success) return false;
+
+ dpiX = m.Groups[1].Value.ToInt();
+ dpiY = m.Groups[2].Value.ToInt();
+
+ return dpiX > 0 && dpiY > 0;
+ }
+
/// <summary>通过 xrandr 获取当前分辨率</summary>
private static String? GetResolutionByXrandr()
{