AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Linux-like copy/paste with mouse
Goto page 1, 2  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Serenity



Joined: 07 Nov 2004
Posts: 1271

PostPosted: Tue Apr 05, 2005 6:54 pm    Post subject: Linux-like copy/paste with mouse Reply with quote

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
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Wed Apr 06, 2005 5:53 pm    Post subject: Reply with quote

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
View user's profile Send private message
Serenity



Joined: 07 Nov 2004
Posts: 1271

PostPosted: Thu Apr 07, 2005 11:15 pm    Post subject: Reply with quote

Thanks Laszlo. Smile 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
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10716

PostPosted: Thu Apr 07, 2005 11:30 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Thu Apr 07, 2005 11:37 pm    Post subject: Reply with quote

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
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10716

PostPosted: Fri Apr 08, 2005 12:13 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Fri Apr 08, 2005 3:16 am    Post subject: Reply with quote

...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
View user's profile Send private message
Tekl



Joined: 24 Sep 2004
Posts: 814
Location: Germany

PostPosted: Wed Apr 13, 2005 12:33 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10716

PostPosted: Wed Apr 13, 2005 1:43 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
MrNomer



Joined: 16 Apr 2005
Posts: 1

PostPosted: Sat Apr 16, 2005 9:16 pm    Post subject: if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < Reply with quote

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
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sat Apr 16, 2005 11:39 pm    Post subject: Reply with quote

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
View user's profile Send private message
utch



Joined: 06 Feb 2008
Posts: 1

PostPosted: Wed Feb 06, 2008 6:48 pm    Post subject: To put it all together Reply with quote

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
View user's profile Send private message
JazzSinger



Joined: 07 Feb 2008
Posts: 1

PostPosted: Thu Feb 07, 2008 12:40 am    Post subject: Reply with quote

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
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Thu Feb 07, 2008 1:05 am    Post subject: Reply with quote

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
View user's profile Send private message
airjrdn



Joined: 25 Feb 2008
Posts: 37

PostPosted: Tue Feb 26, 2008 10:52 pm    Post subject: Reply with quote

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. Smile 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
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group