11import Cocoa
22import Carbon. HIToolbox
33import ServiceManagement
4+ import IOKit. pwr_mgt
45
56extension Notification . Name {
67 static let screenCursorSettingsChanged = Notification . Name ( " ScreenCursor.settingsChanged " )
@@ -206,6 +207,7 @@ final class JiggleController {
206207 private var pollTimer : Timer ?
207208 private var lastMousePosition : NSPoint = . zero
208209 private var lastActivityAt : Date = Date ( )
210+ private var assertionID : IOPMAssertionID = IOPMAssertionID ( 0 )
209211
210212 init ( ) {
211213 NotificationCenter . default. addObserver (
@@ -225,6 +227,7 @@ final class JiggleController {
225227 func stop( ) {
226228 pollTimer? . invalidate ( )
227229 pollTimer = nil
230+ releaseAssertion ( )
228231 }
229232
230233 @objc private func settingsChanged( ) {
@@ -234,13 +237,33 @@ final class JiggleController {
234237 private func applySettings( ) {
235238 pollTimer? . invalidate ( )
236239 pollTimer = nil
237- guard SettingsStore . shared. jiggleEnabled else { return }
240+ guard SettingsStore . shared. jiggleEnabled else {
241+ releaseAssertion ( )
242+ return
243+ }
244+ createAssertion ( )
238245 pollTimer = Timer . scheduledTimer ( withTimeInterval: 1.0 , repeats: true ) { [ weak self] _ in
239246 self ? . checkAndJiggle ( )
240247 }
241248 RunLoop . main. add ( pollTimer!, forMode: . common)
242249 }
243250
251+ private func createAssertion( ) {
252+ releaseAssertion ( )
253+ IOPMAssertionCreateWithName (
254+ kIOPMAssertionTypePreventUserIdleDisplaySleep as CFString ,
255+ IOPMAssertionLevel ( kIOPMAssertionLevelOn) ,
256+ " Screen Cursor Jiggle " as CFString ,
257+ & assertionID
258+ )
259+ }
260+
261+ private func releaseAssertion( ) {
262+ guard assertionID != IOPMAssertionID ( 0 ) else { return }
263+ IOPMAssertionRelease ( assertionID)
264+ assertionID = IOPMAssertionID ( 0 )
265+ }
266+
244267 private func checkAndJiggle( ) {
245268 let current = NSEvent . mouseLocation
246269 if current != lastMousePosition {
@@ -256,15 +279,47 @@ final class JiggleController {
256279
257280 private func performJiggle( ) {
258281 guard let origin = CGEvent ( source: nil ) ? . location else { return }
259- let steps : [ ( CGPoint , TimeInterval ) ] = [
260- ( CGPoint ( x: origin. x, y: origin. y - 1 ) , 0.0 ) ,
261- ( CGPoint ( x: origin. x, y: origin. y + 1 ) , 0.1 ) ,
262- ( CGPoint ( x: origin. x + 1 , y: origin. y) , 0.2 ) ,
263- ( origin, 0.3 ) ,
264- ]
265- for (point, delay) in steps {
266- DispatchQueue . main. asyncAfter ( deadline: . now( ) + delay) {
267- CGWarpMouseCursorPosition ( point)
282+
283+ var displayID = CGMainDisplayID ( )
284+ var displayCount : UInt32 = 0
285+ CGGetDisplaysWithPoint ( origin, 1 , & displayID, & displayCount)
286+ let screen = CGDisplayBounds ( displayID)
287+
288+ let delta : CGFloat = 150
289+ let right = screen. maxX - origin. x
290+ let left = origin. x - screen. minX
291+ let down = screen. maxY - origin. y
292+ let up = origin. y - screen. minY
293+
294+ let dx : CGFloat
295+ let dy : CGFloat
296+ if right >= left && right >= down && right >= up {
297+ dx = min ( delta, right - 5 ) ; dy = 0
298+ } else if left >= down && left >= up {
299+ dx = - min( delta, left - 5 ) ; dy = 0
300+ } else if down >= up {
301+ dx = 0 ; dy = min ( delta, down - 5 )
302+ } else {
303+ dx = 0 ; dy = - min( delta, up - 5 )
304+ }
305+
306+ let steps = 20
307+ let stepDelay = 0.025
308+ let returnOffset = stepDelay * Double( steps) + 0.1
309+
310+ for i in 1 ... steps {
311+ let t = CGFloat ( i) / CGFloat( steps)
312+ let pt = CGPoint ( x: origin. x + dx * t, y: origin. y + dy * t)
313+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + stepDelay * Double( i) ) {
314+ CGWarpMouseCursorPosition ( pt)
315+ CGAssociateMouseAndMouseCursorPosition ( 1 )
316+ }
317+ }
318+ for i in 1 ... steps {
319+ let t = CGFloat ( i) / CGFloat( steps)
320+ let pt = CGPoint ( x: origin. x + dx * ( 1.0 - t) , y: origin. y + dy * ( 1.0 - t) )
321+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + returnOffset + stepDelay * Double( i) ) {
322+ CGWarpMouseCursorPosition ( pt)
268323 CGAssociateMouseAndMouseCursorPosition ( 1 )
269324 }
270325 }
0 commit comments