55using Windows . Win32 ;
66using Windows . Win32 . Foundation ;
77using Windows . Win32 . UI . WindowsAndMessaging ;
8+ using WindowsInput ;
9+ using WindowsInput . Native ;
810
911namespace Flow . Launcher . Infrastructure . QuickSwitch . Models
1012{
@@ -80,7 +82,10 @@ internal class WindowsDialogTab : IQuickSwitchDialogWindowTab
8082
8183 private static readonly string ClassName = nameof ( WindowsDialogTab ) ;
8284
85+ private static readonly InputSimulator _inputSimulator = new ( ) ;
86+
8387 private bool _legacy { get ; set ; } = false ;
88+ private DialogType _type { get ; set ; } = DialogType . None ;
8489
8590 private HWND _pathControl { get ; set ; } = HWND . Null ;
8691 private HWND _pathEditor { get ; set ; } = HWND . Null ;
@@ -90,31 +95,36 @@ internal class WindowsDialogTab : IQuickSwitchDialogWindowTab
9095 public WindowsDialogTab ( HWND handle )
9196 {
9297 Handle = handle ;
93- GetPathControlEditor ( ) ;
98+ GetPathControlEditor ( true ) ;
9499 GetFileEditor ( ) ;
95100 GetOpenButton ( ) ;
96101 }
97102
98- private bool GetPathControlEditor ( )
103+ private bool GetPathControlEditor ( bool focus )
99104 {
105+ if ( focus )
106+ {
107+ // Alt-D or Ctrl-L to focus on the path input box
108+ _inputSimulator . Keyboard . ModifiedKeyStroke ( VirtualKeyCode . LMENU , VirtualKeyCode . VK_D ) ;
109+ // _inputSimulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.LCONTROL, VirtualKeyCode.VK_L);
110+ }
111+
100112 // Get the handle of the path editor
101- // The window with class name "ComboBoxEx32" is not visible when the path editor is not with the keyboard focus
113+ // "ComboBoxEx32" is not visible when the path editor is not with the keyboard focus
102114 _pathControl = PInvoke . GetDlgItem ( Handle , 0x0000 ) ; // WorkerW
103115 _pathControl = PInvoke . GetDlgItem ( _pathControl , 0xA005 ) ; // ReBarWindow32
104116 _pathControl = PInvoke . GetDlgItem ( _pathControl , 0xA205 ) ; // Address Band Root
105117 _pathControl = PInvoke . GetDlgItem ( _pathControl , 0x0000 ) ; // msctls_progress32
106118 _pathControl = PInvoke . GetDlgItem ( _pathControl , 0xA205 ) ; // ComboBoxEx32
107119 if ( _pathControl == HWND . Null )
108120 {
109- // https://github.com/idkidknow/Flow.Launcher.Plugin.DirQuickJump/issues/1
110- // The dialog is a legacy one, so we edit file name editor directly.
111- _legacy = true ;
112121 _pathEditor = HWND . Null ;
113- Log . Info ( ClassName , "Failed to find path control handle - Legacy dialog" ) ;
122+ _legacy = true ;
123+ Log . Info ( ClassName , "Legacy dialog" ) ;
124+ return false ;
114125 }
115126 else
116127 {
117- _legacy = false ;
118128 _pathEditor = PInvoke . GetDlgItem ( _pathControl , 0xA205 ) ; // ComboBox
119129 _pathEditor = PInvoke . GetDlgItem ( _pathEditor , 0xA205 ) ; // Edit
120130 if ( _pathEditor == HWND . Null )
@@ -135,7 +145,7 @@ private bool GetFileEditor()
135145 _fileEditor = PInvoke . GetDlgItem ( _fileEditor , 0x047C ) ; // Edit
136146 if ( _fileEditor == HWND . Null )
137147 {
138- // Get the handle of the file name editor of Save/ SaveAs file dialog
148+ // Get the handle of the file name editor of Save / SaveAs file dialog
139149 _fileEditor = PInvoke . GetDlgItem ( Handle , 0x0000 ) ; // DUIViewWndClassName
140150 _fileEditor = PInvoke . GetDlgItem ( _fileEditor , 0x0000 ) ; // DirectUIHWND
141151 _fileEditor = PInvoke . GetDlgItem ( _fileEditor , 0x0000 ) ; // FloatNotifySink
@@ -144,8 +154,19 @@ private bool GetFileEditor()
144154 if ( _fileEditor == HWND . Null )
145155 {
146156 Log . Error ( ClassName , "Failed to find file name editor handle" ) ;
157+ _type = DialogType . None ;
147158 return false ;
148159 }
160+ else
161+ {
162+ Log . Debug ( ClassName , "File dialog type: Save / Save As" ) ;
163+ _type = DialogType . SaveOrSaveAs ;
164+ }
165+ }
166+ else
167+ {
168+ Log . Debug ( ClassName , "File dialog type: Open" ) ;
169+ _type = DialogType . Open ;
149170 }
150171
151172 return true ;
@@ -166,7 +187,7 @@ private bool GetOpenButton()
166187
167188 public string GetCurrentFolder ( )
168189 {
169- if ( _pathEditor . IsNull && ! GetPathControlEditor ( ) ) return string . Empty ;
190+ if ( _pathEditor . IsNull ) return string . Empty ;
170191 return GetWindowText ( _pathEditor ) ;
171192 }
172193
@@ -178,20 +199,23 @@ public string GetCurrentFile()
178199
179200 public bool JumpFolder ( string path , bool auto )
180201 {
181- if ( _legacy || auto )
202+ if ( auto )
182203 {
183- // https://github.com/idkidknow/Flow.Launcher.Plugin.DirQuickJump/issues/1
184- // The dialog is a legacy one, so we edit file name text box directly
185- if ( _fileEditor . IsNull && ! GetFileEditor ( ) ) return false ;
186- SetWindowText ( _fileEditor , path ) ;
187-
188- if ( _openButton . IsNull && ! GetOpenButton ( ) ) return false ;
189- PInvoke . SendMessage ( _openButton , PInvoke . BM_CLICK , 0 , 0 ) ;
204+ // Use legacy jump folder method for auto quick switch because file editor is default value.
205+ // After setting path using file editor, we do not need to revert its value.
206+ return JumpFolderWithFileEditor ( path ) ;
207+ }
190208
191- return true ;
209+ if ( _legacy )
210+ {
211+ // https://github.com/idkidknow/Flow.Launcher.Plugin.DirQuickJump/issues/1
212+ // The dialog is a legacy one, so we can only edit file editor directly.
213+ return JumpFolderWithFileEditor ( path ) ;
192214 }
193215
194- if ( _pathControl . IsNull && ! GetPathControlEditor ( ) ) return false ;
216+ // Alt-D or Ctrl-L to focus on the path input box
217+ _inputSimulator . Keyboard . ModifiedKeyStroke ( VirtualKeyCode . LMENU , VirtualKeyCode . VK_D ) ;
218+ // _inputSimulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.LCONTROL, VirtualKeyCode.VK_L);
195219
196220 var timeOut = ! SpinWait . SpinUntil ( ( ) =>
197221 {
@@ -204,15 +228,28 @@ public bool JumpFolder(string path, bool auto)
204228 return false ;
205229 }
206230
207- if ( _pathEditor . IsNull && ! GetPathControlEditor ( ) ) return false ;
231+ if ( _pathEditor . IsNull ) return false ;
208232 SetWindowText ( _pathEditor , path ) ;
209233
234+ _inputSimulator . Keyboard . KeyPress ( VirtualKeyCode . RETURN ) ;
235+
236+ return true ;
237+ }
238+
239+ private bool JumpFolderWithFileEditor ( string path )
240+ {
241+ if ( _fileEditor . IsNull && ! GetFileEditor ( ) ) return false ;
242+ SetWindowText ( _fileEditor , path ) ;
243+
244+ if ( _openButton . IsNull && ! GetOpenButton ( ) ) return false ;
245+ PInvoke . SendMessage ( _openButton , PInvoke . BM_CLICK , 0 , 0 ) ;
246+
210247 return true ;
211248 }
212249
213250 public bool JumpFile ( string path )
214251 {
215- if ( _fileEditor . IsNull && ! GetPathControlEditor ( ) ) return false ;
252+ if ( _fileEditor . IsNull && ! GetFileEditor ( ) ) return false ;
216253 SetWindowText ( _fileEditor , path ) ;
217254
218255 return true ;
@@ -251,5 +288,12 @@ public void Dispose()
251288 {
252289 Handle = HWND . Null ;
253290 }
291+
292+ private enum DialogType
293+ {
294+ None ,
295+ Open ,
296+ SaveOrSaveAs
297+ }
254298 }
255299}
0 commit comments