title: Moving a window using Accessibility API excessively slow when using multiple displays macOS Swift
body: <p><strong>Problem summary:</strong></p>
  <p>I'm working on my own window manager for macOS and one of the features involves moving the windows of other applications using mouse events and the Accessibility API.  I create event taps for key pressed and mouse moved events with <code>CGEvent.tapCreate</code> and after my &quot;move mode&quot; is entered by pressing cmd+w I feed mouse moved deltas (while freezing the cursor sprite itself) to a function that takes the location of the currently focused window, adds the deltas, and sets the position of the window (an <code>AXUIElement</code>) by using <code>AXUIElementSetAttributeValue(windowElement, kAXPositionAttribute as CFString, position)</code>.  This gets called a lot, once for every mouse moved event, and works fine when I have one display (built in MacBook display).  Very snappy, no discernible lag, the window gets moved around <em>as if</em> it were the cursor.</p>
  <p>However, when I test with more than one display (I've tested using either or both of a wired Dell monitor and a sidecar iPad), I get <em>very</em> inconsistent behavior and generally a lot of lag during window movement.  The movement seems to be mostly correct, but delayed (the window might keep moving for as much as a few seconds after I lift my finger from the trackpad, or keep moving in the opposite direction of where I'm moving my finger for a bit).</p>
  <p>Sometimes the movement is snappy and correct on one or more displays (otherwise identical behavior to using a single display), but slow on others.  Which displays are affected seems random between launches.  On one occasion moving my &quot;Terminal&quot; window was consistently snappy while &quot;Notes&quot; was slow.  The most common case is just generally sluggish behavior across all displays.  Usually at some point the mouse event tap will stop (I guess taking too long causes this to happen).  I could restart it but that doesn't really solve the problem.</p>
  <p><strong>What I've tried:</strong></p>
  <p>Using Instruments (which I'm a novice at so I may have missed something) &amp; timing code I'm 95% sure the problem is with using the call to <code>AXUIElementSetAttributeValue</code> to set the window position.  If I take out all the logic regarding <em>where</em> to set (not getting where the window is currently, etc.) and just set the window to the same location repeatedly in response to mouse events, I can still observe the mouse event tap getting stopped (fails pretty silently).  Doing <em>all</em> the logic <em>except</em> the location setting doesn't take long enough to stop the tap.</p>
  <p>In researching approaches to accomplish what I want I found the following links:</p>
  <p><a href="https://stackoverflow.com/questions/21069066/move-other-windows-on-mac-os-x-using-accessibility-api?rq=1">Move other windows on Mac OS X using Accessibility API</a></p>
  <p><a href="https://stackoverflow.com/questions/4231110/how-can-i-move-resize-windows-programmatically-from-another-application">How can I move/resize windows programmatically from another application?</a></p>
  <p><a href="https://stackoverflow.com/questions/614185/window-move-and-resize-apis-in-os-x">Window move and resize APIs in OS X</a></p>
  <ul>
  <li>Seem to be Obj-C versions of the same approach I'm using</li>
  </ul>
  <p><a href="https://stackoverflow.com/questions/47480873/set-the-size-and-position-of-all-windows-on-the-screen-in-swift">set the size and position of all windows on the screen in swift</a></p>
  <ul>
  <li>Swift approach to what I'm doing, very similar to my window movement code</li>
  </ul>
  <p><a href="https://stackoverflow.com/questions/4927592/i-want-to-animate-the-movement-of-a-foreign-os-x-apps-window">I want to animate the movement of a foreign OS X app&#39;s window</a></p>
  <ul>
  <li>This approach is about custom animating window movement rather than just moving but the asker indicates that they were able to move foreign windows by &quot;getting an <code>AXUIElementRef</code> that holds the AXUIElement associated with the focused window, then setting the <code>NSAccessibilityPositionAttribute</code>.&quot;  I have not been able to find more details about this approach and a lot of NSAccessibility stuff appears to have since been deprecated.</li>
  </ul>
  <p>I also looked at various Apple docs including Quartz and of course a ton of Accessibility as well as other less useful sources.  Nowhere did I find any mentions of performance discrepancy when using the Accessibility API with multiple displays.</p>
  <p><strong>Code:</strong></p>
  <pre><code>// CODE FOR MOVING A WINDOW
  class WindowTransformer {
  
  var windowElement:AXUIElement?
  
  init?(forWindowWithPid: pid_t) {
      // Make Accessibility object for given PID
      let accessApp:AXUIElement = AXUIElementCreateApplication(forWindowWithPid)
      var windowData:AnyObject?
      AXUIElementCopyAttributeValue(accessApp, kAXWindowsAttribute as CFString, &amp;windowData)
      windowElement = (windowData as? [AXUIElement])?.first
      guard let _ = windowElement else { return nil }
  }
  
  func transformWindowWithDeltas(x: CGFloat, y: CGFloat) {
      let current = getCurrentWindowPosition()
      guard let current = current else { return }
      let newX = current.x + x
      let newY = current.y + y
      setPosition(to: CGPoint(x: newX, y: newY))
  }
  
  func getCurrentWindowPosition() -&gt; CGPoint? {
      if windowElement == nil { return nil }
      var positionData:CFTypeRef?
      AXUIElementCopyAttributeValue(windowElement!,
                                    kAXPositionAttribute as CFString,
                                    &amp;positionData)  
      let currentPos = axValueAsCGPoint(positionData! as! AXValue)
      return currentPos
  }
  
  func axValueAsCGPoint(_ value: AXValue) -&gt; CGPoint {
      var point = CGPoint.zero
      AXValueGetValue(value, AXValueType.cgPoint, &amp;point)
      return point
  }
  
  func setPosition(to: CGPoint) {
      var newPoint = to
      let position:CFTypeRef? = AXValueCreate(AXValueType(rawValue: kAXValueCGPointType)!, &amp;newPoint)
      // What I think is causing issues
      let err = AXUIElementSetAttributeValue(windowElement!, kAXPositionAttribute as CFString, position!)
      if err != .success {
          // I've never seen this happen
          print(&quot;AXError moving window \(err)&quot;)
      }
  }
  
  }
  </code></pre>
  <hr />
  <pre><code>// CODE THAT GETS EXECUTED ON RECEIVING MOUSE EVENTS
  
  // Gets set to true when in &quot;move mode&quot;
  var listeningAndEscapeFlag = false
  // I have a notification center observer that updates this when applications are activated, will probably change how this is set eventually
  var activePid:pid_t
  var transformer:WindowTransformer?
  
  func mouseEventAction(event: CGEvent) -&gt; Unmanaged&lt;CGEvent&gt;? {
  
      let unmodifiedEvent = Unmanaged.passRetained(event)
  
      if !listeningEscapeAndMouseFlag { return unmodifiedEvent }
      guard let activePid = activePid else { return unmodifiedEvent }
  
      if transformer == nil {
          transformer = WindowTransformer(forWindowWithPid: activePid)
      }
  
      let eventLocation = event.location
  
      let deltaEvent = NSEvent.init(cgEvent: event)
      let deltaX = deltaEvent?.deltaX
      let deltaY = deltaEvent?.deltaY
  
      guard let deltaX = deltaX, let deltaY = deltaY else { return nil }
  
      // Attempt to move window based on mouse events
      transformer?.transformWindowWithDeltas(x: deltaX, y: deltaY)
  
      // Keeps cursor visibly frozen
      CGWarpMouseCursorPosition(eventLocation)
  
      return nil
  }
  
  // Gets passed as callback argument to CGEvent.tapCreate
  func mouse_interceptor_callback(tapProxy: CGEventTapProxy,
                                  eventType: CGEventType,
                                  event: CGEvent,
                                  data: UnsafeMutableRawPointer?) -&gt; Unmanaged&lt;CGEvent&gt;? {
  
      // I'm pretty sure modifying mouseMoved events directly doesn't actually do anything
      let unmodifiedEvent = Unmanaged.passRetained(event)
      
      if eventType != .mouseMoved {
          return unmodifiedEvent
      }
  
      return mouseEventAction(event)
  }
  
  </code></pre>
  <pre><code>// HOW I'M CREATING A TAP
  
  var port:CFMachPort?
  
  func createMouseTap() {
      let mask:CGEventMask = CGEventMask(1 &lt;&lt; CGEventType.mouseMoved.rawValue)
      port = CGEvent.tapCreate(tap: CGEventTapLocation.cghidEventTap, // Tap at place where system events enter window server
                               place: CGEventTapPlacement.headInsertEventTap, // Insert before other taps
                               options: CGEventTapOptions.defaultTap, // Can modify events
                               eventsOfInterest: mask,
                               callback: mouse_interceptor_callback, // fn to run on event
                               userInfo: nil)
  }
  
  func activateTap() {
      guard let port = port else { return }
      CGEvent.tapEnable(tap: port, enable: true)
      let runLoopSrc = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, port, 0)
      CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSrc, .commonModes)
  }
  
  </code></pre>
  <p><strong>Notes:</strong></p>
  <ul>
  <li>There are some modifications and omissions from my actual code for brevity but this is the code that is directly involved in what I'm attempting to do.</li>
  <li>My computer performs well and there are no delays with other applications (or dragging windows manually) when using multiple displays.</li>
  </ul>