mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-08-18 15:33:33 +08:00
refactor: 新建 Platform 平台差异层,主工程 P/Invoke 全部迁出
- 新增 Platform.Abstractions(接口+NoOp+PlatformLog 日志桥)、 Platform.Windows、Platform.MacOS、Platform.Android 四个项目 - 迁移电源管理、原生对话框、桌面层嵌入、窗口置底/区域穿透、 DWM 互操作、图标服务、包标识查询等全部 Windows P/Invoke 实现 - 主工程保留静态工厂门面,调用点不变;DllImport 扫描为零 - 更新 WindowPassthroughServiceTests 指向新位置(20/20 通过)
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace LanMountainDesktop.Platform.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 主窗口桌面层服务接口。将主窗口嵌入系统桌面图标层(仅 Windows 支持)。
|
||||
/// </summary>
|
||||
public interface IMainWindowDesktopLayerService
|
||||
{
|
||||
bool IsSupported { get; }
|
||||
void EnableOrRefresh(Window window);
|
||||
void Disable(Window window);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无操作实现。用于不支持桌面层嵌入的平台(Linux/macOS/移动端)。
|
||||
/// </summary>
|
||||
public sealed class NullMainWindowDesktopLayerService : IMainWindowDesktopLayerService
|
||||
{
|
||||
public bool IsSupported => false;
|
||||
|
||||
public void EnableOrRefresh(Window window)
|
||||
{
|
||||
PlatformLog.Info("MainWindowDesktopLayer", "Desktop layer requested on an unsupported platform.");
|
||||
}
|
||||
|
||||
public void Disable(Window window)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
namespace LanMountainDesktop.Platform.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 电源管理服务接口。桌面平台提供关机/重启/注销/锁定/睡眠能力;
|
||||
/// 移动平台不提供此能力(使用 <see cref="NullPowerManagementService"/>)。
|
||||
/// </summary>
|
||||
public interface IPowerManagementService
|
||||
{
|
||||
bool IsShutdownSupported { get; }
|
||||
bool IsRestartSupported { get; }
|
||||
bool IsLogoutSupported { get; }
|
||||
bool IsLockSupported { get; }
|
||||
bool IsSleepSupported { get; }
|
||||
|
||||
Task ShutdownAsync();
|
||||
Task RestartAsync();
|
||||
Task LogoutAsync();
|
||||
Task LockAsync();
|
||||
Task SleepAsync();
|
||||
|
||||
void ShowNativePowerUI(PowerAction action);
|
||||
}
|
||||
|
||||
public enum PowerAction
|
||||
{
|
||||
Shutdown,
|
||||
Restart
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无操作实现。用于不支持电源管理的平台(如移动端)。
|
||||
/// </summary>
|
||||
public sealed class NullPowerManagementService : IPowerManagementService
|
||||
{
|
||||
public bool IsShutdownSupported => false;
|
||||
public bool IsRestartSupported => false;
|
||||
public bool IsLogoutSupported => false;
|
||||
public bool IsLockSupported => false;
|
||||
public bool IsSleepSupported => false;
|
||||
|
||||
public Task ShutdownAsync() => Task.CompletedTask;
|
||||
public Task RestartAsync() => Task.CompletedTask;
|
||||
public Task LogoutAsync() => Task.CompletedTask;
|
||||
public Task LockAsync() => Task.CompletedTask;
|
||||
public Task SleepAsync() => Task.CompletedTask;
|
||||
|
||||
public void ShowNativePowerUI(PowerAction action) { }
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace LanMountainDesktop.Platform.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口置底服务接口。使组件窗口保持在桌面层(Z 序最底)。
|
||||
/// </summary>
|
||||
public interface IWindowBottomMostService
|
||||
{
|
||||
void SetupBottomMost(Window window);
|
||||
void SendToBottom(Window window);
|
||||
PixelPoint GetScreenPosition(Window window);
|
||||
bool SetScreenPosition(Window window, PixelPoint position, bool queueOnFailure = false);
|
||||
bool IsBottomMostSupported { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口交互区域定义。区域外的点击穿透到桌面。
|
||||
/// </summary>
|
||||
public readonly record struct WindowInteractiveRegion(
|
||||
Rect Bounds,
|
||||
double CornerRadius,
|
||||
Matrix? ClientToRegionTransform = null,
|
||||
Rect? ClientClipBounds = null,
|
||||
double ClientClipCornerRadius = 0d);
|
||||
|
||||
/// <summary>
|
||||
/// 区域点击穿透服务接口。
|
||||
/// </summary>
|
||||
public interface IRegionPassthroughService
|
||||
{
|
||||
void SetInteractiveRegions(Window window, IReadOnlyList<WindowInteractiveRegion> interactiveRegions);
|
||||
void ClearInteractiveRegions(Window window);
|
||||
bool IsRegionPassthroughSupported { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无操作实现:非 Windows 平台窗口置底不可用。
|
||||
/// </summary>
|
||||
public sealed class NullWindowBottomMostService : IWindowBottomMostService
|
||||
{
|
||||
public bool IsBottomMostSupported => false;
|
||||
|
||||
public void SetupBottomMost(Window window) { }
|
||||
|
||||
public void SendToBottom(Window window) { }
|
||||
|
||||
public PixelPoint GetScreenPosition(Window window) => window.Position;
|
||||
|
||||
public bool SetScreenPosition(Window window, PixelPoint position, bool queueOnFailure = false)
|
||||
{
|
||||
window.Position = position;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无操作实现:非 Windows 平台区域穿透不可用。
|
||||
/// </summary>
|
||||
public sealed class NullRegionPassthroughService : IRegionPassthroughService
|
||||
{
|
||||
public bool IsRegionPassthroughSupported => false;
|
||||
|
||||
public void SetInteractiveRegions(Window window, IReadOnlyList<WindowInteractiveRegion> interactiveRegions) { }
|
||||
|
||||
public void ClearInteractiveRegions(Window window) { }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
35
LanMountainDesktop.Platform.Abstractions/PlatformLog.cs
Normal file
35
LanMountainDesktop.Platform.Abstractions/PlatformLog.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace LanMountainDesktop.Platform.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 平台层日志桥。平台实现项目不引用宿主,
|
||||
/// 宿主在启动时通过 <see cref="SetSink"/> 接入自己的日志系统(AppLogger)。
|
||||
/// 未接入时日志静默丢弃。
|
||||
/// </summary>
|
||||
public static class PlatformLog
|
||||
{
|
||||
private static IPlatformLogSink? _sink;
|
||||
|
||||
public static void SetSink(IPlatformLogSink sink)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(sink);
|
||||
_sink = sink;
|
||||
}
|
||||
|
||||
public static void Info(string category, string message) => _sink?.Info(category, message);
|
||||
|
||||
public static void Warn(string category, string message, Exception? exception = null) =>
|
||||
_sink?.Warn(category, message, exception);
|
||||
|
||||
public static void Error(string category, string message, Exception? exception = null) =>
|
||||
_sink?.Error(category, message, exception);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 平台层日志输出目标。
|
||||
/// </summary>
|
||||
public interface IPlatformLogSink
|
||||
{
|
||||
void Info(string category, string message);
|
||||
void Warn(string category, string message, Exception? exception = null);
|
||||
void Error(string category, string message, Exception? exception = null);
|
||||
}
|
||||
Reference in New Issue
Block a user