mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into enable_windows_key
This commit is contained in:
commit
b7c3a19a02
12 changed files with 155 additions and 68 deletions
|
|
@ -11,6 +11,7 @@ using System.Windows.Media.Effects;
|
||||||
using Flow.Launcher.Infrastructure;
|
using Flow.Launcher.Infrastructure;
|
||||||
using Flow.Launcher.Infrastructure.Logger;
|
using Flow.Launcher.Infrastructure.Logger;
|
||||||
using Flow.Launcher.Infrastructure.UserSettings;
|
using Flow.Launcher.Infrastructure.UserSettings;
|
||||||
|
using System.Windows.Shell;
|
||||||
|
|
||||||
namespace Flow.Launcher.Core.Resource
|
namespace Flow.Launcher.Core.Resource
|
||||||
{
|
{
|
||||||
|
|
@ -306,12 +307,15 @@ namespace Flow.Launcher.Core.Resource
|
||||||
var marginSetter = windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == Border.MarginProperty) as Setter;
|
var marginSetter = windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == Border.MarginProperty) as Setter;
|
||||||
if (marginSetter == null)
|
if (marginSetter == null)
|
||||||
{
|
{
|
||||||
|
var margin = new Thickness(ShadowExtraMargin, 12, ShadowExtraMargin, ShadowExtraMargin);
|
||||||
marginSetter = new Setter()
|
marginSetter = new Setter()
|
||||||
{
|
{
|
||||||
Property = Border.MarginProperty,
|
Property = Border.MarginProperty,
|
||||||
Value = new Thickness(ShadowExtraMargin, 12, ShadowExtraMargin, ShadowExtraMargin),
|
Value = margin,
|
||||||
};
|
};
|
||||||
windowBorderStyle.Setters.Add(marginSetter);
|
windowBorderStyle.Setters.Add(marginSetter);
|
||||||
|
|
||||||
|
SetResizeBoarderThickness(margin);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -322,6 +326,8 @@ namespace Flow.Launcher.Core.Resource
|
||||||
baseMargin.Right + ShadowExtraMargin,
|
baseMargin.Right + ShadowExtraMargin,
|
||||||
baseMargin.Bottom + ShadowExtraMargin);
|
baseMargin.Bottom + ShadowExtraMargin);
|
||||||
marginSetter.Value = newMargin;
|
marginSetter.Value = newMargin;
|
||||||
|
|
||||||
|
SetResizeBoarderThickness(newMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
windowBorderStyle.Setters.Add(effectSetter);
|
windowBorderStyle.Setters.Add(effectSetter);
|
||||||
|
|
@ -352,9 +358,36 @@ namespace Flow.Launcher.Core.Resource
|
||||||
marginSetter.Value = newMargin;
|
marginSetter.Value = newMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetResizeBoarderThickness(null);
|
||||||
|
|
||||||
UpdateResourceDictionary(dict);
|
UpdateResourceDictionary(dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// because adding drop shadow effect will change the margin of the window,
|
||||||
|
// we need to update the window chrome thickness to correct set the resize border
|
||||||
|
private static void SetResizeBoarderThickness(Thickness? effectMargin)
|
||||||
|
{
|
||||||
|
var window = Application.Current.MainWindow;
|
||||||
|
if (WindowChrome.GetWindowChrome(window) is WindowChrome windowChrome)
|
||||||
|
{
|
||||||
|
Thickness thickness;
|
||||||
|
if (effectMargin == null)
|
||||||
|
{
|
||||||
|
thickness = SystemParameters.WindowResizeBorderThickness;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thickness = new Thickness(
|
||||||
|
effectMargin.Value.Left + SystemParameters.WindowResizeBorderThickness.Left,
|
||||||
|
effectMargin.Value.Top + SystemParameters.WindowResizeBorderThickness.Top,
|
||||||
|
effectMargin.Value.Right + SystemParameters.WindowResizeBorderThickness.Right,
|
||||||
|
effectMargin.Value.Bottom + SystemParameters.WindowResizeBorderThickness.Bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
windowChrome.ResizeBorderThickness = thickness;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public record ThemeData(string FileNameWithoutExtension, string Name, bool? IsDark = null, bool? HasBlur = null);
|
public record ThemeData(string FileNameWithoutExtension, string Name, bool? IsDark = null, bool? HasBlur = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,11 @@ namespace Flow.Launcher.Infrastructure.Image
|
||||||
// Fallback to IconOnly if ThumbnailOnly fails
|
// Fallback to IconOnly if ThumbnailOnly fails
|
||||||
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
|
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
|
||||||
}
|
}
|
||||||
|
catch (FileNotFoundException) when (options == ThumbnailOptions.ThumbnailOnly)
|
||||||
|
{
|
||||||
|
// Fallback to IconOnly if files cannot be found
|
||||||
|
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
using System;
|
using System.Text.Json.Serialization;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin
|
namespace Flow.Launcher.Plugin
|
||||||
{
|
{
|
||||||
|
|
@ -9,15 +6,6 @@ namespace Flow.Launcher.Plugin
|
||||||
{
|
{
|
||||||
public Query() { }
|
public Query() { }
|
||||||
|
|
||||||
[Obsolete("Use the default Query constructor.")]
|
|
||||||
public Query(string rawQuery, string search, string[] terms, string[] searchTerms, string actionKeyword = "")
|
|
||||||
{
|
|
||||||
Search = search;
|
|
||||||
RawQuery = rawQuery;
|
|
||||||
SearchTerms = searchTerms;
|
|
||||||
ActionKeyword = actionKeyword;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raw query, this includes action keyword if it has
|
/// Raw query, this includes action keyword if it has
|
||||||
/// We didn't recommend use this property directly. You should always use Search property.
|
/// We didn't recommend use this property directly. You should always use Search property.
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<!-- WindowChrome -->
|
<!-- WindowChrome -->
|
||||||
<WindowChrome.WindowChrome>
|
<WindowChrome.WindowChrome>
|
||||||
<WindowChrome CaptionHeight="9" ResizeBorderThickness="32 4 32 32" />
|
<WindowChrome CaptionHeight="9" />
|
||||||
</WindowChrome.WindowChrome>
|
</WindowChrome.WindowChrome>
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<converters:QuerySuggestionBoxConverter x:Key="QuerySuggestionBoxConverter" />
|
<converters:QuerySuggestionBoxConverter x:Key="QuerySuggestionBoxConverter" />
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ namespace Flow.Launcher.Storage
|
||||||
|
|
||||||
internal bool IsTopMost(Result result)
|
internal bool IsTopMost(Result result)
|
||||||
{
|
{
|
||||||
|
// origin query is null when user select the context menu item directly of one item from query list
|
||||||
|
// in this case, we do not need to check if the result is top most
|
||||||
if (records.IsEmpty || result.OriginQuery == null ||
|
if (records.IsEmpty || result.OriginQuery == null ||
|
||||||
!records.TryGetValue(result.OriginQuery.RawQuery, out var value))
|
!records.TryGetValue(result.OriginQuery.RawQuery, out var value))
|
||||||
{
|
{
|
||||||
|
|
@ -24,11 +26,25 @@ namespace Flow.Launcher.Storage
|
||||||
|
|
||||||
internal void Remove(Result result)
|
internal void Remove(Result result)
|
||||||
{
|
{
|
||||||
|
// origin query is null when user select the context menu item directly of one item from query list
|
||||||
|
// in this case, we do not need to remove the record
|
||||||
|
if (result.OriginQuery == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
records.Remove(result.OriginQuery.RawQuery, out _);
|
records.Remove(result.OriginQuery.RawQuery, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddOrUpdate(Result result)
|
internal void AddOrUpdate(Result result)
|
||||||
{
|
{
|
||||||
|
// origin query is null when user select the context menu item directly of one item from query list
|
||||||
|
// in this case, we do not need to add or update the record
|
||||||
|
if (result.OriginQuery == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var record = new Record
|
var record = new Record
|
||||||
{
|
{
|
||||||
PluginID = result.PluginID,
|
PluginID = result.PluginID,
|
||||||
|
|
@ -38,11 +54,6 @@ namespace Flow.Launcher.Storage
|
||||||
};
|
};
|
||||||
records.AddOrUpdate(result.OriginQuery.RawQuery, record, (key, oldValue) => record);
|
records.AddOrUpdate(result.OriginQuery.RawQuery, record, (key, oldValue) => record);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Load(Dictionary<string, Record> dictionary)
|
|
||||||
{
|
|
||||||
records = new ConcurrentDictionary<string, Record>(dictionary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Record
|
public class Record
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ namespace Flow.Launcher.Storage
|
||||||
|
|
||||||
private static int GenerateQueryAndResultHashCode(Query query, Result result)
|
private static int GenerateQueryAndResultHashCode(Query query, Result result)
|
||||||
{
|
{
|
||||||
|
// query is null when user select the context menu item directly of one item from query list
|
||||||
|
// so we only need to consider the result
|
||||||
if (query == null)
|
if (query == null)
|
||||||
{
|
{
|
||||||
return GenerateResultHashCode(result);
|
return GenerateResultHashCode(result);
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,6 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
private bool _isQueryRunning;
|
private bool _isQueryRunning;
|
||||||
private Query _lastQuery;
|
private Query _lastQuery;
|
||||||
private Result lastContextMenuResult = new Result();
|
|
||||||
private List<Result> lastContextMenuResults = new List<Result>();
|
|
||||||
private string _queryTextBeforeLeaveResults;
|
private string _queryTextBeforeLeaveResults;
|
||||||
|
|
||||||
private readonly FlowLauncherJsonStorage<History> _historyItemsStorage;
|
private readonly FlowLauncherJsonStorage<History> _historyItemsStorage;
|
||||||
|
|
@ -398,11 +396,15 @@ namespace Flow.Launcher.ViewModel
|
||||||
})
|
})
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
||||||
if (SelectedIsFromQueryResults())
|
if (SelectedIsFromQueryResults())
|
||||||
{
|
{
|
||||||
_userSelectedRecord.Add(result);
|
_userSelectedRecord.Add(result);
|
||||||
_history.Add(result.OriginQuery.RawQuery);
|
// origin query is null when user select the context menu item directly of one item from query list
|
||||||
|
// so we don't want to add it to history
|
||||||
|
if (result.OriginQuery != null)
|
||||||
|
{
|
||||||
|
_history.Add(result.OriginQuery.RawQuery);
|
||||||
|
}
|
||||||
lastHistoryIndex = 1;
|
lastHistoryIndex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -986,19 +988,10 @@ namespace Flow.Launcher.ViewModel
|
||||||
if (selected != null) // SelectedItem returns null if selection is empty.
|
if (selected != null) // SelectedItem returns null if selection is empty.
|
||||||
{
|
{
|
||||||
List<Result> results;
|
List<Result> results;
|
||||||
if (selected == lastContextMenuResult)
|
|
||||||
{
|
|
||||||
results = lastContextMenuResults;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
results = PluginManager.GetContextMenusForPlugin(selected);
|
|
||||||
lastContextMenuResults = results;
|
|
||||||
lastContextMenuResult = selected;
|
|
||||||
results.Add(ContextMenuTopMost(selected));
|
|
||||||
results.Add(ContextMenuPluginInfo(selected.PluginID));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
results = PluginManager.GetContextMenusForPlugin(selected);
|
||||||
|
results.Add(ContextMenuTopMost(selected));
|
||||||
|
results.Add(ContextMenuPluginInfo(selected.PluginID));
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(query))
|
if (!string.IsNullOrEmpty(query))
|
||||||
{
|
{
|
||||||
|
|
@ -1273,6 +1266,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
_topMostRecord.Remove(result);
|
_topMostRecord.Remove(result);
|
||||||
App.API.ShowMsg(InternationalizationManager.Instance.GetTranslation("success"));
|
App.API.ShowMsg(InternationalizationManager.Instance.GetTranslation("success"));
|
||||||
|
App.API.BackToQueryResults();
|
||||||
|
App.API.ReQuery();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1289,6 +1284,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
_topMostRecord.AddOrUpdate(result);
|
_topMostRecord.AddOrUpdate(result);
|
||||||
App.API.ShowMsg(InternationalizationManager.Instance.GetTranslation("success"));
|
App.API.ShowMsg(InternationalizationManager.Instance.GetTranslation("success"));
|
||||||
|
App.API.BackToQueryResults();
|
||||||
|
App.API.ReQuery();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1378,8 +1375,6 @@ namespace Flow.Launcher.ViewModel
|
||||||
lastHistoryIndex = 1;
|
lastHistoryIndex = 1;
|
||||||
// Trick for no delay
|
// Trick for no delay
|
||||||
MainWindowOpacity = 0;
|
MainWindowOpacity = 0;
|
||||||
lastContextMenuResult = new Result();
|
|
||||||
lastContextMenuResults = new List<Result>();
|
|
||||||
|
|
||||||
if (ExternalPreviewVisible)
|
if (ExternalPreviewVisible)
|
||||||
CloseExternalPreview();
|
CloseExternalPreview();
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,7 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
var name = "Plugin: Folder";
|
var name = "Plugin: Folder";
|
||||||
var message = $"File not found: {e.Message}";
|
var message = $"File not found: {e.Message}";
|
||||||
Context.API.ShowMsgError(name, message);
|
Context.API.ShowMsgError(name, message);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Application.Current.MainWindow.Hide();
|
Context.API.HideMainWindow();
|
||||||
_ = InstallOrUpdateAsync(plugin);
|
_ = InstallOrUpdateAsync(plugin);
|
||||||
|
|
||||||
return ShouldHideWindow;
|
return ShouldHideWindow;
|
||||||
|
|
@ -572,7 +572,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Application.Current.MainWindow.Hide();
|
Context.API.HideMainWindow();
|
||||||
_ = InstallOrUpdateAsync(plugin);
|
_ = InstallOrUpdateAsync(plugin);
|
||||||
|
|
||||||
return ShouldHideWindow;
|
return ShouldHideWindow;
|
||||||
|
|
@ -626,7 +626,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
||||||
return ShouldHideWindow;
|
return ShouldHideWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
Application.Current.MainWindow.Hide();
|
Context.API.HideMainWindow();
|
||||||
_ = InstallOrUpdateAsync(x); // No need to wait
|
_ = InstallOrUpdateAsync(x); // No need to wait
|
||||||
return ShouldHideWindow;
|
return ShouldHideWindow;
|
||||||
},
|
},
|
||||||
|
|
@ -703,7 +703,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
||||||
Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"),
|
Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"),
|
||||||
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
||||||
{
|
{
|
||||||
Application.Current.MainWindow.Hide();
|
Context.API.HideMainWindow();
|
||||||
Uninstall(x.Metadata);
|
Uninstall(x.Metadata);
|
||||||
if (Settings.AutoRestartAfterChanging)
|
if (Settings.AutoRestartAfterChanging)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,8 @@ namespace Flow.Launcher.Plugin.Program
|
||||||
Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"),
|
Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"),
|
||||||
Context.API.GetTranslation(
|
Context.API.GetTranslation(
|
||||||
"flowlauncher_plugin_program_disable_dlgtitle_success_message"));
|
"flowlauncher_plugin_program_disable_dlgtitle_success_message"));
|
||||||
|
Context.API.BackToQueryResults();
|
||||||
|
Context.API.ReQuery();
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
IcoPath = "Images/disable.png",
|
IcoPath = "Images/disable.png",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using Flow.Launcher.Infrastructure;
|
using Flow.Launcher.Infrastructure;
|
||||||
using Flow.Launcher.Infrastructure.Logger;
|
using Flow.Launcher.Infrastructure.Logger;
|
||||||
|
|
@ -9,6 +10,7 @@ using Flow.Launcher.Infrastructure.UserSettings;
|
||||||
using Flow.Launcher.Plugin.SharedCommands;
|
using Flow.Launcher.Plugin.SharedCommands;
|
||||||
using Windows.Win32;
|
using Windows.Win32;
|
||||||
using Windows.Win32.Foundation;
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.Security;
|
||||||
using Windows.Win32.System.Shutdown;
|
using Windows.Win32.System.Shutdown;
|
||||||
using Application = System.Windows.Application;
|
using Application = System.Windows.Application;
|
||||||
using Control = System.Windows.Controls.Control;
|
using Control = System.Windows.Controls.Control;
|
||||||
|
|
@ -20,6 +22,10 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
private PluginInitContext context;
|
private PluginInitContext context;
|
||||||
private Dictionary<string, string> KeywordTitleMappings = new Dictionary<string, string>();
|
private Dictionary<string, string> KeywordTitleMappings = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
// SHTDN_REASON_MAJOR_OTHER indicates a generic shutdown reason that isn't categorized under hardware failure, software updates, or other predefined reasons.
|
||||||
|
// SHTDN_REASON_FLAG_PLANNED marks the shutdown as planned rather than an unexpected shutdown or failure
|
||||||
|
private const SHUTDOWN_REASON REASON = SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED;
|
||||||
|
|
||||||
public Control CreateSettingPanel()
|
public Control CreateSettingPanel()
|
||||||
{
|
{
|
||||||
var results = Commands();
|
var results = Commands();
|
||||||
|
|
@ -100,6 +106,44 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static unsafe bool EnableShutdownPrivilege()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!PInvoke.OpenProcessToken(Process.GetCurrentProcess().SafeHandle, TOKEN_ACCESS_MASK.TOKEN_ADJUST_PRIVILEGES | TOKEN_ACCESS_MASK.TOKEN_QUERY, out var tokenHandle))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PInvoke.LookupPrivilegeValue(null, PInvoke.SE_SHUTDOWN_NAME, out var luid))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var privileges = new TOKEN_PRIVILEGES
|
||||||
|
{
|
||||||
|
PrivilegeCount = 1,
|
||||||
|
Privileges = new() { e0 = new LUID_AND_ATTRIBUTES { Luid = luid, Attributes = TOKEN_PRIVILEGES_ATTRIBUTES.SE_PRIVILEGE_ENABLED } }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!PInvoke.AdjustTokenPrivileges(tokenHandle, false, &privileges, 0, null, null))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Marshal.GetLastWin32Error() != (int)WIN32_ERROR.NO_ERROR)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<Result> Commands()
|
private List<Result> Commands()
|
||||||
{
|
{
|
||||||
var results = new List<Result>();
|
var results = new List<Result>();
|
||||||
|
|
@ -120,10 +164,12 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"),
|
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"),
|
||||||
context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"),
|
context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"),
|
||||||
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||||
|
|
||||||
if (result == MessageBoxResult.Yes)
|
if (result == MessageBoxResult.Yes)
|
||||||
{
|
if (EnableShutdownPrivilege())
|
||||||
Process.Start("shutdown", "/s /t 0");
|
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, REASON);
|
||||||
}
|
else
|
||||||
|
Process.Start("shutdown", "/s /t 0");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -140,10 +186,12 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"),
|
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"),
|
||||||
context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"),
|
context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"),
|
||||||
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||||
|
|
||||||
if (result == MessageBoxResult.Yes)
|
if (result == MessageBoxResult.Yes)
|
||||||
{
|
if (EnableShutdownPrivilege())
|
||||||
Process.Start("shutdown", "/r /t 0");
|
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, REASON);
|
||||||
}
|
else
|
||||||
|
Process.Start("shutdown", "/r /t 0");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +210,10 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||||
|
|
||||||
if (result == MessageBoxResult.Yes)
|
if (result == MessageBoxResult.Yes)
|
||||||
Process.Start("shutdown", "/r /o /t 0");
|
if (EnableShutdownPrivilege())
|
||||||
|
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, REASON);
|
||||||
|
else
|
||||||
|
Process.Start("shutdown", "/r /o /t 0");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +232,7 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||||
|
|
||||||
if (result == MessageBoxResult.Yes)
|
if (result == MessageBoxResult.Yes)
|
||||||
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, 0);
|
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, REASON);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +255,11 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
SubTitle = context.API.GetTranslation("flowlauncher_plugin_sys_sleep"),
|
SubTitle = context.API.GetTranslation("flowlauncher_plugin_sys_sleep"),
|
||||||
Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xec46"),
|
Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xec46"),
|
||||||
IcoPath = "Images\\sleep.png",
|
IcoPath = "Images\\sleep.png",
|
||||||
Action = c => PInvoke.SetSuspendState(false, false, false)
|
Action = c =>
|
||||||
|
{
|
||||||
|
PInvoke.SetSuspendState(false, false, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
new Result
|
new Result
|
||||||
{
|
{
|
||||||
|
|
@ -214,12 +269,7 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
IcoPath = "Images\\hibernate.png",
|
IcoPath = "Images\\hibernate.png",
|
||||||
Action= c =>
|
Action= c =>
|
||||||
{
|
{
|
||||||
var info = ShellCommand.SetProcessStartInfo("shutdown", arguments:"/h");
|
PInvoke.SetSuspendState(true, false, false);
|
||||||
info.WindowStyle = ProcessWindowStyle.Hidden;
|
|
||||||
info.UseShellExecute = true;
|
|
||||||
|
|
||||||
ShellCommand.Execute(info);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -231,10 +281,7 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xe773"),
|
Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xe773"),
|
||||||
Action = c =>
|
Action = c =>
|
||||||
{
|
{
|
||||||
{
|
Process.Start("control.exe", "srchadmin.dll");
|
||||||
System.Diagnostics.Process.Start("control.exe", "srchadmin.dll");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -272,10 +319,7 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
CopyText = recycleBinFolder,
|
CopyText = recycleBinFolder,
|
||||||
Action = c =>
|
Action = c =>
|
||||||
{
|
{
|
||||||
{
|
Process.Start("explorer", recycleBinFolder);
|
||||||
System.Diagnostics.Process.Start("explorer", recycleBinFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -333,7 +377,7 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
Action = c =>
|
Action = c =>
|
||||||
{
|
{
|
||||||
// Hide the window first then show msg after done because sometimes the reload could take a while, so not to make user think it's frozen.
|
// Hide the window first then show msg after done because sometimes the reload could take a while, so not to make user think it's frozen.
|
||||||
Application.Current.MainWindow.Hide();
|
context.API.HideMainWindow();
|
||||||
|
|
||||||
_ = context.API.ReloadAllPluginData().ContinueWith(_ =>
|
_ = context.API.ReloadAllPluginData().ContinueWith(_ =>
|
||||||
context.API.ShowMsg(
|
context.API.ShowMsg(
|
||||||
|
|
@ -352,7 +396,7 @@ namespace Flow.Launcher.Plugin.Sys
|
||||||
IcoPath = "Images\\checkupdate.png",
|
IcoPath = "Images\\checkupdate.png",
|
||||||
Action = c =>
|
Action = c =>
|
||||||
{
|
{
|
||||||
Application.Current.MainWindow.Hide();
|
context.API.HideMainWindow();
|
||||||
context.API.CheckForNewUpdate();
|
context.API.CheckForNewUpdate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,10 @@ LockWorkStation
|
||||||
SHEmptyRecycleBin
|
SHEmptyRecycleBin
|
||||||
S_OK
|
S_OK
|
||||||
E_UNEXPECTED
|
E_UNEXPECTED
|
||||||
SetSuspendState
|
SetSuspendState
|
||||||
|
OpenProcessToken
|
||||||
|
WIN32_ERROR
|
||||||
|
LookupPrivilegeValue
|
||||||
|
AdjustTokenPrivileges
|
||||||
|
TOKEN_PRIVILEGES
|
||||||
|
SE_SHUTDOWN_NAME
|
||||||
Loading…
Reference in a new issue