Linux: Moved most input related stuff from native to java

This commit is contained in:
Elias Naur 2006-07-03 18:07:44 +00:00
parent 5671f93656
commit cbe41294a5
16 changed files with 2056 additions and 1353 deletions

View File

@ -450,6 +450,7 @@
<target name="headers" description="invokes javah on java classes" depends="compile">
<!-- platform specific classes -->
<javah classpath="${lwjgl.bin}" destdir="${lwjgl.src.native}/linux" force="yes">
<class name="org.lwjgl.opengl.LinuxMouse" />
<class name="org.lwjgl.opengl.LinuxKeyboard" />
<class name="org.lwjgl.opengl.LinuxDisplay" />
<class name="org.lwjgl.opengl.LinuxPeerInfo" />

View File

@ -47,6 +47,13 @@ import org.lwjgl.LWJGLUtil;
import org.lwjgl.input.Keyboard;
final class LinuxDisplay implements DisplayImplementation {
/* X11 constants */
private final static int GrabSuccess = 0;
private final static int AutoRepeatModeOff = 0;
private final static int AutoRepeatModeOn = 1;
private final static int AutoRepeatModeDefault = 2;
/** Window mode enum */
private static final int FULLSCREEN_LEGACY = 1;
private static final int FULLSCREEN_NETWM = 2;
@ -63,8 +70,6 @@ final class LinuxDisplay implements DisplayImplementation {
/** Current mode swithcing API */
private static int current_displaymode_extension = NONE;
private static final int NUM_BUTTONS = 3;
/** Keep track on the current awt lock owner to avoid
* depending on JAWT locking to be re-entrant (This is a
* problem with GCJ). JAWT locking is not that well specified
@ -86,6 +91,17 @@ final class LinuxDisplay implements DisplayImplementation {
private static DisplayMode saved_mode;
private static DisplayMode current_mode;
private static boolean keyboard_grabbed;
private static boolean pointer_grabbed;
private static boolean input_released;
private static boolean grab;
private static boolean focused;
private static ByteBuffer current_cursor;
private static ByteBuffer blank_cursor;
private static LinuxKeyboard keyboard;
private static LinuxMouse mouse;
private static ByteBuffer getCurrentGammaRamp() throws LWJGLException {
lockAWT();
try {
@ -257,15 +273,113 @@ final class LinuxDisplay implements DisplayImplementation {
return WINDOWED;
}
private static native long getDisplay();
private static native int getScreen();
private static native long getWindow();
private static void ungrabKeyboard() {
if (keyboard_grabbed) {
nUngrabKeyboard(getDisplay());
keyboard_grabbed = false;
}
}
private static native int nUngrabKeyboard(long display);
private static void grabKeyboard() {
if (!keyboard_grabbed) {
int res = nGrabKeyboard(getDisplay(), getWindow());
if (res == GrabSuccess)
keyboard_grabbed = true;
}
}
private static native int nGrabKeyboard(long display, long window);
private static void grabPointer() {
if (!pointer_grabbed) {
int result = nGrabPointer(getDisplay(), getWindow());
if (result == GrabSuccess) {
pointer_grabbed = true;
// make sure we have a centered window
if (isLegacyFullscreen()) {
nSetViewPort(getDisplay(), getWindow(), getScreen());
}
}
}
}
private static native int nGrabPointer(long display, long window);
private static native void nSetViewPort(long display, long window, int screen);
private static void ungrabPointer() {
if (pointer_grabbed) {
pointer_grabbed = false;
nUngrabPointer(getDisplay());
}
}
private static native int nUngrabPointer(long display);
private static boolean isFullscreen() {
return current_window_mode == FULLSCREEN_LEGACY || current_window_mode == FULLSCREEN_NETWM;
}
private static boolean shouldGrab() {
return !input_released && grab;
}
private static void updatePointerGrab() {
if (isFullscreen() || shouldGrab()) {
grabPointer();
} else {
ungrabPointer();
}
updateCursor();
}
private static void updateCursor() {
ByteBuffer cursor;
if (shouldGrab()) {
cursor = blank_cursor;
} else {
cursor = current_cursor;
}
nDefineCursor(getDisplay(), getWindow(), cursor);
}
private static native void nDefineCursor(long display, long window, ByteBuffer cursor_handle);
private static boolean isLegacyFullscreen() {
return current_window_mode == FULLSCREEN_LEGACY;
}
private static void updateKeyboardGrab() {
if (isLegacyFullscreen())
grabKeyboard();
else
ungrabKeyboard();
}
public void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException {
lockAWT();
try {
ByteBuffer handle = peer_info.lockAndGetHandle();
incDisplay();
try {
current_window_mode = getWindowMode(fullscreen);
nCreateWindow(handle, mode, current_window_mode, x, y);
} finally {
peer_info.unlock();
ByteBuffer handle = peer_info.lockAndGetHandle();
try {
current_window_mode = getWindowMode(fullscreen);
nCreateWindow(handle, mode, current_window_mode, x, y);
blank_cursor = createBlankCursor();
current_cursor = null;
focused = true;
input_released = false;
pointer_grabbed = false;
keyboard_grabbed = false;
grab = false;
updateInputGrab();
nSetRepeatMode(getDisplay(), AutoRepeatModeOff);
} finally {
peer_info.unlock();
}
} catch (LWJGLException e) {
decDisplay();
throw e;
}
} finally {
unlockAWT();
@ -273,23 +387,41 @@ final class LinuxDisplay implements DisplayImplementation {
}
private static native void nCreateWindow(ByteBuffer peer_info_handle, DisplayMode mode, int window_mode, int x, int y) throws LWJGLException;
private static void updateInputGrab() {
updatePointerGrab();
updateKeyboardGrab();
}
public void destroyWindow() {
lockAWT();
nDestroyWindow();
unlockAWT();
try {
try {
setNativeCursor(null);
} catch (LWJGLException e) {
LWJGLUtil.log("Failed to reset cursor: " + e.getMessage());
}
nDestroyCursor(blank_cursor);
blank_cursor = null;
ungrabKeyboard();
nDestroyWindow();
nSetRepeatMode(getDisplay(), AutoRepeatModeDefault);
decDisplay();
} finally {
unlockAWT();
}
}
private static native void nDestroyWindow();
public void switchDisplayMode(DisplayMode mode) throws LWJGLException {
lockAWT();
try {
nSwitchDisplayMode(current_displaymode_extension, mode);
nSwitchDisplayMode(getScreen(), current_displaymode_extension, mode);
current_mode = mode;
} finally {
unlockAWT();
}
}
private static native void nSwitchDisplayMode(int extension, DisplayMode mode) throws LWJGLException;
private static native void nSwitchDisplayMode(int screen, int extension, DisplayMode mode) throws LWJGLException;
public void resetDisplayMode() {
lockAWT();
@ -312,7 +444,7 @@ final class LinuxDisplay implements DisplayImplementation {
try {
incDisplay();
try {
return nGetGammaRampLength();
return nGetGammaRampLength(getDisplay(), getScreen());
} catch (LWJGLException e) {
LWJGLUtil.log("Got exception while querying gamma length: " + e);
return 0;
@ -327,7 +459,7 @@ final class LinuxDisplay implements DisplayImplementation {
unlockAWT();
}
}
private static native int nGetGammaRampLength() throws LWJGLException;
private static native int nGetGammaRampLength(long display, int screen) throws LWJGLException;
public void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException {
if (!isXF86VidModeSupported())
@ -338,13 +470,13 @@ final class LinuxDisplay implements DisplayImplementation {
private static void doSetGamma(ByteBuffer native_gamma) throws LWJGLException {
lockAWT();
try {
nSetGammaRamp(native_gamma);
nSetGammaRamp(getScreen(), native_gamma);
current_gamma = native_gamma;
} finally {
unlockAWT();
}
}
private static native void nSetGammaRamp(ByteBuffer gammaRamp) throws LWJGLException;
private static native void nSetGammaRamp(int screen, ByteBuffer gammaRamp) throws LWJGLException;
private static ByteBuffer convertToNativeRamp(FloatBuffer ramp) throws LWJGLException {
return nConvertToNativeRamp(ramp, ramp.position(), ramp.remaining());
@ -406,34 +538,42 @@ final class LinuxDisplay implements DisplayImplementation {
public void setTitle(String title) {
lockAWT();
nSetTitle(title);
unlockAWT();
try {
nSetTitle(title);
} finally {
unlockAWT();
}
}
private static native void nSetTitle(String title);
public boolean isCloseRequested() {
lockAWT();
boolean result = nIsCloseRequested();
unlockAWT();
return result;
try {
return nIsCloseRequested();
} finally {
unlockAWT();
}
}
private static native boolean nIsCloseRequested();
public boolean isVisible() {
lockAWT();
boolean result = nIsVisible();
unlockAWT();
return result;
try {
return nIsVisible();
} finally {
unlockAWT();
}
}
private static native boolean nIsVisible();
public boolean isActive() {
lockAWT();
boolean result = nIsActive(current_window_mode);
unlockAWT();
return result;
try {
return focused || isLegacyFullscreen();
} finally {
unlockAWT();
}
}
private static native boolean nIsActive(int window_mode);
public boolean isDirty() {
lockAWT();
@ -452,17 +592,22 @@ final class LinuxDisplay implements DisplayImplementation {
lockAWT();
try {
nUpdate(current_displaymode_extension, current_window_mode, saved_gamma, current_gamma, saved_mode, current_mode);
checkInput();
} catch (LWJGLException e) {
LWJGLUtil.log("Caught exception while processing messages: " + e);
} finally {
unlockAWT();
}
unlockAWT();
}
private static native void nUpdate(int extension, int current_window_mode, ByteBuffer saved_gamma, ByteBuffer current_gamma, DisplayMode saved_mode, DisplayMode current_mode) throws LWJGLException;
public void reshape(int x, int y, int width, int height) {
lockAWT();
nReshape(x, y, width, height);
unlockAWT();
try {
nReshape(x, y, width, height);
} finally {
unlockAWT();
}
}
private static native void nReshape(int x, int y, int width, int height);
@ -488,61 +633,118 @@ final class LinuxDisplay implements DisplayImplementation {
}
public int getButtonCount() {
return NUM_BUTTONS;
return mouse.getButtonCount();
}
public void createMouse() {
lockAWT();
nCreateMouse(current_window_mode);
unlockAWT();
try {
mouse = new LinuxMouse(getDisplay(), getWindow());
} finally {
unlockAWT();
}
}
private static native void nCreateMouse(int window_mode);
public void destroyMouse() {
lockAWT();
nDestroyMouse();
unlockAWT();
mouse = null;
}
private static native void nDestroyMouse();
public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) {
update();
lockAWT();
nPollMouse(coord_buffer, buttons);
unlockAWT();
try {
mouse.poll(grab, coord_buffer, buttons);
} finally {
unlockAWT();
}
}
private static native void nPollMouse(IntBuffer coord_buffer, ByteBuffer buttons);
public int readMouse(IntBuffer buffer) {
update();
lockAWT();
int count = nReadMouse(buffer, buffer.position());
unlockAWT();
return count;
try {
return mouse.read(buffer);
} finally {
unlockAWT();
}
}
private static native int nReadMouse(IntBuffer buffer, int buffer_position);
public void setCursorPosition(int x, int y) {
lockAWT();
nSetCursorPosition(x, y);
unlockAWT();
try {
mouse.setCursorPosition(x, y);
} finally {
unlockAWT();
}
}
private native void nSetCursorPosition(int x, int y);
public void grabMouse(boolean grab) {
lockAWT();
nGrabMouse(current_window_mode, grab);
unlockAWT();
private static void checkInput() {
focused = nGetInputFocus(getDisplay()) == getWindow();
if (focused) {
acquireInput();
} else {
releaseInput();
}
}
private static native long nGetInputFocus(long display);
private static void releaseInput() {
if (isLegacyFullscreen() || input_released)
return;
input_released = true;
nSetRepeatMode(getDisplay(), AutoRepeatModeDefault);
updateInputGrab();
if (current_window_mode == FULLSCREEN_NETWM) {
nIconifyWindow(getDisplay(), getWindow(), getScreen());
try {
nSwitchDisplayMode(getScreen(), current_displaymode_extension, saved_mode);
nSetGammaRamp(getScreen(), saved_gamma);
} catch (LWJGLException e) {
LWJGLUtil.log("Failed to restore saved mode: " + e.getMessage());
}
}
}
private static native void nIconifyWindow(long display, long window, int screen);
private static void acquireInput() {
if (isLegacyFullscreen() || !input_released)
return;
input_released = false;
nSetRepeatMode(getDisplay(), AutoRepeatModeOff);
updateInputGrab();
if (current_window_mode == FULLSCREEN_NETWM) {
try {
nSwitchDisplayMode(getScreen(), current_displaymode_extension, current_mode);
nSetGammaRamp(getScreen(), current_gamma);
} catch (LWJGLException e) {
LWJGLUtil.log("Failed to restore mode: " + e.getMessage());
}
}
}
private static native void nSetRepeatMode(long display, int mode);
public void grabMouse(boolean new_grab) {
lockAWT();
try {
if (new_grab != grab) {
grab = new_grab;
updateInputGrab();
mouse.changeGrabbed(grab, pointer_grabbed, shouldGrab());
}
} finally {
unlockAWT();
}
}
private static native void nGrabMouse(int window_mode, boolean grab);
public int getNativeCursorCapabilities() {
lockAWT();
try {
incDisplay();
int caps = nGetNativeCursorCapabilities();
decDisplay();
return caps;
try {
return nGetNativeCursorCapabilities();
} finally {
decDisplay();
}
} catch (LWJGLException e) {
throw new RuntimeException(e);
} finally {
@ -552,19 +754,24 @@ final class LinuxDisplay implements DisplayImplementation {
private static native int nGetNativeCursorCapabilities() throws LWJGLException;
public void setNativeCursor(Object handle) throws LWJGLException {
current_cursor = (ByteBuffer)handle;
lockAWT();
nSetNativeCursor(handle);
unlockAWT();
try {
updateCursor();
} finally {
unlockAWT();
}
}
private static native void nSetNativeCursor(Object handle) throws LWJGLException;
public int getMinCursorSize() {
lockAWT();
try {
incDisplay();
int min_size = nGetMinCursorSize();
decDisplay();
return min_size;
try {
return nGetMinCursorSize();
} finally {
decDisplay();
}
} catch (LWJGLException e) {
LWJGLUtil.log("Exception occurred in getMinCursorSize: " + e);
return 0;
@ -578,9 +785,11 @@ final class LinuxDisplay implements DisplayImplementation {
lockAWT();
try {
incDisplay();
int max_size = nGetMaxCursorSize();
decDisplay();
return max_size;
try {
return nGetMaxCursorSize();
} finally {
decDisplay();
}
} catch (LWJGLException e) {
LWJGLUtil.log("Exception occurred in getMaxCursorSize: " + e);
return 0;
@ -594,36 +803,41 @@ final class LinuxDisplay implements DisplayImplementation {
public void createKeyboard() throws LWJGLException {
lockAWT();
try {
nCreateKeyboard(current_window_mode);
keyboard = new LinuxKeyboard(getDisplay(), getWindow());
} finally {
unlockAWT();
}
}
private static native void nCreateKeyboard(int window_mode) throws LWJGLException;
public void destroyKeyboard() {
lockAWT();
nDestroyKeyboard();
unlockAWT();
try {
keyboard.destroy();
keyboard = null;
} finally {
unlockAWT();
}
}
private static native void nDestroyKeyboard();
public void pollKeyboard(ByteBuffer keyDownBuffer) {
update();
lockAWT();
nPollKeyboard(keyDownBuffer);
unlockAWT();
try {
keyboard.poll(keyDownBuffer);
} finally {
unlockAWT();
}
}
private static native void nPollKeyboard(ByteBuffer keyDownBuffer);
public int readKeyboard(IntBuffer buffer) {
update();
lockAWT();
int count = nReadKeyboard(buffer, buffer.position());
unlockAWT();
return count;
try {
return keyboard.read(buffer);
} finally {
unlockAWT();
}
}
private static native int nReadKeyboard(IntBuffer buffer, int buffer_position);
/* public int isStateKeySet(int key) {
return Keyboard.STATE_UNKNOWN;
@ -631,6 +845,11 @@ final class LinuxDisplay implements DisplayImplementation {
*/
private static native ByteBuffer nCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset) throws LWJGLException;
private static ByteBuffer createBlankCursor() {
return nCreateBlankCursor(getDisplay(), getWindow());
}
private static native ByteBuffer nCreateBlankCursor(long display, long window);
public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
lockAWT();
try {
@ -648,9 +867,12 @@ final class LinuxDisplay implements DisplayImplementation {
public void destroyCursor(Object cursorHandle) {
lockAWT();
nDestroyCursor(cursorHandle);
decDisplay();
unlockAWT();
try {
nDestroyCursor(cursorHandle);
decDisplay();
} finally {
unlockAWT();
}
}
private static native void nDestroyCursor(Object cursorHandle);
@ -658,9 +880,11 @@ final class LinuxDisplay implements DisplayImplementation {
lockAWT();
try {
incDisplay();
int caps = nGetPbufferCapabilities();
decDisplay();
return caps;
try {
return nGetPbufferCapabilities();
} finally {
decDisplay();
}
} catch (LWJGLException e) {
LWJGLUtil.log("Exception occurred in getPbufferCapabilities: " + e);
return 0;
@ -753,4 +977,25 @@ final class LinuxDisplay implements DisplayImplementation {
}
private static native void nSetWindowIcon(ByteBuffer icon, int icons_size, int width, int height);
/* Callbacks from nUpdate() */
private static void handleButtonEvent(long millis, int type, int button, int state) {
if (mouse != null)
mouse.handleButtonEvent(grab, type, button);
}
private static void handleKeyEvent(long event_ptr, long millis, int type, int keycode, int state) {
if (keyboard != null)
keyboard.handleKeyEvent(event_ptr, millis, type, keycode, state);
}
private static void handlePointerMotionEvent(long root_window, int x_root, int y_root, int x, int y, int state) {
if (mouse != null)
mouse.handlePointerMotion(grab, pointer_grabbed, shouldGrab(), root_window, x_root, y_root, x, y);
}
private static void handleWarpEvent(int x, int y) {
if (mouse != null)
mouse.handleWarpEvent(x, y);
}
}

View File

@ -0,0 +1,305 @@
/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.opengl;
/**
* @author elias_naur
*/
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.CharBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.Charset;
final class LinuxKeyboard {
private static final int LockMapIndex = 1;
private static final int KeyPress = 2;
private static final int KeyRelease = 3;
private static final long NoSymbol = 0;
private static final long ShiftMask = 1 << 0;
private static final long LockMask = 1 << 1;
private static final int XLookupChars = 2;
private static final int XLookupBoth = 4;
private static final int EVENT_SIZE = 3;
private static final int KEYBOARD_BUFFER_SIZE = 50;
private final long xim;
private final long xic;
private final int numlock_mask;
private final int modeswitch_mask;
private final int caps_lock_mask;
private final int shift_lock_mask;
private final ByteBuffer compose_status;
private final byte[] key_down_buffer = new byte[Keyboard.KEYBOARD_SIZE];
private final EventQueue event_queue = new EventQueue(EVENT_SIZE);
private final int[] tmp_event = new int[3];
private final int[] temp_translation_buffer = new int[KEYBOARD_BUFFER_SIZE];
private final ByteBuffer native_translation_buffer = BufferUtils.createByteBuffer(KEYBOARD_BUFFER_SIZE);
private final CharsetDecoder utf8_decoder = Charset.forName("UTF-8").newDecoder();
private final CharBuffer char_buffer = CharBuffer.allocate(KEYBOARD_BUFFER_SIZE);
public LinuxKeyboard(long display, long window) {
long modifier_map = getModifierMapping(display);
int tmp_numlock_mask = 0;
int tmp_modeswitch_mask = 0;
int tmp_caps_lock_mask = 0;
int tmp_shift_lock_mask = 0;
if (modifier_map != 0) {
int max_keypermod = getMaxKeyPerMod(modifier_map);
// Find modifier masks
int i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < max_keypermod; j++) {
int key_code = lookupModifierMap(modifier_map, i*max_keypermod + j);
int key_sym = (int)keycodeToKeySym(display, key_code);
int mask = 1 << i;
switch (key_sym) {
case LinuxKeycodes.XK_Num_Lock:
tmp_numlock_mask |= mask;
break;
case LinuxKeycodes.XK_Mode_switch:
tmp_modeswitch_mask |= mask;
break;
case LinuxKeycodes.XK_Caps_Lock:
if (i == LockMapIndex) {
tmp_caps_lock_mask = mask;
tmp_shift_lock_mask = 0;
}
break;
case LinuxKeycodes.XK_Shift_Lock:
if (i == LockMapIndex && tmp_caps_lock_mask == 0)
tmp_shift_lock_mask = mask;
break;
default:
break;
}
}
}
freeModifierMapping(modifier_map);
}
numlock_mask = tmp_numlock_mask;
modeswitch_mask = tmp_modeswitch_mask;
caps_lock_mask = tmp_caps_lock_mask;
shift_lock_mask = tmp_shift_lock_mask;
xim = openIM(display);
if (xim != 0) {
xic = createIC(xim, window);
if (xic != 0) {
setupIMEventMask(display, window, xic);
} else {
destroy();
}
} else {
xic = 0;
}
compose_status = allocateComposeStatus();
}
private static native long getModifierMapping(long display);
private static native void freeModifierMapping(long modifier_map);
private static native int getMaxKeyPerMod(long modifier_map);
private static native int lookupModifierMap(long modifier_map, int index);
private static native long keycodeToKeySym(long display, int key_code);
private static native long openIM(long display);
private static native long createIC(long xim, long window);
private static native void setupIMEventMask(long display, long window, long xic);
private static native ByteBuffer allocateComposeStatus();
public void destroy() {
destroyIC(xic);
closeIM(xim);
}
private static native void destroyIC(long xic);
private static native void closeIM(long xim);
public int read(IntBuffer buffer) {
return event_queue.copyEvents(buffer);
}
public void poll(ByteBuffer keyDownBuffer) {
int old_position = keyDownBuffer.position();
keyDownBuffer.put(key_down_buffer);
keyDownBuffer.position(old_position);
}
private void putKeyboardEvent(int keycode, int state, int ch) {
tmp_event[0] = keycode;
tmp_event[1] = state;
tmp_event[2] = ch;
event_queue.putEvent(tmp_event);
}
private int lookupStringISO88591(long event_ptr, int[] translation_buffer) {
int i;
int num_chars = lookupString(event_ptr, native_translation_buffer, compose_status);
for (i = 0; i < num_chars; i++) {
translation_buffer[i] = ((int)native_translation_buffer.get(i)) & 0xff;
}
return num_chars;
}
private static native int lookupString(long event_ptr, ByteBuffer buffer, ByteBuffer compose_status);
private int lookupStringUnicode(long event_ptr, int[] translation_buffer) {
int status = utf8LookupString(xic, event_ptr, native_translation_buffer, native_translation_buffer.position(), native_translation_buffer.remaining());
if (status != XLookupChars && status != XLookupBoth)
return 0;
native_translation_buffer.flip();
utf8_decoder.decode(native_translation_buffer, char_buffer, true);
native_translation_buffer.compact();
char_buffer.flip();
int i = 0;
while (char_buffer.hasRemaining() && i < translation_buffer.length) {
translation_buffer[i++] = char_buffer.get();
}
char_buffer.compact();
return i;
}
private static native int utf8LookupString(long xic, long event_ptr, ByteBuffer buffer, int pos, int size);
private int lookupString(long event_ptr, int[] translation_buffer) {
if (xic != 0) {
return lookupStringUnicode(event_ptr, translation_buffer);
} else
return lookupStringISO88591(event_ptr, translation_buffer);
}
private void translateEvent(long event_ptr, int event_type, int keycode, int key_state) {
int num_chars, i;
int ch;
if (event_type == KeyRelease) {
putKeyboardEvent(keycode, key_state, 0);
return;
}
num_chars = lookupString(event_ptr, temp_translation_buffer);
if (num_chars > 0) {
ch = temp_translation_buffer[0];
putKeyboardEvent(keycode, key_state, ch);
for (i = 1; i < num_chars; i++) {
ch = temp_translation_buffer[i];
putKeyboardEvent(0, 0, ch);
}
} else {
putKeyboardEvent(keycode, key_state, 0);
}
}
private static boolean isKeypadKeysym(long keysym) {
return (0xFF80 <= keysym && keysym <= 0xFFBD) ||
(0x11000000 <= keysym && keysym <= 0x1100FFFF);
}
private static boolean isNoSymbolOrVendorSpecific(long keysym) {
return keysym == NoSymbol || (keysym & (1 << 28)) != 0;
}
private static long getKeySym(long event_ptr, int group, int index) {
long keysym = lookupKeysym(event_ptr, group*2 + index);
if (isNoSymbolOrVendorSpecific(keysym) && index == 1) {
keysym = lookupKeysym(event_ptr, group*2 + 0);
}
if (isNoSymbolOrVendorSpecific(keysym) && group == 1)
keysym = getKeySym(event_ptr, 0, index);
return keysym;
}
private static native long lookupKeysym(long event_ptr, int index);
private static native long toUpper(long keysym);
private long mapEventToKeySym(long event_ptr, int event_state) {
int group;
long keysym;
if ((event_state & modeswitch_mask) != 0)
group = 1;
else
group = 0;
if ((event_state & numlock_mask) != 0 && isKeypadKeysym(keysym = getKeySym(event_ptr, group, 1))) {
if ((event_state & (ShiftMask | shift_lock_mask)) != 0) {
return getKeySym(event_ptr, group, 0);
} else {
return keysym;
}
} else if ((event_state & (ShiftMask | LockMask)) == 0) {
return getKeySym(event_ptr, group, 0);
} else if ((event_state & ShiftMask) == 0) {
keysym = getKeySym(event_ptr, group, 0);
if ((event_state & caps_lock_mask) != 0)
keysym = toUpper(keysym);
return keysym;
} else {
keysym = getKeySym(event_ptr, group, 1);
if ((event_state & caps_lock_mask) != 0)
keysym = toUpper(keysym);
return keysym;
}
}
private int getKeycode(long event_ptr, int event_state) {
long keysym = mapEventToKeySym(event_ptr, event_state);
int keycode = LinuxKeycodes.mapKeySymToLWJGLKeyCode(keysym);
if (keycode == Keyboard.KEY_NONE) {
// Try unshifted keysym mapping
keysym = lookupKeysym(event_ptr, 0);
keycode = LinuxKeycodes.mapKeySymToLWJGLKeyCode(keysym);
}
return keycode;
}
private byte getKeyState(int event_type) {
switch (event_type) {
case KeyPress:
return 1;
case KeyRelease:
return 0;
default:
throw new IllegalArgumentException("Unknown event_type: " + event_type);
}
}
public void handleKeyEvent(long event_ptr, long millis, int event_type, int event_keycode, int event_state) {
int keycode = getKeycode(event_ptr, event_state);
byte key_state = getKeyState(event_type);
key_down_buffer[keycode] = key_state;
translateEvent(event_ptr, event_type, keycode, key_state);
}
}

View File

@ -0,0 +1,760 @@
/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.opengl;
/**
* @author elias_naur
*/
import org.lwjgl.input.Keyboard;
final class LinuxKeycodes {
public final static int XK_Kanji = 0xff21;
public final static int XK_ISO_Left_Tab = 0xfe20;
public final static int XK_dead_grave = 0xfe50;
public final static int XK_dead_acute = 0xfe51;
public final static int XK_dead_circumflex = 0xfe52;
public final static int XK_dead_tilde = 0xfe53;
public final static int XK_dead_macron = 0xfe54;
public final static int XK_dead_breve = 0xfe55;
public final static int XK_dead_abovedot = 0xfe56;
public final static int XK_dead_diaeresis = 0xfe57;
public final static int XK_dead_abovering = 0xfe58;
public final static int XK_dead_doubleacute = 0xfe59;
public final static int XK_dead_caron = 0xfe5a;
public final static int XK_dead_cedilla = 0xfe5b;
public final static int XK_dead_ogonek = 0xfe5c;
public final static int XK_dead_iota = 0xfe5d;
public final static int XK_dead_voiced_sound = 0xfe5e;
public final static int XK_dead_semivoiced_sound = 0xfe5f;
public final static int XK_dead_belowdot = 0xfe60;
public final static int XK_dead_hook = 0xfe61;
public final static int XK_dead_horn = 0xfe62;
public final static int XK_BackSpace = 0xff08;
public final static int XK_Tab = 0xff09;
public final static int XK_Linefeed = 0xff0a;
public final static int XK_Clear = 0xff0b;
public final static int XK_Return = 0xff0d;
public final static int XK_Pause = 0xff13;
public final static int XK_Scroll_Lock = 0xff14;
public final static int XK_Sys_Req = 0xff15;
public final static int XK_Escape = 0xff1b;
public final static int XK_Delete = 0xffff;
public final static int XK_Home = 0xff50;
public final static int XK_Left = 0xff51;
public final static int XK_Up = 0xff52;
public final static int XK_Right = 0xff53;
public final static int XK_Down = 0xff54;
public final static int XK_Prior = 0xff55;
public final static int XK_Page_Up = 0xff55;
public final static int XK_Next = 0xff56;
public final static int XK_Page_Down = 0xff56;
public final static int XK_End = 0xff57;
public final static int XK_Begin = 0xff58;
/* Misc functions */
public final static int XK_Select = 0xff60;
public final static int XK_Print = 0xff61;
public final static int XK_Execute = 0xff62;
public final static int XK_Insert = 0xff63;
public final static int XK_Undo = 0xff65;
public final static int XK_Redo = 0xff66;
public final static int XK_Menu = 0xff67;
public final static int XK_Find = 0xff68;
public final static int XK_Cancel = 0xff69;
public final static int XK_Help = 0xff6a;
public final static int XK_Break = 0xff6b;
public final static int XK_Mode_switch = 0xff7e;
public final static int XK_script_switch = 0xff7e;
public final static int XK_Num_Lock = 0xff7f;
/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
public final static int XK_KP_Space = 0xff80;
public final static int XK_KP_Tab = 0xff89;
public final static int XK_KP_Enter = 0xff8d;
public final static int XK_KP_F1 = 0xff91;
public final static int XK_KP_F2 = 0xff92;
public final static int XK_KP_F3 = 0xff93;
public final static int XK_KP_F4 = 0xff94;
public final static int XK_KP_Home = 0xff95;
public final static int XK_KP_Left = 0xff96;
public final static int XK_KP_Up = 0xff97;
public final static int XK_KP_Right = 0xff98;
public final static int XK_KP_Down = 0xff99;
public final static int XK_KP_Prior = 0xff9a;
public final static int XK_KP_Page_Up = 0xff9a;
public final static int XK_KP_Next = 0xff9b;
public final static int XK_KP_Page_Down = 0xff9b;
public final static int XK_KP_End = 0xff9c;
public final static int XK_KP_Begin = 0xff9d;
public final static int XK_KP_Insert = 0xff9e;
public final static int XK_KP_Delete = 0xff9f;
public final static int XK_KP_Equal = 0xffbd;
public final static int XK_KP_Multiply = 0xffaa;
public final static int XK_KP_Add = 0xffab;
public final static int XK_KP_Separator = 0xffac;
public final static int XK_KP_Subtract = 0xffad;
public final static int XK_KP_Decimal = 0xffae;
public final static int XK_KP_Divide = 0xffaf;
public final static int XK_KP_0 = 0xffb0;
public final static int XK_KP_1 = 0xffb1;
public final static int XK_KP_2 = 0xffb2;
public final static int XK_KP_3 = 0xffb3;
public final static int XK_KP_4 = 0xffb4;
public final static int XK_KP_5 = 0xffb5;
public final static int XK_KP_6 = 0xffb6;
public final static int XK_KP_7 = 0xffb7;
public final static int XK_KP_8 = 0xffb8;
public final static int XK_KP_9 = 0xffb9;
/*
* Auxilliary functions; note the duplicate definitions for left and right
* function keys; Sun keyboards and a few other manufactures have such
* function key groups on the left and/or right sides of the keyboard.
* We've not found a keyboard with more than 35 function keys total.
*/
public final static int XK_F1 = 0xffbe;
public final static int XK_F2 = 0xffbf;
public final static int XK_F3 = 0xffc0;
public final static int XK_F4 = 0xffc1;
public final static int XK_F5 = 0xffc2;
public final static int XK_F6 = 0xffc3;
public final static int XK_F7 = 0xffc4;
public final static int XK_F8 = 0xffc5;
public final static int XK_F9 = 0xffc6;
public final static int XK_F10 = 0xffc7;
public final static int XK_F11 = 0xffc8;
public final static int XK_L1 = 0xffc8;
public final static int XK_F12 = 0xffc9;
public final static int XK_L2 = 0xffc9;
public final static int XK_F13 = 0xffca;
public final static int XK_L3 = 0xffca;
public final static int XK_F14 = 0xffcb;
public final static int XK_L4 = 0xffcb;
public final static int XK_F15 = 0xffcc;
public final static int XK_L5 = 0xffcc;
public final static int XK_F16 = 0xffcd;
public final static int XK_L6 = 0xffcd;
public final static int XK_F17 = 0xffce;
public final static int XK_L7 = 0xffce;
public final static int XK_F18 = 0xffcf;
public final static int XK_L8 = 0xffcf;
public final static int XK_F19 = 0xffd0;
public final static int XK_L9 = 0xffd0;
public final static int XK_F20 = 0xffd1;
public final static int XK_L10 = 0xffd1;
public final static int XK_F21 = 0xffd2;
public final static int XK_R1 = 0xffd2;
public final static int XK_F22 = 0xffd3;
public final static int XK_R2 = 0xffd3;
public final static int XK_F23 = 0xffd4;
public final static int XK_R3 = 0xffd4;
public final static int XK_F24 = 0xffd5;
public final static int XK_R4 = 0xffd5;
public final static int XK_F25 = 0xffd6;
public final static int XK_R5 = 0xffd6;
public final static int XK_F26 = 0xffd7;
public final static int XK_R6 = 0xffd7;
public final static int XK_F27 = 0xffd8;
public final static int XK_R7 = 0xffd8;
public final static int XK_F28 = 0xffd9;
public final static int XK_R8 = 0xffd9;
public final static int XK_F29 = 0xffda;
public final static int XK_R9 = 0xffda;
public final static int XK_F30 = 0xffdb;
public final static int XK_R10 = 0xffdb;
public final static int XK_F31 = 0xffdc;
public final static int XK_R11 = 0xffdc;
public final static int XK_F32 = 0xffdd;
public final static int XK_R12 = 0xffdd;
public final static int XK_F33 = 0xffde;
public final static int XK_R13 = 0xffde;
public final static int XK_F34 = 0xffdf;
public final static int XK_R14 = 0xffdf;
public final static int XK_F35 = 0xffe0;
public final static int XK_R15 = 0xffe0;
/* Modifiers */
public final static int XK_Shift_L = 0xffe1;
public final static int XK_Shift_R = 0xffe2;
public final static int XK_Control_L = 0xffe3;
public final static int XK_Control_R = 0xffe4;
public final static int XK_Caps_Lock = 0xffe5;
public final static int XK_Shift_Lock = 0xffe6;
public final static int XK_Meta_L = 0xffe7;
public final static int XK_Meta_R = 0xffe8;
public final static int XK_Alt_L = 0xffe9;
public final static int XK_Alt_R = 0xffea;
public final static int XK_Super_L = 0xffeb;
public final static int XK_Super_R = 0xffec;
public final static int XK_Hyper_L = 0xffed;
public final static int XK_Hyper_R = 0xffee;
public final static int XK_space = 0x0020;
public final static int XK_exclam = 0x0021;
public final static int XK_quotedbl = 0x0022;
public final static int XK_numbersign = 0x0023;
public final static int XK_dollar = 0x0024;
public final static int XK_percent = 0x0025;
public final static int XK_ampersand = 0x0026;
public final static int XK_apostrophe = 0x0027;
public final static int XK_quoteright = 0x0027;
public final static int XK_parenleft = 0x0028;
public final static int XK_parenright = 0x0029;
public final static int XK_asterisk = 0x002a;
public final static int XK_plus = 0x002b;
public final static int XK_comma = 0x002c;
public final static int XK_minus = 0x002d;
public final static int XK_period = 0x002e;
public final static int XK_slash = 0x002f;
public final static int XK_0 = 0x0030;
public final static int XK_1 = 0x0031;
public final static int XK_2 = 0x0032;
public final static int XK_3 = 0x0033;
public final static int XK_4 = 0x0034;
public final static int XK_5 = 0x0035;
public final static int XK_6 = 0x0036;
public final static int XK_7 = 0x0037;
public final static int XK_8 = 0x0038;
public final static int XK_9 = 0x0039;
public final static int XK_colon = 0x003a;
public final static int XK_semicolon = 0x003b;
public final static int XK_less = 0x003c;
public final static int XK_equal = 0x003d;
public final static int XK_greater = 0x003e;
public final static int XK_question = 0x003f;
public final static int XK_at = 0x0040;
public final static int XK_A = 0x0041;
public final static int XK_B = 0x0042;
public final static int XK_C = 0x0043;
public final static int XK_D = 0x0044;
public final static int XK_E = 0x0045;
public final static int XK_F = 0x0046;
public final static int XK_G = 0x0047;
public final static int XK_H = 0x0048;
public final static int XK_I = 0x0049;
public final static int XK_J = 0x004a;
public final static int XK_K = 0x004b;
public final static int XK_L = 0x004c;
public final static int XK_M = 0x004d;
public final static int XK_N = 0x004e;
public final static int XK_O = 0x004f;
public final static int XK_P = 0x0050;
public final static int XK_Q = 0x0051;
public final static int XK_R = 0x0052;
public final static int XK_S = 0x0053;
public final static int XK_T = 0x0054;
public final static int XK_U = 0x0055;
public final static int XK_V = 0x0056;
public final static int XK_W = 0x0057;
public final static int XK_X = 0x0058;
public final static int XK_Y = 0x0059;
public final static int XK_Z = 0x005a;
public final static int XK_bracketleft = 0x005b;
public final static int XK_backslash = 0x005c;
public final static int XK_bracketright = 0x005d;
public final static int XK_asciicircum = 0x005e;
public final static int XK_underscore = 0x005f;
public final static int XK_grave = 0x0060;
public final static int XK_quoteleft = 0x0060;
public final static int XK_a = 0x0061;
public final static int XK_b = 0x0062;
public final static int XK_c = 0x0063;
public final static int XK_d = 0x0064;
public final static int XK_e = 0x0065;
public final static int XK_f = 0x0066;
public final static int XK_g = 0x0067;
public final static int XK_h = 0x0068;
public final static int XK_i = 0x0069;
public final static int XK_j = 0x006a;
public final static int XK_k = 0x006b;
public final static int XK_l = 0x006c;
public final static int XK_m = 0x006d;
public final static int XK_n = 0x006e;
public final static int XK_o = 0x006f;
public final static int XK_p = 0x0070;
public final static int XK_q = 0x0071;
public final static int XK_r = 0x0072;
public final static int XK_s = 0x0073;
public final static int XK_t = 0x0074;
public final static int XK_u = 0x0075;
public final static int XK_v = 0x0076;
public final static int XK_w = 0x0077;
public final static int XK_x = 0x0078;
public final static int XK_y = 0x0079;
public final static int XK_z = 0x007a;
public final static int XK_braceleft = 0x007b;
public final static int XK_bar = 0x007c;
public final static int XK_braceright = 0x007d;
public final static int XK_asciitilde = 0x007e;
public final static int XK_nobreakspace = 0x00a0;
public final static int XK_exclamdown = 0x00a1;
public final static int XK_cent = 0x00a2;
public final static int XK_sterling = 0x00a3;
public final static int XK_currency = 0x00a4;
public final static int XK_yen = 0x00a5;
public final static int XK_brokenbar = 0x00a6;
public final static int XK_section = 0x00a7;
public final static int XK_diaeresis = 0x00a8;
public final static int XK_copyright = 0x00a9;
public final static int XK_ordfeminine = 0x00aa;
public final static int XK_guillemotleft = 0x00ab;
public final static int XK_notsign = 0x00ac;
public final static int XK_hyphen = 0x00ad;
public final static int XK_registered = 0x00ae;
public final static int XK_macron = 0x00af;
public final static int XK_degree = 0x00b0;
public final static int XK_plusminus = 0x00b1;
public final static int XK_twosuperior = 0x00b2;
public final static int XK_threesuperior = 0x00b3;
public final static int XK_acute = 0x00b4;
public final static int XK_mu = 0x00b5;
public final static int XK_paragraph = 0x00b6;
public final static int XK_periodcentered = 0x00b7;
public final static int XK_cedilla = 0x00b8;
public final static int XK_onesuperior = 0x00b9;
public final static int XK_masculine = 0x00ba;
public final static int XK_guillemotright = 0x00bb;
public final static int XK_onequarter = 0x00bc;
public final static int XK_onehalf = 0x00bd;
public final static int XK_threequarters = 0x00be;
public final static int XK_questiondown = 0x00bf;
public final static int XK_Agrave = 0x00c0;
public final static int XK_Aacute = 0x00c1;
public final static int XK_Acircumflex = 0x00c2;
public final static int XK_Atilde = 0x00c3;
public final static int XK_Adiaeresis = 0x00c4;
public final static int XK_Aring = 0x00c5;
public final static int XK_AE = 0x00c6;
public final static int XK_Ccedilla = 0x00c7;
public final static int XK_Egrave = 0x00c8;
public final static int XK_Eacute = 0x00c9;
public final static int XK_Ecircumflex = 0x00ca;
public final static int XK_Ediaeresis = 0x00cb;
public final static int XK_Igrave = 0x00cc;
public final static int XK_Iacute = 0x00cd;
public final static int XK_Icircumflex = 0x00ce;
public final static int XK_Idiaeresis = 0x00cf;
public final static int XK_ETH = 0x00d0;
public final static int XK_Eth = 0x00d0;
public final static int XK_Ntilde = 0x00d1;
public final static int XK_Ograve = 0x00d2;
public final static int XK_Oacute = 0x00d3;
public final static int XK_Ocircumflex = 0x00d4;
public final static int XK_Otilde = 0x00d5;
public final static int XK_Odiaeresis = 0x00d6;
public final static int XK_multiply = 0x00d7;
public final static int XK_Oslash = 0x00d8;
public final static int XK_Ooblique = 0x00d8;
public final static int XK_Ugrave = 0x00d9;
public final static int XK_Uacute = 0x00da;
public final static int XK_Ucircumflex = 0x00db;
public final static int XK_Udiaeresis = 0x00dc;
public final static int XK_Yacute = 0x00dd;
public final static int XK_THORN = 0x00de;
public final static int XK_Thorn = 0x00de;
public final static int XK_ssharp = 0x00df;
public final static int XK_agrave = 0x00e0;
public final static int XK_aacute = 0x00e1;
public final static int XK_acircumflex = 0x00e2;
public final static int XK_atilde = 0x00e3;
public final static int XK_adiaeresis = 0x00e4;
public final static int XK_aring = 0x00e5;
public final static int XK_ae = 0x00e6;
public final static int XK_ccedilla = 0x00e7;
public final static int XK_egrave = 0x00e8;
public final static int XK_eacute = 0x00e9;
public final static int XK_ecircumflex = 0x00ea;
public final static int XK_ediaeresis = 0x00eb;
public final static int XK_igrave = 0x00ec;
public final static int XK_iacute = 0x00ed;
public final static int XK_icircumflex = 0x00ee;
public final static int XK_idiaeresis = 0x00ef;
public final static int XK_eth = 0x00f0;
public final static int XK_ntilde = 0x00f1;
public final static int XK_ograve = 0x00f2;
public final static int XK_oacute = 0x00f3;
public final static int XK_ocircumflex = 0x00f4;
public final static int XK_otilde = 0x00f5;
public final static int XK_odiaeresis = 0x00f6;
public final static int XK_division = 0x00f7;
public final static int XK_oslash = 0x00f8;
public final static int XK_ooblique = 0x00f8;
public final static int XK_ugrave = 0x00f9;
public final static int XK_uacute = 0x00fa;
public final static int XK_ucircumflex = 0x00fb;
public final static int XK_udiaeresis = 0x00fc;
public final static int XK_yacute = 0x00fd;
public final static int XK_thorn = 0x00fe;
public final static int XK_ydiaeresis = 0x00ff;
public static int mapKeySymToLWJGLKeyCode(long keysym) {
switch ((int)keysym) {
case XK_BackSpace:
return Keyboard.KEY_BACK;
case XK_ISO_Left_Tab:
case XK_Tab:
return Keyboard.KEY_TAB;
case XK_Return:
return Keyboard.KEY_RETURN;
case XK_Pause:
return Keyboard.KEY_PAUSE;
case XK_Scroll_Lock:
return Keyboard.KEY_SCROLL;
case XK_Sys_Req:
return Keyboard.KEY_SYSRQ;
case XK_Escape:
return Keyboard.KEY_ESCAPE;
case XK_Delete:
return Keyboard.KEY_DELETE;
/* Japanese keyboard support */
case XK_Kanji:
return Keyboard.KEY_KANJI;
/* Cursor control & motion */
case XK_Home:
return Keyboard.KEY_HOME;
case XK_Left:
return Keyboard.KEY_LEFT;
case XK_Up:
return Keyboard.KEY_UP;
case XK_Right:
return Keyboard.KEY_RIGHT;
case XK_Down:
return Keyboard.KEY_DOWN;
case XK_Page_Up:
return Keyboard.KEY_PRIOR;
case XK_Page_Down:
return Keyboard.KEY_NEXT;
case XK_End:
return Keyboard.KEY_END;
/* Misc Functions */
case XK_Break:
return Keyboard.KEY_PAUSE;
case XK_Insert:
return Keyboard.KEY_INSERT;
case XK_Num_Lock:
return Keyboard.KEY_NUMLOCK;
/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
case XK_KP_Space:
return Keyboard.KEY_SPACE;
case XK_KP_Tab:
return Keyboard.KEY_TAB;
case XK_KP_Enter:
return Keyboard.KEY_NUMPADENTER;
case XK_KP_F1:
return Keyboard.KEY_F1;
case XK_KP_F2:
return Keyboard.KEY_F2;
case XK_KP_F3:
return Keyboard.KEY_F3;
case XK_KP_F4:
return Keyboard.KEY_F4;
case XK_KP_Home:
return Keyboard.KEY_HOME;
case XK_KP_Left:
return Keyboard.KEY_LEFT;
case XK_KP_Up:
return Keyboard.KEY_UP;
case XK_KP_Right:
return Keyboard.KEY_RIGHT;
case XK_KP_Down:
return Keyboard.KEY_DOWN;
case XK_KP_Page_Up:
return Keyboard.KEY_PRIOR;
case XK_KP_Page_Down:
return Keyboard.KEY_NEXT;
case XK_KP_End:
return Keyboard.KEY_END;
case XK_KP_Insert:
return Keyboard.KEY_INSERT;
case XK_KP_Delete:
return Keyboard.KEY_DELETE;
case XK_KP_Equal:
return Keyboard.KEY_NUMPADEQUALS;
case XK_KP_Multiply:
return Keyboard.KEY_MULTIPLY;
case XK_KP_Add:
return Keyboard.KEY_ADD;
case XK_KP_Subtract:
return Keyboard.KEY_SUBTRACT;
case XK_KP_Decimal:
return Keyboard.KEY_DECIMAL;
case XK_KP_Divide:
return Keyboard.KEY_DIVIDE;
case XK_KP_0:
return Keyboard.KEY_NUMPAD0;
case XK_KP_1:
return Keyboard.KEY_NUMPAD1;
case XK_KP_2:
return Keyboard.KEY_NUMPAD2;
case XK_KP_3:
return Keyboard.KEY_NUMPAD3;
case XK_KP_4:
return Keyboard.KEY_NUMPAD4;
case XK_KP_5:
return Keyboard.KEY_NUMPAD5;
case XK_KP_6:
return Keyboard.KEY_NUMPAD6;
case XK_KP_7:
return Keyboard.KEY_NUMPAD7;
case XK_KP_8:
return Keyboard.KEY_NUMPAD8;
case XK_KP_9:
return Keyboard.KEY_NUMPAD9;
/*
* Auxilliary Functions; note the duplicate definitions for left and right
* function keys; Sun keyboards and a few other manufactures have such
* function key groups on the left and/or right sides of the keyboard.
* We've not found a keyboard with more than 35 function keys total.
*/
case XK_F1:
return Keyboard.KEY_F1;
case XK_F2:
return Keyboard.KEY_F2;
case XK_F3:
return Keyboard.KEY_F3;
case XK_F4:
return Keyboard.KEY_F4;
case XK_F5:
return Keyboard.KEY_F5;
case XK_F6:
return Keyboard.KEY_F6;
case XK_F7:
return Keyboard.KEY_F7;
case XK_F8:
return Keyboard.KEY_F8;
case XK_F9:
return Keyboard.KEY_F9;
case XK_F10:
return Keyboard.KEY_F10;
case XK_F11:
return Keyboard.KEY_F11;
case XK_F12:
return Keyboard.KEY_F12;
case XK_F13:
return Keyboard.KEY_F13;
case XK_F14:
return Keyboard.KEY_F14;
case XK_F15:
return Keyboard.KEY_F15;
/* Modifiers */
case XK_Shift_L:
return Keyboard.KEY_LSHIFT;
case XK_Shift_R:
return Keyboard.KEY_RSHIFT;
case XK_Control_L:
return Keyboard.KEY_LCONTROL;
case XK_Control_R:
return Keyboard.KEY_RCONTROL;
case XK_Caps_Lock:
return Keyboard.KEY_CAPITAL;
case XK_Meta_L:
return Keyboard.KEY_LMENU;
case XK_Meta_R:
return Keyboard.KEY_RMENU;
case XK_Alt_L:
return Keyboard.KEY_LMENU;
case XK_Alt_R:
return Keyboard.KEY_RMENU;
case XK_dead_grave:
return Keyboard.KEY_GRAVE;
case XK_dead_circumflex:
return Keyboard.KEY_CIRCUMFLEX;
/*
* Latin 1
* Byte 3 = 0
*/
case XK_space:
return Keyboard.KEY_SPACE;
case XK_apostrophe:
return Keyboard.KEY_APOSTROPHE;
case XK_comma:
return Keyboard.KEY_COMMA;
case XK_minus:
return Keyboard.KEY_MINUS;
case XK_period:
return Keyboard.KEY_PERIOD;
case XK_slash:
return Keyboard.KEY_SLASH;
case XK_0:
return Keyboard.KEY_0;
case XK_1:
return Keyboard.KEY_1;
case XK_2:
return Keyboard.KEY_2;
case XK_3:
return Keyboard.KEY_3;
case XK_4:
return Keyboard.KEY_4;
case XK_5:
return Keyboard.KEY_5;
case XK_6:
return Keyboard.KEY_6;
case XK_7:
return Keyboard.KEY_7;
case XK_8:
return Keyboard.KEY_8;
case XK_9:
return Keyboard.KEY_9;
case XK_colon:
return Keyboard.KEY_COLON;
case XK_semicolon:
return Keyboard.KEY_SEMICOLON;
case XK_equal:
return Keyboard.KEY_EQUALS;
case XK_at:
return Keyboard.KEY_AT;
case XK_bracketleft:
return Keyboard.KEY_LBRACKET;
case XK_bracketright:
return Keyboard.KEY_RBRACKET;
case XK_asciicircum:
return Keyboard.KEY_CIRCUMFLEX;
case XK_underscore:
return Keyboard.KEY_UNDERLINE;
case XK_grave:
return Keyboard.KEY_GRAVE;
case XK_a:
case XK_A:
return Keyboard.KEY_A;
case XK_b:
case XK_B:
return Keyboard.KEY_B;
case XK_c:
case XK_C:
return Keyboard.KEY_C;
case XK_d:
case XK_D:
return Keyboard.KEY_D;
case XK_e:
case XK_E:
return Keyboard.KEY_E;
case XK_f:
case XK_F:
return Keyboard.KEY_F;
case XK_g:
case XK_G:
return Keyboard.KEY_G;
case XK_h:
case XK_H:
return Keyboard.KEY_H;
case XK_i:
case XK_I:
return Keyboard.KEY_I;
case XK_j:
case XK_J:
return Keyboard.KEY_J;
case XK_k:
case XK_K:
return Keyboard.KEY_K;
case XK_l:
case XK_L:
return Keyboard.KEY_L;
case XK_m:
case XK_M:
return Keyboard.KEY_M;
case XK_n:
case XK_N:
return Keyboard.KEY_N;
case XK_o:
case XK_O:
return Keyboard.KEY_O;
case XK_p:
case XK_P:
return Keyboard.KEY_P;
case XK_q:
case XK_Q:
return Keyboard.KEY_Q;
case XK_r:
case XK_R:
return Keyboard.KEY_R;
case XK_s:
case XK_S:
return Keyboard.KEY_S;
case XK_t:
case XK_T:
return Keyboard.KEY_T;
case XK_u:
case XK_U:
return Keyboard.KEY_U;
case XK_v:
case XK_V:
return Keyboard.KEY_V;
case XK_w:
case XK_W:
return Keyboard.KEY_W;
case XK_x:
case XK_X:
return Keyboard.KEY_X;
case XK_y:
case XK_Y:
return Keyboard.KEY_Y;
case XK_z:
case XK_Z:
return Keyboard.KEY_Z;
default:
return Keyboard.KEY_NONE;
}
}
}

View File

@ -0,0 +1,264 @@
/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.opengl;
/**
* @author elias_naur
*/
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.CharBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.Charset;
final class LinuxMouse {
private static final int EVENT_SIZE = 5;
private static final int NUM_BUTTONS = 3;
private static final int POINTER_WARP_BORDER = 10;
// scale the mouse wheel according to DirectInput
private static final int WHEEL_SCALE = 120;
/* X11 constants */
private final static int Button1 = 1;
private final static int Button2 = 2;
private final static int Button3 = 3;
private final static int Button4 = 4;
private final static int Button5 = 5;
private final static int ButtonPress = 4;
private final static int ButtonRelease = 5;
private final long display;
private final long window;
private final IntBuffer query_pointer_buffer = BufferUtils.createIntBuffer(4);
private final int[] event_buffer = new int[EVENT_SIZE];
private int last_x;
private int last_y;
private int accum_dx;
private int accum_dy;
private int accum_dz;
private byte[] buttons = new byte[NUM_BUTTONS];
private EventQueue event_queue;
public LinuxMouse(long display, long window) {
this.display = display;
this.window = window;
reset();
}
private void reset() {
event_queue = new EventQueue(EVENT_SIZE);
accum_dx = accum_dy = 0;
}
public int read(IntBuffer buffer) {
return event_queue.copyEvents(buffer);
}
public void poll(boolean grab, IntBuffer coord_buffer, ByteBuffer buttons_buffer) {
if (grab) {
coord_buffer.put(0, accum_dx);
coord_buffer.put(1, accum_dy);
} else {
coord_buffer.put(0, last_x);
coord_buffer.put(1, last_y);
}
coord_buffer.put(2, accum_dz);
accum_dx = accum_dy = accum_dz = 0;
for (int i = 0; i < buttons.length; i++)
buttons_buffer.put(i, buttons[i]);
}
private boolean putMouseEventWithCoords(int button, int state, int coord1, int coord2, int dz) {
event_buffer[0] = button;
event_buffer[1] = state;
event_buffer[2] = coord1;
event_buffer[3] = coord2;
event_buffer[4] = dz;
return event_queue.putEvent(event_buffer);
}
private void setCursorPos(boolean grab, int x, int y) {
y = transformY(y);
int dx = x - last_x;
int dy = y - last_y;
accum_dx += dx;
accum_dy += dy;
last_x = x;
last_y = y;
if (grab) {
putMouseEventWithCoords(-1, 0, dx, dy, 0);
} else {
putMouseEventWithCoords(-1, 0, x, y, 0);
}
}
private void doWarpPointer(int center_x, int center_y) {
nSendWarpEvent(display, window, center_x, center_y);
nWarpCursor(display, window, center_x, center_y);
}
private static native void nSendWarpEvent(long display, long window, int center_x, int center_y);
private void doHandlePointerMotion(boolean grab, boolean pointer_grabbed, boolean should_grab, long root_window, int root_x, int root_y, int win_x, int win_y) {
setCursorPos(grab, win_x, win_y);
if (!pointer_grabbed || !should_grab)
return;
int root_window_height = nGetWindowHeight(display, root_window);
int root_window_width = nGetWindowWidth(display, root_window);
int window_height = nGetWindowHeight(display, window);
int window_width = nGetWindowWidth(display, window);
// find the window position in root coordinates
int win_left = root_x - win_x;
int win_top = root_y - win_y;
int win_right = win_left + window_width;
int win_bottom = win_top + window_height;
// cap the window position to the screen dimensions
int border_left = Math.max(0, win_left);
int border_top = Math.max(0, win_top);
int border_right = Math.min(root_window_width, win_right);
int border_bottom = Math.min(root_window_height, win_bottom);
// determine whether the cursor is outside the bounds
boolean outside_limits = root_x < border_left + POINTER_WARP_BORDER || root_y < border_top + POINTER_WARP_BORDER ||
root_x > border_right - POINTER_WARP_BORDER || root_y > border_bottom - POINTER_WARP_BORDER;
if (outside_limits) {
// Find the center of the limits in window coordinates
int center_x = (border_right - border_left)/2;
int center_y = (border_bottom - border_top)/2;
doWarpPointer(center_x, center_y);
}
}
public void changeGrabbed(boolean grab, boolean pointer_grabbed, boolean should_grab) {
reset();
long root_window = nQueryPointer(display, window, query_pointer_buffer);
doHandlePointerMotion(grab, pointer_grabbed, should_grab, root_window, query_pointer_buffer.get(0), query_pointer_buffer.get(1), query_pointer_buffer.get(2), query_pointer_buffer.get(3));
}
public int getButtonCount() {
return buttons.length;
}
private int transformY(int y) {
return nGetWindowHeight(display, window) - 1 - y;
}
private static native int nGetWindowHeight(long display, long window);
private static native int nGetWindowWidth(long display, long window);
private static native long nQueryPointer(long display, long window, IntBuffer result);
public void setCursorPosition(int x, int y) {
nWarpCursor(display, window, x, transformY(y));
}
private static native void nWarpCursor(long display, long window, int x, int y);
public void handlePointerMotion(boolean grab, boolean pointer_grabbed, boolean should_grab, long root_window, int x_root, int y_root, int x, int y) {
doHandlePointerMotion(grab, pointer_grabbed, should_grab, root_window, x_root, y_root, x, y);
}
private void handleButton(boolean grab, int button, byte state) {
int button_num;
switch (button) {
case Button1:
button_num = 0;
break;
case Button2:
button_num = 2;
break;
case Button3:
button_num = 1;
break;
default:
return;
}
buttons[button_num] = state;
putMouseEvent(grab, button_num, state, 0);
}
private void putMouseEvent(boolean grab, int button, int state, int dz) {
if (grab)
putMouseEventWithCoords(button, state, 0, 0, dz);
else
putMouseEventWithCoords(button, state, last_x, last_y, dz);
}
private void handleButtonPress(boolean grab, int button) {
int delta = 0;
switch (button) {
case Button4:
delta = WHEEL_SCALE;
putMouseEvent(grab, -1, 0, delta);
accum_dz += delta;
break;
case Button5:
delta = -WHEEL_SCALE;
putMouseEvent(grab, -1, 0, delta);
accum_dz += delta;
break;
default:
handleButton(grab, button, (byte)1);
break;
}
}
private void handleButtonRelease(boolean grab, int button) {
handleButton(grab, button, (byte)0);
}
public void handleButtonEvent(boolean grab, int type, int button) {
switch (type) {
case ButtonRelease:
handleButton(grab, button, (byte)0);
break;
case ButtonPress:
handleButtonPress(grab, button);
break;
default:
break;
}
}
private void resetCursor(int x, int y) {
last_x = x;
last_y = transformY(y);
}
public void handleWarpEvent(int x, int y) {
resetCursor(x, y);
}
}

View File

@ -119,66 +119,6 @@ void printfDebug(const char *format, ...) {
va_end(ap);
}
int getElementCapacity(event_queue_t *queue) {
return queue->limit - queue->position;
}
void initEventQueue(event_queue_t *queue, int event_size) {
queue->position = 0;
queue->limit = EVENT_BUFFER_SIZE;
queue->event_size = event_size;
}
bool putEvent(event_queue_t *queue, jint *event) {
int i;
if (getElementCapacity(queue) < queue->event_size) {
return false;
}
for (i = 0; i < queue->event_size; i++) {
queue->input_event_buffer[queue->position] = event[i];
queue->position++;
}
return true;
}
static void flip(event_queue_t *queue) {
queue->limit = queue->position;
queue->position = 0;
}
static void compact(event_queue_t *queue) {
int new_position = 0;
while (getElementCapacity(queue) > 0) {
queue->input_event_buffer[new_position] = queue->input_event_buffer[queue->position];
queue->position++;
new_position++;
}
queue->position = new_position;
queue->limit = EVENT_BUFFER_SIZE;
}
static void copyEvent(event_queue_t *queue, jint *output_event_buffer, int output_index) {
int i;
for (i = 0; i < queue->event_size; i++) {
output_event_buffer[output_index] = queue->input_event_buffer[queue->position];
queue->position++;
output_index++;
}
}
int copyEvents(event_queue_t *queue, jint *output_event_buffer, int buffer_size) {
int num_events = 0;
int index = 0;
flip(queue);
while (index + queue->event_size <= buffer_size && getElementCapacity(queue) >= queue->event_size) {
copyEvent(queue, output_event_buffer, index);
num_events++;
index += queue->event_size;
}
compact(queue);
return num_events;
}
static void throwFormattedGeneralException(JNIEnv * env, const char *exception_name, const char *format, va_list ap) {
jclass cls;
jstring str;
@ -361,3 +301,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
}
bool positionBuffer(JNIEnv *env, jobject buffer, jint position) {
jclass buffer_class;
jmethodID position_method;
buffer_class = (*env)->GetObjectClass(env, buffer);
if (buffer_class == NULL)
return false;
position_method = (*env)->GetMethodID(env, buffer_class, "position", "(I)Ljava/nio/Buffer;");
if (position_method == NULL)
return false;
(*env)->CallObjectMethod(env, buffer, position_method, position);
return true;
}

View File

@ -44,16 +44,8 @@
#include <string.h>
#include <stdlib.h>
#define EVENT_BUFFER_SIZE 256
#define ATTRIB_LIST_SIZE (256)
typedef struct {
int event_size;
int position;
int limit;
jint input_event_buffer[EVENT_BUFFER_SIZE];
} event_queue_t;
typedef struct {
int current_index;
int attribs[ATTRIB_LIST_SIZE];
@ -135,9 +127,6 @@ extern void putAttrib(attrib_list_t *list, int attrib);
extern bool isDebugEnabled(void);
extern jstring getVersionString(JNIEnv *env);
extern void initEventQueue(event_queue_t *event_queue, int event_size);
extern int copyEvents(event_queue_t *event_queue, jint *output_event_buffer, int buffer_size);
extern bool putEvent(event_queue_t *queue, jint *event);
extern void throwGeneralException(JNIEnv * env, const char *exception_name, const char * err);
extern void throwException(JNIEnv *env, const char *msg);
extern void throwFormattedException(JNIEnv * env, const char *format, ...);
@ -149,6 +138,7 @@ extern bool getBooleanProperty(JNIEnv *env, const char* propertyName);
extern char * GetStringNativeChars(JNIEnv *env, jstring jstr);
extern jstring NewStringNative(JNIEnv *env, const char *str);
extern jobject newJavaManagedByteBuffer(JNIEnv *env, const int size);
extern bool positionBuffer(JNIEnv *env, jobject buffer, jint position);
extern void ext_InitializeClass(JNIEnv *env, jclass clazz, ExtGetProcAddressPROC gpa, int num_functions, JavaMethodAndExtFunction *functions);
extern bool ext_InitializeFunctions(ExtGetProcAddressPROC gpa, int num_functions, ExtFunction *functions);

View File

@ -51,19 +51,6 @@
extern bool checkXError(JNIEnv *, Display *);
extern Atom getWarpAtom(void);
/*
* Various functions to release/acquire keyboard and mouse
*/
extern void handleWarpEvent(XClientMessageEvent *);
extern void handlePointerMotion(XMotionEvent *);
extern void handleButtonPress(XButtonEvent *);
extern void handleButtonRelease(XButtonEvent *);
extern void handleKeyEvent(XKeyEvent *);
extern void updatePointerGrab(jint);
extern void updateKeyboardGrab(jint);
extern void setGrab(jint, bool);
extern bool isGrabbed(void);
extern bool shouldGrab(void);
/*
* get the current display
@ -80,14 +67,4 @@
*/
extern Window getCurrentWindow(void);
/*
* Return true if we are in fullscreen mode
*/
extern bool isFullscreen(jint window_mode);
/*
* Return true if we are in exclusive fullscreen mode
*/
extern bool isLegacyFullscreen(jint window_mode);
#endif /* _LWJGL_WINDOW_H_INCLUDED_ */

View File

@ -408,15 +408,16 @@ JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetAvailableD
return getAvailableDisplayModes(env, getDisplay(), getCurrentScreen(), extension);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwitchDisplayMode(JNIEnv *env, jclass clazz, jint extension, jobject mode) {
switchDisplayMode(env, getCurrentScreen(), extension, mode);
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwitchDisplayMode(JNIEnv *env, jclass clazz, jint screen, jint extension, jobject mode) {
switchDisplayMode(env, screen, extension, mode);
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetGammaRampLength(JNIEnv *env, jclass clazz) {
return (jint)getGammaRampLengthOfDisplay(env, getDisplay(), getCurrentScreen());
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetGammaRampLength(JNIEnv *env, jclass clazz, jlong display_ptr, jint screen) {
Display *disp = (Display *)(intptr_t)display_ptr;
return (jint)getGammaRampLengthOfDisplay(env, disp, screen);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetGammaRamp(JNIEnv *env, jclass clazz, jobject gamma_buffer) {
setGammaRamp(env, getCurrentScreen(), gamma_buffer);
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetGammaRamp(JNIEnv *env, jclass clazz, jint screen, jobject gamma_buffer) {
setGammaRamp(env, screen, gamma_buffer);
}

View File

@ -1,692 +0,0 @@
/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* $Id$
*
* Linux keyboard handling.
*
* @author elias_naur <elias_naur@users.sourceforge.net>
* @version $Revision$
*/
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <string.h>
#include <assert.h>
#include <iconv.h>
#include <errno.h>
#include "Window.h"
#include "common_tools.h"
#include "org_lwjgl_input_Keyboard.h"
#include "org_lwjgl_opengl_LinuxDisplay.h"
#define KEYBOARD_BUFFER_SIZE 50
static jbyte key_buf[org_lwjgl_input_Keyboard_KEYBOARD_SIZE];
static int numlock_mask;
static int modeswitch_mask;
static int caps_lock_mask;
static int shift_lock_mask;
static event_queue_t event_queue;
static bool keyboard_grabbed;
static bool created = false;
// X input manager values
static iconv_t iconv_descriptor = (iconv_t)-1;
static XIM xim = NULL;
static XIC xic = NULL;
static void grabKeyboard(void) {
if (!keyboard_grabbed) {
int result = XGrabKeyboard(getDisplay(), getCurrentWindow(), False, GrabModeAsync, GrabModeAsync, CurrentTime);
if (result == GrabSuccess)
keyboard_grabbed = true;
}
}
static void ungrabKeyboard(void) {
if (keyboard_grabbed) {
keyboard_grabbed = false;
XUngrabKeyboard(getDisplay(), CurrentTime);
}
}
void updateKeyboardGrab(jint window_mode) {
if (!created)
return;
if (isLegacyFullscreen(window_mode)) {
grabKeyboard();
} else {
ungrabKeyboard();
}
}
static void cleanup() {
if (iconv_descriptor != (iconv_t)-1) {
iconv_close(iconv_descriptor);
iconv_descriptor = (iconv_t)-1;
}
if (xic != NULL) {
XDestroyIC(xic);
xic = NULL;
}
if (xim != NULL) {
XCloseIM(xim);
xim = NULL;
}
}
static void setupIMEventMask() {
long im_event_mask;
XWindowAttributes win_attributes;
XGetWindowAttributes(getDisplay(), getCurrentWindow(), &win_attributes);
XGetICValues(xic, XNFilterEvents, &im_event_mask, NULL);
XSelectInput(getDisplay(), getCurrentWindow(), win_attributes.your_event_mask | im_event_mask);
XSetICFocus(xic);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateKeyboard
(JNIEnv * env, jclass clazz, jint window_mode)
{
memset(key_buf, 0, org_lwjgl_input_Keyboard_KEYBOARD_SIZE*sizeof(jbyte));
created = true;
keyboard_grabbed = false;
initEventQueue(&event_queue, 3);
updateKeyboardGrab(window_mode);
XModifierKeymap *modifier_map = XGetModifierMapping(getDisplay());
numlock_mask = 0;
modeswitch_mask = 0;
caps_lock_mask = 0;
shift_lock_mask = 0;
if (modifier_map != NULL) {
// Find modifier masks
int i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < modifier_map->max_keypermod; j++) {
KeyCode key_code = modifier_map->modifiermap[i*modifier_map->max_keypermod + j];
KeySym key_sym = XKeycodeToKeysym(getDisplay(), key_code, 0);
int mask = 1 << i;
switch (key_sym) {
case XK_Num_Lock:
numlock_mask |= mask;
break;
case XK_Mode_switch:
modeswitch_mask |= mask;
break;
case XK_Caps_Lock:
if (i == LockMapIndex) {
caps_lock_mask = mask;
shift_lock_mask = 0;
}
break;
case XK_Shift_Lock:
if (i == LockMapIndex && caps_lock_mask == 0)
shift_lock_mask = mask;
break;
default:
break;
}
}
}
XFreeModifiermap(modifier_map);
}
// Allocate unicode structures
iconv_descriptor = iconv_open("UCS-2", "UTF-8");
if (iconv_descriptor != (iconv_t)-1) {
xim = XOpenIM(getDisplay(), NULL, NULL, NULL);
if (xim != NULL) {
xic = XCreateIC(xim, XNClientWindow, getCurrentWindow(), XNFocusWindow, getCurrentWindow(), XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL);
if (xic != NULL) {
setupIMEventMask();
} else {
cleanup();
}
} else
cleanup();
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyKeyboard
(JNIEnv * env, jclass clazz)
{
cleanup();
ungrabKeyboard();
created = false;
}
static unsigned char mapKeySymToLWJGLKeyCode(KeySym keysym) {
switch (keysym) {
case XK_BackSpace:
return org_lwjgl_input_Keyboard_KEY_BACK;
case XK_ISO_Left_Tab:
case XK_Tab:
return org_lwjgl_input_Keyboard_KEY_TAB;
case XK_Return:
return org_lwjgl_input_Keyboard_KEY_RETURN;
case XK_Pause:
return org_lwjgl_input_Keyboard_KEY_PAUSE;
case XK_Scroll_Lock:
return org_lwjgl_input_Keyboard_KEY_SCROLL;
case XK_Sys_Req:
return org_lwjgl_input_Keyboard_KEY_SYSRQ;
case XK_Escape:
return org_lwjgl_input_Keyboard_KEY_ESCAPE;
case XK_Delete:
return org_lwjgl_input_Keyboard_KEY_DELETE;
/* Japanese keyboard support */
case XK_Kanji:
return org_lwjgl_input_Keyboard_KEY_KANJI;
/* Cursor control & motion */
case XK_Home:
return org_lwjgl_input_Keyboard_KEY_HOME;
case XK_Left:
return org_lwjgl_input_Keyboard_KEY_LEFT;
case XK_Up:
return org_lwjgl_input_Keyboard_KEY_UP;
case XK_Right:
return org_lwjgl_input_Keyboard_KEY_RIGHT;
case XK_Down:
return org_lwjgl_input_Keyboard_KEY_DOWN;
case XK_Page_Up:
return org_lwjgl_input_Keyboard_KEY_PRIOR;
case XK_Page_Down:
return org_lwjgl_input_Keyboard_KEY_NEXT;
case XK_End:
return org_lwjgl_input_Keyboard_KEY_END;
/* Misc Functions */
case XK_Break:
return org_lwjgl_input_Keyboard_KEY_PAUSE;
case XK_Insert:
return org_lwjgl_input_Keyboard_KEY_INSERT;
case XK_Num_Lock:
return org_lwjgl_input_Keyboard_KEY_NUMLOCK;
/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
case XK_KP_Space:
return org_lwjgl_input_Keyboard_KEY_SPACE;
case XK_KP_Tab:
return org_lwjgl_input_Keyboard_KEY_TAB;
case XK_KP_Enter:
return org_lwjgl_input_Keyboard_KEY_NUMPADENTER;
case XK_KP_F1:
return org_lwjgl_input_Keyboard_KEY_F1;
case XK_KP_F2:
return org_lwjgl_input_Keyboard_KEY_F2;
case XK_KP_F3:
return org_lwjgl_input_Keyboard_KEY_F3;
case XK_KP_F4:
return org_lwjgl_input_Keyboard_KEY_F4;
case XK_KP_Home:
return org_lwjgl_input_Keyboard_KEY_HOME;
case XK_KP_Left:
return org_lwjgl_input_Keyboard_KEY_LEFT;
case XK_KP_Up:
return org_lwjgl_input_Keyboard_KEY_UP;
case XK_KP_Right:
return org_lwjgl_input_Keyboard_KEY_RIGHT;
case XK_KP_Down:
return org_lwjgl_input_Keyboard_KEY_DOWN;
case XK_KP_Page_Up:
return org_lwjgl_input_Keyboard_KEY_PRIOR;
case XK_KP_Page_Down:
return org_lwjgl_input_Keyboard_KEY_NEXT;
case XK_KP_End:
return org_lwjgl_input_Keyboard_KEY_END;
case XK_KP_Insert:
return org_lwjgl_input_Keyboard_KEY_INSERT;
case XK_KP_Delete:
return org_lwjgl_input_Keyboard_KEY_DELETE;
case XK_KP_Equal:
return org_lwjgl_input_Keyboard_KEY_NUMPADEQUALS;
case XK_KP_Multiply:
return org_lwjgl_input_Keyboard_KEY_MULTIPLY;
case XK_KP_Add:
return org_lwjgl_input_Keyboard_KEY_ADD;
case XK_KP_Subtract:
return org_lwjgl_input_Keyboard_KEY_SUBTRACT;
case XK_KP_Decimal:
return org_lwjgl_input_Keyboard_KEY_DECIMAL;
case XK_KP_Divide:
return org_lwjgl_input_Keyboard_KEY_DIVIDE;
case XK_KP_0:
return org_lwjgl_input_Keyboard_KEY_NUMPAD0;
case XK_KP_1:
return org_lwjgl_input_Keyboard_KEY_NUMPAD1;
case XK_KP_2:
return org_lwjgl_input_Keyboard_KEY_NUMPAD2;
case XK_KP_3:
return org_lwjgl_input_Keyboard_KEY_NUMPAD3;
case XK_KP_4:
return org_lwjgl_input_Keyboard_KEY_NUMPAD4;
case XK_KP_5:
return org_lwjgl_input_Keyboard_KEY_NUMPAD5;
case XK_KP_6:
return org_lwjgl_input_Keyboard_KEY_NUMPAD6;
case XK_KP_7:
return org_lwjgl_input_Keyboard_KEY_NUMPAD7;
case XK_KP_8:
return org_lwjgl_input_Keyboard_KEY_NUMPAD8;
case XK_KP_9:
return org_lwjgl_input_Keyboard_KEY_NUMPAD9;
/*
* Auxilliary Functions; note the duplicate definitions for left and right
* function keys; Sun keyboards and a few other manufactures have such
* function key groups on the left and/or right sides of the keyboard.
* We've not found a keyboard with more than 35 function keys total.
*/
case XK_F1:
return org_lwjgl_input_Keyboard_KEY_F1;
case XK_F2:
return org_lwjgl_input_Keyboard_KEY_F2;
case XK_F3:
return org_lwjgl_input_Keyboard_KEY_F3;
case XK_F4:
return org_lwjgl_input_Keyboard_KEY_F4;
case XK_F5:
return org_lwjgl_input_Keyboard_KEY_F5;
case XK_F6:
return org_lwjgl_input_Keyboard_KEY_F6;
case XK_F7:
return org_lwjgl_input_Keyboard_KEY_F7;
case XK_F8:
return org_lwjgl_input_Keyboard_KEY_F8;
case XK_F9:
return org_lwjgl_input_Keyboard_KEY_F9;
case XK_F10:
return org_lwjgl_input_Keyboard_KEY_F10;
case XK_F11:
return org_lwjgl_input_Keyboard_KEY_F11;
case XK_F12:
return org_lwjgl_input_Keyboard_KEY_F12;
case XK_F13:
return org_lwjgl_input_Keyboard_KEY_F13;
case XK_F14:
return org_lwjgl_input_Keyboard_KEY_F14;
case XK_F15:
return org_lwjgl_input_Keyboard_KEY_F15;
/* Modifiers */
case XK_Shift_L:
return org_lwjgl_input_Keyboard_KEY_LSHIFT;
case XK_Shift_R:
return org_lwjgl_input_Keyboard_KEY_RSHIFT;
case XK_Control_L:
return org_lwjgl_input_Keyboard_KEY_LCONTROL;
case XK_Control_R:
return org_lwjgl_input_Keyboard_KEY_RCONTROL;
case XK_Caps_Lock:
return org_lwjgl_input_Keyboard_KEY_CAPITAL;
case XK_Meta_L:
return org_lwjgl_input_Keyboard_KEY_LMENU;
case XK_Meta_R:
return org_lwjgl_input_Keyboard_KEY_RMENU;
case XK_Alt_L:
return org_lwjgl_input_Keyboard_KEY_LMENU;
case XK_Alt_R:
return org_lwjgl_input_Keyboard_KEY_RMENU;
case XK_dead_grave:
return org_lwjgl_input_Keyboard_KEY_GRAVE;
case XK_dead_circumflex:
return org_lwjgl_input_Keyboard_KEY_CIRCUMFLEX;
/*
* Latin 1
* Byte 3 = 0
*/
case XK_space:
return org_lwjgl_input_Keyboard_KEY_SPACE;
case XK_apostrophe:
return org_lwjgl_input_Keyboard_KEY_APOSTROPHE;
case XK_comma:
return org_lwjgl_input_Keyboard_KEY_COMMA;
case XK_minus:
return org_lwjgl_input_Keyboard_KEY_MINUS;
case XK_period:
return org_lwjgl_input_Keyboard_KEY_PERIOD;
case XK_slash:
return org_lwjgl_input_Keyboard_KEY_SLASH;
case XK_0:
return org_lwjgl_input_Keyboard_KEY_0;
case XK_1:
return org_lwjgl_input_Keyboard_KEY_1;
case XK_2:
return org_lwjgl_input_Keyboard_KEY_2;
case XK_3:
return org_lwjgl_input_Keyboard_KEY_3;
case XK_4:
return org_lwjgl_input_Keyboard_KEY_4;
case XK_5:
return org_lwjgl_input_Keyboard_KEY_5;
case XK_6:
return org_lwjgl_input_Keyboard_KEY_6;
case XK_7:
return org_lwjgl_input_Keyboard_KEY_7;
case XK_8:
return org_lwjgl_input_Keyboard_KEY_8;
case XK_9:
return org_lwjgl_input_Keyboard_KEY_9;
case XK_colon:
return org_lwjgl_input_Keyboard_KEY_COLON;
case XK_semicolon:
return org_lwjgl_input_Keyboard_KEY_SEMICOLON;
case XK_equal:
return org_lwjgl_input_Keyboard_KEY_EQUALS;
case XK_at:
return org_lwjgl_input_Keyboard_KEY_AT;
case XK_bracketleft:
return org_lwjgl_input_Keyboard_KEY_LBRACKET;
case XK_bracketright:
return org_lwjgl_input_Keyboard_KEY_RBRACKET;
case XK_asciicircum:
return org_lwjgl_input_Keyboard_KEY_CIRCUMFLEX;
case XK_underscore:
return org_lwjgl_input_Keyboard_KEY_UNDERLINE;
case XK_grave:
return org_lwjgl_input_Keyboard_KEY_GRAVE;
case XK_a:
case XK_A:
return org_lwjgl_input_Keyboard_KEY_A;
case XK_b:
case XK_B:
return org_lwjgl_input_Keyboard_KEY_B;
case XK_c:
case XK_C:
return org_lwjgl_input_Keyboard_KEY_C;
case XK_d:
case XK_D:
return org_lwjgl_input_Keyboard_KEY_D;
case XK_e:
case XK_E:
return org_lwjgl_input_Keyboard_KEY_E;
case XK_f:
case XK_F:
return org_lwjgl_input_Keyboard_KEY_F;
case XK_g:
case XK_G:
return org_lwjgl_input_Keyboard_KEY_G;
case XK_h:
case XK_H:
return org_lwjgl_input_Keyboard_KEY_H;
case XK_i:
case XK_I:
return org_lwjgl_input_Keyboard_KEY_I;
case XK_j:
case XK_J:
return org_lwjgl_input_Keyboard_KEY_J;
case XK_k:
case XK_K:
return org_lwjgl_input_Keyboard_KEY_K;
case XK_l:
case XK_L:
return org_lwjgl_input_Keyboard_KEY_L;
case XK_m:
case XK_M:
return org_lwjgl_input_Keyboard_KEY_M;
case XK_n:
case XK_N:
return org_lwjgl_input_Keyboard_KEY_N;
case XK_o:
case XK_O:
return org_lwjgl_input_Keyboard_KEY_O;
case XK_p:
case XK_P:
return org_lwjgl_input_Keyboard_KEY_P;
case XK_q:
case XK_Q:
return org_lwjgl_input_Keyboard_KEY_Q;
case XK_r:
case XK_R:
return org_lwjgl_input_Keyboard_KEY_R;
case XK_s:
case XK_S:
return org_lwjgl_input_Keyboard_KEY_S;
case XK_t:
case XK_T:
return org_lwjgl_input_Keyboard_KEY_T;
case XK_u:
case XK_U:
return org_lwjgl_input_Keyboard_KEY_U;
case XK_v:
case XK_V:
return org_lwjgl_input_Keyboard_KEY_V;
case XK_w:
case XK_W:
return org_lwjgl_input_Keyboard_KEY_W;
case XK_x:
case XK_X:
return org_lwjgl_input_Keyboard_KEY_X;
case XK_y:
case XK_Y:
return org_lwjgl_input_Keyboard_KEY_Y;
case XK_z:
case XK_Z:
return org_lwjgl_input_Keyboard_KEY_Z;
default:
return org_lwjgl_input_Keyboard_KEY_NONE;
}
}
static bool isKeypadKeysym(KeySym keysym) {
return (0xFF80 <= keysym && keysym <= 0xFFBD) ||
(0x11000000 <= keysym && keysym <= 0x1100FFFF);
}
static bool isNoSymbolOrVendorSpecific(KeySym keysym) {
return keysym == NoSymbol || (keysym & (1 << 28)) != 0;
}
static KeySym getKeySym(XKeyEvent *event, int group, int index) {
KeySym keysym = XLookupKeysym(event, group*2 + index);
if (isNoSymbolOrVendorSpecific(keysym) && index == 1) {
keysym = XLookupKeysym(event, group*2 + 0);
}
if (isNoSymbolOrVendorSpecific(keysym) && group == 1)
keysym = getKeySym(event, 0, index);
return keysym;
}
static KeySym toUpper(KeySym keysym) {
KeySym lower_case, upper_case;
XConvertCase(keysym, &lower_case, &upper_case);
return upper_case;
}
/* Map an event to a KeySym. Use the rules described in
* http://tronche.com/gui/x/xlib/input/keyboard-encoding.html
*/
static KeySym mapEventToKeySym(XKeyEvent *event) {
int group;
KeySym keysym;
if ((event->state & modeswitch_mask) != 0)
group = 1;
else
group = 0;
if ((event->state & numlock_mask) != 0 && isKeypadKeysym(keysym = getKeySym(event, group, 1))) {
if ((event->state & (ShiftMask | shift_lock_mask)) != 0) {
return getKeySym(event, group, 0);
} else {
return keysym;
}
} else if ((event->state & (ShiftMask | LockMask)) == 0) {
return getKeySym(event, group, 0);
} else if ((event->state & ShiftMask) == 0) {
KeySym keysym = getKeySym(event, group, 0);
if ((event->state & caps_lock_mask) != 0)
keysym = toUpper(keysym);
return keysym;
} else {
KeySym keysym = getKeySym(event, group, 1);
if ((event->state & caps_lock_mask) != 0)
keysym = toUpper(keysym);
return keysym;
}
}
static unsigned char getKeycode(XKeyEvent *event) {
unsigned char keycode;
KeySym keysym = mapEventToKeySym(event);
keycode = mapKeySymToLWJGLKeyCode(keysym);
if (keycode == org_lwjgl_input_Keyboard_KEY_NONE) {
// Try unshifted keysym mapping
keysym = XLookupKeysym(event, 0);
keycode = mapKeySymToLWJGLKeyCode(keysym);
}
return keycode;
}
static void putKeyboardEvent(jint keycode, jint state, jint ch) {
int event_list[] = {keycode, state, ch};
putEvent(&event_queue, event_list);
}
static int lookupStringISO88591(XKeyEvent *event, jint *translation_buffer) {
static XComposeStatus status;
char char_translation_buffer[KEYBOARD_BUFFER_SIZE];
int i;
int num_chars = XLookupString(event, char_translation_buffer, KEYBOARD_BUFFER_SIZE*sizeof(char), NULL, &status);
for (i = 0; i < num_chars; i++)
translation_buffer[i] = ((jint)char_translation_buffer[i]) & 0xff;
return num_chars;
}
static int lookupStringUnicode(XKeyEvent *event, jint *translation_buffer) {
char utf8_translation_buffer[KEYBOARD_BUFFER_SIZE];
jchar ucs2_translation_buffer[KEYBOARD_BUFFER_SIZE];
char *utf8_buf = utf8_translation_buffer;
jchar *ucs2_buf = ucs2_translation_buffer;
size_t ucs2_bytes = KEYBOARD_BUFFER_SIZE*sizeof(jchar);
Status status;
int i;
size_t utf8_bytes = Xutf8LookupString(xic, event, utf8_translation_buffer, KEYBOARD_BUFFER_SIZE*sizeof(char), NULL, &status);
if (status != XLookupChars && status != XLookupBoth)
return 0;
// reset converter
iconv(iconv_descriptor, NULL, NULL, NULL, NULL);
// convert from UTF-8 to UCS-2
size_t iconv_result = iconv(iconv_descriptor, &utf8_buf, &utf8_bytes, (void *)&ucs2_buf, &ucs2_bytes);
// compute number of characters converted
int num_chars_converted = KEYBOARD_BUFFER_SIZE - ucs2_bytes/sizeof(jchar);
if (iconv_result == (size_t)-1) {
errno = 0; // ignore conversion error and return no chars converted
return 0;
}
for (i = 0; i < num_chars_converted; i++) {
translation_buffer[i] = ((jint)ucs2_translation_buffer[i]) & 0xffff;
}
return num_chars_converted;
}
static int lookupString(XKeyEvent *event, jint *translation_buffer) {
if (xic != NULL) {
return lookupStringUnicode(event, translation_buffer);
} else
return lookupStringISO88591(event, translation_buffer);
}
static void translateEvent(XKeyEvent *event, jint keycode, jint state) {
jint temp_translation_buffer[KEYBOARD_BUFFER_SIZE];
int num_chars, i;
jint ch;
if (event->type == KeyRelease) {
putKeyboardEvent(keycode, state, 0);
return;
}
num_chars = lookupString(event, temp_translation_buffer);
if (num_chars > 0) {
ch = temp_translation_buffer[0];
putKeyboardEvent(keycode, state, ch);
for (i = 1; i < num_chars; i++) {
ch = temp_translation_buffer[i];
putKeyboardEvent(0, 0, ch);
}
} else {
putKeyboardEvent(keycode, state, 0);
}
}
static jbyte eventState(XKeyEvent *event) {
if (event->type == KeyPress) {
return 1;
} else if (event->type == KeyRelease) {
return 0;
} else
assert(0);
}
static void bufferEvent(XKeyEvent *key_event) {
unsigned char keycode = getKeycode(key_event);
unsigned char state = eventState(key_event);
translateEvent(key_event, keycode, state);
}
void handleKeyEvent(XKeyEvent *event) {
unsigned char keycode = getKeycode(event);
jbyte state = eventState(event);
key_buf[keycode] = state;
bufferEvent(event);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollKeyboard(JNIEnv * env, jclass clazz, jobject buffer) {
jbyte *new_keyboard_buffer = (jbyte *)(*env)->GetDirectBufferAddress(env, buffer);
memcpy(new_keyboard_buffer, key_buf, org_lwjgl_input_Keyboard_KEYBOARD_SIZE*sizeof(jbyte));
}
JNIEXPORT int JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadKeyboard(JNIEnv * env, jclass clazz, jobject buffer, jint buffer_position) {
jint* buffer_ptr = (jint *)(*env)->GetDirectBufferAddress(env, buffer);
int buffer_size = ((*env)->GetDirectBufferCapacity(env, buffer))/sizeof(jint) - buffer_position;
return copyEvents(&event_queue, buffer_ptr + buffer_position, buffer_size);
}

View File

@ -1,367 +0,0 @@
/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* $Id$
*
* Linux mouse handling.
*
* @author elias_naur <elias_naur@users.sourceforge.net>
* @version $Revision$
*/
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/Xcursor/Xcursor.h>
#include <assert.h>
#include <string.h>
#include "Window.h"
#include "common_tools.h"
#include "display.h"
#include "org_lwjgl_input_Mouse.h"
#include "org_lwjgl_opengl_LinuxDisplay.h"
#define EVENT_SIZE 5
#define POINTER_WARP_BORDER 10
// scale the mouse wheel according to win32
#define WHEEL_SCALE 120
static bool pointer_grabbed;
static bool created;
static int accum_dx;
static int accum_dy;
static int accum_dz;
static int last_x;
static int last_y;
static jbyte buttons[org_lwjgl_opengl_LinuxDisplay_NUM_BUTTONS];
static event_queue_t event_queue;
static Cursor blank_cursor;
static Cursor current_cursor;
static bool putMouseEventWithCoords(jint button, jint state, jint coord1, jint coord2, jint dz) {
jint event[] = {button, state, coord1, coord2, dz};
return putEvent(&event_queue, event);
}
static bool putMouseEvent(jint button, jint state, jint dz) {
if (isGrabbed())
return putMouseEventWithCoords(button, state, 0, 0, dz);
else
return putMouseEventWithCoords(button, state, last_x, last_y, dz);
}
static int transformY(int y) {
XWindowAttributes window_attributes;
XGetWindowAttributes(getDisplay(), getCurrentWindow(), &window_attributes);
return window_attributes.height - 1 - y;
}
static void setCursorPos(int x, int y) {
y = transformY(y);
jint dx = x - last_x;
jint dy = y - last_y;
accum_dx += dx;
accum_dy += dy;
last_x = x;
last_y = y;
if (isGrabbed()) {
putMouseEventWithCoords(-1, 0, dx, dy, 0);
} else {
putMouseEventWithCoords(-1, 0, x, y, 0);
}
}
static void resetCursor(int x, int y) {
last_x = x;
last_y = transformY(y);
}
static bool blankCursor(JNIEnv *env) {
unsigned int best_width, best_height;
if (XQueryBestCursor(getDisplay(), getCurrentWindow(), 1, 1, &best_width, &best_height) == 0) {
throwException(env, "Could not query best cursor size");
return false;
}
Pixmap mask = XCreatePixmap(getDisplay(), getCurrentWindow(), best_width, best_height, 1);
XGCValues gc_values;
gc_values.foreground = 0;
GC gc = XCreateGC(getDisplay(), mask, GCForeground, &gc_values);
XFillRectangle(getDisplay(), mask, gc, 0, 0, best_width, best_height);
XFreeGC(getDisplay(), gc);
XColor dummy_color;
blank_cursor = XCreatePixmapCursor(getDisplay(), mask, mask, &dummy_color, &dummy_color, 0, 0);
XFreePixmap(getDisplay(), mask);
return true;
}
static void updateCursor(void) {
Cursor cursor;
if (shouldGrab()) {
cursor = blank_cursor;
} else {
cursor = current_cursor;
}
XDefineCursor(getDisplay(), getCurrentWindow(), cursor);
}
static void grabPointer(jint window_mode) {
if (!pointer_grabbed) {
int result;
int grab_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
result = XGrabPointer(getDisplay(), getCurrentWindow(), False, grab_mask, GrabModeAsync,
GrabModeAsync, getCurrentWindow(), None, CurrentTime);
if (result == GrabSuccess) {
pointer_grabbed = true;
// make sure we have a centered window
if (isLegacyFullscreen(window_mode)) {
XWindowAttributes win_attribs;
XGetWindowAttributes(getDisplay(), getCurrentWindow(), &win_attribs);
XF86VidModeSetViewPort(getDisplay(), getCurrentScreen(), win_attribs.x, win_attribs.y);
}
XFlush(getDisplay());
}
}
}
static void ungrabPointer(void) {
if (pointer_grabbed) {
pointer_grabbed = false;
XUngrabPointer(getDisplay(), CurrentTime);
XFlush(getDisplay());
}
}
void updatePointerGrab(jint window_mode) {
if (!created)
return;
if (isFullscreen(window_mode) || shouldGrab()) {
grabPointer(window_mode);
} else {
ungrabPointer();
}
updateCursor();
}
void handleWarpEvent(XClientMessageEvent *event) {
int center_x = event->data.l[0];
int center_y = event->data.l[1];
resetCursor(center_x, center_y);
}
static void doWarpPointer(int center_x, int center_y) {
XEvent warp_event;
warp_event.type = ClientMessage;
warp_event.xclient.window = getCurrentWindow();
warp_event.xclient.message_type = getWarpAtom();
warp_event.xclient.format = 32;
warp_event.xclient.data.l[0] = center_x;
warp_event.xclient.data.l[1] = center_y;
XSendEvent(getDisplay(), getCurrentWindow(), False, 0, &warp_event);
XWarpPointer(getDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, center_x, center_y);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetNativeCursor(JNIEnv *env, jclass clazz, jobject cursor_handle) {
if (cursor_handle != NULL) {
Cursor *cursor = (Cursor *)(*env)->GetDirectBufferAddress(env, cursor_handle);
current_cursor = *cursor;
} else
current_cursor = None;
updateCursor();
}
static void reset(void) {
initEventQueue(&event_queue, EVENT_SIZE);
accum_dx = accum_dy = 0;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateMouse
(JNIEnv * env, jclass clazz, jint window_mode)
{
int i;
last_y = last_x = accum_dx = accum_dy = accum_dz = 0;
reset();
for (i = 0; i < org_lwjgl_opengl_LinuxDisplay_NUM_BUTTONS; i++)
buttons[i] = 0;
if (!blankCursor(env)) {
return;
}
current_cursor = None;
created = true;
pointer_grabbed = false;
updatePointerGrab(window_mode);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyMouse
(JNIEnv * env, jclass clazz)
{
ungrabPointer();
XFreeCursor(getDisplay(), blank_cursor);
created = false;
}
static unsigned char mapButton(XButtonEvent *event) {
switch (event->button) {
case Button1:
return 0;
case Button2:
return 2;
case Button3:
return 1;
default: return org_lwjgl_opengl_LinuxDisplay_NUM_BUTTONS;
}
}
static void handleButton(XButtonEvent *event, unsigned char state) {
unsigned char button_num = mapButton(event);
if (button_num == org_lwjgl_opengl_LinuxDisplay_NUM_BUTTONS)
return;
buttons[button_num] = state;
putMouseEvent(button_num, state, 0);
}
void handleButtonPress(XButtonEvent *event) {
jint delta = 0;
switch (event->button) {
case Button4:
delta = WHEEL_SCALE;
putMouseEvent(-1, 0, delta);
break;
case Button5:
delta = -WHEEL_SCALE;
putMouseEvent(-1, 0, delta);
break;
default:
break;
}
accum_dz += delta;
handleButton(event, 1);
}
void handleButtonRelease(XButtonEvent *event) {
handleButton(event, 0);
}
static int max(int v1, int v2) {
return v1 > v2 ? v1 : v2;
}
static int min(int v1, int v2) {
return v1 < v2 ? v1 : v2;
}
static void doHandlePointerMotion(Window root_window, Window window, int root_x, int root_y, int win_x, int win_y) {
setCursorPos(win_x, win_y);
if (!pointer_grabbed || !shouldGrab())
return;
XWindowAttributes window_attributes;
XGetWindowAttributes(getDisplay(), root_window, &window_attributes);
int root_window_width = window_attributes.width;
int root_window_height = window_attributes.height;
XGetWindowAttributes(getDisplay(), window, &window_attributes);
int window_width = window_attributes.width;
int window_height = window_attributes.height;
// find the window position in root coordinates
int win_left = root_x - win_x;
int win_top = root_y - win_y;
int win_right = win_left + window_width;
int win_bottom = win_top + window_height;
// cap the window position to the screen dimensions
int border_left = max(0, win_left);
int border_top = max(0, win_top);
int border_right = min(root_window_width, win_right);
int border_bottom = min(root_window_height, win_bottom);
// determine whether the cursor is outside the bounds
bool outside_limits = root_x < border_left + POINTER_WARP_BORDER || root_y < border_top + POINTER_WARP_BORDER ||
root_x > border_right - POINTER_WARP_BORDER || root_y > border_bottom - POINTER_WARP_BORDER;
if (outside_limits) {
// Find the center of the limits in window coordinates
int center_x = (border_right - border_left)/2;
int center_y = (border_bottom - border_top)/2;
doWarpPointer(center_x, center_y);
}
}
void handlePointerMotion(XMotionEvent *event) {
doHandlePointerMotion(event->root, getCurrentWindow(), event->x_root, event->y_root, event->x, event->y);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollMouse(JNIEnv * env, jclass clazz, jobject coord_buffer_obj, jobject button_buffer_obj) {
int *coords = (int *)(*env)->GetDirectBufferAddress(env, coord_buffer_obj);
int coords_length = (*env)->GetDirectBufferCapacity(env, coord_buffer_obj);
unsigned char *buttons_buffer = (unsigned char *)(*env)->GetDirectBufferAddress(env, button_buffer_obj);
int buttons_length = (*env)->GetDirectBufferCapacity(env, button_buffer_obj);
if (coords_length < 3) {
printfDebugJava(env, "ERROR: Not enough space in coords array: %d < 3", coords_length);
return;
}
if (isGrabbed()) {
coords[0] = accum_dx;
coords[1] = accum_dy;
} else {
coords[0] = last_x;
coords[1] = last_y;
}
coords[2] = accum_dz;
accum_dx = accum_dy = accum_dz = 0;
int num_buttons = org_lwjgl_opengl_LinuxDisplay_NUM_BUTTONS;
if (num_buttons > buttons_length)
num_buttons = buttons_length;
int i;
for (i = 0; i < num_buttons; i++)
buttons_buffer[i] = buttons[i];
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadMouse(JNIEnv *env, jclass clazz, jobject buffer, jint buffer_position) {
jint* buffer_ptr = (jint *)(*env)->GetDirectBufferAddress(env, buffer);
int buffer_size = ((*env)->GetDirectBufferCapacity(env, buffer))/sizeof(jint) - buffer_position;
return copyEvents(&event_queue, buffer_ptr + buffer_position, buffer_size);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetCursorPosition(JNIEnv * env, jclass clazz, jint x, jint y) {
XWarpPointer(getDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, x, transformY(y));
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabMouse(JNIEnv * env, jclass clazz, jint window_mode, jboolean new_grab) {
Window root_return, child_return;
int root_x, root_y, win_x, win_y;
unsigned int mask_return;
setGrab(window_mode, new_grab == JNI_TRUE ? true : false);
reset();
XQueryPointer(getDisplay(), getCurrentWindow(), &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask_return);
doHandlePointerMotion(root_return, getCurrentWindow(), root_x, root_y, win_x, win_y);
}

View File

@ -42,6 +42,7 @@
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@ -78,11 +79,8 @@ static Pixmap current_icon_pixmap;
static Visual *current_visual;
static bool input_released;
static bool dirty;
static bool minimized;
static bool focused;
static bool closerequested;
static bool grab;
@ -151,25 +149,15 @@ static void waitMapped(Window win) {
} while ((event.type != MapNotify) || (event.xmap.event != win));
}
static void updateInputGrab(jint window_mode) {
updatePointerGrab(window_mode);
updateKeyboardGrab(window_mode);
}
static void setRepeatMode(JNIEnv *env, int mode) {
XKeyboardControl repeat_mode;
repeat_mode.auto_repeat_mode = mode;
static void __attribute__ ((destructor)) my_fini(void) {
Display *disp = XOpenDisplay(NULL);
if (disp == NULL && env != NULL) {
printfDebugJava(env, "Could not open display to set repeat mode");
if (disp == NULL) {
return;
}
XKeyboardControl repeat_mode;
repeat_mode.auto_repeat_mode = AutoRepeatModeDefault;
XChangeKeyboardControl(disp, KBAutoRepeatMode, &repeat_mode);
XCloseDisplay(disp);
}
static void __attribute__ ((destructor)) my_fini(void) {
setRepeatMode(NULL, AutoRepeatModeDefault);
}
static void setDecorations(int dec) {
@ -180,71 +168,25 @@ static void setDecorations(int dec) {
XChangeProperty (getDisplay(), getCurrentWindow(), motif_hints_atom, motif_hints_atom, 32, PropModeReplace, (unsigned char *)&motif_hints, sizeof(MotifWmHints)/sizeof(long));
}
static bool releaseInput(JNIEnv *env, jint extension, jint window_mode, jobject gamma_ramp, jobject saved_mode) {
if (isLegacyFullscreen(window_mode) || input_released)
return false;
input_released = true;
setRepeatMode(env, AutoRepeatModeDefault);
updateInputGrab(window_mode);
if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) {
XIconifyWindow(getDisplay(), getCurrentWindow(), getCurrentScreen());
switchDisplayMode(env, getCurrentScreen(), extension, saved_mode);
setGammaRamp(env, getCurrentScreen(), gamma_ramp);
}
return true;
}
static void acquireInput(JNIEnv *env, jint extension, jint window_mode, jobject gamma_ramp, jobject mode) {
if (isLegacyFullscreen(window_mode) || !input_released)
return;
input_released = false;
setRepeatMode(env, AutoRepeatModeOff);
updateInputGrab(window_mode);
if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) {
switchDisplayMode(env, getCurrentScreen(), extension, mode);
setGammaRamp(env, getCurrentScreen(), gamma_ramp);
}
}
bool isFullscreen(jint window_mode) {
return window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_LEGACY || window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM;
}
bool isLegacyFullscreen(jint window_mode) {
static bool isLegacyFullscreen(jint window_mode) {
return window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_LEGACY;
}
bool shouldGrab(void) {
return !input_released && grab;
}
bool isGrabbed(void) {
return grab;
}
void setGrab(jint window_mode, bool new_grab) {
if (new_grab != grab) {
grab = new_grab;
updateInputGrab(window_mode);
}
}
static void checkInput(JNIEnv *env, jint extension, jint window_mode, jobject saved_gamma, jobject current_gamma, jobject saved_mode, jobject current_mode) {
Window win;
int revert_mode;
XGetInputFocus(getDisplay(), &win, &revert_mode);
if (win == current_win) {
acquireInput(env, extension, window_mode, current_gamma, current_mode);
focused = true;
} else {
releaseInput(env, extension, window_mode, saved_gamma, saved_mode);
focused = false;
}
}
static void handleMessages(JNIEnv *env, jint extension, jint window_mode, jobject saved_gamma, jobject current_gamma, jobject saved_mode, jobject current_mode) {
static void handleMessages(JNIEnv *env, jclass disp_class) {
XEvent event;
while (XPending(getDisplay()) > 0) {
jmethodID handleKeyEvent_method = (*env)->GetStaticMethodID(env, disp_class, "handleKeyEvent", "(JJIII)V");
if (handleKeyEvent_method == NULL)
return;
jmethodID handleButtonEvent_method = (*env)->GetStaticMethodID(env, disp_class, "handleButtonEvent", "(JIII)V");
if (handleButtonEvent_method == NULL)
return;
jmethodID handlePointerMotionEvent_method = (*env)->GetStaticMethodID(env, disp_class, "handlePointerMotionEvent", "(JIIIII)V");
if (handlePointerMotionEvent_method == NULL)
return;
jmethodID handleWarpEvent_method = (*env)->GetStaticMethodID(env, disp_class, "handleWarpEvent", "(II)V");
if (handleWarpEvent_method == NULL)
return;
while (!(*env)->ExceptionOccurred(env) && XPending(getDisplay()) > 0) {
XNextEvent(getDisplay(), &event);
if (XFilterEvent(&event, None) == True)
continue;
@ -254,7 +196,7 @@ static void handleMessages(JNIEnv *env, jint extension, jint window_mode, jobjec
switch (event.type) {
case ClientMessage:
if (event.xclient.message_type == warp_atom) {
handleWarpEvent(&(event.xclient));
(*env)->CallStaticVoidMethod(env, disp_class, handleWarpEvent_method, (jint)event.xclient.data.l[0], (jint)event.xclient.data.l[1]);
} else if ((event.xclient.format == 32) && ((Atom)event.xclient.data.l[0] == delete_atom))
closerequested = true;
break;
@ -269,22 +211,19 @@ static void handleMessages(JNIEnv *env, jint extension, jint window_mode, jobjec
case Expose:
dirty = true;
break;
case ButtonPress:
handleButtonPress(&(event.xbutton));
break;
case ButtonPress: /* Fall through */
case ButtonRelease:
handleButtonRelease(&(event.xbutton));
(*env)->CallStaticVoidMethod(env, disp_class, handleButtonEvent_method, (jlong)event.xbutton.time, (jint)event.xbutton.type, (jint)event.xbutton.button, (jint)event.xbutton.state);
break;
case MotionNotify:
handlePointerMotion(&(event.xmotion));
(*env)->CallStaticVoidMethod(env, disp_class, handlePointerMotionEvent_method, (jlong)event.xbutton.root, (jint)event.xbutton.x_root, (jint)event.xbutton.y_root, (jint)event.xbutton.x, (jint)event.xbutton.y, (jint)event.xbutton.state);
break;
case KeyPress:
case KeyRelease:
handleKeyEvent(&(event.xkey));
(*env)->CallStaticVoidMethod(env, disp_class, handleKeyEvent_method, (jlong)(intptr_t)&(event.xkey), (jlong)event.xkey.time, (jint)event.xkey.type, (jint)event.xkey.keycode, (jint)event.xkey.state);
break;
}
}
checkInput(env, extension, window_mode, saved_gamma, current_gamma, saved_mode, current_mode);
}
static void setWindowTitle(const char *title) {
@ -332,7 +271,6 @@ static void destroyWindow(JNIEnv *env) {
XDestroyWindow(getDisplay(), current_win);
XFreeColormap(getDisplay(), cmap);
freeIconPixmap();
setRepeatMode(env, AutoRepeatModeDefault);
}
static bool isNetWMFullscreenSupported(JNIEnv *env) {
@ -371,7 +309,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReshape(JNIEnv *env,
static bool createWindow(JNIEnv* env, jint window_mode, X11PeerInfo *peer_info, int x, int y, int width, int height) {
bool undecorated = getBooleanProperty(env, "org.lwjgl.opengl.Window.undecorated");
dirty = true;
focused = true;
minimized = false;
closerequested = false;
grab = false;
@ -380,7 +317,6 @@ static bool createWindow(JNIEnv* env, jint window_mode, X11PeerInfo *peer_info,
XSetWindowAttributes attribs;
int attribmask;
input_released = false;
root_win = RootWindow(getDisplay(), getCurrentScreen());
XVisualInfo *vis_info = getVisualInfoFromPeerInfo(env, peer_info);
if (vis_info == NULL)
@ -429,7 +365,6 @@ static bool createWindow(JNIEnv* env, jint window_mode, X11PeerInfo *peer_info,
XMapRaised(getDisplay(), win);
waitMapped(win);
XClearWindow(getDisplay(), win);
setRepeatMode(env, AutoRepeatModeOff);
if (!checkXError(env, getDisplay())) {
destroyWindow(env);
return false;
@ -444,7 +379,7 @@ Window getCurrentWindow(void) {
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUpdate
(JNIEnv *env, jclass clazz, jint extension, jint window_mode, jobject saved_gamma, jobject current_gamma, jobject saved_mode, jobject current_mode)
{
handleMessages(env, extension, window_mode, saved_gamma, current_gamma, saved_mode, current_mode);
handleMessages(env, clazz);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jobject peer_info_handle, jobject mode, jint window_mode, jint x, jint y) {
@ -497,11 +432,6 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsCloseRequested
return saved;
}
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsActive
(JNIEnv *env, jclass clazz, jint window_mode) {
return focused || isLegacyFullscreen(window_mode) ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nLockAWT(JNIEnv *env, jclass clazz) {
JAWT jawt;
jawt.version = JAWT_VERSION_1_4;
@ -572,3 +502,103 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowIcon
setIcon(env, imgData, icon_size, width, height);
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getDisplay(JNIEnv *env, jclass unused) {
return (intptr_t)getDisplay();
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getWindow(JNIEnv *env, jclass unused) {
return getCurrentWindow();
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUngrabKeyboard(JNIEnv *env, jclass unused, jlong display_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
return XUngrabKeyboard(disp, CurrentTime);
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabKeyboard(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
return XGrabKeyboard(disp, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabPointer(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
int grab_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
return XGrabPointer(disp, win, False, grab_mask, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetViewPort(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jint screen) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
XWindowAttributes win_attribs;
XGetWindowAttributes(disp, win, &win_attribs);
XF86VidModeSetViewPort(disp, screen, win_attribs.x, win_attribs.y);
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUngrabPointer(JNIEnv *env, jclass unused, jlong display_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
return XUngrabPointer(disp, CurrentTime);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDefineCursor(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jobject cursor_handle) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
Cursor cursor;
if (cursor_handle != NULL)
cursor = *((Cursor *)(*env)->GetDirectBufferAddress(env, cursor_handle));
else
cursor = None;
XDefineCursor(disp, win, cursor);
}
JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateBlankCursor(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
jobject handle_buffer = newJavaManagedByteBuffer(env, sizeof(Cursor));
if (handle_buffer == NULL) {
return NULL;
}
Cursor *cursor = (Cursor *)(*env)->GetDirectBufferAddress(env, handle_buffer);
unsigned int best_width, best_height;
if (XQueryBestCursor(disp, win, 1, 1, &best_width, &best_height) == 0) {
throwException(env, "Could not query best cursor size");
return false;
}
Pixmap mask = XCreatePixmap(disp, win, best_width, best_height, 1);
XGCValues gc_values;
gc_values.foreground = 0;
GC gc = XCreateGC(disp, mask, GCForeground, &gc_values);
XFillRectangle(disp, mask, gc, 0, 0, best_width, best_height);
XFreeGC(disp, gc);
XColor dummy_color;
*cursor = XCreatePixmapCursor(disp, mask, mask, &dummy_color, &dummy_color, 0, 0);
XFreePixmap(disp, mask);
return handle_buffer;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getScreen(JNIEnv *env, jclass unsused) {
return getCurrentScreen();
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetInputFocus(JNIEnv *env, jclass unused, jlong display_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
int revert_mode;
Window win;
XGetInputFocus(disp, &win, &revert_mode);
return win;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetRepeatMode(JNIEnv *env, jclass unused, jlong display_ptr, jint mode) {
Display *disp = (Display *)(intptr_t)display_ptr;
XKeyboardControl repeat_mode;
repeat_mode.auto_repeat_mode = mode;
XChangeKeyboardControl(disp, KBAutoRepeatMode, &repeat_mode);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIconifyWindow(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jint screen) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
XIconifyWindow(disp, win, screen);
}

View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* $Id: org_lwjgl_input_Keyboard.c 2399 2006-06-30 19:28:00Z elias_naur $
*
* Linux keyboard handling.
*
* @author elias_naur <elias_naur@users.sourceforge.net>
* @version $Revision: 2399 $
*/
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include "Window.h"
#include "common_tools.h"
#include "org_lwjgl_opengl_LinuxKeyboard.h"
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_getModifierMapping(JNIEnv *env, jclass unused, jlong display_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
XModifierKeymap *modifier_map = XGetModifierMapping(disp);
return (intptr_t)modifier_map;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_freeModifierMapping(JNIEnv *env, jclass unused, jlong mapping_ptr) {
XModifierKeymap *modifier_map = (XModifierKeymap *)(intptr_t)mapping_ptr;
XFreeModifiermap(modifier_map);
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_getMaxKeyPerMod(JNIEnv *env, jclass unsused, jlong mapping_ptr) {
XModifierKeymap *modifier_map = (XModifierKeymap *)(intptr_t)mapping_ptr;
return modifier_map->max_keypermod;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_lookupModifierMap(JNIEnv *env, jclass unused, jlong mapping_ptr, jint index) {
XModifierKeymap *modifier_map = (XModifierKeymap *)(intptr_t)mapping_ptr;
KeyCode key_code = modifier_map->modifiermap[index];
return key_code;
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_keycodeToKeySym(JNIEnv *env, jclass unused, jlong display_ptr, jint key_code) {
Display *disp = (Display *)(intptr_t)display_ptr;
KeySym key_sym = XKeycodeToKeysym(disp, key_code, 0);
return key_sym;
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_openIM(JNIEnv *env, jclass unused, jlong display_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
XIM xim = XOpenIM(disp, NULL, NULL, NULL);
return (intptr_t)xim;
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_createIC(JNIEnv *env, jclass unused, jlong xim_ptr, jlong window_ptr) {
Window win = (Window)window_ptr;
XIM xim = (XIM)(intptr_t)xim_ptr;
XIC xic = XCreateIC(xim, XNClientWindow, win, XNFocusWindow, win, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL);
return (intptr_t)xic;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_setupIMEventMask(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jlong xic_ptr) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
XIC xic = (XIC)(intptr_t)xic_ptr;
long im_event_mask;
XWindowAttributes win_attributes;
XGetWindowAttributes(disp, win, &win_attributes);
XGetICValues(xic, XNFilterEvents, &im_event_mask, NULL);
XSelectInput(disp, win, win_attributes.your_event_mask | im_event_mask);
XSetICFocus(xic);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_destroyIC(JNIEnv *env, jclass unused, jlong xic_ptr) {
XIC xic = (XIC)(intptr_t)xic_ptr;
XDestroyIC(xic);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_closeIM(JNIEnv *env, jclass unused, jlong xim_ptr) {
XIM xim = (XIM)(intptr_t)xim_ptr;
XCloseIM(xim);
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_lookupKeysym(JNIEnv *env, jclass unused, jlong event_ptr, jint index) {
XKeyEvent *event = (XKeyEvent *)(intptr_t)event_ptr;
return XLookupKeysym(event, index);
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_toUpper(JNIEnv *env, jclass unused, jlong keysym) {
KeySym lower_case, upper_case;
XConvertCase(keysym, &lower_case, &upper_case);
return upper_case;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_lookupString(JNIEnv *env, jclass unused, jlong event_ptr, jobject buffer_obj, jobject compose_status_obj) {
XKeyEvent *event = (XKeyEvent *)(intptr_t)event_ptr;
char *buffer = (char *)(*env)->GetDirectBufferAddress(env, buffer_obj);
int capacity = (*env)->GetDirectBufferCapacity(env, buffer_obj);
XComposeStatus *status = (XComposeStatus *)(*env)->GetDirectBufferAddress(env, compose_status_obj);
return XLookupString(event, buffer, capacity, NULL, status);
}
JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_allocateComposeStatus(JNIEnv *env, jclass unused) {
return newJavaManagedByteBuffer(env, sizeof(XComposeStatus));
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_utf8LookupString(JNIEnv *env, jclass unused, jlong xic_ptr, jlong event_ptr, jobject buffer_obj, jint buffer_position, jint buffer_size) {
XIC xic = (XIC)(intptr_t)xic_ptr;
XKeyEvent *event = (XKeyEvent *)(intptr_t)event_ptr;
char *buffer = buffer_position + (char *)(*env)->GetDirectBufferAddress(env, buffer_obj);
Status status;
size_t num_bytes = Xutf8LookupString(xic, event, buffer, buffer_size, NULL, &status);
positionBuffer(env, buffer_obj, num_bytes);
return status;
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* $Id: org_lwjgl_input_Keyboard.c 2399 2006-06-30 19:28:00Z elias_naur $
*
* Linux mouse handling.
*
* @author elias_naur <elias_naur@users.sourceforge.net>
* @version $Revision: 2399 $
*/
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "Window.h"
#include "common_tools.h"
#include "org_lwjgl_opengl_LinuxMouse.h"
static void getWindowAttributes(jlong display_ptr, jlong window_ptr, XWindowAttributes *attr) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
XGetWindowAttributes(disp, win, attr);
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxMouse_nGetWindowHeight(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
XWindowAttributes window_attributes;
getWindowAttributes(display_ptr, window_ptr, &window_attributes);
return window_attributes.height;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxMouse_nGetWindowWidth(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
XWindowAttributes window_attributes;
getWindowAttributes(display_ptr, window_ptr, &window_attributes);
return window_attributes.width;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxMouse_nWarpCursor(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jint x, jint y) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
XWarpPointer(disp, None, win, 0, 0, 0, 0, x, y);
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxMouse_nQueryPointer(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jobject result_buffer) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
Window root_return, child_return;
int root_x, root_y, win_x, win_y;
unsigned int mask_return;
jint *result = (jint *)(*env)->GetDirectBufferAddress(env, result_buffer);
int result_size = (*env)->GetDirectBufferCapacity(env, result_buffer);
if (result_size < 4) {
throwFormattedException(env, "Not enough space in result buffer (%d)", result_size);
return (intptr_t)NULL;
}
XQueryPointer(disp, win, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask_return);
result[0] = root_x;
result[1] = root_y;
result[2] = win_x;
result[3] = win_y;
return root_return;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxMouse_nSendWarpEvent(JNIEnv *env, jclass unusued, jlong display_ptr, jlong window_ptr, jint x, jint y) {
Display *disp = (Display *)(intptr_t)display_ptr;
Window win = (Window)window_ptr;
XEvent warp_event;
warp_event.type = ClientMessage;
warp_event.xclient.window = win;
warp_event.xclient.message_type = getWarpAtom();
warp_event.xclient.format = 32;
warp_event.xclient.data.l[0] = x;
warp_event.xclient.data.l[1] = y;
XSendEvent(disp, win, False, 0, &warp_event);
}

View File

@ -61,17 +61,3 @@ HRESULT objectCallback(JNIEnv *env, jobject enumerator, jint object_type, const
return should_continue == JNI_TRUE ? true : false;
}
bool positionBuffer(JNIEnv *env, jobject buffer, jint position) {
jclass buffer_class;
jmethodID position_method;
buffer_class = (*env)->GetObjectClass(env, buffer);
if (buffer_class == NULL)
return false;
position_method = (*env)->GetMethodID(env, buffer_class, "position", "(I)Ljava/nio/Buffer;");
if (position_method == NULL)
return false;
(*env)->CallObjectMethod(env, buffer, position_method, position);
return true;
}

View File

@ -49,6 +49,5 @@ typedef struct {
} enum_context_t;
HRESULT objectCallback(JNIEnv *env, jobject enumerator, jint object_type, const char *tszName);
bool positionBuffer(JNIEnv *env, jobject buffer, jint position);
#endif