Skip to content

Commit 0e95cd0

Browse files
authored
Merge branch 'dev' into rename-file
2 parents 5d2fb6e + 5ae159d commit 0e95cd0

File tree

87 files changed

+4255
-10192
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+4255
-10192
lines changed

Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs

Lines changed: 0 additions & 24 deletions
This file was deleted.

Flow.Launcher.Core/Resource/Theme.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,19 @@ public bool ChangeTheme(string theme = null)
449449
}
450450
return false;
451451
}
452-
catch (XamlParseException)
452+
catch (XamlParseException e)
453453
{
454-
_api.LogError(ClassName, $"Theme <{theme}> fail to parse");
454+
_api.LogException(ClassName, $"Theme <{theme}> fail to parse xaml", e);
455+
if (theme != Constant.DefaultTheme)
456+
{
457+
_api.ShowMsgBox(Localize.theme_load_failure_parse_error(theme));
458+
ChangeTheme(Constant.DefaultTheme);
459+
}
460+
return false;
461+
}
462+
catch (Exception e)
463+
{
464+
_api.LogException(ClassName, $"Theme <{theme}> fail to load", e);
455465
if (theme != Constant.DefaultTheme)
456466
{
457467
_api.ShowMsgBox(Localize.theme_load_failure_parse_error(theme));

Flow.Launcher.Infrastructure/NativeMethods.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,10 @@ QueryFullProcessImageName
8585
EVENT_OBJECT_HIDE
8686
EVENT_SYSTEM_DIALOGEND
8787

88+
DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
8889
WM_POWERBROADCAST
89-
PBT_APMRESUMEAUTOMATIC
90+
PBT_APMRESUMEAUTOMATIC
91+
PBT_APMRESUMESUSPEND
92+
PowerRegisterSuspendResumeNotification
93+
PowerUnregisterSuspendResumeNotification
94+
DeviceNotifyCallbackRoutine

Flow.Launcher.Infrastructure/Win32Helper.cs

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Windows.Win32;
2020
using Windows.Win32.Foundation;
2121
using Windows.Win32.Graphics.Dwm;
22+
using Windows.Win32.System.Power;
2223
using Windows.Win32.System.Threading;
2324
using Windows.Win32.UI.Input.KeyboardAndMouse;
2425
using Windows.Win32.UI.Shell.Common;
@@ -338,9 +339,6 @@ public static Point TransformPixelsToDIP(Visual visual, double unitX, double uni
338339
public const int SC_MAXIMIZE = (int)PInvoke.SC_MAXIMIZE;
339340
public const int SC_MINIMIZE = (int)PInvoke.SC_MINIMIZE;
340341

341-
public const int WM_POWERBROADCAST = (int)PInvoke.WM_POWERBROADCAST;
342-
public const int PBT_APMRESUMEAUTOMATIC = (int)PInvoke.PBT_APMRESUMEAUTOMATIC;
343-
344342
#endregion
345343

346344
#region Window Handle
@@ -918,5 +916,105 @@ public static string SelectFile()
918916
}
919917

920918
#endregion
919+
920+
#region Sleep Mode Listener
921+
922+
private static Action _func;
923+
private static PDEVICE_NOTIFY_CALLBACK_ROUTINE _callback = null;
924+
private static DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS _recipient;
925+
private static SafeHandle _recipientHandle;
926+
private static HPOWERNOTIFY _handle = HPOWERNOTIFY.Null;
927+
928+
/// <summary>
929+
/// Registers a listener for sleep mode events.
930+
/// Inspired from: https://github.com/XKaguya/LenovoLegionToolkit
931+
/// https://blog.csdn.net/mochounv/article/details/114668594
932+
/// </summary>
933+
/// <param name="func"></param>
934+
/// <exception cref="Win32Exception"></exception>
935+
public static unsafe void RegisterSleepModeListener(Action func)
936+
{
937+
if (_callback != null)
938+
{
939+
// Only register if not already registered
940+
return;
941+
}
942+
943+
_func = func;
944+
_callback = new PDEVICE_NOTIFY_CALLBACK_ROUTINE(DeviceNotifyCallback);
945+
_recipient = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS()
946+
{
947+
Callback = _callback,
948+
Context = null
949+
};
950+
951+
_recipientHandle = new StructSafeHandle<DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS>(_recipient);
952+
_handle = PInvoke.PowerRegisterSuspendResumeNotification(
953+
REGISTER_NOTIFICATION_FLAGS.DEVICE_NOTIFY_CALLBACK,
954+
_recipientHandle,
955+
out var handle) == WIN32_ERROR.ERROR_SUCCESS ?
956+
new HPOWERNOTIFY(new IntPtr(handle)) :
957+
HPOWERNOTIFY.Null;
958+
if (_handle.IsNull)
959+
{
960+
throw new Win32Exception("Error registering for power notifications: " + Marshal.GetLastWin32Error());
961+
}
962+
}
963+
964+
/// <summary>
965+
/// Unregisters the sleep mode listener.
966+
/// </summary>
967+
public static void UnregisterSleepModeListener()
968+
{
969+
if (!_handle.IsNull)
970+
{
971+
PInvoke.PowerUnregisterSuspendResumeNotification(_handle);
972+
_handle = HPOWERNOTIFY.Null;
973+
_func = null;
974+
_callback = null;
975+
_recipientHandle = null;
976+
}
977+
}
978+
979+
private static unsafe uint DeviceNotifyCallback(void* context, uint type, void* setting)
980+
{
981+
switch (type)
982+
{
983+
case PInvoke.PBT_APMRESUMEAUTOMATIC:
984+
// Operation is resuming automatically from a low-power state.This message is sent every time the system resumes
985+
_func?.Invoke();
986+
break;
987+
988+
case PInvoke.PBT_APMRESUMESUSPEND:
989+
// Operation is resuming from a low-power state.This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key
990+
_func?.Invoke();
991+
break;
992+
}
993+
994+
return 0;
995+
}
996+
997+
private sealed class StructSafeHandle<T> : SafeHandle where T : struct
998+
{
999+
private readonly nint _ptr = nint.Zero;
1000+
1001+
public StructSafeHandle(T recipient) : base(nint.Zero, true)
1002+
{
1003+
var pRecipient = Marshal.AllocHGlobal(Marshal.SizeOf<T>());
1004+
Marshal.StructureToPtr(recipient, pRecipient, false);
1005+
SetHandle(pRecipient);
1006+
_ptr = pRecipient;
1007+
}
1008+
1009+
public override bool IsInvalid => handle == nint.Zero;
1010+
1011+
protected override bool ReleaseHandle()
1012+
{
1013+
Marshal.FreeHGlobal(_ptr);
1014+
return true;
1015+
}
1016+
}
1017+
1018+
#endregion
9211019
}
9221020
}

Flow.Launcher/App.xaml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,26 @@
22
x:Class="Flow.Launcher.App"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5-
xmlns:ui="http://schemas.modernwpf.com/2019"
5+
xmlns:sys="clr-namespace:System;assembly=mscorlib"
6+
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
67
ShutdownMode="OnMainWindowClose"
78
Startup="OnStartup">
89
<Application.Resources>
910
<ResourceDictionary>
1011
<ResourceDictionary.MergedDictionaries>
1112
<ui:ThemeResources>
1213
<ui:ThemeResources.ThemeDictionaries>
13-
<ResourceDictionary x:Key="Light">
14+
<ResourceDictionary x:Key="Light" ui:ThemeDictionary.Key="Light">
1415
<ResourceDictionary.MergedDictionaries>
1516
<ResourceDictionary Source="pack://application:,,,/Resources/Light.xaml" />
1617
</ResourceDictionary.MergedDictionaries>
1718
</ResourceDictionary>
18-
<ResourceDictionary x:Key="Dark">
19+
<ResourceDictionary x:Key="Dark" ui:ThemeDictionary.Key="Dark">
1920
<ResourceDictionary.MergedDictionaries>
2021
<ResourceDictionary Source="pack://application:,,,/Resources/Dark.xaml" />
2122
</ResourceDictionary.MergedDictionaries>
2223
</ResourceDictionary>
23-
<ResourceDictionary x:Key="HighContrast">
24+
<ResourceDictionary x:Key="HighContrast" ui:ThemeDictionary.Key="HighContrast">
2425
<ResourceDictionary.MergedDictionaries>
2526
<ResourceDictionary Source="pack://application:,,,/Resources/Dark.xaml" />
2627
</ResourceDictionary.MergedDictionaries>
@@ -33,6 +34,15 @@
3334
<ResourceDictionary Source="pack://application:,,,/Themes/Win11Light.xaml" />
3435
<ResourceDictionary Source="pack://application:,,,/Languages/en.xaml" />
3536
</ResourceDictionary.MergedDictionaries>
37+
38+
<!-- Override styles in UI.Modern.WPF -->
39+
<Thickness x:Key="ListViewItemCompactSelectedBorderThemeThickness">2</Thickness>
40+
<sys:Double x:Key="CheckBoxMinWidth">0</sys:Double>
41+
<sys:Double x:Key="GridViewItemMinWidth">0</sys:Double>
42+
<sys:Double x:Key="GridViewItemMinHeight">40</sys:Double>
43+
<sys:Double x:Key="ListViewItemMinWidth">0</sys:Double>
44+
<sys:Double x:Key="ListViewItemMinHeight">36</sys:Double>
45+
<SolidColorBrush x:Key="NavigationViewSelectionIndicatorForeground" Color="#FF0063B1" />
3646
</ResourceDictionary>
3747
</Application.Resources>
3848
</Application>

Flow.Launcher/App.xaml.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using Flow.Launcher.Plugin;
2323
using Flow.Launcher.SettingPages.ViewModels;
2424
using Flow.Launcher.ViewModel;
25+
using iNKORE.UI.WPF.Modern.Common;
2526
using Microsoft.Extensions.DependencyInjection;
2627
using Microsoft.Extensions.Hosting;
2728
using Microsoft.VisualStudio.Threading;
@@ -56,6 +57,9 @@ public partial class App : IDisposable, ISingleInstanceApp
5657

5758
public App()
5859
{
60+
// Do not use bitmap cache since it can cause WPF second window freezing issue
61+
ShadowAssist.UseBitmapCache = false;
62+
5963
// Initialize settings
6064
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
6165

Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace Flow.Launcher.Converters;
77

8-
internal class BoolToIMEConversionModeConverter : IValueConverter
8+
public class BoolToIMEConversionModeConverter : IValueConverter
99
{
1010
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
1111
{
@@ -22,7 +22,7 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu
2222
}
2323
}
2424

25-
internal class BoolToIMEStateConverter : IValueConverter
25+
public class BoolToIMEStateConverter : IValueConverter
2626
{
2727
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
2828
{
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows;
4+
using System.Windows.Data;
5+
6+
namespace Flow.Launcher.Converters;
7+
8+
public class CornerRadiusFilterConverter : DependencyObject, IValueConverter
9+
{
10+
public CornerRadiusFilterKind Filter { get; set; }
11+
12+
public double Scale { get; set; } = 1.0;
13+
14+
public static CornerRadius Convert(CornerRadius radius, CornerRadiusFilterKind filterKind)
15+
{
16+
CornerRadius result = radius;
17+
18+
switch (filterKind)
19+
{
20+
case CornerRadiusFilterKind.Top:
21+
result.BottomLeft = 0;
22+
result.BottomRight = 0;
23+
break;
24+
case CornerRadiusFilterKind.Right:
25+
result.TopLeft = 0;
26+
result.BottomLeft = 0;
27+
break;
28+
case CornerRadiusFilterKind.Bottom:
29+
result.TopLeft = 0;
30+
result.TopRight = 0;
31+
break;
32+
case CornerRadiusFilterKind.Left:
33+
result.TopRight = 0;
34+
result.BottomRight = 0;
35+
break;
36+
}
37+
38+
return result;
39+
}
40+
41+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
42+
{
43+
var cornerRadius = (CornerRadius)value;
44+
45+
var scale = Scale;
46+
if (!double.IsNaN(scale))
47+
{
48+
cornerRadius.TopLeft *= scale;
49+
cornerRadius.TopRight *= scale;
50+
cornerRadius.BottomRight *= scale;
51+
cornerRadius.BottomLeft *= scale;
52+
}
53+
54+
var filterType = Filter;
55+
if (filterType == CornerRadiusFilterKind.TopLeftValue ||
56+
filterType == CornerRadiusFilterKind.BottomRightValue)
57+
{
58+
return GetDoubleValue(cornerRadius, filterType);
59+
}
60+
61+
return Convert(cornerRadius, filterType);
62+
}
63+
64+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
65+
{
66+
throw new NotImplementedException();
67+
}
68+
69+
private static double GetDoubleValue(CornerRadius radius, CornerRadiusFilterKind filterKind)
70+
{
71+
switch (filterKind)
72+
{
73+
case CornerRadiusFilterKind.TopLeftValue:
74+
return radius.TopLeft;
75+
case CornerRadiusFilterKind.BottomRightValue:
76+
return radius.BottomRight;
77+
}
78+
return 0;
79+
}
80+
}
81+
82+
public enum CornerRadiusFilterKind
83+
{
84+
None,
85+
Top,
86+
Right,
87+
Bottom,
88+
Left,
89+
TopLeftValue,
90+
BottomRightValue
91+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows;
4+
using System.Windows.Data;
5+
6+
namespace Flow.Launcher.Converters;
7+
8+
public class PlacementRectangleConverter : IMultiValueConverter
9+
{
10+
public Thickness Margin { get; set; }
11+
12+
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
13+
{
14+
if (values.Length == 2 &&
15+
values[0] is double width &&
16+
values[1] is double height)
17+
{
18+
var margin = Margin;
19+
var topLeft = new Point(margin.Left, margin.Top);
20+
var bottomRight = new Point(width - margin.Right, height - margin.Bottom);
21+
var rect = new Rect(topLeft, bottomRight);
22+
return rect;
23+
}
24+
25+
return Rect.Empty;
26+
}
27+
28+
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
29+
{
30+
throw new NotImplementedException();
31+
}
32+
}

0 commit comments

Comments
 (0)