How can I mimic inertial scrolling via CGEvent?

Viewed 27

I want allow users of my app to scroll with an ease-in and ease-out animation using a CGEvent. This answer showed me how to send the scroll event, and I have a simple playground below to attempt to demonstrate what I would like to do. I can't find an easy API to do this, so I figured I would have to scroll a few dozen times (at least) with delays in between. If there's an easier way, I would love to find it! Naturally I could increase the resolution of my scrollY function, but I'm hoping somebody else knows of an easier, smoother way to do this.

extension CGEvent {
  public class func scrollMouse(onPoint point: CGPoint, xLines: Int, yLines: Int) {
    if #available(OSX 10.13, *) {
      guard let scrollEvent = CGEvent(scrollWheelEvent2Source: nil, units: CGScrollEventUnit.line, wheelCount: 2, wheel1: Int32(yLines), wheel2: Int32(xLines), wheel3: 0) else {
        return
      }
      scrollEvent.setIntegerValueField(CGEventField.eventSourceUserData, value: 1)
      scrollEvent.post(tap: CGEventTapLocation.cghidEventTap)
    } else {
      // scroll event is not supported for macOS older than 10.13
    }
  }
}


func scrollY() {
  let y = 12
  let sleep: UInt32 = 10000
  
  // The ease-IN portion
  for i in stride(from: 1, to: y, by: 1) {
    CGEvent.scrollMouse(onPoint: CGPoint.zero, xLines: 0, yLines:-i)
    usleep(sleep * UInt32(i))
  }
  
  // The ease-OUT portion
  for i in stride(from: y, to: 1, by: -1) {
    CGEvent.scrollMouse(onPoint: CGPoint.zero, xLines: 0, yLines:-i)
    usleep(sleep * UInt32(y + (y - i)))
  }
}
0 Answers
Related