Initial version of linux (working) and Windows (not yet working) native
libraries for enabling and disabling keyboard auto-repeat. Restored auto-repeating in our own KeyboardManager, and disabled the interval used to differentiate between a "real" and "fake" key repeat since we believe we can now do without it. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2107 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
//
|
//
|
||||||
// $Id: KeyboardManager.java,v 1.14 2002/11/08 08:17:35 ray Exp $
|
// $Id: KeyboardManager.java,v 1.15 2003/01/12 00:26:39 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.util;
|
package com.threerings.util;
|
||||||
|
|
||||||
import java.awt.KeyEventDispatcher;
|
import java.awt.KeyEventDispatcher;
|
||||||
import java.awt.KeyboardFocusManager;
|
import java.awt.KeyboardFocusManager;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.KeyAdapter;
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.event.WindowFocusListener;
|
import java.awt.event.WindowFocusListener;
|
||||||
@@ -24,6 +24,8 @@ import com.samskivert.util.Interval;
|
|||||||
import com.samskivert.util.IntervalManager;
|
import com.samskivert.util.IntervalManager;
|
||||||
import com.samskivert.util.ObserverList;
|
import com.samskivert.util.ObserverList;
|
||||||
|
|
||||||
|
import com.threerings.util.keybd.Keyboard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The keyboard manager observes keyboard actions on a particular
|
* The keyboard manager observes keyboard actions on a particular
|
||||||
* component and posts commands associated with the key presses to the
|
* component and posts commands associated with the key presses to the
|
||||||
@@ -130,14 +132,23 @@ public class KeyboardManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
// clear out any previous management we were engaged in
|
if (Keyboard.isAvailable()) {
|
||||||
|
// restore the original key auto-repeat settings
|
||||||
|
Keyboard.setKeyRepeat(_nativeRepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out all of our key states
|
||||||
releaseAllKeys();
|
releaseAllKeys();
|
||||||
_keys.clear();
|
_keys.clear();
|
||||||
|
|
||||||
|
// cease listening to all of our business
|
||||||
if (_window != null) {
|
if (_window != null) {
|
||||||
_window.removeWindowFocusListener(this);
|
_window.removeWindowFocusListener(this);
|
||||||
_window = null;
|
_window = null;
|
||||||
}
|
}
|
||||||
_target.removeAncestorListener(this);
|
_target.removeAncestorListener(this);
|
||||||
|
|
||||||
|
// note that we no longer have the focus
|
||||||
_focus = false;
|
_focus = false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -157,6 +168,15 @@ public class KeyboardManager
|
|||||||
|
|
||||||
// assume the keyboard focus since we were just enabled
|
// assume the keyboard focus since we were just enabled
|
||||||
_focus = true;
|
_focus = true;
|
||||||
|
|
||||||
|
if (Keyboard.isAvailable()) {
|
||||||
|
// note whether key auto-repeating was enabled
|
||||||
|
_nativeRepeat = Keyboard.isKeyRepeatEnabled();
|
||||||
|
|
||||||
|
// disable native key auto-repeating so that we can
|
||||||
|
// definitively ascertain key pressed/released events
|
||||||
|
Keyboard.setKeyRepeat(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save off our new enabled state
|
// save off our new enabled state
|
||||||
@@ -201,6 +221,12 @@ public class KeyboardManager
|
|||||||
*/
|
*/
|
||||||
protected void gainedFocus ()
|
protected void gainedFocus ()
|
||||||
{
|
{
|
||||||
|
if (Keyboard.isAvailable()) {
|
||||||
|
// disable key auto-repeating
|
||||||
|
Keyboard.setKeyRepeat(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// note that we've regained the focus
|
||||||
_focus = true;
|
_focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +236,14 @@ public class KeyboardManager
|
|||||||
*/
|
*/
|
||||||
protected void lostFocus ()
|
protected void lostFocus ()
|
||||||
{
|
{
|
||||||
|
if (Keyboard.isAvailable()) {
|
||||||
|
// restore key auto-repeating
|
||||||
|
Keyboard.setKeyRepeat(_nativeRepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out all of our keyboard state
|
||||||
releaseAllKeys();
|
releaseAllKeys();
|
||||||
|
// note that we no longer have the focus
|
||||||
_focus = false;
|
_focus = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,19 +414,19 @@ public class KeyboardManager
|
|||||||
_lastPress = time;
|
_lastPress = time;
|
||||||
_lastRelease = time;
|
_lastRelease = time;
|
||||||
|
|
||||||
// if (_iid == -1) {
|
if (_iid == -1) {
|
||||||
// // register an interval to post the command associated
|
// register an interval to post the command associated
|
||||||
// // with the key press until the key is decidedly released
|
// with the key press until the key is decidedly released
|
||||||
// _iid = IntervalManager.register(this, _pressDelay, null, true);
|
_iid = IntervalManager.register(this, _pressDelay, null, true);
|
||||||
// if (DEBUG_EVENTS) {
|
if (DEBUG_EVENTS) {
|
||||||
// Log.info("Pressing key [key=" + _keyText + "].");
|
Log.info("Pressing key [key=" + _keyText + "].");
|
||||||
// }
|
}
|
||||||
|
|
||||||
if (_pressCommand != null) {
|
if (_pressCommand != null) {
|
||||||
// post the initial key press command
|
// post the initial key press command
|
||||||
postPress(time);
|
postPress(time);
|
||||||
}
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,33 +435,33 @@ public class KeyboardManager
|
|||||||
public synchronized void setReleaseTime (long time)
|
public synchronized void setReleaseTime (long time)
|
||||||
{
|
{
|
||||||
release(time);
|
release(time);
|
||||||
// _lastRelease = time;
|
_lastRelease = time;
|
||||||
|
|
||||||
// // handle key release events received so quickly after the key
|
// handle key release events received so quickly after the key
|
||||||
// // press event that the press/release times are exactly equal
|
// press event that the press/release times are exactly equal
|
||||||
// // and, in intervalExpired(), we would therefore be unable to
|
// and, in intervalExpired(), we would therefore be unable to
|
||||||
// // distinguish between the key being initially pressed and the
|
// distinguish between the key being initially pressed and the
|
||||||
// // actual true key release that's taken place.
|
// actual true key release that's taken place.
|
||||||
|
|
||||||
// // the only case I can think of that might result in this
|
// the only case I can think of that might result in this
|
||||||
// // happening is if the event manager class queues up a key
|
// happening is if the event manager class queues up a key
|
||||||
// // press and release event succession while other code is
|
// press and release event succession while other code is
|
||||||
// // executing, and when it comes time for it to dispatch the
|
// executing, and when it comes time for it to dispatch the
|
||||||
// // events in its queue it manages to dispatch both of them to
|
// events in its queue it manages to dispatch both of them to
|
||||||
// // us really-lickety-split. one would still think at least a
|
// us really-lickety-split. one would still think at least a
|
||||||
// // few milliseconds should pass between the press and release,
|
// few milliseconds should pass between the press and release,
|
||||||
// // but in any case, we arguably ought to be watching for and
|
// but in any case, we arguably ought to be watching for and
|
||||||
// // handling this case for posterity even though it would seem
|
// handling this case for posterity even though it would seem
|
||||||
// // unlikely or impossible, and so, now we do, which is a good
|
// unlikely or impossible, and so, now we do, which is a good
|
||||||
// // thing since it appears this does in fact happen, and not so
|
// thing since it appears this does in fact happen, and not so
|
||||||
// // infrequently.
|
// infrequently.
|
||||||
// if (_lastPress == _lastRelease) {
|
if (_lastPress == _lastRelease) {
|
||||||
// if (DEBUG_EVENTS) {
|
if (DEBUG_EVENTS) {
|
||||||
// Log.warning("Insta-releasing key due to equal key " +
|
Log.warning("Insta-releasing key due to equal key " +
|
||||||
// "press/release times [key=" + _keyText + "].");
|
"press/release times [key=" + _keyText + "].");
|
||||||
// }
|
}
|
||||||
// release(time);
|
release(time);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -438,9 +471,9 @@ public class KeyboardManager
|
|||||||
public synchronized void release (long timestamp)
|
public synchronized void release (long timestamp)
|
||||||
{
|
{
|
||||||
// bail if we're not currently pressed
|
// bail if we're not currently pressed
|
||||||
// if (_iid == -1) {
|
if (_iid == -1) {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
if (DEBUG_EVENTS) {
|
if (DEBUG_EVENTS) {
|
||||||
Log.info("Releasing key [key=" + _keyText + "].");
|
Log.info("Releasing key [key=" + _keyText + "].");
|
||||||
@@ -484,21 +517,21 @@ public class KeyboardManager
|
|||||||
// we're certain the key is now up, or (c) repeat the key
|
// we're certain the key is now up, or (c) repeat the key
|
||||||
// command if we're certain the key is still down
|
// command if we're certain the key is still down
|
||||||
if (_lastRelease != _lastPress) {
|
if (_lastRelease != _lastPress) {
|
||||||
if (deltaRelease < _repeatDelay) {
|
// if (deltaRelease < _repeatDelay) {
|
||||||
// register a one-shot sub-interval to
|
// // register a one-shot sub-interval to
|
||||||
// definitively check whether the key was released
|
// // definitively check whether the key was released
|
||||||
long delay = _repeatDelay - deltaRelease;
|
// long delay = _repeatDelay - deltaRelease;
|
||||||
_siid = IntervalManager.register(
|
// _siid = IntervalManager.register(
|
||||||
this, delay, new Long(_lastPress), false);
|
// this, delay, new Long(_lastPress), false);
|
||||||
if (KeyboardManager.DEBUG_INTERVAL) {
|
// if (KeyboardManager.DEBUG_INTERVAL) {
|
||||||
Log.info("Registered sub-interval " +
|
// Log.info("Registered sub-interval " +
|
||||||
"[id=" + _siid + "].");
|
// "[id=" + _siid + "].");
|
||||||
}
|
// }
|
||||||
|
|
||||||
} else {
|
// } else {
|
||||||
// we know the key was released, so cease repeating
|
// we know the key was released, so cease repeating
|
||||||
release(now);
|
release(now);
|
||||||
}
|
// }
|
||||||
|
|
||||||
} else if (_pressCommand != null) {
|
} else if (_pressCommand != null) {
|
||||||
// post the key press command again
|
// post the key press command again
|
||||||
@@ -663,4 +696,8 @@ public class KeyboardManager
|
|||||||
|
|
||||||
/** The operation used to notify observers of actual key events. */
|
/** The operation used to notify observers of actual key events. */
|
||||||
protected KeyObserverOp _keyOp = new KeyObserverOp();
|
protected KeyObserverOp _keyOp = new KeyObserverOp();
|
||||||
|
|
||||||
|
/** Whether native key auto-repeating was enabled when the keyboard
|
||||||
|
* manager was last enabled. */
|
||||||
|
protected boolean _nativeRepeat;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// $Id: Keyboard.java,v 1.1 2003/01/12 00:26:39 shaper Exp $
|
||||||
|
|
||||||
|
package com.threerings.util.keybd;
|
||||||
|
|
||||||
|
import com.threerings.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the native operating system's auto-repeat keyboard
|
||||||
|
* settings.
|
||||||
|
*/
|
||||||
|
public class Keyboard
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sets whether key auto-repeating is enabled.
|
||||||
|
*/
|
||||||
|
public static native void setKeyRepeat (boolean enabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether key auto-repeating is enabled.
|
||||||
|
*/
|
||||||
|
public static native boolean isKeyRepeatEnabled ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests keyboard functionality.
|
||||||
|
*/
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
boolean enabled = (args.length > 0 && args[0].equals("on"));
|
||||||
|
Keyboard.setKeyRepeat(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the native keyboard interface is available.
|
||||||
|
*/
|
||||||
|
public static boolean isAvailable ()
|
||||||
|
{
|
||||||
|
return _haveLib;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether the keyboard native library was successfully loaded. */
|
||||||
|
protected static boolean _haveLib;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("keybd");
|
||||||
|
_haveLib = true;
|
||||||
|
Log.info("Loaded native keyboard library.");
|
||||||
|
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
Log.warning("Failed to load native keyboard library " +
|
||||||
|
"[e=" + e + "].");
|
||||||
|
_haveLib = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||||
|
#include <jni.h>
|
||||||
|
/* Header for class com_threerings_util_keybd_Keyboard */
|
||||||
|
|
||||||
|
#ifndef _Included_com_threerings_util_keybd_Keyboard
|
||||||
|
#define _Included_com_threerings_util_keybd_Keyboard
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_keybd_Keyboard
|
||||||
|
* Method: setKeyRepeat
|
||||||
|
* Signature: (Z)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_threerings_util_keybd_Keyboard_setKeyRepeat
|
||||||
|
(JNIEnv *, jclass, jboolean);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_keybd_Keyboard
|
||||||
|
* Method: isKeyRepeatEnabled
|
||||||
|
* Signature: ()Z
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_com_threerings_util_keybd_Keyboard_isKeyRepeatEnabled
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1 2003/01/12 00:26:39 shaper Exp $
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
RM=rm
|
||||||
|
|
||||||
|
INCLUDES=-I.. -I/usr/local/jdk1.4/include -I/usr/local/jdk1.4/include/linux
|
||||||
|
LIBRARIES_PATH=-L/usr/X11R6/lib
|
||||||
|
LIBRARIES=-lX11
|
||||||
|
TARGET=libkeybd.so
|
||||||
|
|
||||||
|
all: ${TARGET}
|
||||||
|
|
||||||
|
${TARGET}: com_threerings_util_keybd_Keyboard.c
|
||||||
|
${CC} ${INCLUDES} -c com_threerings_util_keybd_Keyboard.c \
|
||||||
|
-o com_threerings_util_keybd_Keyboard.o
|
||||||
|
${CC} -o ${TARGET} com_threerings_util_keybd_Keyboard.o \
|
||||||
|
${LIBRARIES} ${LIBRARIES_PATH} -shared
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-${RM} *.o
|
||||||
|
-${RM} ${TARGET}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* $Id: com_threerings_util_keybd_Keyboard.c,v 1.1 2003/01/12 00:26:39 shaper Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include "com_threerings_util_keybd_Keyboard.h"
|
||||||
|
|
||||||
|
/* defines */
|
||||||
|
#define MESSAGE_LENGTH (256)
|
||||||
|
|
||||||
|
/* prototype definitions */
|
||||||
|
Display* getXDisplay (JNIEnv* env);
|
||||||
|
void throwRuntimeException (JNIEnv* env, char* message);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_keybd_Keyboard_setKeyRepeat (
|
||||||
|
JNIEnv* env, jclass class, jboolean enabled)
|
||||||
|
{
|
||||||
|
Display* display = getXDisplay(env);
|
||||||
|
if (display == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the desired key auto-repeat state. */
|
||||||
|
if (enabled) {
|
||||||
|
XAutoRepeatOn(display);
|
||||||
|
} else {
|
||||||
|
XAutoRepeatOff(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the display to save our changes */
|
||||||
|
XCloseDisplay(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_threerings_util_keybd_Keyboard_isKeyRepeatEnabled (
|
||||||
|
JNIEnv* env, jclass class)
|
||||||
|
{
|
||||||
|
XKeyboardState values;
|
||||||
|
Display* display = getXDisplay(env);
|
||||||
|
if (display == NULL) {
|
||||||
|
/* for now, assume auto-repeat is enabled */
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the current keyboard control information */
|
||||||
|
XGetKeyboardControl(display, &values);
|
||||||
|
|
||||||
|
/* close the display */
|
||||||
|
XCloseDisplay(display);
|
||||||
|
|
||||||
|
return (values.global_auto_repeat) ? JNI_TRUE : JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a pointer to the X display, or null if an error occurred.
|
||||||
|
*/
|
||||||
|
Display*
|
||||||
|
getXDisplay (JNIEnv* env)
|
||||||
|
{
|
||||||
|
char* disp = NULL;
|
||||||
|
Display* dpy = XOpenDisplay(disp);
|
||||||
|
if (dpy == NULL) {
|
||||||
|
char message[MESSAGE_LENGTH];
|
||||||
|
snprintf(message, MESSAGE_LENGTH,
|
||||||
|
"Unable to open display [display=%s].\n", XDisplayName(disp));
|
||||||
|
throwRuntimeException(env, message);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printf("Opened display [disp=%s].\n", XDisplayName(disp)); */
|
||||||
|
return dpy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Throws a runtime exception with the supplied message.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
throwRuntimeException (JNIEnv* env, char* message)
|
||||||
|
{
|
||||||
|
jclass eclass = (*env)->FindClass(env, "java/lang/RuntimeException");
|
||||||
|
if (eclass == 0) {
|
||||||
|
/* unable to find the exception class */
|
||||||
|
fprintf(stderr, "Can't get runtime exception class?! [message=%s].\n",
|
||||||
|
message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*env)->ThrowNew(env, eclass, message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1 2003/01/12 00:26:39 shaper Exp $
|
||||||
|
|
||||||
|
CROSSTOOLS_PATH=/usr/local/cross-tools
|
||||||
|
MINGW_PATH=${CROSSTOOLS_PATH}/i386-mingw32msvc
|
||||||
|
WIN32API_PATH=${CROSSTOOLS_PATH}/w32api
|
||||||
|
|
||||||
|
CC=${MINGW_PATH}/bin/gcc
|
||||||
|
RM=rm
|
||||||
|
|
||||||
|
INCLUDES=-I.. -I/usr/local/jdk1.4/include -I/usr/local/jdk1.4/include/linux \
|
||||||
|
-I${CROSSTOOLS_PATH}/include -I${WIN32API_PATH}/include
|
||||||
|
LIBRARIES_PATH=-L${CROSSTOOLS_PATH}/lib -L${WIN32API_PATH}/lib
|
||||||
|
LIBRARIES=
|
||||||
|
TARGET=keybd.dll
|
||||||
|
|
||||||
|
all: ${TARGET}
|
||||||
|
|
||||||
|
${TARGET}: com_threerings_util_keybd_Keyboard.c
|
||||||
|
${CC} ${INCLUDES} -c com_threerings_util_keybd_Keyboard.c \
|
||||||
|
-o com_threerings_util_keybd_Keyboard.o
|
||||||
|
${CC} -o ${TARGET} com_threerings_util_keybd_Keyboard.o \
|
||||||
|
${LIBRARIES} ${LIBRARIES_PATH} -shared
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-${RM} *.o
|
||||||
|
-${RM} ${TARGET}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* $Id: com_threerings_util_keybd_Keyboard.c,v 1.1 2003/01/12 00:26:39 shaper Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include "com_threerings_util_keybd_Keyboard.h"
|
||||||
|
|
||||||
|
/* prototype definitions */
|
||||||
|
LRESULT CALLBACK KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT CALLBACK LowLevelKeyboardProc (int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
/* static global variables */
|
||||||
|
static HHOOK gKeyHook;
|
||||||
|
static HINSTANCE gHInst;
|
||||||
|
|
||||||
|
BOOL WINAPI
|
||||||
|
DllMain (HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
|
||||||
|
{
|
||||||
|
/* save off our instance handle */
|
||||||
|
fprintf(stderr, "In DllMain.\n");
|
||||||
|
gHInst = (HINSTANCE)hinstDLL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_keybd_Keyboard_setKeyRepeat (
|
||||||
|
JNIEnv* env, jclass class, jboolean enabled)
|
||||||
|
{
|
||||||
|
if (enabled) {
|
||||||
|
if (gKeyHook != NULL) {
|
||||||
|
fprintf(stderr, "Removing windows keyboard hook.\n");
|
||||||
|
/* remove the keyboard hook */
|
||||||
|
UnhookWindowsHookEx(gKeyHook);
|
||||||
|
gKeyHook = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* install the hook with which we usurp all keyboard events */
|
||||||
|
/* gKeyHook = SetWindowsHookEx( */
|
||||||
|
/* WH_KEYBOARD_LL, LowLevelKeyboardProc, hinstExe, 0); */
|
||||||
|
|
||||||
|
fprintf(stderr, "Setting windows keyboard hook.\n");
|
||||||
|
gKeyHook = SetWindowsHookEx(
|
||||||
|
WH_KEYBOARD, KeyboardProc, gHInst, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_threerings_util_keybd_Keyboard_isKeyRepeatEnabled (
|
||||||
|
JNIEnv* env, jclass class)
|
||||||
|
{
|
||||||
|
/* since windows has no global key repeat enable/disable facility, we
|
||||||
|
* simply always return true here so that we'll be sure to "re-enable"
|
||||||
|
* key repeat, which will result in our properly removing the keyboard
|
||||||
|
* hook with which we trap key events. */
|
||||||
|
fprintf(stderr, "isKeyRepeatEnabled stderr.\n");
|
||||||
|
printf("isKeyRepeatEnabled stdout.\n");
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The keyboard event hook that eats all repeated keystrokes.
|
||||||
|
*/
|
||||||
|
LRESULT CALLBACK
|
||||||
|
KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
int repeatCount = (lParam & KF_REPEAT);
|
||||||
|
fprintf(stderr, "Key down [key=%d, repeatCount=%d].\n",
|
||||||
|
wParam, repeatCount);
|
||||||
|
return (repeatCount > 1) ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The low-level keyboard event hook that eats all keystrokes.
|
||||||
|
*/
|
||||||
|
LRESULT CALLBACK
|
||||||
|
LowLevelKeyboardProc (int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
BOOL fEatKeystroke = FALSE;
|
||||||
|
|
||||||
|
if (nCode == HC_ACTION) {
|
||||||
|
switch (wParam) {
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
|
||||||
|
fEatKeystroke =
|
||||||
|
((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
|
||||||
|
((p->vkCode == VK_ESCAPE) &&
|
||||||
|
((p->flags & LLKHF_ALTDOWN) != 0)) ||
|
||||||
|
((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) &
|
||||||
|
0x8000) != 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (fEatKeystroke) ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user