Skip to content

Commit

Permalink
Added some install helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
gkpln3 committed Oct 2, 2022
1 parent e9fc577 commit 70d0fb8
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 20 deletions.
8 changes: 4 additions & 4 deletions CapsLockNoDelay.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,15 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = X822FM39JE;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = CapsLockNoDelay/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = gkpln3.CapsLockNoDelay;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand All @@ -288,15 +288,15 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = X822FM39JE;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = CapsLockNoDelay/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = gkpln3.CapsLockNoDelay;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand Down
89 changes: 85 additions & 4 deletions CapsLockNoDelay/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,98 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let capsLockManager = CapsLockManager()

func applicationDidFinishLaunching(_ aNotification: Notification) {
// Request accessability permissions.
if (!capsLockManager.requestAccess()) {
exit(1)
if (checkIfAppIsAlreadyRunning()) {
// Show an alert and quit.
let alert = NSAlert()
alert.messageText = "CapsLockNoDelay is already running."
alert.alertStyle = .warning
alert.addButton(withTitle: "OK")
alert.runModal()
NSApplication.shared.terminate(self)
}

// if (!checkIfRunningFromApplicationsFolder()) {
// // Prompt the user to move the app to the Applications folder.
// let alert = NSAlert()
// alert.messageText = "Would you like to move CapsLockNoDelay to the applications forlder?"
// alert.alertStyle = .warning
// alert.addButton(withTitle: "Yes")
// alert.addButton(withTitle: "No")
// let response = alert.runModal()
// if (response == .alertFirstButtonReturn) {
// moveApplicationToApplicationsFolder()
//
// // Run the app from the applications folder and terminate.
// NSWorkspace.shared.launchApplication("/Applications/CapsLockNoDelay.app")
// NSApplication.shared.terminate(self)
// }
// }

if (!hasAccessibilityPermission()) {
askForAccessibilityPermission()
}

// Start listening for events.
self.capsLockManager.registerEventListener()
}

func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}

private func hasAccessibilityPermission() -> Bool {
let promptFlag = kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString
let myDict: CFDictionary = NSDictionary(dictionary: [promptFlag: false])
return AXIsProcessTrustedWithOptions(myDict)
}

private func askForAccessibilityPermission() {
let alert = NSAlert.init()
alert.messageText = "CapsLockNoDelay requires accessibility permissions."
alert.informativeText = "Please re-launch CapsLockNoDelay after you've granted permission in system preferences."
alert.addButton(withTitle: "Configure Accessibility Settings")
alert.alertStyle = NSAlert.Style.warning

if alert.runModal() == .alertFirstButtonReturn {
guard let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility") else {
return
}
NSWorkspace.shared.open(url)
NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.systempreferences").first?.activate(options: .activateIgnoringOtherApps)
NSApplication.shared.terminate(self)
}
}

private func checkIfAppIsAlreadyRunning() -> Bool {
let bundleIdentifier = Bundle.main.bundleIdentifier!
let runningApps = NSWorkspace.shared.runningApplications
let isRunning = !runningApps.filter { $0.bundleIdentifier == bundleIdentifier && $0.processIdentifier != getpid() }.isEmpty
return isRunning
}

private func checkIfRunningFromApplicationsFolder() -> Bool {
let bundlePath = Bundle.main.bundlePath
let appPath = "/Applications/"
return bundlePath.hasPrefix(appPath)
}

private func moveApplicationToApplicationsFolder() {
let bundlePath = Bundle.main.bundlePath
let appPath = "/Applications/"
let appName = "CapsLockNoDelay.app"
let newPath = appPath + appName
do {
try FileManager.default.moveItem(atPath: bundlePath, toPath: newPath)
} catch {
let alert = NSAlert()
alert.messageText = "Failed to move CapsLockNoDelay to the applications forlder."
alert.informativeText = error.localizedDescription
alert.alertStyle = .warning
alert.addButton(withTitle: "OK")
alert.runModal()
NSApplication.shared.terminate(self)
}
}

}

12 changes: 0 additions & 12 deletions CapsLockNoDelay/CapsLockManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,6 @@ import Cocoa

class CapsLockManager {
var currentState = false

/// Requests accessability permissions to enable capturing of keyboard events.
func requestAccess() -> Bool {
let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String : true]
let accessEnabled = AXIsProcessTrustedWithOptions(options)

if !accessEnabled {
print("Access Not Enabled")
return false
}
return true
}

/// Register an event listener and listen for caps-lock presses.
func registerEventListener() {
Expand Down

0 comments on commit 70d0fb8

Please sign in to comment.