Page 1 of 1

Get user idle time?

Posted: Thu Jan 18, 2024 6:21 pm
by Quin
Hi,
In my app I need to be able to get how long the user has been idle for. I wrote code for Windows to do this using LASTINPUTINFO and GetLastInputInfo_(), but I'm having much worse luck on the Mac. I saw people on places like Stackoverflow suggesting I run a terminal command (because of course; it's the Mac), but I can't get it to work. Here's my code:

Code: Select all

Procedure GetIdleTime()
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    Protected Info.LASTINPUTINFO
    Info\cbSize = SizeOf(LASTINPUTINFO)
    GetLastInputInfo_(@Info)
    CompilerIf #PB_Compiler_32Bit
      ProcedureReturn (GetTickCount_() - Info\dwTime) / (1000 * 60)
    CompilerElse
      ProcedureReturn (GetTickCount64() - Info\dwTime) / (1000 * 60)
    CompilerEndIf
  CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
    Protected IOReg, Result$
    IOReg = RunProgram("ioreg", "-c IOHIDSystem", GetCurrentDirectory(), #PB_Program_Read)
    Result$ = ReadProgramString(IOReg)
    CreateRegularExpression(0, "HIDIdleTime.*")
    ExamineRegularExpression(0, Result$)
    If NextRegularExpressionMatch(0)
      Result$ = RegularExpressionMatchString(0)
    EndIf
    Debug Result$
    ProcedureReturn Val(Result$)
  CompilerEndIf
EndProcedure
No matter what I do ,it throws a program is null error and makes the entire app blow up. Is there something I'm doing wrong in my code, or even better, is there a way to do this with something like CocoaMessage()?
Thanks.

Re: Get user idle time?

Posted: Thu Jan 18, 2024 6:43 pm
by skywalk

Code: Select all

Procedure.d SL_IdleTime_Sec(Delay_ms.i=5000)
  ; If no input > given Delay_ms, then return idltm
  ; Else return 0
  ; SYNTAX: Debug SL_IdleTime_Sec()
  Protected idle.LASTINPUTINFO
  idle\cbSize = SizeOf(LASTINPUTINFO)
  Delay(Delay_ms)
  GetLastInputInfo_(@idle)
  Protected.d idltm = GetTickCount_() - idle\dwTime
  If idltm > Delay_ms
    idltm / 1000
  Else
    idltm = 0
  EndIf
  ProcedureReturn idltm
EndProcedure
Debug SL_IdleTime_Sec(1000) ; Move mouse while timeout being checked.
EDIT: sorry I didn't see the MAC requirement :(

Re: Get user idle time?

Posted: Fri Jan 19, 2024 1:36 pm
by Piero

Code: Select all

Structure daResults
   Out.s
   Err.s
   ExC.w ; exit code
EndStructure

Global Sh.daResults

Procedure Shell(ShellCommand$, AddReturns = #True)
   Protected Err$, tmper$, Output$, shell, Exc.w = -1 ; -1 on failed launch
   shell = RunProgram("/bin/sh","","",
      #PB_Program_Open|#PB_Program_Write|#PB_Program_Read|#PB_Program_Error )
   If shell
      WriteProgramStringN(shell,ShellCommand$)
      WriteProgramData(shell,#PB_Program_Eof,0)
      While ProgramRunning(shell)
         If AvailableProgramOutput(shell)
            Output$ + ReadProgramString(shell)
            If AddReturns : Output$ + Chr(13) : EndIf
         EndIf
         tmper$ = ReadProgramError(shell)
         If tmper$ : Err$ + tmper$ + Chr(13) : EndIf
      Wend
      Exc = ProgramExitCode(shell) : CloseProgram(shell)
   EndIf
   Sh\Out = Output$ : Sh\Err = Err$ : Sh\ExC = Exc
EndProcedure

; IdleSecs$ = "echo $((`ioreg -c IOHIDSystem | sed -e '/HIDIdleTime/ !{ d' -e 't' -e '}' -e 's/.* = //g' -e 'q'` / 1000000000))"
IdleSecs$ = "ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000)}'"

Shell(IdleSecs$)
Debug Sh\Out

Delay(1000)

Shell(IdleSecs$)
Debug Sh\Out

Re: Get user idle time?

Posted: Wed Jan 24, 2024 11:32 pm
by deseven

Code: Select all

ImportC ""
  CGEventSourceSecondsSinceLastEventType.d(CGEventSourceStateID.l,CGEventType.l)
EndImport

#kCGAnyInputEventType = ~0
#hidSystemState = 1

Repeat
  Debug "seconds inactive: " + StrD(CGEventSourceSecondsSinceLastEventType(#hidSystemState,#kCGAnyInputEventType),3)
  Delay(1000)
ForEver

Re: Get user idle time?

Posted: Thu Jan 25, 2024 12:37 pm
by Piero
deseven wrote: Wed Jan 24, 2024 11:32 pm

Code: Select all

#kCGAnyInputEventType = ~0
Me and Buddha: :shock: :lol:

Re: Get user idle time?

Posted: Thu Jan 25, 2024 12:50 pm
by deseven
~ is a bitwise "not" (see PB docs for Variables, Types and Operators), this expression calculates to just -1, but I left it as it is since this is how it's defined in Apple constants.

Re: Get user idle time?

Posted: Thu Jan 25, 2024 1:21 pm
by Piero
I knew something about bitwise stuff... but it's somewhat becoming rusty like my cocoa...
PLEASE don't mess with Zero; you may repent if you aren't strong enough...
...and even less with stuff like CGEventSourceSecondsSinceLastEventType(,3)
:P

Re: Get user idle time?

Posted: Thu Feb 01, 2024 11:23 am
by infratec
For all OSs with the same result (idle time in seconds)

Moved to:

https://www.purebasic.fr/english/viewtopic.php?t=83473