├── asdfghjkl ├── bat27.png ├── asdfghjkl-Bridging-Header.h ├── ScrollUtils.h ├── ScrollUtils.m ├── Base.lproj │ └── MainMenu.xib ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist └── AppDelegate.swift ├── asdfghjkl.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── matt.xcuserdatad │ │ ├── xcschemes │ │ ├── xcschememanagement.plist │ │ ├── asdfghjkl- root.xcscheme │ │ └── asdfghjkl.xcscheme │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist └── project.pbxproj ├── asdfghjklTests ├── Info.plist └── asdfghjklTests.swift └── README.md /asdfghjkl/bat27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shrugs/asdfghjkl/HEAD/asdfghjkl/bat27.png -------------------------------------------------------------------------------- /asdfghjkl/asdfghjkl-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "ScrollUtils.h" -------------------------------------------------------------------------------- /asdfghjkl.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /asdfghjkl/ScrollUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollUtils.h 3 | // asdfghjkl 4 | // 5 | // Created by Matt Condon on 9/6/15. 6 | // Copyright © 2015 mattc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ScrollUtils : NSObject 12 | 13 | + (CGEventRef) createScrollEventWithScrollAmount:(int32_t)amt; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /asdfghjkl/ScrollUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollUtils.m 3 | // asdfghjkl 4 | // 5 | // Created by Matt Condon on 9/6/15. 6 | // Copyright © 2015 mattc. All rights reserved. 7 | // 8 | 9 | #import "ScrollUtils.h" 10 | 11 | @implementation ScrollUtils 12 | 13 | + (CGEventRef) createScrollEventWithScrollAmount:(int32_t)amt 14 | { 15 | return CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, amt, 0); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /asdfghjklTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /asdfghjkl.xcodeproj/xcuserdata/matt.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | asdfghjkl- root.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | asdfghjkl.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | C935D0221B9AC16400D8E9AC 21 | 22 | primary 23 | 24 | 25 | C935D0321B9AC16400D8E9AC 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /asdfghjklTests/asdfghjklTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // asdfghjklTests.swift 3 | // asdfghjklTests 4 | // 5 | // Created by Matt Condon on 9/5/15. 6 | // Copyright (c) 2015 mattc. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import XCTest 11 | 12 | class asdfghjklTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /asdfghjkl/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /asdfghjkl/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /asdfghjkl/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | LSUIElement 28 | 29 | NSHumanReadableCopyright 30 | Copyright © 2015 mattc. All rights reserved. 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## asdfghjkl 2 | 3 | > Keyboard as Trackpad 4 | 5 | Yes, really. 6 | 7 | [![Watch asdfghjkl in action on YouTube.](https://img.youtube.com/vi/QZ1KNP_R76c/0.jpg)](https://www.youtube.com/watch?v=QZ1KNP_R76c) 8 | 9 | Watch it in action [on YouTube](https://www.youtube.com/watch?v=QZ1KNP_R76c). 10 | 11 | ## Inspiration 12 | 13 | Throughout history, we've invented better and better ways of interfacing with machines. The **mouse**, the **VirtualBoy**, the **nub mouse thing** on ThinkPads. But we weren't satisfied with the current state of input devices. As computers become more and more personal and more and more a part of our daily lives, we need better, **more efficient** ways of interacting with them. One of the biggest inefficiencies in modern desktop computing is moving your hands from the keyboard to the track pad. So we got rid of that. Yup. Really. 14 | 15 | Introducing **asdfghjkl** , a revolution in computer-human interface design patterns, by team "Keyboard as Trackpad". 16 | 17 | ## What it does 18 | 19 | Hold down the _Control_ key and run your finger across the keyboard. Watch as the mouse follows your commands. Marvel at the time you saved. 20 | Hold down the _Shift_ key and run your finger across the keyboard. Watch as the page scrolls under your command. Marvel at the time you saved. 21 | 22 | ## Challenges I ran into 23 | 24 | Using my computer. 25 | 26 | ## Accomplishments that I'm proud of 27 | 28 | Using my computer. 29 | 30 | ## What I learned 31 | 32 | How to better use my computer. 33 | 34 | ## How I built it 35 | 36 | After getting the MVP working, I exclusively used **asdfghjkl** for navigation and input while developing the app. 37 | 38 | It's built in Swift 2.0 (for the easy C interoperability) and partially Obj-C for certain functions. 39 | 40 | ## What's next for **asdfghjkl** 41 | 42 | Apple partnership is in the works. NASA partnership is going smoothly; soon the inhabitants of the ISS will be able to get more done, easier, thanks to mandatory **asdfghjkl** usage. 43 | 44 | ## Info 45 | 46 | The correct way to pronounce **asdfghjkl** is "asdfghjkl". Please don't get it wrong. Additionally, the only way to type **asdfghjkl** is by sliding your finger across the entire home row. Just don't hold _Control_, or your mouse will fly to the right! 47 | -------------------------------------------------------------------------------- /asdfghjkl.xcodeproj/xcuserdata/matt.xcuserdatad/xcschemes/asdfghjkl- root.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 74 | 76 | 82 | 83 | 84 | 85 | 87 | 88 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /asdfghjkl.xcodeproj/xcuserdata/matt.xcuserdatad/xcschemes/asdfghjkl.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /asdfghjkl.xcodeproj/xcuserdata/matt.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 18 | 30 | 31 | 32 | 34 | 46 | 47 | 48 | 50 | 62 | 63 | 64 | 66 | 78 | 79 | 80 | 82 | 94 | 95 | 96 | 98 | 110 | 111 | 112 | 114 | 126 | 127 | 128 | 130 | 140 | 141 | 142 | 144 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /asdfghjkl/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // asdfghjkl 4 | // 5 | // Created by Matt Condon on 9/5/15. 6 | // Copyright (c) 2015 mattc. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import CoreGraphics 11 | 12 | let POSITIONS : [Int64: [Int]] = [ 13 | 50: [223, 173], 14 | 18: [267, 173], 15 | 19: [309, 173], 16 | 20: [351, 173], 17 | 21: [393, 173], 18 | 23: [435, 173], 19 | 22: [477, 173], 20 | 26: [519, 173], 21 | 28: [561, 173], 22 | 25: [603, 173], 23 | 29: [645, 173], 24 | 27: [687, 173], 25 | 24: [730, 173], 26 | 51: [786, 173], 27 | 28 | 48: [233, 214], 29 | 12: [285, 214], 30 | 13: [330, 214], 31 | 14: [372, 214], 32 | 15: [414, 214], 33 | 17: [456, 214], 34 | 16: [498, 214], 35 | 32: [540, 214], 36 | 34: [582, 214], 37 | 31: [624, 214], 38 | 35: [666, 214], 39 | 33: [708, 214], 40 | 30: [750, 214], 41 | 42: [792, 214], 42 | 43 | 0: [298, 255], 44 | 1: [340, 255], 45 | 2: [382, 255], 46 | 3: [424, 255], 47 | 5: [466, 255], 48 | 4: [508, 255], 49 | 38: [550, 255], 50 | 40: [592, 255], 51 | 37: [634, 255], 52 | 41: [676, 255], 53 | 39: [718, 255], 54 | 36: [779, 255], 55 | 56 | 6: [319, 296], 57 | 7: [361, 296], 58 | 8: [403, 296], 59 | 9: [445, 296], 60 | 11: [487, 296], 61 | 45: [529, 296], 62 | 46: [571, 296], 63 | 43: [613, 296], 64 | 47: [655, 296], 65 | 44: [697, 296], 66 | 67 | 49: [489, 340], 68 | 123: [712, 350], 69 | 126: [754, 330], 70 | 125: [754, 350], 71 | 124: [796, 350], 72 | ] 73 | 74 | let LEFT_KEYS : [Int64] = [50, 18, 19, 20, 21, 23, 48, 12, 13, 14, 15, 17, 0, 1, 2, 3, 5, 6, 7, 8, 9, 11] 75 | let RIGHT_KEYS : [Int64] = [22, 26, 28, 25, 29, 27, 24, 51, 16, 32, 34, 31, 35, 33, 30, 42, 4, 38, 40, 37, 41, 39, 36, 11, 45, 46, 43, 47, 44, 49, 123, 125, 126, 124] 76 | 77 | var lastLocation : [Int] = [] 78 | var lastKeyCode : Int64? 79 | var isTouchingTimer : NSTimer? 80 | var keyUpTimer : NSTimer? 81 | var timeOfLastKeypress : NSDate? 82 | 83 | var wasDragging : Bool = false 84 | 85 | var setOfHeldButtons = NSMutableSet() 86 | var setOfPreviouslyHeldButtons = NSSet() 87 | var hasPotentialScroll = false 88 | var isScrolling = false 89 | var scrollTimer : NSTimer? 90 | var scrollUp = false 91 | 92 | var interpTimer : NSTimer? 93 | let steps : Double = 15.0 94 | 95 | var isScrollingTimer : NSTimer? 96 | 97 | var delayedMoveTimer : NSTimer? 98 | 99 | let scrollDelay = 0.1 100 | 101 | var scrollEventStarted = false 102 | var scrollEventContinued = false 103 | var isMoving = false 104 | 105 | class Whatever : NSObject { 106 | func touchingFinished() { 107 | isTouchingTimer?.invalidate() 108 | isTouchingTimer = nil 109 | 110 | lastKeyCode = nil 111 | timeOfLastKeypress = nil 112 | 113 | delayedMoveTimer?.invalidate() 114 | delayedMoveTimer = nil 115 | 116 | scrollEventStarted = false 117 | scrollEventContinued = false 118 | isMoving = false 119 | } 120 | 121 | func scrollingFinished() { 122 | isScrollingTimer = nil 123 | } 124 | 125 | func lClick() { 126 | leftClick() 127 | } 128 | 129 | func rClick() { 130 | rightClick() 131 | } 132 | 133 | func interpTimerCallback(timer : NSTimer) { 134 | let userInfo = timer.userInfo as! [String: Double] 135 | let iter = userInfo["iteration"]! 136 | 137 | if (iter > steps) { 138 | // stop iteration 139 | return 140 | } 141 | 142 | let interval = userInfo["interval"]! 143 | let dx = userInfo["dx"]! 144 | let dy = userInfo["dy"]! 145 | let fromX = userInfo["fromX"]! 146 | let fromY = userInfo["fromY"]! 147 | let dt = interval * iter 148 | let totalTime = interval * steps 149 | 150 | let t = dt / totalTime 151 | 152 | let newX = lerp(fromX, d: dx, t: t) 153 | let newY = lerp(fromY, d: dy, t: t) 154 | 155 | moveMouse(to: CGPoint(x: newX, y: newY)) 156 | 157 | interpTimer = NSTimer.scheduledTimerWithTimeInterval(interval, target: whatever, selector: "interpTimerCallback:", userInfo: [ 158 | "iteration": iter + 1, 159 | "interval": interval, 160 | "dx": dx, 161 | "dy": dy, 162 | "fromX": fromX, 163 | "fromY": fromY 164 | ], repeats: false) 165 | } 166 | 167 | func interpolateScroll(timer : NSTimer) { 168 | let userInfo = timer.userInfo as! [String: Double] 169 | let iter = userInfo["iteration"]! 170 | 171 | if (iter > steps) { 172 | // stop iteration 173 | return 174 | } 175 | 176 | let interval = userInfo["interval"]! 177 | let dy = userInfo["dy"]! 178 | let dt = interval * iter 179 | let totalTime = interval * steps 180 | 181 | let direction = userInfo["direction"]! > 0 182 | 183 | let t = dt / totalTime 184 | 185 | let newY = lerp(0, d: dy, t: t) 186 | 187 | scroll(newY, direction: direction) 188 | 189 | interpTimer = NSTimer.scheduledTimerWithTimeInterval(interval, target: whatever, selector: "interpolateScroll:", userInfo: [ 190 | "iteration": iter + 1, 191 | "interval": interval, 192 | "dy": dy, 193 | "direction": direction 194 | ], repeats: false) 195 | } 196 | 197 | func delayedMoveTimerCallback(timer : NSTimer) { 198 | isMoving = true 199 | // let p = timer.userInfo as! [Int] 200 | // smoothMoveMouse(by: p) 201 | } 202 | } 203 | 204 | let whatever = Whatever() 205 | 206 | func lerp(a : Double, d: Double, t : Double) -> Double { 207 | return a + d * t 208 | } 209 | 210 | func interpolateBetweenPoints(from from: CGPoint, to: CGPoint) { 211 | let deltaX = to.x - from.x 212 | let deltaY = to.y - from.y 213 | 214 | let totalTime = 0.08 215 | 216 | interpTimer?.invalidate() 217 | interpTimer = NSTimer.scheduledTimerWithTimeInterval(totalTime / steps, target: whatever, selector: "interpTimerCallback:", userInfo: [ 218 | "iteration": 0, 219 | "interval": totalTime / steps, 220 | "dx": deltaX, 221 | "dy": deltaY, 222 | "fromX": from.x, 223 | "fromY": from.y 224 | ], repeats: false) 225 | } 226 | 227 | func interpolateScroll(amt : Double, direction : Double) { 228 | 229 | let totalTime = 0.4 230 | 231 | interpTimer?.invalidate() 232 | interpTimer = NSTimer.scheduledTimerWithTimeInterval(totalTime / steps, target: whatever, selector: "interpolateScroll:", userInfo: [ 233 | "iteration": 0, 234 | "interval": totalTime / steps, 235 | "dy": amt, 236 | "direction": direction 237 | ], repeats: false) 238 | } 239 | 240 | func distanceFromLast(keyCode : Int64) -> [Int] { 241 | // computes the distance with (0,0) at top left 242 | guard let lastKey = lastKeyCode else { 243 | return [0, 0] 244 | } 245 | 246 | let location = POSITIONS[keyCode]! 247 | let lastLocation = POSITIONS[lastKey]! 248 | let r = [location[0] - lastLocation[0], location[1] - lastLocation[1]] 249 | return r 250 | } 251 | 252 | func modifyValue(v : Double, forTime time : Double) -> Double { 253 | let s = -12.5 * time + 4 254 | return v * s 255 | } 256 | 257 | func onShiftKeyDown(keyCode : Int64) { 258 | 259 | if let _ = isScrollingTimer { 260 | // only trigger this block if it's the nth key we've touched in a row 261 | 262 | // deltaT for keyDown events calculations 263 | var dt = 0.0 264 | if let tl = timeOfLastKeypress { 265 | dt = NSDate().timeIntervalSinceDate(tl) 266 | } 267 | 268 | let d = distanceFromLast(keyCode) 269 | let direction = d[1] < 0 270 | let scrollAmt = modifyValue(abs(Double(d[1])/2.0), forTime: dt) 271 | smoothScroll(scrollAmt, direction: direction ? 1.0 : -1.0) 272 | } 273 | 274 | lastKeyCode = keyCode 275 | timeOfLastKeypress = NSDate() 276 | 277 | isScrollingTimer?.invalidate() 278 | isScrollingTimer = NSTimer.scheduledTimerWithTimeInterval(0.3, target: whatever, selector: "scrollingFinished", userInfo: nil, repeats: false) 279 | 280 | } 281 | 282 | func onShiftKeyUp(keyCode : Int64) { 283 | 284 | } 285 | 286 | func onKeyDown(keyCode : Int64) { 287 | setOfHeldButtons.addObject(NSNumber(longLong: keyCode)) 288 | 289 | if let _ = isTouchingTimer { 290 | // only trigger this block if it's the nth key we've touched in a row 291 | 292 | // deltaT for keyDown events calculations 293 | var dt = 0.0 294 | if let tl = timeOfLastKeypress { 295 | dt = NSDate().timeIntervalSinceDate(tl) 296 | } 297 | 298 | // print(keyCode, dt, setOfHeldButtons.count) 299 | let d = distanceFromLast(keyCode) 300 | let nd = [ 301 | Int(modifyValue(Double(d[0]), forTime: dt)), 302 | Int(modifyValue(Double(d[1]), forTime: dt)) 303 | ] 304 | 305 | isMoving = true 306 | smoothMoveMouse(by: nd) 307 | } else { 308 | isTouchingTimer?.invalidate() 309 | isTouchingTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: whatever, selector: "touchingFinished", userInfo: nil, repeats: false) 310 | } 311 | 312 | lastKeyCode = keyCode 313 | timeOfLastKeypress = NSDate() 314 | // reset the isTouching and keyUp timers every time we get a keyDown 315 | keyUpTimer?.invalidate() 316 | keyUpTimer = nil 317 | 318 | } 319 | 320 | func onKeyUp(keyCode : Int64) { 321 | setOfHeldButtons.removeObject(NSNumber(longLong: keyCode)) 322 | 323 | if !isMoving { 324 | // if we're not dragging, we care about clicks 325 | // just in case, create a timer that's invalidated if the user clicks down before the timeout 326 | keyUpTimer?.invalidate() 327 | if LEFT_KEYS.contains(keyCode) { 328 | keyUpTimer = NSTimer.scheduledTimerWithTimeInterval(0.31, target: whatever, selector: "lClick", userInfo: nil, repeats: false) 329 | } else { 330 | keyUpTimer = NSTimer.scheduledTimerWithTimeInterval(0.31, target: whatever, selector: "rClick", userInfo: nil, repeats: false) 331 | } 332 | } else { 333 | isTouchingTimer?.invalidate() 334 | isTouchingTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: whatever, selector: "touchingFinished", userInfo: nil, repeats: false) 335 | } 336 | 337 | } 338 | 339 | 340 | 341 | 342 | 343 | /**** 344 | 345 | EVENT FUNCTIONS 346 | 347 | ****/ 348 | 349 | func smoothMoveMouse(by by : [Int]) { 350 | let currentLocation = NSEvent.mouseLocation() 351 | let newX = currentLocation.x + CGFloat(by[0]) 352 | let newY = currentLocation.y - CGFloat(by[1]) 353 | 354 | interpolateBetweenPoints(from: currentLocation, to: CGPoint(x: newX, y: newY)) 355 | } 356 | 357 | func smoothScroll(amt : Double, direction : Double) { 358 | interpolateScroll(amt, direction: direction) 359 | } 360 | 361 | func moveMouse(by by: [Int]) { 362 | 363 | let currentLocation = NSEvent.mouseLocation() 364 | let newX = currentLocation.x + CGFloat(by[0]) 365 | // invert to use origin at bottom left 366 | let newY = (NSScreen.mainScreen()?.frame.size.height)! - (currentLocation.y - CGFloat(by[1])) 367 | let move = CGEventCreateMouseEvent( 368 | nil, 369 | CGEventType.MouseMoved, 370 | CGPoint(x: newX, y: newY), 371 | CGMouseButton.Left 372 | ) 373 | CGEventPost(CGEventTapLocation.CGHIDEventTap, move) 374 | } 375 | 376 | func moveMouse(to to: CGPoint) { 377 | // lol global coordinates 378 | let newTo = CGPoint(x: to.x, y: (NSScreen.mainScreen()?.frame.size.height)! - to.y) 379 | let move = CGEventCreateMouseEvent( 380 | nil, 381 | CGEventType.MouseMoved, 382 | newTo, 383 | CGMouseButton.Left 384 | ) 385 | CGEventPost(CGEventTapLocation.CGHIDEventTap, move) 386 | } 387 | 388 | func scroll(amt: Double, direction : Bool) { 389 | let scrollAmt = amt * (direction ? 1 : -1) 390 | let move = ScrollUtils.createScrollEventWithScrollAmount(Int32(scrollAmt)).takeRetainedValue() as CGEvent 391 | CGEventPost(CGEventTapLocation.CGHIDEventTap, move) 392 | } 393 | 394 | func leftDown() { 395 | let down = CGEventCreateMouseEvent( 396 | nil, 397 | CGEventType.LeftMouseDown, 398 | CGPoint(x: NSEvent.mouseLocation().x, y: (NSScreen.mainScreen()?.frame.size.height)! - NSEvent.mouseLocation().y), 399 | CGMouseButton.Left 400 | ) 401 | CGEventPost(CGEventTapLocation.CGHIDEventTap, down) 402 | } 403 | 404 | func leftUp() { 405 | let up = CGEventCreateMouseEvent( 406 | nil, 407 | CGEventType.LeftMouseUp, 408 | CGPoint(x: NSEvent.mouseLocation().x, y: (NSScreen.mainScreen()?.frame.size.height)! - NSEvent.mouseLocation().y), 409 | CGMouseButton.Left 410 | ) 411 | CGEventPost(CGEventTapLocation.CGHIDEventTap, up) 412 | } 413 | 414 | func leftClick() { 415 | leftDown() 416 | leftUp() 417 | } 418 | 419 | func leftDrag(to to : CGPoint) { 420 | let drag = CGEventCreateMouseEvent( 421 | nil, 422 | CGEventType.LeftMouseDragged, 423 | to, 424 | CGMouseButton.Left 425 | ) 426 | CGEventPost(CGEventTapLocation.CGHIDEventTap, drag) 427 | } 428 | 429 | func rightDown() { 430 | let down = CGEventCreateMouseEvent( 431 | nil, 432 | CGEventType.RightMouseDown, 433 | CGPoint(x: NSEvent.mouseLocation().x, y: (NSScreen.mainScreen()?.frame.size.height)! - NSEvent.mouseLocation().y), 434 | CGMouseButton.Right 435 | ) 436 | CGEventPost(CGEventTapLocation.CGHIDEventTap, down) 437 | } 438 | 439 | func rightUp() { 440 | let up = CGEventCreateMouseEvent( 441 | nil, 442 | CGEventType.RightMouseUp, 443 | CGPoint(x: NSEvent.mouseLocation().x, y: (NSScreen.mainScreen()?.frame.size.height)! - NSEvent.mouseLocation().y), 444 | CGMouseButton.Right 445 | ) 446 | CGEventPost(CGEventTapLocation.CGHIDEventTap, up) 447 | } 448 | 449 | func rightClick() { 450 | print("rightClick") 451 | rightDown() 452 | rightUp() 453 | } 454 | 455 | @NSApplicationMain 456 | class AppDelegate: NSObject, NSApplicationDelegate { 457 | 458 | @IBOutlet weak var window: NSWindow! 459 | 460 | var eventTap : CFMachPort? 461 | let w = whatever 462 | 463 | func applicationDidFinishLaunching(aNotification: NSNotification) { 464 | 465 | let eventMask = (1 << CGEventType.KeyDown.rawValue) | 466 | (1 << CGEventType.KeyUp.rawValue) | 467 | (1 << CGEventType.LeftMouseDown.rawValue) | 468 | (1 << CGEventType.LeftMouseUp.rawValue) | 469 | (1 << CGEventType.MouseMoved.rawValue) | 470 | (1 << CGEventType.RightMouseDown.rawValue) | 471 | (1 << CGEventType.RightMouseUp.rawValue) | 472 | (1 << CGEventType.LeftMouseDragged.rawValue) | 473 | (1 << CGEventType.ScrollWheel.rawValue) 474 | 475 | guard let eventTap = CGEventTapCreate( 476 | .CGHIDEventTap, 477 | .HeadInsertEventTap, 478 | .Default, 479 | CGEventMask(eventMask), 480 | { (proxy : CGEventTapProxy, type : CGEventType, event : CGEvent, userInfo : UnsafeMutablePointer) -> Unmanaged? in 481 | 482 | let ctrlKeyHeld = (CGEventGetFlags(event).rawValue & CGEventFlags.MaskControl.rawValue) > 0; 483 | let shiftKeyHeld = (CGEventGetFlags(event).rawValue & CGEventFlags.MaskAlternate.rawValue) > 0; 484 | 485 | if ((ctrlKeyHeld || shiftKeyHeld) && CGEventGetIntegerValueField(event, .KeyboardEventAutorepeat) == 0) { 486 | // ctrl key and not an autorepeat 487 | let keyCode = CGEventGetIntegerValueField(event, .KeyboardEventKeycode) 488 | 489 | if (ctrlKeyHeld) { 490 | if type == .KeyDown { 491 | onKeyDown(keyCode) 492 | } 493 | 494 | if type == .KeyUp { 495 | onKeyUp(keyCode) 496 | } 497 | } 498 | 499 | if (shiftKeyHeld) { 500 | if type == .KeyDown { 501 | onShiftKeyDown(keyCode) 502 | } 503 | 504 | if type == .KeyUp { 505 | onShiftKeyUp(keyCode) 506 | } 507 | } 508 | 509 | if [.LeftMouseDown, .LeftMouseUp, .RightMouseDown, .RightMouseUp, .MouseMoved, .LeftMouseDragged, .ScrollWheel].contains(type) { 510 | CGEventSetFlags(event, CGEventFlags(rawValue: 0)!) 511 | return Unmanaged.passRetained(event) 512 | } 513 | 514 | return nil 515 | } 516 | return Unmanaged.passRetained(event) 517 | }, 518 | nil) else { 519 | print("FAILED"); 520 | exit(1) 521 | } 522 | 523 | let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) 524 | CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes) 525 | CGEventTapEnable(eventTap, true) 526 | CFRunLoopRun() 527 | 528 | } 529 | 530 | 531 | 532 | func applicationWillTerminate(aNotification: NSNotification) { 533 | // Insert code here to tear down your application 534 | } 535 | 536 | 537 | } 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | -------------------------------------------------------------------------------- /asdfghjkl.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C935D0291B9AC16400D8E9AC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C935D0281B9AC16400D8E9AC /* AppDelegate.swift */; }; 11 | C935D02B1B9AC16400D8E9AC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C935D02A1B9AC16400D8E9AC /* Images.xcassets */; }; 12 | C935D02E1B9AC16400D8E9AC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = C935D02C1B9AC16400D8E9AC /* MainMenu.xib */; }; 13 | C935D03A1B9AC16400D8E9AC /* asdfghjklTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C935D0391B9AC16400D8E9AC /* asdfghjklTests.swift */; }; 14 | C935D0441B9AC1C700D8E9AC /* bat27.png in Resources */ = {isa = PBXBuildFile; fileRef = C935D0431B9AC1C700D8E9AC /* bat27.png */; }; 15 | C95632251B9C1C24003F8DE3 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C95632241B9C1C24003F8DE3 /* CoreGraphics.framework */; }; 16 | C95632281B9C1C5F003F8DE3 /* ScrollUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = C95632271B9C1C5F003F8DE3 /* ScrollUtils.m */; settings = {ASSET_TAGS = (); }; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | C935D0341B9AC16400D8E9AC /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = C935D01B1B9AC16400D8E9AC /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = C935D0221B9AC16400D8E9AC; 25 | remoteInfo = asdfghjkl; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | C935D0231B9AC16400D8E9AC /* asdfghjkl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = asdfghjkl.app; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | C935D0271B9AC16400D8E9AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | C935D0281B9AC16400D8E9AC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33 | C935D02A1B9AC16400D8E9AC /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 34 | C935D02D1B9AC16400D8E9AC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 35 | C935D0331B9AC16400D8E9AC /* asdfghjklTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = asdfghjklTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | C935D0381B9AC16400D8E9AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | C935D0391B9AC16400D8E9AC /* asdfghjklTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = asdfghjklTests.swift; sourceTree = ""; }; 38 | C935D0431B9AC1C700D8E9AC /* bat27.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bat27.png; sourceTree = ""; }; 39 | C95632211B9C1B4F003F8DE3 /* asdfghjkl-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "asdfghjkl-Bridging-Header.h"; sourceTree = ""; }; 40 | C95632241B9C1C24003F8DE3 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 41 | C95632261B9C1C5F003F8DE3 /* ScrollUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollUtils.h; sourceTree = ""; }; 42 | C95632271B9C1C5F003F8DE3 /* ScrollUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScrollUtils.m; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | C935D0201B9AC16400D8E9AC /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | C95632251B9C1C24003F8DE3 /* CoreGraphics.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | C935D0301B9AC16400D8E9AC /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | C935D01A1B9AC16400D8E9AC = { 65 | isa = PBXGroup; 66 | children = ( 67 | C95632241B9C1C24003F8DE3 /* CoreGraphics.framework */, 68 | C935D0251B9AC16400D8E9AC /* asdfghjkl */, 69 | C935D0361B9AC16400D8E9AC /* asdfghjklTests */, 70 | C935D0241B9AC16400D8E9AC /* Products */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | C935D0241B9AC16400D8E9AC /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | C935D0231B9AC16400D8E9AC /* asdfghjkl.app */, 78 | C935D0331B9AC16400D8E9AC /* asdfghjklTests.xctest */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | C935D0251B9AC16400D8E9AC /* asdfghjkl */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | C935D0281B9AC16400D8E9AC /* AppDelegate.swift */, 87 | C935D02A1B9AC16400D8E9AC /* Images.xcassets */, 88 | C935D02C1B9AC16400D8E9AC /* MainMenu.xib */, 89 | C935D0261B9AC16400D8E9AC /* Supporting Files */, 90 | C95632211B9C1B4F003F8DE3 /* asdfghjkl-Bridging-Header.h */, 91 | C95632261B9C1C5F003F8DE3 /* ScrollUtils.h */, 92 | C95632271B9C1C5F003F8DE3 /* ScrollUtils.m */, 93 | ); 94 | path = asdfghjkl; 95 | sourceTree = ""; 96 | }; 97 | C935D0261B9AC16400D8E9AC /* Supporting Files */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | C935D0431B9AC1C700D8E9AC /* bat27.png */, 101 | C935D0271B9AC16400D8E9AC /* Info.plist */, 102 | ); 103 | name = "Supporting Files"; 104 | sourceTree = ""; 105 | }; 106 | C935D0361B9AC16400D8E9AC /* asdfghjklTests */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | C935D0391B9AC16400D8E9AC /* asdfghjklTests.swift */, 110 | C935D0371B9AC16400D8E9AC /* Supporting Files */, 111 | ); 112 | path = asdfghjklTests; 113 | sourceTree = ""; 114 | }; 115 | C935D0371B9AC16400D8E9AC /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | C935D0381B9AC16400D8E9AC /* Info.plist */, 119 | ); 120 | name = "Supporting Files"; 121 | sourceTree = ""; 122 | }; 123 | /* End PBXGroup section */ 124 | 125 | /* Begin PBXNativeTarget section */ 126 | C935D0221B9AC16400D8E9AC /* asdfghjkl */ = { 127 | isa = PBXNativeTarget; 128 | buildConfigurationList = C935D03D1B9AC16400D8E9AC /* Build configuration list for PBXNativeTarget "asdfghjkl" */; 129 | buildPhases = ( 130 | C935D01F1B9AC16400D8E9AC /* Sources */, 131 | C935D0201B9AC16400D8E9AC /* Frameworks */, 132 | C935D0211B9AC16400D8E9AC /* Resources */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | ); 138 | name = asdfghjkl; 139 | productName = asdfghjkl; 140 | productReference = C935D0231B9AC16400D8E9AC /* asdfghjkl.app */; 141 | productType = "com.apple.product-type.application"; 142 | }; 143 | C935D0321B9AC16400D8E9AC /* asdfghjklTests */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = C935D0401B9AC16400D8E9AC /* Build configuration list for PBXNativeTarget "asdfghjklTests" */; 146 | buildPhases = ( 147 | C935D02F1B9AC16400D8E9AC /* Sources */, 148 | C935D0301B9AC16400D8E9AC /* Frameworks */, 149 | C935D0311B9AC16400D8E9AC /* Resources */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | C935D0351B9AC16400D8E9AC /* PBXTargetDependency */, 155 | ); 156 | name = asdfghjklTests; 157 | productName = asdfghjklTests; 158 | productReference = C935D0331B9AC16400D8E9AC /* asdfghjklTests.xctest */; 159 | productType = "com.apple.product-type.bundle.unit-test"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | C935D01B1B9AC16400D8E9AC /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | LastSwiftMigration = 0700; 168 | LastSwiftUpdateCheck = 0700; 169 | LastUpgradeCheck = 0700; 170 | ORGANIZATIONNAME = mattc; 171 | TargetAttributes = { 172 | C935D0221B9AC16400D8E9AC = { 173 | CreatedOnToolsVersion = 6.4; 174 | }; 175 | C935D0321B9AC16400D8E9AC = { 176 | CreatedOnToolsVersion = 6.4; 177 | TestTargetID = C935D0221B9AC16400D8E9AC; 178 | }; 179 | }; 180 | }; 181 | buildConfigurationList = C935D01E1B9AC16400D8E9AC /* Build configuration list for PBXProject "asdfghjkl" */; 182 | compatibilityVersion = "Xcode 3.2"; 183 | developmentRegion = English; 184 | hasScannedForEncodings = 0; 185 | knownRegions = ( 186 | en, 187 | Base, 188 | ); 189 | mainGroup = C935D01A1B9AC16400D8E9AC; 190 | productRefGroup = C935D0241B9AC16400D8E9AC /* Products */; 191 | projectDirPath = ""; 192 | projectRoot = ""; 193 | targets = ( 194 | C935D0221B9AC16400D8E9AC /* asdfghjkl */, 195 | C935D0321B9AC16400D8E9AC /* asdfghjklTests */, 196 | ); 197 | }; 198 | /* End PBXProject section */ 199 | 200 | /* Begin PBXResourcesBuildPhase section */ 201 | C935D0211B9AC16400D8E9AC /* Resources */ = { 202 | isa = PBXResourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | C935D0441B9AC1C700D8E9AC /* bat27.png in Resources */, 206 | C935D02B1B9AC16400D8E9AC /* Images.xcassets in Resources */, 207 | C935D02E1B9AC16400D8E9AC /* MainMenu.xib in Resources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | C935D0311B9AC16400D8E9AC /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | }; 218 | /* End PBXResourcesBuildPhase section */ 219 | 220 | /* Begin PBXSourcesBuildPhase section */ 221 | C935D01F1B9AC16400D8E9AC /* Sources */ = { 222 | isa = PBXSourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | C95632281B9C1C5F003F8DE3 /* ScrollUtils.m in Sources */, 226 | C935D0291B9AC16400D8E9AC /* AppDelegate.swift in Sources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | C935D02F1B9AC16400D8E9AC /* Sources */ = { 231 | isa = PBXSourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | C935D03A1B9AC16400D8E9AC /* asdfghjklTests.swift in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | /* End PBXSourcesBuildPhase section */ 239 | 240 | /* Begin PBXTargetDependency section */ 241 | C935D0351B9AC16400D8E9AC /* PBXTargetDependency */ = { 242 | isa = PBXTargetDependency; 243 | target = C935D0221B9AC16400D8E9AC /* asdfghjkl */; 244 | targetProxy = C935D0341B9AC16400D8E9AC /* PBXContainerItemProxy */; 245 | }; 246 | /* End PBXTargetDependency section */ 247 | 248 | /* Begin PBXVariantGroup section */ 249 | C935D02C1B9AC16400D8E9AC /* MainMenu.xib */ = { 250 | isa = PBXVariantGroup; 251 | children = ( 252 | C935D02D1B9AC16400D8E9AC /* Base */, 253 | ); 254 | name = MainMenu.xib; 255 | sourceTree = ""; 256 | }; 257 | /* End PBXVariantGroup section */ 258 | 259 | /* Begin XCBuildConfiguration section */ 260 | C935D03B1B9AC16400D8E9AC /* Debug */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 265 | CLANG_CXX_LIBRARY = "libc++"; 266 | CLANG_ENABLE_MODULES = YES; 267 | CLANG_ENABLE_OBJC_ARC = YES; 268 | CLANG_WARN_BOOL_CONVERSION = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 271 | CLANG_WARN_EMPTY_BODY = YES; 272 | CLANG_WARN_ENUM_CONVERSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | CODE_SIGN_IDENTITY = "-"; 278 | COPY_PHASE_STRIP = NO; 279 | DEBUG_INFORMATION_FORMAT = dwarf; 280 | ENABLE_STRICT_OBJC_MSGSEND = YES; 281 | ENABLE_TESTABILITY = YES; 282 | GCC_C_LANGUAGE_STANDARD = gnu99; 283 | GCC_DYNAMIC_NO_PIC = NO; 284 | GCC_NO_COMMON_BLOCKS = YES; 285 | GCC_OPTIMIZATION_LEVEL = 0; 286 | GCC_PREPROCESSOR_DEFINITIONS = ( 287 | "DEBUG=1", 288 | "$(inherited)", 289 | ); 290 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 291 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 292 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 293 | GCC_WARN_UNDECLARED_SELECTOR = YES; 294 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 295 | GCC_WARN_UNUSED_FUNCTION = YES; 296 | GCC_WARN_UNUSED_VARIABLE = YES; 297 | MACOSX_DEPLOYMENT_TARGET = 10.10; 298 | MTL_ENABLE_DEBUG_INFO = YES; 299 | ONLY_ACTIVE_ARCH = YES; 300 | SDKROOT = macosx; 301 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 302 | }; 303 | name = Debug; 304 | }; 305 | C935D03C1B9AC16400D8E9AC /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 310 | CLANG_CXX_LIBRARY = "libc++"; 311 | CLANG_ENABLE_MODULES = YES; 312 | CLANG_ENABLE_OBJC_ARC = YES; 313 | CLANG_WARN_BOOL_CONVERSION = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 316 | CLANG_WARN_EMPTY_BODY = YES; 317 | CLANG_WARN_ENUM_CONVERSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_UNREACHABLE_CODE = YES; 321 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 322 | CODE_SIGN_IDENTITY = "-"; 323 | COPY_PHASE_STRIP = NO; 324 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 325 | ENABLE_NS_ASSERTIONS = NO; 326 | ENABLE_STRICT_OBJC_MSGSEND = YES; 327 | GCC_C_LANGUAGE_STANDARD = gnu99; 328 | GCC_NO_COMMON_BLOCKS = YES; 329 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 330 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 331 | GCC_WARN_UNDECLARED_SELECTOR = YES; 332 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 333 | GCC_WARN_UNUSED_FUNCTION = YES; 334 | GCC_WARN_UNUSED_VARIABLE = YES; 335 | MACOSX_DEPLOYMENT_TARGET = 10.10; 336 | MTL_ENABLE_DEBUG_INFO = NO; 337 | SDKROOT = macosx; 338 | }; 339 | name = Release; 340 | }; 341 | C935D03E1B9AC16400D8E9AC /* Debug */ = { 342 | isa = XCBuildConfiguration; 343 | buildSettings = { 344 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 345 | CLANG_ENABLE_MODULES = YES; 346 | COMBINE_HIDPI_IMAGES = YES; 347 | INFOPLIST_FILE = asdfghjkl/Info.plist; 348 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 349 | PRODUCT_BUNDLE_IDENTIFIER = "mat.tc.$(PRODUCT_NAME:rfc1034identifier)"; 350 | PRODUCT_NAME = "$(TARGET_NAME)"; 351 | SWIFT_OBJC_BRIDGING_HEADER = "asdfghjkl/asdfghjkl-Bridging-Header.h"; 352 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 353 | }; 354 | name = Debug; 355 | }; 356 | C935D03F1B9AC16400D8E9AC /* Release */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 360 | CLANG_ENABLE_MODULES = YES; 361 | COMBINE_HIDPI_IMAGES = YES; 362 | INFOPLIST_FILE = asdfghjkl/Info.plist; 363 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 364 | PRODUCT_BUNDLE_IDENTIFIER = "mat.tc.$(PRODUCT_NAME:rfc1034identifier)"; 365 | PRODUCT_NAME = "$(TARGET_NAME)"; 366 | SWIFT_OBJC_BRIDGING_HEADER = "asdfghjkl/asdfghjkl-Bridging-Header.h"; 367 | }; 368 | name = Release; 369 | }; 370 | C935D0411B9AC16400D8E9AC /* Debug */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | BUNDLE_LOADER = "$(TEST_HOST)"; 374 | COMBINE_HIDPI_IMAGES = YES; 375 | FRAMEWORK_SEARCH_PATHS = ( 376 | "$(DEVELOPER_FRAMEWORKS_DIR)", 377 | "$(inherited)", 378 | ); 379 | GCC_PREPROCESSOR_DEFINITIONS = ( 380 | "DEBUG=1", 381 | "$(inherited)", 382 | ); 383 | INFOPLIST_FILE = asdfghjklTests/Info.plist; 384 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 385 | PRODUCT_BUNDLE_IDENTIFIER = "mat.tc.$(PRODUCT_NAME:rfc1034identifier)"; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/asdfghjkl.app/Contents/MacOS/asdfghjkl"; 388 | }; 389 | name = Debug; 390 | }; 391 | C935D0421B9AC16400D8E9AC /* Release */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | BUNDLE_LOADER = "$(TEST_HOST)"; 395 | COMBINE_HIDPI_IMAGES = YES; 396 | FRAMEWORK_SEARCH_PATHS = ( 397 | "$(DEVELOPER_FRAMEWORKS_DIR)", 398 | "$(inherited)", 399 | ); 400 | INFOPLIST_FILE = asdfghjklTests/Info.plist; 401 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 402 | PRODUCT_BUNDLE_IDENTIFIER = "mat.tc.$(PRODUCT_NAME:rfc1034identifier)"; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/asdfghjkl.app/Contents/MacOS/asdfghjkl"; 405 | }; 406 | name = Release; 407 | }; 408 | /* End XCBuildConfiguration section */ 409 | 410 | /* Begin XCConfigurationList section */ 411 | C935D01E1B9AC16400D8E9AC /* Build configuration list for PBXProject "asdfghjkl" */ = { 412 | isa = XCConfigurationList; 413 | buildConfigurations = ( 414 | C935D03B1B9AC16400D8E9AC /* Debug */, 415 | C935D03C1B9AC16400D8E9AC /* Release */, 416 | ); 417 | defaultConfigurationIsVisible = 0; 418 | defaultConfigurationName = Release; 419 | }; 420 | C935D03D1B9AC16400D8E9AC /* Build configuration list for PBXNativeTarget "asdfghjkl" */ = { 421 | isa = XCConfigurationList; 422 | buildConfigurations = ( 423 | C935D03E1B9AC16400D8E9AC /* Debug */, 424 | C935D03F1B9AC16400D8E9AC /* Release */, 425 | ); 426 | defaultConfigurationIsVisible = 0; 427 | defaultConfigurationName = Release; 428 | }; 429 | C935D0401B9AC16400D8E9AC /* Build configuration list for PBXNativeTarget "asdfghjklTests" */ = { 430 | isa = XCConfigurationList; 431 | buildConfigurations = ( 432 | C935D0411B9AC16400D8E9AC /* Debug */, 433 | C935D0421B9AC16400D8E9AC /* Release */, 434 | ); 435 | defaultConfigurationIsVisible = 0; 436 | defaultConfigurationName = Release; 437 | }; 438 | /* End XCConfigurationList section */ 439 | }; 440 | rootObject = C935D01B1B9AC16400D8E9AC /* Project object */; 441 | } 442 | --------------------------------------------------------------------------------