From 3d0bfa456da555cf9cea320321bfb1b0a418375d Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Thu, 14 Nov 2024 17:00:19 +0100 Subject: [PATCH] fix: moved DispatchSource.MemoryPressureEvent to custom RAMPressure enum. Fixed the crashes on some macs (#2212) --- Kit/Widgets/BarChart.swift | 6 +++--- Kit/Widgets/LineChart.swift | 6 +++--- Kit/Widgets/Memory.swift | 4 ++-- Kit/Widgets/Mini.swift | 6 +++--- Kit/Widgets/Text.swift | 3 +-- Kit/types.swift | 17 +++++++++++++++++ Modules/RAM/main.swift | 25 +++++++++++++------------ Modules/RAM/notifications.swift | 2 +- Modules/RAM/popup.swift | 13 ++++++------- Modules/RAM/portal.swift | 4 ++-- Modules/RAM/readers.swift | 12 +++++++++--- Modules/RAM/widget.swift | 6 +++--- Stats/Supporting Files/Info.plist | 2 +- Widgets/Supporting Files/Info.plist | 2 +- 14 files changed, 65 insertions(+), 43 deletions(-) diff --git a/Kit/Widgets/BarChart.swift b/Kit/Widgets/BarChart.swift index e5cdd654f60..7cdb694e5cf 100644 --- a/Kit/Widgets/BarChart.swift +++ b/Kit/Widgets/BarChart.swift @@ -19,7 +19,7 @@ public class BarChart: WidgetWrapper { private var colors: [SColor] = SColor.allCases private var _value: [[ColorValue]] = [[]] - private var _pressureLevel: DispatchSource.MemoryPressureEvent = .normal + private var _pressureLevel: RAMPressure = .normal private var _colorZones: colorZones = (0.6, 0.8) private var boxSettingsView: NSSwitch? = nil @@ -93,7 +93,7 @@ public class BarChart: WidgetWrapper { super.draw(dirtyRect) var value: [[ColorValue]] = [] - var pressureLevel: DispatchSource.MemoryPressureEvent = .normal + var pressureLevel: RAMPressure = .normal var colorZones: colorZones = (0.6, 0.8) self.queue.sync { value = self._value @@ -224,7 +224,7 @@ public class BarChart: WidgetWrapper { }) } - public func setPressure(_ newPressureLevel: DispatchSource.MemoryPressureEvent) { + public func setPressure(_ newPressureLevel: RAMPressure) { guard self._pressureLevel != newPressureLevel else { return } self._pressureLevel = newPressureLevel DispatchQueue.main.async(execute: { diff --git a/Kit/Widgets/LineChart.swift b/Kit/Widgets/LineChart.swift index aab03fdaff5..78d76d923d4 100644 --- a/Kit/Widgets/LineChart.swift +++ b/Kit/Widgets/LineChart.swift @@ -29,7 +29,7 @@ public class LineChart: WidgetWrapper { ), num: 60) private var colors: [SColor] = SColor.allCases.filter({ $0 != SColor.cluster }) private var _value: Double = 0 - private var _pressureLevel: DispatchSource.MemoryPressureEvent = .normal + private var _pressureLevel: RAMPressure = .normal private var historyNumbers: [KeyValue_p] = [ KeyValue_t(key: "30", value: "30"), @@ -129,7 +129,7 @@ public class LineChart: WidgetWrapper { guard let context = NSGraphicsContext.current?.cgContext else { return } var value: Double = 0 - var pressureLevel: DispatchSource.MemoryPressureEvent = .normal + var pressureLevel: RAMPressure = .normal self.queue.sync { value = self._value pressureLevel = self._pressureLevel @@ -249,7 +249,7 @@ public class LineChart: WidgetWrapper { }) } - public func setPressure(_ newPressureLevel: DispatchSource.MemoryPressureEvent) { + public func setPressure(_ newPressureLevel: RAMPressure) { guard self._pressureLevel != newPressureLevel else { return } self._pressureLevel = newPressureLevel DispatchQueue.main.async(execute: { diff --git a/Kit/Widgets/Memory.swift b/Kit/Widgets/Memory.swift index cd14512e738..5a04f949b45 100644 --- a/Kit/Widgets/Memory.swift +++ b/Kit/Widgets/Memory.swift @@ -15,7 +15,7 @@ public class MemoryWidget: WidgetWrapper { private var orderReversedState: Bool = false private var value: (String, String) = ("0", "0") private var percentage: Double = 0 - private var pressureLevel: DispatchSource.MemoryPressureEvent = .normal + private var pressureLevel: RAMPressure = .normal private var symbolsState: Bool = true private var colorState: SColor = .monochrome @@ -137,7 +137,7 @@ public class MemoryWidget: WidgetWrapper { }) } - public func setPressure(_ newPressureLevel: DispatchSource.MemoryPressureEvent) { + public func setPressure(_ newPressureLevel: RAMPressure) { guard self.pressureLevel != newPressureLevel else { return } self.pressureLevel = newPressureLevel DispatchQueue.main.async(execute: { diff --git a/Kit/Widgets/Mini.swift b/Kit/Widgets/Mini.swift index 3a0b9844c6f..4e384ab1635 100644 --- a/Kit/Widgets/Mini.swift +++ b/Kit/Widgets/Mini.swift @@ -19,7 +19,7 @@ public class Mini: WidgetWrapper { private var colors: [SColor] = SColor.allCases private var _value: Double = 0 - private var _pressureLevel: DispatchSource.MemoryPressureEvent = .normal + private var _pressureLevel: RAMPressure = .normal private var _colorZones: colorZones = (0.6, 0.8) private var _suffix: String = "%" @@ -93,7 +93,7 @@ public class Mini: WidgetWrapper { super.draw(dirtyRect) var value: Double = 0 - var pressureLevel: DispatchSource.MemoryPressureEvent = .normal + var pressureLevel: RAMPressure = .normal var colorZones: colorZones = (0.6, 0.8) var label: String = "" var suffix: String = "" @@ -155,7 +155,7 @@ public class Mini: WidgetWrapper { }) } - public func setPressure(_ newPressureLevel: DispatchSource.MemoryPressureEvent) { + public func setPressure(_ newPressureLevel: RAMPressure) { guard self._pressureLevel != newPressureLevel else { return } self._pressureLevel = newPressureLevel DispatchQueue.main.async(execute: { diff --git a/Kit/Widgets/Text.swift b/Kit/Widgets/Text.swift index f0888d9e5b3..bb661289a59 100644 --- a/Kit/Widgets/Text.swift +++ b/Kit/Widgets/Text.swift @@ -74,7 +74,7 @@ public class TextWidget: WidgetWrapper { self.display() }) } - + static public func parseText(_ raw: String) -> [KeyValue_t] { var pairs: [KeyValue_t] = [] do { @@ -97,5 +97,4 @@ public class TextWidget: WidgetWrapper { } return pairs } - } diff --git a/Kit/types.swift b/Kit/types.swift index 17aa38b9985..494427c7e78 100644 --- a/Kit/types.swift +++ b/Kit/types.swift @@ -394,3 +394,20 @@ extension SizeUnit: CaseIterable { } } } + +public enum RAMPressure: String, Codable { + case normal + case warning + case critical + + func pressureColor() -> NSColor { + switch self { + case .normal: + return NSColor.systemGreen + case .warning: + return NSColor.systemYellow + case .critical: + return NSColor.systemRed + } + } +} diff --git a/Modules/RAM/main.swift b/Modules/RAM/main.swift index aba63961898..4029cb3d7e3 100644 --- a/Modules/RAM/main.swift +++ b/Modules/RAM/main.swift @@ -26,16 +26,12 @@ public struct RAM_Usage: Codable { var app: Double var cache: Double - var rawPressureLevel: UInt var swap: Swap + var pressure: Pressure public var usage: Double { get { Double((self.total - self.free) / self.total) } } - - public var pressureLevel: DispatchSource.MemoryPressureEvent { - DispatchSource.MemoryPressureEvent(rawValue: self.rawPressureLevel) - } } public struct Swap: Codable { @@ -44,6 +40,11 @@ public struct Swap: Codable { var free: Double } +public struct Pressure: Codable { + let level: Int + let value: RAMPressure +} + public class RAM: Module { private let popupView: Popup private let settingsView: Settings @@ -141,10 +142,10 @@ public class RAM: Module { switch w.item { case let widget as Mini: widget.setValue(value.usage) - widget.setPressure(value.pressureLevel) + widget.setPressure(value.pressure.value) case let widget as LineChart: widget.setValue(value.usage) - widget.setPressure(value.pressureLevel) + widget.setPressure(value.pressure.value) case let widget as BarChart: if self.splitValueState { widget.setValue([[ @@ -155,7 +156,7 @@ public class RAM: Module { } else { widget.setValue([[ColorValue(value.usage)]]) widget.setColorZones((0.8, 0.95)) - widget.setPressure(value.pressureLevel) + widget.setPressure(value.pressure.value) } case let widget as PieChart: widget.setValue([ @@ -167,7 +168,7 @@ public class RAM: Module { let free = Units(bytes: Int64(value.free)).getReadableMemory() let used = Units(bytes: Int64(value.used)).getReadableMemory() widget.setValue((free, used), usedPercentage: value.usage) - widget.setPressure(value.pressureLevel) + widget.setPressure(value.pressure.value) case let widget as Tachometer: widget.setValue([ circle_segment(value: value.app/total, color: self.appColor), @@ -175,7 +176,7 @@ public class RAM: Module { circle_segment(value: value.compressed/total, color: self.compressedColor) ]) case let widget as TextWidget: - var text = self.textValue + var text = "\(self.textValue)" let pairs = TextWidget.parseText(text) pairs.forEach { pair in var replacement: String? = nil @@ -203,8 +204,8 @@ public class RAM: Module { } case "$pressure": switch pair.value { - case "value": replacement = value.pressureLevel.description - case "level": replacement = value.rawPressureLevel.description + case "level": replacement = "\(value.pressure.level)" + case "value": replacement = value.pressure.value.rawValue default: return } default: return diff --git a/Modules/RAM/notifications.swift b/Modules/RAM/notifications.swift index dbe30e90a85..6069a71f17f 100644 --- a/Modules/RAM/notifications.swift +++ b/Modules/RAM/notifications.swift @@ -127,7 +127,7 @@ class Notifications: NotificationsWrapper { if let threshold = thresholdPair.additional as? DispatchSource.MemoryPressureEvent { self.checkDouble( id: self.pressureID, - value: Double(value.pressureLevel.rawValue), + value: Double(value.pressure.level), threshold: Double(threshold.rawValue), title: title, subtitle: "\(localizedString("Memory pressure")): \(localizedString(thresholdPair.value))" diff --git a/Modules/RAM/popup.swift b/Modules/RAM/popup.swift index 182e8c6634d..96d5e7a4760 100644 --- a/Modules/RAM/popup.swift +++ b/Modules/RAM/popup.swift @@ -257,7 +257,7 @@ internal class Popup: PopupWrapper { circle_segment(value: value.compressed/value.total, color: self.compressedColor) ]) self.circle?.setNonActiveSegmentColor(self.freeColor) - self.level?.setLevel(value.pressureLevel) + self.level?.setValue(value.pressure) self.initialized = true } @@ -429,7 +429,7 @@ public class PressureView: NSView { circle_segment(value: 1/3, color: NSColor.systemRed) ] - private var level: DispatchSource.MemoryPressureEvent = .normal + private var value: Pressure = Pressure(level: 1, value: .normal) public override func draw(_ rect: CGRect) { let arcWidth: CGFloat = 7.0 @@ -465,7 +465,7 @@ public class PressureView: NSView { let needleEndSize: CGFloat = 2 let needlePath = NSBezierPath() - switch self.level { + switch self.value.value { case .normal: needlePath.move(to: CGPoint(x: self.bounds.width * 0.15, y: self.bounds.width * 0.40)) needlePath.line(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 - needleEndSize)) @@ -478,7 +478,6 @@ public class PressureView: NSView { needlePath.move(to: CGPoint(x: self.bounds.width * 0.85, y: self.bounds.width * 0.40)) needlePath.line(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 - needleEndSize)) needlePath.line(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 + needleEndSize)) - default: break } needlePath.close() @@ -501,12 +500,12 @@ public class PressureView: NSView { ] let rect = CGRect(x: (self.frame.width-6)/2, y: (self.frame.height-26)/2, width: 6, height: 12) - let str = NSAttributedString.init(string: "\(self.level.rawValue)", attributes: stringAttributes) + let str = NSAttributedString.init(string: "\(self.value.level)", attributes: stringAttributes) str.draw(with: rect) } - public func setLevel(_ level: DispatchSource.MemoryPressureEvent) { - self.level = level + public func setValue(_ newValue: Pressure) { + self.value = newValue if self.window?.isVisible ?? true { self.display() } diff --git a/Modules/RAM/portal.swift b/Modules/RAM/portal.swift index 6acd7c440f3..cc2c202cbef 100644 --- a/Modules/RAM/portal.swift +++ b/Modules/RAM/portal.swift @@ -103,11 +103,11 @@ public class Portal: PortalWrapper { self.usedField?.stringValue = Units(bytes: Int64(value.used)).getReadableMemory() self.freeField?.stringValue = Units(bytes: Int64(value.free)).getReadableMemory() self.swapField?.stringValue = Units(bytes: Int64(value.swap.used)).getReadableMemory() - self.pressureLevelField?.stringValue = "\(value.pressureLevel.rawValue)" + self.pressureLevelField?.stringValue = value.pressure.value.rawValue self.usedField?.toolTip = "\(Int(value.usage.rounded(toPlaces: 2) * 100))%" self.freeField?.toolTip = "\(Int((1-value.usage).rounded(toPlaces: 2) * 100))%" - if let level = memoryPressureLevels.first(where: { $0.additional as? DispatchSource.MemoryPressureEvent == value.pressureLevel }) { + if let level = memoryPressureLevels.first(where: { $0.additional as? RAMPressure == value.pressure.value }) { self.pressureLevelField?.toolTip = localizedString(level.value) } diff --git a/Modules/RAM/readers.swift b/Modules/RAM/readers.swift index ab34f32187c..095b70b2013 100644 --- a/Modules/RAM/readers.swift +++ b/Modules/RAM/readers.swift @@ -60,6 +60,13 @@ internal class UsageReader: Reader { var pressureLevel: Int = 0 sysctlbyname("kern.memorystatus_vm_pressure_level", &pressureLevel, &intSize, nil, 0) + var pressureValue: RAMPressure + switch pressureLevel { + case 2: pressureValue = .warning + case 4: pressureValue = .critical + default: pressureValue = .normal + } + var stringSize: size_t = MemoryLayout.size var swap: xsw_usage = xsw_usage() sysctlbyname("vm.swapusage", &swap, &stringSize, nil, 0) @@ -77,13 +84,12 @@ internal class UsageReader: Reader { app: used - wired - compressed, cache: purgeable + external, - rawPressureLevel: UInt(pressureLevel), - swap: Swap( total: Double(swap.xsu_total), used: Double(swap.xsu_used), free: Double(swap.xsu_avail) - ) + ), + pressure: Pressure(level: pressureLevel, value: pressureValue) )) return } diff --git a/Modules/RAM/widget.swift b/Modules/RAM/widget.swift index 02ebbd78f2b..7e6aa60a65e 100644 --- a/Modules/RAM/widget.swift +++ b/Modules/RAM/widget.swift @@ -27,8 +27,8 @@ public struct RAM_entry: TimelineEntry { compressed: 414629888.0, app: 16369778688.0, cache: 12575948800.0, - rawPressureLevel: 1, - swap: Swap(total: 0, used: 0, free: 0) + swap: Swap(total: 0, used: 0, free: 0), + pressure: Pressure(level: 1, value: .normal) ) ) @@ -110,7 +110,7 @@ public struct RAMWidget: Widget { HStack { Text(localizedString("Pressure level")).font(.system(size: 12, weight: .regular)).foregroundColor(.secondary) Spacer() - Text("\(value.rawPressureLevel)") + Text("\(value.pressure.level)") } } } else { diff --git a/Stats/Supporting Files/Info.plist b/Stats/Supporting Files/Info.plist index a0e07bc812b..d668c37d137 100755 --- a/Stats/Supporting Files/Info.plist +++ b/Stats/Supporting Files/Info.plist @@ -17,7 +17,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 610 + 632 Description Simple macOS system monitor in your menu bar LSApplicationCategoryType diff --git a/Widgets/Supporting Files/Info.plist b/Widgets/Supporting Files/Info.plist index a1cddd393b8..399eb214fae 100644 --- a/Widgets/Supporting Files/Info.plist +++ b/Widgets/Supporting Files/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 2.11.17 CFBundleVersion - 610 + 632 NSExtension NSExtensionPointIdentifier