2011-01-10 8 views

risposta

6

Nel caso in cui non è possibile collegare al carbonio (. Per esempio, si desidera compilare po x86_64 binario) si può avvolgere questa funzione (che restituisce ore di inattività nella risoluzione secondi, come doppio - CFTimeInterval) in un timer:

#include <IOKit/IOKitLib.h> 

CFTimeInterval CFDateGetIdleTimeInterval() { 
    mach_port_t port; 
    io_iterator_t iter; 
    CFTypeRef value = kCFNull; 
    uint64_t idle = 0; 
    CFMutableDictionaryRef properties = NULL; 
    io_registry_entry_t entry; 

    IOMasterPort(MACH_PORT_NULL, &port); 
    IOServiceGetMatchingServices(port, IOServiceMatching("IOHIDSystem"), &iter); 
    if (iter) { 
     if ((entry = IOIteratorNext(iter))) { 
      if (IORegistryEntryCreateCFProperties(entry, &properties, kCFAllocatorDefault, 0) == KERN_SUCCESS && properties) { 
       if (CFDictionaryGetValueIfPresent(properties, CFSTR("HIDIdleTime"), &value)) { 
        if (CFGetTypeID(value) == CFDataGetTypeID()) { 
         CFDataGetBytes(value, CFRangeMake(0, sizeof(idle)), (UInt8 *) &idle); 
        } else if (CFGetTypeID(value) == CFNumberGetTypeID()) { 
         CFNumberGetValue(value, kCFNumberSInt64Type, &idle); 
        } 
       } 
       CFRelease(properties); 
      } 
      IOObjectRelease(entry); 
     } 
     IOObjectRelease(iter); 
    } 

    return idle/1000000000.0; 
} 

sarà necessario collegare il codice per IOKit.framework

+0

Piccola modifica, voce = IOIteratorNext (livello) deve essere voce = IOIteratorNext (iter). – Shaun

+0

Si noti che HIDIdleTime non è molto affidabile e restituisce sempre zero su alcuni Mac per motivi sconosciuti (probabilmente alcuni dispositivi collegati ripristinano il conteggio del tempo di inattività). –

0

Apple Technical Q&A QA1340 Registering and unregistering for sleep and wake notifications può essere quello che stai cercando.

Se è necessario un controllo maggiore di NSWorkspaceWillSleepNotification (Elenco 1), utilizzare I/O Kit e registrarsi per ricevere le notifiche di alimentazione (Elenco 3).

+0

Il problema con le notifiche a seconda sonno/veglia è che se un utente imposta le proprie impostazioni di sonno a "mai" non saranno mai inviati. Mi piacerebbe contare il tempo di inattività quando non ci sono attività da tastiera/mouse. – David

+0

Ci scusiamo, anche se intendevi quando l'app entra nel sonno ideale. La soluzione di kperryua con CGEventSourceSecondsSinceLastEventType è corretta per il monitoraggio del tempo dall'ultimo input dell'utente. –

5

C'è una API Carbon che invierà una notifica quando non c'è stato un evento utente dopo una certa durata chiamata EventLoopIdleTimer. Uli Kusterer ha scritto un wrapper Cocoa per here (look for UKIdleTimer).

Se si desidera qualcosa di livello inferiore, è possibile implementare il comportamento desiderato con una combinazione di timer e la funzione CoreGraphics CGEventSourceSecondsSinceLastEventType (disponibile in <CoreGraphics/CGEventSource.h>).

+0

È possibile fare lo stesso su iOS? – SlowTree

+0

Nessuna di queste API è disponibile su iOS. Non so se ci sono degli equivalenti. – kperryua

+0

Non utilizzare CGEventSourceSecondsSinceLastEventType nel daemon di avvio. –

0

ho usato un approccio diverso. Applicazione sottoclasse UIA I override del tocco del metodo sendEvent tocchi (in realtà è possibile filtrare qualsiasi tipo di evento, accelerazione, tocco, ecc.). Utilizzando una variabile condivisa e un timer dello sfondo ho gestito il "idle". Ogni volta che l'utente tocca lo schermo, la variabile viene impostata con timeInterval corrente (ora corrente). I timer metodo fuoco i controlli per il tempo trascorso dall'ultima tocco, se superiore alla soglia (nel mio caso è stato di circa 90 secondi) si possono inviare la propria notifica.

Ho usato questo metodo semplice per creare un set personalizzato di applicazioni che dopo un certo tempo di inattività chiamano automaticamente il "screensaver" app.

Niente intelligente, semplicemente fare il lavoro.

Spero che questo aiuti.

Problemi correlati