Skip to content

Commit 9cfd9f0

Browse files
Add launch at startup setting
Uses SMAppService to register/unregister the app as a login item, controlled by a checkbox in the settings window. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 0d12d87 commit 9cfd9f0

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

Sources/ScreenCursor/main.swift

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Cocoa
2+
import ServiceManagement
23

34
extension Notification.Name {
45
static let screenCursorSettingsChanged = Notification.Name("ScreenCursor.settingsChanged")
@@ -275,10 +276,11 @@ final class SettingsWindowController: NSWindowController {
275276
private let colorWell = NSColorWell(frame: .zero)
276277
private let enabledCheckbox = NSButton(checkboxWithTitle: "Enable highlight", target: nil, action: nil)
277278
private let clickFeedbackCheckbox = NSButton(checkboxWithTitle: "Click feedback", target: nil, action: nil)
279+
private let launchAtStartupCheckbox = NSButton(checkboxWithTitle: "Launch at startup", target: nil, action: nil)
278280

279281
init() {
280282
let window = NSWindow(
281-
contentRect: NSRect(x: 0, y: 0, width: 460, height: 348),
283+
contentRect: NSRect(x: 0, y: 0, width: 460, height: 390),
282284
styleMask: [.titled, .closable, .miniaturizable],
283285
backing: .buffered,
284286
defer: false
@@ -317,6 +319,9 @@ final class SettingsWindowController: NSWindowController {
317319
clickFeedbackCheckbox.target = self
318320
clickFeedbackCheckbox.action = #selector(clickFeedbackChanged)
319321

322+
launchAtStartupCheckbox.target = self
323+
launchAtStartupCheckbox.action = #selector(launchAtStartupChanged)
324+
320325
let radiusLabel = NSTextField(labelWithString: "Radius")
321326
radiusLabel.font = .systemFont(ofSize: 13, weight: .medium)
322327

@@ -368,7 +373,8 @@ final class SettingsWindowController: NSWindowController {
368373
innerOpacityValueLabel,
369374
colorLabel,
370375
colorWell,
371-
clickFeedbackCheckbox
376+
clickFeedbackCheckbox,
377+
launchAtStartupCheckbox
372378
].forEach {
373379
$0.translatesAutoresizingMaskIntoConstraints = false
374380
contentView.addSubview($0)
@@ -427,13 +433,17 @@ final class SettingsWindowController: NSWindowController {
427433
colorWell.heightAnchor.constraint(equalToConstant: 32),
428434

429435
clickFeedbackCheckbox.topAnchor.constraint(equalTo: colorWell.bottomAnchor, constant: 22),
430-
clickFeedbackCheckbox.leadingAnchor.constraint(equalTo: title.leadingAnchor)
436+
clickFeedbackCheckbox.leadingAnchor.constraint(equalTo: title.leadingAnchor),
437+
438+
launchAtStartupCheckbox.topAnchor.constraint(equalTo: clickFeedbackCheckbox.bottomAnchor, constant: 14),
439+
launchAtStartupCheckbox.leadingAnchor.constraint(equalTo: title.leadingAnchor)
431440
])
432441
}
433442

434443
@objc private func syncFromSettings() {
435444
enabledCheckbox.state = SettingsStore.shared.enabled ? .on : .off
436445
clickFeedbackCheckbox.state = SettingsStore.shared.clickFeedback ? .on : .off
446+
launchAtStartupCheckbox.state = SMAppService.mainApp.status == .enabled ? .on : .off
437447
radiusSlider.doubleValue = Double(SettingsStore.shared.radius)
438448
radiusValueLabel.stringValue = "\(Int(SettingsStore.shared.radius.rounded())) px"
439449
borderWidthSlider.doubleValue = Double(SettingsStore.shared.borderWidth)
@@ -451,6 +461,18 @@ final class SettingsWindowController: NSWindowController {
451461
SettingsStore.shared.clickFeedback = clickFeedbackCheckbox.state == .on
452462
}
453463

464+
@objc private func launchAtStartupChanged() {
465+
do {
466+
if launchAtStartupCheckbox.state == .on {
467+
try SMAppService.mainApp.register()
468+
} else {
469+
try SMAppService.mainApp.unregister()
470+
}
471+
} catch {
472+
launchAtStartupCheckbox.state = SMAppService.mainApp.status == .enabled ? .on : .off
473+
}
474+
}
475+
454476
@objc private func radiusChanged() {
455477
SettingsStore.shared.radius = CGFloat(radiusSlider.doubleValue)
456478
}

0 commit comments

Comments
 (0)