0

Working on a new personal project with . My goal is to close the frame in an ActionListener to the background, and when specific keys are pressed (Ctrl+Shft+L), I want to open the frame back up.

I'm not sure how I can do this keeping CPU usage low. I know I can set the frames visibility to false and then probably use a generic ActionListener for the keys however I have a few problems (and questions).

  1. Is this the best way to do it? I'm trying to keep the CPU usage as low as possible.

  2. Will the ActionListener even work while the frame's not visible?

  3. How do I listen to multiple key presses? I have an idea but it doesn't sound like it will work.

Spedwards
  • 4,167
  • 16
  • 49
  • 106

2 Answers2

0

Well, the problem is that java is designed to be platform independent. Too achieve that, there have to be some limitations for the programms written in this programming language. You want to capture keystrokes even if your window/programm doesn't have the focus set on it. In fact what you need to write is some kind of global keylistener. You can't do such things in java. In fact you have to choose a much more machine-oriented programming language like c/c++ to achieve what you want.

In java such stuff is only possible using the Java Native Interface (short JNI). Using JNI it is possible to write a library for hooking the keyevents in for example c/c++ and call the librarys' methods using a java programm.

JNativeHook ( https://github.com/kwhat/jnativehook ) is using this exact approach. But well, i haven't tried this framework so i can't tell if it's working.

But i once used this and it worked fine for me: http://softk.de/opensource/jglobalkeylistener.html

You can just download the source and don't panic even if the site is written in german, the source-code is documented in english and even the comments within the code are in english.

PS: if that doesn't work, it may help you to google for things like "java global keylogger", because thats exactly what a keylogger is doing (well it obviously also logs the keys) and i think there will be much more stuff that may help you.

Greetings, Loki

  • To answer your third question... Windows and Mac are sending one keydown event after another if a key is pressed, so you could just store them in some kind of queue or list and remove them from the list if the keyup even is risen. Linux is somehow annoying because it always sends a keydown-keyup-pair even if the key is still pressed. –  Jul 07 '15 at 16:19
  • `"In java such stuff is only possible using the Java Native Interface (short JNI)."` -- not so. JNA could solve as could hooking Java with an OS-specific scripting language such as AutoIt. – Hovercraft Full Of Eels Jul 08 '15 at 02:20
  • You're right, forgot about JNA while writing my answer. Thanks –  Jul 09 '15 at 20:59
0
  1. Is this the best way to do it? I'm trying to keep the CPU usage as low as possible.

As previously mentioned, use JNativeHook. It is the only cross-platform solution and it will be much faster and less intensive than a polling approach like while (1) { GetAsyncKeyState(...); Sleep(5); } The biggest performance bottleneck with JNativeHook is the OS, not the library.

  1. Will the ActionListener even work while the frame's not visible?

It will not work unless the frame has focus, but the native library will provide other events that do fire out of focus, so you could make it work by fabricating your own ActionEvent's from the NativeInputEvent listeners. Just make sure you set the library to use the Swing event dispatcher as it does not by default!

  1. How do I listen to multiple key presses? I have an idea but it doesn't sound like it will work.

What do you mean by "multiple key presses?" If you mean auto-repeat when a key is held down, that is handled by sending multiple Key Pressed events after the auto repeat delay is exceeded at an interval of the auto repeat rate. You many also receive multiple Key Typed events if that event produces a printable character. When the key is released, a single key release event will be dispatched. If you mean a sequence of keys or multiple keys at the same time, you will need to do your own tracking or checks in the native input listener, but it should be possible.

Basic Modifier Example: Note that JNativeHook library has both a left and right mask for the modifier keys. I assume you want to use a combination of either the left or the right which makes this a tad more complicated.

public void nativeKeyPressed(NativeKeyEvent e) {
    // If the keycode is L
    if (e.getKeyCode() == NativeKeyEvent.VK_L) {
        // We have a shift mask and a control mask for either the left or right key.
        if (e.getModifiers() & NativeInputEvent.SHIFT_MASK && e.getModifiers() & NativeInputEvent.CTRL_MASK) {
            // Make sure you don't have extra modifiers like the meta key.
            if (e.getModifiers() & ~(NativeInputEvent.SHIFT_MASK | NativeInputEvent.CTRL_MASK) == 0x00) {
                ....
            }
        }
    }
}
Alex Barker
  • 4,316
  • 4
  • 28
  • 47