prole/prole-app/Sources/HotKeyManager.swift
chrisfu 8a6e8738db ProleStatus: app-window default, light splash restored, status bar controls; endpoint config via properties; build + docs
- Default to Application Window mode with full app menu; status bar overlay remains available
- Restore clickable startup Splash Tip (5s) with animated GIF and live counter; use light theme (Aqua)
- Status bar item: monospaced "P" icon; left click shows overlay (status mode) or main window (app mode)
- Overlay: add Maximize button (□) to toggle back to main window; keep click‑through elsewhere
- Global hotkey Cmd+Opt+Shift+P toggles modes; Prole menu item mirrors the same toggle and updates title dynamically
- Application menu (Prole): Show Status Bar / Show Main Window (contextual), Refresh Now, Quit
- Application Window layout: non‑scrolling, vertical 1‑line rows (svc, k3s aggregate, local) with top‑right timestamp; bottom‑left controls (⟳ Refresh, _ Minimize)
- Parameterize endpoints via `prole.properties` (bundled + user override). Replace legacy raspberry with retropie defaults
- ServiceChecker + UI read endpoints from Config loader; tooltips/labels reflect configured hosts/ports
- Build script: generate `Info.plist` with `LSUIElement=false`; bundle resources (`prole-type.gif`, `prole.properties`); ad‑hoc codesign. Universal build supported
- Documentation: rewrite README with technical build/run/config details and operational posture

Files:
- proleStatus/Sources/: AppDelegate.swift, OverlayWindow.swift, StatusView.swift, StatusItemController.swift,
  SplashTipWindowController.swift, MainWindowController.swift, AppStatusView.swift, ServiceChecker.swift, Config.swift
- proleStatus/build.sh
- proleStatus/prole.properties
- proleStatus/README.md

Notes:
- Build verified via `./build.sh build` (arm64). App starts in App Window mode with light theme; menu + hotkey + overlay toggle operate as intended
2025-12-01 21:08:30 -08:00

35 lines
1.5 KiB
Swift

import AppKit
import Carbon.HIToolbox
final class HotKeyManager {
private var hotKeyRef: EventHotKeyRef?
enum Key: UInt32 { case p = 35 /* US keyboard virtual keycode for P */ }
struct Modifiers: OptionSet {
let rawValue: UInt32
static let command = Modifiers(rawValue: UInt32(cmdKey))
static let option = Modifiers(rawValue: UInt32(optionKey))
static let shift = Modifiers(rawValue: UInt32(shiftKey))
}
func registerGlobalHotKey(modifiers: Modifiers, key: Key, handler: @escaping () -> Void) {
var eventSpec = EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed))
InstallEventHandler(GetApplicationEventTarget(), { (_, _, userData) -> OSStatus in
let handler = Unmanaged<HotKeyHandlerWrapper>.fromOpaque(userData!).takeUnretainedValue()
handler.handler()
return noErr
}, 1, &eventSpec, Unmanaged.passRetained(HotKeyHandlerWrapper(handler: handler)).toOpaque(), nil)
let hotKeyID = EventHotKeyID(signature: OSType(UInt32(bitPattern: Int32(bitPattern: 0x50524F4C))), id: 1) // 'PROL'
RegisterEventHotKey(UInt32(key.rawValue), modifiers.rawValue, hotKeyID, GetApplicationEventTarget(), 0, &hotKeyRef)
}
deinit { if let ref = hotKeyRef { UnregisterEventHotKey(ref) } }
}
private final class HotKeyHandlerWrapper {
let handler: () -> Void
init(handler: @escaping () -> Void) { self.handler = handler }
}