Solved

Detecting inactivity

Posted on 2004-04-02
30
740 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 13
  • 7
  • 4
  • +2
30 Comments
 
LVL 17

Expert Comment

by:krakatoa
ID: 10745019
>>  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 17

Expert Comment

by:krakatoa
ID: 10745038
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
ID: 10745041
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
The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

 
LVL 17

Expert Comment

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

Expert Comment

by:CEHJ
ID: 10745073
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
ID: 10745419
You can't, (without the use of JNI of course)
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10745457
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
ID: 10746548
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 17

Expert Comment

by:krakatoa
ID: 10746885
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
ID: 10747361
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 17

Expert Comment

by:krakatoa
ID: 10748940
>> 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
ID: 10757829
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
ID: 10758813
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
ID: 10760206
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 17

Expert Comment

by:krakatoa
ID: 10760270
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
 
LVL 17

Expert Comment

by:krakatoa
ID: 10760332
>> 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 17

Expert Comment

by:krakatoa
ID: 10760469
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 17

Expert Comment

by:krakatoa
ID: 10760613
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
ID: 10761040
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 17

Expert Comment

by:krakatoa
ID: 10761358
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
ID: 10761408
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
ID: 10761553
>>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 17

Expert Comment

by:krakatoa
ID: 10761643
>> 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 17

Expert Comment

by:krakatoa
ID: 10761671
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 17

Expert Comment

by:krakatoa
ID: 10761679
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
ID: 10762737
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
ID: 10769965
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
ID: 10770041
My pleasure! =-)
0
 
LVL 92

Expert Comment

by:objects
ID: 10770567
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10770813
8-)
0

Featured Post

Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

689 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