Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | // |
2 | // MouseHandler.swift |
||
3 | // GyroServer |
||
4 | // |
||
5 | // Created by Matteo Riva on 07/08/15. |
||
6 | // Copyright © 2015 Matteo Riva. All rights reserved. |
||
7 | // |
||
8 | |||
9 | import CoreGraphics |
||
10 | import Cocoa |
||
11 | import Carbon |
||
12 | import CoreServices |
||
13 | |||
14 | class MouseHandler: NSObject, ServerHandlerDelegate { |
||
15 | |||
16 | private let server = ServerHandler() |
||
17 | |||
18 | private var activeScreen: Int { |
||
19 | get { |
||
20 | return UserDefaults.standard.integer(forKey: "activeScreen") |
||
21 | } |
||
22 | } |
||
23 | private var mLoc: (x: CGFloat, y: CGFloat) = (x: 0, y: 0) |
||
24 | private var isDragging = false |
||
25 | |||
26 | override init() { |
||
27 | super.init() |
||
28 | resetPointerPosition(moveMouse: false) |
||
29 | server.startBroadcast() |
||
30 | NotificationCenter.default.addObserver(forName: ActiveScreenDidChangeNotification, object: nil, queue: OperationQueue.main) {[unowned self] (_) -> Void in |
||
31 | self.resetPointerPosition(moveMouse: false) |
||
32 | } |
||
33 | NotificationCenter.default.addObserver(forName: ServerDidConnectNotification, object: nil, queue: OperationQueue.main) {[unowned self] (_) -> Void in |
||
34 | self.resetPointerPosition(moveMouse: true) |
||
35 | self.server.delegate = self |
||
36 | } |
||
37 | NotificationCenter.default.addObserver(forName: ServerDidDisconnectNotification, object: nil, queue: OperationQueue.main) {[unowned self] (_) -> Void in |
||
38 | self.server.delegate = nil |
||
39 | self.resetPointerPosition(moveMouse: false) |
||
40 | } |
||
41 | } |
||
42 | |||
43 | deinit { |
||
44 | NotificationCenter.default.removeObserver(self) |
||
45 | } |
||
46 | |||
47 | //MARK: - Mouse movements |
||
7 | pmbaty | 48 | |
49 | var averagedPoints: [CGPoint] = [ CGPoint(x: -1, y: -1), CGPoint(x: -1, y: -1), CGPoint(x: -1, y: -1), CGPoint(x: -1, y: -1), CGPoint(x: -1, y: -1), CGPoint(x: -1, y: -1) ] |
||
1 | pmbaty | 50 | |
7 | pmbaty | 51 | func computePointerMovement(grav: (X: Double, Y: Double, Z: Double), rotat: (X: Double, Z: Double), acc: (X: Double, Y: Double, Z: Double), moveVelocity: Double) { |
1 | pmbaty | 52 | let frame = NSScreen.screens[activeScreen].frame |
7 | pmbaty | 53 | let bounds = (origin: frame.origin, width: frame.maxX - 1, height: frame.maxY - 1) |
1 | pmbaty | 54 | |
7 | pmbaty | 55 | // compute new mouse location |
56 | mLoc = ( |
||
57 | x: max(bounds.origin.x, min(mLoc.x + CGFloat((rotat.Z * -1) * (1 + abs(acc.Z)) * moveVelocity * abs(grav.Z)), bounds.width)), |
||
58 | y: max(0, min(mLoc.y + CGFloat((rotat.X * -1) * (1 + abs(acc.X)) * moveVelocity * abs(grav.Z)), bounds.height)) |
||
59 | ) |
||
1 | pmbaty | 60 | |
7 | pmbaty | 61 | // initialize history array |
62 | for i in 0...(averagedPoints.count - 1) { |
||
63 | if ((averagedPoints[i].x == -1) && (averagedPoints[i].y == -1)) { |
||
64 | averagedPoints[0].x = mLoc.x |
||
65 | averagedPoints[0].y = mLoc.y |
||
66 | } |
||
67 | } |
||
68 | |||
69 | // shift history array and insert new position at the end |
||
70 | for i in 0...(averagedPoints.count - 2) { |
||
71 | averagedPoints[i].x = averagedPoints[i + 1].x |
||
72 | averagedPoints[i].y = averagedPoints[i + 1].y |
||
73 | } |
||
74 | averagedPoints[averagedPoints.count - 1].x = mLoc.x |
||
75 | averagedPoints[averagedPoints.count - 1].y = mLoc.y |
||
76 | |||
77 | // compute averaged coordinates |
||
78 | var averagedPoint = CGPoint(x: 0, y: 0) |
||
79 | for i in 0...(averagedPoints.count - 1) { |
||
80 | averagedPoint.x += averagedPoints[i].x |
||
81 | averagedPoint.y += averagedPoints[i].y |
||
82 | } |
||
83 | averagedPoint.x /= CGFloat(averagedPoints.count) |
||
84 | averagedPoint.y /= CGFloat(averagedPoints.count) |
||
85 | |||
86 | //print ("Updated mouse pos to \(averagedPoint.x),\(averagedPoint.y)") |
||
87 | |||
88 | let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: averagedPoint, mouseButton: .left) |
||
1 | pmbaty | 89 | mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap) |
90 | |||
7 | pmbaty | 91 | if (isDragging) { |
92 | let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDragged, mouseCursorPosition: averagedPoint, mouseButton: .left) |
||
1 | pmbaty | 93 | mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap) |
94 | } |
||
95 | } |
||
96 | |||
97 | func resetPointerPosition(moveMouse: Bool) { |
||
98 | let aIndex = UserDefaults.standard.integer(forKey: "activeScreen") |
||
99 | let frame = NSScreen.screens[aIndex].frame |
||
100 | let x = frame.midX |
||
101 | let y = frame.midY - frame.origin.y |
||
102 | NSLog("x: %f, y: %f, origin x: %f, y: %f, mid x: %f, y: %f", x,y,frame.origin.x, frame.origin.y, frame.midX, frame.midY) |
||
103 | mLoc = (x: x, y: y) |
||
104 | if moveMouse { |
||
105 | let point = CGPoint(x: x, y: y) |
||
106 | let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: point, mouseButton: .left) |
||
107 | mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap) |
||
108 | } |
||
109 | } |
||
110 | |||
111 | //MARK: - Mouse actions |
||
112 | |||
113 | var rollGate = 0 |
||
114 | |||
7 | pmbaty | 115 | func scrollWithRoll(roll: Double, velocity: Double) { |
1 | pmbaty | 116 | rollGate += 1 |
117 | if rollGate == 10 { |
||
118 | let amount = (Int32) (roll * velocity * -50) |
||
119 | let mouseEvent = CGEvent(scrollWheelEvent2Source: nil, units: .pixel, wheelCount: 1, wheel1: amount, wheel2: 0, wheel3: 0) |
||
120 | mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap) |
||
121 | |||
122 | rollGate = 0 |
||
123 | } |
||
124 | } |
||
125 | |||
7 | pmbaty | 126 | func clickButton(isRightButton: Bool, isButtonDown: Bool) { |
1 | pmbaty | 127 | let mousePos = CGPoint(x: mLoc.x, y: mLoc.y) |
128 | let mouseEventType: CGEventType |
||
129 | let mouseButton: CGMouseButton |
||
130 | |||
7 | pmbaty | 131 | if (isRightButton) { |
1 | pmbaty | 132 | mouseButton = .right |
7 | pmbaty | 133 | mouseEventType = (isButtonDown ? .rightMouseDown : .rightMouseUp) |
1 | pmbaty | 134 | isDragging = false |
7 | pmbaty | 135 | } else { |
136 | mouseButton = .left |
||
137 | mouseEventType = (isButtonDown ? .leftMouseDown : .leftMouseUp) |
||
138 | isDragging = isButtonDown |
||
1 | pmbaty | 139 | } |
140 | |||
141 | let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: mouseEventType, mouseCursorPosition: mousePos, mouseButton: mouseButton) |
||
142 | mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap) |
||
143 | } |
||
144 | |||
145 | //MARK: - AppleScript launcher |
||
146 | |||
7 | pmbaty | 147 | func runAppleScript(_ scriptText: String) { |
1 | pmbaty | 148 | let script = NSAppleScript(source: scriptText)! |
149 | var error: NSDictionary? = nil |
||
150 | let resultMaybe = script.executeAndReturnError(&error) as NSAppleEventDescriptor? |
||
5 | pmbaty | 151 | if (resultMaybe == nil) |
1 | pmbaty | 152 | { |
5 | pmbaty | 153 | let myStringDict = error as? [String:AnyObject] |
154 | if (myStringDict?["NSAppleScriptErrorNumber"] as! Int16 == 1002) { |
||
155 | let alert = NSAlert() |
||
156 | alert.addButton(withTitle: "OK".localized) |
||
157 | alert.messageText = "system_message".localized + "\n" + (myStringDict?["NSAppleScriptErrorBriefMessage"] as! String) |
||
158 | alert.informativeText = "allow_perms".localized |
||
159 | alert.alertStyle = .warning |
||
160 | alert.runModal() |
||
161 | } |
||
1 | pmbaty | 162 | print (error as Any) |
163 | return |
||
164 | } |
||
165 | } |
||
166 | } |