diff --git a/Flow.Launcher.Infrastructure/FileExplorerHelper.cs b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs
new file mode 100644
index 00000000000..a3b1bd6b7e6
--- /dev/null
+++ b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace Flow.Launcher.Infrastructure
+{
+ public static class FileExplorerHelper
+ {
+ ///
+ /// Gets the path of the file explorer that is currently in the foreground
+ ///
+ public static string GetActiveExplorerPath()
+ {
+ var explorerWindow = GetActiveExplorer();
+ string locationUrl = explorerWindow?.LocationURL;
+ return !string.IsNullOrEmpty(locationUrl) ? new Uri(locationUrl).LocalPath : null;
+ }
+
+ ///
+ /// Gets the file explorer that is currently in the foreground
+ ///
+ private static dynamic GetActiveExplorer()
+ {
+ Type type = Type.GetTypeFromProgID("Shell.Application");
+ if (type == null) return null;
+ dynamic shell = Activator.CreateInstance(type);
+ if (shell == null)
+ {
+ return null;
+ }
+
+ var explorerWindows = new List();
+ var openWindows = shell.Windows();
+ for (int i = 0; i < openWindows.Count; i++)
+ {
+ var window = openWindows.Item(i);
+ if (window == null) continue;
+
+ // find the desired window and make sure that it is indeed a file explorer
+ // we don't want the Internet Explorer or the classic control panel
+ // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
+ if (Path.GetFileName((string)window.FullName)?.ToLower() == "explorer.exe")
+ {
+ explorerWindows.Add(window);
+ }
+ }
+
+ if (explorerWindows.Count == 0) return null;
+
+ var zOrders = GetZOrder(explorerWindows);
+
+ return explorerWindows.Zip(zOrders).MinBy(x => x.Second).First;
+ }
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
+
+ private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
+
+ ///
+ /// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1.
+ ///
+ private static IEnumerable GetZOrder(List hWnds)
+ {
+ var z = new int[hWnds.Count];
+ for (var i = 0; i < hWnds.Count; i++) z[i] = -1;
+
+ var index = 0;
+ var numRemaining = hWnds.Count;
+ EnumWindows((wnd, _) =>
+ {
+ var searchIndex = hWnds.FindIndex(x => x.HWND == wnd.ToInt32());
+ if (searchIndex != -1)
+ {
+ z[searchIndex] = index;
+ numRemaining--;
+ if (numRemaining == 0) return false;
+ }
+ index++;
+ return true;
+ }, IntPtr.Zero);
+
+ return z;
+ }
+ }
+}
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index a184520d081..753334e2392 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -192,8 +192,10 @@ public string QuerySearchPrecisionString
public ObservableCollection CustomShortcuts { get; set; } = new ObservableCollection();
[JsonIgnore]
- public ObservableCollection BuiltinShortcuts { get; set; } = new ObservableCollection() {
- new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText)
+ public ObservableCollection BuiltinShortcuts { get; set; } = new()
+ {
+ new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText),
+ new BuiltinShortcutModel("{active_explorer_path}", "shortcut_active_explorer_path", FileExplorerHelper.GetActiveExplorerPath)
};
public bool DontPromptUpdateMsg { get; set; }
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index b192617cb79..49c603dc851 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -176,6 +176,7 @@
Are you sure you want to delete {0} plugin hotkey?
Are you sure you want to delete shortcut: {0} with expansion {1}?
Get text from clipboard.
+ Get path from active explorer.
Query window shadow effect
Shadow effect has a substantial usage of GPU. Not recommended if your computer performance is limited.
Window Width Size