1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-06 11:30:08 +02:00

♻️ Include HotKey source code

This commit is contained in:
2022-03-18 18:21:55 +01:00
parent d1c40f2eb5
commit 9a6975e3d9
14 changed files with 960 additions and 41 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Nico Verbruggen
Copyright (c) 2019-2022 Nico Verbruggen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
@ -11,6 +11,16 @@
5420395F2613607600FB00FA /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; };
54B48B5F275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; };
54B48B60275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; };
54D9E0B227E4F51E003B9AD9 /* HotKeysController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */; };
54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */; };
54D9E0B427E4F51E003B9AD9 /* Key.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AD27E4F51E003B9AD9 /* Key.swift */; };
54D9E0B527E4F51E003B9AD9 /* Key.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AD27E4F51E003B9AD9 /* Key.swift */; };
54D9E0B627E4F51E003B9AD9 /* HotKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AE27E4F51E003B9AD9 /* HotKey.swift */; };
54D9E0B727E4F51E003B9AD9 /* HotKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AE27E4F51E003B9AD9 /* HotKey.swift */; };
54D9E0B827E4F51E003B9AD9 /* KeyCombo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AF27E4F51E003B9AD9 /* KeyCombo.swift */; };
54D9E0B927E4F51E003B9AD9 /* KeyCombo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AF27E4F51E003B9AD9 /* KeyCombo.swift */; };
54D9E0BA27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0B027E4F51E003B9AD9 /* ModifierFlagsExtension.swift */; };
54D9E0BB27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0B027E4F51E003B9AD9 /* ModifierFlagsExtension.swift */; };
54EAC806262F212B0092D14E /* GlobalKeybindPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41CD0282628D8EE0065BBED /* GlobalKeybindPreference.swift */; };
54FCFD26276C883F004CE748 /* SelectPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD25276C883F004CE748 /* SelectPreferenceView.xib */; };
54FCFD27276C883F004CE748 /* SelectPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD25276C883F004CE748 /* SelectPreferenceView.xib */; };
@ -112,7 +122,6 @@
C4927F0C27B2DFC200C55AFD /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4927F0A27B2DFC200C55AFD /* Errors.swift */; };
C493084A279F331F009C240B /* AddSiteVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4930849279F331F009C240B /* AddSiteVC.swift */; };
C493084B279F331F009C240B /* AddSiteVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4930849279F331F009C240B /* AddSiteVC.swift */; };
C4998F0626175E7200B2526E /* HotKey in Frameworks */ = {isa = PBXBuildFile; productRef = C4998F0526175E7200B2526E /* HotKey */; };
C4998F0A2617633900B2526E /* PrefsWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4998F092617633900B2526E /* PrefsWC.swift */; };
C4998F0B2617633900B2526E /* PrefsWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4998F092617633900B2526E /* PrefsWC.swift */; };
C49E171F27A5736E00787921 /* PMServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49E171E27A5736E00787921 /* PMServicesView.swift */; };
@ -140,7 +149,6 @@
C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */; };
C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */; };
C4BF90C127C57C220054E78C /* MainMenu+FixMyValet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42C49DA27C2806F0074ABAC /* MainMenu+FixMyValet.swift */; };
C4C1019627C659B7001FACC2 /* HotKey in Frameworks */ = {isa = PBXBuildFile; productRef = C4C1019527C659B7001FACC2 /* HotKey */; };
C4C1019B27C65C6F001FACC2 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1019A27C65C6F001FACC2 /* Process.swift */; };
C4C1019C27C65C6F001FACC2 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1019A27C65C6F001FACC2 /* Process.swift */; };
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3ED402783497000AB15D8 /* MainMenu+Startup.swift */; };
@ -231,6 +239,13 @@
5420395826135DC100FB00FA /* PrefsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVC.swift; sourceTree = "<group>"; };
5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
54B48B5E275F66AE006D90C5 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotKeysController.swift; sourceTree = "<group>"; };
54D9E0AD27E4F51E003B9AD9 /* Key.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Key.swift; sourceTree = "<group>"; };
54D9E0AE27E4F51E003B9AD9 /* HotKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotKey.swift; sourceTree = "<group>"; };
54D9E0AF27E4F51E003B9AD9 /* KeyCombo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyCombo.swift; sourceTree = "<group>"; };
54D9E0B027E4F51E003B9AD9 /* ModifierFlagsExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModifierFlagsExtension.swift; sourceTree = "<group>"; };
54D9E0BF27E4F5D9003B9AD9 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
54D9E0C027E4F5E9003B9AD9 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
54FCFD25276C883F004CE748 /* SelectPreferenceView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SelectPreferenceView.xib; sourceTree = "<group>"; };
54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxPreferenceView.swift; sourceTree = "<group>"; };
54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HotkeyPreferenceView.xib; sourceTree = "<group>"; };
@ -362,7 +377,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C4998F0626175E7200B2526E /* HotKey in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -370,7 +384,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C4C1019627C659B7001FACC2 /* HotKey in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -405,6 +418,27 @@
path = PHP;
sourceTree = "<group>";
};
54D9E0AB27E4F502003B9AD9 /* HotKey */ = {
isa = PBXGroup;
children = (
54D9E0BF27E4F5D9003B9AD9 /* LICENSE */,
54D9E0AE27E4F51E003B9AD9 /* HotKey.swift */,
54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */,
54D9E0AD27E4F51E003B9AD9 /* Key.swift */,
54D9E0AF27E4F51E003B9AD9 /* KeyCombo.swift */,
54D9E0B027E4F51E003B9AD9 /* ModifierFlagsExtension.swift */,
);
path = HotKey;
sourceTree = "<group>";
};
54D9E0BE27E4F5C0003B9AD9 /* Vendor */ = {
isa = PBXGroup;
children = (
54D9E0AB27E4F502003B9AD9 /* HotKey */,
);
path = Vendor;
sourceTree = "<group>";
};
54FCFD28276C88C0004CE748 /* Views */ = {
isa = PBXGroup;
children = (
@ -471,6 +505,7 @@
C4F8C0A522D4FA41002EFE61 /* README.md */,
C4E713562570150F00007428 /* SECURITY.md */,
C4168F4427ADB4A3003B6C39 /* DEVELOPER.md */,
54D9E0C027E4F5E9003B9AD9 /* LICENSE */,
C4E713572570151400007428 /* docs */,
C41C1B3522B0097F00E7CF16 /* phpmon */,
C4F7807A25D7F84B000DBC97 /* phpmon-tests */,
@ -493,6 +528,7 @@
children = (
C4B5853A2770FE2500DA4FBE /* Common */,
C41E181722CB61EB0072CF09 /* Domain */,
54D9E0BE27E4F5C0003B9AD9 /* Vendor */,
C41C1B3F22B0098000E7CF16 /* Info.plist */,
C4232EE42612526500158FC6 /* Credits.html */,
C41C1B4022B0098000E7CF16 /* phpmon.entitlements */,
@ -807,7 +843,6 @@
);
name = "PHP Monitor";
packageProductDependencies = (
C4998F0526175E7200B2526E /* HotKey */,
);
productName = phpmon;
productReference = C41C1B3322B0097F00E7CF16 /* PHP Monitor.app */;
@ -828,7 +863,6 @@
);
name = "phpmon-tests";
packageProductDependencies = (
C4C1019527C659B7001FACC2 /* HotKey */,
);
productName = "phpmon-tests";
productReference = C4F7807925D7F84B000DBC97 /* phpmon-tests.xctest */;
@ -862,7 +896,6 @@
);
mainGroup = C41C1B2A22B0097F00E7CF16;
packageReferences = (
C4998F0426175E7200B2526E /* XCRemoteSwiftPackageReference "HotKey" */,
);
productRefGroup = C41C1B3422B0097F00E7CF16 /* Products */;
projectDirPath = "";
@ -955,6 +988,7 @@
C415D3B72770F294005EF286 /* Actions.swift in Sources */,
C4AC51FC27E27F47008528CA /* SiteListKindCell.swift in Sources */,
C44C198D276E3A1C0072762D /* ProgressWindow.swift in Sources */,
54D9E0B827E4F51E003B9AD9 /* KeyCombo.swift in Sources */,
C4C3ED4327834C5200AB15D8 /* CustomPrefs.swift in Sources */,
54B48B5F275F66AE006D90C5 /* Application.swift in Sources */,
C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
@ -963,9 +997,11 @@
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */,
C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */,
C4F30B03278E16BA00755FCE /* HomebrewService.swift in Sources */,
54D9E0B427E4F51E003B9AD9 /* Key.swift in Sources */,
5420395F2613607600FB00FA /* Preferences.swift in Sources */,
C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */,
54FCFD2A276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */,
54D9E0B227E4F51E003B9AD9 /* HotKeysController.swift in Sources */,
C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */,
C40C7F3027722E8D00DDDCDC /* Logger.swift in Sources */,
C41CA5ED2774F8EE00A2C80E /* SiteListVC+Actions.swift in Sources */,
@ -998,9 +1034,11 @@
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
C4080FFA27BD956700BF2C6B /* BetterAlertVC.swift in Sources */,
C4B5635E276AB09000F12CCB /* VersionExtractor.swift in Sources */,
54D9E0B627E4F51E003B9AD9 /* HotKey.swift in Sources */,
C4D936C927E3EB6100BD69FE /* PhpHelper.swift in Sources */,
C47331A2247093B7009A0597 /* StatusMenu.swift in Sources */,
C44067F927E2585E0045BD4E /* SiteListTypeCell.swift in Sources */,
54D9E0BA27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */,
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */,
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */,
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
@ -1020,6 +1058,7 @@
54EAC806262F212B0092D14E /* GlobalKeybindPreference.swift in Sources */,
C4EE55AE27708B9E001DF387 /* PMStatsView.swift in Sources */,
C41CA5EE2774F8EE00A2C80E /* SiteListVC+Actions.swift in Sources */,
54D9E0B727E4F51E003B9AD9 /* HotKey.swift in Sources */,
C4F780C425D80B75000DBC97 /* MainMenu.swift in Sources */,
54FCFD2B276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */,
C415D3B82770F294005EF286 /* Actions.swift in Sources */,
@ -1029,6 +1068,7 @@
C4D9ADC0277610E1007277F4 /* PhpSwitcher.swift in Sources */,
C4080FFB27BD956700BF2C6B /* BetterAlertVC.swift in Sources */,
C4F780CC25D80B75000DBC97 /* ActivePhpInstallation.swift in Sources */,
54D9E0BB27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */,
C4F780B125D80B4D000DBC97 /* PhpExtension.swift in Sources */,
C4D5CFCB27E0F9CD00035329 /* NginxConfigParser.swift in Sources */,
C4068CA827B07A1300544CD5 /* SelectPreferenceView.swift in Sources */,
@ -1040,6 +1080,7 @@
C4C8E81C276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */,
C4F319C927B034A500AFF46F /* Stats.swift in Sources */,
C4F30B04278E16BA00755FCE /* HomebrewService.swift in Sources */,
54D9E0B527E4F51E003B9AD9 /* Key.swift in Sources */,
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */,
C4C1019C27C65C6F001FACC2 /* Process.swift in Sources */,
C4F780C025D80B6E000DBC97 /* Startup.swift in Sources */,
@ -1049,6 +1090,7 @@
C4F2E4382752F08D0020E974 /* HomebrewDiagnostics.swift in Sources */,
C4F780AE25D80B37000DBC97 /* ExtensionParserTest.swift in Sources */,
C4C8E819276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
54D9E0B927E4F51E003B9AD9 /* KeyCombo.swift in Sources */,
C4EED88A27A48778006D7272 /* InterAppHandler.swift in Sources */,
C48D6C75279CD3E400F26D7E /* PhpVersionNumberTest.swift in Sources */,
C43603A1275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
@ -1068,6 +1110,7 @@
C417DC75277614690015E6EE /* Helpers.swift in Sources */,
C4080FF727BD8C6400BF2C6B /* BetterAlert.swift in Sources */,
C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */,
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */,
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */,
@ -1372,30 +1415,6 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
C4998F0426175E7200B2526E /* XCRemoteSwiftPackageReference "HotKey" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/soffes/HotKey";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 0.1.3;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
C4998F0526175E7200B2526E /* HotKey */ = {
isa = XCSwiftPackageProductDependency;
package = C4998F0426175E7200B2526E /* XCRemoteSwiftPackageReference "HotKey" */;
productName = HotKey;
};
C4C1019527C659B7001FACC2 /* HotKey */ = {
isa = XCSwiftPackageProductDependency;
package = C4998F0426175E7200B2526E /* XCRemoteSwiftPackageReference "HotKey" */;
productName = HotKey;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = C41C1B2B22B0097F00E7CF16 /* Project object */;
}

View File

@ -42,15 +42,16 @@
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
allowLocationSimulation = "YES"
consoleMode = "1">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference

View File

@ -6,7 +6,6 @@
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import HotKey
import Cocoa
extension App {

View File

@ -6,7 +6,6 @@
//
import Cocoa
import HotKey
class App {

View File

@ -7,7 +7,6 @@
//
import Cocoa
import HotKey
import Carbon
class PrefsVC: NSViewController {

View File

@ -9,7 +9,6 @@
import Foundation
import Foundation
import HotKey
import Cocoa
class HotkeyPreferenceView: NSView, XibLoadable {

View File

@ -7,7 +7,6 @@
//
import Cocoa
import HotKey
import Carbon
class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

50
phpmon/Vendor/HotKey/HotKey.swift vendored Normal file
View File

@ -0,0 +1,50 @@
import AppKit
import Carbon
public final class HotKey {
// MARK: - Types
public typealias Handler = () -> Void
// MARK: - Properties
let identifier = UUID()
public let keyCombo: KeyCombo
public var keyDownHandler: Handler?
public var keyUpHandler: Handler?
public var isPaused = false {
didSet {
if isPaused {
HotKeysController.unregister(self)
} else {
HotKeysController.register(self)
}
}
}
// MARK: - Initializers
public init(keyCombo: KeyCombo, keyDownHandler: Handler? = nil, keyUpHandler: Handler? = nil) {
self.keyCombo = keyCombo
self.keyDownHandler = keyDownHandler
self.keyUpHandler = keyUpHandler
HotKeysController.register(self)
}
public convenience init(carbonKeyCode: UInt32, carbonModifiers: UInt32, keyDownHandler: Handler? = nil, keyUpHandler: Handler? = nil) {
let keyCombo = KeyCombo(carbonKeyCode: carbonKeyCode, carbonModifiers: carbonModifiers)
self.init(keyCombo: keyCombo, keyDownHandler: keyDownHandler, keyUpHandler: keyUpHandler)
}
public convenience init(key: Key, modifiers: NSEvent.ModifierFlags, keyDownHandler: Handler? = nil, keyUpHandler: Handler? = nil) {
let keyCombo = KeyCombo(key: key, modifiers: modifiers)
self.init(keyCombo: keyCombo, keyDownHandler: keyDownHandler, keyUpHandler: keyUpHandler)
}
deinit {
HotKeysController.unregister(self)
}
}

View File

@ -0,0 +1,185 @@
import Carbon
final class HotKeysController {
// MARK: - Types
final class HotKeyBox {
let identifier: UUID
weak var hotKey: HotKey?
let carbonHotKeyID: UInt32
var carbonEventHotKey: EventHotKeyRef?
init(hotKey: HotKey, carbonHotKeyID: UInt32) {
self.identifier = hotKey.identifier
self.hotKey = hotKey
self.carbonHotKeyID = carbonHotKeyID
}
}
// MARK: - Properties
static var hotKeys = [UInt32: HotKeyBox]()
static private var hotKeysCount: UInt32 = 0
static let eventHotKeySignature: UInt32 = {
let string = "SSHk"
var result: FourCharCode = 0
for char in string.utf16 {
result = (result << 8) + FourCharCode(char)
}
return result
}()
private static let eventSpec = [
EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed)),
EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyReleased))
]
private static var eventHandler: EventHandlerRef?
// MARK: - Registration
static func register(_ hotKey: HotKey) {
// Don't register an already registered HotKey
if hotKeys.values.first(where: { $0.identifier == hotKey.identifier }) != nil {
return
}
// Increment the count which will become out next ID
hotKeysCount += 1
// Create a box for our metadata and weak HotKey
let box = HotKeyBox(hotKey: hotKey, carbonHotKeyID: hotKeysCount)
hotKeys[box.carbonHotKeyID] = box
// Register with the system
var eventHotKey: EventHotKeyRef?
let hotKeyID = EventHotKeyID(signature: eventHotKeySignature, id: box.carbonHotKeyID)
let registerError = RegisterEventHotKey(
hotKey.keyCombo.carbonKeyCode,
hotKey.keyCombo.carbonModifiers,
hotKeyID,
GetEventDispatcherTarget(),
0,
&eventHotKey
)
// Ensure registration worked
guard registerError == noErr, eventHotKey != nil else {
return
}
// Store the event so we can unregister it later
box.carbonEventHotKey = eventHotKey
// Setup the event handler if needed
updateEventHandler()
}
static func unregister(_ hotKey: HotKey) {
// Find the box
guard let box = self.box(for: hotKey) else {
return
}
// Unregister the hot key
UnregisterEventHotKey(box.carbonEventHotKey)
// Destroy the box
box.hotKey = nil
hotKeys.removeValue(forKey: box.carbonHotKeyID)
}
// MARK: - Events
static func handleCarbonEvent(_ event: EventRef?) -> OSStatus {
// Ensure we have an event
guard let event = event else {
return OSStatus(eventNotHandledErr)
}
// Get the hot key ID from the event
var hotKeyID = EventHotKeyID()
let error = GetEventParameter(
event,
UInt32(kEventParamDirectObject),
UInt32(typeEventHotKeyID),
nil,
MemoryLayout<EventHotKeyID>.size,
nil,
&hotKeyID
)
if error != noErr {
return error
}
// Ensure we have a HotKey registered for this ID
guard hotKeyID.signature == eventHotKeySignature,
let hotKey = self.hotKey(for: hotKeyID.id)
else {
return OSStatus(eventNotHandledErr)
}
// Call the handler
switch GetEventKind(event) {
case UInt32(kEventHotKeyPressed):
if !hotKey.isPaused, let handler = hotKey.keyDownHandler {
handler()
return noErr
}
case UInt32(kEventHotKeyReleased):
if !hotKey.isPaused, let handler = hotKey.keyUpHandler {
handler()
return noErr
}
default:
break
}
return OSStatus(eventNotHandledErr)
}
private static func updateEventHandler() {
if hotKeysCount == 0 || eventHandler != nil {
return
}
// Register for key down and key up
let eventSpec = [
EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed)),
EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyReleased))
]
// Install the handler
InstallEventHandler(GetEventDispatcherTarget(), hotKeyEventHandler, 2, eventSpec, nil, &eventHandler)
}
// MARK: - Querying
private static func hotKey(for carbonHotKeyID: UInt32) -> HotKey? {
if let hotKey = hotKeys[carbonHotKeyID]?.hotKey {
return hotKey
}
hotKeys.removeValue(forKey: carbonHotKeyID)
return nil
}
private static func box(for hotKey: HotKey) -> HotKeyBox? {
for box in hotKeys.values {
if box.identifier == hotKey.identifier {
return box
}
}
return nil
}
}
private func hotKeyEventHandler(eventHandlerCall: EventHandlerCallRef?, event: EventRef?, userData: UnsafeMutableRawPointer?) -> OSStatus {
return HotKeysController.handleCarbonEvent(event)
}

497
phpmon/Vendor/HotKey/Key.swift vendored Normal file
View File

@ -0,0 +1,497 @@
import Carbon
public enum Key {
// MARK: - Letters
case a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
// MARK: - Numbers
case zero, one, two, three, four, five, six, seven, eight, nine
// MARK: - Symbols
case period, quote, rightBracket, semicolon, slash, backslash, comma, equal, grave, leftBracket, minus
// MARK: - Whitespace
case space, tab, `return`
// MARK: - Modifiers
case command, rightCommand, option, rightOption, control, rightControl, shift, rightShift, function, capsLock
// MARK: - Navigation
case pageUp, pageDown, home, end, upArrow, rightArrow, downArrow, leftArrow
// MARK: - Functions
case f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20
// MARK: - Keypad
case keypad0, keypad1, keypad2, keypad3, keypad4, keypad5, keypad6, keypad7, keypad8, keypad9,
keypadClear, keypadDecimal, keypadDivide, keypadEnter, keypadEquals, keypadMinus, keypadMultiply, keypadPlus
// MARK: - Misc
case escape, delete, forwardDelete, help, volumeUp, volumeDown, mute
// MARK: - Initializers
public init?(string: String) {
switch string.lowercased() {
case "a": self = .a
case "s": self = .s
case "d": self = .d
case "f": self = .f
case "h": self = .h
case "g": self = .g
case "z": self = .z
case "x": self = .x
case "c": self = .c
case "v": self = .v
case "b": self = .b
case "q": self = .q
case "w": self = .w
case "e": self = .e
case "r": self = .r
case "y": self = .y
case "t": self = .t
case "one", "1": self = .one
case "two", "2": self = .two
case "three", "3": self = .three
case "four", "4": self = .four
case "six", "6": self = .six
case "five", "5": self = .five
case "equal", "=": self = .equal
case "nine", "9": self = .nine
case "seven", "7": self = .seven
case "minus", "-": self = .minus
case "eight", "8": self = .eight
case "zero", "0": self = .zero
case "rightBracket", "]": self = .rightBracket
case "o": self = .o
case "u": self = .u
case "leftBracket", "[": self = .leftBracket
case "i": self = .i
case "p": self = .p
case "l": self = .l
case "j": self = .j
case "quote", "\"": self = .quote
case "k": self = .k
case "semicolon", ";": self = .semicolon
case "backslash", "\\": self = .backslash
case "comma", ",": self = .comma
case "slash", "/": self = .slash
case "n": self = .n
case "m": self = .m
case "period", ".": self = .period
case "grave", "`", "ˋ", "": self = .grave
case "keypaddecimal": self = .keypadDecimal
case "keypadmultiply": self = .keypadMultiply
case "keypadplus": self = .keypadPlus
case "keypadclear", "": self = .keypadClear
case "keypaddivide": self = .keypadDivide
case "keypadenter": self = .keypadEnter
case "keypadminus": self = .keypadMinus
case "keypadequals": self = .keypadEquals
case "keypad0": self = .keypad0
case "keypad1": self = .keypad1
case "keypad2": self = .keypad2
case "keypad3": self = .keypad3
case "keypad4": self = .keypad4
case "keypad5": self = .keypad5
case "keypad6": self = .keypad6
case "keypad7": self = .keypad7
case "keypad8": self = .keypad8
case "keypad9": self = .keypad9
case "return", "\r", "↩︎", "", "": self = .return
case "tab", "\t", "": self = .tab
case "space", " ", "": self = .space
case "delete", "": self = .delete
case "escape", "": self = .escape
case "command", "", "": self = .command
case "shift", "": self = .shift
case "capslock", "": self = .capsLock
case "option", "": self = .option
case "control", "": self = .control
case "rightcommand": self = .rightCommand
case "rightshift": self = .rightShift
case "rightoption": self = .rightOption
case "rightcontrol": self = .rightControl
case "function", "fn": self = .function
case "f17", "F17": self = .f17
case "volumeup", "🔊": self = .volumeUp
case "volumedown", "🔉": self = .volumeDown
case "mute", "🔇": self = .mute
case "f18", "F18": self = .f18
case "f19", "F19": self = .f19
case "f20", "F20": self = .f20
case "f5", "F5": self = .f5
case "f6", "F6": self = .f6
case "f7", "F7": self = .f7
case "f3", "F3": self = .f3
case "f8", "F8": self = .f8
case "f9", "F9": self = .f9
case "f11", "F11": self = .f11
case "f13", "F13": self = .f13
case "f16", "F16": self = .f16
case "f14", "F14": self = .f14
case "f10", "F10": self = .f10
case "f12", "F12": self = .f12
case "f15", "F15": self = .f15
case "help", "?⃝": self = .help
case "home", "": self = .home
case "pageup", "": self = .pageUp
case "forwarddelete", "": self = .forwardDelete
case "f4", "F4": self = .f4
case "end", "": self = .end
case "f2", "F2": self = .f2
case "pagedown", "": self = .pageDown
case "f1", "F1": self = .f1
case "leftarrow", "": self = .leftArrow
case "rightarrow", "": self = .rightArrow
case "downarrow", "": self = .downArrow
case "uparrow", "": self = .upArrow
default: return nil
}
}
public init?(carbonKeyCode: UInt32) {
switch carbonKeyCode {
case UInt32(kVK_ANSI_A): self = .a
case UInt32(kVK_ANSI_S): self = .s
case UInt32(kVK_ANSI_D): self = .d
case UInt32(kVK_ANSI_F): self = .f
case UInt32(kVK_ANSI_H): self = .h
case UInt32(kVK_ANSI_G): self = .g
case UInt32(kVK_ANSI_Z): self = .z
case UInt32(kVK_ANSI_X): self = .x
case UInt32(kVK_ANSI_C): self = .c
case UInt32(kVK_ANSI_V): self = .v
case UInt32(kVK_ANSI_B): self = .b
case UInt32(kVK_ANSI_Q): self = .q
case UInt32(kVK_ANSI_W): self = .w
case UInt32(kVK_ANSI_E): self = .e
case UInt32(kVK_ANSI_R): self = .r
case UInt32(kVK_ANSI_Y): self = .y
case UInt32(kVK_ANSI_T): self = .t
case UInt32(kVK_ANSI_1): self = .one
case UInt32(kVK_ANSI_2): self = .two
case UInt32(kVK_ANSI_3): self = .three
case UInt32(kVK_ANSI_4): self = .four
case UInt32(kVK_ANSI_6): self = .six
case UInt32(kVK_ANSI_5): self = .five
case UInt32(kVK_ANSI_Equal): self = .equal
case UInt32(kVK_ANSI_9): self = .nine
case UInt32(kVK_ANSI_7): self = .seven
case UInt32(kVK_ANSI_Minus): self = .minus
case UInt32(kVK_ANSI_8): self = .eight
case UInt32(kVK_ANSI_0): self = .zero
case UInt32(kVK_ANSI_RightBracket): self = .rightBracket
case UInt32(kVK_ANSI_O): self = .o
case UInt32(kVK_ANSI_U): self = .u
case UInt32(kVK_ANSI_LeftBracket): self = .leftBracket
case UInt32(kVK_ANSI_I): self = .i
case UInt32(kVK_ANSI_P): self = .p
case UInt32(kVK_ANSI_L): self = .l
case UInt32(kVK_ANSI_J): self = .j
case UInt32(kVK_ANSI_Quote): self = .quote
case UInt32(kVK_ANSI_K): self = .k
case UInt32(kVK_ANSI_Semicolon): self = .semicolon
case UInt32(kVK_ANSI_Backslash): self = .backslash
case UInt32(kVK_ANSI_Comma): self = .comma
case UInt32(kVK_ANSI_Slash): self = .slash
case UInt32(kVK_ANSI_N): self = .n
case UInt32(kVK_ANSI_M): self = .m
case UInt32(kVK_ANSI_Period): self = .period
case UInt32(kVK_ANSI_Grave): self = .grave
case UInt32(kVK_ANSI_KeypadDecimal): self = .keypadDecimal
case UInt32(kVK_ANSI_KeypadMultiply): self = .keypadMultiply
case UInt32(kVK_ANSI_KeypadPlus): self = .keypadPlus
case UInt32(kVK_ANSI_KeypadClear): self = .keypadClear
case UInt32(kVK_ANSI_KeypadDivide): self = .keypadDivide
case UInt32(kVK_ANSI_KeypadEnter): self = .keypadEnter
case UInt32(kVK_ANSI_KeypadMinus): self = .keypadMinus
case UInt32(kVK_ANSI_KeypadEquals): self = .keypadEquals
case UInt32(kVK_ANSI_Keypad0): self = .keypad0
case UInt32(kVK_ANSI_Keypad1): self = .keypad1
case UInt32(kVK_ANSI_Keypad2): self = .keypad2
case UInt32(kVK_ANSI_Keypad3): self = .keypad3
case UInt32(kVK_ANSI_Keypad4): self = .keypad4
case UInt32(kVK_ANSI_Keypad5): self = .keypad5
case UInt32(kVK_ANSI_Keypad6): self = .keypad6
case UInt32(kVK_ANSI_Keypad7): self = .keypad7
case UInt32(kVK_ANSI_Keypad8): self = .keypad8
case UInt32(kVK_ANSI_Keypad9): self = .keypad9
case UInt32(kVK_Return): self = .`return`
case UInt32(kVK_Tab): self = .tab
case UInt32(kVK_Space): self = .space
case UInt32(kVK_Delete): self = .delete
case UInt32(kVK_Escape): self = .escape
case UInt32(kVK_Command): self = .command
case UInt32(kVK_Shift): self = .shift
case UInt32(kVK_CapsLock): self = .capsLock
case UInt32(kVK_Option): self = .option
case UInt32(kVK_Control): self = .control
case UInt32(kVK_RightCommand): self = .rightCommand
case UInt32(kVK_RightShift): self = .rightShift
case UInt32(kVK_RightOption): self = .rightOption
case UInt32(kVK_RightControl): self = .rightControl
case UInt32(kVK_Function): self = .function
case UInt32(kVK_F17): self = .f17
case UInt32(kVK_VolumeUp): self = .volumeUp
case UInt32(kVK_VolumeDown): self = .volumeDown
case UInt32(kVK_Mute): self = .mute
case UInt32(kVK_F18): self = .f18
case UInt32(kVK_F19): self = .f19
case UInt32(kVK_F20): self = .f20
case UInt32(kVK_F5): self = .f5
case UInt32(kVK_F6): self = .f6
case UInt32(kVK_F7): self = .f7
case UInt32(kVK_F3): self = .f3
case UInt32(kVK_F8): self = .f8
case UInt32(kVK_F9): self = .f9
case UInt32(kVK_F11): self = .f11
case UInt32(kVK_F13): self = .f13
case UInt32(kVK_F16): self = .f16
case UInt32(kVK_F14): self = .f14
case UInt32(kVK_F10): self = .f10
case UInt32(kVK_F12): self = .f12
case UInt32(kVK_F15): self = .f15
case UInt32(kVK_Help): self = .help
case UInt32(kVK_Home): self = .home
case UInt32(kVK_PageUp): self = .pageUp
case UInt32(kVK_ForwardDelete): self = .forwardDelete
case UInt32(kVK_F4): self = .f4
case UInt32(kVK_End): self = .end
case UInt32(kVK_F2): self = .f2
case UInt32(kVK_PageDown): self = .pageDown
case UInt32(kVK_F1): self = .f1
case UInt32(kVK_LeftArrow): self = .leftArrow
case UInt32(kVK_RightArrow): self = .rightArrow
case UInt32(kVK_DownArrow): self = .downArrow
case UInt32(kVK_UpArrow): self = .upArrow
default: return nil
}
}
public var carbonKeyCode: UInt32 {
switch self {
case .a: return UInt32(kVK_ANSI_A)
case .s: return UInt32(kVK_ANSI_S)
case .d: return UInt32(kVK_ANSI_D)
case .f: return UInt32(kVK_ANSI_F)
case .h: return UInt32(kVK_ANSI_H)
case .g: return UInt32(kVK_ANSI_G)
case .z: return UInt32(kVK_ANSI_Z)
case .x: return UInt32(kVK_ANSI_X)
case .c: return UInt32(kVK_ANSI_C)
case .v: return UInt32(kVK_ANSI_V)
case .b: return UInt32(kVK_ANSI_B)
case .q: return UInt32(kVK_ANSI_Q)
case .w: return UInt32(kVK_ANSI_W)
case .e: return UInt32(kVK_ANSI_E)
case .r: return UInt32(kVK_ANSI_R)
case .y: return UInt32(kVK_ANSI_Y)
case .t: return UInt32(kVK_ANSI_T)
case .one: return UInt32(kVK_ANSI_1)
case .two: return UInt32(kVK_ANSI_2)
case .three: return UInt32(kVK_ANSI_3)
case .four: return UInt32(kVK_ANSI_4)
case .six: return UInt32(kVK_ANSI_6)
case .five: return UInt32(kVK_ANSI_5)
case .equal: return UInt32(kVK_ANSI_Equal)
case .nine: return UInt32(kVK_ANSI_9)
case .seven: return UInt32(kVK_ANSI_7)
case .minus: return UInt32(kVK_ANSI_Minus)
case .eight: return UInt32(kVK_ANSI_8)
case .zero: return UInt32(kVK_ANSI_0)
case .rightBracket: return UInt32(kVK_ANSI_RightBracket)
case .o: return UInt32(kVK_ANSI_O)
case .u: return UInt32(kVK_ANSI_U)
case .leftBracket: return UInt32(kVK_ANSI_LeftBracket)
case .i: return UInt32(kVK_ANSI_I)
case .p: return UInt32(kVK_ANSI_P)
case .l: return UInt32(kVK_ANSI_L)
case .j: return UInt32(kVK_ANSI_J)
case .quote: return UInt32(kVK_ANSI_Quote)
case .k: return UInt32(kVK_ANSI_K)
case .semicolon: return UInt32(kVK_ANSI_Semicolon)
case .backslash: return UInt32(kVK_ANSI_Backslash)
case .comma: return UInt32(kVK_ANSI_Comma)
case .slash: return UInt32(kVK_ANSI_Slash)
case .n: return UInt32(kVK_ANSI_N)
case .m: return UInt32(kVK_ANSI_M)
case .period: return UInt32(kVK_ANSI_Period)
case .grave: return UInt32(kVK_ANSI_Grave)
case .keypadDecimal: return UInt32(kVK_ANSI_KeypadDecimal)
case .keypadMultiply: return UInt32(kVK_ANSI_KeypadMultiply)
case .keypadPlus: return UInt32(kVK_ANSI_KeypadPlus)
case .keypadClear: return UInt32(kVK_ANSI_KeypadClear)
case .keypadDivide: return UInt32(kVK_ANSI_KeypadDivide)
case .keypadEnter: return UInt32(kVK_ANSI_KeypadEnter)
case .keypadMinus: return UInt32(kVK_ANSI_KeypadMinus)
case .keypadEquals: return UInt32(kVK_ANSI_KeypadEquals)
case .keypad0: return UInt32(kVK_ANSI_Keypad0)
case .keypad1: return UInt32(kVK_ANSI_Keypad1)
case .keypad2: return UInt32(kVK_ANSI_Keypad2)
case .keypad3: return UInt32(kVK_ANSI_Keypad3)
case .keypad4: return UInt32(kVK_ANSI_Keypad4)
case .keypad5: return UInt32(kVK_ANSI_Keypad5)
case .keypad6: return UInt32(kVK_ANSI_Keypad6)
case .keypad7: return UInt32(kVK_ANSI_Keypad7)
case .keypad8: return UInt32(kVK_ANSI_Keypad8)
case .keypad9: return UInt32(kVK_ANSI_Keypad9)
case .`return`: return UInt32(kVK_Return)
case .tab: return UInt32(kVK_Tab)
case .space: return UInt32(kVK_Space)
case .delete: return UInt32(kVK_Delete)
case .escape: return UInt32(kVK_Escape)
case .command: return UInt32(kVK_Command)
case .shift: return UInt32(kVK_Shift)
case .capsLock: return UInt32(kVK_CapsLock)
case .option: return UInt32(kVK_Option)
case .control: return UInt32(kVK_Control)
case .rightCommand: return UInt32(kVK_RightCommand)
case .rightShift: return UInt32(kVK_RightShift)
case .rightOption: return UInt32(kVK_RightOption)
case .rightControl: return UInt32(kVK_RightControl)
case .function: return UInt32(kVK_Function)
case .f17: return UInt32(kVK_F17)
case .volumeUp: return UInt32(kVK_VolumeUp)
case .volumeDown: return UInt32(kVK_VolumeDown)
case .mute: return UInt32(kVK_Mute)
case .f18: return UInt32(kVK_F18)
case .f19: return UInt32(kVK_F19)
case .f20: return UInt32(kVK_F20)
case .f5: return UInt32(kVK_F5)
case .f6: return UInt32(kVK_F6)
case .f7: return UInt32(kVK_F7)
case .f3: return UInt32(kVK_F3)
case .f8: return UInt32(kVK_F8)
case .f9: return UInt32(kVK_F9)
case .f11: return UInt32(kVK_F11)
case .f13: return UInt32(kVK_F13)
case .f16: return UInt32(kVK_F16)
case .f14: return UInt32(kVK_F14)
case .f10: return UInt32(kVK_F10)
case .f12: return UInt32(kVK_F12)
case .f15: return UInt32(kVK_F15)
case .help: return UInt32(kVK_Help)
case .home: return UInt32(kVK_Home)
case .pageUp: return UInt32(kVK_PageUp)
case .forwardDelete: return UInt32(kVK_ForwardDelete)
case .f4: return UInt32(kVK_F4)
case .end: return UInt32(kVK_End)
case .f2: return UInt32(kVK_F2)
case .pageDown: return UInt32(kVK_PageDown)
case .f1: return UInt32(kVK_F1)
case .leftArrow: return UInt32(kVK_LeftArrow)
case .rightArrow: return UInt32(kVK_RightArrow)
case .downArrow: return UInt32(kVK_DownArrow)
case .upArrow: return UInt32(kVK_UpArrow)
}
}
}
extension Key: CustomStringConvertible {
public var description: String {
switch self {
case .a: return "A"
case .s: return "S"
case .d: return "D"
case .f: return "F"
case .h: return "H"
case .g: return "G"
case .z: return "Z"
case .x: return "X"
case .c: return "C"
case .v: return "V"
case .b: return "B"
case .q: return "Q"
case .w: return "W"
case .e: return "E"
case .r: return "R"
case .y: return "Y"
case .t: return "T"
case .one, .keypad1: return "1"
case .two, .keypad2: return "2"
case .three, .keypad3: return "3"
case .four, .keypad4: return "4"
case .six, .keypad6: return "6"
case .five, .keypad5: return "5"
case .equal: return "="
case .nine, .keypad9: return "9"
case .seven, .keypad7: return "7"
case .minus: return "-"
case .eight, .keypad8: return "8"
case .zero, .keypad0: return "0"
case .rightBracket: return "]"
case .o: return "O"
case .u: return "U"
case .leftBracket: return "["
case .i: return "I"
case .p: return "P"
case .l: return "L"
case .j: return "J"
case .quote: return "\""
case .k: return "K"
case .semicolon: return ";"
case .backslash: return "\\"
case .comma: return ","
case .slash: return "/"
case .n: return "N"
case .m: return "M"
case .period: return "."
case .grave: return "`"
case .keypadDecimal: return "."
case .keypadMultiply: return "𝗑"
case .keypadPlus: return "+"
case .keypadClear: return ""
case .keypadDivide: return "/"
case .keypadEnter: return "↩︎"
case .keypadMinus: return "-"
case .keypadEquals: return "="
case .`return`: return "↩︎"
case .tab: return ""
case .space: return ""
case .delete: return ""
case .escape: return ""
case .command, .rightCommand: return ""
case .shift, .rightShift: return ""
case .capsLock: return ""
case .option, .rightOption: return ""
case .control, .rightControl: return ""
case .function: return "fn"
case .f17: return "F17"
case .volumeUp: return "🔊"
case .volumeDown: return "🔉"
case .mute: return "🔇"
case .f18: return "F18"
case .f19: return "F19"
case .f20: return "F20"
case .f5: return "F5"
case .f6: return "F6"
case .f7: return "F7"
case .f3: return "F3"
case .f8: return "F8"
case .f9: return "F9"
case .f11: return "F11"
case .f13: return "F13"
case .f16: return "F16"
case .f14: return "F14"
case .f10: return "F10"
case .f12: return "F12"
case .f15: return "F15"
case .help: return "?⃝"
case .home: return ""
case .pageUp: return ""
case .forwardDelete: return ""
case .f4: return "F4"
case .end: return ""
case .f2: return "F2"
case .pageDown: return ""
case .f1: return "F1"
case .leftArrow: return ""
case .rightArrow: return ""
case .downArrow: return ""
case .upArrow: return ""
}
}
}

82
phpmon/Vendor/HotKey/KeyCombo.swift vendored Normal file
View File

@ -0,0 +1,82 @@
import AppKit
public struct KeyCombo: Equatable {
// MARK: - Properties
public var carbonKeyCode: UInt32
public var carbonModifiers: UInt32
public var key: Key? {
get {
return Key(carbonKeyCode: carbonKeyCode)
}
set {
carbonKeyCode = newValue?.carbonKeyCode ?? 0
}
}
public var modifiers: NSEvent.ModifierFlags {
get {
return NSEvent.ModifierFlags(carbonFlags: carbonModifiers)
}
set {
carbonModifiers = newValue.carbonFlags
}
}
public var isValid: Bool {
return carbonKeyCode >= 0
}
// MARK: - Initializers
public init(carbonKeyCode: UInt32, carbonModifiers: UInt32 = 0) {
self.carbonKeyCode = carbonKeyCode
self.carbonModifiers = carbonModifiers
}
public init(key: Key, modifiers: NSEvent.ModifierFlags = []) {
self.carbonKeyCode = key.carbonKeyCode
self.carbonModifiers = modifiers.carbonFlags
}
// MARK: - Converting Keys
public static func carbonKeyCodeToString(_ carbonKeyCode: UInt32) -> String? {
return nil
}
}
extension KeyCombo {
public var dictionary: [String: Any] {
return [
"keyCode": Int(carbonKeyCode),
"modifiers": Int(carbonModifiers)
]
}
public init?(dictionary: [String: Any]) {
guard let keyCode = dictionary["keyCode"] as? Int,
let modifiers = dictionary["modifiers"] as? Int
else {
return nil
}
self.init(carbonKeyCode: UInt32(keyCode), carbonModifiers: UInt32(modifiers))
}
}
extension KeyCombo: CustomStringConvertible {
public var description: String {
var output = modifiers.description
if let keyDescription = key?.description {
output += keyDescription
}
return output
}
}

20
phpmon/Vendor/HotKey/LICENSE vendored Normal file
View File

@ -0,0 +1,20 @@
Copyright (c) 20172019 Sam Soffes, http://soff.es
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,70 @@
import AppKit
import Carbon
extension NSEvent.ModifierFlags {
public var carbonFlags: UInt32 {
var carbonFlags: UInt32 = 0
if contains(.command) {
carbonFlags |= UInt32(cmdKey)
}
if contains(.option) {
carbonFlags |= UInt32(optionKey)
}
if contains(.control) {
carbonFlags |= UInt32(controlKey)
}
if contains(.shift) {
carbonFlags |= UInt32(shiftKey)
}
return carbonFlags
}
public init(carbonFlags: UInt32) {
self.init()
if carbonFlags & UInt32(cmdKey) == UInt32(cmdKey) {
insert(.command)
}
if carbonFlags & UInt32(optionKey) == UInt32(optionKey) {
insert(.option)
}
if carbonFlags & UInt32(controlKey) == UInt32(controlKey) {
insert(.control)
}
if carbonFlags & UInt32(shiftKey) == UInt32(shiftKey) {
insert(.shift)
}
}
}
extension NSEvent.ModifierFlags: CustomStringConvertible {
public var description: String {
var output = ""
if contains(.control) {
output += Key.control.description
}
if contains(.option) {
output += Key.option.description
}
if contains(.shift) {
output += Key.shift.description
}
if contains(.command) {
output += Key.command.description
}
return output
}
}