mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 09:14:25 +08:00
Make settings window independent and taskbar-aware
Convert the settings window into an independent top-level window with its own taskbar icon and open-or-focus semantics. Removed Owner/anchor/toggle semantics from SettingsWindowService and added ScreenReferenceWindow for centering; settings windows now ShowInTaskbar = true and are truly destroyed on close. Added SettingsWindowPlacementHelper and tests for placement/centering. Main window now respects an AppSettingsSnapshot.ShowInTaskbar flag (new setting exposed in GeneralSettings UI) and slide/visibility animations and "back to Windows" behavior no longer affect the independent settings window. Updated various callers to use OpenIndependentSettingsModule, adjusted window transitions/X offsets, and added/updated spec files documenting the feature and animation boundary.
This commit is contained in:
@@ -117,8 +117,8 @@ public partial class App : Application
|
||||
$"Opening settings window. Source='{source}'; PageTag='{pageTag ?? "<default>"}'.");
|
||||
_settingsWindowService?.Open(new SettingsWindowOpenRequest(
|
||||
Source: source,
|
||||
Owner: _mainWindow is { IsVisible: true } ? _mainWindow : null,
|
||||
PageId: pageTag));
|
||||
PageId: pageTag,
|
||||
ScreenReferenceWindow: _mainWindow is { IsVisible: true } ? _mainWindow : null));
|
||||
}
|
||||
|
||||
public App()
|
||||
@@ -738,7 +738,7 @@ public partial class App : Application
|
||||
var mainWindow = GetOrCreateMainWindow(desktop, source);
|
||||
mainWindow.PrepareEnterAnimation();
|
||||
|
||||
mainWindow.ShowInTaskbar = true;
|
||||
mainWindow.ShowInTaskbar = ShouldShowMainWindowInTaskbar();
|
||||
|
||||
if (!mainWindow.IsVisible)
|
||||
{
|
||||
@@ -1106,7 +1106,7 @@ public partial class App : Application
|
||||
var mainWindow = new MainWindow
|
||||
{
|
||||
DataContext = new MainWindowViewModel(),
|
||||
ShowInTaskbar = true
|
||||
ShowInTaskbar = ShouldShowMainWindowInTaskbar()
|
||||
};
|
||||
|
||||
_mainWindowOpened = false;
|
||||
@@ -1296,6 +1296,11 @@ public partial class App : Application
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldShowMainWindowInTaskbar()
|
||||
{
|
||||
return _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App).ShowInTaskbar;
|
||||
}
|
||||
|
||||
private void SetDesktopShellState(DesktopShellState state, string source)
|
||||
{
|
||||
if (_desktopShellState == state)
|
||||
|
||||
@@ -154,6 +154,8 @@ public sealed class AppSettingsSnapshot
|
||||
|
||||
public bool EnableSlideTransition { get; set; } = false;
|
||||
|
||||
public bool ShowInTaskbar { get; set; } = false;
|
||||
|
||||
public bool EnableFusedDesktop { get; set; } = false;
|
||||
|
||||
public List<string> DisabledPluginIds { get; set; } = [];
|
||||
|
||||
@@ -14,28 +14,10 @@ using LanMountainDesktop.Views;
|
||||
|
||||
namespace LanMountainDesktop.Services.Settings;
|
||||
|
||||
public enum SettingsWindowAnchorTarget
|
||||
{
|
||||
DesktopDockTrailingEdge = 0
|
||||
}
|
||||
|
||||
public enum SettingsWindowFallbackMode
|
||||
{
|
||||
None = 0,
|
||||
ScreenBottomRight = 1
|
||||
}
|
||||
|
||||
public readonly record struct SettingsWindowOpenRequest(
|
||||
string Source,
|
||||
Window? Owner = null,
|
||||
string? PageId = null,
|
||||
SettingsWindowAnchorTarget AnchorTarget = SettingsWindowAnchorTarget.DesktopDockTrailingEdge,
|
||||
SettingsWindowFallbackMode FallbackMode = SettingsWindowFallbackMode.ScreenBottomRight);
|
||||
|
||||
public interface ISettingsWindowAnchorProvider
|
||||
{
|
||||
bool TryGetSettingsWindowAnchorBounds(out PixelRect anchorBounds);
|
||||
}
|
||||
Window? ScreenReferenceWindow = null);
|
||||
|
||||
public interface ISettingsWindowService
|
||||
{
|
||||
@@ -46,8 +28,6 @@ public interface ISettingsWindowService
|
||||
void Open(SettingsWindowOpenRequest request);
|
||||
|
||||
void Close();
|
||||
|
||||
void Toggle(SettingsWindowOpenRequest request);
|
||||
}
|
||||
|
||||
internal sealed class SettingsWindowService : ISettingsWindowService
|
||||
@@ -92,27 +72,25 @@ internal sealed class SettingsWindowService : ISettingsWindowService
|
||||
var appearanceSnapshot = _appearanceThemeService.GetCurrent();
|
||||
_window.ApplyChromeMode(appearanceSnapshot.UseSystemChrome);
|
||||
ApplyTheme(_window);
|
||||
_window.ReloadPages(request.PageId);
|
||||
PositionWindow(_window, request);
|
||||
|
||||
var targetPageId = request.PageId ?? _window.ViewModel.CurrentPageId;
|
||||
_window.ReloadPages(targetPageId);
|
||||
|
||||
if (!_window.IsVisible)
|
||||
{
|
||||
if (request.Owner is not null && request.Owner.IsVisible)
|
||||
{
|
||||
_window.Show(request.Owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
_window.Show();
|
||||
}
|
||||
|
||||
CenterWindow(_window, request);
|
||||
_window.Show();
|
||||
NotifyStateChanged();
|
||||
PositionWindowLater(_window, request);
|
||||
CenterWindowLater(_window, request);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_window.WindowState == WindowState.Minimized)
|
||||
{
|
||||
_window.WindowState = WindowState.Normal;
|
||||
}
|
||||
|
||||
_window.Activate();
|
||||
PositionWindowLater(_window, request);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
@@ -120,17 +98,6 @@ internal sealed class SettingsWindowService : ISettingsWindowService
|
||||
_window?.Close();
|
||||
}
|
||||
|
||||
public void Toggle(SettingsWindowOpenRequest request)
|
||||
{
|
||||
if (IsOpen)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
Open(request);
|
||||
}
|
||||
|
||||
private SettingsWindow CreateWindow()
|
||||
{
|
||||
var regionState = _settingsFacade.Region.Get();
|
||||
@@ -147,7 +114,7 @@ internal sealed class SettingsWindowService : ISettingsWindowService
|
||||
_hostApplicationLifecycle,
|
||||
useSystemChrome);
|
||||
ApplyTheme(window);
|
||||
window.ShowInTaskbar = false;
|
||||
window.ShowInTaskbar = true;
|
||||
window.Closed += (_, _) =>
|
||||
{
|
||||
_window = null;
|
||||
@@ -156,106 +123,87 @@ internal sealed class SettingsWindowService : ISettingsWindowService
|
||||
return window;
|
||||
}
|
||||
|
||||
private void PositionWindowLater(SettingsWindow window, SettingsWindowOpenRequest request)
|
||||
private void CenterWindowLater(SettingsWindow window, SettingsWindowOpenRequest request)
|
||||
{
|
||||
Dispatcher.UIThread.Post(
|
||||
() =>
|
||||
{
|
||||
if (!window.IsVisible)
|
||||
if (!ReferenceEquals(_window, window) || !window.IsVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PositionWindow(window, request);
|
||||
CenterWindow(window, request);
|
||||
},
|
||||
DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
private static void PositionWindow(SettingsWindow window, SettingsWindowOpenRequest request)
|
||||
private static void CenterWindow(SettingsWindow window, SettingsWindowOpenRequest request)
|
||||
{
|
||||
if (request.AnchorTarget == SettingsWindowAnchorTarget.DesktopDockTrailingEdge &&
|
||||
request.Owner is ISettingsWindowAnchorProvider anchorProvider &&
|
||||
anchorProvider.TryGetSettingsWindowAnchorBounds(out var anchorBounds))
|
||||
{
|
||||
PositionWindowAboveAnchor(window, anchorBounds, request);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.FallbackMode == SettingsWindowFallbackMode.ScreenBottomRight)
|
||||
{
|
||||
PositionWindowNearScreenBottomRight(window, request);
|
||||
}
|
||||
var referenceWorkingArea =
|
||||
request.ScreenReferenceWindow is { IsVisible: true } screenReferenceWindow &&
|
||||
screenReferenceWindow.Screens?.ScreenFromWindow(screenReferenceWindow) is { } referenceScreen
|
||||
? referenceScreen.WorkingArea
|
||||
: (PixelRect?)null;
|
||||
var width = ResolveWindowWidth(window, request.ScreenReferenceWindow);
|
||||
var height = ResolveWindowHeight(window, request.ScreenReferenceWindow);
|
||||
var workingArea = SettingsWindowPlacementHelper.ResolveWorkingArea(
|
||||
referenceWorkingArea,
|
||||
window.Screens?.Primary?.WorkingArea,
|
||||
width,
|
||||
height);
|
||||
window.Position = SettingsWindowPlacementHelper.CalculateCenteredPosition(workingArea, width, height);
|
||||
}
|
||||
|
||||
private static void PositionWindowAboveAnchor(Window window, PixelRect anchorBounds, SettingsWindowOpenRequest request)
|
||||
private static int ResolveWindowWidth(Window window, Window? referenceWindow)
|
||||
{
|
||||
var workingArea = GetWorkingArea(window, request);
|
||||
|
||||
if (anchorBounds.Width <= 0 || anchorBounds.Height <= 0 ||
|
||||
anchorBounds.Right < workingArea.X || anchorBounds.Y > workingArea.Bottom)
|
||||
{
|
||||
PositionWindowNearScreenBottomRight(window, request);
|
||||
return;
|
||||
}
|
||||
|
||||
var scale = window.RenderScaling > 0 ? window.RenderScaling : 1d;
|
||||
var width = ResolveWindowWidth(window, scale);
|
||||
var height = ResolveWindowHeight(window, scale);
|
||||
var inset = (int)Math.Round(24 * scale);
|
||||
var gap = (int)Math.Round(16 * scale);
|
||||
|
||||
var x = anchorBounds.Right - width - inset;
|
||||
var y = anchorBounds.Y - height - gap;
|
||||
x = Math.Clamp(x, workingArea.X + inset, Math.Max(workingArea.X + inset, workingArea.Right - width - inset));
|
||||
y = Math.Clamp(y, workingArea.Y + inset, Math.Max(workingArea.Y + inset, workingArea.Bottom - height - inset));
|
||||
window.Position = new PixelPoint(x, y);
|
||||
}
|
||||
|
||||
private static void PositionWindowNearScreenBottomRight(Window window, SettingsWindowOpenRequest request)
|
||||
{
|
||||
var workingArea = GetWorkingArea(window, request);
|
||||
var scale = window.RenderScaling > 0 ? window.RenderScaling : 1d;
|
||||
var width = ResolveWindowWidth(window, scale);
|
||||
var height = ResolveWindowHeight(window, scale);
|
||||
var inset = (int)Math.Round(24 * scale);
|
||||
|
||||
var x = Math.Max(workingArea.X + inset, workingArea.Right - width - inset);
|
||||
var y = Math.Max(workingArea.Y + inset, workingArea.Bottom - height - inset);
|
||||
window.Position = new PixelPoint(x, y);
|
||||
}
|
||||
|
||||
private static PixelRect GetWorkingArea(Window window, SettingsWindowOpenRequest request)
|
||||
{
|
||||
if (request.Owner is not null && request.Owner.Screens?.ScreenFromWindow(request.Owner) is { } ownerScreen)
|
||||
{
|
||||
return ownerScreen.WorkingArea;
|
||||
}
|
||||
|
||||
if (window.Screens?.ScreenFromWindow(window) is { } windowScreen)
|
||||
{
|
||||
return windowScreen.WorkingArea;
|
||||
}
|
||||
|
||||
return window.Screens?.Primary?.WorkingArea
|
||||
?? new PixelRect(
|
||||
0,
|
||||
0,
|
||||
Math.Max(1280, ResolveWindowWidth(window, 1d) + 96),
|
||||
Math.Max(720, ResolveWindowHeight(window, 1d) + 96));
|
||||
}
|
||||
|
||||
private static int ResolveWindowWidth(Window window, double scale)
|
||||
{
|
||||
var widthDip = window.Bounds.Width > 1 ? window.Bounds.Width : Math.Max(window.Width, window.MinWidth);
|
||||
var widthDip = ResolveWindowDimensionDip(window.Bounds.Width, window.Width, window.MinWidth, 1120d);
|
||||
var scale = ResolveWindowScale(window, referenceWindow);
|
||||
return Math.Max(320, (int)Math.Round(widthDip * scale));
|
||||
}
|
||||
|
||||
private static int ResolveWindowHeight(Window window, double scale)
|
||||
private static int ResolveWindowHeight(Window window, Window? referenceWindow)
|
||||
{
|
||||
var heightDip = window.Bounds.Height > 1 ? window.Bounds.Height : Math.Max(window.Height, window.MinHeight);
|
||||
var heightDip = ResolveWindowDimensionDip(window.Bounds.Height, window.Height, window.MinHeight, 760d);
|
||||
var scale = ResolveWindowScale(window, referenceWindow);
|
||||
return Math.Max(240, (int)Math.Round(heightDip * scale));
|
||||
}
|
||||
|
||||
private static double ResolveWindowScale(Window window, Window? referenceWindow)
|
||||
{
|
||||
if (referenceWindow is not null && referenceWindow.RenderScaling > 0)
|
||||
{
|
||||
return referenceWindow.RenderScaling;
|
||||
}
|
||||
|
||||
if (window.RenderScaling > 0)
|
||||
{
|
||||
return window.RenderScaling;
|
||||
}
|
||||
|
||||
return 1d;
|
||||
}
|
||||
|
||||
private static double ResolveWindowDimensionDip(double boundsDip, double configuredDip, double minimumDip, double fallbackDip)
|
||||
{
|
||||
if (boundsDip > 1)
|
||||
{
|
||||
return boundsDip;
|
||||
}
|
||||
|
||||
if (!double.IsNaN(configuredDip) && configuredDip > 1)
|
||||
{
|
||||
return configuredDip;
|
||||
}
|
||||
|
||||
if (!double.IsNaN(minimumDip) && minimumDip > 1)
|
||||
{
|
||||
return minimumDip;
|
||||
}
|
||||
|
||||
return fallbackDip;
|
||||
}
|
||||
|
||||
private void NotifyStateChanged()
|
||||
{
|
||||
StateChanged?.Invoke(this, EventArgs.Empty);
|
||||
@@ -363,3 +311,38 @@ internal sealed class SettingsWindowService : ISettingsWindowService
|
||||
}, DispatcherPriority.Background);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SettingsWindowPlacementHelper
|
||||
{
|
||||
internal static PixelRect ResolveWorkingArea(
|
||||
PixelRect? referenceWorkingArea,
|
||||
PixelRect? primaryWorkingArea,
|
||||
int fallbackWindowWidth,
|
||||
int fallbackWindowHeight)
|
||||
{
|
||||
if (referenceWorkingArea is { } referenceArea)
|
||||
{
|
||||
return referenceArea;
|
||||
}
|
||||
|
||||
if (primaryWorkingArea is { } primaryArea)
|
||||
{
|
||||
return primaryArea;
|
||||
}
|
||||
|
||||
return new PixelRect(
|
||||
0,
|
||||
0,
|
||||
Math.Max(1280, fallbackWindowWidth + 96),
|
||||
Math.Max(720, fallbackWindowHeight + 96));
|
||||
}
|
||||
|
||||
internal static PixelPoint CalculateCenteredPosition(PixelRect workingArea, int windowWidth, int windowHeight)
|
||||
{
|
||||
var horizontalOffset = Math.Max(0, (workingArea.Width - windowWidth) / 2);
|
||||
var verticalOffset = Math.Max(0, (workingArea.Height - windowHeight) / 2);
|
||||
return new PixelPoint(
|
||||
workingArea.X + horizontalOffset,
|
||||
workingArea.Y + verticalOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +202,7 @@ public sealed partial class GeneralSettingsPageViewModel : ViewModelBase, IDispo
|
||||
string.Equals(option.Value, normalizedRenderMode, StringComparison.OrdinalIgnoreCase))
|
||||
?? RenderModes[0];
|
||||
EnableSlideTransition = appSnapshot.EnableSlideTransition;
|
||||
ShowInTaskbar = appSnapshot.ShowInTaskbar;
|
||||
_isInitializing = false;
|
||||
|
||||
RefreshPreview();
|
||||
@@ -238,6 +239,11 @@ public sealed partial class GeneralSettingsPageViewModel : ViewModelBase, IDispo
|
||||
{
|
||||
EnableSlideTransition = _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App).EnableSlideTransition;
|
||||
}
|
||||
|
||||
if (changedKeys.Contains(nameof(AppSettingsSnapshot.ShowInTaskbar)))
|
||||
{
|
||||
ShowInTaskbar = _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App).ShowInTaskbar;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action? RestartRequested;
|
||||
@@ -260,6 +266,9 @@ public sealed partial class GeneralSettingsPageViewModel : ViewModelBase, IDispo
|
||||
[ObservableProperty]
|
||||
private bool _enableSlideTransition;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _showInTaskbar;
|
||||
|
||||
public bool IsSlideTransitionAvailable => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows);
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -367,6 +376,12 @@ public sealed partial class GeneralSettingsPageViewModel : ViewModelBase, IDispo
|
||||
SaveField(nameof(AppSettingsSnapshot.EnableSlideTransition), value);
|
||||
}
|
||||
|
||||
partial void OnShowInTaskbarChanged(bool value)
|
||||
{
|
||||
if (_isInitializing) return;
|
||||
SaveField(nameof(AppSettingsSnapshot.ShowInTaskbar), value);
|
||||
}
|
||||
|
||||
private void SaveField<T>(string key, T value)
|
||||
{
|
||||
var snapshot = _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
|
||||
|
||||
@@ -256,18 +256,14 @@ public partial class FusedDesktopComponentLibraryControl : UserControl
|
||||
private void OnFindMoreComponentsClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
// 打开设置窗口并导航到插件目录页面
|
||||
if (Application.Current is App app && app.SettingsWindowService is { } settingsWindowService)
|
||||
if (Application.Current is App app)
|
||||
{
|
||||
var mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow as MainWindow;
|
||||
var request = new SettingsWindowOpenRequest(
|
||||
Source: "FusedDesktopComponentLibrary",
|
||||
Owner: mainWindow,
|
||||
PageId: "plugin-catalog");
|
||||
settingsWindowService.Open(request);
|
||||
app.OpenIndependentSettingsModule("FusedDesktopComponentLibrary", "plugin-catalog");
|
||||
}
|
||||
|
||||
// 关闭所在窗口
|
||||
var window = this.FindAncestorOfType<Window>();
|
||||
window?.Close();
|
||||
var componentLibraryWindow = this.FindAncestorOfType<Window>();
|
||||
componentLibraryWindow?.Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ using LanMountainDesktop.DesktopEditing;
|
||||
using LanMountainDesktop.Host.Abstractions;
|
||||
using LanMountainDesktop.Models;
|
||||
using LanMountainDesktop.Services;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.Settings.Core;
|
||||
using LanMountainDesktop.Theme;
|
||||
using LanMountainDesktop.Views.Components;
|
||||
@@ -282,16 +281,7 @@ public partial class MainWindow
|
||||
CloseComponentLibraryWindow(reopenSettings: false);
|
||||
}
|
||||
|
||||
var app = Application.Current as App;
|
||||
if (app?.SettingsWindowService is { } settingsWindowService)
|
||||
{
|
||||
settingsWindowService.Toggle(new SettingsWindowOpenRequest(
|
||||
Source: "MainWindowTaskbar",
|
||||
Owner: this));
|
||||
return;
|
||||
}
|
||||
|
||||
app?.OpenIndependentSettingsModule("MainWindowTaskbar");
|
||||
(Application.Current as App)?.OpenIndependentSettingsModule("MainWindowTaskbar");
|
||||
}
|
||||
|
||||
private void OnPowerMenuEnterClick(object? sender, RoutedEventArgs e)
|
||||
@@ -2861,34 +2851,6 @@ public partial class MainWindow
|
||||
CloseDetachedComponentLibraryWindow();
|
||||
}
|
||||
|
||||
public bool TryGetSettingsWindowAnchorBounds(out PixelRect anchorBounds)
|
||||
{
|
||||
anchorBounds = default;
|
||||
if (!IsVisible || BottomTaskbarContainer is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var origin = BottomTaskbarContainer.TranslatePoint(new Point(0, 0), this);
|
||||
if (origin is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var scale = RenderScaling > 0 ? RenderScaling : 1d;
|
||||
var width = (int)Math.Round(BottomTaskbarContainer.Bounds.Width * scale);
|
||||
var height = (int)Math.Round(BottomTaskbarContainer.Bounds.Height * scale);
|
||||
if (width <= 0 || height <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var x = Position.X + (int)Math.Round(origin.Value.X * scale);
|
||||
var y = Position.Y + (int)Math.Round(origin.Value.Y * scale);
|
||||
anchorBounds = new PixelRect(x, y, width, height);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CollapseComponentLibraryPanel()
|
||||
{
|
||||
// Animate component library panel collapsing downward
|
||||
|
||||
@@ -79,6 +79,7 @@ public partial class MainWindow
|
||||
string.Equals(key, nameof(AppSettingsSnapshot.UpdateDownloadSource), StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(key, nameof(AppSettingsSnapshot.UpdateDownloadThreads), StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(key, nameof(AppSettingsSnapshot.EnableThreeFingerSwipe), StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(key, nameof(AppSettingsSnapshot.ShowInTaskbar), StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(key, nameof(AppSettingsSnapshot.EnableSlideTransition), StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return;
|
||||
@@ -688,6 +689,10 @@ public partial class MainWindow
|
||||
StatusBarShadowEnabled = _statusBarShadowEnabled,
|
||||
StatusBarShadowColor = _statusBarShadowColor,
|
||||
StatusBarShadowOpacity = _statusBarShadowOpacity,
|
||||
EnableThreeFingerSwipe = existingSnapshot.EnableThreeFingerSwipe,
|
||||
EnableSlideTransition = existingSnapshot.EnableSlideTransition,
|
||||
ShowInTaskbar = existingSnapshot.ShowInTaskbar,
|
||||
EnableFusedDesktop = existingSnapshot.EnableFusedDesktop,
|
||||
DisabledPluginIds = existingSnapshot.DisabledPluginIds,
|
||||
StudyFrameMs = existingSnapshot.StudyFrameMs,
|
||||
StudyScoreThresholdDbfs = existingSnapshot.StudyScoreThresholdDbfs,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
UseLayoutRounding="True"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Background="Transparent"
|
||||
TransparencyLevelHint="Transparent"
|
||||
Title="LanMountainDesktop">
|
||||
|
||||
<Design.DataContext>
|
||||
@@ -99,12 +100,17 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.RenderTransform>
|
||||
<TranslateTransform />
|
||||
<TranslateTransform>
|
||||
<TranslateTransform.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="X" Duration="{StaticResource FluttermotionToken.Duration.Intro}" Easing="0.05,0.75,0.10,1.00" />
|
||||
</Transitions>
|
||||
</TranslateTransform.Transitions>
|
||||
</TranslateTransform>
|
||||
</Grid.RenderTransform>
|
||||
<Grid.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="{StaticResource FluttermotionToken.Duration.Page}" Easing="0.05,0.75,0.10,1.00" />
|
||||
<DoubleTransition Property="TranslateTransform.X" Duration="{StaticResource FluttermotionToken.Duration.Intro}" Easing="0.05,0.75,0.10,1.00" />
|
||||
</Transitions>
|
||||
</Grid.Transitions>
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ using LanMountainDesktop.Views.Components;
|
||||
|
||||
namespace LanMountainDesktop.Views;
|
||||
|
||||
public partial class MainWindow : Window, ISettingsWindowAnchorProvider
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private enum WallpaperMediaType
|
||||
{
|
||||
@@ -450,6 +450,8 @@ public partial class MainWindow : Window, ISettingsWindowAnchorProvider
|
||||
MinShortSideCells,
|
||||
MaxShortSideCells);
|
||||
|
||||
ShowInTaskbar = snapshot.ShowInTaskbar;
|
||||
|
||||
_gridSpacingPreset = _gridSettingsService.NormalizeSpacingPreset(snapshot.GridSpacingPreset);
|
||||
|
||||
_desktopEdgeInsetPercent = Math.Clamp(snapshot.DesktopEdgeInsetPercent, MinEdgeInsetPercent, MaxEdgeInsetPercent);
|
||||
@@ -884,7 +886,19 @@ public partial class MainWindow : Window, ISettingsWindowAnchorProvider
|
||||
return;
|
||||
}
|
||||
|
||||
WindowState = WindowState.Minimized;
|
||||
var snapshot = _settingsService.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
|
||||
if (snapshot.ShowInTaskbar)
|
||||
{
|
||||
WindowState = WindowState.Minimized;
|
||||
}
|
||||
else if (Application.Current is App app)
|
||||
{
|
||||
app.HideMainWindowToTray(this, "MinimizeAction");
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowState = WindowState.Minimized;
|
||||
}
|
||||
|
||||
slideTransform.X = 0;
|
||||
DesktopPage.Opacity = 1;
|
||||
@@ -906,7 +920,8 @@ public partial class MainWindow : Window, ISettingsWindowAnchorProvider
|
||||
|
||||
if (useSlide)
|
||||
{
|
||||
slideTransform.X = Bounds.Width > 0 ? Bounds.Width : 1920;
|
||||
var screenWidth = Screens.ScreenFromVisual(this)?.Bounds.Width ?? 3840;
|
||||
slideTransform.X = Bounds.Width > 0 ? Bounds.Width : screenWidth;
|
||||
}
|
||||
|
||||
DesktopPage.Transitions = savedTransitions;
|
||||
@@ -941,7 +956,27 @@ public partial class MainWindow : Window, ISettingsWindowAnchorProvider
|
||||
return;
|
||||
}
|
||||
|
||||
if (WindowState is WindowState.Minimized or WindowState.FullScreen)
|
||||
var newState = (WindowState)e.NewValue!;
|
||||
var oldState = (WindowState)e.OldValue!;
|
||||
|
||||
if (oldState == WindowState.Minimized && newState != WindowState.Minimized)
|
||||
{
|
||||
PrepareEnterAnimation();
|
||||
|
||||
if (newState != WindowState.FullScreen)
|
||||
{
|
||||
WindowState = WindowState.FullScreen;
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
PlayEnterAnimation();
|
||||
}, DispatcherPriority.Background);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (newState is WindowState.Minimized or WindowState.FullScreen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,16 @@
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="桌面主窗口在任务栏显示图标"
|
||||
Description="仅控制桌面主窗口在系统任务栏中的图标显示;不会影响设置窗口,设置窗口打开时始终保留独立任务栏图标">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Window" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding ShowInTaskbar}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
Reference in New Issue
Block a user