0

I have a thread which impelments JNativeHook.jar which creates a global keybourd and mouse listener. Based on user input the thread can act as such.

I would like to stop all Thread execution when a user (let's say) presses VK_SPACE. I would want to spawn another Thread which also watches the keyboard, and when it gets a VK_SPACE again it will tell the main Thread to resume.

Is this sort of action possible in Java, and how might it look?

Here is some code to work with and JNativeHook.jar

CODE:

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

public class GlobalKeyListenerExample implements NativeKeyListener 
{
public void nativeKeyPressed(NativeKeyEvent e) 
{
    System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

    if (e.getKeyCode() == NativeKeyEvent.VK_ESCAPE) 
    {
        GlobalScreen.unregisterNativeHook();
    }
    if (e.getKeyCode() == NativeKeyEvent.VK_SPACE) 
    {
            WatchForMe w = new WatchForMe(this);
            w.start();
            this.wait();
    }
}

public void nativeKeyReleased(NativeKeyEvent e){}
public void nativeKeyTyped(NativeKeyEvent e){}

public static void main(String[] args) 
{
    try 
    {
        GlobalScreen.registerNativeHook();
    }
    catch (NativeHookException ex) 
    {
        System.err.println("There was a problem registering the native hook.");
        System.exit(1);
    }

    //Construct the example object and initialze native hook.
    GlobalScreen.getInstance().addNativeKeyListener(new GlobalKeyListenerExample());
}
}

public class WatchForMe implements NativeKeyListener 
{
boolean alive = true;
Thread me = null;
public WatchForMe(Thread me)
{
    if(me == null) return;
    this.me = me;
    GlobalScreen.getInstance().addNativeKeyListener(this);
}
public void nativeKeyPressed(NativeKeyEvent e) 
{
        System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
        if (e.getKeyCode() == NativeKeyEvent.VK_SPACE) 
        {
                me.notify(); 
                alive = false;
        }
}
 public void run()
 {
     while(alive){}
 }

public void nativeKeyReleased(NativeKeyEvent e){}
public void nativeKeyTyped(NativeKeyEvent e){}
}

2 Answers2

0

Instead of running around trying to lock on different monitors and stuff, I would, personally, place a flag in GlobalKeyListenerExample that would, when a certain key combination is detected, start ignoring any more incoming keys until a certain key combination was raised.

The problem you face currently is knowing 1- What thread you are in and what effect "pausing" it might have and 2- Knowing when the "un-pause" combination is raised...cause you're no longer listening to key events (because you may have inadvertently stopped the thread that the native interface was using to raise the events with...)

public void nativeKeyPressed(NativeKeyEvent e) 
{
    System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

    if (isPaused) {
        if (e.getKeyCode == UNPAUSE_KEY_CODE) { 
            isPaused = false;
        }
    } else {
        if (e.getKeyCode == PAUSE_KEY_CODE) { 
            isPaused = true;
        } else {
            // Handle other key strokes...
        }
    }
}

Updated

Just as a side note...this

public void run()
{
    while(alive){}
}

Isn't a good idea. Basically, it leaves the thread in "running" state, consuming CPU cycles unnecessarily. In your case, I'm not sure how you would actually be able to correct for it...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I used the main method in GlobalKeyListenerExample for examples sake, I use a constructor in my actual program I am just trying to get an idea of how to do this. –  Jan 30 '13 at 03:32
  • What what I can gather, `JNativeHook` is using a single thread for event dispatching (it's possible the mouse and keyboard events are dispatched from separate threads) - This means that if you block the thread, it will no longer be able to deliver any more threads to ANY registered listener. This, of course, would require additional testing – MadProgrammer Jan 30 '13 at 03:37
0

in method run:

public void run(){
 while(me!=null) //execute forever
   try{
      Thread.sleep(5);
      if(!alive) continue; //define pause

      ... do somthing   
   catch(Exception e){}

We need to "thread" stay all the time checking on whether this "pause".

Important! is recommended to use a method public synchronized void setAlive (boolean value) to avoid conflicts of "thread"

Edgard Leal
  • 2,592
  • 26
  • 30