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:
@@ -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