2021-08-31 14:56:34 +00:00
|
|
|
//
|
|
|
|
// AppDelegate.swift
|
|
|
|
// ScrollSwitcher
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 8/31/21.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Cocoa
|
|
|
|
|
2021-09-01 03:23:29 +00:00
|
|
|
let defaultsKey = "com.apple.swipescrolldirection"
|
2021-08-31 14:56:34 +00:00
|
|
|
|
2021-09-01 03:23:29 +00:00
|
|
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
2021-08-31 14:56:34 +00:00
|
|
|
|
2021-09-01 03:23:29 +00:00
|
|
|
// things that need to be retained to keep them from disappearing
|
|
|
|
private var prefPanesSupport: Bundle!
|
|
|
|
private var item: NSStatusItem!
|
2021-09-01 14:34:29 +00:00
|
|
|
|
2021-08-31 14:56:34 +00:00
|
|
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
2021-09-01 03:23:29 +00:00
|
|
|
item = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
|
|
|
|
item.button!.target = self
|
2021-09-01 14:34:29 +00:00
|
|
|
item.button!.action = #selector(menuItemClicked)
|
2021-09-01 03:23:29 +00:00
|
|
|
updateIcon()
|
|
|
|
|
|
|
|
// update the icon when system prefs changes
|
|
|
|
DistributedNotificationCenter.default().addObserver(self, selector: #selector(updateIcon), name: .swipeScrollDirectionDidChangeNotification, object: nil)
|
2021-08-31 14:56:34 +00:00
|
|
|
}
|
2021-09-01 03:23:29 +00:00
|
|
|
|
|
|
|
@objc private func updateIcon() {
|
|
|
|
item.button!.image = Direction.current.image
|
|
|
|
}
|
|
|
|
|
2021-09-01 14:34:29 +00:00
|
|
|
@objc private func menuItemClicked() {
|
|
|
|
if let event = NSApp.currentEvent, event.modifierFlags.contains(.shift) {
|
|
|
|
item.menu = createMenu()
|
|
|
|
item.button!.performClick(nil)
|
|
|
|
} else {
|
|
|
|
toggleScrollDirection()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func createMenu() -> NSMenu {
|
|
|
|
let menu = NSMenu()
|
|
|
|
menu.delegate = self
|
|
|
|
let state = Direction.current == .natural ? "On" : "Off"
|
|
|
|
let status = NSMenuItem(title: "Natural Scrolling: \(state)", action: nil, keyEquivalent: "")
|
|
|
|
menu.addItem(status)
|
|
|
|
let verb = Direction.current == .natural ? "Disable" : "Enable"
|
|
|
|
let toggleItem = NSMenuItem(title: "\(verb) Natural Scrolling", action: #selector(toggleScrollDirection), keyEquivalent: "")
|
|
|
|
menu.addItem(toggleItem)
|
|
|
|
menu.addItem(NSMenuItem.separator())
|
|
|
|
menu.addItem(withTitle: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")
|
|
|
|
return menu
|
|
|
|
}
|
|
|
|
|
2021-09-01 03:23:29 +00:00
|
|
|
@objc private func toggleScrollDirection() {
|
|
|
|
setDirection(.current == Direction.natural ? .normal : .natural)
|
2021-08-31 14:56:34 +00:00
|
|
|
}
|
2021-09-01 03:23:29 +00:00
|
|
|
|
|
|
|
private func setDirection(_ new: Direction) {
|
|
|
|
// can't construct a UserDefaults with NSGlobalDomain, so set it via the command line
|
|
|
|
let proc = Process()
|
|
|
|
// let out = Pipe()
|
|
|
|
// let err = Pipe()
|
|
|
|
proc.launchPath = "/usr/bin/env"
|
|
|
|
let newVal = new == .normal ? "NO" : "YES"
|
|
|
|
proc.arguments = ["defaults", "write", "-g", "com.apple.swipescrolldirection", "-bool", newVal]
|
|
|
|
// proc.standardOutput = out
|
|
|
|
// proc.standardError = err
|
|
|
|
proc.launch()
|
|
|
|
proc.waitUntilExit()
|
2021-08-31 14:56:34 +00:00
|
|
|
|
2021-09-01 03:23:29 +00:00
|
|
|
// let outData = out.fileHandleForReading.readDataToEndOfFile()
|
|
|
|
// let errData = err.fileHandleForReading.readDataToEndOfFile()
|
|
|
|
if proc.terminationStatus != 0 {
|
|
|
|
fatalError("uh oh, exit code: \(proc.terminationStatus)")
|
|
|
|
}
|
|
|
|
|
|
|
|
// makes system preferences update
|
|
|
|
DistributedNotificationCenter.default().postNotificationName(.swipeScrollDirectionDidChangeNotification, object: nil, userInfo: nil, deliverImmediately: false)
|
|
|
|
// make the actual input behavior update
|
2021-09-02 03:33:58 +00:00
|
|
|
setSwipeScrollDirection(new == .natural)
|
2021-08-31 14:56:34 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 03:23:29 +00:00
|
|
|
}
|
2021-08-31 14:56:34 +00:00
|
|
|
|
2021-09-01 14:34:29 +00:00
|
|
|
extension AppDelegate: NSMenuDelegate {
|
|
|
|
func menuDidClose(_ menu: NSMenu) {
|
|
|
|
// remove the menu so the next time the item is clicked, it performs the primary action
|
|
|
|
item.menu = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-02 03:33:58 +00:00
|
|
|
enum Direction: Equatable {
|
2021-09-01 03:23:29 +00:00
|
|
|
case normal, natural
|
|
|
|
|
|
|
|
static var current: Direction {
|
|
|
|
let value = UserDefaults.standard.bool(forKey: defaultsKey)
|
|
|
|
if value {
|
|
|
|
return .natural
|
|
|
|
} else {
|
|
|
|
return .normal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var image: NSImage {
|
|
|
|
switch self {
|
|
|
|
case .normal:
|
|
|
|
return NSImage(systemSymbolName: "scroll", accessibilityDescription: nil)!
|
|
|
|
case .natural:
|
|
|
|
return NSImage(systemSymbolName: "scroll.fill", accessibilityDescription: nil)!
|
|
|
|
}
|
|
|
|
}
|
2021-08-31 14:56:34 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 03:23:29 +00:00
|
|
|
extension Notification.Name {
|
|
|
|
static let swipeScrollDirectionDidChangeNotification = Notification.Name(rawValue: "SwipeScrollDirectionDidChangeNotification")
|
|
|
|
}
|