Rev 5 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
//
// MouseHandler.swift
// GyroServer
//
// Created by Matteo Riva on 07/08/15.
// Copyright © 2015 Matteo Riva. All rights reserved.
//
import CoreGraphics
import Cocoa
import Carbon
import CoreServices
class MouseHandler: NSObject, ServerHandlerDelegate {
private let server = ServerHandler()
private var activeScreen: Int {
get {
return UserDefaults.standard.integer(forKey: "activeScreen")
}
}
private var mLoc: (x: CGFloat, y: CGFloat) = (x: 0, y: 0)
private var isDragging = false
override init() {
super.init()
resetPointerPosition(moveMouse: false)
server.startBroadcast()
NotificationCenter.default.addObserver(forName: ActiveScreenDidChangeNotification, object: nil, queue: OperationQueue.main) {[unowned self] (_) -> Void in
self.resetPointerPosition(moveMouse: false)
}
NotificationCenter.default.addObserver(forName: ServerDidConnectNotification, object: nil, queue: OperationQueue.main) {[unowned self] (_) -> Void in
self.resetPointerPosition(moveMouse: true)
self.server.delegate = self
}
NotificationCenter.default.addObserver(forName: ServerDidDisconnectNotification, object: nil, queue: OperationQueue.main) {[unowned self] (_) -> Void in
self.server.delegate = nil
self.resetPointerPosition(moveMouse: false)
}
}
deinit {
NotificationCenter.default.removeObserver(self)
}
//MARK: - Mouse movements
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) ]
func computePointerMovement(grav: (X: Double, Y: Double, Z: Double), rotat: (X: Double, Z: Double), acc: (X: Double, Y: Double, Z: Double), moveVelocity: Double) {
let frame = NSScreen.screens[activeScreen].frame
let bounds = (origin: frame.origin, width: frame.maxX - 1, height: frame.maxY - 1)
// compute new mouse location
mLoc = (
x: max(bounds.origin.x, min(mLoc.x + CGFloat((rotat.Z * -1) * (1 + abs(acc.Z)) * moveVelocity * abs(grav.Z)), bounds.width)),
y: max(0, min(mLoc.y + CGFloat((rotat.X * -1) * (1 + abs(acc.X)) * moveVelocity * abs(grav.Z)), bounds.height))
)
// initialize history array
for i in 0...(averagedPoints.count - 1) {
if ((averagedPoints[i].x == -1) && (averagedPoints[i].y == -1)) {
averagedPoints[0].x = mLoc.x
averagedPoints[0].y = mLoc.y
}
}
// shift history array and insert new position at the end
for i in 0...(averagedPoints.count - 2) {
averagedPoints[i].x = averagedPoints[i + 1].x
averagedPoints[i].y = averagedPoints[i + 1].y
}
averagedPoints[averagedPoints.count - 1].x = mLoc.x
averagedPoints[averagedPoints.count - 1].y = mLoc.y
// compute averaged coordinates
var averagedPoint = CGPoint(x: 0, y: 0)
for i in 0...(averagedPoints.count - 1) {
averagedPoint.x += averagedPoints[i].x
averagedPoint.y += averagedPoints[i].y
}
averagedPoint.x /= CGFloat(averagedPoints.count)
averagedPoint.y /= CGFloat(averagedPoints.count)
//print ("Updated mouse pos to \(averagedPoint.x),\(averagedPoint.y)")
let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: averagedPoint, mouseButton: .left)
mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
if (isDragging) {
let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDragged, mouseCursorPosition: averagedPoint, mouseButton: .left)
mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
}
}
func resetPointerPosition(moveMouse: Bool) {
let aIndex = UserDefaults.standard.integer(forKey: "activeScreen")
let frame = NSScreen.screens[aIndex].frame
let x = frame.midX
let y = frame.midY - frame.origin.y
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)
mLoc = (x: x, y: y)
if moveMouse {
let point = CGPoint(x: x, y: y)
let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: point, mouseButton: .left)
mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
}
}
//MARK: - Mouse actions
var rollGate = 0
func scrollWithRoll(roll: Double, velocity: Double) {
rollGate += 1
if rollGate == 10 {
let amount = (Int32) (roll * velocity * -50)
let mouseEvent = CGEvent(scrollWheelEvent2Source: nil, units: .pixel, wheelCount: 1, wheel1: amount, wheel2: 0, wheel3: 0)
mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
rollGate = 0
}
}
func clickButton(isRightButton: Bool, isButtonDown: Bool) {
let mousePos = CGPoint(x: mLoc.x, y: mLoc.y)
let mouseEventType: CGEventType
let mouseButton: CGMouseButton
if (isRightButton) {
mouseButton = .right
mouseEventType = (isButtonDown ? .rightMouseDown : .rightMouseUp)
isDragging = false
} else {
mouseButton = .left
mouseEventType = (isButtonDown ? .leftMouseDown : .leftMouseUp)
isDragging = isButtonDown
}
let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: mouseEventType, mouseCursorPosition: mousePos, mouseButton: mouseButton)
mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
}
//MARK: - AppleScript launcher
func runAppleScript(_ scriptText: String) {
let script = NSAppleScript(source: scriptText)!
var error: NSDictionary? = nil
let resultMaybe = script.executeAndReturnError(&error) as NSAppleEventDescriptor?
if (resultMaybe == nil)
{
let myStringDict = error as? [String:AnyObject]
if (myStringDict?["NSAppleScriptErrorNumber"] as! Int16 == 1002) {
let alert = NSAlert()
alert.addButton(withTitle: "OK".localized)
alert.messageText = "system_message".localized + "\n" + (myStringDict?["NSAppleScriptErrorBriefMessage"] as! String)
alert.informativeText = "allow_perms".localized
alert.alertStyle = .warning
alert.runModal()
}
print (error as Any)
return
}
}
}