Skip to content

Commit 1418599

Browse files
committed
Support file path open
1 parent e111d22 commit 1418599

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-12
lines changed

Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ private static void NavigateDialogPath()
204204

205205
public static bool JumpToPath(string path)
206206
{
207-
if (!CheckPath(path)) return false;
207+
if (!CheckPath(path, out var isFile)) return false;
208208

209209
var t = new Thread(() =>
210210
{
@@ -217,21 +217,31 @@ public static bool JumpToPath(string path)
217217
};
218218

219219
// Assume that the dialog is in the foreground now
220-
Win32Helper.DirJump(path, Win32Helper.GetForegroundWindow());
220+
if (isFile)
221+
{
222+
Win32Helper.FileJump(path, Win32Helper.GetForegroundWindow());
223+
}
224+
else
225+
{
226+
Win32Helper.DirJump(path, Win32Helper.GetForegroundWindow());
227+
}
221228
});
222229
t.Start();
223230
return true;
224231

225-
static bool CheckPath(string path)
232+
static bool CheckPath(string path, out bool file)
226233
{
227-
// Is non-null
234+
file = false;
235+
// Is non-null?
228236
if (string.IsNullOrEmpty(path)) return false;
229237
// Is absolute?
230238
if (!Path.IsPathRooted(path)) return false;
231239
// Is folder?
232-
if (!Directory.Exists(path)) return false;
240+
var isFolder = Directory.Exists(path);
233241
// Is file?
234-
return true;
242+
var isFile = File.Exists(path);
243+
file = isFile;
244+
return isFolder || isFile;
235245
}
236246
}
237247

Flow.Launcher.Infrastructure/Win32Helper.cs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.ComponentModel;
33
using System.Diagnostics;
44
using System.Globalization;
5+
using System.IO;
56
using System.Runtime.InteropServices;
67
using System.Threading;
78
using System.Windows;
@@ -620,7 +621,17 @@ public static void OpenImeSettings()
620621

621622
private static readonly InputSimulator _inputSimulator = new();
622623

623-
public static bool DirJump(string path, nint dialog, bool altD = true)
624+
public static bool FileJump(string filePath, nint dialog, bool altD = true)
625+
{
626+
return DirFileJump(Path.GetDirectoryName(filePath), filePath, dialog, altD);
627+
}
628+
629+
public static bool DirJump(string dirPath, nint dialog, bool altD = true)
630+
{
631+
return DirFileJump(dirPath, null, dialog, altD);
632+
}
633+
634+
private static bool DirFileJump(string dirPath, string filePath, nint dialog, bool altD = true, bool editFileName = false)
624635
{
625636
// Get the handle of the dialog window
626637
var dialogHandle = new HWND(dialog);
@@ -635,6 +646,12 @@ public static bool DirJump(string path, nint dialog, bool altD = true)
635646
_inputSimulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.LCONTROL, VirtualKeyCode.VK_L);
636647
}
637648

649+
// Directly edit file name
650+
if (editFileName)
651+
{
652+
return DirFileJumpForFileName(filePath, dialogHandle);
653+
}
654+
638655
// Get the handle of the path input box and then set the text.
639656
// The window with class name "ComboBoxEx32" is not visible when the path input box is not with the keyboard focus.
640657
var controlHandle = PInvoke.FindWindowEx(new(dialogHandle), HWND.Null, "WorkerW", null);
@@ -644,7 +661,9 @@ public static bool DirJump(string path, nint dialog, bool altD = true)
644661
controlHandle = PInvoke.FindWindowEx(controlHandle, HWND.Null, "ComboBoxEx32", null);
645662
if (controlHandle == HWND.Null)
646663
{
647-
return DirJumpOnLegacyDialog(path, dialogHandle);
664+
// https://github.com/idkidknow/Flow.Launcher.Plugin.DirQuickJump/issues/1
665+
// The dialog is a legacy one, so we edit file name text box directly.
666+
return DirFileJumpForFileName(string.IsNullOrEmpty(filePath) ? dirPath : filePath, dialogHandle);
648667
}
649668

650669
var timeOut = !SpinWait.SpinUntil(() =>
@@ -664,15 +683,23 @@ public static bool DirJump(string path, nint dialog, bool altD = true)
664683
return false;
665684
}
666685

667-
SetWindowText(editHandle, path);
686+
SetWindowText(editHandle, dirPath);
668687
_inputSimulator.Keyboard.KeyPress(VirtualKeyCode.RETURN);
669688

689+
if (!string.IsNullOrEmpty(filePath))
690+
{
691+
// After navigating to the path, we then set the file name.
692+
return DirFileJump(null, Path.GetFileName(filePath), dialog, altD, true);
693+
}
694+
670695
return true;
671696
}
672697

673-
private static bool DirJumpOnLegacyDialog(string path, HWND dialogHandle)
698+
/// <summary>
699+
/// Edit file name text box in the file open dialog.
700+
/// </summary>
701+
private static bool DirFileJumpForFileName(string fileName, HWND dialogHandle)
674702
{
675-
// https://github.com/idkidknow/Flow.Launcher.Plugin.DirQuickJump/issues/1
676703
var controlHandle = PInvoke.FindWindowEx(dialogHandle, HWND.Null, "ComboBoxEx32", null);
677704
controlHandle = PInvoke.FindWindowEx(controlHandle, HWND.Null, "ComboBox", null);
678705
controlHandle = PInvoke.FindWindowEx(controlHandle, HWND.Null, "Edit", null);
@@ -681,7 +708,8 @@ private static bool DirJumpOnLegacyDialog(string path, HWND dialogHandle)
681708
return false;
682709
}
683710

684-
SetWindowText(controlHandle, path);
711+
SetWindowText(controlHandle, fileName);
712+
685713
// Alt-O (equivalent to press the Open button) twice. In normal cases it suffices to press once,
686714
// but when the focus is on an irrelevant folder, that press once will just open the irrelevant one.
687715
_inputSimulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.LMENU, VirtualKeyCode.VK_O);

0 commit comments

Comments
 (0)