7

Im trying to figure out how to track when a user has been idle from the computer, meaning not only my application. The reason is that i want my application to be able to set the user as "Away" after a certain amount of time. Think like Skype which takes you away after X minutes.

Any ideas how to accomplish this?

Edit

What i've got so far to track the mouse:

    //Init
    mouseTimer = new QTimer();
    mouseLastPos = QCursor::pos();
    mouseIdleSeconds = 0;

    //Connect and Start
    connect(mouseTimer, SIGNAL(timeout()), this, SLOT(mouseTimerTick()));
    mouseTimer->start(1000);

void MainWindow::mouseTimerTick()
{
    QPoint point = QCursor::pos();
    if(point != mouseLastPos)
        mouseIdleSeconds = 0;
    else
        mouseIdleSeconds++;

    mouseLastPos = point;

    //Here you could determine whatever to do
    //with the total number of idle seconds.

    qDebug() << mouseIdleSeconds;
}

Any way to add keyboard to this also?

Alosyius
  • 8,771
  • 26
  • 76
  • 120
  • Is this for a multi-platform application? Cause I don't think there is anything platform independent in Qt to track system idle time... You could always keep an eye on the mouse and keyboard activity though. – Jite Feb 20 '14 at 07:54
  • 1
    Found this on a quick google search: http://qt-project.org/faq/answer/how_can_i_detect_a_period_of_no_user_interaction Might be worth checking out. – Jite Feb 20 '14 at 07:55
  • Yes, sorry this is for a multi-platform application :) – Alosyius Feb 20 '14 at 07:56
  • Then I would think checking for mouse/keyboard events would be your best bet (with least messy platform specific cases). – Jite Feb 20 '14 at 08:00

2 Answers2

7

There are platform-specific ways of getting idle user notifications. You should almost always use those, instead of rolling your own.

Suppose you insist on rolling your own code. On X11, OS X and Windows, applications simply don't receive any events that are targeted at other applications. Qt doesn't offer much help in monitoring such global events. You need hook into the relevant global events, and filter them. This is platform specific.

So, no matter what you do, you have to write some front-end API that exposes the functionality you're after, and write one or more platform-specific backends.

The preferred platform-specific idle time APIs are:

  • On Windows, GetLastInputInfo, see this answer.

  • On OS X, NSWorkspaceWillSleepNotification and NSWorkspaceDidWakeNotification, see this answer.

  • On X11, it is the screensaver API:

    /* gcc -o getIdleTime getIdleTime.c -lXss */
    #include <X11/extensions/scrnsaver.h>
    #include <stdio.h>
    
    int main(void) {
      Display *dpy = XOpenDisplay(NULL);
    
      if (!dpy) {
        return(1);
      }
    
      XScreenSaverInfo *info = XScreenSaverAllocInfo();
      XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info);
      printf("%u", info->idle);
    
      return(0);
    }
    
Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
1

Best bet would be to check for mouse and keyboard events.

If you override the eventFilter function and in that check for:

QEvent::MouseButtonPress
QEvent::MouseButtonRelease
QEvent::Wheel
QEvent::KeyPress
QEvent::KeyRelease

Create a QTimer, which will be reset on any of the events, and if not, just let the timer tick and fire a callback at whatever intervalls you wish.

Edit:
Please see comments and Kuba Ober's answer for more info.

Jite
  • 5,761
  • 2
  • 23
  • 37
  • Don't forget to call `installEventFilter(this);`, always forget that while working with Qt myself ;) – Jite Feb 20 '14 at 08:10
  • 1
    You haven't tried it out, right? Because it simply doesn't work: Qt provides no means of filtering system-global UI events. – Kuba hasn't forgotten Monica Feb 20 '14 at 10:27
  • No, I have not had the chance to try this out at the moment, do not have Qt installed on this computer and am at work currently, so gave an answer that I thought was *worth trying*. Is it confirmed that it does not work (ie, tested)? Cause in that case ill gladly remove my answer. – Jite Feb 20 '14 at 10:35
  • This has not much to do with Qt at all. On X11, OS X and Windows, an application, by default, simply does not receive events that are not specifically targeted at it. So, as soon as the mouse is outside of your application's visible window, or as soon as you lose keyboard focus, you stop receiving relevant events. Things would be horribly slow otherwise - imagine hundreds of threads (typical on most systems) all receiving the same events all the time! That why there's a concept of keyboard/mouse grabbing. – Kuba hasn't forgotten Monica Feb 20 '14 at 10:42
  • What you say sounds reasonable (and what I kinda was expecting). And by reading the qt event documentation i get the same impression. Ill leave the wrong answer to keep our discussion saved for reference. ;) – Jite Feb 20 '14 at 11:06