Skip to content

Instantly share code, notes, and snippets.

@darrarski
Last active March 30, 2021 07:05
Show Gist options
  • Save darrarski/c586ce379d3e7e91a57d89ed557192ec to your computer and use it in GitHub Desktop.
Save darrarski/c586ce379d3e7e91a57d89ed557192ec to your computer and use it in GitHub Desktop.
Get Mac OS X system idle time in Swift or Objective-C
//
// Created by Dariusz Rybicki on 17/04/16.
// Copyright © 2016 Darrarski. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
Returns number of seconds since system became idle
@return `double` System idle time in seconds or -1 when unable to retrieve it
*/
double SystemIdleTime(void) {
double idleSeconds = -1;
io_iterator_t iter = 0;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOHIDSystem"), &iter) == KERN_SUCCESS) {
io_registry_entry_t entry = IOIteratorNext(iter);
if (entry) {
CFMutableDictionaryRef dict = NULL;
kern_return_t status;
status = IORegistryEntryCreateCFProperties(entry, &dict, kCFAllocatorDefault, 0);
if (status == KERN_SUCCESS) {
CFNumberRef obj = CFDictionaryGetValue(dict, CFSTR("HIDIdleTime"));
if (obj) {
int64_t nanoseconds = 0;
if (CFNumberGetValue(obj, kCFNumberSInt64Type, &nanoseconds)) {
idleSeconds = (double) nanoseconds / NSEC_PER_SEC;
}
}
CFRelease(dict);
}
IOObjectRelease(entry);
}
IOObjectRelease(iter);
}
return idleSeconds;
}
//
// Created by Dariusz Rybicki on 17/04/16.
// Copyright © 2016 Darrarski. All rights reserved.
//
import Foundation
/**
Returns number of seconds since system became idle
returns: `Double?`: System idle time in seconds or nil when unable to retrieve it
*/
public func SystemIdleTime() -> Double? {
var iterator: io_iterator_t = 0
defer { IOObjectRelease(iterator) }
guard IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOHIDSystem"), &iterator) == KERN_SUCCESS else { return nil }
let entry: io_registry_entry_t = IOIteratorNext(iterator)
defer { IOObjectRelease(entry) }
guard entry != 0 else { return nil }
var unmanagedDict: Unmanaged<CFMutableDictionaryRef>? = nil
defer { unmanagedDict?.release() }
guard IORegistryEntryCreateCFProperties(entry, &unmanagedDict, kCFAllocatorDefault, 0) == KERN_SUCCESS else { return nil }
guard let dict = unmanagedDict?.takeUnretainedValue() else { return nil }
let key: CFString = "HIDIdleTime"
let value = CFDictionaryGetValue(dict, unsafeAddressOf(key))
let number: CFNumberRef = unsafeBitCast(value, CFNumberRef.self)
var nanoseconds: Int64 = 0
guard CFNumberGetValue(number, CFNumberType.SInt64Type, &nanoseconds) else { return nil }
let interval = Double(nanoseconds) / Double(NSEC_PER_SEC)
return interval
}
@gbbr
Copy link

gbbr commented Aug 23, 2017

Couldn't get this to work for Swift 3 / macOS, but it would be super useful :)

@DamirDjozicCoing
Copy link

DamirDjozicCoing commented Feb 7, 2018

@gbbr here is swift 3 version

public func SystemIdleTime() -> Double? {
var iterator: io_iterator_t = 0
defer { IOObjectRelease(iterator) }
guard IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOHIDSystem"), &iterator) == KERN_SUCCESS else { 
  return nil }    

let entry: io_registry_entry_t = IOIteratorNext(iterator)
defer { IOObjectRelease(entry) }
guard entry != 0 else { return nil }

var unmanagedDict: Unmanaged<CFMutableDictionary>? = nil
defer { unmanagedDict?.release() }
guard IORegistryEntryCreateCFProperties(entry, &unmanagedDict, kCFAllocatorDefault, 0) == KERN_SUCCESS else { return nil }
guard let dict = unmanagedDict?.takeUnretainedValue() else { return nil }

let key: CFString = "HIDIdleTime" as CFString
let value = CFDictionaryGetValue(dict, Unmanaged.passUnretained(key).toOpaque())
let number: CFNumber = unsafeBitCast(value, to: CFNumber.self)
var nanoseconds: Int64 = 0
guard CFNumberGetValue(number, CFNumberType.sInt64Type, &nanoseconds) else { return nil }
let interval = Double(nanoseconds) / Double(NSEC_PER_SEC)

return interval
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment