mirror of
https://github.com/reactos/reactos.git
synced 2026-06-01 00:40:26 +08:00
[WIN32SS:NTUSER] Implement SharedUserData->LastSystemRITEventTickCount (#8537)
This field was introduced in NT5.1, records the tick count of the last user input (system-wide), updated at most once per minute (or once per second since NT6.0). Unlike `GetLastInputInfo` which is designed for providing session-specific user input information, `SharedUserData->LastSystemRITEventTickCount` provides system-wide time, used by: - [Task Schedule (TASK_EVENT_TRIGGER_ON_IDLE)](https://learn.microsoft.com/en-us/windows/win32/taskschd/i) - [Inactivity Monitoring](https://learn.microsoft.com/en-us/windows/win32/devnotes/inactivity-monitoring) - Maybe some places I don't know... See also: - [KUSER_SHARED_DATA - Geoff Chappell](https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm) - [TASK_TRIGGER_TYPE enumeration - Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/mstask/ne-mstask-task_trigger_type) - [Task Scheduler: idle conditions](https://learn.microsoft.com/en-us/windows/win32/taskschd/i) - [GetLastInputInfo function - Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getlastinputinfo) - [Inactivity Monitoring](https://learn.microsoft.com/en-us/windows/win32/devnotes/inactivity-monitoring) ## Proposed changes Before this PR, `SharedUserData->LastSystemRITEventTickCount` is never used and always 0, `gpsi->dwLastSystemRITEventTickCountUpdate` is never used too. After this PR, `SharedUserData->LastSystemRITEventTickCount` updates correctly by using `gpsi->dwLastSystemRITEventTickCountUpdate` to record previous update time, the behavior is the same as on Windows.
This commit is contained in:
@@ -3,4 +3,5 @@ add_subdirectory(messagebox)
|
||||
add_subdirectory(paintdesktop)
|
||||
add_subdirectory(psmtest)
|
||||
add_subdirectory(sysicon)
|
||||
add_subdirectory(useridletime)
|
||||
add_subdirectory(winstation)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
add_executable(useridletime UserIdleTime.c)
|
||||
set_module_type(useridletime win32cui UNICODE)
|
||||
add_importlibs(useridletime user32 msvcrt kernel32)
|
||||
add_rostests_file(TARGET useridletime SUBDIR suppl)
|
||||
47
modules/rostests/win32/user32/useridletime/UserIdleTime.c
Normal file
47
modules/rostests/win32/user32/useridletime/UserIdleTime.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Tests
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Calculate and print user idle time once per second by using
|
||||
* user32!GetLastInputInfo() API and SharedUserData->LastSystemRITEventTickCount
|
||||
* field separately. The former updates in real-time, while the latter updates
|
||||
* periodically (60s in NT5, 1s since NT6.0). Press Ctrl+C to exit this program.
|
||||
* COPYRIGHT: Copyright 2026 Ratin Gao <ratin@knsoft.org>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winuser.h>
|
||||
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/psfuncs.h>
|
||||
|
||||
int
|
||||
_cdecl
|
||||
wmain(
|
||||
_In_ int argc,
|
||||
_In_reads_(argc) _Pre_z_ wchar_t** argv)
|
||||
{
|
||||
DWORD dwTickCount, dwError;
|
||||
LASTINPUTINFO lii = { sizeof(lii) };
|
||||
|
||||
puts("User idle time in second (LastSystemRITEventTickCount, GetLastInputInfo):");
|
||||
for (;;)
|
||||
{
|
||||
dwTickCount = GetTickCount();
|
||||
if (!GetLastInputInfo(&lii))
|
||||
{
|
||||
dwError = GetLastError();
|
||||
printf("GetLastInputInfo failed with: 0x%08lX\n", dwError);
|
||||
return dwError;
|
||||
}
|
||||
printf("\t%lu, %lu\n",
|
||||
(dwTickCount - SharedUserData->LastSystemRITEventTickCount) / 1000UL,
|
||||
(dwTickCount - lii.dwTime) / 1000UL);
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -10,6 +10,13 @@
|
||||
#include <win32k.h>
|
||||
DBG_DEFAULT_CHANNEL(UserInput);
|
||||
|
||||
/* LastRITEventTickCount update cycle has been adjusted from 60s to 1s since NT6 */
|
||||
#if (NTDDI_VERSION < NTDDI_VISTA)
|
||||
#define LAST_RIT_EVENT_UPDATE_INTERVAL 60000UL
|
||||
#else
|
||||
#define LAST_RIT_EVENT_UPDATE_INTERVAL 1000UL
|
||||
#endif
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
PTHREADINFO ptiRawInput;
|
||||
@@ -34,7 +41,16 @@ IntLastInputTick(BOOL bUpdate)
|
||||
if (bUpdate)
|
||||
{
|
||||
LastInputTick = EngGetTickCount32();
|
||||
if (gpsi) gpsi->dwLastRITEventTickCount = LastInputTick;
|
||||
if (gpsi)
|
||||
{
|
||||
gpsi->dwLastRITEventTickCount = LastInputTick;
|
||||
if (gpsi->dwLastRITEventTickCount - gpsi->dwLastSystemRITEventTickCountUpdate >
|
||||
LAST_RIT_EVENT_UPDATE_INTERVAL)
|
||||
{
|
||||
SharedUserData->LastSystemRITEventTickCount = LastInputTick;
|
||||
gpsi->dwLastSystemRITEventTickCountUpdate = LastInputTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
return LastInputTick;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user