From d67524485c83d950825809bcbd1acab243a0ff79 Mon Sep 17 00:00:00 2001 From: lars-berger Date: Sun, 17 Sep 2023 19:50:48 +0800 Subject: [PATCH] feat: option to disable window transition animations (#389) --- GlazeWM.App.Watcher/WatcherStartup.cs | 4 +++ GlazeWM.App.WindowManager/WmStartup.cs | 10 ++++++ GlazeWM.App/Resources/sample-config.yaml | 4 +++ GlazeWM.Domain/UserConfigs/GeneralConfig.cs | 5 ++- .../UserConfigs/WindowAnimations.cs | 9 ++++++ .../WindowsApi/SystemSettings.cs | 22 +++++++++++++ .../WindowsApi/WindowsApiService.cs | 31 +++++++++++++++++++ 7 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 GlazeWM.Domain/UserConfigs/WindowAnimations.cs create mode 100644 GlazeWM.Infrastructure/WindowsApi/SystemSettings.cs diff --git a/GlazeWM.App.Watcher/WatcherStartup.cs b/GlazeWM.App.Watcher/WatcherStartup.cs index 84dfc8351..eeed4de7f 100644 --- a/GlazeWM.App.Watcher/WatcherStartup.cs +++ b/GlazeWM.App.Watcher/WatcherStartup.cs @@ -10,6 +10,10 @@ namespace GlazeWM.App.Watcher { public sealed class WatcherStartup { + /// + /// Watcher is responsible for restoring all managed handles when the main process is + /// killed unexpectedly. + /// public static async Task Run(int ipcServerPort) { var client = new IpcClient(ipcServerPort); diff --git a/GlazeWM.App.WindowManager/WmStartup.cs b/GlazeWM.App.WindowManager/WmStartup.cs index 78488316f..b4ec77508 100644 --- a/GlazeWM.App.WindowManager/WmStartup.cs +++ b/GlazeWM.App.WindowManager/WmStartup.cs @@ -76,6 +76,16 @@ public ExitCode Run() _systemTrayIcon = new SystemTrayIcon(systemTrayIconConfig); _systemTrayIcon.Show(); + var windowAnimations = _userConfigService.GeneralConfig.WindowAnimations; + + // Enable/disable window transition animations. + if (windowAnimations is not WindowAnimations.Unchanged) + { + SystemSettings.SetWindowAnimationsEnabled( + windowAnimations is WindowAnimations.True + ); + } + if (_userConfigService.FocusBorderConfig.Active.Enabled || _userConfigService.FocusBorderConfig.Inactive.Enabled) { diff --git a/GlazeWM.App/Resources/sample-config.yaml b/GlazeWM.App/Resources/sample-config.yaml index bce40742a..82ef0921f 100644 --- a/GlazeWM.App/Resources/sample-config.yaml +++ b/GlazeWM.App/Resources/sample-config.yaml @@ -18,6 +18,10 @@ general: floating_window_move_amount: "5%" # When enabled, switching to the current workspace activates the previously focused workspace toggle_workspace_on_refocus: false + # *Strongly* recommended to set to 'false'. Whether to globally enable/disable + # window transition animations (on minimize, close, etc). Set to 'unchanged' + # to make no setting changes. + window_animations: "unchanged" bar: height: "30px" diff --git a/GlazeWM.Domain/UserConfigs/GeneralConfig.cs b/GlazeWM.Domain/UserConfigs/GeneralConfig.cs index 7d0f53aee..27a88df89 100644 --- a/GlazeWM.Domain/UserConfigs/GeneralConfig.cs +++ b/GlazeWM.Domain/UserConfigs/GeneralConfig.cs @@ -8,7 +8,6 @@ public class GeneralConfig public bool ShowFloatingOnTop { get; set; } /// /// Center the cursor in the middle of a newly focused window - /// TODO: Not officially released because implementation is buggy. Use at own risk. /// public bool CursorFollowsFocus { get; set; } /// @@ -23,5 +22,9 @@ public class GeneralConfig /// If activated, by switching to the current workspace the previous focused workspace is activated. /// public bool ToggleWorkspaceOnRefocus { get; set; } + /// + /// Whether to enable window transition animations (on minimize, close, etc). + /// + public WindowAnimations WindowAnimations { get; set; } = WindowAnimations.Unchanged; } } diff --git a/GlazeWM.Domain/UserConfigs/WindowAnimations.cs b/GlazeWM.Domain/UserConfigs/WindowAnimations.cs new file mode 100644 index 000000000..319672b1d --- /dev/null +++ b/GlazeWM.Domain/UserConfigs/WindowAnimations.cs @@ -0,0 +1,9 @@ +namespace GlazeWM.Domain.UserConfigs +{ + public enum WindowAnimations + { + Unchanged, + True, + False + } +} diff --git a/GlazeWM.Infrastructure/WindowsApi/SystemSettings.cs b/GlazeWM.Infrastructure/WindowsApi/SystemSettings.cs new file mode 100644 index 000000000..a908e6ad6 --- /dev/null +++ b/GlazeWM.Infrastructure/WindowsApi/SystemSettings.cs @@ -0,0 +1,22 @@ +using static GlazeWM.Infrastructure.WindowsApi.WindowsApiService; + +namespace GlazeWM.Infrastructure.WindowsApi +{ + public static class SystemSettings + { + /// + /// Modify global setting for whether window transition animations are enabled. + /// + public static void SetWindowAnimationsEnabled(bool enabled) + { + var animationInfo = AnimationInfo.Create(enabled); + + SystemParametersInfo( + SystemParametersInfoFlags.SetAnimation, + animationInfo.CallbackSize, + ref animationInfo, + 0 + ); + } + } +} diff --git a/GlazeWM.Infrastructure/WindowsApi/WindowsApiService.cs b/GlazeWM.Infrastructure/WindowsApi/WindowsApiService.cs index 1619cb3d9..5b9080378 100644 --- a/GlazeWM.Infrastructure/WindowsApi/WindowsApiService.cs +++ b/GlazeWM.Infrastructure/WindowsApi/WindowsApiService.cs @@ -464,6 +464,37 @@ public struct SystemPowerStatus [DllImport("dwmapi.dll")] public static extern int DwmSetWindowAttribute(IntPtr handle, uint attribute, ref uint value, uint size); + [StructLayout(LayoutKind.Sequential)] + public struct AnimationInfo + { + public uint CallbackSize; + public int MinAnimate; + + public bool IsEnabled + { + readonly get => MinAnimate != 0; + set => MinAnimate = value ? 1 : 0; + } + + public static AnimationInfo Create(bool isEnabled) + { + return new() + { + IsEnabled = isEnabled, + CallbackSize = (uint)Marshal.SizeOf(typeof(AnimationInfo)) + }; + } + } + + public enum SystemParametersInfoFlags : uint + { + GetAnimation = 72, + SetAnimation = 73, + } + + [DllImport("User32.dll", SetLastError = true)] + public static extern bool SystemParametersInfo(SystemParametersInfoFlags uiAction, uint uiParam, ref AnimationInfo pvParam, uint fWinIni); + [DllImport("kernel32.dll")] internal static extern bool AttachConsole(uint dwProcessId);