From fe0153be088d8f82877d7ea06b46364a556c68f5 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Wed, 15 Dec 2021 05:21:40 -0500
Subject: [PATCH 01/11] Initial commit
---
Flow.Launcher/Flow.Launcher.csproj | 33 ++++++++++++
Flow.Launcher/ViewModel/MainViewModel.cs | 65 +++++++++++++++++++++++-
2 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index f431504c2e4..117dececf5a 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -77,6 +77,24 @@
Designer
PreserveNewest
+
+ 1
+ 1
+ eab22ac0-30c1-11cf-a7eb-0000c05bae0b
+ 0
+ tlbimp
+ false
+ true
+
+
+ 0
+ 1
+ 50a7e9b0-70ef-11d1-b75a-00a0c90564fe
+ 0
+ tlbimp
+ false
+ true
+
PreserveNewest
@@ -110,6 +128,21 @@
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index abf3a1d14ea..cbe35e0f587 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -20,7 +20,9 @@
using Microsoft.VisualStudio.Threading;
using System.Threading.Channels;
using ISavable = Flow.Launcher.Plugin.ISavable;
-
+using System.Runtime.InteropServices;
+using System.Text;
+using SHDocVw;
namespace Flow.Launcher.ViewModel
{
@@ -720,6 +722,62 @@ private void SetOpenResultModifiers()
OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers;
}
+ private static string GetActiveExplorerPath()
+ {
+ // get the active window
+ IntPtr handle = GetForegroundWindow();
+
+ // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
+ ShellWindows shellWindows = new SHDocVw.ShellWindows();
+
+ // loop through all windows
+ foreach (InternetExplorer window in shellWindows)
+ {
+ // match active window
+ if (window.HWND == (int)handle)
+ {
+ // Required ref: Shell32 - C:\Windows\system32\Shell32.dll
+ var shellWindow = window.Document as Shell32.IShellFolderViewDual2;
+
+ // will be null if you are in Internet Explorer for example
+ if (shellWindow != null)
+ {
+ // Item without an index returns the current object
+ var currentFolder = shellWindow.Folder.Items().Item();
+
+ // special folder - use window title
+ // for some reason on "Desktop" gives null
+ if (currentFolder == null || currentFolder.Path.StartsWith("::"))
+ {
+ // Get window title instead
+ const int nChars = 256;
+ StringBuilder Buff = new StringBuilder(nChars);
+ if (GetWindowText(handle, Buff, nChars) > 0)
+ {
+ return Buff.ToString();
+ }
+ }
+ else
+ {
+ return currentFolder.Path;
+ }
+ }
+
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ // COM Imports
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+
public void ToggleFlowLauncher()
{
if (!MainWindowVisibilityStatus)
@@ -734,6 +792,9 @@ public void ToggleFlowLauncher()
public void Show()
{
+ string _explorerPath = GetActiveExplorerPath();
+
+ ChangeQueryText($"{_explorerPath}\\>");
if (_settings.UseSound)
{
MediaPlayer media = new MediaPlayer();
@@ -749,6 +810,8 @@ public void Show()
((MainWindow)Application.Current.MainWindow).WindowAnimator();
MainWindowOpacity = 1;
+
+
}
public async void Hide()
From 79a6fda289dfa641e011588f500d98b22425b3d2 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Wed, 15 Dec 2021 05:24:31 -0500
Subject: [PATCH 02/11] Only insert when explorer is active
---
Flow.Launcher/ViewModel/MainViewModel.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index cbe35e0f587..7a48d159fca 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -793,8 +793,11 @@ public void ToggleFlowLauncher()
public void Show()
{
string _explorerPath = GetActiveExplorerPath();
-
- ChangeQueryText($"{_explorerPath}\\>");
+ if (_explorerPath != null)
+ {
+ ChangeQueryText($"{_explorerPath}\\>");
+ }
+
if (_settings.UseSound)
{
MediaPlayer media = new MediaPlayer();
From 1fdaec2648f14994b9b15fc86c732629796f6f13 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Wed, 15 Dec 2021 06:15:05 -0500
Subject: [PATCH 03/11] ChangeQuery after window is visible
---
Flow.Launcher/ViewModel/MainViewModel.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 7a48d159fca..b525ac34222 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -731,7 +731,7 @@ private static string GetActiveExplorerPath()
ShellWindows shellWindows = new SHDocVw.ShellWindows();
// loop through all windows
- foreach (InternetExplorer window in shellWindows)
+ foreach (SHDocVw.InternetExplorer window in shellWindows)
{
// match active window
if (window.HWND == (int)handle)
@@ -793,10 +793,7 @@ public void ToggleFlowLauncher()
public void Show()
{
string _explorerPath = GetActiveExplorerPath();
- if (_explorerPath != null)
- {
- ChangeQueryText($"{_explorerPath}\\>");
- }
+
if (_settings.UseSound)
{
@@ -813,7 +810,10 @@ public void Show()
((MainWindow)Application.Current.MainWindow).WindowAnimator();
MainWindowOpacity = 1;
-
+ if (_explorerPath != null && _explorerPath != "File Explorer")
+ {
+ ChangeQueryText($"{_explorerPath}\\>");
+ }
}
From 1109f9887e78ddcfda62f0e775893f6161344ec2 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Thu, 16 Dec 2021 02:03:22 -0500
Subject: [PATCH 04/11] Remove unnecessary changes
---
Flow.Launcher/Flow.Launcher.csproj | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 117dececf5a..9d40427005a 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -128,21 +128,6 @@
-
-
- True
- True
- Settings.settings
-
-
-
-
-
- SettingsSingleFileGenerator
- Settings.Designer.cs
-
-
-
From aa5ca76b180b94680ee4f1f677581eb35bbf7424 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Mon, 20 Dec 2021 03:34:41 -0500
Subject: [PATCH 05/11] Check window is InternetExplorer type
---
Flow.Launcher/ViewModel/MainViewModel.cs | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index b525ac34222..412af09fdfd 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -731,13 +731,19 @@ private static string GetActiveExplorerPath()
ShellWindows shellWindows = new SHDocVw.ShellWindows();
// loop through all windows
- foreach (SHDocVw.InternetExplorer window in shellWindows)
+ foreach (var window in shellWindows)
{
+ if (window is not SHDocVw.InternetExplorer)
+ {
+ continue;
+ }
+
+ var explorerWindow = (SHDocVw.InternetExplorer)window;
// match active window
- if (window.HWND == (int)handle)
+ if (explorerWindow.HWND == (int)handle)
{
// Required ref: Shell32 - C:\Windows\system32\Shell32.dll
- var shellWindow = window.Document as Shell32.IShellFolderViewDual2;
+ var shellWindow = explorerWindow.Document as Shell32.IShellFolderViewDual2;
// will be null if you are in Internet Explorer for example
if (shellWindow != null)
From c039b17d93c66717dbdaf4a14843ce19a224f5c8 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Sat, 16 Jul 2022 11:16:00 +0200
Subject: [PATCH 06/11] Refactor file explorer path getting
---
Flow.Launcher/Helper/FileExplorerHelper.cs | 70 ++++++++++++++++++++++
Flow.Launcher/ViewModel/MainViewModel.cs | 66 +-------------------
2 files changed, 72 insertions(+), 64 deletions(-)
create mode 100644 Flow.Launcher/Helper/FileExplorerHelper.cs
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
new file mode 100644
index 00000000000..16152e8306d
--- /dev/null
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.IO;
+
+namespace Flow.Launcher.Helper
+{
+ public 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;
+ if (!string.IsNullOrEmpty(locationUrl))
+ {
+ return new Uri(locationUrl).LocalPath;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the file explorer that is currently in the foreground
+ ///
+ private static SHDocVw.InternetExplorer GetActiveExplorer()
+ {
+ // get the active window
+ IntPtr handle = GetForegroundWindow();
+
+ // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
+ var shellWindows = new SHDocVw.ShellWindows();
+
+ // loop through all windows
+ foreach (var window in shellWindows)
+ {
+ if (window is SHDocVw.InternetExplorer explorerWindow && new IntPtr(explorerWindow.HWND) == handle)
+ {
+ // we have found the desired window, now let's make sure that it is indeed a file explorer
+ // we don't want the Internet Explorer or the classic control panel
+ if (explorerWindow.Document is not Shell32.IShellFolderViewDual2)
+ {
+ return null;
+ }
+ if (Path.GetFileName(explorerWindow.FullName) != "explorer.exe")
+ {
+ return null;
+ }
+
+ return explorerWindow;
+ }
+ }
+
+ return null;
+ }
+
+ // COM Imports
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+ }
+}
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 412af09fdfd..ff0c8833931 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -722,68 +722,6 @@ private void SetOpenResultModifiers()
OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers;
}
- private static string GetActiveExplorerPath()
- {
- // get the active window
- IntPtr handle = GetForegroundWindow();
-
- // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
- ShellWindows shellWindows = new SHDocVw.ShellWindows();
-
- // loop through all windows
- foreach (var window in shellWindows)
- {
- if (window is not SHDocVw.InternetExplorer)
- {
- continue;
- }
-
- var explorerWindow = (SHDocVw.InternetExplorer)window;
- // match active window
- if (explorerWindow.HWND == (int)handle)
- {
- // Required ref: Shell32 - C:\Windows\system32\Shell32.dll
- var shellWindow = explorerWindow.Document as Shell32.IShellFolderViewDual2;
-
- // will be null if you are in Internet Explorer for example
- if (shellWindow != null)
- {
- // Item without an index returns the current object
- var currentFolder = shellWindow.Folder.Items().Item();
-
- // special folder - use window title
- // for some reason on "Desktop" gives null
- if (currentFolder == null || currentFolder.Path.StartsWith("::"))
- {
- // Get window title instead
- const int nChars = 256;
- StringBuilder Buff = new StringBuilder(nChars);
- if (GetWindowText(handle, Buff, nChars) > 0)
- {
- return Buff.ToString();
- }
- }
- else
- {
- return currentFolder.Path;
- }
- }
-
- break;
- }
- }
-
- return null;
- }
-
- // COM Imports
-
- [DllImport("user32.dll")]
- private static extern IntPtr GetForegroundWindow();
-
- [DllImport("user32.dll")]
- static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
-
public void ToggleFlowLauncher()
{
if (!MainWindowVisibilityStatus)
@@ -798,7 +736,7 @@ public void ToggleFlowLauncher()
public void Show()
{
- string _explorerPath = GetActiveExplorerPath();
+ string _explorerPath = FileExplorerHelper.GetActiveExplorerPath();
if (_settings.UseSound)
@@ -816,7 +754,7 @@ public void Show()
((MainWindow)Application.Current.MainWindow).WindowAnimator();
MainWindowOpacity = 1;
- if (_explorerPath != null && _explorerPath != "File Explorer")
+ if (_explorerPath != null)
{
ChangeQueryText($"{_explorerPath}\\>");
}
From 81bacdb9a72e5482788d2f90933e46659fd4ce42 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Sat, 16 Jul 2022 11:20:36 +0200
Subject: [PATCH 07/11] Remove unused function
---
Flow.Launcher/Helper/FileExplorerHelper.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
index 16152e8306d..3b24b741407 100644
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -63,8 +63,5 @@ private static SHDocVw.InternetExplorer GetActiveExplorer()
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
-
- [DllImport("user32.dll")]
- static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
}
}
From ab306d90cc1ef0187b3227c9174d303e846c38fa Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Sat, 16 Jul 2022 11:22:31 +0200
Subject: [PATCH 08/11] Remove unused imports
---
Flow.Launcher/ViewModel/MainViewModel.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index ff0c8833931..d785249a6f7 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -20,9 +20,6 @@
using Microsoft.VisualStudio.Threading;
using System.Threading.Channels;
using ISavable = Flow.Launcher.Plugin.ISavable;
-using System.Runtime.InteropServices;
-using System.Text;
-using SHDocVw;
namespace Flow.Launcher.ViewModel
{
From 1606908d28484c1cc63410be0bbd2ef499730e25 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Mon, 8 Aug 2022 19:07:18 +0200
Subject: [PATCH 09/11] Move to dynamic
---
Flow.Launcher/Flow.Launcher.csproj | 18 ------------
Flow.Launcher/Helper/FileExplorerHelper.cs | 34 +++++++++-------------
2 files changed, 14 insertions(+), 38 deletions(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 9d40427005a..f431504c2e4 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -77,24 +77,6 @@
Designer
PreserveNewest
-
- 1
- 1
- eab22ac0-30c1-11cf-a7eb-0000c05bae0b
- 0
- tlbimp
- false
- true
-
-
- 0
- 1
- 50a7e9b0-70ef-11d1-b75a-00a0c90564fe
- 0
- tlbimp
- false
- true
-
PreserveNewest
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
index 3b24b741407..22c3de63ff9 100644
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -14,7 +14,7 @@ public class FileExplorerHelper
public static string GetActiveExplorerPath()
{
var explorerWindow = GetActiveExplorer();
- string locationUrl = explorerWindow.LocationURL;
+ string locationUrl = explorerWindow?.LocationURL;
if (!string.IsNullOrEmpty(locationUrl))
{
return new Uri(locationUrl).LocalPath;
@@ -28,31 +28,25 @@ public static string GetActiveExplorerPath()
///
/// Gets the file explorer that is currently in the foreground
///
- private static SHDocVw.InternetExplorer GetActiveExplorer()
+ private static dynamic GetActiveExplorer()
{
// get the active window
IntPtr handle = GetForegroundWindow();
- // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
- var shellWindows = new SHDocVw.ShellWindows();
-
- // loop through all windows
- foreach (var window in shellWindows)
+ Type type = Type.GetTypeFromProgID("Shell.Application");
+ if (type == null) return null;
+ dynamic shell = Activator.CreateInstance(type);
+ var openWindows = shell.Windows();
+ for (int i = 0; i < openWindows.Count; i++)
{
- if (window is SHDocVw.InternetExplorer explorerWindow && new IntPtr(explorerWindow.HWND) == handle)
- {
- // we have found the desired window, now let's make sure that it is indeed a file explorer
- // we don't want the Internet Explorer or the classic control panel
- if (explorerWindow.Document is not Shell32.IShellFolderViewDual2)
- {
- return null;
- }
- if (Path.GetFileName(explorerWindow.FullName) != "explorer.exe")
- {
- return null;
- }
+ var window = openWindows.Item(i);
+ if (window == null) continue;
- return explorerWindow;
+ // 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
+ if (Path.GetFileName((string)window.FullName) == "explorer.exe" && new IntPtr(window.HWND) == handle)
+ {
+ return window;
}
}
From 0a062c310a1386d9e7c9bbe4ad59e3927981ea96 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Mon, 8 Aug 2022 19:19:05 +0200
Subject: [PATCH 10/11] Fix querying of explorer window
---
Flow.Launcher/Helper/FileExplorerHelper.cs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
index 22c3de63ff9..c6d50f514d0 100644
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -44,7 +44,8 @@ private static dynamic GetActiveExplorer()
// 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
- if (Path.GetFileName((string)window.FullName) == "explorer.exe" && new IntPtr(window.HWND) == handle)
+ // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
+ if (Path.GetFileName((string)window.FullName).ToLower() == "explorer.exe" && new IntPtr(window.HWND) == handle)
{
return window;
}
@@ -53,8 +54,6 @@ private static dynamic GetActiveExplorer()
return null;
}
- // COM Imports
-
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
}
From 55dee4f471641651583208f4ffbdc4b07299a4ab Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Tue, 3 Jan 2023 23:05:35 -0500
Subject: [PATCH 11/11] Use the explorer window with the lowest z-index to
allow active explorer path be a built-in shortcut
---
.../FileExplorerHelper.cs | 89 +++++++++++++++++++
.../UserSettings/Settings.cs | 6 +-
Flow.Launcher/Helper/FileExplorerHelper.cs | 60 -------------
Flow.Launcher/Languages/en.xaml | 1 +
4 files changed, 94 insertions(+), 62 deletions(-)
create mode 100644 Flow.Launcher.Infrastructure/FileExplorerHelper.cs
delete mode 100644 Flow.Launcher/Helper/FileExplorerHelper.cs
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/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
deleted file mode 100644
index c6d50f514d0..00000000000
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.IO;
-
-namespace Flow.Launcher.Helper
-{
- public 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;
- if (!string.IsNullOrEmpty(locationUrl))
- {
- return new Uri(locationUrl).LocalPath;
- }
- else
- {
- return null;
- }
- }
-
- ///
- /// Gets the file explorer that is currently in the foreground
- ///
- private static dynamic GetActiveExplorer()
- {
- // get the active window
- IntPtr handle = GetForegroundWindow();
-
- Type type = Type.GetTypeFromProgID("Shell.Application");
- if (type == null) return null;
- dynamic shell = Activator.CreateInstance(type);
- 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" && new IntPtr(window.HWND) == handle)
- {
- return window;
- }
- }
-
- return null;
- }
-
- [DllImport("user32.dll")]
- private static extern IntPtr GetForegroundWindow();
- }
-}
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