 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Serenity
Joined: 07 Nov 2004 Posts: 1271
|
Posted: Tue Apr 05, 2005 6:54 pm Post subject: Linux-like copy/paste with mouse |
|
|
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.
| Code: | 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 |
_________________ "Anything worth doing is worth doing slowly." - Mae West
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Wed Apr 06, 2005 5:53 pm Post subject: |
|
|
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: | Code: | 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 |
|
|
| Back to top |
|
 |
Serenity
Joined: 07 Nov 2004 Posts: 1271
|
Posted: Thu Apr 07, 2005 11:15 pm Post subject: |
|
|
Thanks Laszlo. Your version works much better with Ctrl+C, and I didn't know you could do expressions like this:
| Code: | | 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:
| Quote: | 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 |
_________________ "Anything worth doing is worth doing slowly." - Mae West
 |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10716
|
Posted: Thu Apr 07, 2005 11:30 pm Post subject: |
|
|
| Serenity wrote: | I get this error message from time to time although I am unsure what triggers it:
| Quote: | Error: GetClipboardData
---> 020: if ClipBoard =
|
| 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.
Thanks. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Thu Apr 07, 2005 11:37 pm Post subject: |
|
|
| 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. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10716
|
Posted: Fri Apr 08, 2005 12:13 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Fri Apr 08, 2005 3:16 am Post subject: |
|
|
...just thinkin...
Maybe the clipboard still changes after ClipWait saw data there, and accessing it causes errors. You could try | Code: | 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. | Code: | 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
} |
|
|
| Back to top |
|
 |
Tekl
Joined: 24 Sep 2004 Posts: 814 Location: Germany
|
Posted: Wed Apr 13, 2005 12:33 pm Post subject: |
|
|
Hi,
I can reproduce the Error with the following Hotkey:
| Code: |
#q::
Send, ^c
ClipWait, 0.5, 1
msgbox %Clipboard%
Return |
Now if I've opened an archive in WinRAR and no file is selected (clicking on white space) this hotkey gives me that error.
Tekl |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10716
|
Posted: Wed Apr 13, 2005 1:43 pm Post subject: |
|
|
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] |
|
| Back to top |
|
 |
MrNomer
Joined: 16 Apr 2005 Posts: 1
|
Posted: Sat Apr 16, 2005 9:16 pm Post subject: if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < |
|
|
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. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Sat Apr 16, 2005 11:39 pm Post subject: |
|
|
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. |
|
| Back to top |
|
 |
utch
Joined: 06 Feb 2008 Posts: 1
|
Posted: Wed Feb 06, 2008 6:48 pm Post subject: To put it all together |
|
|
| Code: | 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
return |
On an even cooler note, I pasted the code above using this script! |
|
| Back to top |
|
 |
JazzSinger
Joined: 07 Feb 2008 Posts: 1
|
Posted: Thu Feb 07, 2008 12:40 am Post subject: |
|
|
| 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? |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Thu Feb 07, 2008 1:05 am Post subject: |
|
|
| JazzSinger wrote: | | great script | Thx
| JazzSinger wrote: | | when I select text by double-clicking, it doesn't work the same way as when I select by click-and-drag | 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.
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. |
|
| Back to top |
|
 |
airjrdn
Joined: 25 Feb 2008 Posts: 37
|
Posted: Tue Feb 26, 2008 10:52 pm Post subject: |
|
|
I took a couple of scripts and pieced them together that seems to handle the double click. Here's the code:
| Code: |
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. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|