Mac 上用户交互的最后一个实例

发布于 2024-12-21 18:20:11 字数 129 浏览 2 评论 0原文

我试图检测用户与给定 Mac 交互的最后一个实例(最好是某种可比较的数据结构,例如自纪元以来的秒数。)

此交互应包括打字、鼠标运动、应用程序交互等。但是,我不想确定计算机是否被锁定或处于屏幕保护状态,因为这些状态取决于用户偏好。

I'm trying to detect the last instance that a user interacted with a given Mac (preferably in some sort of comparable data structure, like seconds since the epoch.)

This interaction should include typing, mouse motion, app interaction, etc. However, I am not looking to determine whether or not the computer is locked or on screen-save, because those states are subject to user preference.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怎言笑 2024-12-28 18:20:11

您可以使用此函数获取自上次事件以来的秒数:

CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);

这会返回一个 CFTimeInterval,它是一个 double

You can get the number of seconds since the last event using this function:

CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);

This returns a CFTimeInterval which is a double.

倥絔 2024-12-28 18:20:11

使用IOKit框架。看看 RHSystemIdleTimer

#import <Cocoa/Cocoa.h>

@interface RHSystemIdleTimer : NSObject {
    NSTimer *idleTimer, *continuingIdleTimer;
    id delegate;
    NSTimeInterval timeInterval;
@private
    mach_port_t masterPort;
    io_iterator_t iter;
    io_registry_entry_t curObj; 
}
- (id)initSystemIdleTimerWithTimeInterval:(NSTimeInterval)ti;
- (int)systemIdleTime;
- (id)delegate;
- (void)setDelegate:(id)receiver;
- (void)invalidate;
@end

@interface RHSystemIdleTimer(Delegates)
-(void)timerBeginsIdling:(id)sender;
-(void)timerContinuesIdling:(id)sender;
-(void)timerFinishedIdling:(id)sender;
@end

#import "RHSystemIdleTimer.h"

@interface RHSystemIdleTimer(Private)
- (void)checkIdleStatus;
- (void)checkIfStillIdle;
@end

@implementation RHSystemIdleTimer

#pragma mark Initilization/Dealloc

- (id)initSystemIdleTimerWithTimeInterval:(NSTimeInterval)ti
{
    self = [super init];
    if(self) {

        IOMasterPort(MACH_PORT_NULL, &masterPort);

        /* Get IOHIDSystem */
        IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOHIDSystem"), &iter);
        if (iter == 0) {
            NSLog(@"Error accessing IOHIDSystem\n");
        }
        else {
            curObj = IOIteratorNext(iter);

            if (curObj == 0) {
                NSLog(@"Iterator's empty!\n");
            }
        }

        timeInterval = ti;              
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:ti
                                                     target:self
                                                   selector:@selector(checkIdleStatus)
                                                   userInfo:nil
                                                    repeats:NO];
    }
    return self;
}

- (void) dealloc {
    IOObjectRelease(curObj);
    IOObjectRelease(iter);
    [super dealloc];
}

#pragma mark Accessors

- (id)delegate
{
    return delegate;
}

- (void)setDelegate:(id)receiver
{
    delegate = receiver;
}

#pragma mark Private Methods

- (void)checkIdleStatus
{
    double idleTime = [self systemIdleTime];
    double timeLeft = timeInterval - idleTime;
    if(timeLeft <= 0) {

        if([delegate respondsToSelector:@selector(timerBeginsIdling:)]) {
            [delegate timerBeginsIdling:self];          
        }

        [NSTimer scheduledTimerWithTimeInterval:1.0
                                         target:self
                                       selector:@selector(checkIfStillIdle)
                                       userInfo:nil
                                        repeats:NO];

        if([delegate respondsToSelector:@selector(timerContinuesIdling:)]) {
            continuingIdleTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval
                                                                   target:delegate
                                                                 selector:@selector(timerContinuesIdling:)
                                                                 userInfo:nil
                                                                  repeats:YES];
        }       
    }
    else {
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:timeLeft
                                                     target:self
                                                   selector:@selector(checkIdleStatus)
                                                   userInfo:nil
                                                    repeats:NO];
    }
}

- (void)checkIfStillIdle
{
    double idleTime = [self systemIdleTime];
    if(idleTime <= 1.0) {
        [continuingIdleTimer invalidate];

        if([delegate respondsToSelector:@selector(timerFinishedIdling:)]) {
            [delegate timerFinishedIdling:self];            
        }

        // reset; start checking for system idle time again
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval
                                         target:self
                                       selector:@selector(checkIdleStatus)
                                       userInfo:nil
                                        repeats:NO];
    }
    else {
        [NSTimer scheduledTimerWithTimeInterval:1.0
                                         target:self
                                       selector:@selector(checkIfStillIdle)
                                       userInfo:nil
                                        repeats:NO];
    }
}

#pragma mark Public Methods

- (void)invalidate
{
    [idleTimer invalidate]; 
}

- (int)systemIdleTime
{       
    CFMutableDictionaryRef properties = 0;
    CFTypeRef obj;

    if (IORegistryEntryCreateCFProperties(curObj, &properties, kCFAllocatorDefault, 0) == KERN_SUCCESS && properties != NULL) {
        obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime"));
        CFRetain(obj);
    } else {
        NSLog(@"Couldn't grab properties of system\n");
        obj = NULL;
    }

    uint64_t tHandle = 0;
    if (obj) {
        CFTypeID type = CFGetTypeID(obj);

        if (type == CFDataGetTypeID()) {
            CFDataGetBytes((CFDataRef) obj, CFRangeMake(0, sizeof(tHandle)), (UInt8*) &tHandle);
        }
        else if (type == CFNumberGetTypeID()) {
            CFNumberGetValue((CFNumberRef)obj, kCFNumberSInt64Type, &tHandle);
        }
        else {
            NSLog(@"%d: unsupported type\n", (int)type);
        }

        CFRelease(obj);

        tHandle >>= 30; // essentially divides by 10^9 (nanoseconds)
    }
    else {
        NSLog(@"Can't find idle time\n");
    }

    CFRelease((CFTypeRef)properties);       
    return tHandle;
}

@end  

Use IOKit framework. Have a look at RHSystemIdleTimer

#import <Cocoa/Cocoa.h>

@interface RHSystemIdleTimer : NSObject {
    NSTimer *idleTimer, *continuingIdleTimer;
    id delegate;
    NSTimeInterval timeInterval;
@private
    mach_port_t masterPort;
    io_iterator_t iter;
    io_registry_entry_t curObj; 
}
- (id)initSystemIdleTimerWithTimeInterval:(NSTimeInterval)ti;
- (int)systemIdleTime;
- (id)delegate;
- (void)setDelegate:(id)receiver;
- (void)invalidate;
@end

@interface RHSystemIdleTimer(Delegates)
-(void)timerBeginsIdling:(id)sender;
-(void)timerContinuesIdling:(id)sender;
-(void)timerFinishedIdling:(id)sender;
@end

#import "RHSystemIdleTimer.h"

@interface RHSystemIdleTimer(Private)
- (void)checkIdleStatus;
- (void)checkIfStillIdle;
@end

@implementation RHSystemIdleTimer

#pragma mark Initilization/Dealloc

- (id)initSystemIdleTimerWithTimeInterval:(NSTimeInterval)ti
{
    self = [super init];
    if(self) {

        IOMasterPort(MACH_PORT_NULL, &masterPort);

        /* Get IOHIDSystem */
        IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOHIDSystem"), &iter);
        if (iter == 0) {
            NSLog(@"Error accessing IOHIDSystem\n");
        }
        else {
            curObj = IOIteratorNext(iter);

            if (curObj == 0) {
                NSLog(@"Iterator's empty!\n");
            }
        }

        timeInterval = ti;              
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:ti
                                                     target:self
                                                   selector:@selector(checkIdleStatus)
                                                   userInfo:nil
                                                    repeats:NO];
    }
    return self;
}

- (void) dealloc {
    IOObjectRelease(curObj);
    IOObjectRelease(iter);
    [super dealloc];
}

#pragma mark Accessors

- (id)delegate
{
    return delegate;
}

- (void)setDelegate:(id)receiver
{
    delegate = receiver;
}

#pragma mark Private Methods

- (void)checkIdleStatus
{
    double idleTime = [self systemIdleTime];
    double timeLeft = timeInterval - idleTime;
    if(timeLeft <= 0) {

        if([delegate respondsToSelector:@selector(timerBeginsIdling:)]) {
            [delegate timerBeginsIdling:self];          
        }

        [NSTimer scheduledTimerWithTimeInterval:1.0
                                         target:self
                                       selector:@selector(checkIfStillIdle)
                                       userInfo:nil
                                        repeats:NO];

        if([delegate respondsToSelector:@selector(timerContinuesIdling:)]) {
            continuingIdleTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval
                                                                   target:delegate
                                                                 selector:@selector(timerContinuesIdling:)
                                                                 userInfo:nil
                                                                  repeats:YES];
        }       
    }
    else {
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:timeLeft
                                                     target:self
                                                   selector:@selector(checkIdleStatus)
                                                   userInfo:nil
                                                    repeats:NO];
    }
}

- (void)checkIfStillIdle
{
    double idleTime = [self systemIdleTime];
    if(idleTime <= 1.0) {
        [continuingIdleTimer invalidate];

        if([delegate respondsToSelector:@selector(timerFinishedIdling:)]) {
            [delegate timerFinishedIdling:self];            
        }

        // reset; start checking for system idle time again
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval
                                         target:self
                                       selector:@selector(checkIdleStatus)
                                       userInfo:nil
                                        repeats:NO];
    }
    else {
        [NSTimer scheduledTimerWithTimeInterval:1.0
                                         target:self
                                       selector:@selector(checkIfStillIdle)
                                       userInfo:nil
                                        repeats:NO];
    }
}

#pragma mark Public Methods

- (void)invalidate
{
    [idleTimer invalidate]; 
}

- (int)systemIdleTime
{       
    CFMutableDictionaryRef properties = 0;
    CFTypeRef obj;

    if (IORegistryEntryCreateCFProperties(curObj, &properties, kCFAllocatorDefault, 0) == KERN_SUCCESS && properties != NULL) {
        obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime"));
        CFRetain(obj);
    } else {
        NSLog(@"Couldn't grab properties of system\n");
        obj = NULL;
    }

    uint64_t tHandle = 0;
    if (obj) {
        CFTypeID type = CFGetTypeID(obj);

        if (type == CFDataGetTypeID()) {
            CFDataGetBytes((CFDataRef) obj, CFRangeMake(0, sizeof(tHandle)), (UInt8*) &tHandle);
        }
        else if (type == CFNumberGetTypeID()) {
            CFNumberGetValue((CFNumberRef)obj, kCFNumberSInt64Type, &tHandle);
        }
        else {
            NSLog(@"%d: unsupported type\n", (int)type);
        }

        CFRelease(obj);

        tHandle >>= 30; // essentially divides by 10^9 (nanoseconds)
    }
    else {
        NSLog(@"Can't find idle time\n");
    }

    CFRelease((CFTypeRef)properties);       
    return tHandle;
}

@end  
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文