Last active
March 22, 2024 01:13
-
-
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 )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Many people have this default requirement - in the vast majority of cases, left-clicking on a bookmark item (including the horizontal bookmark bar and vertical folder list view ) should open the bookmark URL in a new tab. However, Chrome does not provide this option. This can be solved using AHK, which works almost perfectly.
AutoHotKey (a scripting language for automating hotkeys) can be considered as Windows' user-script engine, which has been around since the XP era, with many users and abundant resources, capable of solving many pain points. It is simple yet elegant, and in the obscure corners of forums, there are many works that impress me.
Returning to the main topic, how can you make Chrome open a new page when clicking on a bookmark? Chrome can do this by ctrl+shift+click, or ctrl+click, or middle-click on the bookmark to open in a new page. However, these methods either require holding additional keyboard keys or just open the new page in the background, none of them meet the simple requirement of "single left-clicking on a bookmark to open a new page."
After some thought, I first focused on the tooltip because when the mouse hovers over a bookmark, a tooltip window pops up with two lines of text containing the bookmark name and URL. I tried to retrieve the text inside it, but was not very successful.
To display more text content, the new version of Chrome (v100 and above) no longer uses the win32 native tooltips_class32 for tooltips, so you can't simply use ControlGetText to retrieve the text. Even if you could retrieve it, you can't quickly trigger the tooltip window. Originally, I thought that if it was a native tooltip, maybe it's possible to get the text content of the tooltip without triggering the tooltip (because of
toolInfo.lpszText = LPSTR_TEXTCALLBACK; pszText
callback and theTTN_GETDISPINFO
window message)?Text recognition or…?
Now, Chrome is using its own Chrome_WidgetWin_1 (views system) to draw tooltip pop-ups.
If you want to get the text within, what’s the best way to do it?
Text recognition?
The Windows Magnifier has a small feature where, if you click the speaker button on it, and then click on another window interface, it will read out the text aloud, somewhat like a screen text capture.
This text capture feature is based on the Accessibility API. AHK has relevant libraries, and here’s a patchwork version:
acc_lite.ahk
By using the Acc_ObjectFromPoint function from the mouse position to create an acc object, and then calling
acc.accName(0)
you can get the text content. Simple!In fact, many methods are transferred from C++ code, and then they can be transferred back, applying to other applications.
Mouse text capture!
Since we can obtain the text content under the mouse, there’s no need to bother with tooltips anymore (it was a detour).
I tried and it successfully captures the full name of bookmarks. It works for Chrome, Edge, and even other programs!
test_capture.ahk
Finally, solving the issue of opening bookmarks in new tabs.
There are two scenarios.
First, horizontal Bookmarks Bar
My bookmarks bar mostly consists of folders, with only three exceptions.
In that case, treat the few exceptions as special cases and add Ctrl+Shift when clicking, while keeping the clicks on the rest items unchanged.
In short, distinguish whether to add Ctrl+Shift to the left mouse click based on the combination of mouse click position and mouse text capture result!
Second, Folder view : Vertical List Panel of Bookmarks.
For Chrome v120, the window class for a folder view (when expanded from bookmark bar) is Chrome_WidgetWin_2.
For folder view, most can be opened in new tab pages with Ctrl+Shift, while a few, such as JavaScript code, are exceptions and can be distinguished by the bookmark name, for example,
<<I'm javascript bookmarklet>>
as bookmark name.In the folder view, folders do not respond when clicked with Ctrl+Shift, so there’s no need to distinguish them.
If you still wish to open bookmarks in the same tab with left-click, you can:
cheers.