Lorenzo501

Minimized Tabs Outliner (old stuff).ahk

Aug 6th, 2024
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;the non-compiled script can run itself w/ UIA (aka UI Access, the EXE should not use UIA b/c the personal UIA certificate of the EXE that it requires, expires after a period of time).
  2. ;and the if statement to detect it being a compiled script can check if it's running as admin, then if it's not it can just attempt to run itself as admin via predetermined tasks that should
  3. ;have been added to task scheduler, which it then triggers via code and terminates the non-admin instance.. generating an error if the task is not added to task scheduler yet.
  4. ;task scheduler can run the EXE as admin w/o the elevation prompt, even the taskbar icons can simply run the EXE w/o admin first, w/ launch parameters which then use code to request task
  5. ;scheduler to run a specific task that has matching launch parameters, to run it as admin (this solution does require multiple tasks b/c there are multiple launch parameters).
  6. ;the EXE running as admin would need to prevent running other software as admin, because it runs other software as admin by default, which usually isn't good
  7. ;it should be made available here: https://github.com/Lorenzo501/Lorenzo501/blob/main/My%20Projects%20(Extra)/Compiled/Minimized%20Tabs%20Outliner.exe
  8.  
  9. ;consider removing the --new-window flag because simply Run("chrome.exe") seems to open a new browser window as well
  10.  
  11. ;consider automatically installing tabs outliner with this flag --install-chrome-app when the script detects it not being installed yet
  12.  
  13. ;for the one at startup of the PC it's a bit more risky to send input while a bunch of processess are being started, it waits for the user to log on at the very least to make it work
  14. ;but I could send input twice, that will probably work (probably not necessary though and to do it reliably it might need a delay before sending each duplicate)
  15.  
  16.  
  17. ;if mouse-click interference isn't as rare as I thought, then create a LButton hotkey that saves the cursor position when executed and have this hotkey disabled by default, and enabled on
  18. ;demand when temporarily necessary to buffer mouse clicks. so then when it's enabled, it'll save cursor positions of times when the user clicked while in the buffer state, then when the
  19. ;buffer state ends, you can iterate over the cursor positions and sending clicks with them (without moving the cursor), removing the ones from the collection that are used. the LButton
  20. ;hotkey should ofcourse not send clicks itself when used. and maybe the LButton Up hotkey needs to simply temporarily return. if this for some reason doesn't work then simply use BlockInput
  21. ;temporarily. And do ALWAYS/IN ANY CASE keep the WinActivate before each input being send (it keeps it more reliable in case windows appear out of nowhere)
  22.  
  23. ;I only need BlockInput or w/e for the one that executes at startup of the PC there the user can actually interfere, b/c the others execute as soon as I click one of the icons in the
  24. ;taskbar so it's likely that I won't click something other than inside the chrome window that opens, and the ones that are invisible can't be clicked by the user.
  25. ;and the ones where keys are being send w/ SendInput, will cause user input to be postponed so I highly doubt that the user can interfere! even when it's not just one SendInput action
  26.  
  27.  
  28. ;the fast mode might improve things, but I don't fully understand it: CallbackCreate(Function, "Fast")
  29.  
  30.  
  31. ;I can make a new instance send a msg to the first instance to trigger something extra (if absolutely necessary, but I can likely always let the new instance do the extra thing itself)
  32.  
  33.  
  34. ;if (WinActive("ahk_exe explorer.exe") && !WinActive("ahk_class CabinetWClass")) ; is probably better than combining WinActive("ahk_class Progman") || WinActive("ahk_class Shell_TrayWnd")
  35. ;because there might be other classes that need to be detected as well, except the file explorer
  36.  
  37.  
  38. ;this is not great and doesn't always work (try no keydelay and sending lots of keys first, then consider a delay if sending lots of keys isn't making it reliable)
  39. ;temporary "BlockInput and AlwaysOnTop" not included
  40. ;A_KeyDelay := 500
  41. ;ControlSend("{End 2}{Esc}") ; works even when the window has been made hidden (w/ WinHide)
  42.  
  43.  
  44. ;perhaps this is even more thread-safe (although I doubt it's necessary)
  45. ;static isBeingMinimized
  46. ;if (!IsSet(isBeingMinimized) && (isBeingMinimized := true))
  47.  
  48.  
  49. ;a higher A_KeyDuration could be useful to make pasting with ControlSend more reliable? and if I were to use SendEvent (A_KeyDelayPlay & A_KeyDurationPlay contain the settings for SendPlay)
  50.  
  51.  
  52. ;MsgBox(FormatTime(A_Now, "HH : mm : ss")) ; RUNS BEFORE I'M EVEN LOGGED ON!^^
  53. ;startTime := A_TickCount
  54. ;Run("chrome.exe --start-maximized",,, &pid) ; doing this before the hooking results in some events being missed
  55. ;WinWait("ahk_pid " pid)
  56. ;MsgBox(A_TickCount - startTime " milliseconds have elapsed")
  57. ;DllCall("SetWinEventHook", "UInt", 32780, "UInt", 32780, "Ptr", 0, "Ptr", CallbackCreate(cb), "UInt", pid, "UInt", 0, "UInt", 0)
  58. cb(hWinEventHook, Event, hWnd, *)
  59. {
  60.     Critical()
  61.     static isNewTabChromeActive := true, isTabsOutlinerActive := true
  62.    
  63.     try
  64.     {
  65.         if (InStr(WinGetTitle(hWnd), "Google Chrome",, -1) && isNewTabChromeActive)
  66.         {
  67.             isNewTabChromeActive := false
  68.             oldWinDelay := SetWinDelay(-1)
  69.             WinSetTransparent(0, hWnd)
  70.             A_WinDelay := oldWinDelay
  71.             WinHide(hWnd)
  72.  
  73.             return
  74.         }
  75.  
  76.         if (WinGetTitle(hWnd) != "_crx_eggkanocgddhmamlbiijnphhppkpkmkl")
  77.             return
  78.     }
  79.     catch
  80.     {
  81.         return
  82.     }
  83.  
  84.     if (isTabsOutlinerActive)
  85.     {
  86.         isTabsOutlinerActive := false
  87.         oldWinDelay := SetWinDelay(-1)
  88.         WinSetTransparent(0, hWnd)
  89.         A_WinDelay := oldWinDelay
  90.  
  91.         WinHide(hWnd)
  92.         DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  93.  
  94.         ;Thread("NoTimers")
  95.         ;Thread("Priority", 1)
  96.  
  97.         ; To make ControlClick work (put it on the line above ControlClick?)
  98.         ;ProcessWaitClose("LogonUI.exe")
  99.  
  100.         DetectHiddenWindows(true)
  101.         A_WinDelay := -1
  102.         WinWait("Tabs Outliner ahk_exe chrome.exe")
  103.         A_WinDelay := oldWinDelay
  104.  
  105.         ; TRY AGAIN, WITH SILENT-LAUNCH (now includes controldelay -1) AND TRY SCROLLWHEEL
  106.         ; this can be used to click on the bottom of the tabs outliner scrollbar
  107.         ;WinGetClientPos(,, &tabsOutlinerWidth, &tabsOutlinerHeight)
  108.         ;Send("{Shift down}")
  109.         ;A_ControlDelay := -1
  110.         ;ControlClick("x" tabsOutlinerWidth-1 " y" tabsOutlinerHeight-1,,,,, "NA")
  111.         ;Send("{Shift up}")
  112.  
  113.         ;https://www.autohotkey.com/board/topic/24029-controlsend-controlclick-workaround-send-a-ctrldownleftmouse/page-2#entry156078
  114.         ;https://www.autohotkey.com/boards/viewtopic.php?style=7&t=97971
  115.         ;so these can't be used instead
  116.         ;ControlSend("{Shift down}")
  117.         ;ControlSend("{Shift up}")
  118.  
  119.         ;ControlClick(, hWnd,, "WD", 273, "NA")
  120.  
  121.         WinMinimize()
  122.         WinClose("Google Chrome ahk_exe chrome.exe")
  123.         DetectHiddenWindows(false)
  124.         WinSetTransparent("Off")
  125.  
  126.         ; This needs to be delayed until all startup items are running, b/c too early caused it to try to fix the size/position of uTorrent for example, causing it to get shown at startup
  127.         ; and that was bad b/c I had uTorrent set up to start as minimized. So apparently it didn't even get the chance to do that.. Similar to the issue it may cause w/ tabs outliner
  128.         Run(RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run", "WinSize2"))
  129.        
  130.         ExitApp()
  131.     }
  132. }
  133.  
  134.  
  135. ;A_ControlDelay := -1 ; default is 20, could try 0 instead, or maybe above 20 is best b/c the CPU could be under load (this only affects ControlClick)
  136.  
  137. ;WinSetTransparent(1)
  138. ;ControlClick(,,, "WheelUp", 12, "NA")
  139. ;WinSetTransparent(0)
  140.  
  141.  
  142. ;Not all applications obey a ClickCount higher than 1 for turning the mouse wheel. For those applications, use a loop to turn the wheel more than one notch as in this example, which turns
  143. ;it 5 notches:
  144. /*Loop 5
  145.     ControlClick Control, WinTitle, WinText, "WheelUp"*/
  146.  
  147.  
  148. ;maybe the lowest possible value to allow ControlClick to work? idk but this normally allows the window to be clickable by the user (can do 0 first and then 1 right before ControlClick)
  149. ;WinSetTransparent(1)
  150.  
  151.  
  152. ;REQUIRES UI ACCESS WHEN START MENU IS OPEN
  153. ;temporarily hiding the taskbar to get rid of all orange icons or if that doesn't happen, then hide until the Tabs Outliner hide-show code removes the individual orange icon
  154. ;WinHide("ahk_class Shell_TrayWnd")
  155. ;WinShow("ahk_class Shell_TrayWnd")
  156.  
  157.  
  158. ;#WinActivateForce might fix the orange icon but not always, so try the solution below with ̶S̶l̶e̶e̶p̶(̶1̶0̶0̶) Sleep(500) right above it if another window function was executed right before
  159. ;if this doesn't fix the orange icon, then try doing it after the user has logged on at the end of the cb function (or mix it together with the solution above this)
  160. ;SetWinDelay(-1)
  161. ;WinHide("Tabs Outliner ahk_exe chrome.exe")
  162. ;WinShow("Tabs Outliner ahk_exe chrome.exe")
  163. ;SetWinDelay(100)
  164.  
  165.  
  166. ; CONFIRMED WORKAROUND TO SETUP WINDOW THAT'S MOVED OUT OF VIEW (DON'T FORGET "DetectHiddenWindows"): HIDE > INVISIBLE > MAXIMIZE > HIDE > MINIMIZE > VISIBLE
  167.  
  168.  
  169. ; [gotta make sure that WinSize2 doesn't interfere with ControlClick nor minimization:]
  170. ; UNSAFE/INITIAL VERSION (this one doesn't make sure that it has been paused/unpaused)
  171. ; This is necessary to stop interference from WinSize2 AHK scripts (e.g. use this if tabs outliner isn't always being minimized, then I suspect it's b/c of WinSize2 interfering)
  172. ToggleWinSize2()
  173. {
  174.     A_DetectHiddenWindows := true
  175.  
  176.     ; Pause/unpause when the main WinSize2 AHK script is running
  177.     loop
  178.     {
  179.         ids := WinGetList("ahk_class AutoHotkey")
  180.  
  181.         for (iteratedId in ids)
  182.             if (InStr(WinGetTitle(iteratedId), "WinSize2.EXE",, -1))
  183.             {
  184.                 ; The following is the same as the user having selected "Pause Script" from the tray menu (65306 = PAUSE, 65305 = SUSPEND)
  185.                 PostMessage(0x0111, 65306,,, iteratedId)
  186.  
  187.                 break 2
  188.             }
  189.  
  190.         Sleep(30)
  191.     }
  192. }
  193.  
  194. ;the next thing is probably not necessary, b/c I can just use SendMessage with TimeoutError to bruteforce the toggle (very reliable) and then there's no need to edit WinSize2 source,
  195. ;and providing the change in the EXE but yeah I'm already gonna provide the EXE but it's better to keep most stuff in my own script. if u use PostMessage instead of SendMessage to pause
  196. ;script, then u need to add Sleep(10) before SendMsg(0x5555, 69)
  197.  
  198. ;convert to AHKv1 and then put this in the target script:
  199. ;OnMessage(0x5555, (wParam, *) => (wParam = 69 ? A_IsPaused : ""))
  200.  
  201. ;send pause message with this function:
  202. PauseScript(targetScriptTitle)
  203. {
  204.     DetectHiddenWindows(true)
  205.  
  206.     if (!WinExist(targetScriptTitle))
  207.         return TrayTip("Target Script Not Found")
  208.  
  209.     SendMessage(0x0111, 65306)
  210.  
  211.     return "Target Script " (SendMessage(0x5555, 69) ? "Is Paused" : "Is Not Paused")
  212. }
  213.  
  214. ;version 2
  215. PauseScript(targetScriptTitle)
  216. {
  217.     DetectHiddenWindows(true)
  218.    
  219.     if (!WinExist(targetScriptTitle))
  220.         return TrayTip("Target Script Not Found")
  221.  
  222.     try SendMsg(0x0111, 65306)
  223.  
  224.     try return SendMsg(0x5555, 69) ? "Is Paused" : "Is Not Paused"
  225.     return "SendMessage Failed"
  226.  
  227.     SendMsg(msg, wParam := 0, lParam := 0, timeout := 500) => SendMessage(msg, wParam, lParam,,,,,, timeout)
  228. }
  229.  
  230.  
  231. ;SetKeyDelay():
  232. ;Every newly launched thread (such as a hotkey, custom menu item, or timed subroutine) starts off fresh with the default setting for this function. That default may be changed by using this
  233. ;function during script startup
  234. ;For Send/SendEvent mode, a delay of 0 internally executes a Sleep(0), which yields the remainder of the script's timeslice to any other process that may need it. If there is none, Sleep(0)
  235. ;will not sleep at all. By contrast, a delay of -1 will never sleep. For better reliability, 0 is recommended as an alternative to -1.
  236. ;When the delay is set to -1, a script's process-priority becomes an important factor in how fast it can send keystrokes when using the traditional SendEvent mode. To raise a script's
  237. ;priority, use ProcessSetPriority "High". Although this typically causes keystrokes to be sent faster than the active window can process them, the system automatically buffers them.
  238. ;Buffered keystrokes continue to arrive in the target window after the Send function completes (even if the window is no longer active). This is usually harmless because any subsequent
  239. ;keystrokes sent to the same window get queued up behind the ones already in the buffer
  240.  
  241. ;AutoHotkey's update interval is 16ms, so using 10ms in code will make it happen at each update, making it 20ms would probably become 2x16=32ms, so each second update then
  242. ;Specify -1 for no delay at all or 0 for the smallest possible delay?
  243.  
  244. ;in AHK scripts you can use this if it needs priority above basically everything else (overkill for most situations):
  245. ;ProcessSetPriority("High")
  246. ;if you add an AHK script as a task to task scheduler, you might want to export the task & then change the XML default priority from value: 7 (below normal) to: 5 (normal), then import it.
  247. ;no need to set it to normal in the AHK script itself, because it's normal by default (programs ran by task scheduler sometimes need different priorities but usually below normal is fine).
  248. ;don't set any other priority in task scheduler for AHK scripts, b/c those you should set in the AHK scripts directly (for when you open the file directly plus any other situation)
  249. ;for non-AHK tasks in task scheduler it could make a lot more sense, so you might want this:
  250. ;Task Priority  Priority Category
  251. ;0      Real-time
  252. ;1      High
  253. ;2-3        Above normal
  254. ;4-6        Normal
  255. ;7-8        Below normal
  256. ;9-10       Idle
  257.  
  258.  
  259. AHK is not case-sensitive, so:
  260. class EXAMPLE {
  261. }
  262. instance := example()
  263. MsgBox(Type(instance))
  264.  
  265. Will show:
  266. EXAMPLE
  267.  
  268. But this won't work, b/c the variable name is already used by the class name:
  269. class EXAMPLE {
  270. }
  271. example := EXAMPLE()
  272. MsgBox(Type(example))
  273.  
  274. Therefore you'd have to use hungarian notation, like an underscore to do it right:
  275. class Example {
  276. }
  277. _example := Example()
  278. MsgBox(Type(_example))
  279.  
  280.  
  281. UI Access allows accessible-level interaction from applications running different integrity levels while administrative application have access to system-level resources.
  282. UI Access is as insecure as an elevated process with the huge caveat that doesn't have access to system-level assets making harder to vertical level attacks to affect
  283. Is harder to an escalation of privileges
  284. https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-account-control-allow-uiaccess-applications-to-prompt-for-elevation-without-using-the-secure-desktop
  285. And the why is harder:
  286. https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-account-control-only-elevate-uiaccess-applications-that-are-installed-in-secure-locations
  287. The requirements are tailored to make it so, only applications installed AND with the proper configuration in the manifest (plus a verified signature) are able to bypass the UIPI
  288.  
  289.  
  290. ; if (GetUrl(hWnd) = "chrome://newtab")
  291. ; if (GetUrl(hWnd) = "chrome://newtab/")
  292. ; if (GetUrl(hWnd) = "chrome://new-tab-page")
  293. ; if (GetUrl(hWnd) = "chrome://new-tab-page/")
  294.  
  295. ; Version: 2023.05.11.1
  296. ; https://gist.github.com/7cce378c9dfdaf733cb3ca6df345b140
  297.  
  298. GetUrl(WinTitle*) {
  299.     active := WinExist("A")
  300.     if !(hWnd := WinExist(WinTitle*))
  301.         return
  302.     objId := -4
  303.     wClass := WinGetClass()
  304.     if (wClass ~= "Chrome") {
  305.         appPid := WinGetPID()
  306.         hWnd := WinExist("ahk_pid" appPid)
  307.         if (active != hWnd)
  308.             objId := 0
  309.     }
  310.     oAcc := Acc_ObjectFromWindow(hWnd, objId)
  311.     if (wClass ~= "Chrome") {
  312.         try {
  313.             SendMessage 0x003D, 0, 1, "Chrome_RenderWidgetHostHWND1"
  314.             oAcc.accName(0)
  315.         }
  316.     }
  317.     if (oAcc := GetUrl_Recurse(oAcc))
  318.         return oAcc.accValue(0)
  319. }
  320.  
  321. GetUrl_Recurse(oAcc) {
  322.     if (ComObjType(oAcc, "Name") != "IAccessible")
  323.         return
  324.     if (oAcc.accValue(0) ~= "^[\w-]+:")
  325.         return oAcc
  326.     for _, accChild in Acc_Children(oAcc) {
  327.         oAcc := GetUrl_Recurse(accChild)
  328.         if (IsObject(oAcc))
  329.             return oAcc
  330.     }
  331. }
  332.  
  333. /*************************************************************
  334.  * To reset cursors in registry use "Default cursors.reg"
  335.  * and then invoke DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0)
  336.  *************************************************************
  337. Windows Registry Editor Version 5.00
  338.  
  339. [HKEY_CURRENT_USER\Control Panel\Cursors]
  340. "Arrow"="C:\\WINDOWS\\cursors\\aero_arrow.cur"
  341. "Hand"="C:\\WINDOWS\\cursors\\aero_link.cur"
  342. "Help"="C:\\WINDOWS\\cursors\\aero_helpsel.cur"
  343. "IBeam"=""
  344. "NWPen"="C:\\WINDOWS\\cursors\\aero_pen.cur"
  345. "SizeAll"="C:\\WINDOWS\\cursors\\aero_move.cur"
  346. "SizeNESW"="C:\\WINDOWS\\cursors\\aero_nesw.cur"
  347. "SizeNS"="C:\\WINDOWS\\cursors\\aero_ns.cur"
  348. "SizeNWSE"="C:\\WINDOWS\\cursors\\aero_nwse.cur"
  349. "SizeWE"="C:\\WINDOWS\\cursors\\aero_ew.cur"
  350. */
  351.  
  352. /********** TRASH: loading cursor without animation **********/
  353.  
  354. /*cursors := [32512, 32513, 32514, 32515, 32516, 32642, 32643, 32644, 32645, 32646, 32648, 32649, 32650]
  355. OnExit((*) => (DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0), 0)) ; Lambda returns last value (non-zero avoids exit)
  356.  
  357. for (id in cursors)
  358.     DllCall("SetSystemCursor", "Ptr", DllCall("CopyIcon", "Ptr", DllCall("LoadCursor", "Ptr", 0, "Ptr", IDC_APPSTARTING := 32650)), "UInt", id)*/
  359.  
  360. /********** proper input tooltip **********/
  361.  
  362. ;Persistent()
  363. ;HookAllKeys()
  364.  
  365. HookAllKeys()
  366. {
  367.     static inputs     := ""
  368.     ih                := InputHook("I1 L0 *")
  369.     ih.NotifyNonText  := true
  370.     ih.VisibleNonText := false
  371.     ih.OnKeyDown      := OnKey.Bind(,,, "Down")
  372.     ih.OnKeyUp        := OnKey.Bind(,,, "Up")
  373.     ih.KeyOpt("{All}", "N S")
  374.     ih.Start()
  375.    
  376.     OnKey(ih, VK, SC, UD) => (
  377.         Critical(),
  378.         ToolTip(inputs .= Format("{{1} {2}}", GetKeyName(Format("vk{:x}sc{:x}", VK, SC)), UD))
  379.     )
  380.  
  381. ;Change the callback function OnKey to this, then it will just send the key u pressed itself
  382. ;OnKey(ih, VK, SC, UD) => Send(Format("{Blind}{{1} {2}}", GetKeyName(Format("vk{:x}sc{:x}", VK, SC)), UD))
  383. }
  384.  
  385. /********** TRASH: input tooltip 2, release & repress **********/
  386.  
  387. ;Func1()
  388. Func1()
  389. {
  390. loop
  391. {
  392.     loop (0xFF)
  393.     {
  394.         static input := ""
  395.         key := Format("VK{:02X}", A_Index)
  396.  
  397.         if (GetKeyState(key))
  398.             Tooltip(input .= key)
  399.     }
  400. }
  401. }
  402.  
  403.  
  404.  
  405. ; Use it to release all currently pressed keys, do a hotkey action, and then repress the keys:
  406. ReleaseKeys()
  407. {
  408.     releasedKeys := [], str := ""
  409.  
  410.     loop (0xFF)
  411.     {
  412.         key := Format("VK{:02X}", A_Index)
  413.  
  414.         if (GetKeyState(key))
  415.         {
  416.             str .= "{" key " Up}"
  417.             releasedKeys.Push(key)
  418.         }
  419.     }
  420.  
  421.     Send(str)
  422.     return releasedKeys
  423. }
  424.  
  425. RepressKeys(keys)
  426. {
  427.     str := ""
  428.  
  429.     for (key in keys)
  430.     {
  431.         if (GetKeyState(key, "P"))
  432.             str .= "{" key " Down}"
  433.     }
  434.  
  435.     Send(str)
  436. }
  437.  
  438. /********** TRASH: compact buffer input **********/
  439.  
  440. /*text := ""
  441.  
  442. loop (226)
  443. {
  444.     iteratedKey := GetKeyName(Format("VK{1:02X}", A_Index))
  445.  
  446.     if (iteratedKey)
  447.         text .= iteratedKey " "
  448. }
  449.  
  450. MsgBox text
  451.  
  452. ; BUFFERING INPUT WORKS (you do lose key modifiers and key down/up status, which is what makes selecting text w/ cursor works)
  453. loop (226)
  454.     Hotkey("$" Format("VK{1:02X}", A_Index), (*) => Send("{" SubStr(A_ThisHotkey, 2) "}"))*/
  455.  
  456.     ; BUT NOT LIKE THIS (idk how this makes sense but whatever, I got a more reliable way that allows you to keep all key functionality)
  457.     /*if (key := Format("VK{1:02X}", A_Index) != "LButton")
  458.         Hotkey("$" key, (*) => Send("{" SubStr(A_ThisHotkey, 2) "}"))*/
  459.  
  460. /*F1::
  461. {
  462. Critical
  463. Tooltip("buffering input")
  464. startTime := A_TickCount
  465.  
  466. while (A_TickCount - startTime < 5000)
  467.     continue
  468.  
  469. Tooltip()
  470. }
  471.  
  472. ; This also doesn't allow text to be selected properly while mouse input is buffered..
  473. $LButton::Send("{LButton Down}")
  474. $LButton Up::Send("{LButton Up}")*/
  475.  
  476. /********** TRASH: I've patched WinSize2.ahk in a more simple way (keeping this in case if I ever wanna implement the patch in my own script or need to do something differently) **********/
  477.  
  478. /* BRAINSTORM SESSION *
  479. ** * * * * * * * * * *
  480. ** ISSUE: This will cause the WinSize2 unpause at the end to affect (in my case) uTorrent, making it become activated/unminimized and its pos/size being fixed unintentionally
  481. ** HACKY SOLUTION: First doing WinActive("A") to see if there's anything active, in which case the issue mentioned above will happen, so then do the following:
  482. ** Find all minimized apps of WinSize2 INI that exist after userinit.exe closes, right before unpausing WinSize2, and then make those transparent,
  483. ** unpause WinSize2, set timer of 5sec and then minimize them again in case WinSize2 has unminimized them and whatnot, and then just make them visible
  484. ** NICE SOLUTION: use code from WinSize2Turbo, e.g. the callback to see if WinSize2 has finished doing something, might work like a charm, using a timeout of 500ms b/c it should be done
  485. ** by then: 10ms custom interval in WinSize2 settings + max approx 150ms for each of these two actions: resize and move, WinSize2 checks all windows at once, so I bet it's fine this way.
  486. ** I could leave a note in the initial commit to multiply the 2-action timeout by the amount of minimized windows that WinSize2 can affect at that moment, add the base timeout 200ms on top.
  487. ** The 500ms timeout is made up of the 2-action timeout: 150ms+150ms=300ms and the base timeout: 10ms custom interval (200ms interval for those who kept the default) in WinSize2 settings.
  488. ** If the timeout is reached then WinSize2 didn't affect it ̶a̶n̶d̶ ̶t̶h̶e̶ ̶u̶s̶e̶r̶ ̶m̶i̶g̶h̶t̶'̶v̶e̶ ̶u̶n̶m̶i̶n̶i̶m̶i̶z̶e̶d̶ ̶i̶t (np, then it'd get fixed), so after the timeout the windows have to become visible again
  489. **
  490. ** Can also save the minimized windows, then when the event watcher notices a window has become (unminimized?) resized/repositioned then start a timeout for that specific window and
  491. ** in that time it can do the other resize/reposition action, and if it doesn't, then the user has unminimized the window itself....... NOPE?: even if the user unminimizes it, then WinSize2
  492. ** would DEFINITELY fix it... ̶s̶o̶ ̶i̶t̶ ̶d̶o̶e̶s̶n̶'̶t̶ ̶m̶a̶t̶t̶e̶r̶/̶d̶o̶e̶s̶n̶'̶t̶ ̶h̶a̶v̶e̶ ̶t̶o̶  which will be seen by the event watcher as the 2nd event (resize/reposition), or 150ms extra as a timeout..hmmmm, it
  493. ** DOESN'T HAVE TO USE A TIMEOUT AFTERWARDS IF THE WINDOW GETS UNMINIMIZED BY THE USER (or after the first resize/reposition action happened), B/C THE WINDOW WILL DEFINITELY GET FIXED THEN.
  494. ** should have a timeout beforehand in case it doesn't get affected by WinSize2 unintentionally or unminimized by the user (the script HAS to ExitApp), or maybe start a timer at the end of
  495. ** the DevTools cb, which first makes all invisible windows that remain, visible again and then uses ExitApp(). I can probably incorporate this fix in the patched WinSize2 to make that work
  496. ** properly (there is a Patched WinSize2 folder in the AutoHotkey folder), or if it can't be done then just use it in this script (Minimized Tabs Outliner.ahk) and use the patched WinSize2
  497. ** alongside it, because that one should then work fine as long as I have fixed the issue somewhere
  498. */
  499. ; Early attempt to start chrome normally (otherwise trying again later in case Tabs Outliner does exist then)
  500. ;CODE OMITTED
  501.  
  502. ;Attempt #2 like described earlier
  503. ;in WinSize2.ahk somewhere before it tries to fix stuff
  504. ;maybe a delay is necessary first to hold off until the ToggleWinSize2 unpause (idk if it will otherwise execute too early, at the start of my script when running WinSize2, which is bad)
  505. ;find the minimized windows, make em invisible
  506. ;setup an event watcher
  507. ;then let it fix what it want,
  508. ;and make unminimized windows minimized and visible again
  509.  
  510. ;the WinSize2 workarounds in my own script are gonna be kept in the next commit but then taken out in the one after that, just in case (so I can see where everything belonged in the code)
  511.  
  512. /********** TRASH: old target+start_dir **********/
  513.  
  514. ;DEFAULT TARGET+START_DIR OF CHROME
  515. ;"C:\Program Files\Google\Chrome\Application\chrome.exe"
  516. ;"C:\Program Files\Google\Chrome\Application"
  517.  
  518. ;DEFAULT TARGET OF TABS OUTLINER:
  519. ;"C:\Program Files\Google\Chrome\Application\chrome.exe" --profile-directory=Default --app-id=eggkanocgddhmamlbiijnphhppkpkmkl
  520.  
  521. ;PREVIOUS TARGET+START_DIR OF TABS OUTLINER
  522. ;"C:\Program Files\Google\Chrome\Application\chrome.exe" --silent-launch
  523. ;"C:\Program Files\Google\Chrome\Application"
  524.  
  525. /********** TRASH: problematic INI stuff **********/
  526.  
  527. /*; This will prevent WinSize2 from affecting other windows
  528. FileCopy(A_AppData "\MagraSoft\WinSize2.INI", A_Temp, 1)
  529. section := IniRead(A_AppData "\MagraSoft\WinSize2.INI", "WinSize")
  530. linesSplit := StrSplit(section, "`n")
  531. for (iteratedLine in linesSplit)
  532.     if (InStr(iteratedLine, "Tabs Outliner"))
  533.         IniWrite("AWNr_1=" StrSplit(iteratedLine, "=")[2], A_AppData "\MagraSoft\WinSize2.INI", "WinSize")*/
  534.  
  535.  
  536. /*"HandleDevToolsEvent" CODE OMITTED
  537.             HookEvent(EVENT_OBJECT_LOCATIONCHANGE, HandleFinalPhaseTabsOutlinerEvent, WinGetPID("Tabs Outliner ahk_exe chrome.exe"))
  538.  
  539.             ; Letting WinSize2 temporarily run to fix the size and position of Tabs Outliner while it's invisible
  540.             ToggleWinSize2()
  541.         }
  542.     }
  543.  
  544.     HandleFinalPhaseTabsOutlinerEvent(hWinEventHook, event, hWnd, *)
  545.     {
  546.         ; The first one is WinSize2 resizing Tabs Outliner and second one is WinSize2 repositioning Tabs Outliner
  547.         static matchCounter := 0
  548.  
  549.         try if (WinGetTitle(hWnd) = "Tabs Outliner" && ++matchCounter = 2)
  550.         {
  551.             ToggleWinSize2() ; Temporarily pausing WinSize2 to prevent interference with the code below
  552.             FileCopy(A_Temp "\WinSize2.INI", A_AppData "\MagraSoft", 1)
  553.             DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  554. CODE OMITTED*/
  555.  
  556. /********** TRASH: visibility check that's likely not gonna be used **********/
  557.  
  558. ;if I want to check if a window is visible or invisible,
  559. ;then use WinGetTransparent or maybe this (usage example: WinVisible("ahk_class Shell_TrayWnd")):
  560.  
  561. WinVisible(winTitle)
  562. {
  563.     style := WinGetStyle(winTitle)
  564.     result := style & 0x10000000 ; 0x10000000 is WS_VISIBLE
  565.  
  566.     return result != 0 ? true : false
  567. }
  568.  
  569. /********** TRASH: Embedded INI.ahk that's likely not gonna be used **********/
  570.  
  571. #Requires AutoHotkey 2.0
  572. ;so you don't need to read/write to the registry
  573.  
  574. F1::GetFeatureStatus("Feature1")
  575. F2::GetFeatureStatus("Feature2")
  576. F3::IniWrite("Feature1=test123", A_ScriptFullPath, "SavedVariables2")
  577.  
  578. GetFeatureStatus(featureName)
  579. {
  580.     section := IniRead(A_ScriptFullPath, "SavedVariables")
  581.     linesSplit := StrSplit(section, "`n")
  582.  
  583.     for (line in linesSplit)
  584.         if (InStr(line, featureName))
  585.             if (StrSplit(line, "=")[2])
  586.                 MsgBox(featureName " is enabled")
  587.             else
  588.                 MsgBox(featureName " is disabled")
  589. }
  590.  
  591. /*
  592. [SavedVariables]
  593. Feature1=1
  594. Feature2=0
  595. [SavedVariables2]
  596. Feature1=test123
  597. */
  598.  
  599. /******************** TRASH: WinSize2.INI ********************/
  600.  
  601. [Settings]
  602. Date=2024-03-02 02.35.35
  603. Version=2.38.04
  604. LangIDHex=0413
  605. LangIDDec=19
  606. GuiWindowX=1
  607. GuiWindowY=1
  608. GuiWindowWidth=815
  609. GuiWindowHeight=410
  610. Hotkey=^!/
  611. Message_Help=0
  612. Language=?
  613. TitleTimer=10
  614. Tooltip_Time_Show=10
  615. Command_Time_Wait=2000
  616. IniScreen_Time_Show=0
  617. MenuTrayIcon_Show=1
  618. Update_Path=--\
  619. StartWithLogon=1
  620. Char_Delay_msec=50
  621. Tooltip_Show_Tip=0
  622. Titles_Sort_Basis=0
  623. Titles_Sort_ZA=0
  624. Titles_Sort_with_Comment=0
  625. LogFile_Level=3
  626. TabNumber_Open_Last_Tab=
  627. TabNumber_ActTab=1
  628. Group_Choose_Nr=1
  629. Font_Factor=1
  630. DesktopIcon_CheckAfterLogin=0
  631. DesktopIcon_AutoRestore=0
  632. DesktopIcon_CheckResolution=0
  633. DesktopIcon_StoreInFile=1
  634. Network_WithIconSave=0
  635. Network_WithIconRestore=0
  636. Delay_Show_Tooltip=0
  637. [WinSize]
  638. AWNr_1=Tabs Outliner-804941449300001100001Chrome_WidgetWin_1{Return}0Z
  639. AWNr_2=Untitled - Notepad5003031559841300001100999Notepad{Return}0Z
  640. AWNr_3=Torrent5795814011334200001100001µTorrent4823DF041B09{Return}0Z
  641. AWNr_4=Calculator13482741218941300001100001ApplicationFrameWindow{Return}0Z
  642. AWNr_5=Find505144-1-1300001100999#32770{Return}0Z
  643. AWNr_6=magnet13942751169860200001100999#32770{Return}0Z
  644. AWNr_7=This PC5787214041303300001100001CabinetWClass{Return}0Z
  645. AWNr_8=Desktop5787214041303300001100001CabinetWClass{Return}0Z
  646. AWNr_9=Downloads5787214041303300001100001CabinetWClass{Return}0Z
  647. AWNr_10=Films5787214041303300001100001CabinetWClass{Return}0Z
  648.  
  649. /******************** TRASH: MINIMIZED TABS OUTLINER BEFORE I TOOK OUT THE WINSIZE2 STUFF AND COMPILATION STUFF ********************/
  650.  
  651. ;@Ahk2Exe-UpdateManifest 0,,, 1
  652. #Requires AutoHotkey 2.0
  653. #SingleInstance Off
  654.  
  655. ; Show the Tabs Outliner extension in the chrome web store when it hasn't been installed and configured yet
  656. if (!(hasTabsOutlinerExtension := DirExist(EnvGet("LocalAppData") "\Google\Chrome\User Data\Default\Extensions\eggkanocgddhmamlbiijnphhppkpkmkl")))
  657. {
  658.     Run("chrome.exe https://chromewebstore.google.com/detail/tabs-outliner/eggkanocgddhmamlbiijnphhppkpkmkl --start-maximized --disable-features=GlobalMediaControls")
  659.     MsgBox("Tabs Outliner has not been installed and configured yet!",, "0x40000 Iconx")
  660.     ExitApp()
  661. }
  662.  
  663. ; Early attempt to start chrome normally (otherwise trying again later in case a chrome process does exist then)
  664. if (A_Args.Length > 0 && A_Args[1] = "--duo" && ProcessExist("chrome.exe"))
  665. {
  666.     Run("chrome.exe --start-maximized --disable-features=GlobalMediaControls")
  667.     ExitApp()
  668. }
  669.  
  670. if (A_IsCompiled)
  671. {
  672.     A_DetectHiddenWindows := true
  673.  
  674.     if (WinGetList(A_ScriptFullPath " ahk_class AutoHotkey").Length > 1)
  675.         ExitApp()
  676.  
  677.     A_DetectHiddenWindows := false
  678. }
  679. ; To make certain things work even when an admin window becomes active
  680. else if (!InStr(A_AhkPath, "_UIA.exe"))
  681. {
  682.     A_DetectHiddenWindows := true
  683.  
  684.     ; Gets skipped when the user executes the script manually from the taskbar before or while the startup instance executes
  685.     if (WinGetList(A_ScriptFullPath " ahk_class AutoHotkey").Length = 1)
  686.         Run("*UIAccess " A_ScriptFullPath (A_Args.Length > 0 ? " " A_Args[1] : ""))
  687.    
  688.     ExitApp()
  689. }
  690.  
  691. #NoTrayIcon
  692. Persistent()
  693. OnError((*) => (ListLines(), StopBufferingInputsAndReleaseOnRelevantWnd(), 0)) ; Lambda returns last value (zero shows error)
  694. interfaceImprovementsJS := "
  695. (
  696.    arrayHtml = document.getElementsByClassName("winNTASC"); arrayHtml[arrayHtml.length - 1].classList.add("tabsOutlinerWindow")
  697.    sheet = document.styleSheets[0]; rules = sheet.cssRules
  698.    sheet.insertRule("div#scrollToLastNodeCompensator { height: 17.6em !important; }", sheet.cssRules.length)
  699.     sheet.insertRule("li.tabsOutlinerWindow { visibility: hidden; height: 0px; padding: 0px; margin: 0px; }", sheet.cssRules.length)
  700.     window.scrollTo(0, document.body.scrollHeight - window.innerHeight)
  701.     arrayHtml = document.getElementsByClassName("mainViewMessage"); arrayHtml[0].parentNode.removeChild(arrayHtml[0])
  702. )"
  703. A_TitleMatchMode := 3 ; For detecting windows with a title that matches the given WinTitle exactly (e.g. to match "Tabs Outliner" when requested, skipping "Tabs Outliner Options")
  704. A_CoordModeMouse := "Screen"
  705. A_KeyDelay := -1 ; For pasting with ControlSend and also for Send b/c it reverts to the Event SendMode when another AHK script installs a native low-level keyboard/mouse hook
  706. A_KeyDuration := -1 ; For Send b/c it reverts to the Event SendMode when another AHK script installs a native low-level keyboard/mouse hook
  707. A_MouseDelay := -1 ; For a buffered left-, right- or double-click with Send b/c it reverts to the Event SendMode when another AHK script installs a native low-level keyboard/mouse hook
  708. A_WinDelay := -1
  709. EVENT_OBJECT_SHOW := 0x8002
  710. EVENT_OBJECT_NAMECHANGE := 0x800C
  711. tabsOutliner := {IsBeingPrepared: false} ; Ad hoc object, usable w/ dot notation (no need for class)
  712. disposableNewTabChrome := {Id: 0} ; Ad hoc object, usable w/ dot notation (no need for class)
  713.  
  714. ; The first scope executes at startup (using no flag or the experimental startup flag will trigger this expanded single mode)
  715. if (A_Args.Length = 0 || A_Args[1] = "--uninhibited-clicks")
  716. {
  717.    EVENT_OBJECT_LOCATIONCHANGE := 0x800B
  718.  
  719.    WinWait("ahk_class Progman") ; Gotta wait until it exists before activating it to deactivate the taskbar
  720.    TaskbarUtilities.ToggleDeactivateTimer()
  721.    TaskbarUtilities.WaitDeactivate()
  722.  
  723.    if (!TaskbarUtilities.HasDeactivateTimedOut)
  724.        TaskbarUtilities.MakeInvisible()
  725.  
  726.    ProcessWaitClose("LogonUI.exe")
  727.  
  728.    if (A_Args.Length = 0)
  729.        AddBufferedLatestClickMouseHotkeys()
  730.  
  731.    BufferKeyboardInputs(true,, () => (BufferKeyboardInputs(), BufferLatestClick())) ; Start buffering keys and let Ctrl+Alt+Del terminate both keyboard and mouse buffering
  732.    windowToActivate := WinExist("A") ; The currently active window gets reactivated in the end (only for any buffered keyboard input, the taskbar also gets activated on top if clicked)
  733.    HookEvent(EVENT_OBJECT_NAMECHANGE, HandleTabsOutlinerEvent)
  734. }
  735. else if (A_Args[1] = "--single")
  736. {
  737.    ToggleWinSize2()
  738.    AddBufferedLatestClickMouseHotkeys()
  739.    BufferKeyboardInputs(true,, () => (BufferKeyboardInputs(), BufferLatestClick())) ; Start buffering keys and let Ctrl+Alt+Del terminate both keyboard and mouse buffering
  740.    HookEvent(EVENT_OBJECT_NAMECHANGE, HandleTabsOutlinerEvent)
  741. }
  742. else if (A_Args[1] = "--duo")
  743. {
  744.    if (ProcessExist("chrome.exe"))
  745.    {
  746.        Run("chrome.exe --start-maximized --disable-features=GlobalMediaControls")
  747.        ExitApp()
  748.    }
  749.    else
  750.    {
  751.        ToggleWinSize2()
  752.        AddBufferedLatestClickMouseHotkeys()
  753.        BufferKeyboardInputs(true,, () => (BufferKeyboardInputs(), BufferLatestClick())) ; Start buffering keys and let Ctrl+Alt+Del terminate both keyboard and mouse buffering
  754.        HookEvent(EVENT_OBJECT_NAMECHANGE, HandleNewTabEvent)
  755.        HookEvent(EVENT_OBJECT_NAMECHANGE, HandleTabsOutlinerEvent)
  756.        SetTimer(OnTabsOutlinerTimeout, -7500)
  757.        Run("chrome.exe --start-maximized --disable-features=GlobalMediaControls")
  758.    }
  759. }
  760. else
  761.    throw ValueError("Parameter invalid, use either --single or --duo (unset and the experimental parameter is expanded single`nmode to be executed at startup)", -1, A_Args[1])
  762.  
  763. if (A_Args.Length = 0 || A_Args[1] = "--uninhibited-clicks" || A_Args[1] = "--single")
  764. {
  765.    if (ProcessExist("chrome.exe"))
  766.    {
  767.        HookEvent(EVENT_OBJECT_NAMECHANGE, HandleDisposableNewTabEvent)
  768.        SetTimer(() => OnTabsOutlinerTimeout(true), -7500)
  769.        Run("chrome.exe --new-window")
  770.  
  771.        HandleDisposableNewTabEvent(hWinEventHook, event, hWnd, *)
  772.        {
  773.            static isBeingUsed := false
  774.  
  775.            try
  776.                if (InStr(WinGetTitle(hWnd), "Google Chrome",, -1) && !isBeingUsed)
  777.                {
  778.                    isBeingUsed := true
  779.                    WinSetTransparent(0, hWnd)
  780.                    DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  781.                    TaskbarUtilities.DeleteTab(hWnd)
  782.                    disposableNewTabChrome.Id := hWnd
  783.  
  784.                    while (!WinExist("Tabs Outliner ahk_exe chrome.exe"))
  785.                        ControlSend("!x", hWnd), Sleep(100)
  786.                }
  787.        }
  788.    }
  789.    else
  790.        SetTimer(OnTabsOutlinerTimeout, -7500), Run("chrome.exe --silent-launch --start-maximized --disable-features=GlobalMediaControls")
  791. }
  792.  
  793. ;********** LIBRARY **********
  794.  
  795. OnTabsOutlinerTimeout(isShortcutUsed := false)
  796. {
  797.    if (tabsOutliner.IsBeingPrepared)
  798.        return
  799.  
  800.    BufferKeyboardInputs()
  801.    BufferLatestClick()
  802.  
  803.    if (isShortcutUsed)
  804.    {
  805.        WinClose(disposableNewTabChrome.Id)
  806.        WinActivate("ahk_exe chrome.exe")
  807.        Sleep(100)
  808.        Send("^tchrome://extensions/shortcuts{Enter}")
  809.        Sleep(100)
  810.        MsgBox("Go to the Tabs Outliner shortcuts and set Alt+X as the shortcut for `"Activate the extension`"",, "0x40000 Icon!")
  811.    }
  812.    else
  813.    {
  814.        Run("chrome.exe --app-id=eggkanocgddhmamlbiijnphhppkpkmkl")
  815.        MsgBox("Go to the GENERAL tab and put a checkmark next to:`n`"Open Tabs Outliner window on Chrome startup.`"",, "0x40000 Icon!")
  816.    }
  817.  
  818.    ExitApp()
  819. }
  820.  
  821. HandleNewTabEvent(hWinEventHook, event, hWnd, *)
  822. {
  823.    static isBeingDeactivated := false
  824.  
  825.    try
  826.        if (InStr(WinGetTitle(hWnd), "Google Chrome",, -1) && !isBeingDeactivated)
  827.        {
  828.            isBeingDeactivated := true
  829.            DllCall("Sleep", "UInt", 100) ; Necessary to make the deactivation work (this DllCall workaround prevents queued events to be handled in the meantime)
  830.            WinActivate("ahk_class Progman") ; Makes the window visually inactive straight away, instead of later when the window has already been visually active
  831.            DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  832.        }
  833. }
  834.  
  835. HandleTabsOutlinerEvent(hWinEventHook, event, hWnd, *)
  836. {
  837.    try shouldExecute := (WinGetTitle(hWnd) = "_crx_eggkanocgddhmamlbiijnphhppkpkmkl" || WinExist("Tabs Outliner ahk_exe chrome.exe ahk_id " hWnd)) && !tabsOutliner.IsBeingPrepared
  838.  
  839.    if (shouldExecute ?? false)
  840.    {
  841.        tabsOutliner.IsBeingPrepared := true
  842.        WinSetTransparent(0, hWnd)
  843.        DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  844.        HookEvent(EVENT_OBJECT_SHOW, HandleStatusBarEvent)
  845.        TaskbarUtilities.DeleteTab(hWnd)
  846.        WinWait("Tabs Outliner ahk_exe chrome.exe")
  847.        HookEvent(EVENT_OBJECT_NAMECHANGE, HandleDevToolsEvent, WinGetPID())
  848.        Sleep(100) ; Allows Tabs Outliner to properly load (otherwise the auto-scroll won't work)
  849.        WinActivate()
  850.        Send("{F12}")
  851.    }
  852.  
  853.    HandleStatusBarEvent(hWinEventHook, event, hWnd, *)
  854.    {
  855.        static isBeingHidden := false
  856.        titleMatchModePrevious := SetTitleMatchMode("RegEx")
  857.  
  858.        try
  859.            if (WinExist("^$ ahk_class Chrome_WidgetWin_1") && !isBeingHidden) ; Titleless chrome status bar (^ = start of line, $ = end of line)
  860.            {
  861.                isBeingHidden := true
  862.                WinHide()
  863.                DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  864.            }
  865.  
  866.        A_TitleMatchMode := titleMatchModePrevious
  867.    }
  868.  
  869.    HandleDevToolsEvent(hWinEventHook, event, hWnd, *)
  870.    {
  871.        static isBeingMadeTransparent := false
  872.        try shouldExecute := WinGetTitle(hWnd) = "DevToolsApp" && !isBeingMadeTransparent
  873.  
  874.        if (shouldExecute ?? false)
  875.        {
  876.            isBeingMadeTransparent := true
  877.            WinSetTransparent(0, hWnd)
  878.            DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  879.            TaskbarUtilities.DeleteTab(hWnd)
  880.            WinExist(hWnd)
  881.            Sleep(500)
  882.            Send("^``")
  883.            Sleep(500)
  884.            shouldDetectHiddenWindowsPrevious := DetectHiddenWindows(true)
  885.            ClipSend(interfaceImprovementsJS)
  886.            Sleep(500) ; Increasing this might make pasting more reliable
  887.            WinClose()
  888.  
  889.            if (disposableNewTabChrome.Id)
  890.                WinClose(disposableNewTabChrome.Id)
  891.  
  892.            A_DetectHiddenWindows := shouldDetectHiddenWindowsPrevious
  893.            tabsOutlinerId := WinExist("Tabs Outliner ahk_exe chrome.exe")
  894.            MoveAndResize()
  895.  
  896.            if (A_Args.Length = 0 || A_Args[1] = "--uninhibited-clicks" || A_Args[1] = "--duo")
  897.                WinMinimize()
  898.  
  899.            WinSetTransparent("Off")
  900.            TaskbarUtilities.AddTab(tabsOutlinerId)
  901.            TaskbarUtilities.Show()
  902.            ProcessWaitClose("userinit.exe") ; At this point all startup software is running
  903.            Sleep(100)
  904.            StopBufferingInputsAndReleaseOnRelevantWnd()
  905.  
  906.            if (A_Args.Length = 0 || A_Args[1] = "--uninhibited-clicks")
  907.                Run(RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run", "WinSize2"))
  908.            else
  909.                ToggleWinSize2() ; Unpausing WinSize2 now that it can no longer misbehave
  910.  
  911.            ExitApp()
  912.        }
  913.    }
  914. }
  915.  
  916. class TaskbarUtilities
  917. {
  918.    static HasDeactivateTimedOut => A_TickCount - this.StartTime > 900
  919.  
  920.    static __New()
  921.    {
  922.        this.IsInvisible := false
  923.        this.DeactivatedTaskbarY := A_ScreenHeight - 2
  924.        iid_ITaskbarList := "{56FDF342-FD6D-11d0-958A-006097C9A090}" ; Interface id (iid)
  925.        clsid_TaskbarList := "{56FDF344-FD6D-11d0-958A-006097C9A090}" ; Class id (clsid)
  926.        this.Tbl := ComObject(clsid_TaskbarList, iid_ITaskbarList) ; Creates the TaskbarList object
  927.  
  928.        loop (10)
  929.        {
  930.            try ComCall(3, this.Tbl) ; Calls this.Tbl.HrInit(), which initializes the TaskbarList object
  931.            catch
  932.                Sleep(50)
  933.            else
  934.                break
  935.        }
  936.    }
  937.  
  938.    ; To make it less bothersome by deactivating the taskbar
  939.    static ToggleDeactivateTimer()
  940.    {
  941.        static isEnabled := false
  942.        SetTimer(Deactivate, (isEnabled := !isEnabled) ? 30 : 0)
  943.  
  944.        Deactivate() => WinActivate("ahk_class Progman")
  945.    }
  946.  
  947.    static WaitDeactivate()
  948.    {
  949.        this.StartTime := A_TickCount
  950.        try WinGetPos(, &currentTaskbarY,,, "ahk_class Shell_TrayWnd")
  951.  
  952.        while ((currentTaskbarY ?? 0) != this.DeactivatedTaskbarY)
  953.        {
  954.            Sleep(10)
  955.            try WinGetPos(, &currentTaskbarY,,, "ahk_class Shell_TrayWnd")
  956.  
  957.            if (this.HasDeactivateTimedOut)
  958.                break
  959.        }
  960.  
  961.        this.ToggleDeactivateTimer()
  962.    }
  963.  
  964.    ; To prevent anything except the user from reactivating the taskbar
  965.    static MakeInvisible()
  966.    {
  967.        WinSetTransparent(0, "ahk_class Shell_TrayWnd")
  968.        this.IsInvisible := true
  969.        SetTimer(this._ShowOnHover := ObjBindMethod(this, "ShowOnHover"), 20)
  970.        Hotkey("~LWin", (*) => this.Show())
  971.    }
  972.  
  973.    static ShowOnHover()
  974.    {
  975.        try
  976.        {
  977.            MouseGetPos(, &currentCursorY)
  978.  
  979.            if (currentCursorY >= this.DeactivatedTaskbarY)
  980.                this.Show()
  981.        }
  982.    }
  983.  
  984.    static Show()
  985.    {
  986.        if (this.IsInvisible)
  987.        {
  988.            this.ToggleDeactivateTimer(), this.WaitDeactivate()
  989.            WinSetTransparent("Off", "ahk_class Shell_TrayWnd"), SetTimer(this._ShowOnHover, 0), Hotkey("~LWin", (*) => this.Show(), "Off"), this.IsInvisible := false
  990.        }
  991.    }
  992.  
  993.    static AddTab(winId) => ComCall(4, this.Tbl, "Ptr", winId) ; Calls this.Tbl.AddTab(winId), which adds a tab to the TaskbarList
  994.  
  995.    static DeleteTab(winId) => ComCall(5, this.Tbl, "Ptr", winId) ; Calls this.Tbl.DeleteTab(winId), which deletes a tab from the TaskbarList
  996. }
  997.  
  998. StopBufferingInputsAndReleaseOnRelevantWnd()
  999. {
  1000.    if (IsSet(windowToActivate))
  1001.        try WinActivate(windowToActivate), Sleep(200)
  1002.  
  1003.    BufferKeyboardInputs(, true) ; Stop buffering keys and sending them out
  1004.    BufferLatestClick(, true) ; Stop buffering the latest click and sending it out
  1005. }
  1006.  
  1007. ; Start buffering the latest left-, right- or double-click with dynamic mouse button hotkeys
  1008. AddBufferedLatestClickMouseHotkeys()
  1009. {
  1010.    static _ := InitializeWindowGroups()
  1011.  
  1012.    HotIf(MouseIsOverBlacklistedWindow)
  1013.    Hotkey("*LButton", (*) => BufferLatestClick(true,, true))
  1014.    Hotkey("*RButton", (*) => BufferLatestClick(true,, true))
  1015.    HotIf()
  1016.    Hotkey("*LButton", (*) => BufferLatestClick(true))
  1017.    Hotkey("*RButton", (*) => BufferLatestClick(true))
  1018.  
  1019.    InitializeWindowGroups()
  1020.    {
  1021.        ; Any of these that get clicked will be reactivated
  1022.        GroupAdd("Taskbar", "ahk_class Shell_TrayWnd") ; [Win10 & Win11] Main taskbar
  1023.        GroupAdd("Taskbar", "ahk_class Shell_SecondaryTrayWnd") ; [Win10 & Win11] Taskbar of 2nd monitor
  1024.  
  1025.        ; These will be blocked instead of postponed
  1026.        GroupAdd("Blacklist", "Start ahk_class Windows.UI.Core.CoreWindow") ; [Win10 & Win11] Start menu
  1027.        GroupAdd("Blacklist", "Search ahk_class Windows.UI.Core.CoreWindow") ; [Win10 & Win11] Windows Search
  1028.        GroupAdd("Blacklist", "Task View ahk_class Windows.UI.Core.CoreWindow") ; [Win10] Win+Tab window
  1029.        GroupAdd("Blacklist", "ahk_class MultitaskingViewFrame") ; [Win10] Alt+Tab window
  1030.        ;GroupAdd("Blacklist", "ahk_class TaskListThumbnailWnd") ; [Win10] Preview window (won't need this though b/c it won't become the foreground window)
  1031.        GroupAdd("Blacklist", "ahk_class XamlExplorerHostIslandWindow") ; [Win11] Alt+Tab window, Win+Tab window & Preview window
  1032.        GroupAdd("Blacklist", "ahk_class NotifyIconOverflowWindow") ; [Win10] Hidden icons tray window
  1033.        GroupAdd("Blacklist", "ahk_class TopLevelWindowForOverflowXamlIsland") ; [Win11] Hidden icons tray window
  1034.        GroupAdd("Blacklist", "ahk_exe ShellExperienceHost.exe") ; [Win10 & Win11] Network Connections window, Volume Control window, Date and Time Information window & Action center window
  1035.        GroupAdd("Blacklist", "ahk_class #32770") ; [Win10 & Win11] Any dialog box, such as the Properties window, Find window & MsgBox window
  1036.        ;GroupAdd("Blacklist", "ahk_class #32768") ; [Win10 & Win11] Right-click menu (won't need this with right-click buffering active)
  1037.        ;GroupAdd("Blacklist", "ahk_class WorkerW") ; [Win10 & Win11] Invisible worker window (overlays the desktop once Win+Tab gets used, desktop click gets buffered so no need for this)
  1038.    }
  1039. }
  1040.  
  1041. /**
  1042. * Buffering the latest left-, right- or double-click to send later. Use in mouse button hotkeys. By using `shouldSendBufferedClick` with its default value False, you can prevent it from
  1043. * being send out when you stop buffering the latest click
  1044. * @param {Integer} mode Toggle on/off
  1045. * @param {Integer} shouldSendBufferedClick Release buffered latest click when it stops buffering the latest click
  1046. * @param {Integer} isMouseOverBlacklistedWindow Ignore buffering when the latest click is on a blacklisted window
  1047. */
  1048. BufferLatestClick(mode := false, shouldSendBufferedClick := false, isMouseOverBlacklistedWindow := false)
  1049. {
  1050.    static cursorX, cursorY, taskbarToActivate, shouldRightClick := false, shouldDoubleClick := false
  1051.  
  1052.    if (!mode)
  1053.    {
  1054.        HotIf(MouseIsOverBlacklistedWindow)
  1055.        try Hotkey("*LButton", "Off")
  1056.        try Hotkey("*RButton", "Off")
  1057.        HotIf()
  1058.        try Hotkey("*LButton", "Off")
  1059.        try Hotkey("*RButton", "Off")
  1060.  
  1061.        if (shouldSendBufferedClick && IsSet(cursorX))
  1062.        {
  1063.            if (taskbarToActivate)
  1064.                Sleep(200), WinActivate(taskbarToActivate), Sleep(200)
  1065.  
  1066.            MouseGetPos(&previousCursorX, &previousCursorY)
  1067.  
  1068.            if (shouldRightClick)
  1069.                Send("{Click " cursorX " " cursorY " R}")
  1070.            else if (shouldDoubleClick)
  1071.                Send("{Click " cursorX " " cursorY " 2}")
  1072.            else
  1073.                Send("{Click " cursorX " " cursorY "}")
  1074.  
  1075.            Send("{Click " previousCursorX " " previousCursorY " 0}")
  1076.        }
  1077.  
  1078.        return
  1079.    }
  1080.  
  1081.    ; Any MsgBox window created by this script is allowed to be clicked b/c it'd otherwise prevent the thread from continuing, in which case the mouse could remain blocked
  1082.    if (MouseIsOver("ahk_class #32770 ahk_pid " WinGetPID(A_ScriptHwnd)))
  1083.    {
  1084.        Send(InStr(A_ThisHotkey, "LButton") ? "{LButton}" : "{RButton}")
  1085.  
  1086.        return
  1087.    }
  1088.  
  1089.    ; Show loading cursor until the script exits
  1090.    if (!IsSet(cursorX))
  1091.    {
  1092.        cursors := Map("Arrow", 0, "Hand", 0, "Help", 0, "IBeam", 0, "NWPen", 0, "SizeAll", 0, "SizeNESW", 0, "SizeNS", 0, "SizeNWSE", 0, "SizeWE", 0)
  1093.        OnExit((*) => (ResetCursor(), 0)) ; Lambda returns last value (non-zero avoids exit)
  1094.        OnError((*) => (ResetCursor(), 0)) ; Lambda returns last value (zero shows error)
  1095.  
  1096.        for (iteratedValueName in cursors)
  1097.        {
  1098.            cursors[iteratedValueName] := RegRead("HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  1099.            RegWrite("%SYSTEMROOT%\Cursors\aero_working.ani", "REG_EXPAND_SZ", "HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  1100.        }
  1101.  
  1102.        DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0)
  1103.  
  1104.        for (iteratedValueName, iteratedCursorFilePath in cursors)
  1105.            RegWrite(iteratedCursorFilePath, "REG_SZ", "HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  1106.    }
  1107.  
  1108.    if (isMouseOverBlacklistedWindow)
  1109.        return
  1110.  
  1111.    if (A_ThisHotkey = "*RButton")
  1112.        shouldRightClick := true, shouldDoubleClick := false
  1113.    else if (A_PriorHotkey = A_ThisHotkey && A_TimeSincePriorHotkey < 500)
  1114.        shouldDoubleClick := true, shouldRightClick := false
  1115.    else
  1116.        shouldDoubleClick := false, shouldRightClick := false
  1117.  
  1118.    MouseGetPos(&cursorX, &cursorY)
  1119.    taskbarToActivate := MouseIsOver("ahk_group Taskbar") ; Attempts to retrieve a clicked taskbar to activate later
  1120.  
  1121.    ResetCursor() => DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0)
  1122. }
  1123.  
  1124. MouseIsOver(winTitle, winText?, excludeTitle?, excludeText?) => (MouseGetPos(,, &winId), WinExist(winTitle " ahk_id " winId, winText?, excludeTitle?, excludeText?))
  1125. MouseIsOverBlacklistedWindow(*) => MouseIsOver("ahk_group Blacklist")
  1126.  
  1127. /**
  1128. * Buffering keyboard inputs to send later. By using `shouldSendBufferedkeys` with its default value False, you can prevent them from being send out when you stop buffering keys.
  1129. * If `mode` is the default value False, it returns all the buffered inputs as a string: bufferedkeys := BufferKeyboardInputs()
  1130. * @param {Integer} mode Toggle on/off
  1131. * @param {Integer} shouldSendBufferedkeys Release buffered keys when it stops buffering keys
  1132. * @param {() => String} terminationHotkeyFnObj Ctrl+Alt+Del is a termination hotkey which works while buffering is active (use this as a last resort to stop buffering keys or w/e)
  1133. * @returns {String} All the inputs that were being buffered
  1134. */
  1135. BufferKeyboardInputs(mode := false, shouldSendBufferedkeys := false, terminationHotkeyFnObj := () => BufferKeyboardInputs())
  1136. {
  1137.    static ih, inputs := ""
  1138.  
  1139.    if (!mode)
  1140.    {
  1141.        try ih.Stop()
  1142.        
  1143.        if (shouldSendBufferedkeys)
  1144.            Send(inputs)
  1145.        
  1146.        return inputs
  1147.    }
  1148.    else
  1149.        inputs := ""
  1150.  
  1151.    ih := InputHook("I1 L0 *")
  1152.    ih.NotifyNonText := true
  1153.    ih.VisibleNonText := false
  1154.    ih.OnKeyDown := (ih, VK, SC) => OnKey(ih, VK, SC, "Down")
  1155.    ih.OnKeyUp := (ih, VK, SC) => OnKey(ih, VK, SC, "Up")
  1156.    ih.KeyOpt("{All}", "N S")
  1157.    ih.Start()
  1158.  
  1159.    OnKey(ih, VK, SC, UD)
  1160.    {
  1161.        Critical()
  1162.        key := GetKeyName(Format("vk{1:x}sc{2:x}", VK, SC))
  1163.  
  1164.        if (key = "Delete" && GetKeyState("Ctrl", "P") && GetKeyState("Alt", "P"))
  1165.            inputs .= "{Ctrl up}{Alt up}", terminationHotkeyFnObj()
  1166.        else
  1167.            inputs .= Format("{{1} {2}}", key, UD)
  1168.    }
  1169. }
  1170.  
  1171. ClipSend(textToSend)
  1172. {
  1173.  clipPrevious := ClipboardAll()
  1174.  A_Clipboard := textToSend
  1175.  Send("{Ctrl down}")
  1176.  Sleep(100)
  1177.  WinActivate()
  1178.  ControlSend("v{Enter}")
  1179.  Send("{Ctrl up}")
  1180.  Sleep(250) ; Increasing this might make pasting more reliable
  1181.  A_Clipboard := clipPrevious
  1182. }
  1183.  
  1184. ; Uses the INI file of WinSize2 to fix Tabs Outliner (should be used while it's still invisible and looks better than WinSize2 doing it)
  1185. MoveAndResize()
  1186. {
  1187.    section := IniRead(A_AppData "\MagraSoft\WinSize2.INI", "WinSize"), linesSplit := StrSplit(section, "`n")
  1188.  
  1189.    for (iteratedLine in linesSplit)
  1190.        if (InStr(iteratedLine, "Tabs Outliner"))
  1191.            lineSplit := StrSplit(iteratedLine, ""), tabsOutlinerInfo := [lineSplit[2], lineSplit[3], lineSplit[4], lineSplit[5]]
  1192.  
  1193.    WinRestore(), WinMove(tabsOutlinerInfo[1], tabsOutlinerInfo[2], tabsOutlinerInfo[3], tabsOutlinerInfo[4])
  1194. }
  1195.  
  1196. ; Using ControlSetChecked to toggle the checkbox which can be found in the WinSize2 GUI that (de)activates WinSize2, this would make it possible for people to use the original WinSize2.
  1197. ; This is necessary to stop interference from the customized WinSize2, which discards event messages when A_IsPaused=1 (e.g. Tabs Outliner not always being minimized could otherwise happen)
  1198. ToggleWinSize2()
  1199. {
  1200.    A_DetectHiddenWindows := true
  1201.  
  1202.    ; Pause/unpause when the WinSize2 executable is running
  1203.    loop
  1204.    {
  1205.        ids := WinGetList("ahk_class AutoHotkey")
  1206.  
  1207.        for (iteratedId in ids)
  1208.            if (InStr(WinGetTitle(iteratedId), "WinSize2.EXE",, -1))
  1209.            {
  1210.                loop
  1211.                    try
  1212.                    {
  1213.                        ; The following is the same as the user having selected "Pause Script" from the tray menu (65306 = PAUSE, 65305 = SUSPEND)
  1214.                        SendMessage(0x0111, 65306,,, iteratedId,,,, 300)
  1215.  
  1216.                        return
  1217.                    }
  1218.                    catch (TimeoutError)
  1219.                        continue
  1220.            }
  1221.  
  1222.        Sleep(30)
  1223.                                                      ; [REMEMBER: BUFFERED INPUT WILL PREVENT NEW SCRIPT INSTANCES BUT NOT RIGHT AWAY]
  1224.         ; Runs WinSize2 if it's not detected within 4 seconds                        ; [IF THIS FN WAITS FOR THE STARTUP SCRIPT TO RUN WS2, IT'D CONTINUE IN WRONG SCOPE!
  1225.         ;if (A_Index = 135)                                      ; SO CONSIDER LOWER TIMEOUT OR CHECKING MODE HERE, OR PLACING RUN/RELOAD OUTSIDE FN]
  1226.            ;Run(RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run", "WinSize2")) ; MAYBE IT SHOULD RELOAD HERE INSTEAD, B/C IT SHOULD'VE EXECUTED
  1227.     }                                                             ; THE SIMPLE "RUN CHROME AND EXITAPP" SCOPE OF THE --DUO MODE, OR
  1228. }                                                             ; PERHAPS THE SIMILAR SIMPLE SCOPE OF THE --SINGLE MODE
  1229.  
  1230. HookEvent(event, fnObj, pid := 0) => DllCall("SetWinEventHook", "UInt", event, "UInt", event, "Ptr", 0, "Ptr", CallbackCreate(fnObj), "UInt", pid, "UInt", 0, "UInt", 0)
  1231.  
  1232. /********** TRASH: notes about WinSize2 for the script above **********/
  1233.  
  1234. /*
  1235. ToggleWinSize2() called from anything other than MTO startup mode basically waits until startup mode has finished executing, b/c it runs WinSize2 at the very end
  1236.  
  1237. so if the startup mode is never used or fails, then the script in other modes would not be able to continue in ToggleWinSize2() .. the startup mode did actually fail for me:
  1238. kb hook stayed on in newtab and TO remained invisible, however the latest buffered click scripts still had to be implemented so clicks can apparently interfere or something
  1239.  
  1240. [COMMENTED, CHECK COMMENTS]
  1241. I have now made it run WS2 when 4 seconds have passed in ToggleWinSize2() without toggling due to the WinSize2 process not existing (not sure if this is the best place to do it tho)
  1242.  
  1243. instead of ToggleWinSize2() waiting for WS2 to exist, I could maybe wait for a reply w/ SendMessage to the other MTO instance to check if the startup mode script is running
  1244.  
  1245.  
  1246. - make ToggleWinSize2() return execution when the reg entry doesn't exist
  1247. - make MoveAndResize() return execution when ...
  1248. - skip starting WS2 when the reg entry doesn't exist
  1249.  
  1250.  
  1251. [Actually it might be better to check if the INI file exists at all, if not then return already. Because this might also cause an error otherwise]
  1252. MoveAndResize() improvement:
  1253. Check if the used array variable is actually set, otherwise it will probably throw an error and then the cb will simply return execution due to the try:
  1254.  
  1255. WinRestore(), WinMove(
  1256. tabsOutlinerInfo[1], tabsOutlinerInfo[2], tabsOutlinerInfo[3], tabsOutlinerInfo[4])
  1257.  
  1258. Also check if the registry thing exists before using it to start WS2 in the event handler
  1259.  
  1260. [CHROME GETS MAXIMIZED, SO TABS OUTLINER WILL TOO AND THAT HAS TO FIXED BY EITHER THE WS2 INI OR HARDCODED MTO POS/SIZE, I CHOSE THE LATTER AND TO TAKE WS2 OUT OF MTO ENTIRELY)
  1261. [my customized WinSize2 is required now because apparently the ToggleWinSize2 method doesn't affect the original (only mine checks A_IsPaused)
  1262. I mean if ppl want to use WS2, they can only use my customized version, I should mention this in the docs
  1263. ofc make it possible to use MTO w/o WS2 in case other ppl have no window size/pos issues and therefore do not need WS2 at all]
  1264. This way I can let people use MTO without them being forced to use WS2 if they don't even need it
  1265.  
  1266.  
  1267. readme in github:
  1268.  
  1269. get WinSize2 and set it up for the tabs outliner window (fixes position and size)
  1270.  
  1271. the script should START WinSize2 AFTER IT'S DONE, then WinSize2 can no longer interfere (disable WinSize2 in the Startup tab in Task Manager)
  1272.             ^       ^      ^    ^    ^
  1273.  
  1274. You have to give the AHK script the responsibility to start WinSize2 after it has finished executing its main code
  1275.  
  1276. Give over responsibility from the Task Manager > Startup, to our AHK script
  1277.  
  1278.  
  1279. AUTOMATION FEATURE which I wanted to add to Time Saver:
  1280. Auto-run WinSize2 after a delay if disabled in the Startup tab of Task Manager
  1281.  
  1282.    ; Takes over the responsibility to run WinSize2 at an appropriate time if the app is disabled in the Startup tab of Task Manager (when it can no longer interfere with startup apps)
  1283.    try
  1284.    {
  1285.        startupAppStatus := RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32", "WinSize2")
  1286.  
  1287.        if (startupAppStatus != "020000000000000000000000")
  1288.        {
  1289.            ProcessWaitClose("userinit.exe") ; At this point all startup software is running
  1290.            Sleep(500) ; GOTTA TEST HOW LONG THIS SHOULD BE, BUT I'M GUESSING IT'S AROUND THIS MUCH
  1291.            Run(RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run", "WinSize2"))
  1292.        }
  1293.    }
  1294.  
  1295. but apparently this was not necessary because my customized WinSize2 already fixed the issue by using a different event,
  1296. and if that doesn't work after all then I can probably also just fix it in my customized WinSize2 by delaying itself (using the ProcessWaitClose and Sleep)
  1297.  
  1298. WinSize2 is distributed as an EXE file (compiled by AHK)
  1299.  
  1300. BE WARY OF THE ARROW SYMBOL DIFFERENCES
  1301. ➤ Download WinSize2 (https://sourceforge.net/projects/winsize2/files/latest/download)
  1302. ▶ Extract the zip content
  1303. ⯈ Start "WinSize2_Update.exe"
  1304. ⯈ Right-click the WinSize2 icon in the tray
  1305. ⯈ Click "Special Parameters"
  1306. ⯈ Click the "Special" tab
  1307. ⯈ Enable "Start WinSize2 with Login"
  1308. ⯈ Set "0" [msec] Show INI logo (0=do not show, RECOMMENDED)
  1309. ⯈ Click "OK" (to make its file path appear in the registry, so that my AHK script can start it instead)
  1310. ⯈ Open "Task Manager"
  1311. ⯈ Click the "Startup" tab
  1312. ⯈ Disable "WinSize2" (you're giving over the responsibility of starting it, so that it won't interfere)
  1313.  
  1314. If you happen to have a 2K monitor just like me (2560x1440), and also use uTorrent, then feel free to use my window configurations.
  1315. Right-click the WinSize2 icon in the tray > Click "Edit INI-File" > Add the following entries at the bottom:
  1316.  
  1317. [WinSize]
  1318. AWNr_1=Tabs Outliner-804941449300001100001Chrome_WidgetWin_1{Return}0Z
  1319.  
  1320.  
  1321. TitleTimer=10
  1322. Hotkey=^!/
  1323. Ctrl+Alt+Z (the default hotkey) is already used by Photoshop, so I had to set it to Ctrl+Alt+/
  1324. */
  1325.  
  1326. /********** TRASH: brainstorm notes about the installer for the script above compiled into an EXE (the necessary certificate shit made it too annoying) **********/
  1327.  
  1328. /*
  1329. can execute powershell commands from AHK or I could make the ahk-bat hybrid
  1330. I can make an EXE for the former option but I'm sure ppl appreciate the ahk-bat hybrid more b/c then they see exactly what it does
  1331. however, maybe keeping it secret what it does, to avoid them getting worried about commands they don't understand, could be good too
  1332. or somewhat secret? (having the source available in the repo with the rest, but an EXE for this in the release folder [b/c I bet many ppl don't even check the source])
  1333.  
  1334. the certificate needs to be renewed by a script that gets executed via task scheduler, every 10 years, to do so these 2 commands need to be executed first to remove the expired ones:
  1335.  
  1336. Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Subject -eq "CN=lorenzo.pappalettera@gmail.com" } | Remove-Item
  1337. Get-ChildItem Cert:\CurrentUser\Root | Where-Object { $_.Subject -eq "CN=lorenzo.pappalettera@gmail.com" } | Remove-Item
  1338.  
  1339. command (generate the key):
  1340.  
  1341. New-SelfSignedCertificate -DnsName lorenzo.pappalettera@gmail.com -Type CodeSigning -CertStoreLocation cert:\CurrentUser\My -NotAfter (Get-Date).AddYears(10)
  1342.  
  1343. output:
  1344.  
  1345.   PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\My
  1346.  
  1347. Thumbprint                                Subject
  1348. ----------                                -------
  1349. 390F7B9DBC5581457386AEDBB05531153086A1F9  CN=lorenzo.pappalettera@gmail.com
  1350.  
  1351.  
  1352. now there is a 390F7B9DBC5581457386AEDBB05531153086A1F9 file in shell:SystemCertificates (C:\Users\loren\AppData\Roaming\Microsoft\SystemCertificates\My\Certificates)
  1353. and a 3244FBC90DA3A02BD51122948FF516B1AC087FF0 file in shell:SystemCertificates (C:\Users\loren\AppData\Roaming\Microsoft\SystemCertificates\My\Keys)
  1354. this got added to the registry: Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\SystemCertificates\CA\Certificates\390F7B9DBC5581457386AEDBB05531153086A1F9
  1355. and I can see the lorenzo.pappalettera@gmail.com certificate in certmgr.msc > Personal > Certificates
  1356.  
  1357.  
  1358. command (export the certificate without the private key):
  1359.  
  1360. Export-Certificate -Cert (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)[0] -FilePath code_signing.crt
  1361.  
  1362. output:
  1363.  
  1364.    Directory: C:\WINDOWS\system32
  1365.  
  1366.  
  1367. Mode                 LastWriteTime         Length Name
  1368. ----                 -------------         ------ ----
  1369. -a----         6/28/2024   8:18 PM            849 code_signing.crt
  1370.  
  1371.  
  1372. now there is a code_signing.crt file in C:\Windows\System32
  1373.  
  1374.  
  1375. command (import it as a Root certificate authority), this triggers a Security Warning dialog asking "Do you want to install this certificate" with options [Yes] and [No] (click yes ofc):
  1376.  
  1377. Import-Certificate -FilePath .\code_signing.crt -Cert Cert:\CurrentUser\Root
  1378.  
  1379. output:
  1380.  
  1381.   PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root
  1382.  
  1383. Thumbprint                                Subject
  1384. ----------                                -------
  1385. 390F7B9DBC5581457386AEDBB05531153086A1F9  CN=lorenzo.pappalettera@gmail.com
  1386.  
  1387.  
  1388. now this has been added to the registry: Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\390F7B9DBC5581457386AEDBB05531153086A1F9
  1389. and I can see the lorenzo.pappalettera@gmail.com certificate in certmgr.msc > Trusted Root Certification Authorities > Certificates
  1390.  
  1391.  
  1392. command (sign the EXE):
  1393.  
  1394. Set-AuthenticodeSignature "C:\Program Files\Minimized Tabs Outliner\Minimized Tabs Outliner.exe" -Certificate (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)[0]
  1395.  
  1396. output:
  1397.  
  1398.    Directory: C:\Program Files\Minimized Tabs Outliner
  1399.  
  1400.  
  1401. SignerCertificate                         Status                                 Path
  1402. -----------------                         ------                                 ----
  1403. 390F7B9DBC5581457386AEDBB05531153086A1F9  Valid                                  Minimized Tabs Outliner.exe
  1404.  
  1405.  
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.  
  1412.  
  1413. (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)[0]
  1414.  
  1415. can most likely become:
  1416.  
  1417. Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Where-Object { $_.Subject -eq "CN=lorenzo.pappalettera@gmail.com" }
  1418.  
  1419.  
  1420.  
  1421.  
  1422. putting the ; symbol at the end of a command lets u add another command after it, so then you can execute all commands at once but you would still have to confirm some actions
  1423. so then it would be good to make the Security Warning window invisible with an event handler and then automatically accept it
  1424.  
  1425.  
  1426.  
  1427.  
  1428. doesn't matter where the EXE is btw, I think read somewhere that it needs to be in Program Files but that's not true (maybe it was for running as admin via task scheduler, idk)
  1429.  
  1430.  
  1431.  
  1432. task scheduler:
  1433.  
  1434. Program/script: "%ProgramFiles%\Minimized Tabs Outliner\Minimized Tabs Outliner.exe"
  1435. Add arguments (optional): blank
  1436. Start in (optional): blank
  1437.  
  1438.  
  1439.  
  1440. shell:::{1F3427C8-5C10-4210-AA03-2EE45287D668}
  1441.  
  1442. is the same as:
  1443. "C:\Users\loren\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned"
  1444.  
  1445.  
  1446.  
  1447. EVEN BETTER:
  1448.  
  1449. Access shortcuts pinned to the Start menu or Taskbar
  1450. shell:User Pinned
  1451. %AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\
  1452.  
  1453.  
  1454.  
  1455. misschien als ik ze normaal compiled doe, zonder UIA en dan via task scheduler 'm als admin doe. Dan als het via dubbelklik op taskbar icon opgestart moet worden,
  1456. laat hem een task runnen die 'm als admin doet. Dus gwn meerdere tasks met verschillende launch flags. Maar dan moet de run commands 'm niet als admin doen.
  1457. Meh teveel moeite om ervoor te zorgen dat admin geen problemen levert bij beide scripts
  1458.  
  1459. [Use Run("Explore " ..)]
  1460. For the MTO installer, open the folder in program files once it has finished?
  1461.  
  1462. [Use Run("Properties " ..)]
  1463. The other one can maybe be used to open the properties window on chrome and tabs outliner, the two files that cause it to be pinned to the taskbar,
  1464. making the properties window invisible and then navigating to the target input field, etc etc. Idk something like this maybe?
  1465.  
  1466. https://www.autohotkey.com/docs/v2/Program.htm#Installer_uiAccess
  1467. https://learn.microsoft.com/en-us/windows/msix/package/create-certificate-package-signing
  1468. https://learn.microsoft.com/en-us/powershell/module/pki/new-selfsignedcertificate?view=windowsserver2022-ps
  1469. https://stackoverflow.com/questions/84847/how-do-i-create-a-self-signed-certificate-for-code-signing-on-windows/51443366#51443366
  1470.  
  1471. https://github.com/drshajul/Autohotkey/blob/master/COM/Create%20Scheduled%20Task%20-%20On%20Boot.ahk
  1472. https://github.com/drshajul/Autohotkey/blob/master/COM/Create%20Scheduled%20Task%20-%20Time%20Trigger.ahk
  1473. https://www.autohotkey.com/board/topic/61042-create-a-scheduled-task-natively-ahk-l/
  1474.  
  1475. RunAsTask:
  1476. https://www.autohotkey.com/boards/viewtopic.php?t=84424
  1477. https://www.autohotkey.com/boards/viewtopic.php?t=4334
  1478. https://www.autohotkey.com/boards/viewtopic.php?f=83&t=119710
  1479.  
  1480. https://www.reddit.com/r/AutoHotkey/comments/2kcg1n/run_program_as_administrator/
  1481. https://www.autohotkey.com/board/topic/46526-run-as-administrator-xpvista7-a-isadmin-params-lib/
  1482.  
  1483. further down in this file is some trash about a task scheduler script that uses xml import!
  1484.  
  1485.  
  1486. AHK task scheduler script, providing a non-compiled and compiled "Minimized Tabs Outliner EXE Installer" script
  1487.  
  1488. [RESEARCH HOW TO COPY/EXTRACT FROM ARCHIVE PROGRAMMATICALLY W/ AHK AND THEN RESEARCH HOW TO MAKE AN EXECUTABLE ARCHIVE]
  1489. Make the two compiled scripts into an executable archive, so it's basically a folder with two .exe files and if you execute the archive,
  1490. it should start the installer which should then make sure it runs as admin (I think), then creating the program files folder and
  1491. then copies or extracts MTO.exe in there. Import task and then install the certificate with powershell (also via AHK ofcourse)
  1492.  
  1493. Provide the MTO.exe and Installer Archive.exe on github as seperate files, do not put them in an archive as well
  1494. |
  1495. Also not if the executable archive doesn't succeed and if it doesn't succeed, then it should first make the script run as admin (I think),
  1496. then use FileSelect to select the MTO.exe file if it cannot be found in A_ScriptDir, then creating the program files folder and moving
  1497. it in there. Import task and then install the certificate with powershell (also via AHK ofcourse)
  1498.  
  1499.  
  1500. [NVM, only put the exe+xml on the releases page, then in the repo you just see the source and I can mention about the standalone executable release not needing AutoHotkey to be installed on the device]
  1501. [Nvm, move the AHK script to a folder called Source, that makes more sense (WinSize2 does this as well) and place the exe in the root]
  1502. Another folder in the MTO repo called Compiled with the exe and a readme explaining that it's standalone executable that does not require the user to have AutoHotkey installed
  1503.  
  1504. Make another the task scheduler xml for the exe, have both folders get their relevant xml
  1505.  
  1506. Make a release that only contains the exe and the relevant xml
  1507.  
  1508.  
  1509. maybe this is useful for the installer script, I dunno: https://discord.com/channels/115993023636176902/1197266125558382733/1197266125558382733
  1510. Schedule a task to run the current AutoHotkey script at logon with optional admin privileges. Uses PowerShell to register the task. Requires a prompt to elevate the command to schedule the task,
  1511. but after that you won't see any further requests. This will only run upon logging into the current user account.
  1512. AhkRunAtLogon(AsAdmin := true) {
  1513.    AsAdmin := !!AsAdmin
  1514.    PsCommand := Format(
  1515.        "$Action = New-ScheduledTaskAction -Execute {1} -Argument {2};"
  1516.         "$Trigger = New-ScheduledTaskTrigger -AtLogon -User $Env:UserName;"
  1517.         "$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-Timespan -Seconds 0);"
  1518.         "$Principal = New-ScheduledTaskPrincipal -UserId $Env:UserName -LogonType 3 {3};"
  1519.         "$Definition = New-ScheduledTask -Action $Action -Principal $Principal -Trigger $Trigger -Settings $Settings;"
  1520.         "Register-Scheduledtask -Taskname {4} -InputObject $Definition;",
  1521.         "'" '"""' A_AhkPath '"""' "'",
  1522.         '"""' A_ScriptFullPath '"""',
  1523.         !AsAdmin ? "" : "-RunLevel Highest",
  1524.         "'AutoHotkey - " A_ScriptName "'"
  1525.     )
  1526.     RunWait('*RunAs powershell.exe -executionpolicy "bypass" -command "' PsCommand '"', A_WorkingDir, "Hide")
  1527. }
  1528.  
  1529. I also got something like this in the `Shell` folder, which might be useful for automating the two `User Pinned > Chrome File` properties:
  1530. OpenProperties(path) {
  1531.     shell := ComObject("shell.application")
  1532.     shell.namespace(0).parsename(path).invokeverb("Properties")
  1533. }
  1534. */
  1535.  
  1536. /******************** TRASH: BACKUP FROM BEFORE I CHANGED IT INTO A MULTI-PURPOSE SCRIPT ********************/
  1537.  
  1538. #Requires AutoHotkey 2.0
  1539. #SingleInstance Force ; For UI Access
  1540. #NoTrayIcon
  1541.  
  1542. ; To make certain things work even when an admin window becomes active
  1543. if (!InStr(A_AhkPath, "_UIA.exe"))
  1544. {
  1545.     Run("*UIAccess " A_ScriptFullPath)
  1546.     ExitApp()
  1547. }
  1548.  
  1549. Persistent()
  1550. interfaceImprovementsJS := "
  1551. (
  1552.    arrayHtml = document.getElementsByClassName(`"mainViewMessage`"); arrayHtml[0].parentNode.removeChild(arrayHtml[0]);
  1553.    arrayHtml = document.getElementsByClassName(`"winNTASC`"); arrayHtml[arrayHtml.length - 1].replaceChildren();
  1554.    window.scrollTo(0, document.body.scrollHeight - window.innerHeight - 1200)
  1555. )"
  1556. A_KeyDelay := -1 ; For pasting with ControlSend
  1557. A_WinDelay := -1
  1558. A_CoordModeMouse := "Screen"
  1559. EVENT_OBJECT_SHOW := 0x8002
  1560. EVENT_OBJECT_LOCATIONCHANGE := 0x800B
  1561. EVENT_OBJECT_NAMECHANGE := 0x800C
  1562.  
  1563. WinWait("ahk_class Progman") ; Gotta wait until it exists before activating it to deactivate the taskbar
  1564. TaskbarUtilities.ToggleDeactivateTimer()
  1565.  
  1566. Run(RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run", "WinSize2"),,, &pid)
  1567. HookEvent(EVENT_OBJECT_SHOW, HandleWinSize2Event, pid)
  1568. HookEvent(EVENT_OBJECT_LOCATIONCHANGE, HandleWinSize2Event, pid)
  1569. Sleep(200)
  1570. ToggleWinSize2()
  1571.  
  1572. HandleWinSize2Event(hWinEventHook, event, hWnd, *)
  1573. {
  1574.     try WinClose("ahk_class tooltips_class32 ahk_id " hWnd)
  1575. }
  1576.  
  1577. TaskbarUtilities.WaitDeactivate()
  1578.  
  1579. if (!TaskbarUtilities.HasDeactivateTimedOut)
  1580.     TaskbarUtilities.MakeInvisible()
  1581.  
  1582. if (WinActive("ahk_exe explorer.exe") && !WinActive("ahk_class CabinetWClass"))
  1583.     windowToActivate := "ahk_class Progman" ; Activating desktop in the end to prevent WinSize2 from trying to fix the position/size of a minimized window (keeps it minimized)
  1584. else
  1585.     windowToActivate := WinExist("A") ; The currently active window gets reactivated in the end
  1586.  
  1587. BufferInputs(true) ; Start buffering keys
  1588. HookEvent(EVENT_OBJECT_NAMECHANGE, HandleTabsOutlinerEvent)
  1589. Run("chrome.exe --silent-launch --start-maximized")
  1590.  
  1591. HandleTabsOutlinerEvent(hWinEventHook, event, hWnd, *)
  1592. {
  1593.     static isBeingMinimized := false
  1594.  
  1595.     try
  1596.         if (WinGetTitle(hWnd) = "_crx_eggkanocgddhmamlbiijnphhppkpkmkl" && !isBeingMinimized)
  1597.         {
  1598.             isBeingMinimized := true
  1599.             WinSetTransparent(0, hWnd)
  1600.             DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  1601.             HookEvent(EVENT_OBJECT_SHOW, HandleStatusBarEvent)
  1602. ;Thread("NoTimers")
  1603. ;Thread("Priority", 1)
  1604.             WinWait("Tabs Outliner ahk_exe chrome.exe")
  1605.             ProcessWaitClose("LogonUI.exe")
  1606.             WinActivate()
  1607.             Send("{End 2}{Esc}")
  1608.             HookEvent(EVENT_OBJECT_NAMECHANGE, HandleDevToolsEvent, WinGetPID())
  1609. ;Sleep(500)
  1610.             WinActivate()
  1611.             Send("{Esc}{F12}")
  1612.         }
  1613.  
  1614.     HandleStatusBarEvent(hWinEventHook, event, hWnd, *)
  1615.     {
  1616.         static isBeingHidden := false
  1617.         titleMatchModePrevious := SetTitleMatchMode("RegEx")
  1618.  
  1619.         try
  1620.             if (WinExist("^$ ahk_class Chrome_WidgetWin_1") && !isBeingHidden) ; Titleless chrome status bar (^ = start of line, $ = end of line)
  1621.             {
  1622.                 isBeingHidden := true
  1623.                 WinHide()
  1624.                 DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  1625.             }
  1626.  
  1627.         A_TitleMatchMode := titleMatchModePrevious
  1628.     }
  1629.  
  1630.     HandleDevToolsEvent(hWinEventHook, event, hWnd, *)
  1631.     {
  1632.         static isBeingMadeTransparent := false, errors := "Errors:"
  1633.  
  1634.         try
  1635.             if (WinGetTitle(hWnd) = "DevToolsApp" && !isBeingMadeTransparent)
  1636.             {
  1637.                 isBeingMadeTransparent := true
  1638.                 WinSetTransparent(0, hWnd)
  1639.                 DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
  1640.                 WinExist(hWnd)
  1641.                 Sleep(300)
  1642.                 WinHide()
  1643.                 Send("^``")
  1644.                 Sleep(500)
  1645.                 shouldDetectHiddenWindowsPrevious := DetectHiddenWindows(true)
  1646.                 ClipSend(interfaceImprovementsJS)
  1647.                 Sleep(500)
  1648.                 WinClose()
  1649.                 A_DetectHiddenWindows := shouldDetectHiddenWindowsPrevious
  1650.  
  1651.                 WinExist("Tabs Outliner ahk_exe chrome.exe")
  1652.                 MoveAndResize()
  1653. ;Sleep(200)
  1654.                 WinMinimize()
  1655. ;WinWaitNotActive(,, 2) ; Use this if the window becomes opaque before the minimize animation finishes
  1656.                 WinSetTransparent("Off")
  1657. /*
  1658. instead of the two lines above, only for the multi-purpose / launch parameter / merged version of this script (the next 'Create' commit)
  1659. if (A_Args.length = 0)
  1660.     WinMinimize(), WinSetTransparent("Off")
  1661. */
  1662.                 Sleep(200)
  1663.                 WinHide()
  1664.                 Sleep(100)
  1665.                 WinShow()
  1666.                 TaskbarUtilities.Show()
  1667.                 ProcessWaitClose("userinit.exe") ; At this point all startup software is running
  1668.                 Sleep(100)
  1669.                 WinActivate(WinExist(windowToActivate) ? windowToActivate : "ahk_class Progman")
  1670.                 Sleep(200)
  1671.                 BufferInputs(, true) ; Stop buffering keys and sending them out
  1672.                 ToggleWinSize2() ; Unpausing WinSize2 now that it can no longer misbehave at startup
  1673. /*
  1674. only for the multi-purpose / launch parameter / merged version of this script (the next 'Create' commit)
  1675. ; These scopes are executed late b/c there is no other workaround to prevent WinSize2 from affecting Tabs Outliner in these modes
  1676. if (A_Args.length > 0)
  1677. {
  1678.     if (A_Args[1] = "--duo")
  1679.     {
  1680.         Sleep(1000)
  1681.         WinMinimize()
  1682.         WinSetTransparent("Off")
  1683.     }
  1684.     else if (A_Args[1] = "--single")
  1685.         WinSetTransparent("Off")
  1686. }
  1687. */
  1688.                 Sleep(8000) ; To get rid of the WinSize2 ToolTip
  1689.                 ExitApp()
  1690.             }
  1691.         catch (as error)  ; Handles the first error thrown by the block above
  1692.             Tooltip(errors .= "`n" error.Message "`t" error.What "`t" error.Line "`t" error.Stack)
  1693.     }
  1694. }
  1695.  
  1696. ;********** LIBRARY **********
  1697.  
  1698. class TaskbarUtilities
  1699. {
  1700.     static HasDeactivateTimedOut => A_TickCount - this.StartTime > 900
  1701.  
  1702.     static __New() => (this.IsInvisible := false, this.DeactivatedTaskbarY := A_ScreenHeight - 2)
  1703.  
  1704.     ; To make it less bothersome by deactivating the taskbar
  1705.     static ToggleDeactivateTimer()
  1706.     {
  1707.         static isEnabled := false
  1708.         SetTimer(Deactivate, (isEnabled := !isEnabled) ? 30 : 0)
  1709.  
  1710.         Deactivate() => WinActivate("ahk_class Progman")
  1711.     }
  1712.  
  1713.     static WaitDeactivate()
  1714.     {
  1715.         this.StartTime := A_TickCount, WinGetPos(, &currentTaskbarY,,, "ahk_class Shell_TrayWnd")
  1716.  
  1717.         while (currentTaskbarY != this.DeactivatedTaskbarY)
  1718.         {
  1719.             Sleep(10)
  1720.             WinGetPos(, &currentTaskbarY,,, "ahk_class Shell_TrayWnd")
  1721.  
  1722.             if (this.HasDeactivateTimedOut)
  1723.                 break
  1724.         }
  1725.  
  1726.         this.ToggleDeactivateTimer()
  1727.     }
  1728.  
  1729.     ; To prevent anything except the user from reactivating the taskbar
  1730.     static MakeInvisible()
  1731.     {
  1732.         WinSetTransparent(0, "ahk_class Shell_TrayWnd")
  1733.         this.IsInvisible := true
  1734.         SetTimer(this._ShowOnHover := ObjBindMethod(this, "ShowOnHover"), 20)
  1735.         Hotkey("~LWin", (*) => this.Show())
  1736.     }
  1737.  
  1738.     static ShowOnHover()
  1739.     {
  1740.         MouseGetPos(, &currentCursorY)
  1741.  
  1742.         if (currentCursorY >= this.DeactivatedTaskbarY)
  1743.             this.Show()
  1744.     }
  1745.  
  1746.     static Show()
  1747.     {
  1748.         if (this.IsInvisible)
  1749.         {
  1750.             this.ToggleDeactivateTimer(), this.WaitDeactivate()
  1751.             WinSetTransparent("Off", "ahk_class Shell_TrayWnd"), SetTimer(this._ShowOnHover, 0), Hotkey("~LWin", (*) => this.Show(), "Off"), this.IsInvisible := false
  1752.         }
  1753.     }
  1754. }
  1755.  
  1756. /*
  1757.  * Buffering keyboard inputs to send later. if `shouldSendBufferedkeys` is false, it returns all the inputs that were being buffered.
  1758.  * [Unused feature] stop buffering keys but not sending them out. It returns all the buffered inputs as a string: bufferedkeys := BufferInputs()
  1759.  * @param {number} mode Toggle on/off
  1760.  * @param {number} shouldSendBufferedkeys Release buffered keys when it stops buffering keys
  1761.  * @returns {string} All the inputs that were being buffered
  1762.  */
  1763. BufferInputs(mode := false, shouldSendBufferedkeys := false)
  1764. {
  1765.     static ih, inputs := ""
  1766.  
  1767.     if (!mode)
  1768.     {
  1769.         try ih.Stop()
  1770.        
  1771.         if (shouldSendBufferedkeys)
  1772.             Send(inputs)
  1773.        
  1774.         return inputs
  1775.     }
  1776.     else
  1777.         inputs := ""
  1778.  
  1779.     ih                := InputHook("I1 L0 *")
  1780.     ih.NotifyNonText  := true
  1781.     ih.VisibleNonText := false
  1782.     ih.OnKeyDown      := OnKey.Bind(,,, "Down")
  1783.     ih.OnKeyUp        := OnKey.Bind(,,, "Up")
  1784.     ih.KeyOpt("{All}", "N S")
  1785.     ih.Start()
  1786.  
  1787.     OnKey(ih, VK, SC, UD) => (Critical(), inputs .= Format("{{1} {2}}", GetKeyName(Format("vk{1:x}sc{2:x}", VK, SC)), UD))
  1788. }
  1789.  
  1790. ClipSend(textToSend)
  1791. {
  1792.   clipPrevious := ClipboardAll()
  1793.   A_Clipboard := textToSend
  1794.   Send("{Ctrl down}")
  1795.   Sleep(100)
  1796.   WinActivate()
  1797.   ControlSend("v{Enter}")
  1798.   Send("{Ctrl up}")
  1799.   Sleep(250)
  1800.   A_Clipboard := clipPrevious
  1801. }
  1802.  
  1803. ; Uses the INI file of WinSize2 to fix tabs outliner (should be used while it's still invisible and looks better than WinSize2 doing it)
  1804. MoveAndResize()
  1805. {
  1806.     section := IniRead(A_AppData "\MagraSoft\WinSize2.INI", "WinSize"), linesSplit := StrSplit(section, "`n")
  1807.  
  1808.     for (iteratedLine in linesSplit)
  1809.         if (InStr(iteratedLine, "Tabs Outliner"))
  1810.             lineSplit := StrSplit(iteratedLine, ""), tabsOutlinerInfo := [lineSplit[2], lineSplit[3], lineSplit[4], lineSplit[5]]
  1811.  
  1812.     WinRestore(), WinMove(tabsOutlinerInfo[1], tabsOutlinerInfo[2], tabsOutlinerInfo[3], tabsOutlinerInfo[4])
  1813. }
  1814.  
  1815. ; This is necessary to stop interference from WinSize2 AHK scripts (e.g. tabs outliner not always being minimized could otherwise happen)
  1816. ToggleWinSize2()
  1817. {
  1818.     A_DetectHiddenWindows := true
  1819.  
  1820.     ; Pause/unpause when the main WinSize2 AHK script is running
  1821.     loop
  1822.     {
  1823.         ids := WinGetList("ahk_class AutoHotkey")
  1824.  
  1825.         for (iteratedId in ids)
  1826.             if (InStr(WinGetTitle(iteratedId), "WinSize2.EXE",, -1))
  1827.             {
  1828.                 loop
  1829.                     try
  1830.                     {
  1831.                         ; The following is the same as the user having selected "Pause Script" from the tray menu (65306 = PAUSE, 65305 = SUSPEND)
  1832.                         SendMessage(0x0111, 65306,,, iteratedId,,,, 300)
  1833.  
  1834.                         return
  1835.                     }
  1836.                     catch (TimeoutError)
  1837.                         continue
  1838.             }
  1839.  
  1840.         Sleep(30)
  1841.     }
  1842. }
  1843.  
  1844. HookEvent(event, fnObj, pid := 0) => DllCall("SetWinEventHook", "UInt", event, "UInt", event, "Ptr", 0, "Ptr", CallbackCreate(fnObj), "UInt", pid, "UInt", 0, "UInt", 0)
  1845.  
  1846. /******************** TRASH: "HotIf( Mouse_Is_ Over_Taskbar ).ahk" which can probably be deleted now, not sure ********************/
  1847.  
  1848. #Requires AutoHotkey 2.0
  1849.  
  1850. HotIf(MouseIsOverTaskbar)
  1851. Hotkey("*LButton", (*) => (BufferLatestClick(), windowToActivate := "ahk_class Shell_TrayWnd"))
  1852. HotIf()
  1853. Hotkey("*LButton", (*) => BufferLatestClick())
  1854.  
  1855. ;********** LIBRARY **********
  1856.  
  1857. MouseIsOver(winTitle, winText?, excludeTitle?, excludeText?) => (MouseGetPos(,, &winId), winId = WinExist(winTitle, winText?, excludeTitle?, excludeText?))
  1858. MouseIsOverTaskbar(*) => MouseIsOver("ahk_class Shell_TrayWnd")
  1859.  
  1860. /******************** TRASH: "topWnd behind sysWnd.ahk" which can probably be deleted now, not sure ********************/
  1861.  
  1862. #Requires AutoHotkey v2
  1863.  
  1864. GroupAdd("SysWnd", "ahk_class Shell_TrayWnd") ; [Win10 & Win11] Main taskbar
  1865. GroupAdd("SysWnd", "ahk_class Shell_SecondaryTrayWnd") ; [Win10 & Win11] Taskbar of 2nd monitor
  1866. GroupAdd("SysWnd", "Search ahk_class Windows.UI.Core.CoreWindow") ; [Win10 & Win11] Start menu & Windows Search
  1867. GroupAdd("SysWnd", "Task View ahk_class Windows.UI.Core.CoreWindow") ; [Win10] Win+Tab window
  1868. GroupAdd("SysWnd", "ahk_class MultitaskingViewFrame") ; [Win10] Alt+Tab window
  1869. ;GroupAdd("SysWnd", "ahk_class TaskListThumbnailWnd") ; [Win10] Preview window (won't need this though b/c it won't become the foreground window)
  1870. GroupAdd("SysWnd", "ahk_class XamlExplorerHostIslandWindow") ; [Win11] Alt+Tab window, Win+Tab window & Preview window
  1871. GroupAdd("SysWnd", "ahk_class NotifyIconOverflowWindow") ; [Win10] Hidden icons tray window
  1872. GroupAdd("SysWnd", "ahk_class TopLevelWindowForOverflowXamlIsland") ; [Win11] Hidden icons tray window
  1873. GroupAdd("SysWnd", "ahk_exe ShellExperienceHost.exe") ; [Win10 & Win11] Network Connections window, Volume Control window, Date and Time Information window & Action center window
  1874. GroupAdd("SysWnd", "ahk_class #32770") ; [Win10 & Win11] Any dialog box, such as the Properties window, Find window & MsgBox window
  1875. ;GroupAdd("SysWnd", "ahk_class #32768") ; [Win10 & Win11] Right-click menu (won't need this with right-click buffering active)
  1876. GroupAdd("SysWnd", "ahk_class WorkerW") ; [Win10 & Win11] Invisible worker window
  1877.  
  1878. F4::ShowTopWnd()
  1879. ;*LButton::ShowTopWnd() ; no error
  1880. ;*RButton::ShowTopWnd() ; no error
  1881. ;~*LButton::ShowTopWnd() ; not found error! maybe the window stops existing, like msgbox
  1882. ;~*RButton::ShowTopWnd() ; not found error! maybe the window stops existing, like right-click window
  1883. F5::ExitApp()
  1884. F6::Reload()
  1885.  
  1886. ShowTopWnd() ; CHANGE ALL "hWnd" INSTANCES OF FOR LOOP TO "iteratedId" ?? to stay consistent with my other scripts..
  1887. {
  1888.     ;if (WinActive("ahk_group SysWnd")) ; what if I just always executed this scope and got rid of the SysWnd check and the else scope which can get the not found error
  1889.     {                   ; OK DO THAT, BUT PERHAPS THE GROUP CAN BE USED FOR SOMETHING ELSE (HOWEVER IF NO USE-CASE COMES TO MIND, THEN PUT IT IN THE TRASH MTO.ahk COMMIT)
  1890.         topWnd := ""
  1891.         WS_CAPTION := 0xC00000 ; title bar
  1892.  
  1893.         for (hWnd in WinGetList())
  1894.             if (!WinActive(topWnd := hWnd) && WinGetMinMax(topWnd) != -1 && (WinGetClass(topWnd) = "Progman" ? true : WinGetStyle(topWnd) & WS_CAPTION) && WinGetTitle(topWnd) != "")
  1895.                 break
  1896.  
  1897.         MsgBox("1) " WinGetTitle(topWnd) " ahk_class " WinGetClass(topWnd))
  1898.     }
  1899.     ;else
  1900.         ;MsgBox("2) " WinGetTitle(WinExist("A")) " ahk_class " WinGetClass(WinExist("A")))
  1901. }
  1902.  
  1903. /******************** TRASH: "taskbar pos up.txt" which can probably be deleted now, not sure ********************/
  1904.  
  1905. ON CLICK WHILE BUFFERING IS IN PROGRESS: is taskbar up (doesn't have to be active to be up btw and for some it is always up), then activate taskbar before releasing buffered click
  1906. the taskbar likely won't be active while- and b/c MTO.ahk is doing stuff, so no need to worry/think about that.. just check if the taskbar is up and the (non-control) click will be fine
  1907.  
  1908. what if search window is up and user types, will it end up being typed into the foreground window that's behind both the search window and the taskbar
  1909. gotta prevent that, if the search window was active when windowToActivate got set then just make it block/discard keyboard input instead of releasing it
  1910. but still activate the foreground window that's behind both the search window and the taskbar
  1911.  
  1912. /******************** TRASH: "Buffer Latest Click.ahk" which can probably be deleted now, not sure ********************/
  1913.  
  1914. #Requires AutoHotkey 2.0
  1915. CoordMode("Mouse", "Screen")
  1916. F4::
  1917. {   ; START BUFFERING LATEST CLICK
  1918.     Hotkey("*LButton", (*) => BufferLatestClick())
  1919.     Hotkey("*RButton", (*) => BufferLatestClick())
  1920. }
  1921. F5::BufferLatestClick(true), Reload()
  1922.  
  1923. ; Left-, right- or double-click
  1924. BufferLatestClick(shouldSendBufferedClick := false)
  1925. {
  1926.     static cursorX, cursorY, shouldRightClick := false, shouldDoubleClick := false
  1927.  
  1928.     if (shouldSendBufferedClick)
  1929.     {
  1930.         ;if (IsSet(cursorX) && shouldActivateTaskbar)
  1931.             ;Sleep(200), WinActivate("ahk_class Shell_TrayWnd"), Sleep(200)
  1932.  
  1933.         try Hotkey("*LButton", "Off")
  1934.         try Hotkey("*RButton", "Off")
  1935.         MouseGetPos(&previousCursorX, &previousCursorY)
  1936.  
  1937.         if (shouldRightClick)
  1938.             Send("{Click " cursorX " " cursorY " R}")
  1939.         else if (shouldDoubleClick)
  1940.             Send("{Click " cursorX " " cursorY " 2}")
  1941.         else
  1942.             try Send("{Click " cursorX " " cursorY "}")
  1943.  
  1944.         Send("{Click " previousCursorX " " previousCursorY " 0}")
  1945.     }
  1946.     else
  1947.     {
  1948.         ; Show loading cursor
  1949.         if (!IsSet(cursorX))
  1950.         {
  1951.             cursors := Map("Arrow", 0, "Hand", 0, "Help", 0, "IBeam", 0, "NWPen", 0, "SizeAll", 0, "SizeNESW", 0, "SizeNS", 0, "SizeNWSE", 0, "SizeWE", 0)
  1952.             OnExit((*) => (DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0), 0)) ; Lambda returns last value (non-zero avoids exit)
  1953.  
  1954.             for (iteratedValueName in cursors)
  1955.             {
  1956.                 cursors[iteratedValueName] := RegRead("HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  1957.                 RegWrite("%SYSTEMROOT%\Cursors\aero_working.ani", "REG_EXPAND_SZ", "HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  1958.             }
  1959.  
  1960.             DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0)
  1961.  
  1962.             for (iteratedValueName, iteratedCursorFilePath in cursors)
  1963.                 RegWrite(iteratedCursorFilePath, "REG_SZ", "HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  1964.         }
  1965.  
  1966.         if (A_ThisHotkey = "*RButton")
  1967.             shouldRightClick := true, shouldDoubleClick := false
  1968.         else if (A_PriorHotkey = A_ThisHotkey && A_TimeSincePriorHotkey < 500)
  1969.             shouldDoubleClick := true, shouldRightClick := false
  1970.         else
  1971.             shouldDoubleClick := false, shouldRightClick := false
  1972.  
  1973.         MouseGetPos(&cursorX, &cursorY)
  1974.     }
  1975. }
  1976.  
  1977. /******************** TRASH: "IMPLEMENTED Buffer Latest Click - Copy.ahk" which can probably be deleted now, not sure ********************/
  1978.  
  1979. #Requires AutoHotkey 2.0
  1980. A_CoordModeMouse := "Screen"
  1981.  
  1982. GroupAdd("Taskbar", "ahk_class Shell_TrayWnd") ; [Win10 & Win11] Main taskbar
  1983. GroupAdd("Taskbar", "ahk_class Shell_SecondaryTrayWnd") ; [Win10 & Win11] Taskbar of 2nd monitor
  1984.  
  1985. GroupAdd("Blacklist", "Start ahk_class Windows.UI.Core.CoreWindow") ; [Win10 & Win11] Start menu
  1986. GroupAdd("Blacklist", "Search ahk_class Windows.UI.Core.CoreWindow") ; [Win10 & Win11] Windows Search
  1987. GroupAdd("Blacklist", "Task View ahk_class Windows.UI.Core.CoreWindow") ; [Win10] Win+Tab window
  1988. GroupAdd("Blacklist", "ahk_class MultitaskingViewFrame") ; [Win10] Alt+Tab window
  1989. ;GroupAdd("Blacklist", "ahk_class TaskListThumbnailWnd") ; [Win10] Preview window (won't need this though b/c it won't become the foreground window)
  1990. GroupAdd("Blacklist", "ahk_class XamlExplorerHostIslandWindow") ; [Win11] Alt+Tab window, Win+Tab window & Preview window
  1991. GroupAdd("Blacklist", "ahk_class NotifyIconOverflowWindow") ; [Win10] Hidden icons tray window
  1992. GroupAdd("Blacklist", "ahk_class TopLevelWindowForOverflowXamlIsland") ; [Win11] Hidden icons tray window
  1993. GroupAdd("Blacklist", "ahk_exe ShellExperienceHost.exe") ; [Win10 & Win11] Network Connections window, Volume Control window, Date and Time Information window & Action center window
  1994. GroupAdd("Blacklist", "ahk_class #32770") ; [Win10 & Win11] Any dialog box, such as the Properties window, Find window & MsgBox window
  1995. ;GroupAdd("Blacklist", "ahk_class #32768") ; [Win10 & Win11] Right-click menu (won't need this with right-click buffering active)
  1996. ;GroupAdd("Blacklist", "ahk_class WorkerW") ; [Win10 & Win11] Invisible worker window (overlays the desktop once Win+Tab gets used, a desktop click should be buffered so I won't need this)
  1997.  
  1998. F4::
  1999. {   ; START BUFFERING LATEST CLICK
  2000.     HotIf(MouseIsOverBlacklistedWindow)
  2001.     Hotkey("*LButton", (*) => BufferLatestClick(, true))
  2002.     Hotkey("*RButton", (*) => BufferLatestClick(, true))
  2003.     HotIf(MouseIsOverTaskbar)
  2004.     Hotkey("*LButton", (*) => BufferLatestClick(,, true))
  2005.     Hotkey("*RButton", (*) => BufferLatestClick(,, true))
  2006.     HotIf()
  2007.     Hotkey("*LButton", (*) => BufferLatestClick())
  2008.     Hotkey("*RButton", (*) => BufferLatestClick())
  2009. }
  2010. F5::BufferLatestClick(true), Reload()
  2011.  
  2012. ; Left-, right- or double-click
  2013. BufferLatestClick(shouldSendBufferedClick := false, isMouseOverBlacklistedWindow := false, isMouseOverTaskbar := false)
  2014. {
  2015.     static cursorX, cursorY, shouldRightClick := false, shouldDoubleClick := false, shouldActivateTaskbar := false
  2016.  
  2017.     if (shouldSendBufferedClick && IsSet(cursorX))
  2018.     {
  2019.         if (shouldActivateTaskbar)
  2020.             Sleep(200), WinActivate("ahk_class Shell_TrayWnd"), Sleep(200)
  2021.  
  2022.         HotIf(MouseIsOverBlacklistedWindow)
  2023.         Hotkey("*LButton", "Off")
  2024.         Hotkey("*RButton", "Off")
  2025.         HotIf(MouseIsOverTaskbar)
  2026.         Hotkey("*LButton", "Off")
  2027.         Hotkey("*RButton", "Off")
  2028.         HotIf()
  2029.         Hotkey("*LButton", "Off")
  2030.         Hotkey("*RButton", "Off")
  2031.  
  2032.         MouseGetPos(&previousCursorX, &previousCursorY)
  2033.  
  2034.         if (shouldRightClick)
  2035.             Send("{Click " cursorX " " cursorY " R}")
  2036.         else if (shouldDoubleClick)
  2037.             Send("{Click " cursorX " " cursorY " 2}")
  2038.         else
  2039.             Send("{Click " cursorX " " cursorY "}")
  2040.  
  2041.         Send("{Click " previousCursorX " " previousCursorY " 0}")
  2042.     }
  2043.     else if (isMouseOverBlacklistedWindow)
  2044.         return
  2045.     else
  2046.     {
  2047.         ; Show loading cursor
  2048.         if (!IsSet(cursorX))
  2049.         {
  2050.             cursors := Map("Arrow", 0, "Hand", 0, "Help", 0, "IBeam", 0, "NWPen", 0, "SizeAll", 0, "SizeNESW", 0, "SizeNS", 0, "SizeNWSE", 0, "SizeWE", 0)
  2051.             OnExit((*) => (DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0), 0)) ; Lambda returns last value (non-zero avoids exit)
  2052.  
  2053.             for (iteratedValueName in cursors)
  2054.             {
  2055.                 cursors[iteratedValueName] := RegRead("HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  2056.                 RegWrite("%SYSTEMROOT%\Cursors\aero_working.ani", "REG_EXPAND_SZ", "HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  2057.             }
  2058.  
  2059.             DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS := 0x0057, "UInt", 0, "Ptr", 0, "UInt", 0)
  2060.  
  2061.             for (iteratedValueName, iteratedCursorFilePath in cursors)
  2062.                 RegWrite(iteratedCursorFilePath, "REG_SZ", "HKEY_CURRENT_USER\Control Panel\Cursors", iteratedValueName)
  2063.         }
  2064.  
  2065.         if (A_ThisHotkey = "*RButton")
  2066.             shouldRightClick := true, shouldDoubleClick := false
  2067.         else if (A_PriorHotkey = A_ThisHotkey && A_TimeSincePriorHotkey < 500)
  2068.             shouldDoubleClick := true, shouldRightClick := false
  2069.         else
  2070.             shouldDoubleClick := false, shouldRightClick := false
  2071.  
  2072.         MouseGetPos(&cursorX, &cursorY)
  2073.         shouldActivateTaskbar := isMouseOverTaskbar
  2074.     }
  2075. }
  2076.  
  2077. ;********** LIBRARY **********
  2078.  
  2079. MouseIsOver(winTitle, winText?, excludeTitle?, excludeText?) => (MouseGetPos(,, &winId), WinExist(winTitle " ahk_id " winId, winText?, excludeTitle?, excludeText?))
  2080. MouseIsOverTaskbar(*) => MouseIsOver("ahk_group Taskbar")
  2081. MouseIsOverBlacklistedWindow(*) => MouseIsOver("ahk_group Blacklist")
  2082.  
  2083. /******************** TRASH: "maybe test the code that can import task unless if I was gonna do it with a batch script but compiled ahk installer script is surely fine too.ahk" ********************/
  2084.  
  2085. ; Find AutoHotkey Dash in your start menu > AutoHotkey Launch Config > Enable UI Access for AHK v2 (necessary to make it work when clicking preview windows and when Task Manager is focused)
  2086. #Requires AutoHotkey 2.0.5
  2087. #NoTrayIcon
  2088. ProcessSetPriority("High")
  2089. Persistent()
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098. RunAsTask(SingleInstance := 0, Shortcut := "") ; RunAsTask() v0.23 - Auto-elevates script without UAC prompt
  2099. {                                              ;    By SKAN for ah2 on D67M/D683 @ autohotkey.com/r?t=119710
  2100.     Global A_Args
  2101.  
  2102.     Local  TaskSchd,  TaskRoot,  TaskName,  RunAsTask,  TaskExists
  2103.         ,  CmdLine,  PathCrc,  Args,  XML,  AhkPath,  Description
  2104.         ,  STMM  :=  A_TitleMatchMode
  2105.         ,  DHW   :=  A_DetectHiddenWindows
  2106.         ,  SWD   :=  A_WinDelay
  2107.         ,  QUO   :=  '"'
  2108.  
  2109.    A_TitleMatchMode      :=  1
  2110.    A_DetectHiddenWindows :=  1
  2111.    A_WinDelay            :=  0
  2112.  
  2113.    Try    TaskSchd  :=  ComObject("Schedule.Service")
  2114.      ,    TaskSchd.Connect()
  2115.      ,    TaskRoot  :=  TaskSchd.GetFolder("\")
  2116.    Catch
  2117.           Return
  2118.  
  2119.    Loop Files A_AhkPath
  2120.         AhkPath  :=  A_LoopFileFullPath
  2121.  
  2122.    CmdLine  :=  A_IsCompiled ? QUO A_ScriptFullpath QUO :  QUO AhkPath QUO A_Space QUO A_ScriptFullpath QUO
  2123.    PathCrc  :=  DllCall("ntdll\RtlComputeCrc32", "int",0, "wstr",CmdLine, "uint",StrLen(CmdLine)*2, "uint")
  2124.    TaskName :=  Format("RunAsTask\{1:}_{2:}@{3:08X}", A_ScriptName, A_PtrSize=8 ? "64" : "32", PathCrc)
  2125.  
  2126.      Try  RunAsTask  :=  TaskRoot.GetTask(TaskName)
  2127.        ,  TaskExists :=  1
  2128.    Catch
  2129.           TaskExists :=  0
  2130.  
  2131.  
  2132.    If ( A_IsAdmin = False )
  2133.    {
  2134.         If ( A_Args.Length > 0 )
  2135.              Args := Format(StrReplace(Format("{:" A_Args.Length "}",""), "`s", "`n{}"), A_Args*)  ; Join()
  2136.          ,   WinSetTitle(TaskName Args , A_ScriptHwnd)
  2137.  
  2138.         If ( TaskExists = True )
  2139.              Try    RunAsTask.Run(0)
  2140.              Catch
  2141.                     MsgBox("Task launch failed (disabled?):`n" TaskName, "RunAsTask", " 0x40000 Iconx")
  2142.                  ,  ExitApp()
  2143.  
  2144.         If ( TaskExists = False )
  2145.              Try    Run("*RunAs " CmdLine, A_ScriptDir)
  2146.              Catch
  2147.                     MsgBox("Task not created..`nChoose 'Yes' in UAC",    "RunAsTask", " 0x40000 Iconx T4")
  2148.                  ,  ExitApp()
  2149.  
  2150.         If ( A_Args.Length > 0 )
  2151.              WinWait("Exit_" TaskName " ahk_class AutoHotkey",, 5)
  2152.  
  2153.         ExitApp()
  2154.    }
  2155.  
  2156.  
  2157.    If ( A_IsAdmin = True )
  2158.    {
  2159.        If ( TaskExists = False )
  2160.             XML :=  Format('
  2161.                           ( LTrim
  2162.                             <?xml version="1.0" ?>
  2163.                             <Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  2164.                                 <Principals>
  2165.                                     <Principal>
  2166.                                         <LogonType>InteractiveToken</LogonType>
  2167.                                         <RunLevel>HighestAvailable</RunLevel>
  2168.                                     </Principal>
  2169.                                 </Principals>
  2170.                                 <Settings>
  2171.                                     <MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy>
  2172.                                     <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
  2173.                                     <AllowHardTerminate>true</AllowHardTerminate>
  2174.                                     <AllowStartOnDemand>true</AllowStartOnDemand>
  2175.                                     <Enabled>true</Enabled>
  2176.                                     <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
  2177.                                 </Settings>
  2178.                                 <Actions>
  2179.                                     <Exec>
  2180.                                         <Command>{1:}</Command>
  2181.                                         <Arguments>{2:}</Arguments>
  2182.                                         <WorkingDirectory>{3:}</WorkingDirectory>
  2183.                                     </Exec>
  2184.                                 </Actions>
  2185.                             </Task>
  2186.                          )'
  2187.                          ,  A_IsCompiled = 1  ?  QUO A_ScriptFullpath QUO  :  QUO AhkPath QUO
  2188.                          ,  A_IsCompiled = 0  ?  QUO A_ScriptFullpath QUO  :  ""
  2189.                          ,  A_ScriptDir
  2190.                          )
  2191.         ,   TaskRoot.RegisterTask( TaskName
  2192.                                  , XML
  2193.                                  , 0x2  ; TASK_CREATE
  2194.                                  , ""
  2195.                                  , ""
  2196.                                  , 3    ; TASK_LOGON_INTERACTIVE_TOKEN
  2197.                                  )
  2198.  
  2199.        If ( StrLen(Shortcut) )
  2200.             Try   FileGetShortcut(Shortcut,,,, &Description)
  2201.             Catch
  2202.                   Description := ""
  2203.             Finally
  2204.              If ( Description != Taskname )
  2205.                   FileCreateShortcut("schtasks.exe", Shortcut, A_WorkingDir
  2206.                                    , "/run /tn " QUO TaskName QUO, TaskName,,,,7)
  2207.  
  2208.        If ( SingleInstance )
  2209.             DllCall( "User32\ChangeWindowMessageFilterEx"
  2210.                    , "ptr",  A_ScriptHwnd
  2211.                    , "uint", 0x44       ;  WM_COMMNOTIFY
  2212.                    , "uint", 1          ;  MSGFLT_ALLOW
  2213.                    , "ptr",  0
  2214.                    )
  2215.  
  2216.        If ( WinExist(TaskName " ahk_class AutoHotkey") )
  2217.             Args   :=  WinGetTitle()
  2218.         ,   WinSetTitle("Exit_" TaskName)
  2219.         ,   Args   :=  SubStr(Args, InStr(Args, "`n") + 1)
  2220.         ,   A_Args :=  StrSplit(Args, "`n")
  2221.    }
  2222.  
  2223.    A_WinDelay            :=  SWD
  2224.    A_DetectHiddenWindows :=  DHW
  2225.    A_TitleMatchMode      :=  STMM
  2226.  
  2227.    Return TaskName
  2228. } ; ________________________________________________________________________________________________________
  2229.  
  2230. ;RunAsTask() ; if I use this, I'll need to put a normal shortcut in the Startup folder (the one below makes a task scheduler shortcut, maybe that one is faster)
  2231. RunAsTask(false, "C:\Users\loren\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\Prevent Volume Up When Bluetooth Headset Disconnects.ahk - Shortcut.lnk") ; self elevate
  2232. ;Run("*RunAs `"C:\Program Files\PowerToys\KeyboardManagerEngine\PowerToys.KeyboardManagerEngine.exe`"")
  2233. MsgBox "hmmmm"
  2234.  
  2235.  
  2236.  
  2237.  
  2238.  
  2239.  
  2240.  
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246. wmi  := ComObjGet("winmgmts:")
  2247. sink := ComObject("WbemScripting.SWbemSink")
  2248. ComObjConnect(sink, "SINK_")
  2249. StopListening(*) => ComObjConnect(sink)
  2250. OnExit(StopListening)
  2251. target := "Bluetooth Audio Renderer (2- Bluetooth stereo-audio)"
  2252.  
  2253. ; The numeral next to each event on the line below is the interval in seconds for the listener
  2254. ;for (k, v in Map("Creation", 30, "Deletion", 5))
  2255. for (k, v in Map("Creation", 1, "Deletion", 1))
  2256.    wmi.ExecNotificationQueryAsync(sink, Format("SELECT * FROM __Instance{1}Event WITHIN {2} WHERE TargetInstance ISA `"Win32_PnPEntity`" AND TargetInstance.Name = `"{3}`"", k, v, target))
  2257.  
  2258. SINK_OnObjectReady(obj, *)
  2259. {
  2260.    Event := (obj.Path_.Class = "__InstanceCreationEvent" ? "Connected" : "Disconnected")
  2261.  
  2262.    if (Event = "Connected")
  2263.        Run("*RunAs `"C:\Program Files\PowerToys\KeyboardManagerEngine\PowerToys.KeyboardManagerEngine.exe`"")
  2264.    else
  2265.    {
  2266. MsgBox "test"
  2267.        StopListening()
  2268.        Hotkey("*Volume_Up Up", (*) => (Send("{Volume_Up}"), ProcessClose("PowerToys.KeyboardManagerEngine.exe"), ExitApp()), "On")
  2269.    }
  2270. }
  2271.  
  2272. /******************** TRASH: "[TRASH]dynamic click hotkey.txt" which can probably be deleted now, not sure ********************/
  2273.  
  2274. gotta check if the cursor is over the taskbar <before I save the window to activate> and if true then save that instead
  2275. can't simply use WinExist("A") b/c that won't see the taskbar when the taskbar hasn't be clicked on
  2276.  
  2277.  
  2278.  
  2279. >>> actually, I have to make an additional variable which if set has to be activated instead of the normal windowToActivate variable
  2280. this additional variable has to be set with this (b/c only then will you know for sure that the relevant window gets activated, the one that was active at the time the user last clicked):
  2281.  
  2282. ; ClassNN argument consists of three classes seperated by the | (OR) symbol, the first two for W11 and the third one for W10 (can be seen by using WinSpy++ on the app section in taskbar)
  2283. #HotIf MouseIsOverControl("ahk_class Shell_TrayWnd", "iS)\QWindows.UI.Composition.DesktopWindowContentBridge1\E|MSTaskSwWClass1|MSTaskListWClass")
  2284. *LButton::
  2285.  
  2286. but with the other one that is used for a dynamic hotkey, like this one but which has extra code for setting the additional variable, and simply using Hotif() for the one w/o extra code:
  2287. Hotkey("*LButton", (*) => BufferLatestClick())
  2288.  
  2289.  
  2290.  
  2291. MouseIsOverControl(winTitle, classNN)
  2292. {
  2293.    try return (MouseGetPos(,, &winId, &control), WinExist(winTitle " ahk_id " winId) && control ~= classNN)
  2294.    return false
  2295. }
  2296.  
  2297.  
  2298.  
  2299.  
  2300. hmm.. I think this might not work how I thought it would
  2301.  
  2302. ; ClassNN argument consists of three classes seperated by the | (OR) symbol, the first two for W11 and the third one for W10 (can be seen by using WinSpy++ on the app section in taskbar)
  2303. Hotif("MouseIsOverControl(`"ahk_class Shell_TrayWnd`", `"iS)\QWindows.UI.Composition.DesktopWindowContentBridge1\E|MSTaskSwWClass1|MSTaskListWClass`")")
  2304. Hotkey("*LButton", (*) => (BufferLatestClick(), shouldActivateTaskbarInstead := true))
  2305. Hotif()
  2306. Hotkey("*LButton", (*) => BufferLatestClick())
  2307.  
  2308.  
  2309.  
  2310. ; The only argument that's usually given is WinTitle but can add 3 other optional string arguments seperated with a comma
  2311. MouseIsOver(params_WinTitle_WinText_ExcludeTitle_ExcludeText*) => (MouseGetPos(,, &winId), winId = WinExist(params_WinTitle_WinText_ExcludeTitle_ExcludeText*))
  2312.  
  2313. MouseIsOverTaskbar(*) => MouseIsOver("ahk_class Shell_TrayWnd")
  2314.  
  2315. /********** TRASH: task scheduler info which can probably be deleted now, not sure **********/
  2316.  
  2317. Program/script: "%ProgramFiles%\AutoHotkey\v2\AutoHotkey.exe"
  2318. Add arguments (optional): "%UserProfile%\Downloads\AutoHotkey\Minimized Tabs Outliner.ahk"
  2319. Start in (optional): %UserProfile%\Downloads\AutoHotkey
Add Comment
Please, Sign In to add comment