Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AutoHotKey https://www.autohotkey.com/ script to simuate "selection clipboard" behavior of Linux desktop environments
; Simulate "Selection Cipboard" of Linux desktop environments
; Based on:
; https://softwarerecs.stackexchange.com/questions/9791/copy-selection-to-clipboard-automatically
; Usage:
; 1. Install AutoHotKey: https://www.autohotkey.com/
; 2. Save this file as "SelectionClipboard.ahk".
; 3. Put it into the startup folder.
; Note:
; * Ctrl-C will be sent when you do drag and drop with the left button always, including
; window moving and resizing. This means that SIGINT is sent to appls when you try to
; move/resize any WSL window. Thus this fatally incompatible to WSL.
; * Ctrl-V will be sent when you do middle click always, including "close tab" on Firefox
; and other apps.
; * I struggled to find out something alternative method to get selection text safely, but
; sadly there looks to be no way to do that. Firefox and some other major applications
; don't use any regular text edit control, and AutoHotKey doesn't provide functions to
; retrieve selection text with such apps. If any future version of AHK support
; accessivility services, it may become a solution for this problem...
doubleClickDelay := 200
tripleClickDelay := 350
handleCursor := 1 ; Shift-left, Shift-right, Shift-up and Shift-down
handleDrag := 1
handleDoubleClick := 1
handleTripleClick := 1
handleCtrlA := 1
selectionClipboard := ""
DebugPrint(ByRef message)
{
return ; comment out this line while debugging
ToolTip, %message%
SetTimer, ClearDebugPrint, 5000
return
ClearDebugPrint:
ToolTip,
return
}
NotifyCopied()
{
ToolTip, Copied
SetTimer, ClearNotification, 750
return
ClearNotification:
ToolTip,
return
}
TryCopy(type)
{
global selectionClipboard
clip0 := ClipBoardAll ; save old clipboard
SetEnv ClipBoard, "" ; clear clipboard
Send, ^c ; selection -> clipboard
ClipWait 1, 1
selectionText := ClipBoard ; store selection text -> selection clipboard
If selectionText <> ""
{
selectionClipboard := selectionText
message = Copied(%type%): "%selectionClipboard%"
NotifyCopied()
DebugPrint(message)
}
SetEnv ClipBoard, %clip0% ; restore clipboard
clip0 :=
}
TryPaste()
{
global selectionClipboard
message = TryPaste: "%selectionClipboard%"
DebugPrint(message)
If selectionClipboard = ""
return ; do nothing if no text was selected
clip0 := ClipBoardAll ; save old clipboard
SetEnv ClipBoard, %selectionClipboard% ; selection clipboard -> clipboard
Send, ^v
SetEnv ClipBoard, %clip0% ; restore clipboard
clip0 :=
}
~Lshift::
global selectionClipboard
global handleCursor
If handleCursor <> 1
return
TimeButtonDown = %A_TickCount%
; Wait for it to be released
Loop
{
Sleep 10
GetKeyState, LshiftState, Lshift, P
if LshiftState = U ; Button has been released.
break
elapsed = %A_TickCount%
elapsed -= %TimeButtonDown%
if elapsed > 200 ; Button was held down long enough
{
x0 = A_CaretX
y0 = A_CaretY
Loop
{
Sleep 20 ; yield time to others
GetKeyState keystate, Lshift
IfEqual keystate, U, {
x = A_CaretX
y = A_CaretY
break
}
}
if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5)
{ ; Caret has moved
TryCopy("cursor")
}
return
}
}
~LButton::
global selectionClipboard
global handleDrag
global handleDoubleClick
global handleTripleClick
MouseGetPos, xx
TimeButtonDown = %A_TickCount%
MouseGetPos x0, y0 ; save start mouse position
; Wait for it to be released
Loop
{
Sleep 10
GetKeyState, LButtonState, LButton, P
if LButtonState = U ; Button has been released.
{
If WinActive("Crimson Editor") and (xx < 25) ; Single Click in the Selection Area of CE
{
If handleDrag = 1
TryCopy("drag")
return
}
break
}
elapsed = %A_TickCount%
elapsed -= %TimeButtonDown%
if elapsed > %doubleClickDelay% ; Button was held down too long, so assume it's not a double-click.
{
Loop
{
Sleep 20 ; yield time to others
GetKeyState keystate, LButton
IfEqual keystate, U, {
MouseGetPos x, y ; position when button released
break
}
}
if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5)
{ ; mouse has moved
If handleDrag = 1
TryCopy("drag")
}
return
}
}
; Otherwise, button was released quickly enough. Wait to see if it's a double-click:
TimeButtonUp = %A_TickCount%
Loop
{
Sleep 10
GetKeyState, LButtonState, LButton, P
if LButtonState = D ; Button has been pressed down again.
break
elapsed = %A_TickCount%
elapsed -= %TimeButtonUp%
if elapsed > %tripleClickDelay% ; No click has occurred within the allowed time, so assume it's not a double-click.
return
}
; Button pressed down again, it's at least a double-click
TimeButtonUp2 = %A_TickCount%
Loop
{
Sleep 10
GetKeyState, LButtonState2, LButton, P
if LButtonState2 = U ; Button has been released a 2nd time, let's see if it's a tripple-click.
break
}
; Button released a 2nd time
TimeButtonUp3 = %A_TickCount%
Loop
{
Sleep 10
GetKeyState, LButtonState3, LButton, P
if LButtonState3 = D ; Button has been pressed down a 3rd time.
break
elapsed = %A_TickCount%
elapsed -= %TimeButtonUp%
if elapsed > %tripleClickDelay% ; No click has occurred within the allowed time, so assume it's not a tripple-click.
{ ;Double-click
If handleDoubleClick = 1
TryCopy("double click")
return
}
}
;Tripple-click:
global selectionClipboard
Sleep, 100
If handleTripleClick = 1
TryCopy("triple click")
return
; Ctl+A = Select All, then Copy
~^a::
If handleCtrlA = 1
TryCopy("Ctrl-A")
return
; Paste with Middle-click
~mbutton::
TryPaste()
return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.