Get user idle time?

Mac OSX specific forum
Quin
Addict
Addict
Posts: 1132
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Get user idle time?

Post 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.
User avatar
skywalk
Addict
Addict
Posts: 4213
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Get user idle time?

Post 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 :(
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Piero
Addict
Addict
Posts: 885
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Get user idle time?

Post 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
Last edited by Piero on Mon Jan 22, 2024 8:28 am, edited 1 time in total.
User avatar
deseven
Enthusiast
Enthusiast
Posts: 367
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: Get user idle time?

Post 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
User avatar
Piero
Addict
Addict
Posts: 885
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Get user idle time?

Post by Piero »

deseven wrote: Wed Jan 24, 2024 11:32 pm

Code: Select all

#kCGAnyInputEventType = ~0
Me and Buddha: :shock: :lol:
User avatar
deseven
Enthusiast
Enthusiast
Posts: 367
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: Get user idle time?

Post 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.
User avatar
Piero
Addict
Addict
Posts: 885
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Get user idle time?

Post 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
infratec
Always Here
Always Here
Posts: 7598
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Get user idle time?

Post by infratec »

For all OSs with the same result (idle time in seconds)

Moved to:

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