Subversion Repositories Mobile Apps.GyroMouse

Rev

Rev 1 | Go to most recent revision | 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
48
 
49
    private func computePointerMovementWithPacket(_ packet: GyroPacket) {
50
         let roll = packet.roll
51
        let sgn: Double = roll ?? 0 < 0 ? -1 : 1
52
        let gate = 0.75
53
        let changeMovCond = roll == nil || (roll! > -gate && roll! < gate)
54
 
55
        let rotatZ = changeMovCond ? packet.rotatZ! : packet.rotatX! * -sgn
56
        let accZ = changeMovCond ? packet.accZ! : packet.accX!
57
        let rotatX = changeMovCond ? packet.rotatX! : packet.rotatZ! * sgn
58
        let accX = changeMovCond ? packet.accX! : packet.accZ!
59
        let gravZ = changeMovCond ? packet.gravZ! : packet.gravX! * sgn
60
 
61
        var dx = ((rotatZ * -1) * (1 + abs(accZ))) * packet.moveVelocity! * abs(gravZ)
62
        var dy = ((rotatX * -1) * (1 + abs(accX))) * packet.moveVelocity! * abs(gravZ)
63
 
64
        if packet.type == .scroll {
65
            dx = min(dx,1)
66
            dy = min(dy,1)
67
        }
68
 
69
        var x = mLoc.x + CGFloat(dx)
70
        var y = mLoc.y + CGFloat(dy)
71
 
72
        let frame = NSScreen.screens[activeScreen].frame
73
        let s = (o: frame.origin, w: frame.maxX - 1, h: frame.maxY - 1)
74
 
75
        mLoc = (x: x, y: y)
76
        x = max(s.o.x,min(x, s.w))
77
        y = max(0,min(y, s.h))
78
 
79
        let point = CGPoint(x: x, y: y)
80
 
81
        let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: point, mouseButton: .left)
82
        mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
83
 
84
        if isDragging {
85
             let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDragged, mouseCursorPosition: point, mouseButton: .left)
86
            mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
87
        }
88
    }
89
 
90
    func resetPointerPosition(moveMouse: Bool) {
91
        let aIndex = UserDefaults.standard.integer(forKey: "activeScreen")
92
        let frame = NSScreen.screens[aIndex].frame
93
        let x = frame.midX
94
        let y = frame.midY - frame.origin.y
95
        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)
96
        mLoc = (x: x, y: y)
97
        if moveMouse {
98
            let point = CGPoint(x: x, y: y)
99
            let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: point, mouseButton: .left)
100
            mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
101
        }
102
    }
103
 
104
    //MARK: - Mouse actions
105
 
106
    var rollGate = 0
107
 
108
    private func scrollWithRoll(_ roll: Double, velocity: Double) {
109
        rollGate += 1
110
        if rollGate == 10 {
111
            let amount = (Int32) (roll * velocity * -50)
112
            let mouseEvent = CGEvent(scrollWheelEvent2Source: nil, units: .pixel, wheelCount: 1, wheel1: amount, wheel2: 0, wheel3: 0)
113
            mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
114
 
115
            rollGate = 0
116
        }
117
    }
118
 
119
    private func clickButton(_ button: ButtonType, click: ClickType) {
120
        let mousePos = CGPoint(x: mLoc.x, y: mLoc.y)
121
        let mouseEventType: CGEventType
122
        let mouseButton: CGMouseButton
123
 
124
        if button == .left {
125
            mouseButton = .left
126
            mouseEventType = (click == .down ? .leftMouseDown : .leftMouseUp)
127
            isDragging = (click == .down)
128
        } else {
129
            mouseButton = .right
130
            mouseEventType = (click == .down ? .rightMouseDown : .rightMouseUp)
131
            isDragging = false
132
        }
133
 
134
        let mouseEvent = CGEvent(mouseEventSource: nil, mouseType: mouseEventType, mouseCursorPosition: mousePos, mouseButton: mouseButton)
135
        mouseEvent?.post(tap: CGEventTapLocation.cghidEventTap)
136
    }
137
 
138
    //MARK: - AppleScript launcher
139
 
140
    private func runAppleScript(_ scriptText: String) {
141
        let script = NSAppleScript(source: scriptText)!
142
        var error: NSDictionary? = nil
143
        let resultMaybe = script.executeAndReturnError(&error) as NSAppleEventDescriptor?
5 pmbaty 144
        if (resultMaybe == nil)
1 pmbaty 145
        {
5 pmbaty 146
            let myStringDict = error as? [String:AnyObject]
147
            if (myStringDict?["NSAppleScriptErrorNumber"] as! Int16 == 1002) {
148
                let alert = NSAlert()
149
                alert.addButton(withTitle: "OK".localized)
150
                alert.messageText = "system_message".localized + "\n" + (myStringDict?["NSAppleScriptErrorBriefMessage"] as! String)
151
                alert.informativeText = "allow_perms".localized
152
                alert.alertStyle = .warning
153
                alert.runModal()
154
            }
1 pmbaty 155
            print (error as Any)
156
            return
157
        }
158
    }
159
 
160
    //MARK: - ServerHandlerDelegate
161
 
162
    func serverDidReceivePacket(_ packet: GyroPacket) {
163
        switch packet.type {
164
        case .scroll:
165
            scrollWithRoll(packet.roll!, velocity: packet.scrollVelocity!)
166
            computePointerMovementWithPacket(packet)
167
        case .movement:
168
            computePointerMovementWithPacket(packet)
169
        case .click:
170
            clickButton(packet.button!, click: packet.click!)
171
        case .keyTapped:
172
            runAppleScript("tell app \"System Events\" to keystroke \"\(packet.key!)\"")
173
        case .deleteBackward:
174
            runAppleScript ("tell app \"System Events\" to key code 51")
175
        case .returnTapped:
176
            runAppleScript("tell app \"System Events\" to keystroke return")
177
        case .resetPointerPosition:
178
            resetPointerPosition(moveMouse: true)
179
        }
180
    }
181
}