Skip to content

Commit 3e9a0e2

Browse files
committed
Added basic structure for fluent window
1 parent c7218fb commit 3e9a0e2

File tree

4 files changed

+181
-6
lines changed

4 files changed

+181
-6
lines changed

Flow.Launcher.Core/Resource/Theme.cs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
using Flow.Launcher.Infrastructure.Logger;
1313
using Flow.Launcher.Infrastructure.UserSettings;
1414
using System.Windows.Shell;
15+
using static Flow.Launcher.Core.Resource.Theme.ParameterTypes;
16+
using System.Runtime.InteropServices;
17+
using System.Windows.Interop;
1518

1619
namespace Flow.Launcher.Core.Resource
1720
{
@@ -59,6 +62,153 @@ public Theme()
5962
_oldTheme = Path.GetFileNameWithoutExtension(_oldResource.Source.AbsolutePath);
6063
}
6164

65+
#region Blur Handling
66+
public class ParameterTypes
67+
{
68+
69+
[Flags]
70+
public enum DWMWINDOWATTRIBUTE
71+
{
72+
DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
73+
DWMWA_SYSTEMBACKDROP_TYPE = 38,
74+
DWMWA_TRANSITIONS_FORCEDISABLED = 3,
75+
DWMWA_BORDER_COLOR
76+
}
77+
78+
[StructLayout(LayoutKind.Sequential)]
79+
public struct MARGINS
80+
{
81+
public int cxLeftWidth; // width of left border that retains its size
82+
public int cxRightWidth; // width of right border that retains its size
83+
public int cyTopHeight; // height of top border that retains its size
84+
public int cyBottomHeight; // height of bottom border that retains its size
85+
};
86+
}
87+
88+
public static class Methods
89+
{
90+
[DllImport("DwmApi.dll")]
91+
static extern int DwmExtendFrameIntoClientArea(
92+
IntPtr hwnd,
93+
ref ParameterTypes.MARGINS pMarInset);
94+
95+
[DllImport("dwmapi.dll")]
96+
static extern int DwmSetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE dwAttribute, ref int pvAttribute, int cbAttribute);
97+
98+
public static int ExtendFrame(IntPtr hwnd, ParameterTypes.MARGINS margins)
99+
=> DwmExtendFrameIntoClientArea(hwnd, ref margins);
100+
101+
public static int SetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE attribute, int parameter)
102+
=> DwmSetWindowAttribute(hwnd, attribute, ref parameter, Marshal.SizeOf<int>());
103+
}
104+
105+
Window mainWindow = Application.Current.MainWindow;
106+
107+
public void RefreshFrame()
108+
{
109+
IntPtr mainWindowPtr = new WindowInteropHelper(mainWindow).Handle;
110+
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
111+
//mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 255, 181, 178);
112+
113+
ParameterTypes.MARGINS margins = new ParameterTypes.MARGINS();
114+
margins.cxLeftWidth = -1;
115+
margins.cxRightWidth = -1;
116+
margins.cyTopHeight = -1;
117+
margins.cyBottomHeight = -1;
118+
Methods.ExtendFrame(mainWindowSrc.Handle, margins);
119+
120+
// Remove OS minimizing/maximizing animation
121+
Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_TRANSITIONS_FORCEDISABLED, 3);
122+
//Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_BORDER_COLOR, 0x00FF0000);
123+
Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE, 3);
124+
SetBlurForWindow();
125+
}
126+
127+
128+
129+
/// <summary>
130+
/// Sets the blur for a window via SetWindowCompositionAttribute
131+
/// </summary>
132+
public void SetBlurForWindow()
133+
{
134+
//SetWindowAccent();
135+
var dict = GetThemeResourceDictionary(Settings.Theme);
136+
var windowBorderStyle = dict["WindowBorderStyle"] as Style;
137+
if (BlurEnabled)
138+
{
139+
windowBorderStyle.Setters.Remove(windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property.Name == "Background"));
140+
windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
141+
//mainWindow.WindowStyle = WindowStyle.SingleBorderWindow;
142+
Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE, 3);
143+
BlurColor(BlurMode());
144+
}
145+
else
146+
{
147+
mainWindow.WindowStyle = WindowStyle.None;
148+
if (windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property.Name == "Background") != null)
149+
{
150+
windowBorderStyle.Setters.Add(windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property.Name == "Background"));
151+
}
152+
Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE, 1);
153+
}
154+
UpdateResourceDictionary(dict);
155+
}
156+
157+
public void BlurColor(string Color)
158+
{
159+
if (Color == "Light")
160+
{
161+
Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, 0);
162+
}
163+
else if (Color == "Dark")
164+
{
165+
Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, 1);
166+
}
167+
else /* Case of "Auto" Blur Type Theme */
168+
{
169+
//if (_isDarkTheme())
170+
//{
171+
// Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, 1);
172+
//}
173+
//else
174+
//{
175+
// Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, 0);
176+
//}
177+
Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, 1);
178+
}
179+
180+
}
181+
public bool IsBlurTheme()
182+
{
183+
if (Environment.OSVersion.Version >= new Version(6, 2))
184+
{
185+
var resource = Application.Current.TryFindResource("ThemeBlurEnabled");
186+
187+
if (resource is bool)
188+
return (bool)resource;
189+
190+
return false;
191+
}
192+
193+
return false;
194+
}
195+
public string BlurMode()
196+
{
197+
if (Environment.OSVersion.Version >= new Version(6, 2))
198+
{
199+
var resource = Application.Current.TryFindResource("BlurMode");
200+
201+
if (resource is string)
202+
return (string)resource;
203+
204+
return null;
205+
}
206+
207+
return null;
208+
}
209+
210+
#endregion
211+
62212
private void MakeSureThemeDirectoriesExist()
63213
{
64214
foreach (var dir in _themeDirectories.Where(dir => !Directory.Exists(dir)))
@@ -103,6 +253,7 @@ public bool ChangeTheme(string theme)
103253
AddDropShadowEffectToCurrentTheme();
104254

105255
Win32Helper.SetBlurForWindow(Application.Current.MainWindow, BlurEnabled);
256+
//Win32Helper.SetMicaForWindow(Application.Current.MainWindow, BlurEnabled);
106257
}
107258
catch (DirectoryNotFoundException)
108259
{

Flow.Launcher.Infrastructure/Win32Helper.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ namespace Flow.Launcher.Infrastructure
77
{
88
public static class Win32Helper
99
{
10+
private enum DwmSystemBackdropType
11+
{
12+
DWMSBT_AUTO = 0,
13+
DWMSBT_NONE = 1,
14+
DWMSBT_MICA = 2,
15+
DWMSBT_ACRYLIC = 3,
16+
DWMSBT_TABBED = 4
17+
}
18+
19+
private const int DWMWA_SYSTEMBACKDROP_TYPE = 38;
20+
21+
[DllImport("dwmapi.dll")]
22+
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, ref DwmSystemBackdropType pvAttribute, int cbAttribute);
23+
24+
public static void SetMicaForWindow(Window window, bool enableMica)
25+
{
26+
var windowHelper = new WindowInteropHelper(window);
27+
windowHelper.EnsureHandle();
28+
29+
DwmSystemBackdropType backdropType = enableMica ? DwmSystemBackdropType.DWMSBT_MICA : DwmSystemBackdropType.DWMSBT_NONE;
30+
DwmSetWindowAttribute(windowHelper.Handle, DWMWA_SYSTEMBACKDROP_TYPE, ref backdropType, sizeof(int));
31+
}
1032
#region Blur Handling
1133

1234
/*

Flow.Launcher/MainWindow.xaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@
1515
MinHeight="30"
1616
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
1717
AllowDrop="True"
18-
AllowsTransparency="True"
19-
Background="Transparent"
18+
AllowsTransparency="False"
19+
Background="#DB213C95"
2020
Closing="OnClosing"
2121
Deactivated="OnDeactivated"
2222
Icon="Images/app.png"
23-
SourceInitialized="OnSourceInitialized"
2423
Initialized="OnInitialized"
2524
Left="{Binding Settings.WindowLeft, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
2625
Loaded="OnLoaded"
@@ -31,10 +30,11 @@
3130
ResizeMode="CanResize"
3231
ShowInTaskbar="False"
3332
SizeToContent="Height"
33+
SourceInitialized="OnSourceInitialized"
3434
Topmost="True"
3535
Visibility="{Binding MainWindowVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
3636
WindowStartupLocation="Manual"
37-
WindowStyle="None"
37+
WindowStyle="SingleBorderWindow"
3838
mc:Ignorable="d">
3939
<!-- WindowChrome -->
4040
<WindowChrome.WindowChrome>
@@ -213,7 +213,7 @@
213213
Modifiers="{Binding CycleHistoryDownHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
214214
</Window.InputBindings>
215215

216-
<Border MouseDown="OnMouseDown" Style="{DynamicResource WindowBorderStyle}">
216+
<Border MouseDown="OnMouseDown">
217217
<StackPanel Orientation="Vertical">
218218
<Grid>
219219
<Border MinHeight="30" Style="{DynamicResource QueryBoxBgStyle}">

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ public MainWindow(Settings settings, MainViewModel mainVM)
6060
InitializePosition();
6161

6262
InitSoundEffects();
63-
6463
DataObject.AddPastingHandler(QueryTextBox, OnPaste);
6564

6665
this.Loaded += (_, _) =>
@@ -182,6 +181,9 @@ private void OnInitialized(object sender, EventArgs e)
182181

183182
private void OnLoaded(object sender, RoutedEventArgs _)
184183
{
184+
// Remove OS minimizing/maximizing animation
185+
ThemeManager.Instance.RefreshFrame();
186+
185187
// MouseEventHandler
186188
PreviewMouseMove += MainPreviewMouseMove;
187189
CheckFirstLaunch();

0 commit comments

Comments
 (0)