mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-01-09 16:48:38 +00:00
Add new "cpu" widget (#415)
This commit is contained in:
parent
352bf4887c
commit
d199bbd852
@ -21,6 +21,8 @@
|
|||||||
36FEF872235A1CFC00A0ABCE /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FEF871235A1CFC00A0ABCE /* AppSettings.swift */; };
|
36FEF872235A1CFC00A0ABCE /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FEF871235A1CFC00A0ABCE /* AppSettings.swift */; };
|
||||||
4CC9FEDC22FDEA65001512EB /* AMR_ANSIEscapeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */; };
|
4CC9FEDC22FDEA65001512EB /* AMR_ANSIEscapeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */; };
|
||||||
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */; };
|
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */; };
|
||||||
|
4CF222EB26CC00470025BDA7 /* CPUBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF222EA26CC00470025BDA7 /* CPUBarItem.swift */; };
|
||||||
|
4CF222ED26CC43D50025BDA7 /* CPU.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF222EC26CC43D40025BDA7 /* CPU.swift */; };
|
||||||
4CFF5E5C22E623DD00BFB1EE /* YandexWeatherBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */; };
|
4CFF5E5C22E623DD00BFB1EE /* YandexWeatherBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */; };
|
||||||
5DC6CA02241F92CB005CD5E8 /* Music.nowPlaying.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */; };
|
5DC6CA02241F92CB005CD5E8 /* Music.nowPlaying.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */; };
|
||||||
5DC6CA03241F92CB005CD5E8 /* Music.next.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */; };
|
5DC6CA03241F92CB005CD5E8 /* Music.next.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */; };
|
||||||
@ -104,6 +106,8 @@
|
|||||||
4CC9FEDA22FDEA65001512EB /* AMR_ANSIEscapeHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMR_ANSIEscapeHelper.h; sourceTree = "<group>"; };
|
4CC9FEDA22FDEA65001512EB /* AMR_ANSIEscapeHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMR_ANSIEscapeHelper.h; sourceTree = "<group>"; };
|
||||||
4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMR_ANSIEscapeHelper.m; sourceTree = "<group>"; };
|
4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMR_ANSIEscapeHelper.m; sourceTree = "<group>"; };
|
||||||
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellScriptTouchBarItem.swift; sourceTree = "<group>"; };
|
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellScriptTouchBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
4CF222EA26CC00470025BDA7 /* CPUBarItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CPUBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
4CF222EC26CC43D40025BDA7 /* CPU.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CPU.swift; sourceTree = "<group>"; };
|
||||||
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YandexWeatherBarItem.swift; sourceTree = "<group>"; };
|
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YandexWeatherBarItem.swift; sourceTree = "<group>"; };
|
||||||
5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Music.nowPlaying.scpt; sourceTree = "<group>"; };
|
5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Music.nowPlaying.scpt; sourceTree = "<group>"; };
|
||||||
5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Music.next.scpt; sourceTree = "<group>"; };
|
5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Music.next.scpt; sourceTree = "<group>"; };
|
||||||
@ -239,6 +243,7 @@
|
|||||||
B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */,
|
B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */,
|
||||||
36FEF871235A1CFC00A0ABCE /* AppSettings.swift */,
|
36FEF871235A1CFC00A0ABCE /* AppSettings.swift */,
|
||||||
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */,
|
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */,
|
||||||
|
4CF222EC26CC43D40025BDA7 /* CPU.swift */,
|
||||||
36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */,
|
36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */,
|
||||||
BAF5AB5824317CAF00B04904 /* SwipeItem.swift */,
|
BAF5AB5824317CAF00B04904 /* SwipeItem.swift */,
|
||||||
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */,
|
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */,
|
||||||
@ -310,6 +315,7 @@
|
|||||||
6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */,
|
6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */,
|
||||||
B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */,
|
B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */,
|
||||||
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */,
|
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */,
|
||||||
|
4CF222EA26CC00470025BDA7 /* CPUBarItem.swift */,
|
||||||
607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */,
|
607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */,
|
||||||
B081732B213739FE005D4908 /* DnDBarItem.swift */,
|
B081732B213739FE005D4908 /* DnDBarItem.swift */,
|
||||||
60669B4220AD8FA80074E817 /* GroupBarItem.swift */,
|
60669B4220AD8FA80074E817 /* GroupBarItem.swift */,
|
||||||
@ -478,12 +484,14 @@
|
|||||||
B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */,
|
B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */,
|
||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
||||||
B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */,
|
B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */,
|
||||||
|
4CF222EB26CC00470025BDA7 /* CPUBarItem.swift in Sources */,
|
||||||
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
|
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
|
||||||
6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */,
|
6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */,
|
||||||
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */,
|
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */,
|
||||||
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
||||||
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */,
|
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */,
|
||||||
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
|
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
|
||||||
|
4CF222ED26CC43D50025BDA7 /* CPU.swift in Sources */,
|
||||||
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */,
|
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */,
|
||||||
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */,
|
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */,
|
||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
||||||
|
|||||||
21
MTMR/Assets.xcassets/cpu.imageset/Contents.json
vendored
Normal file
21
MTMR/Assets.xcassets/cpu.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "cpu.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
MTMR/Assets.xcassets/cpu.imageset/cpu.png
vendored
Normal file
BIN
MTMR/Assets.xcassets/cpu.imageset/cpu.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
191
MTMR/CPU.swift
Normal file
191
MTMR/CPU.swift
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
//
|
||||||
|
// CPU.swift
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by zixun on 2016/12/5.
|
||||||
|
// https://github.com/zixun/SystemEye
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
private let HOST_CPU_LOAD_INFO_COUNT : mach_msg_type_number_t =
|
||||||
|
UInt32(MemoryLayout<host_cpu_load_info_data_t>.size / MemoryLayout<integer_t>.size)
|
||||||
|
|
||||||
|
/// CPU Class
|
||||||
|
public class CPU: NSObject {
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// MARK: OPEN PROPERTY
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// /// Number of physical cores on this machine.
|
||||||
|
// public static var physicalCores: Int {
|
||||||
|
// get {
|
||||||
|
// return Int(System.hostBasicInfo.physical_cpu)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Number of logical cores on this machine. Will be equal to physicalCores
|
||||||
|
// /// unless it has hyper-threading, in which case it will be double.
|
||||||
|
// public static var logicalCores: Int {
|
||||||
|
// get {
|
||||||
|
// return Int(System.hostBasicInfo.logical_cpu)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// MARK: OPEN FUNCTIONS
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Get CPU usage of hole system (system, user, idle, nice). Determined by the delta between
|
||||||
|
/// the current and last call.
|
||||||
|
public static func systemUsage() -> (system: Double,
|
||||||
|
user: Double,
|
||||||
|
idle: Double,
|
||||||
|
nice: Double) {
|
||||||
|
let load = self.hostCPULoadInfo
|
||||||
|
|
||||||
|
let userDiff = Double(load.cpu_ticks.0 - loadPrevious.cpu_ticks.0)
|
||||||
|
let sysDiff = Double(load.cpu_ticks.1 - loadPrevious.cpu_ticks.1)
|
||||||
|
let idleDiff = Double(load.cpu_ticks.2 - loadPrevious.cpu_ticks.2)
|
||||||
|
let niceDiff = Double(load.cpu_ticks.3 - loadPrevious.cpu_ticks.3)
|
||||||
|
|
||||||
|
let totalTicks = sysDiff + userDiff + niceDiff + idleDiff
|
||||||
|
|
||||||
|
let sys = sysDiff / totalTicks * 100.0
|
||||||
|
let user = userDiff / totalTicks * 100.0
|
||||||
|
let idle = idleDiff / totalTicks * 100.0
|
||||||
|
let nice = niceDiff / totalTicks * 100.0
|
||||||
|
|
||||||
|
loadPrevious = load
|
||||||
|
|
||||||
|
return (sys, user, idle, nice)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get CPU usage of application,get from all thread
|
||||||
|
open class func applicationUsage() -> Double {
|
||||||
|
let threads = self.threadBasicInfos()
|
||||||
|
var result : Double = 0.0
|
||||||
|
threads.forEach { (thread:thread_basic_info) in
|
||||||
|
if self.flag(thread) {
|
||||||
|
result += Double.init(thread.cpu_usage) / Double.init(TH_USAGE_SCALE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// MARK: PRIVATE PROPERTY
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// previous load of cpu
|
||||||
|
private static var loadPrevious = host_cpu_load_info()
|
||||||
|
|
||||||
|
static var hostCPULoadInfo: host_cpu_load_info {
|
||||||
|
get {
|
||||||
|
var size = HOST_CPU_LOAD_INFO_COUNT
|
||||||
|
var hostInfo = host_cpu_load_info()
|
||||||
|
let result = withUnsafeMutablePointer(to: &hostInfo) {
|
||||||
|
$0.withMemoryRebound(to: integer_t.self, capacity: Int(size)) {
|
||||||
|
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if result != KERN_SUCCESS {
|
||||||
|
fatalError("ERROR - \(#file):\(#function) - kern_result_t = "
|
||||||
|
+ "\(result)")
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return hostInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// MARK: PRIVATE FUNCTION
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private class func flag(_ thread:thread_basic_info) -> Bool {
|
||||||
|
let foo = thread.flags & TH_FLAGS_IDLE
|
||||||
|
let number = NSNumber.init(value: foo)
|
||||||
|
return !Bool.init(truncating: number)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class func threadActPointers() -> [thread_act_t] {
|
||||||
|
var threads_act = [thread_act_t]()
|
||||||
|
|
||||||
|
var threads_array: thread_act_array_t? = nil
|
||||||
|
var count = mach_msg_type_number_t()
|
||||||
|
|
||||||
|
let result = task_threads(mach_task_self_, &(threads_array), &count)
|
||||||
|
|
||||||
|
guard result == KERN_SUCCESS else {
|
||||||
|
return threads_act
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let array = threads_array else {
|
||||||
|
return threads_act
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..<count {
|
||||||
|
threads_act.append(array[Int(i)])
|
||||||
|
}
|
||||||
|
|
||||||
|
let krsize = count * UInt32.init(MemoryLayout<thread_t>.size)
|
||||||
|
_ = vm_deallocate(mach_task_self_, vm_address_t(array.pointee), vm_size_t(krsize));
|
||||||
|
return threads_act
|
||||||
|
}
|
||||||
|
|
||||||
|
private class func threadBasicInfos() -> [thread_basic_info] {
|
||||||
|
var result = [thread_basic_info]()
|
||||||
|
|
||||||
|
let thinfo : thread_info_t = thread_info_t.allocate(capacity: Int(THREAD_INFO_MAX))
|
||||||
|
let thread_info_count = UnsafeMutablePointer<mach_msg_type_number_t>.allocate(capacity: 128)
|
||||||
|
var basic_info_th: thread_basic_info_t? = nil
|
||||||
|
|
||||||
|
for act_t in self.threadActPointers() {
|
||||||
|
thread_info_count.pointee = UInt32(THREAD_INFO_MAX);
|
||||||
|
let kr = thread_info(act_t ,thread_flavor_t(THREAD_BASIC_INFO),thinfo, thread_info_count);
|
||||||
|
if (kr != KERN_SUCCESS) {
|
||||||
|
return [thread_basic_info]();
|
||||||
|
}
|
||||||
|
basic_info_th = withUnsafePointer(to: &thinfo.pointee, { (ptr) -> thread_basic_info_t in
|
||||||
|
let int8Ptr = unsafeBitCast(ptr, to: thread_basic_info_t.self)
|
||||||
|
return int8Ptr
|
||||||
|
})
|
||||||
|
if basic_info_th != nil {
|
||||||
|
result.append(basic_info_th!.pointee)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: this function is used for get cpu usage of all thread,and this is in developing
|
||||||
|
private class func threadIdentifierInfos() -> [thread_identifier_info] {
|
||||||
|
var result = [thread_identifier_info]()
|
||||||
|
let thinfo : thread_info_t = thread_info_t.allocate(capacity: Int(THREAD_INFO_MAX))
|
||||||
|
let thread_info_count = UnsafeMutablePointer<mach_msg_type_number_t>.allocate(capacity: 128)
|
||||||
|
var identifier_info_th: thread_identifier_info_t? = nil
|
||||||
|
|
||||||
|
for act_t in self.threadActPointers() {
|
||||||
|
thread_info_count.pointee = UInt32(THREAD_INFO_MAX);
|
||||||
|
let kr = thread_info(act_t ,thread_flavor_t(THREAD_IDENTIFIER_INFO),thinfo, thread_info_count);
|
||||||
|
if (kr != KERN_SUCCESS) {
|
||||||
|
return [thread_identifier_info]();
|
||||||
|
}
|
||||||
|
identifier_info_th = withUnsafePointer(to: &thinfo.pointee, { (ptr) -> thread_identifier_info_t in
|
||||||
|
let int8Ptr = unsafeBitCast(ptr, to: thread_identifier_info_t.self)
|
||||||
|
return int8Ptr
|
||||||
|
})
|
||||||
|
if identifier_info_th != nil {
|
||||||
|
result.append(identifier_info_th!.pointee)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -261,6 +261,7 @@ enum ItemType: Decodable {
|
|||||||
case shellScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
|
case shellScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
|
||||||
case timeButton(formatTemplate: String, timeZone: String?, locale: String?)
|
case timeButton(formatTemplate: String, timeZone: String?, locale: String?)
|
||||||
case battery
|
case battery
|
||||||
|
case cpu(refreshInterval: Double)
|
||||||
case dock(autoResize: Bool, filter: String?)
|
case dock(autoResize: Bool, filter: String?)
|
||||||
case volume
|
case volume
|
||||||
case brightness(refreshInterval: Double)
|
case brightness(refreshInterval: Double)
|
||||||
@ -317,6 +318,7 @@ enum ItemType: Decodable {
|
|||||||
case shellScriptTitledButton
|
case shellScriptTitledButton
|
||||||
case timeButton
|
case timeButton
|
||||||
case battery
|
case battery
|
||||||
|
case cpu
|
||||||
case dock
|
case dock
|
||||||
case volume
|
case volume
|
||||||
case brightness
|
case brightness
|
||||||
@ -362,6 +364,10 @@ enum ItemType: Decodable {
|
|||||||
|
|
||||||
case .battery:
|
case .battery:
|
||||||
self = .battery
|
self = .battery
|
||||||
|
|
||||||
|
case .cpu:
|
||||||
|
let refreshInterval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 5.0
|
||||||
|
self = .cpu(refreshInterval: refreshInterval)
|
||||||
|
|
||||||
case .dock:
|
case .dock:
|
||||||
let autoResize = try container.decodeIfPresent(Bool.self, forKey: .autoResize) ?? false
|
let autoResize = try container.decodeIfPresent(Bool.self, forKey: .autoResize) ?? false
|
||||||
|
|||||||
@ -29,6 +29,8 @@ extension ItemType {
|
|||||||
return "com.toxblh.mtmr.timeButton."
|
return "com.toxblh.mtmr.timeButton."
|
||||||
case .battery:
|
case .battery:
|
||||||
return "com.toxblh.mtmr.battery."
|
return "com.toxblh.mtmr.battery."
|
||||||
|
case .cpu(refreshInterval: _):
|
||||||
|
return "com.toxblh.mtmr.cpu."
|
||||||
case .dock(autoResize: _, filter: _):
|
case .dock(autoResize: _, filter: _):
|
||||||
return "com.toxblh.mtmr.dock"
|
return "com.toxblh.mtmr.dock"
|
||||||
case .volume:
|
case .volume:
|
||||||
@ -272,6 +274,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template, timeZone: timeZone, locale: locale)
|
barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template, timeZone: timeZone, locale: locale)
|
||||||
case .battery:
|
case .battery:
|
||||||
barItem = BatteryBarItem(identifier: identifier)
|
barItem = BatteryBarItem(identifier: identifier)
|
||||||
|
case let .cpu(refreshInterval: refreshInterval):
|
||||||
|
barItem = CPUBarItem(identifier: identifier, refreshInterval: refreshInterval)
|
||||||
case let .dock(autoResize: autoResize, filter: regexString):
|
case let .dock(autoResize: autoResize, filter: regexString):
|
||||||
if let regexString = regexString {
|
if let regexString = regexString {
|
||||||
guard let regex = try? NSRegularExpression(pattern: regexString, options: []) else {
|
guard let regex = try? NSRegularExpression(pattern: regexString, options: []) else {
|
||||||
|
|||||||
82
MTMR/Widgets/CPUBarItem.swift
Normal file
82
MTMR/Widgets/CPUBarItem.swift
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// CPUBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by bobrosoft on 17/08/2021.
|
||||||
|
// Copyright © 2018 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class CPUBarItem: CustomButtonTouchBarItem {
|
||||||
|
private let refreshInterval: TimeInterval
|
||||||
|
private var refreshQueue: DispatchQueue? = DispatchQueue(label: "mtmr.cpu")
|
||||||
|
private let defaultSingleTapScript: NSAppleScript! = "activate application \"Activity Monitor\"\rtell application \"System Events\"\r\ttell process \"Activity Monitor\"\r\t\ttell radio button \"CPU\" of radio group 1 of group 2 of toolbar 1 of window 1 to perform action \"AXPress\"\r\tend tell\rend tell".appleScript
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier, refreshInterval: TimeInterval) {
|
||||||
|
self.refreshInterval = refreshInterval
|
||||||
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
|
||||||
|
// Set default image
|
||||||
|
if self.image == nil {
|
||||||
|
self.image = #imageLiteral(resourceName: "cpu").resize(maxSize: NSSize(width: 24, height: 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default action
|
||||||
|
if actions.filter({ $0.trigger == .singleTap }).isEmpty {
|
||||||
|
actions.append(ItemAction(
|
||||||
|
trigger: .singleTap,
|
||||||
|
defaultTapAction
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshAndSchedule()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshAndSchedule() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// Get CPU load
|
||||||
|
let usage = 100 - CPU.systemUsage().idle
|
||||||
|
guard usage.isFinite else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose color based on CPU load
|
||||||
|
var color: NSColor? = nil
|
||||||
|
var bgColor: NSColor? = nil
|
||||||
|
if usage > 70 {
|
||||||
|
color = .black
|
||||||
|
bgColor = .yellow
|
||||||
|
} else if usage > 30 {
|
||||||
|
color = .yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update layout
|
||||||
|
let attrTitle = NSMutableAttributedString.init(attributedString: String(format: "%.1f%%", usage).defaultTouchbarAttributedString)
|
||||||
|
if let color = color {
|
||||||
|
attrTitle.addAttributes([.foregroundColor: color], range: NSRange(location: 0, length: attrTitle.length))
|
||||||
|
}
|
||||||
|
self.attributedTitle = attrTitle
|
||||||
|
self.backgroundColor = bgColor
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshQueue?.asyncAfter(deadline: .now() + refreshInterval) { [weak self] in
|
||||||
|
self?.refreshAndSchedule()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultTapAction() {
|
||||||
|
refreshQueue?.async { [weak self] in
|
||||||
|
self?.defaultSingleTapScript.executeAndReturnError(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
refreshQueue?.suspend()
|
||||||
|
refreshQueue = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
16
README.md
16
README.md
@ -73,6 +73,7 @@ The pre-installed configuration contains less or more than you'll probably want,
|
|||||||
|
|
||||||
- timeButton
|
- timeButton
|
||||||
- battery
|
- battery
|
||||||
|
- cpu
|
||||||
- currency
|
- currency
|
||||||
- weather
|
- weather
|
||||||
- yandexWeather
|
- yandexWeather
|
||||||
@ -189,7 +190,7 @@ Example:
|
|||||||
> Note: script may return also colors using escape sequences (read more here https://misc.flogisoft.com/bash/tip_colors_and_formatting)
|
> Note: script may return also colors using escape sequences (read more here https://misc.flogisoft.com/bash/tip_colors_and_formatting)
|
||||||
> Only "16 Colors" mode supported atm. If background color returned, button will pick it up as own background color.
|
> Only "16 Colors" mode supported atm. If background color returned, button will pick it up as own background color.
|
||||||
|
|
||||||
Example of "CPU load" button which also changes color based on load value.
|
Example of "CPU load" button which also changes color based on load value (Note: you can use native `cpu` plugin for that purpose which runs better):
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
"type": "shellScriptTitledButton",
|
"type": "shellScriptTitledButton",
|
||||||
@ -246,6 +247,19 @@ To close a group, use the button:
|
|||||||
|
|
||||||
## Native plugins
|
## Native plugins
|
||||||
|
|
||||||
|
#### `cpu`
|
||||||
|
|
||||||
|
> Shows current CPU load in percents, changes color based on load value.
|
||||||
|
> Has lower power consumption and more stable in comparison to shell-based solution.
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"type": "cpu",
|
||||||
|
"refreshInterval": 3,
|
||||||
|
"width": 80
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### `timeButton`
|
#### `timeButton`
|
||||||
|
|
||||||
> Attention! Works not all: https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
|
> Attention! Works not all: https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user