SetKeyDelay, -1 CoordMode, Mouse, Screen ~LButton:: WinGetClass, class, A MouseGetPos, mx, my, , control, 1 x1 = %mx% y1 = %my% loop { GetKeyState, keystate, LButton if keystate = U { MouseGetPos, mx, my x2 = %mx% y2 = %my% break } } x := (x2 - x1) y := (y2 - y1) if (x >= 6) gosub, get if (y >= 6) gosub, get if (x <= -6) gosub, get if (y <= -6) gosub, get return get: ControlGet, text, Selected, , %control%, ahk_class %class% if text != { clipboard = %text% ;-------------------------------- ; remove this line if you prefer selected text to stay highlighted: controlsend, %control%, {left}{right}, ahk_class %class% ;-------------------------------- /* tooltip, you selected:`n%text%`nfrom: %class%`, %control% sleep, 1000 tooltip */ return } return ~Mbutton:: Send, %text% return
Linux-like copy/paste with mouse
Started by
Serenity
, Apr 05 2005 06:54 PM
19 replies to this topic
This script emulates the copy selected text to clipboard behaviour common to Linux. An optional paste with middle mouse button is included in the script. Unfortunately certain types of edit controls do not return the selected text with ControlGet. Feel free to tweak this - the mouse move detection routine isn't perfect.
#1
-
Posted 05 April 2005 - 06:54 PM
"Anything worth doing is worth doing slowly." - Mae West
Nice idea, Serenity!
Very few controls tell if they have selected texts. Many more react to Ctrl-C, copying (any) selection to the clipboard directly. Here is another version of your script using Ctrl-C:
Very few controls tell if they have selected texts. Many more react to Ctrl-C, copying (any) selection to the clipboard directly. Here is another version of your script using Ctrl-C:
CoordMode Mouse, Screen ~LButton:: MouseGetPos x0, y0 ; save start mouse position 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 clip0 := ClipBoardAll ; save old clipboard ClipBoard = Send ^c ; selection -> clipboard ClipWait 1, 1 ; restore clipboard if no data IfEqual ClipBoard,, SetEnv ClipBoard, %clip0% } return
#2
-
Posted 06 April 2005 - 05:53 PM
Thanks Laszlo. Your version works much better with Ctrl+C, and I didn't know you could do expressions like this:
I get this error message from time to time although I am unsure what triggers it:
if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5)
I get this error message from time to time although I am unsure what triggers it:
Error: GetClipboardData
Line#
013: }
014: if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5)
015: {
016: clip0 = ClipBoardAll
017: ClipBoard =
018: Send,^c
019: ClipWait,1,1
---> 020: if ClipBoard =
020: ClipBoard = %clip0%
021: }
022: Return
025: Send,^v
026: Return
027: Exit
028: Exit
#3
-
Posted 07 April 2005 - 11:15 PM
"Anything worth doing is worth doing slowly." - Mae West
That happens when the internal call to GetClipboardData() fails to retrieve the plain text or list of copied files that resides on the clipboard. If you find out any more about the conditions that trigger this error, please let me know. Also, if anyone else gets this error, it would help to know the circumstances.I get this error message from time to time although I am unsure what triggers it:
Error: GetClipboardData
---> 020: if ClipBoard =
Thanks.
#4
-
Posted 07 April 2005 - 11:30 PM
This GetClipboardData error is strange. I have not seen it in my Win2k laptop. (Everyone: please try to reproduce it!) Serenity, have you tried increasing the ClipWait time? Maybe your PC is slow and the clipboard was still busy when AHK wanted to check it.
#5
-
Posted 07 April 2005 - 11:37 PM
It's a very unexpected error because at that stage, the clipboard is already opened and fully owned by the script. I've never heard of GetClipboardData() failing under these conditions, especially since it's called with CF_TEXT (plain text) or CF_HDROP (list of copied files), which are very mainstream.
However, I have seen GetClipboardData() fail for ClipboardAll, and for this reason ClipboardAll ignores the error and simply tries to get as much data as it can.
However, I have seen GetClipboardData() fail for ClipboardAll, and for this reason ClipboardAll ignores the error and simply tries to get as much data as it can.
#6
-
Posted 08 April 2005 - 12:13 AM
...just thinkin...
Maybe the clipboard still changes after ClipWait saw data there, and accessing it causes errors. You could try
Maybe the clipboard still changes after ClipWait saw data there, and accessing it causes errors. You could try
ClipWait 1, 1 clip2 := ClipBoard IfEqual clip2,, SetEnv ClipBoard, %clip0%If it does not help, we can try waiting until the clipboard does not change for a while.
clip0 := ClipBoardAll ; save old clipboard ClipBoard = Send ^c ; selection -> clipboard ClipWait 1, 1 ; wait for some data clip1 := ClipBoard ; current state of clipboard Loop { Sleep 20 clip2 := ClipBoard IfEqual clip1,%clip2%, break ; exit if no change for 20 ms clip1 := ClipBoard ; current state of clipboard }
#7
-
Posted 08 April 2005 - 03:16 AM
Hi,
I can reproduce the Error with the following Hotkey:
Tekl
I can reproduce the Error with the following Hotkey:
#q:: Send, ^c ClipWait, 0.5, 1 msgbox %Clipboard% ReturnNow if I've opened an archive in WinRAR and no file is selected (clicking on white space) this hotkey gives me that error.
Tekl
#8
-
Posted 13 April 2005 - 12:33 PM
Thanks for the script; it produces the same error for me.
The next update will contain the following change:
Fixed the Clipboard variable to avoid producing an error when a set of zero files was copied onto the clipboard. [thanks Serenity & Tekl]
The next update will contain the following change:
Fixed the Clipboard variable to avoid producing an error when a set of zero files was copied onto the clipboard. [thanks Serenity & Tekl]
#9
-
Posted 13 April 2005 - 01:43 PM
I'm a newbie here but thought I'd add a couple cents...
couldn't the expression
if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5)
be reduced to
if sqr((x-x0)^2+(y-y0)^2) > 5
and eliminate several logical OR's?
Sorry ... so new .. I'm not even sure if AHK has a square root function. LOL
Thanks to all for sharing code. Looking forward to learning this.
couldn't the expression
if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5)
be reduced to
if sqr((x-x0)^2+(y-y0)^2) > 5
and eliminate several logical OR's?
Sorry ... so new .. I'm not even sure if AHK has a square root function. LOL
Thanks to all for sharing code. Looking forward to learning this.
#10
-
Posted 16 April 2005 - 09:16 PM
Assuming you defined your own square root function, and replace ^ with ** (the power operator in AHK) it should work. (But it does not, because negative base is not allowed, and so the result is wrong.) In any case, your condition is different. The original one allows the mouse to move in a little square without the selection copied to the clipboard, you specify a circle. But it doesn't really matter.
If you care about fast execution, function calls, multiplications are usually slower than a series of comparisons. Especially, with short circuits (not calculating further when the overall result becomes determined from a few conditions). Much depend on the compiler, though. Stupid compilation of conditionals might flush the processor pipeline unnecessarily, causing wait states.
If you care about fast execution, function calls, multiplications are usually slower than a series of comparisons. Especially, with short circuits (not calculating further when the overall result becomes determined from a few conditions). Much depend on the compiler, though. Stupid compilation of conditionals might flush the processor pipeline unnecessarily, causing wait states.
#11
-
Posted 16 April 2005 - 11:39 PM
CoordMode Mouse, Screen ~LButton:: MouseGetPos x0, y0 ; save start mouse position 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 clip0 := ClipBoardAll ; save old clipboard ClipBoard = Send ^c ; selection -> clipboard ClipWait 1, 1 ; restore clipboard if no data IfEqual ClipBoard,, SetEnv ClipBoard, %clip0% } return ~Mbutton:: Send, ^v ;Paste via middle mouse click returnOn an even cooler note, I pasted the code above using this script!
#12
-
Posted 06 February 2008 - 06:48 PM
Utch: great script. But when I select text by double-clicking, it doesn't work the same way as when I select by click-and-drag. Any way to fix that?
#13
-
Posted 07 February 2008 - 12:40 AM
Thxgreat script
It was discussed a few times in the Forum. Windows handles the mouse differently, so there is no perfect Linux emulation possible. What you need is to detect when a new selection is made, but it is application dependent. Often double clicks select words, triple clicks select sentences or lines, quadruple clicks select paragraphs… In other applications triple clicks deselect the last selected words, so you don’t know if a click selected something new by just monitoring the mouse. Also, if you drag something around it may stay selected, or may not.when I select text by double-clicking, it doesn't work the same way as when I select by click-and-drag
A possible solution could be to send Ctrl-C always when the mouse button is released. If the clipboard becomes empty, restore its previous content. However, at dragging you might not want to change the clipboard, but the script cannot tell. There are speed and memory problems, too. If you select many directories to drag somewhere, Ctrl-C might need a lot of time to update the clipboard. During the wait time the system may look frozen.
#14
-
Posted 07 February 2008 - 01:05 AM
I took a couple of scripts and pieced them together that seems to handle the double click. Here's the code:
I've found that I sometimes highlight the text I'm going to paste over though, which, in this case, replaces what's on the clipboard already. I don't know how Linux handles that, but it's something to get used to if you decided to use a script like this.
CoordMode Mouse, Screen ~LButton:: If A_PriorHotkey = %A_ThisHotkey% { If A_TimeSincePriorHotkey < 300 ; 300 ms to double click, adjust if needed { clip0 := ClipBoardAll ; save old clipboard ClipBoard = Send ^c ; selection -> clipboard ClipWait 1, 1 ; restore clipboard if no data IfEqual ClipBoard,, SetEnv ClipBoard, %clip0% } else { MouseGetPos x0, y0 ; save start mouse position 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 clip0 := ClipBoardAll ; save old clipboard ClipBoard = Send ^c ; selection -> clipboard ClipWait 1, 1 ; restore clipboard if no data IfEqual ClipBoard,, SetEnv ClipBoard, %clip0% } return } } ~Mbutton:: Send, ^v ;Paste via middle mouse click return
I've found that I sometimes highlight the text I'm going to paste over though, which, in this case, replaces what's on the clipboard already. I don't know how Linux handles that, but it's something to get used to if you decided to use a script like this.
#15
-
Posted 26 February 2008 - 10:52 PM