()
18 |
19 | override init() {
20 | super.init()
21 | }
22 |
23 | // Accept new XPC connections by setting up the exported interface and object.
24 | func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
25 | newConnection.exportedInterface = NSXPCInterface(with: HelperToolProtocol.self)
26 | newConnection.exportedObject = self
27 | newConnection.invalidationHandler = { [weak self] in
28 | self?.activeConnections.remove(newConnection)
29 | if self?.activeConnections.isEmpty == true {
30 | exit(0) // Exit when no active connections remain
31 | }
32 | }
33 | activeConnections.insert(newConnection)
34 | newConnection.resume()
35 | return true
36 | }
37 |
38 | // Execute the shell command and reply with output.
39 | func runCommand(command: String, withReply reply: @escaping (Bool, String) -> Void) {
40 | let process = Process()
41 | process.executableURL = URL(fileURLWithPath: "/bin/bash")
42 | process.arguments = ["-c", command]
43 | let pipe = Pipe()
44 | process.standardOutput = pipe
45 | process.standardError = pipe
46 | do {
47 | try process.run()
48 | process.waitUntilExit()
49 | } catch {
50 | reply(false, "Failed to run command: \(error.localizedDescription)")
51 | return
52 | }
53 | let data = pipe.fileHandleForReading.readDataToEndOfFile()
54 | let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
55 | let success = (process.terminationStatus == 0) // Check if process exited successfully
56 | reply(success, output.isEmpty ? "No output" : output)
57 | }
58 | }
59 |
60 | // Set up and start the XPC listener.
61 | let delegate = HelperToolDelegate()
62 | let listener = NSXPCListener(machServiceName: "com.alienator88.PearHID.Helper")
63 | listener.delegate = delegate
64 | listener.resume()
65 | RunLoop.main.run()
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PearHID
2 |
3 |
4 |
5 | Status: Maintained
6 |
7 | Version: 1.0.0 (BETA)
8 |
9 | Download
10 | ·
11 | Commits
12 |
13 |
14 |
15 |
16 |
17 | Easily swap keyboard keys with a nice SwiftUI frontend for IOKit.hid/hidutil
18 |
19 |
20 | ## Features
21 | - Save/clear multiple key combinations at once
22 | - Save to launchd plist to persist reboots
23 | - Turn off persist in settings to only affect the current session and disable launch daemon
24 | - Helper tool to perform the launchd plist editing without asking for user password each time
25 | - Custom auto-updater that pulls latest release notes and binaries from GitHub Releases
26 |
27 |
28 | ## Preview
29 | 
30 |
31 |
32 | ## Requirements
33 | - MacOS 13.0+ (App uses some newer SwiftUI functions/modifiers which don't work on anything lower than 13.0)
34 |
35 |
36 | ## Getting PearHID
37 |
38 |
39 | Releases
40 |
41 | Pre-compiled, always up-to-date versions are available from my [releases](https://github.com/alienator88/PearHID/releases) page.
42 |
43 |
44 |
45 | Homebrew Coming Soon
46 |
47 | You can add the app via Homebrew:
48 | ```
49 |
50 | ```
51 |
52 |
53 |
54 | ## License
55 | > [!IMPORTANT]
56 | > PearHID is licensed under Apache 2.0 with [Commons Clause](https://commonsclause.com/). This means that you can do anything you'd like with the source, modify it, contribute to it, etc., but the license explicitly prohibits any form of monetization for PearHID or any modified versions of it. See full license [HERE](https://github.com/alienator88/Sentinel/blob/main/LICENSE.md)
57 |
58 | ## Thanks
59 | [This Gist](https://gist.github.com/bennlee/0f5bc8dc15a53b2cc1c81cd92363bf18)
60 |
61 | [hidutil-key-remapping-generator](https://github.com/amarsyla/hidutil-key-remapping-generator)
62 |
63 | ## Some of my apps
64 |
65 | [Pearcleaner](https://github.com/alienator88/Pearcleaner) - An opensource app cleaner with privacy in mind
66 |
67 | [Sentinel](https://github.com/alienator88/Sentinel) - A GUI for controlling gatekeeper status on your mac
68 |
69 | [Viz](https://github.com/alienator88/Viz) - Utility for extracting text from images, videos, qr/barcodes
70 |
--------------------------------------------------------------------------------
/Resources/Icons/icon_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_128x128.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_128x128@2x.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_16x16.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_16x16@2x.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_256x256.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_256x256@2x.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_32x32.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_32x32@2x.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_512x512.png
--------------------------------------------------------------------------------
/Resources/Icons/icon_512x512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alienator88/PearHID/a34e891ae2a96da3d7702a16a15f73157d5fe8c0/Resources/Icons/icon_512x512@2x.png
--------------------------------------------------------------------------------
/announcements.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | }
4 |
--------------------------------------------------------------------------------