Skip to content

Commit

Permalink
fix menu close by escape/click-outside
Browse files Browse the repository at this point in the history
  • Loading branch information
potoo0 committed Mar 1, 2024
1 parent b585716 commit d866857
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
tmp_**
QuickSwitch.exe
QuickSwitch.ini

# These are some examples of commonly ignored file patterns.
# You should customize this list as applicable to your project.
Expand Down
14 changes: 13 additions & 1 deletion Libs/Config.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ CFG := Config()


class Context {
static WinID := ""
static WinID := 0
static FingerPrint := ""
static FileDialog := ""
static DebugViewHwnd := 0

static Update(_winID) {
Context.WinID := _winID
Context.FingerPrint := ""
Context.FileDialog := ""
Context.DebugViewHwnd := 0
}

static InitFingerPrint(winID) {
; process name of the windows file dialog, eg: notepad.exe
Expand Down Expand Up @@ -65,4 +73,8 @@ class Config extends Object {
}
IniDelete(this.ConfigFilePath, section, key)
}

ClearCache() {
this._cache.Clear()
}
}
11 changes: 10 additions & 1 deletion Libs/FileDialog.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ FileDialogDispatcher(winId) {
; First is for notepad/vscode...; second for all other filedialogs
; That is our rough detection of a File dialog. Returns 1 or 0 (TRUE/FALSE)
flag := 0 ; bits: SysListView321 ToolbarWindow321 DirectUIHWND1 Edit1
for control in WinGetControls("ahk_id " . winId) {
if (!WinExist("ahk_id " winId)) {
return false
}
for control in WinGetControls("ahk_id " winId) {
switch control {
case "Edit1":
flag |= 1
Expand Down Expand Up @@ -46,6 +49,9 @@ class GeneralFileDialog extends AbstractFileDialog {
* @param {Integer} dstFolder
*/
static UpdateCurrentFolder(winId, dstFolder) {
if (!WinExist("ahk_id " winId)) {
return
}
WinActivate("ahk_id " winId)
Sleep(60)

Expand Down Expand Up @@ -104,6 +110,9 @@ class SysListWiewFileDialog extends AbstractFileDialog {
* @param {Integer} dstFolder
*/
static UpdateCurrentFolder(winId, dstFolder) {
if (!WinExist("ahk_id " winId)) {
return
}
WinActivate("ahk_id " winId)

; Read the current text in the "File Name:" input box
Expand Down
10 changes: 9 additions & 1 deletion Libs/FileManager.ahk
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
GetAllFolder() {
allFolders := []
for winId in WinGetlist() {

; skip hidden windows
DetectHiddenWindowsStateOld := A_DetectHiddenWindows
DetectHiddenWindows false
windows := WinGetlist()
DetectHiddenWindows DetectHiddenWindowsStateOld

; parse foler
for winId in windows {
winCls := WinGetClass("ahk_id " winId)
fileManager := ""
switch winCls {
Expand Down
45 changes: 29 additions & 16 deletions Libs/FolderSelector.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,46 @@


ShowFolderSelector(*) {
; double check file dialog
if (!WinExist("ahk_id" Context.WinID) || !(WinActive("ahk_id" Context.WinID) || WinActive("ahk_id " A_ScriptHwnd))) {
return
}
folders := GetAllFolder()
if (!folders or !folders.Length) {
return
}

; create menu
contextMenu := createMenu(folders)
contextMenu.Show("100", "100") ; halt main thread

; double check file dialog
if (WinExist("ahk_id" Context.WinID) && (WinActive("ahk_id" Context.WinID) || WinActive("ahk_id " A_ScriptHwnd))) {
; manually calc pos, as the file dialog not active
WinGetPos(&posX, &posY,,, "ahk_id" Context.WinID)
contextMenu.Show(posX + 200, posY + 200) ; halt main thread
}

destroyMenu()

createMenu(folders) {
; --------------- [ Title Bar ] ---------------
contextMenu := Menu()
contextMenu.Add("QuickSwitch Menu", (*) => "")
contextMenu.disable("QuickSwitch Menu")

; --------------- [ folders ] ---------------
; --------------- [ folders ] ---------------
for idx, folder in folders {
; name := "(!" idx ") " folder
name := folder
name := idx <= 10 ? ("&" idx " " folder) : folder
contextMenu.Add(name, onFolderChoice)
contextMenu.SetIcon(name, "shell32.dll", "5")
contextMenu.SetIcon(name, "shell32.dll", 5)
}

; --------------- [ Settings ] ---------------
contextMenu.Add()
contextMenu.Add("Settings for this dialog", (*) => "")
contextMenu.disable("Settings for this dialog")
contextMenu.Add("Never here", onMenuDisable, "Radio")
contextMenu.Add("Not now", onResetConfig, "Radio")
contextMenu.Add("Debug this dialog", DebugFileDialog)
contextMenu.Add("&Never here", onMenuDisable, "Radio")
contextMenu.SetIcon("&Never here", "shell32.dll", 110)
contextMenu.Add("&Not now", onResetConfig, "Radio")
contextMenu.SetIcon("&Not now", "shell32.dll", 132)
contextMenu.Add("&Debug this dialog", DebugFileDialog)
contextMenu.SetIcon("&Debug this dialog", "shell32.dll", 57)

; --------------- [ Style ] ---------------
contextMenu.SetColor("C0C59C")
Expand All @@ -47,9 +55,12 @@ ShowFolderSelector(*) {
contextMenu.Delete()
}

onFolderChoice(ItemName, *) {
if (Context.FileDialog and DirExist(ItemName)) {
Context.FileDialog.UpdateCurrentFolder(Context.WinID, ItemName)
onFolderChoice(itemName, *) {
if (RegExMatch(itemName, "^&\d\W", &OutputVar)) {
itemName := SubStr(itemName, StrLen(OutputVar[0]) + 1)
}
if (Context.FileDialog and DirExist(itemName)) {
Context.FileDialog.UpdateCurrentFolder(Context.WinID, itemName)
}
}

Expand Down Expand Up @@ -78,10 +89,12 @@ DebugFileDialog(*) {
cancelBtn := debugGui.Add("Button", "x+10 w100 h30", "Cancel")
cancelBtn.OnEvent("Click", cancel)

Context.DebugViewHwnd := debugGui.Hwnd
debugGui.OnEvent("Escape", cancel)
debugGui.Show()

appendFileDialogInfo() {
winId := WinExist("A")
winId := WinExist("ahk_id " Context.WinID)
if (!winId) {
return
}
Expand Down
21 changes: 18 additions & 3 deletions QuickSwitch.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ThisVersion := "0.5.1"

;@Ahk2Exe-SetVersion 0.5.1
;@Ahk2Exe-SetName QuickSwitch
;@Ahk2Exe-SetDescription Use opened file manager folders in File dialogs.
;@Ahk2Exe-SetDescription QuickSwitch ; the script's name in Task Manager under "Processes".
;@Ahk2Exe-SetCopyright NotNull

#Include Libs\Config.ahk
Expand All @@ -19,6 +19,7 @@ ThisVersion := "0.5.1"
;
SendMode("Input") ; SendInput and SendPlay use the same syntax as SendEvent but are generally faster and more reliable.
SetWorkingDir(A_ScriptDir) ; working dir for rw ini config file.
CoordMode("Menu") ; set the coord of menu relative to the desktop (entire screen)

; CTRL-Q
MENU_HOTKEY := "^Q"
Expand All @@ -37,14 +38,14 @@ If (VerCompare(A_OSVersion, "<6.1.7601")) {
}

; bind menu hotkey, but only work when file dialog is active
HotIfWinActive("ahk_class " FILE_DIALOG_CLASS) ; make context-sensitive
HotIfWinActive("ahk_class " FILE_DIALOG_CLASS) ; make context-sensitive
Hotkey(MENU_HOTKEY, ShowFolderSelector)
HotIfWinActive ; turn off context-sensitive

; listen file dialog event
Loop {
WinID := WinWaitActive("ahk_class " FILE_DIALOG_CLASS)
Context.WinID := WinID
Context.Update(WinID)

FileDialog := FileDialogDispatcher(WinID)
Context.FileDialog := FileDialog
Expand All @@ -56,14 +57,28 @@ Loop {
case 0:
; Never here, do nothing
default:
; active script's window, see https://github.com/samhocevar-forks/ahk/blob/master/source/script_menu.cpp#L1273
; must ensure one of the script's windows is active before showing the menu
; because otherwise the menu cannot be dismissed via the escape key or by clicking outside the menu.
DetectHiddenWindows true
WinActivate("ahk_id " A_ScriptHwnd)
ShowFolderSelector()
; restore active state if needed
if (!Context.DebugViewHwnd) {
WinActivate("ahk_id " WinID)
}
; move script's window to bottom
WinMoveBottom("ahk_id " A_ScriptHwnd)
DetectHiddenWindows false
}
}

; wait windows file dialog not active
WinWaitNotActive("ahk_id " WinID)

; Clean up
Context.Update("")
CFG.ClearCache()
WinID := ""
FileDialog := ""
}
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

QuickSwitch is an alternative to [Listary's QuickSwitch](https://www.youtube.com/watch?v=9T9-OtRVeUw) as that is abandoned.

Modified:
Modified based on [gepruts/QuickSwitch](https://github.com/gepruts/QuickSwitch):

1. Get path of active or all explorer tab
2. Fix menu close by escape/click-outside

### What does QuickSwitch do?

Expand Down
11 changes: 0 additions & 11 deletions todo.md

This file was deleted.

0 comments on commit d866857

Please sign in to comment.