Solved

Detecting inactivity

Posted on 2004-04-02
30
732 Views
Last Modified: 2008-01-09
I'm currently implementing a small chat /instant messenger application for our company's internal use.  I'm 90% done with the exception of "detecting inactivity".  I somehow need to detect keyboard and mouse inactivity while my chat application is running in the background.  If there is no activity for say 10 minutes, my chat application should switch to away mode...

How can I detect keyboard and mouse inactivity while my application is not the active one?  I'm programming in Java...
0
Comment
Question by:asimalp
  • 13
  • 7
  • 4
  • +2
30 Comments
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
>>  I'm programming in Java...

You've come to the right place then. ;)

Put a timer loop on a listener pair, and make it report when it's up.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
But don't forget - or rather, please consider first of all - that automatic detection of such things may not always be what the client wants. What happens if a user spills coffee over his trousers and is cleaning it up, so cant type, but still wants to see what the tohers say. If an away icon appears for him, then it could have undesireable consequences.
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
You could 'mirror' the event queue. Implement a mouse/keyboard listener that add enqueues the 'events' (it doesn't have to be the events themselves) onto a queue. These events would be dequeued. When the queue is empty you set off a Timer that increments a counter. The timer is cancelled as soon as more events are enqueued. If the counter reaches a certain value - then you know there's been no activity for some time.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
IOW - think carefully before proxying-away the users rights.
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
In fact it's easier than that - you can hook the real event queue:

http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Toolkit.html#addAWTEventListener(java.awt.event.AWTEventListener, long)
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
You can't, (without the use of JNI of course)
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
You'll probably find that the following is sufficient as the parameter to that function:

AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK
0
 
LVL 14

Expert Comment

by:Tommy Braas
Comment Utility
Just like objects said, you can't do what you want without using JNI, at least not if your application is supposed play nice with the other applications.

You need to hook into the operating system event queue, using native code, in order to achieve your goal.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
You may make a timer, and that timer routine's clock gets reset to zero if the keystroke or mouse listener has fired, otherwise it implements or prompts the inactivity - away - flag to be set, then sleeps.
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 50 total points
Comment Utility
The bit that's been decribed by some people here as impossible without native code access is actually the easy bit. Here it is:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 *  Hook the AWT event queue
 *
 * @author     Administrator
 * @created    19 February 2004
 */
public class F extends JFrame  implements AWTEventListener, ActionListener {

      private void setGui() {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JButton button = new JButton("Click me");
            button.addActionListener(this);
            JPanel buttonPanel = new JPanel();
            buttonPanel.add(button);
            Container c = getContentPane();
            c.add(buttonPanel);
            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK );
            setSize(200, 200);
      }
      
      public void eventDispatched(AWTEvent event) {
            System.out.println("AWTEvent heard: " + event.paramString());
      }

      public void actionPerformed(ActionEvent event) {
            System.out.println("ActionEvent heard: " + event.paramString());
      }
      
      public static void main(String[] args) {
            F f = new F();
            f.setGui();
            f.setVisible(true);
      }
}


0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
>> Detecting inactivity

I hope the question's title is not indicative of the questioner's intent! If that makes sense ;)
0
 

Author Comment

by:asimalp
Comment Utility
Dear krakatoa, CEHJ, objects and orangehead911,

Thank you very much for all your comments.  I definetely wasn't expecting such feedback especially over the weekend.  Sorry for my "inactivity" on the issue.  I just noticed all your messages.

krakatoa and CEHJ.  I tried using listeners, however listeners only work within the boundaries of my active Java Application.  My main problem is to detect inactivity when the user is actually working on some other applications.  You know messenger applications like ICQ and AIM...  They spend most of their time in the background until the user starts chatting with someone.  The chat application that I'm implementing will be automatically linked to our company's live tech support line.  If there are no tech people using their computers, then the live tech support system should automatically turn off.  So we basically don't want to have any accidents in which one of our customers send us a message, and we miss it...

objects and orangehead911.  I think you are on the right track about the use of JNI.  This is what I was suspecting to begin with; however I have no idea as to how I can use JNI?  This chat application will be working on Windows and Mac OS X.  Any ideas as to how I can hook into the operating system event queue?

Thank you very much!

Asim
0
 
LVL 14

Assisted Solution

by:Tommy Braas
Tommy Braas earned 75 total points
Comment Utility
I haven't personally hooked into the system event loop, but it should be failry straight forward.

This might be a good starting point for Mac OS X:
http://developer.apple.com/documentation/CoreFoundation/EventsOtherInput-date.html

Here's something possibly useful for Windows:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msaa/msaaccrf_87ja.asp
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
I don't quite follow this. You seem to want to detect inactivity in the entire system, in which case you *will* need to use native code, and in Windows, this will probably centre around SetWindowsHookEx.

This is not such a good idea for several reasons:

a. hooking into Windows message queues is potentially troublesome if you get it wrong, can slow the system down and face it, would be troublesome if you got it right anyway
b. Surely if they're not using your app, then they're inactive anyway? OK - you could say the system may be quiet and they're doing other work. That's fine, but wouldn't it be better to give them a 'dead man's handle' hoop to jump through? (i'm sure management will love that ;-)). It means that if they don't register their presence at regular intervals with your app by providing input of any kind, they are effectively absent. API problem solved and they're on their toes LOL
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
I agree with CEHJ. Since when has it anyway been the case that inactivity in one app means that the user is not present on the system somwhere else? If you want to detect inactivity in the java chat application, you can do it as previously described. Or is this question just a joke, like so many that get posted here?
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
>> Since when has it anyway been the case that inactivity in one app means that the user is not present on the system somwhere else? ...

by which I mean of course that it sounds like you need 2 computers for each employee - one to do real work, and one to keep you happy.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
Your premises are incorrect I would venture to say. You wrote :

"My main problem is to detect inactivity when the user is actually working on some other applications.  You know messenger applications like ICQ and AIM...  They spend most of their time in the background until the user starts chatting with someone.  The chat application that I'm implementing will be automatically linked to our company's live tech support line.  If there are no tech people using their computers, then the live tech support system should automatically turn off.  So we basically don't want to have any accidents in which one of our customers send us a message, and we miss it..."

a) How can a user be "inactive" when he is working on some other applications? If he souldn't be working on the other apps, then they shouldnt be on his PC.
b) If no tech people are "using their computers", then there is nothing to detect anyway;
c) Why would you want to turn it off? On the face of it this makes little sense.
d) What accidents? You mean people ignoring incoming requests, right? If so, that should be handled differently.

It seems to me that what you want is a system that detect inactivity in your app *as well as* in all other apps. That's maybe where you need JNI, although you are going to have a lot of fun when people go to staggered lunch breaks - should make a nice switch case block somewhere.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
Your best bet is to write threads into your app which launch the other apps via Runtime.exec()'s and hover on waitFor's. That way, you'll know exactly when each user started and stopped an app. Then you can get your java to pop a message on to the techie's screen every so often, to the effect of "If you dont type something soon, clear your desk at 5:00 tonight".
0
 
LVL 14

Assisted Solution

by:Tommy Braas
Tommy Braas earned 75 total points
Comment Utility
That last suggestion krakatoa is not a very good one. I am sure that there are plenty examples on the net describing how to register and listen for system event queue events. It might not be trivial, as CEHJ has alluded to, but not insurmountable I am sure.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
Well I dont know why it wouldnt be a good one - not that I meant it very seriously in the first place though, as I think the question has unrealistic expectations.
0
 
LVL 92

Assisted Solution

by:objects
objects earned 375 total points
Comment Utility
The question is totally realistic, and many other applications have implemented exactly the same thing.
But you cannot implement it in Java without use of JNI, I'd suggest asking in Window/Mac programming topics for the native code involved. Once you've got that using JNI to integrate with Java is fairly straight forward.
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
>>I'd suggest asking in Window/Mac programming topics for the native code involved.

I can give you that native code, but it's not necessary, nor probably desirable
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
>> and many other applications have implemented exactly the same thing ...

when I said unrealistic, I didnt mean technically. I think you are missing the picture here objects; computers are meant to serve people, not the other way 'round. You may well be able to detect inactivity across the whole system, but what does that tell you? If you applied the same principle to the classic bank teller's problem - which people have tried to do in the past - then you end up with a system that deceives itself into believing its own lies - ie that there are enough resources to cater for demand, or, vice versa, that there are not.

The way an away flag should be raised is by the computer user himself, not by some arbitrary piece of code taking that decision away from the user. There is no argument for automatiing an inactivity flag that could ever handle all the eventualities that occur in real life that would amount to a jot.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
Of course, the chickens only come home to roost on a question like this when a manager has a client; then, the manager wants his cake and eat it too - he wants to see all the traffic, but doesnt have anything to add, unless and until some situation requires intervention, in which case he's probably going to pick the bone with the techie afterwards offline. Of course, he'll want a much longer timeout on his client in order to be able to do this. :)). LOL.
0
 
LVL 16

Expert Comment

by:krakatoa
Comment Utility
Anyway, the operating system already has an inactivity detector built in - its called the screen saver.
0
 
LVL 92

Accepted Solution

by:
objects earned 375 total points
Comment Utility
here's the windows code:

static HANDLE hMapObject = NULL;
static DWORD *lastTime = NULL;
static HHOOK keyHook = NULL;
static HHOOK mouseHook = NULL;

static
DWORD*
SetupSharedMemory()
{
     // Set up the shared memory.
     hMapObject = CreateFileMapping(
          (HANDLE) 0xFFFFFFFF, // use paging file
          NULL,                // no security attributes
          PAGE_READWRITE,      // read/write access
          0,                   // size: high 32-bits
          sizeof(DWORD),       // size: low 32-bits
          "timermem"); // name of map object

     if (hMapObject == NULL)
          return NULL;
     
     // The first process to attach initializes memory.
     bool fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
     
     // Get a pointer to the file-mapped shared memory.
     lastTime = (DWORD*) MapViewOfFile(
          hMapObject,     // object to map view of
          FILE_MAP_WRITE, // read/write access
          0,              // high offset:  map from
          0,              // low offset:   beginning
          0);             // default: map entire file

     if (lastTime == NULL)
          return NULL;
     
     *lastTime = GetTickCount();

     return lastTime;
}


LRESULT
CALLBACK
KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
     if (code < 0)
          return CallNextHookEx(keyHook, code, wParam, lParam);

     if (lastTime == NULL)
          lastTime = SetupSharedMemory();

     if (lastTime)
          *lastTime = GetTickCount();

     return 0;
}


LRESULT
CALLBACK
MouseProc(int code, WPARAM wParam, LPARAM lParam)
{
     if (code < 0)
          return CallNextHookEx(mouseHook, code, wParam, lParam);

     if (lastTime == NULL)
          lastTime = SetupSharedMemory();

     if (lastTime)
          *lastTime = GetTickCount();

     return 0;
}


DWORD
GetCurrentTime()
{
     return GetTickCount();
}


DWORD
GetLastActiveTime()
{
     if (lastTime == NULL)
          lastTime = SetupSharedMemory();

     if (lastTime)
          return *lastTime;
     
     return 0;
}


BOOL
SetHooks()
{
     // Set up the shared memory.
     lastTime = SetupSharedMemory();
     if (lastTime == NULL)
          return FALSE;
     *lastTime = GetTickCount();

     // Set up the keyboard hook.
     keyHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, theApp.m_hInstance, NULL);
     if (keyHook == NULL)
     {
          UnmapViewOfFile(lastTime);
          CloseHandle(hMapObject);
          return false;
     }

     // Set up the mouse hook.
     mouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, theApp.m_hInstance, NULL);
     if (mouseHook == NULL)
     {
          UnhookWindowsHookEx(keyHook);
          UnmapViewOfFile(lastTime);
          CloseHandle(hMapObject);
          return FALSE;
     }

     return TRUE;
}


void
RemoveHooks()
{
     if (keyHook)
          UnhookWindowsHookEx(keyHook);
     if (mouseHook)
          UnhookWindowsHookEx(mouseHook);
     if (lastTime)
          UnmapViewOfFile(lastTime);
     if (hMapObject)
          CloseHandle(hMapObject);
}

0
 

Author Comment

by:asimalp
Comment Utility
objects, thank you very much for the code you have provided!  I think this is the solution to our problem.  Now, I'll just go ahead and figure out JNI to hook-up this code to my Java program.

orangehead911, thank you very much for the links and all the input.

CEHJ, thank you very much for your comments and the code piece you have provided.

krakatoa, the main problem is this:  8 am in the morning, tech people come to work.  Turn on their chat applications.  Then they start doing whatever they need to do (write programs, design websites, write HTML code, answer support emails...).  During this time, from time to time, chat application pops up with questions from our customers.  Of course, the support people answer these questions...  At lunch time however, when they are all away from their computers (eating lunch), they might forget the turn off the chat application that usually runs in the background.  In that case, our customers might still send messages, but this time there is no one to reply...  The same case applies when the support people leave office at 6 pm...  We happen to leave all our computers on through out the night.  Anyway, there is no reason to get very philosophical and question the need for such a program.  We need this feature simply because the company officials want it.  I personally think it makes sense.  But I do respect your opinion.  Thank you very much for all your input.
0
 
LVL 14

Expert Comment

by:Tommy Braas
Comment Utility
My pleasure! =-)
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
8-)
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now