feat: can pass the --logs= flags at launch to show logs
This commit is contained in:
1 parent
f7de2bb6d9
commit
81eb07ee98
17 files changed
+139
-131
No files matched your search
@@ -22,7 +22,7 @@
|
||||
1C96132D9BFCC988B0013509 /* app_icons_show_running_applications_windows_light@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1C961334F059C39979BEDF19 /* app_icons_show_running_applications_windows_light@2x.jpg */; };
|
||||
1C961383737C00845E881EA6 /* thumbnails_show_app_badges_light@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1C9617A90991E963760F7475 /* thumbnails_show_app_badges_light@2x.jpg */; };
|
||||
1C9614261DF293C650675A6C /* titles_hide_tabs_as_windows_light@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1C9619DEB8B7905DBF9A6030 /* titles_hide_tabs_as_windows_light@2x.jpg */; };
|
||||
1C96143D5AD69C894A4D8375 /* LogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C96110EB5B28C814DA35465 /* LogManager.swift */; };
|
||||
1C96143D5AD69C894A4D8375 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C96110EB5B28C814DA35465 /* Logger.swift */; };
|
||||
1C96149CFE6DB491DCAEA943 /* titles_light@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1C961B26B70C826BBD762AC5 /* titles_light@2x.jpg */; };
|
||||
1C9614C924F2EEB592314C67 /* app_icons_show_running_windows_light@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1C96127120349FE18C5C39DA /* app_icons_show_running_windows_light@2x.jpg */; };
|
||||
1C9614D96191FACFACD38055 /* thumbnails_align_thumbnails_center_light@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1C9610071E9F3434C893DC95 /* thumbnails_align_thumbnails_center_light@2x.jpg */; };
|
||||
@@ -74,6 +74,7 @@
|
||||
5F706EC32BA448D8004D542D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5F706EC12BA448D8004D542D /* InfoPlist.strings */; };
|
||||
76D02BB22BFE7C9E0056008D /* Pods_alt_tab_macos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0712B3BEA2B3780398C0999 /* Pods_alt_tab_macos.framework */; };
|
||||
AA974BA929B7D84C0099A29E /* PreviewPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA974BA829B7D84C0099A29E /* PreviewPanel.swift */; };
|
||||
BF0C80484AA63306D0DB4DB2 /* SpacesEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8DF008F1EB5F23291A13 /* SpacesEvents.swift */; };
|
||||
BF0C8052AE41B1B10E42BFCE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C875C983226CB16DBD90F /* InfoPlist.strings */; };
|
||||
BF0C8053A58DFB383A3E3351 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8E237569FA2A8FE20707 /* InfoPlist.strings */; };
|
||||
BF0C807D26E465F467B066F7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C849EBA5A547912BD8BB9 /* Localizable.strings */; };
|
||||
@@ -84,6 +85,7 @@
|
||||
BF0C81A79128CF877FE895CC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8A48BBB3BF649864DB08 /* InfoPlist.strings */; };
|
||||
BF0C81B64A1205F066AC796A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C80404D3455D496C02F29 /* Localizable.strings */; };
|
||||
BF0C81D836A8A4CA393B135F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C82E55127D38ABF969CA0 /* InfoPlist.strings */; };
|
||||
BF0C8203D0EFEDEED0F908E8 /* ScreensEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C822D3BEDAB1F1C9F775E /* ScreensEvents.swift */; };
|
||||
BF0C820C6E89C2D90FA30A4B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8F67ABD271F26FA0EDEF /* Localizable.strings */; };
|
||||
BF0C8224CFD1ED511F3F0063 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8D94228D90FE99D4A3C8 /* Localizable.strings */; };
|
||||
BF0C823630E3DEAC576FAFE6 /* menubar-1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BF0C88BF67CF4D71002A60EB /* menubar-1@2x.png */; };
|
||||
@@ -120,6 +122,7 @@
|
||||
BF0C898511686611E4D7D81E /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8B2C057099EDABE46779 /* Button.swift */; };
|
||||
BF0C89C49CFBAAB4646BB8CB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C82A8848224E76B880A83 /* InfoPlist.strings */; };
|
||||
BF0C89F0632E0A2EC52D9168 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C87749F1A64E2D3305181 /* InfoPlist.strings */; };
|
||||
BF0C8A3F32B2177AF407DC7E /* DockEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C870C14C20C936BA4AF40 /* DockEvents.swift */; };
|
||||
BF0C8A739A74695E60F16369 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8062E78677398A4A217B /* InfoPlist.strings */; };
|
||||
BF0C8A95AAD9DADC95887A2D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C895A9AF79A869EE6B108 /* Localizable.strings */; };
|
||||
BF0C8AC57CE5E9BBEEE2442A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C885D34CDCE2AFC5A94F7 /* InfoPlist.strings */; };
|
||||
@@ -160,7 +163,7 @@
|
||||
D04BA15A1B0C4871EA7CB899 /* GeneralTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BACE22DC907F03D193075 /* GeneralTab.swift */; };
|
||||
D04BA1621718FF26F8D5E75D /* CustomRecorderControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAE333F7170E87C5AC0EF /* CustomRecorderControl.swift */; };
|
||||
D04BA1637E125D38546C26E2 /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA8AC77465E1B2BC947CF /* StackView.swift */; };
|
||||
D04BA1766FBCB2E941D081A5 /* WorkspaceEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA76AEE37D6656EB80126 /* WorkspaceEvents.swift */; };
|
||||
D04BA1766FBCB2E941D081A5 /* RunningApplicationsEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA76AEE37D6656EB80126 /* RunningApplicationsEvents.swift */; };
|
||||
D04BA1B133D53572D7B312C2 /* ThumbnailFontIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA1DF8CAB2FAB7FE9244B /* ThumbnailFontIconView.swift */; };
|
||||
D04BA1C85041FB043FD43E65 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA05006D56C7AA011C0CE /* Localizable.strings */; };
|
||||
D04BA1CEC6B9C8945FEC8740 /* ThumbnailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA258B56193958D60978A /* ThumbnailView.swift */; };
|
||||
@@ -254,7 +257,7 @@
|
||||
1C961093FB75180759EC6972 /* app_icons_hide_app_badges_light@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "app_icons_hide_app_badges_light@2x.jpg"; sourceTree = "<group>"; };
|
||||
1C9610B2E76F1E429C8D3660 /* titles_show_running_windows_light@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "titles_show_running_windows_light@2x.jpg"; sourceTree = "<group>"; };
|
||||
1C9611039BDBE0C84F349BA1 /* titles_show_status_icons_light@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "titles_show_status_icons_light@2x.jpg"; sourceTree = "<group>"; };
|
||||
1C96110EB5B28C814DA35465 /* LogManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogManager.swift; sourceTree = "<group>"; };
|
||||
1C96110EB5B28C814DA35465 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
|
||||
1C96112432E87D36F90AFBED /* translate_i18n_tools.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = translate_i18n_tools.py; sourceTree = "<group>"; };
|
||||
1C9611334B667767A4514B57 /* thumbnails_hide_space_number_labels_light@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "thumbnails_hide_space_number_labels_light@2x.jpg"; sourceTree = "<group>"; };
|
||||
1C961139B16ADE6E0B8A33A6 /* thumbnails_show_running_applications_windows_light@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "thumbnails_show_running_applications_windows_light@2x.jpg"; sourceTree = "<group>"; };
|
||||
@@ -333,6 +336,7 @@
|
||||
BF0C816F38751995E4F49BB0 /* he */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = he; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C817E063D1405392D6C5B /* he */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = he; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C81D602ED642A48D50B78 /* notarytool */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notarytool; sourceTree = "<group>"; };
|
||||
BF0C822D3BEDAB1F1C9F775E /* ScreensEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreensEvents.swift; sourceTree = "<group>"; };
|
||||
BF0C828AF7BCC4F47E70B28F /* menubar-2.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = "menubar-2.svg"; sourceTree = "<group>"; };
|
||||
BF0C82C381FCBCF8109735AC /* pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = pl; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C82D44C2DFAA5D8F60394 /* sq */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sq; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
@@ -360,6 +364,7 @@
|
||||
BF0C864F182B6155A66D241D /* KeyRepeatTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyRepeatTimer.swift; sourceTree = "<group>"; };
|
||||
BF0C86C2BB70A8E05D2103CA /* cs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = cs; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C86E06A44AC151FEA4903 /* sv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sv; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C870C14C20C936BA4AF40 /* DockEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DockEvents.swift; sourceTree = "<group>"; };
|
||||
BF0C87320241EAE01E38EF53 /* .periphery.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.yaml; path = .periphery.yml; sourceTree = "<group>"; };
|
||||
BF0C87897C24638DDE4A9889 /* app-icons-style.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "app-icons-style.jpg"; sourceTree = "<group>"; };
|
||||
BF0C87B913292EE53EDE4220 /* menubar-1.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = "menubar-1.svg"; sourceTree = "<group>"; };
|
||||
@@ -411,6 +416,7 @@
|
||||
BF0C8D7DE89E594FEE6DA692 /* ta */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ta; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C8D87C20B7308B16498B6 /* et */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = et; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C8D9E024876AD9A92BE8D /* sr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sr; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C8DF008F1EB5F23291A13 /* SpacesEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpacesEvents.swift; sourceTree = "<group>"; };
|
||||
BF0C8DF400A1AF64EB0CD0B3 /* TrafficLightButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrafficLightButton.swift; sourceTree = "<group>"; };
|
||||
BF0C8E1FBCBC7B64C69D933C /* titles-style-full.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "titles-style-full.jpg"; sourceTree = "<group>"; };
|
||||
BF0C8E25373671B528AD448D /* screen-recording@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "screen-recording@2x.png"; sourceTree = "<group>"; };
|
||||
@@ -509,7 +515,7 @@
|
||||
D04BA72AC9B57A1673C28B2E /* android-chrome-256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "android-chrome-256x256.png"; sourceTree = "<group>"; };
|
||||
D04BA7457E30F608E139B695 /* zh-TW */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
D04BA765138B5E1C512245BE /* Thanks.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Thanks.md; sourceTree = "<group>"; };
|
||||
D04BA76AEE37D6656EB80126 /* WorkspaceEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkspaceEvents.swift; sourceTree = "<group>"; };
|
||||
D04BA76AEE37D6656EB80126 /* RunningApplicationsEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RunningApplicationsEvents.swift; sourceTree = "<group>"; };
|
||||
D04BA788228BA86D9EFBD1ED /* AcknowledgmentsTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AcknowledgmentsTab.swift; sourceTree = "<group>"; };
|
||||
D04BA7957E5E02FB09BCE10C /* de */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = de; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
D04BA7A758026814667273DC /* convert_iconset_to_icns.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = convert_iconset_to_icns.sh; sourceTree = "<group>"; };
|
||||
@@ -1171,7 +1177,7 @@
|
||||
D04BA1C271F0DA573345B860 /* permission-window */,
|
||||
D04BAAF79737A0673502FEB5 /* AppCenterApplication.h */,
|
||||
D04BA48BC82D3060C3A1AB11 /* AppCenterApplication.m */,
|
||||
1C96110EB5B28C814DA35465 /* LogManager.swift */,
|
||||
1C96110EB5B28C814DA35465 /* Logger.swift */,
|
||||
);
|
||||
path = ui;
|
||||
sourceTree = "<group>";
|
||||
@@ -1643,9 +1649,12 @@
|
||||
children = (
|
||||
D04BA8FDCF137D892114F5F3 /* AccessibilityEvents.swift */,
|
||||
D04BA4A621A8A15660F973C1 /* KeyboardEvents.swift */,
|
||||
D04BA76AEE37D6656EB80126 /* WorkspaceEvents.swift */,
|
||||
D04BA76AEE37D6656EB80126 /* RunningApplicationsEvents.swift */,
|
||||
D04BA5D9B4EBEB9E4333AE39 /* UserDefaultsEvents.swift */,
|
||||
D04BAF320F4D43F0DDFE063E /* MouseEvents.swift */,
|
||||
BF0C870C14C20C936BA4AF40 /* DockEvents.swift */,
|
||||
BF0C8DF008F1EB5F23291A13 /* SpacesEvents.swift */,
|
||||
BF0C822D3BEDAB1F1C9F775E /* ScreensEvents.swift */,
|
||||
);
|
||||
path = events;
|
||||
sourceTree = "<group>";
|
||||
@@ -2102,7 +2111,7 @@
|
||||
5F21C9E02C6E94240091F72F /* ShortcutsWhenActiveSheet.swift in Sources */,
|
||||
D04BAE8B16A06A10E2FA94DE /* AccessibilityEvents.swift in Sources */,
|
||||
D04BAAAF5CFA991D3B078DB8 /* KeyboardEvents.swift in Sources */,
|
||||
D04BA1766FBCB2E941D081A5 /* WorkspaceEvents.swift in Sources */,
|
||||
D04BA1766FBCB2E941D081A5 /* RunningApplicationsEvents.swift in Sources */,
|
||||
D04BA0AE9865276FF8EF5DEB /* UserDefaultsEvents.swift in Sources */,
|
||||
D04BA4A11F821548EE3C5E95 /* Bash.swift in Sources */,
|
||||
5F21C9E62C6E94920091F72F /* AnimationsSheet.swift in Sources */,
|
||||
@@ -2126,8 +2135,11 @@
|
||||
BF0C83578F7292F307E30751 /* PopupButtonLikeSystemSettings.swift in Sources */,
|
||||
1C961F9CF4F1BEDF04ACAEE0 /* Switch.swift in Sources */,
|
||||
1C96182D2ECA735740ED474E /* ImageTextButtonView.swift in Sources */,
|
||||
1C96143D5AD69C894A4D8375 /* LogManager.swift in Sources */,
|
||||
1C96143D5AD69C894A4D8375 /* Logger.swift in Sources */,
|
||||
BF0C860F1779DDE8C0171EA0 /* WindowlessAppIndicator.swift in Sources */,
|
||||
BF0C8A3F32B2177AF407DC7E /* DockEvents.swift in Sources */,
|
||||
BF0C80484AA63306D0DB4DB2 /* SpacesEvents.swift in Sources */,
|
||||
BF0C8203D0EFEDEED0F908E8 /* ScreensEvents.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -55,6 +55,12 @@
|
||||
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||
referenceType = "1">
|
||||
</LocationScenarioReference>
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "--logs=info"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Debug"
|
||||
|
||||
@@ -2,8 +2,6 @@ import Foundation
|
||||
|
||||
class MissionControl {
|
||||
private static var state_ = MissionControlState.inactive
|
||||
private static var axObserver: AXObserver?
|
||||
private static var axUiElement: AXUIElement?
|
||||
|
||||
static func state() -> MissionControlState {
|
||||
if #available(macOS 12.0, *) {
|
||||
@@ -32,29 +30,4 @@ class MissionControl {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static func observe(_ dockPid: pid_t) {
|
||||
if #available(macOS 12.0, *) {
|
||||
axUiElement = AXUIElementCreateApplication(dockPid)
|
||||
AXObserverCreate(dockPid, axObserverCallbackDock, &axObserver)
|
||||
// are we sure we always get a non-nil axObserver?
|
||||
for notification in MissionControlState.allCases {
|
||||
retryAxCallUntilTimeout {
|
||||
try axUiElement!.subscribeToNotification(axObserver!, notification.rawValue, nil)
|
||||
}
|
||||
}
|
||||
CFRunLoopAddSource(BackgroundWork.missionControlThread.runLoop, AXObserverGetRunLoopSource(axObserver!), .defaultMode)
|
||||
} else {
|
||||
// we could handle macOS < 12 here like yabai does. However, they poll with ax calls until they notice Mission Control stops
|
||||
// this takes up ressources when Mission Control is open. If the user keeps it open for a few hours, this would accelerate battery usage
|
||||
// SLSRegisterConnectionNotifyProc(g_connection, connection_handler, 1204, NULL);
|
||||
// then listen every 0.1f * NSEC_PER_SEC for layer == 18 and owner = "Dock"
|
||||
// when found, mission control is not active anymore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let axObserverCallbackDock: AXObserverCallback = { _, element, notificationName, _ in
|
||||
logger.d(notificationName, element)
|
||||
MissionControl.setState(MissionControlState(rawValue: notificationName as String)!)
|
||||
}
|
||||
@@ -40,7 +40,7 @@ class Application: NSObject {
|
||||
}
|
||||
|
||||
deinit {
|
||||
logger.i("Deinit app", runningApplication.bundleIdentifier ?? runningApplication.bundleURL ?? "nil")
|
||||
logger.d("Deinit app", runningApplication.bundleIdentifier ?? runningApplication.bundleURL ?? "nil")
|
||||
}
|
||||
|
||||
override var description: String {
|
||||
@@ -73,7 +73,7 @@ class Application: NSObject {
|
||||
if runningApplication.activationPolicy != .prohibited && axUiElement == nil {
|
||||
axUiElement = AXUIElementCreateApplication(pid)
|
||||
AXObserverCreate(pid, axObserverCallback, &axObserver)
|
||||
logger.i("Adding app", pid ?? "nil", runningApplication.bundleIdentifier ?? "nil")
|
||||
logger.d("Adding app", pid ?? "nil", runningApplication.bundleIdentifier ?? "nil")
|
||||
observeEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class Applications {
|
||||
static func initialDiscovery() {
|
||||
addInitialRunningApplications()
|
||||
addInitialRunningApplicationsWindows()
|
||||
WorkspaceEvents.observeRunningApplications()
|
||||
RunningApplicationsEvents.observe()
|
||||
}
|
||||
|
||||
static func addInitialRunningApplications() {
|
||||
@@ -48,7 +48,7 @@ class Applications {
|
||||
static func addRunningApplications(_ runningApps: [NSRunningApplication]) {
|
||||
runningApps.forEach {
|
||||
if $0.bundleIdentifier == "com.apple.dock" {
|
||||
MissionControl.observe($0.processIdentifier)
|
||||
DockEvents.observe($0.processIdentifier)
|
||||
}
|
||||
if isActualApplication($0) {
|
||||
Applications.list.append(Application($0))
|
||||
@@ -68,7 +68,7 @@ class Applications {
|
||||
}
|
||||
Windows.list.removeAll { $0.application.runningApplication.isEqual(runningApp) }
|
||||
}
|
||||
guard Windows.list.count > 0 else { App.app.hideUi(); return }
|
||||
if Windows.list.count == 0 { App.app.hideUi(); return }
|
||||
if windowsOnTheLeftOfFocusedWindow > 0 {
|
||||
Windows.cycleFocusedWindowIndex(-windowsOnTheLeftOfFocusedWindow)
|
||||
}
|
||||
|
||||
+2
-22
@@ -7,25 +7,6 @@ class Spaces {
|
||||
static var screenSpacesMap = [ScreenUuid: [CGSSpaceID]]()
|
||||
static var idsAndIndexes = [(CGSSpaceID, SpaceIndex)]()
|
||||
|
||||
static func observeSpaceChanges() {
|
||||
NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.activeSpaceDidChangeNotification, object: nil, queue: nil, using: { _ in
|
||||
logger.i("OS event", "activeSpaceDidChangeNotification")
|
||||
refreshAllIdsAndIndexes()
|
||||
updateCurrentSpace()
|
||||
// if UI was kept open during Space transition, the Spaces may be obsolete; we refresh them
|
||||
Windows.list.forEachAsync { $0.updatesWindowSpace() }
|
||||
// from macos 12.2 beta onwards, we can't get other-space windows; grabbing windows when switching spaces mitigates the issue
|
||||
// also, updating windows on Space transition works around an issue with Safari where its fullscreen windows spawn not in fullscreen.
|
||||
// resize/move events happen and the window is still not fullscreen. AltTab doesn't get informed that the window is later fullscreen.
|
||||
// updating on Space change helps correct the window to being fullscreen
|
||||
Applications.manuallyUpdateWindows()
|
||||
})
|
||||
NSWorkspace.shared.notificationCenter.addObserver(forName: NSApplication.didChangeScreenParametersNotification, object: nil, queue: nil, using: { _ in
|
||||
logger.i("OS event", "didChangeScreenParametersNotification")
|
||||
refreshAllIdsAndIndexes()
|
||||
})
|
||||
}
|
||||
|
||||
static func refreshCurrentSpaceId() {
|
||||
// it seems that in some rare scenarios, some of these values are nil; we wrap to avoid crashing
|
||||
if let mainScreen = NSScreen.main,
|
||||
@@ -34,10 +15,9 @@ class Spaces {
|
||||
}
|
||||
}
|
||||
|
||||
static func initialDiscovery() {
|
||||
static func initialize() {
|
||||
refreshAllIdsAndIndexes()
|
||||
updateCurrentSpace()
|
||||
observeSpaceChanges()
|
||||
}
|
||||
|
||||
static func updateCurrentSpace() {
|
||||
@@ -45,7 +25,7 @@ class Spaces {
|
||||
currentSpaceIndex = idsAndIndexes.first { (spaceId: CGSSpaceID, _) -> Bool in
|
||||
spaceId == currentSpaceId
|
||||
}?.1 ?? SpaceIndex(1)
|
||||
logger.i("Current Space", currentSpaceId)
|
||||
logger.i(currentSpaceIndex, currentSpaceId)
|
||||
}
|
||||
|
||||
static func refreshAllIdsAndIndexes() -> Void {
|
||||
|
||||
@@ -54,7 +54,7 @@ class Window: CustomStringConvertible {
|
||||
}
|
||||
application.removeWindowslessAppWindow()
|
||||
checkIfFocused(application, wid)
|
||||
logger.i("Adding window", cgWindowId ?? "nil", title ?? "nil", application.runningApplication.bundleIdentifier ?? "nil")
|
||||
logger.d("Adding window", cgWindowId ?? "nil", title ?? "nil", application.runningApplication.bundleIdentifier ?? "nil")
|
||||
observeEvents()
|
||||
}
|
||||
|
||||
@@ -64,11 +64,11 @@ class Window: CustomStringConvertible {
|
||||
self.title = application.runningApplication.localizedName
|
||||
Window.globalCreationCounter += 1
|
||||
self.creationOrder = Window.globalCreationCounter
|
||||
logger.i("Adding app-window", title ?? "nil", application.runningApplication.bundleIdentifier ?? "nil")
|
||||
logger.d(title ?? "nil", application.runningApplication.bundleIdentifier ?? "nil")
|
||||
}
|
||||
|
||||
deinit {
|
||||
logger.i("Deinit window", title ?? "nil", application.runningApplication.bundleIdentifier ?? "nil")
|
||||
logger.d(title ?? "nil", application.runningApplication.bundleIdentifier ?? "nil")
|
||||
}
|
||||
|
||||
var description: String {
|
||||
|
||||
@@ -8,10 +8,10 @@ let axObserverCallback: AXObserverCallback = { _, element, notificationName, _ i
|
||||
}
|
||||
|
||||
fileprivate func handleEvent(_ type: String, _ element: AXUIElement) throws {
|
||||
logger.i("Accessibility event", type, try element.title() ?? "nil")
|
||||
// events are handled concurrently, thus we check that the app is still running
|
||||
if let pid = try element.pid(),
|
||||
try pid != ProcessInfo.processInfo.processIdentifier || (element.subrole() != kAXUnknownSubrole) {
|
||||
logger.d(type, pid, try element.title() ?? "nil")
|
||||
switch type {
|
||||
case kAXApplicationActivatedNotification: try applicationActivated(element, pid)
|
||||
case kAXApplicationHiddenNotification,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import Foundation
|
||||
|
||||
class DockEvents {
|
||||
private static var axObserver: AXObserver?
|
||||
private static var axUiElement: AXUIElement?
|
||||
|
||||
static func observe(_ dockPid: pid_t) {
|
||||
if #available(macOS 12.0, *) {
|
||||
axUiElement = AXUIElementCreateApplication(dockPid)
|
||||
AXObserverCreate(dockPid, handleEvent, &axObserver)
|
||||
// are we sure we always get a non-nil axObserver?
|
||||
for notification in MissionControlState.allCases {
|
||||
retryAxCallUntilTimeout {
|
||||
try axUiElement!.subscribeToNotification(axObserver!, notification.rawValue, nil)
|
||||
}
|
||||
}
|
||||
CFRunLoopAddSource(BackgroundWork.missionControlThread.runLoop, AXObserverGetRunLoopSource(axObserver!), .defaultMode)
|
||||
} else {
|
||||
// we could handle macOS < 12 here like yabai does. However, they poll with ax calls until they notice Mission Control stops
|
||||
// this takes up ressources when Mission Control is open. If the user keeps it open for a few hours, this would accelerate battery usage
|
||||
// SLSRegisterConnectionNotifyProc(g_connection, connection_handler, 1204, NULL);
|
||||
// then listen every 0.1f * NSEC_PER_SEC for layer == 18 and owner = "Dock"
|
||||
// when found, mission control is not active anymore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let handleEvent: AXObserverCallback = { _, element, notificationName, _ in
|
||||
logger.d(notificationName, element)
|
||||
MissionControl.setState(MissionControlState(rawValue: notificationName as String)!)
|
||||
}
|
||||
@@ -26,7 +26,7 @@ private func observe_() {
|
||||
place: .headInsertEventTap,
|
||||
options: .defaultTap,
|
||||
eventsOfInterest: eventMask,
|
||||
callback: mouseHandler,
|
||||
callback: handleEvent,
|
||||
userInfo: nil)
|
||||
if let eventTap = eventTap {
|
||||
MouseEvents.toggle(false)
|
||||
@@ -37,7 +37,7 @@ private func observe_() {
|
||||
}
|
||||
}
|
||||
|
||||
private let mouseHandler: CGEventTapCallBack = {_, type, cgEvent, _ in
|
||||
private let handleEvent: CGEventTapCallBack = { _, type, cgEvent, _ in
|
||||
if type == .leftMouseDown {
|
||||
isPointerInsideUi_()
|
||||
if !isPointerInsideUi {
|
||||
|
||||
+5
-6
@@ -1,23 +1,22 @@
|
||||
import Cocoa
|
||||
|
||||
class WorkspaceEvents {
|
||||
class RunningApplicationsEvents {
|
||||
private static var appsObserver: NSKeyValueObservation!
|
||||
private static var previousValueOfRunningApps: Set<NSRunningApplication>!
|
||||
|
||||
static func observeRunningApplications() {
|
||||
static func observe() {
|
||||
previousValueOfRunningApps = Set(NSWorkspace.shared.runningApplications)
|
||||
appsObserver = NSWorkspace.shared.observe(\.runningApplications, options: [.old, .new], changeHandler: observerCallback)
|
||||
appsObserver = NSWorkspace.shared.observe(\.runningApplications, options: [.old, .new], changeHandler: handleEvent)
|
||||
}
|
||||
|
||||
static func observerCallback<A>(_: NSWorkspace, _ change: NSKeyValueObservedChange<A>) {
|
||||
static func handleEvent<A>(_: NSWorkspace, _ change: NSKeyValueObservedChange<A>) {
|
||||
let workspaceApps = Set(NSWorkspace.shared.runningApplications)
|
||||
// TODO: symmetricDifference has bad performance
|
||||
let diff = Array(workspaceApps.symmetricDifference(previousValueOfRunningApps))
|
||||
logger.d(change.kind, diff.map { ($0.processIdentifier, $0.bundleIdentifier) })
|
||||
if change.kind == .insertion {
|
||||
logger.i("OS event", "apps launched", diff.map { ($0.processIdentifier, $0.bundleIdentifier) })
|
||||
Applications.addRunningApplications(diff)
|
||||
} else if change.kind == .removal {
|
||||
logger.i("OS event", "apps quit", diff.map { ($0.processIdentifier, $0.bundleIdentifier) })
|
||||
Applications.removeRunningApplications(diff)
|
||||
}
|
||||
previousValueOfRunningApps = workspaceApps
|
||||
@@ -0,0 +1,10 @@
|
||||
import Cocoa
|
||||
|
||||
class ScreensEvents {
|
||||
static func observe() {
|
||||
NSWorkspace.shared.notificationCenter.addObserver(forName: NSApplication.didChangeScreenParametersNotification, object: nil, queue: nil, using: { notification in
|
||||
logger.i(notification.name, NSScreen.screens.map { ($0.uuid(), $0.frame) })
|
||||
Spaces.refreshAllIdsAndIndexes()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import Cocoa
|
||||
|
||||
class SpacesEvents {
|
||||
static func observe() {
|
||||
NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.activeSpaceDidChangeNotification, object: nil, queue: nil, using: { notification in
|
||||
logger.d(notification.name)
|
||||
Spaces.refreshAllIdsAndIndexes()
|
||||
Spaces.updateCurrentSpace()
|
||||
// if UI was kept open during Space transition, the Spaces may be obsolete; we refresh them
|
||||
Windows.list.forEachAsync { $0.updatesWindowSpace() }
|
||||
// from macos 12.2 beta onwards, we can't get other-space windows; grabbing windows when switching spaces mitigates the issue
|
||||
// also, updating windows on Space transition works around an issue with Safari where its fullscreen windows spawn not in fullscreen.
|
||||
// resize/move events happen and the window is still not fullscreen. AltTab doesn't get informed that the window is later fullscreen.
|
||||
// updating on Space change helps correct the window to being fullscreen
|
||||
Applications.manuallyUpdateWindows()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,11 @@ class UserDefaultsEvents: NSObject {
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
|
||||
handleEvent(keyPath)
|
||||
}
|
||||
|
||||
private func handleEvent(_ keyPath: String?) {
|
||||
logger.d(keyPath, PoliciesTab.policyLock, Preferences.updatePolicy)
|
||||
guard !PoliciesTab.policyLock else { return }
|
||||
let buttons = PoliciesTab.updatesPolicyDropdown!
|
||||
let id = buttonIdToUpdate()
|
||||
|
||||
+9
-5
@@ -50,7 +50,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
appCenterDelegate = AppCenterCrash()
|
||||
App.shared.disableRelaunchOnLogin()
|
||||
LogManager.setup()
|
||||
Logger.initialize()
|
||||
#if DEBUG
|
||||
UserDefaults.standard.set(true, forKey: "NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints")
|
||||
#endif
|
||||
@@ -69,7 +69,9 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
self.loadMainMenuXib()
|
||||
self.thumbnailsPanel = ThumbnailsPanel()
|
||||
self.previewPanel = PreviewPanel()
|
||||
Spaces.initialDiscovery()
|
||||
Spaces.initialize()
|
||||
SpacesEvents.observe()
|
||||
ScreensEvents.observe()
|
||||
Applications.initialDiscovery()
|
||||
self.preferencesWindow = PreferencesWindow()
|
||||
self.feedbackWindow = FeedbackWindow()
|
||||
@@ -122,7 +124,8 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
}
|
||||
|
||||
func hideUi(_ keepPreview: Bool = false) {
|
||||
logger.i("hideUi")
|
||||
logger.i()
|
||||
if appIsBeingUsed == false { return } // already hidden
|
||||
appIsBeingUsed = false
|
||||
isFirstSummon = true
|
||||
MouseEvents.toggle(false)
|
||||
@@ -171,8 +174,9 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
}
|
||||
|
||||
func focusTarget() {
|
||||
logger.i("focusTarget")
|
||||
focusSelectedWindow(Windows.focusedWindow())
|
||||
let focusedWindow = Windows.focusedWindow()
|
||||
logger.i(focusedWindow ?? "nil")
|
||||
focusSelectedWindow(focusedWindow)
|
||||
}
|
||||
|
||||
@objc func checkForUpdatesNow(_ sender: NSMenuItem) {
|
||||
|
||||
@@ -3,68 +3,38 @@ import Foundation
|
||||
|
||||
let logger = SwiftyBeaver.self
|
||||
|
||||
class LogManager {
|
||||
private static let maxDays = 1 // Set maximum log retention days
|
||||
private static var timer: Timer?
|
||||
class Logger {
|
||||
static let flag = "--logs="
|
||||
|
||||
static func setup() {
|
||||
setupLogger()
|
||||
if ((logger.destinations.first { $0 is FileDestination } as? FileDestination)?.logFileURL != nil) {
|
||||
startLogFileCleanupTimer()
|
||||
}
|
||||
}
|
||||
|
||||
private static func setupLogger() {
|
||||
let format = "$Dyyyy-MM-dd HH:mm:ss.SSS$d $C$L$c $N.swift:$l $F - $M"
|
||||
static func initialize() {
|
||||
let console = ConsoleDestination()
|
||||
console.format = format
|
||||
let file = FileDestination()
|
||||
file.format = format
|
||||
|
||||
#if DEBUG
|
||||
console.minLevel = .verbose
|
||||
file.minLevel = .verbose
|
||||
console.useTerminalColors = true
|
||||
console.levelString.verbose = "VERB"
|
||||
console.levelString.debug = "DEBG"
|
||||
console.levelString.info = "INFO"
|
||||
console.levelString.warning = "WARN"
|
||||
console.levelString.error = "ERRO"
|
||||
console.format = "$C$DHH:mm:ss$d $L$c $N.swift:$l $F $M"
|
||||
console.minLevel = decideLevel()
|
||||
logger.addDestination(console)
|
||||
logger.addDestination(file)
|
||||
#else
|
||||
console.minLevel = .error
|
||||
file.minLevel = .error
|
||||
// logger.addDestination(console)
|
||||
// logger.addDestination(file)
|
||||
#endif
|
||||
|
||||
if let logFileURL = file.logFileURL {
|
||||
logger.info("Default log file path: \(logFileURL.path)")
|
||||
}
|
||||
}
|
||||
|
||||
private static func startLogFileCleanupTimer() {
|
||||
// Schedule a timer to run every 24 hours to clean up log files
|
||||
timer = Timer.scheduledTimer(timeInterval: 86400, target: self, selector: #selector(cleanupLogFiles), userInfo: nil, repeats: true)
|
||||
// Set tolerance to save battery
|
||||
timer?.tolerance = 3600
|
||||
}
|
||||
|
||||
@objc private static func cleanupLogFiles() {
|
||||
guard let fileDestination = logger.destinations.first(where: { $0 is FileDestination }) as? FileDestination,
|
||||
let logFileURL = fileDestination.logFileURL else { return }
|
||||
|
||||
let fileManager = FileManager.default
|
||||
// Get the file attributes to check the creation date
|
||||
if let attributes = try? fileManager.attributesOfItem(atPath: logFileURL.path),
|
||||
let creationDate = attributes[.creationDate] as? Date {
|
||||
// Calculate the expiration date
|
||||
let expirationDate = Calendar.current.date(byAdding: .day, value: -maxDays, to: Date())
|
||||
// If the log file is older than the specified retention period, delete it
|
||||
if creationDate < expirationDate ?? Date() {
|
||||
fileDestination.deleteLogFile()
|
||||
static func decideLevel() -> SwiftyBeaver.Level {
|
||||
if let level = CommandLine.arguments.first { $0.starts(with: flag) }?.substring(from: flag.endIndex) {
|
||||
switch level {
|
||||
case "verbose": return .verbose
|
||||
case "debug": return .debug
|
||||
case "info": return .info
|
||||
case "warning": return .warning
|
||||
case "error": return .error
|
||||
default: break
|
||||
}
|
||||
}
|
||||
return .error
|
||||
}
|
||||
}
|
||||
|
||||
extension SwiftyBeaver {
|
||||
|
||||
class func isVerboseEnabled() -> Bool {
|
||||
return isEnabled(level: .verbose)
|
||||
}
|
||||
@@ -25,7 +25,7 @@ class PermissionsWindow: NSWindow, NSWindowDelegate {
|
||||
|
||||
|
||||
func windowWillClose(_ notification: Notification) {
|
||||
logger.d("PermissionsWindow windowWillClose", SystemPermissions.preStartupPermissionsPassed)
|
||||
logger.d(SystemPermissions.preStartupPermissionsPassed)
|
||||
if !SystemPermissions.preStartupPermissionsPassed {
|
||||
if SystemPermissions.accessibilityIsGranted() == .notGranted || SystemPermissions.screenRecordingIsGranted() == .notGranted {
|
||||
logger.e("Before using this app, you need to give permission in System Preferences > Security & Privacy > Privacy > Accessibility.",
|
||||
|
||||
Reference in new issue
Block a user