Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Flow.Launcher/Flow.Launcher.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,24 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<COMReference Include="SHDocVw">
<VersionMinor>1</VersionMinor>
<VersionMajor>1</VersionMajor>
<Guid>eab22ac0-30c1-11cf-a7eb-0000c05bae0b</Guid>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>false</Isolated>
<EmbedInteropTypes>true</EmbedInteropTypes>
</COMReference>
<COMReference Include="Shell32">
<VersionMinor>0</VersionMinor>
<VersionMajor>1</VersionMajor>
<Guid>50a7e9b0-70ef-11d1-b75a-00a0c90564fe</Guid>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>false</Isolated>
<EmbedInteropTypes>true</EmbedInteropTypes>
</COMReference>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about the COMREference? Is it better to use dynamic typing as what you did in the runner plugin? Somehow the dotnet cli doesn't support this feature, and the previous workaround is to copy the reference dll and directly reference that dll.

Copy link
Contributor Author

@stefnotch stefnotch Jul 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly have no clue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say since you have shared a way to prevent usage of comreference, let's use that. Previously I workaround this by copying out the dll and reference that directly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I personally think it may be better to have strongly type?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@stefnotch stefnotch Jul 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah for sure, but I think that's pretty messy. We do have some example about that.

<Content Include="Resources\Segoe Fluent Icons.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Expand Down
70 changes: 70 additions & 0 deletions Flow.Launcher/Helper/FileExplorerHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace Flow.Launcher.Helper
{
public class FileExplorerHelper
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other function that might be interesting would be getting all open file explorer paths (sorted by depth/zindex). (See also jjw24/Wox.Plugin.Runner#27 )
Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, maybe we should return the paths sorted by depth/zindex (since we will need to get all of them). The overhead can be ignored.

{

/// <summary>
/// Gets the path of the file explorer that is currently in the foreground
/// </summary>
public static string GetActiveExplorerPath()
{
var explorerWindow = GetActiveExplorer();
string locationUrl = explorerWindow.LocationURL;
if (!string.IsNullOrEmpty(locationUrl))
{
return new Uri(locationUrl).LocalPath;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ended up being the most reliable way of getting the explorer path. I think edge cases are folders like the desktop, recycle bin, documents folder, etc.

}
else
{
return null;
}
}

/// <summary>
/// Gets the file explorer that is currently in the foreground
/// </summary>
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)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check could be removed, since the check below catches everything.

(The classical control panel is a pretty nasty edge case, try it out)

{
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);
}
}
12 changes: 11 additions & 1 deletion Flow.Launcher/ViewModel/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -734,6 +736,9 @@ public void ToggleFlowLauncher()

public void Show()
{
string _explorerPath = FileExplorerHelper.GetActiveExplorerPath();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be a useful function to expose to all plugins.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this is a utility function? Maybe we can put the helper in Flow.Launcher.Plugin?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@taooceros Yes, that sounds useful



if (_settings.UseSound)
{
MediaPlayer media = new MediaPlayer();
Expand All @@ -749,6 +754,11 @@ public void Show()
((MainWindow)Application.Current.MainWindow).WindowAnimator();

MainWindowOpacity = 1;
if (_explorerPath != null)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check has been simplified, so that's nice

{
ChangeQueryText($"{_explorerPath}\\>");
}

}

public async void Hide()
Expand Down