From ddcf12231f46206d23557c05b072ba0b65d9ab1d Mon Sep 17 00:00:00 2001
From: wuyangfan <1102042793@qq.com>
Date: Mon, 18 May 2026 00:15:20 +0800
Subject: [PATCH] feat(ui): add option to disable menu popup animations (#3737)
Expose EnableMenuAnimations in Display settings (defaults to the OS
preference). When disabled, menu and submenu popups open instantly
without fade animation via SystemParameters.MenuPopupAnimation.
---
ILSpy/App.xaml.cs | 2 ++
ILSpy/Options/DisplaySettings.cs | 9 ++++++
ILSpy/Options/DisplaySettingsPanel.xaml | 1 +
ILSpy/Properties/Resources.Designer.cs | 9 ++++++
ILSpy/Properties/Resources.resx | 3 ++
ILSpy/Util/MenuPopupAnimationHelper.cs | 41 +++++++++++++++++++++++++
ILSpy/Util/SettingsService.cs | 7 +++++
7 files changed, 72 insertions(+)
create mode 100644 ILSpy/Util/MenuPopupAnimationHelper.cs
diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs
index 66f81e7a49..f6dce89104 100644
--- a/ILSpy/App.xaml.cs
+++ b/ILSpy/App.xaml.cs
@@ -29,6 +29,7 @@
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.AssemblyTree;
+using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Analyzers;
using Medo.Application;
@@ -109,6 +110,7 @@ public App()
Resources.MergedDictionaries.Add(DataTemplateManager.CreateDynamicDataTemplates(ExportProvider));
var sessionSettings = settingsService.SessionSettings;
+ MenuPopupAnimationHelper.Apply(settingsService.DisplaySettings.EnableMenuAnimations);
ThemeManager.Current.Theme = sessionSettings.Theme;
if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture))
{
diff --git a/ILSpy/Options/DisplaySettings.cs b/ILSpy/Options/DisplaySettings.cs
index a65748446e..bbbf2499da 100644
--- a/ILSpy/Options/DisplaySettings.cs
+++ b/ILSpy/Options/DisplaySettings.cs
@@ -19,6 +19,7 @@
using System.Windows.Media;
using System.Xml.Linq;
+using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Settings;
using TomsToolbox.Wpf;
@@ -156,6 +157,12 @@ public bool EnableSmoothScrolling {
set => SetProperty(ref enableSmoothScrolling, value);
}
+ private bool enableMenuAnimations;
+ public bool EnableMenuAnimations {
+ get => enableMenuAnimations;
+ set => SetProperty(ref enableMenuAnimations, value);
+ }
+
private bool decodeCustomAttributeBlobs;
public bool DecodeCustomAttributeBlobs {
get => decodeCustomAttributeBlobs;
@@ -187,6 +194,7 @@ public void LoadFromXml(XElement section)
ShowRawOffsetsAndBytesBeforeInstruction = (bool?)section.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false;
StyleWindowTitleBar = (bool?)section.Attribute("StyleWindowTitleBar") ?? false;
EnableSmoothScrolling = (bool?)section.Attribute("EnableSmoothScrolling") ?? true;
+ EnableMenuAnimations = (bool?)section.Attribute("EnableMenuAnimations") ?? MenuPopupAnimationHelper.DefaultFromSystem();
DecodeCustomAttributeBlobs = (bool?)section.Attribute("DecodeCustomAttributeBlobs") ?? false;
}
@@ -215,6 +223,7 @@ public XElement SaveToXml()
section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", ShowRawOffsetsAndBytesBeforeInstruction);
section.SetAttributeValue("StyleWindowTitleBar", StyleWindowTitleBar);
section.SetAttributeValue("EnableSmoothScrolling", EnableSmoothScrolling);
+ section.SetAttributeValue("EnableMenuAnimations", EnableMenuAnimations);
section.SetAttributeValue("DecodeCustomAttributeBlobs", DecodeCustomAttributeBlobs);
return section;
diff --git a/ILSpy/Options/DisplaySettingsPanel.xaml b/ILSpy/Options/DisplaySettingsPanel.xaml
index 58c7ae3161..ffc5e3bd2e 100644
--- a/ILSpy/Options/DisplaySettingsPanel.xaml
+++ b/ILSpy/Options/DisplaySettingsPanel.xaml
@@ -80,6 +80,7 @@
+
diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs
index b96523d852..1dfcf69de2 100644
--- a/ILSpy/Properties/Resources.Designer.cs
+++ b/ILSpy/Properties/Resources.Designer.cs
@@ -1830,6 +1830,15 @@ public static string EnableSmoothScrolling {
}
}
+ ///
+ /// Looks up a localized string similar to Enable menu animations.
+ ///
+ public static string EnableMenuAnimations {
+ get {
+ return ResourceManager.GetString("EnableMenuAnimations", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Enable word wrap.
///
diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx
index aa5fff5fd0..c7bfd90af7 100644
--- a/ILSpy/Properties/Resources.resx
+++ b/ILSpy/Properties/Resources.resx
@@ -627,6 +627,9 @@ Are you sure you want to continue?
Enable smooth scrolling
+
+ Enable menu animations
+
Enable word wrap
diff --git a/ILSpy/Util/MenuPopupAnimationHelper.cs b/ILSpy/Util/MenuPopupAnimationHelper.cs
new file mode 100644
index 0000000000..d7d54cc3e1
--- /dev/null
+++ b/ILSpy/Util/MenuPopupAnimationHelper.cs
@@ -0,0 +1,41 @@
+// Copyright (c) 2026 ILSpy contributors
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System.Windows;
+using System.Windows.Controls.Primitives;
+
+namespace ICSharpCode.ILSpy.Util
+{
+ internal static class MenuPopupAnimationHelper
+ {
+ private static readonly PopupAnimation SystemMenuPopupAnimation = SystemParameters.MenuPopupAnimation;
+
+ public static bool DefaultFromSystem()
+ {
+ return SystemMenuPopupAnimation != PopupAnimation.None;
+ }
+
+ public static void Apply(bool enableMenuAnimations)
+ {
+ var animation = enableMenuAnimations ? SystemMenuPopupAnimation : PopupAnimation.None;
+ SystemParameters.OverrideMetadata(
+ SystemParameters.MenuPopupAnimationKey,
+ new FrameworkPropertyMetadata(animation));
+ }
+ }
+}
diff --git a/ILSpy/Util/SettingsService.cs b/ILSpy/Util/SettingsService.cs
index 289d097464..d2b0493e83 100644
--- a/ILSpy/Util/SettingsService.cs
+++ b/ILSpy/Util/SettingsService.cs
@@ -99,6 +99,7 @@ public void Reload()
finally
{
reloading = false;
+ MenuPopupAnimationHelper.Apply(DisplaySettings.EnableMenuAnimations);
}
}
@@ -129,6 +130,12 @@ protected override void Section_PropertyChanged(object? sender, PropertyChangedE
assemblyListManager.UseDebugSymbols = decompilerSettings.UseDebugSymbols;
}
+ if (sender is DisplaySettings displaySettings
+ && e.PropertyName == nameof(DisplaySettings.EnableMenuAnimations))
+ {
+ MenuPopupAnimationHelper.Apply(displaySettings.EnableMenuAnimations);
+ }
+
MessageBus.Send(sender, new SettingsChangedEventArgs(e));
}