347 lines
7.6 KiB
AutoHotkey
347 lines
7.6 KiB
AutoHotkey
#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.
|
|
CoordMode, Mouse, Screen ; mouse coordinates relative to the screen
|
|
|
|
; =========================
|
|
; CONFIGURATION
|
|
; =========================
|
|
; global RATIO := 0.618
|
|
global RATIO := 0.382
|
|
global ID_SEEN := Object()
|
|
global ARRANGEMENT := Object()
|
|
global ARRANGEMENT_PATH := A_AppData . "\arrangement.json"
|
|
global PADDING := 10
|
|
LoadArrangement()
|
|
;WatchNewWindow()
|
|
SetTimer, AdjustNewWindow, 1000
|
|
; =========================
|
|
; BINDINGS
|
|
; =========================
|
|
^Esc:: Send ^{``}
|
|
*#q:: !F4
|
|
#Esc:: Reload
|
|
^BS::
|
|
Send ^a
|
|
Send {BS}
|
|
return
|
|
#=::SoundSet, +5
|
|
#-::SoundSet, -5
|
|
#\::Send {Volume_Mute}
|
|
#BS::#l
|
|
#f:: ToggleActiveWinMaximum()
|
|
^#p::ShowActiveWinGeometry()
|
|
#j:: FocusWinByDirection("right")
|
|
#k:: FocusWinByDirection("left")
|
|
#+j::MoveActiveWinByDirection("right")
|
|
#+k::MoveActiveWinByDirection("left")
|
|
#+r::reload
|
|
#i::IgnoreArrangementForActiveWindow()
|
|
#+i::UnignoreArrangementForActiveWindow()
|
|
#t::ShowDebug()
|
|
|
|
; Ctrl + Alt + v : paste as plain text
|
|
^!v::
|
|
Clip0 = %ClipBoardAll%
|
|
ClipBoard = %ClipBoard% ; Convert to plain text
|
|
Send ^v
|
|
Sleep 1000
|
|
ClipBoard = %Clip0%
|
|
VarSetCapacity(Clip0, 0) ; Free memory
|
|
Return
|
|
|
|
; Ctrl + Alt + Shift + v : paste as plain test a replace \ with /
|
|
^+!v::
|
|
Clip0 = %ClipBoardAll%
|
|
ClipBoard := StrReplace(ClipBoard, "\", "/") ; Convert to plain text
|
|
Send ^v
|
|
Sleep 1000
|
|
ClipBoard = %Clip0%
|
|
VarSetCapacity(Clip0, 0) ; Free memory
|
|
Return
|
|
|
|
; move cursor to center of window after switching
|
|
~#1 Up::
|
|
~#2 Up::
|
|
~#3 Up::
|
|
~#4 Up::
|
|
~#5 Up::
|
|
~#6 Up::
|
|
~#7 Up::
|
|
~#8 Up::
|
|
~#9 Up::
|
|
Sleep 100
|
|
SetCursorToCenterOfActiveWin()
|
|
return
|
|
~!Tab Up::
|
|
while (GetKeyState("Alt") != 0 or GetKeyState("Tab") != 0) {
|
|
Sleep 50
|
|
}
|
|
Sleep 100
|
|
WinGetPos, x, y, w, h, A
|
|
SetCursorToCenterOfActiveWin()
|
|
return
|
|
|
|
; =========================
|
|
; CAPSLOCK AS HYBRID KEY
|
|
; =========================
|
|
|
|
; Capslock & h:: Send {Left}
|
|
; Capslock & j:: Send {Down}
|
|
; Capslock & k:: Send {Up}
|
|
; Capslock & l:: Send {Right}
|
|
; Capslock & y:: Send {Browser_Back}
|
|
; Capslock & u:: Send ^{PgUp}
|
|
; Capslock & i:: Send ^{PgDn}
|
|
; Capslock & o:: Send {Browser_Forward}
|
|
; Capslock & BackSpace:: Send {Del}
|
|
|
|
; Capslock & n:: Send {Home}
|
|
; Capslock & m:: Send {PgUp}
|
|
; Capslock & ,:: Send {PgDn}
|
|
; Capslock & .:: Send {End}
|
|
|
|
; Capslock & Space:: SetCapsLockState % !GetKeyState("CapsLock", "T")
|
|
; +CapsLock::
|
|
; Send {~}
|
|
; SetCapsLockState % !GetKeyState("CapsLock", "T")
|
|
; Return
|
|
; Capslock::return
|
|
|
|
; =========================
|
|
; FUNCTIONS
|
|
; =========================
|
|
|
|
#Include, WinGetPosEx.ahk
|
|
#Include, JSON.ahk
|
|
|
|
ShowGeometry(x, y, w, h) {
|
|
MsgBox, , Geometry,% Format("x:{}, y:{}, w: {}, h: {}", x, y, w, h)
|
|
}
|
|
|
|
ShowActiveWinGeometry() {
|
|
WinGetPos x, y, w, h, A
|
|
ShowGeometry(x, y, w, h)
|
|
}
|
|
|
|
SetCursorPos(x, y) {
|
|
DllCall("SetCursorPos", "int", x, "int", y)
|
|
}
|
|
|
|
FocusWinUnderCursor() {
|
|
MouseGetPos, MouseX, MouseY, WinId
|
|
WinActivate, ahk_id %WinId%
|
|
}
|
|
|
|
SetCursorToCenterOfActiveWin() {
|
|
WinGetPos x, y, w, h, A
|
|
SetCursorPos(x + w / 2, y + h / 2)
|
|
}
|
|
|
|
FocusWinByPos(x, y) {
|
|
SetCursorPos(x, y)
|
|
FocusWinUnderCursor()
|
|
SetCursorToCenterOfActiveWin()
|
|
}
|
|
|
|
GetCursorMonGeometry(ByRef x, ByRef y, ByRef w, ByRef h) {
|
|
MouseGetPos, MouseX, MouseY
|
|
SysGet, mc, MonitorCount
|
|
; find current monitor
|
|
mi := 0
|
|
loop {
|
|
SysGet, mon, MonitorWorkArea, %mi%
|
|
if (monLeft < MouseX and monRight > MouseX) {
|
|
x := monLeft
|
|
y := monTop
|
|
w := monRight - monLeft
|
|
h := monBottom - monTop
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
FocusWinByDirection(direction) {
|
|
global RATIO
|
|
GetCursorMonGeometry(x, y, w, h)
|
|
wf := RATIO / 2
|
|
hf := 0.5
|
|
if (direction = "right")
|
|
wf := RATIO + (1 - RATIO) / 2
|
|
FocusWinByPos(x + w * wf, y + h * hf)
|
|
}
|
|
|
|
MoveActiveWinByDirection(direction) {
|
|
WinGet, isMax, MinMax, A
|
|
if (isMax) {
|
|
WinRestore, A
|
|
}
|
|
global RATIO
|
|
global PADDING
|
|
GetCursorMonGeometry(x, y, w, h)
|
|
activeWinId := WinExist("A")
|
|
WinGetPosEx(activeWinId, wx, wy, ww, wh, l, t, r, b)
|
|
wx := x
|
|
wy := y
|
|
ww := floor(w * RATIO)
|
|
wh := h
|
|
if (direction = "right") {
|
|
wx := ww + floor(PADDING / 2)
|
|
ww := w - ww
|
|
} else {
|
|
wx := wx + PADDING
|
|
}
|
|
ww := ww - floor(PADDING * 1.5)
|
|
wy := wy + PADDING
|
|
wh := wh - PADDING * 2
|
|
WinMove, A,, wx - l, wy - t, ww + l + r, wh + t + b
|
|
SaveActiveWindowDirection(direction)
|
|
}
|
|
|
|
SaveArrangement() {
|
|
global ARRANGEMENT
|
|
global ARRANGEMENT_PATH
|
|
file := FileOpen(ARRANGEMENT_PATH, "w")
|
|
file.Write(JSON.Dump(ARRANGEMENT,, 2))
|
|
file.Close()
|
|
}
|
|
|
|
LoadArrangement() {
|
|
global ARRANGEMENT
|
|
global ARRANGEMENT_PATH
|
|
try {
|
|
FileRead, temp, %ARRANGEMENT_PATH%
|
|
ARRANGEMENT := JSON.Load(temp)
|
|
} catch {
|
|
ARRANGEMENT := Object()
|
|
}
|
|
if not IsObject(ARRANGEMENT) {
|
|
ARRANGEMENT := Object()
|
|
}
|
|
if not IsObject(ARRANGEMENT["windows"]) {
|
|
ARRANGEMENT["windows"] := Object()
|
|
}
|
|
if not IsObject(ARRANGEMENT["ignore"]) {
|
|
ARRANGEMENT["ignore"] := Object()
|
|
}
|
|
}
|
|
|
|
GetActiveWindowClassPath() {
|
|
WinGet processPath, ProcessPath, A
|
|
WinGetClass windowClass, A
|
|
return processPath . ":" . windowClass
|
|
}
|
|
|
|
IsActiveWindowSeen() {
|
|
global ID_SEEN
|
|
WinGet winId, ID, A
|
|
seen := ID_SEEN.HasKey(winId)
|
|
ID_SEEN[winId] := true
|
|
return seen
|
|
}
|
|
|
|
IgnoreArrangementForActiveWindow() {
|
|
global ARRANGEMENT
|
|
ARRANGEMENT["ignore"][GetActiveWindowClassPath()] := true
|
|
SaveArrangement()
|
|
}
|
|
|
|
UnignoreArrangementForActiveWindow() {
|
|
global ARRANGEMENT
|
|
ARRANGEMENT["ignore"].Delete(GetActiveWindowClassPath())
|
|
SaveArrangement()
|
|
}
|
|
|
|
IsActiveWindowBorderless() {
|
|
WinGet s, Style, A
|
|
if (not s & +0xC00000) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
IsActiveWindowSizeboxed() {
|
|
WinGet, s, Style, A
|
|
return s & 0x40000
|
|
}
|
|
|
|
IsActiveWindowIgnored() {
|
|
global ARRANGEMENT
|
|
if (ARRANGEMENT["ignore"].HasKey(GetActiveWindowClassPath())) {
|
|
return true
|
|
}
|
|
; WinGetTitle, title, A
|
|
; if (title = "") {
|
|
; return true
|
|
; }
|
|
if (not IsActiveWindowSizeboxed()) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
SaveActiveWindowDirection(direction) {
|
|
global ARRANGEMENT
|
|
key := GetActiveWindowClassPath()
|
|
ARRANGEMENT["windows"][key] := direction
|
|
SaveArrangement()
|
|
}
|
|
|
|
ActiveWinInfo() {
|
|
WinGetTitle, title, A
|
|
WinGetClass, klass, A
|
|
WinGet processPath, ProcessPath, A
|
|
return processPath . " " . klass . " " . title
|
|
}
|
|
|
|
AdjustNewWindow() {
|
|
global log
|
|
seen := IsActiveWindowSeen()
|
|
ignored := IsActiveWindowIgnored()
|
|
wininfo := ActiveWinInfo()
|
|
if not seen {
|
|
LogDebug(Format("win: {1}, seen: {2}, ignore: {3}", wininfo, seen, ignored))
|
|
}
|
|
if not seen and not ignored {
|
|
classPath := GetActiveWindowClassPath()
|
|
if ARRANGEMENT["windows"].HasKey(classPath) {
|
|
MoveActiveWinByDirection(ARRANGEMENT["windows"][classPath])
|
|
}
|
|
}
|
|
}
|
|
|
|
ToggleActiveWinMaximum() {
|
|
WinGet, isMax, MinMax, A
|
|
if (isMax) {
|
|
WinRestore, A
|
|
} else {
|
|
WinMaximize, A
|
|
}
|
|
}
|
|
|
|
GetSelectedText() {
|
|
tmp = %ClipboardAll% ; save clipboard
|
|
Clipboard := "" ; clear clipboard
|
|
Send, ^c ; simulate Ctrl+C (=selection in clipboard)
|
|
ClipWait, 0, 1 ; wait until clipboard contains data
|
|
selection = %Clipboard% ; save the content of the clipboard
|
|
Clipboard = %tmp% ; restore old content of the clipboard
|
|
return selection
|
|
}
|
|
|
|
ShowDebug() {
|
|
ShowObject(IsActiveWindowSizeboxed())
|
|
}
|
|
|
|
ShowObject(obj) {
|
|
msg := JSON.Dump(obj)
|
|
MsgBox, %msg%
|
|
}
|
|
|
|
LogDebug(msg) {
|
|
FormatTIme, now, , MM-dd HH:mm:ss
|
|
log := FileOpen("d:\win.ahk.log", "a")
|
|
log.WriteLine(Format("[{1}] {2}", now, msg))
|
|
log.Close()
|
|
} |