Skip to content

Instantly share code, notes, and snippets.

@KnIfER
Last active March 22, 2024 01:13
Show Gist options
  • Save KnIfER/1c968deb61a6eb893842a286a7d12524 to your computer and use it in GitHub Desktop.
Save KnIfER/1c968deb61a6eb893842a286a7d12524 to your computer and use it in GitHub Desktop.
Chrome open bookmarked pages in new tab by default. (single left click open new tab in foreground )
global click_state := 0
global leftDwn := 0
GroupAdd, browser_gp, ahk_exe chrome.exe
Acc_Init(Function := "") {
Static h
If Not h
h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
If Function
return DllCall("GetProcAddress", "Ptr", h, "AStr", Function, "Ptr")
}
Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Error(p="") {
static setting:=0
return p=""?setting:setting:=p
}
Acc_GetStateText(nState)
{
nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
Return sState
}
; Acc_Child(Acc, ChildId=0) {
; try child:=Acc.accChild(ChildId)
; return child?Acc_Query(child):
; }
Acc_Children(Acc) {
if ComObjType(Acc,"Name") != "IAccessible"
ErrorLevel := "Invalid IAccessible Object"
else {
Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
Loop %cChildren%
i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
return Children.MaxIndex()?Children:
} else
ErrorLevel := "AccessibleChildren DllCall Failed"
}
if Acc_Error()
throw Exception(ErrorLevel,-1)
}
Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code
try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
catch
return
Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
return {x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")}
}
Acc_State(Acc, ChildId=0) {
try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
}
Acc_ObjectFromWindow(hWnd, idObject = -4)
{
Acc_Init()
If DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
Return ComObjEnwrap(9,pacc,1)
}
Acc_ObjectFromPoint(ByRef ChildIdOut := "", x := 0, y := 0) {
static S_OK := 0
static address := Acc_Init("AccessibleObjectFromPoint")
point := x & 0xFFFFFFFF | y << 32
if (point = 0) {
DllCall("User32\GetCursorPos", "Int64*", point)
}
pAcc := 0
VarSetCapacity(child, A_PtrSize * 2 + 8, 0)
NTSTATUS := DllCall(address, "Int64", point, "Ptr*", pAcc, "Ptr", &child, "UInt")
if (NTSTATUS != S_OK) {
throw Exception("AccessibleObjectFromPoint() failed.", -1, A_LastError)
}
ChildIdOut := NumGet(child, 8, "UInt")
return ComObj(9, pAcc, 1)
}
inGroup(GroupName)
{
IfWinActive, ahk_group %GroupName%
return true
}
indexOf(str, t, st=0) {
StringGetPos, ret, str, %t%, , st
return ret
}
#SingleInstance Force
GroupAdd, browser_gp, ahk_exe chrome.exe
; GroupAdd, browser_gp, ahk_exe msedge.exe
global leftDwn := 0
#Include acc_lite.ahk
clickLeft(dwn=true) {
if(dwn!=leftDwn || dwn) {
leftDwn := dwn
if(dwn) {
send {LButton down}
} else
send {LButton up}
; Msgbee("clickLeft" dwn)
}
; else
; Msgbee("clickLeft nono " dwn)
}
StartsWith(str, t, only=false) {
l := StrLen(str)
n := StrLen(t)
if(l-n>=0 && SubStr(str, 1, n) = t) {
if(!only || indexOf(str, t, n)<0) {
return 1
}
}
return 0
}
$LButton::
WinGetTitle, ti
MouseGetPos, xpos, ypos, MouseWindowUID, MouseControlID
WinGetPos,x,y,w,h,A
if(xpos>=0 && xpos<=w && ypos>=0 && ypos<=h) {
browser := inGroup("browser_gp")
if(click_state=0) {
if browser and not InStr(ti, "New Tab"){
newTab := false
; open bookmarked pages in new tab
WinGetClass, WindowClass, ahk_id %MouseWindowUID%
if(WindowClass="Chrome_WidgetWin_2") { ; folder panel, valid for chrome v120.
; for edge (not handled) the window class is still Chrome_WidgetWin_1 and you need to judge by width
CoordMode, Mouse, Screen
MouseGetPos, sX, sY
WinGetPos, x, , , , ahk_id %MouseWindowUID%
CoordMode, Mouse, Relative
if(sX - x > 34) {
; click on the favicon means to open url in current tab (same as before)
acc := Acc_ObjectFromPoint(ChildIdOut, sX, sY)
text := acc.accName(0)
; xx(text)
if(!StartsWith(text, "<<")
&& !StartsWith(text, "{{")
&& !StartsWith(text, "页面")
&& !StartsWith(text, "复制")
&& true) {
newTab := true
}
}
} else if(ypos < 160 && ypos > 110 && A_Cursor="Arrow") { ; Judge clicks on the horizontal bookmark bar.
; you need to adjust the min and max ypos on your computer
CoordMode, Mouse, Screen
MouseGetPos, sX, sY
CoordMode, Mouse, Relative
acc := Acc_ObjectFromPoint(ChildIdOut, sX, sY)
text := acc.accName(0)
if(text = "website name") {
if(!InStr(ti, "website name")) { ; maybe the url is same as current tab, and in that case dont open new tab.
newTab := true
}
}
if(StartsWith(text, "http") ; and InStr(text, "Untitled")
|| text="xxx"
|| text="yyy") {
; clicked bookmark bar item is not folder, then open new tab!
newTab := true
}
}
; xx(ypos " " A_Cursor)
if newTab {
Send ^+{click}
return
}
}
}
; Msgbee("123")
clickLeft(1)
} else {
clickLeft(1)
}
return
$LButton up::
if(click_state=3)
click_state := 0
clickLeft(0) ; allows for original left click dragging
return
@KnIfER
Copy link
Author

KnIfER commented Mar 18, 2024

www.autohotkey.com/boards/viewtopic.php?f=6&t=94568&p=419785&hilit=chrome+bookmark+new+tab#p419785

similar solution . it use accDescription . sendBlindLButton is better than listening lbutton up

;!-Alt/+-Shift/^-Control/#-win
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
;#Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

/****************************************
GUI For Logger (uncomment if you want to look at logs)
*/
Gui +AlwaysOnTop Resize
Gui, Add, Edit, x5 y5 w228 h1658 vConsole
Gui, Show, x3535 y0 w238 h1666, Logger AHK


/****************************************
LOGGER Logic (uncomment if you want to look at logs. uncomment all lines with log() below!)
*/
log(msg) {
    FormatTime, TimeString, A_Now, HH:mm:ss ; Generates a time stamp
    GuiControlGet, Console
    GuiControl, , Console, %Console%[%TimeString%] %msg%`r`n ; GUI write
}


/****************************************
Chrome Fix
*/
LButton::
{
    MouseGetPos,,,guideUnderCursor
	WinGetClass, Title, ahk_id %guideUnderCursor%
	WinGetActiveTitle, activeTitle
	
	if (Title == "Chrome_WidgetWin_1") and not WinActive("ahk_exe Chrome.exe"){
		log("LMB inside Inactive Chrome")
        sendLButton()
	} else
    {
        log("LMB Outside Chrome")
		sendBlindLButton()
    }
    
    Return 
}

^LButton::
{
    MouseGetPos,,,guideUnderCursor
	WinGetClass, Title, ahk_id %guideUnderCursor%
	WinGetActiveTitle, activeTitle

	if (Title == "Chrome_WidgetWin_1") and not WinActive("ahk_exe Chrome.exe")
    {
        log("Ctrl+LMB inside Inactive Chrome")
		sendLButton(true)
	} 
    else
    {
        log("Ctrl+LMB Outside Chrome")
		sendBlindLButton()
    }
    
    Return 
}   

sendLButton(ctrl=false) 
{
    desc := ""
    objectP := Acc_ObjectFromPoint()
    try desc := objectP.accDescription(0)
    if (desc ~= "i)^http|www") and not ctrl 
    {
        log("Bookmark: Sending Ctrl+LMB")
        Send ^{Click}{Alt down}{Alt up}
    }
    else if (desc ~= "i)^http|www") and ctrl 
    {
        log("Bookmark: Sending LMB")
        Send {Click}
    } 
    else 
    {
        log("Not a Bookmark")
		sendBlindLButton()
    }
}

sendBlindLButton()
{
	Send {Blind}{LButton Down}
	KeyWait LButton
	Send {Blind}{LButton Up}
}

#IfWinActive ahk_exe chrome.exe
    ^LButton:: 
        log("Ctrl+LMB inside Active Chrome")
		sendLButton(true)    
	return

    LButton::
        log("LMB inside Active Chrome")
		sendLButton()    
	return
		
    $Enter::
        log("Enter inside Active Chrome")
        path := "4.1.1.1.1.2.5.3"
        exist := WinExist()
        objectW := Acc_ObjectFromWindow(exist, 0)
        Send % (Acc_Get("Focus", path,, objectW) = 0 ? "!" : "") "{Enter}"
    return
#IfWinActive

@KnIfER
Copy link
Author

KnIfER commented Mar 22, 2024

update : actually lbutton up is better.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment