12

If I have two identical applications side-by-side on my desktop, is there software that exists that will mimic what I do on the left half on the right? Basically, if my screen is 1000x1000 and a click event happens at 5,5, I would also like it to fire that event at 505,5 (mirrored on the X-axis). I'd like to emulate keyboard and mouse events.

14
  • have you ever actually used a mirror and figured out how they work?
    – Baarn
    Feb 24, 2012 at 20:44
  • 1
    Alright, less a mirror and more a duplication. The concept is the same, the math is just different.
    – qJake
    Feb 24, 2012 at 20:48
  • Which operating system?
    – iglvzx
    Feb 24, 2012 at 20:59
  • 2
    {In super-hero announcer voice} This sounds like a job for Autohotkey!
    – Synetech
    Feb 24, 2012 at 21:13
  • 1
    @SpikeX, I threw something together last night that doubles mouse clicks on both halves of the screen, but I’m not sure about your specific requirements. Do you only need single clicks to be doubled or do you need actual dragging (holding the button down and moving the mouse to be doubled on both sides)? I’ve kind of, sort of got that working, but it stutters and is messy. Also, I’m not sure what you mean by keyboard events. Mouse clicks are sent to whatever window happens to be under the cursor at the point, but keys don’t have a screen coordinate associated with them.
    – Synetech
    Feb 25, 2012 at 20:28

1 Answer 1

8

(Knocking out a preliminary script that did the basic function was about as easy as I thought. It took only a few minutes and worked reasonably well. The problem is that there are lots of little gotchas and edge-cases where something might not work in some specific circumstance or if some other specific expectation exists. I’m still working on an enhanced version of the script that handles double-clicks and dragging, but while there’s plenty of examples and attempts, there are no solid, effective, and concise examples of handling these quite right at this time, so it’s a work in progress.)


In any case, the script below is an older version that I threw together (and cleaned up a bit for public consumption). It does what was asked (and a little more). There’s no real manual; you just run the script and it starts up in the mirroring mode. Mouse-clicks on either side of the screen are duplicated on the other (vertical) half. There are a few hotkeys that can be used to modify the script behavior:

  • Alt+Shift+Q turns mirroring on and off
  • Ctrl+Shift+Q turns autofire (rapid-repeat) on and off
  • Ctrl+Alt+Shift+Q pauses the script so that the mouse behaves normally
  • Ctrl+Alt+Shift+Win+Q exits the script


Here is a sample output of the script:

Screenshot of Mirror.ahk output

Mirror.ahk

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Mirror.ahk mirrors mouse clicks on one half of the screen to the other half
; http://superuser.com/questions/393738/
;
;   (cl) 2012- Synetech inc., Alec Soroudi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Hotkeys:
;       Alt+Shift+Q                     to toggle mirroring
;       Ctrl+Shift+Q                    to toggle autofire
;       Ctrl+Alt+Shift+Q            to completely pause the script (mouse behaves normally)
;       Ctrl+Alt+Shift+Win+Q    to quit
;
;       Defaults to single-click, mirrored
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#SingleInstance force
CoordMode, Mouse, Screen
SetDefaultMouseSpeed, 0
SetMouseDelay, -1
SendMode Play                                       ;Try modes Event, Input, or Play


;Variables
SysGet, MonitorWorkArea, MonitorWorkArea, %A_Index%
Half            :=  (MonitorWorkAreaRight - MonitorWorkAreaLeft) >> 1
Mirror      :=  1
Autofire    :=  0



;Main function
Dupe(action, var) {
    ;Calculate other half
    MouseGetPos, x,y
    Global Half
    if (x<Half) {
        Left := (Half + x)
    }
    else {
        Left := (x - Half)
    }

    Global Mirror
    if (action=0) {                             ;Mouse
        if (var=0) {                                ;Left-click
            if Mirror
                Click %Left% %y% Left
            Click %x% %y% Left
        }

        else if (var=1) {                       ;Right-click
            Click %Left% %y% Right
            Click %x% %y% Right
        }

        else if (var=2) {                       ;Middle-click
            Click %Left% %y% Middle
            Click %x% %y% Middle
        }

        else if (var=3) {                       ;Button4-click
            Click %Left% %y% X1
            Click %x% %y% X1
        }

        else if (var=4) {                       ;Button5-click
            Click %Left% %y% X2
            Click %x% %y% X2
        }
    }


;   else if (action=1) {                    ;Keyboard - do what???
;   }
}



;Hotkeys
!+q::                                                       ;Pause mirroring with Alt+Shift+Q
    Mirror := !Mirror
;   MsgBox  Mirror: %Mirror%
return

^+q::                                                       ;Toggle autofire with Ctrl+Shift+Q
    Autofire := !Autofire
;   MsgBox  Autofire: %Autofire%
return

^!+q::                                                  ;Pause script with Ctrl+Alt+Shift+Q
    Suspend
;   if (A_IsSuspended = 1)
;       MsgBox  Hotkeys suspended
;   else
;       MsgBox  Hotkeys resumed
return

^!+#q::                                                 ;Quit with Ctrl+Alt+Shift+Win+Q
;   MsgBox Quitting
    ExitApp
return

+#q::                                                       ;Reload/restart script with Shift+Win+Q
;   MsgBox Reloading
    Reload
return



;Handlers
*$LButton::
Loop {
;       if (Mirror)
            Dupe(0, 0)
        GetKeyState, State, LButton, P
        if (!Autofire || State = "U")
            Break
}
return

*$RButton::
Loop {
        if (Mirror)
            Dupe(0, 1)
        GetKeyState, State, RButton, P
        if (!Autofire || State = "U")
            Break
}
return

*$MButton::
Loop {
        if (Mirror)
            Dupe(0, 2)
        GetKeyState, State, MButton, P
        if (!Autofire || State = "U")
            Break
}
return

*$XButton1::
Loop {
        if (Mirror)
            Dupe(0, 3)
        GetKeyState, State, XButton1, P
        if (!Autofire || State = "U")
            Break
}
return

*$XButton2::
Loop {
        if (Mirror)
            Dupe(0, 4)
        GetKeyState, State, XButton2, P
        if (!Autofire || State = "U")
            Break
}
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5
  • can you tell what is the differences between auto- and no autofire?
    – Ooker
    Jan 21, 2018 at 9:49
  • 1
    With auto-fire on, it keeps drawing dots while you hold the mouse-button down. With it off, you have to click the mouse-button for each dot.
    – Synetech
    Jan 22, 2018 at 16:31
  • 1
    how do I get it to work I tried it out but it wont not click Mar 26, 2019 at 8:47
  • 4
    Tried this on Windows 10, too - no click events are fired anymore while the script is running. Any ideas, what to change in the script? Apr 25, 2019 at 16:31
  • Drag and drop does not work, and will never work without emulating "multi-touch gestures". I mean, above emulates "mouse" jumping to other side and clicking there as well, but because said jumping counts as dragging, same hack/trick is not possible for dragging.
    – Top-Master
    May 17, 2023 at 5:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .