Descolada / Acc-v2

Acc library for AHK v2
MIT License
40 stars 6 forks source link

Not retrieving URL from browser #6

Closed edwyn-amador closed 4 months ago

edwyn-amador commented 4 months ago

I noticed on the example script 'Examples/Example7_Page_URL_From_Hover.ahk', the url is retrieved correctly on my main computer, but not on most computers I have tested, in those others it simply returns null on oEl.value, no matter which browser is used.

Can you please fix it or help me to get a workaround to work on all devices? Thanks.

Descolada commented 4 months ago

Interesting, I've tested in all my Chromium-based apps (Chrome, Edge, Discord, Notion, VSCode) and it works as expected.

Could you try changing the line oEl := oAcc.Normalize({RoleText:"document", not:{Value:""}}) to oEl := oAcc.Normalize({Role:15, not:{Value:""}}) to see whether it makes a difference?

edwyn-amador commented 4 months ago

Interesting, I've tested in all my Chromium-based apps (Chrome, Edge, Discord, Notion, VSCode) and it works as expected.

Could you try changing the line oEl := oAcc.Normalize({RoleText:"document", not:{Value:""}}) to oEl := oAcc.Normalize({Role:15, not:{Value:""}}) to see whether it makes a difference?

Thanks, this works! Can you please explain why?

Also, that workaround noticed it isn't working when using the following way:

oAcc := Acc.ElementFromChromium("ahk_id " hwnd) instead of oAcc := Acc.ElementFromPoint(), I was using it that way in my custom script before, is there a way to make it work for this other method as well?

Descolada commented 4 months ago

It stemmed from the fact that I assumed RoleText will be in English, but I'm guessing that if your computer is set up in a different language then RoleText is also in that language. The role number however stays the same.

What exactly are you trying to achieve? I tested replacing oAcc := Acc.ElementFromPoint() with try MouseGetPos(,, &hwnd), oAcc := Acc.ElementFromChromium("ahk_id " hwnd) and it worked as expected (it doesn't work in Firefox because it isn't a Chromium app).

edwyn-amador commented 4 months ago

Ah, that makes total sense now.

I don't remember why I noticed something that made me thought it wasn't working with oAcc := Acc.ElementFromChromium("ahk_id " hwnd), (I'm pretty sure it wasn't Firefox related) but I did the tests again and it is working.

So, I'm mainly using oAcc := Acc.ElementFromChromium("ahk_id " hwnd) because I noticed this way it works even when the cursor is not on the viewport/page area, (I need it to work no matter where the cursor is pointing), as for example when using oAcc := Acc.ElementFromPoint() it doesn't work if the cursor is pointing on the browser tabs section or somewhere else outside the browser window.

Now I need to implement a workaround to make it work that way on Firefox as well. No matter where the cursor is pointing, detect the url as long as the window is on top (as for example when navigating through tabs via keyboard, Ctrl + 1, Ctrl + 2).

Can you please help me to implement something to make it work like that on Firefox? Thanks..

Descolada commented 4 months ago

Try this modified GetUrl function from the GetUrl() gist:

#Requires AutoHotkey v2.0

; Version: 2023.10.05.1
; https://gist.github.com/7cce378c9dfdaf733cb3ca6df345b140

GetUrl(WinTitle?, WinText?, ExcludeTitle?, ExcludeText?) {
    static S_OK := 0, TreeScope_Descendants := 4, UIA_ControlTypePropertyId := 30003, UIA_DocumentControlTypeId := 50030, UIA_EditControlTypeId := 50004, UIA_ValueValuePropertyId := 30045
    if !(hWnd := WinExist(WinTitle?, WinText?, ExcludeTitle?, ExcludeText?))
        throw TargetError("Target window not found")
    IUIAutomation := ComObject("{FF48DBA4-60EF-4201-AA87-54103EEF594E}", "{30CBE57D-D9D0-452A-AB13-7AC5AC4825EE}")
    eRoot := ComValue(13, 0)
    HRESULT := ComCall(6, IUIAutomation, "Ptr", hWnd, "Ptr*", eRoot)
    if (HRESULT != S_OK) {
        throw Error("IUIAutomation::ElementFromHandle()", -1, HRESULT)
    }
    winClass := WinGetClass("A")
    ctrlTypeId := (winClass ~= "Chrome" ? UIA_DocumentControlTypeId : UIA_EditControlTypeId)
    value := Buffer(8 + 2 * A_PtrSize, 0)
    NumPut("UShort", 3, value, 0)
    NumPut("Ptr", ctrlTypeId, value, 8)
    condition := ComValue(13, 0)
    if (A_PtrSize = 8) {
        HRESULT := ComCall(23, IUIAutomation, "UInt", UIA_ControlTypePropertyId, "Ptr", value, "Ptr*", condition)
    } else {
        HRESULT := ComCall(23, IUIAutomation, "UInt", UIA_ControlTypePropertyId, "UInt64", NumGet(value, 0, "UInt64"), "UInt64", NumGet(value, 8, "UInt64"), "Ptr*", condition)
    }
    if (HRESULT != S_OK) {
        throw Error("IUIAutomation::CreatePropertyCondition()", -1, HRESULT)
    }
    eFirst := ComValue(13, 0)
    HRESULT := ComCall(5, eRoot, "UInt", TreeScope_Descendants, "Ptr", condition, "Ptr*", eFirst)
    if (HRESULT != S_OK) {
        throw Error("IUIAutomationElement::GetRootElement()", -1, HRESULT)
    }
    propertyValue := Buffer(8 + 2 * A_PtrSize)
    HRESULT := ComCall(10, eFirst, "UInt", UIA_ValueValuePropertyId, "Ptr", propertyValue)
    if (HRESULT != S_OK) {
        throw Error("IUIAutomationElement::GetCurrentPropertyValue()", -1, HRESULT)
    }
    ObjRelease(eFirst.Ptr)
    ObjRelease(eRoot.Ptr)
    try {
        pProperty := NumGet(propertyValue, 8, "Ptr")
        return StrGet(pProperty, "UTF-16")
    }
}
edwyn-amador commented 4 months ago

That works, thankss, I appreciate it!