From e23825c3e57c9d0d46aefe71d7afb96aa4193b9a Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Tue, 24 Oct 2006 09:52:12 +0000 Subject: [PATCH] Linux: Moved more event handling logic to java --- build.xml | 1 + src/java/org/lwjgl/opengl/LinuxDisplay.java | 56 +++++- src/java/org/lwjgl/opengl/LinuxEvent.java | 173 ++++++++++++++++++ src/native/linux/org_lwjgl_opengl_Display.c | 77 +------- .../linux/org_lwjgl_opengl_LinuxEvent.c | 161 ++++++++++++++++ 5 files changed, 385 insertions(+), 83 deletions(-) create mode 100644 src/java/org/lwjgl/opengl/LinuxEvent.java create mode 100644 src/native/linux/org_lwjgl_opengl_LinuxEvent.c diff --git a/build.xml b/build.xml index ef503ffd..f9e581f3 100644 --- a/build.xml +++ b/build.xml @@ -494,6 +494,7 @@ + diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java index 02503c27..48c21bb3 100644 --- a/src/java/org/lwjgl/opengl/LinuxDisplay.java +++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java @@ -82,11 +82,15 @@ final class LinuxDisplay implements DisplayImplementation { private static int display_connection_usage_count = 0; + /** Event buffer */ + private final LinuxEvent event_buffer = new LinuxEvent(); + /** Current mode swithcing API */ private int current_displaymode_extension = NONE; /** Atom used for the pointer warp messages */ private long warp_atom; + private long delete_atom; private PeerInfo peer_info; @@ -268,8 +272,8 @@ final class LinuxDisplay implements DisplayImplementation { } } - private static native long openDisplay() throws LWJGLException; - private static native void closeDisplay(long display); + static native long openDisplay() throws LWJGLException; + static native void closeDisplay(long display); private int getWindowMode(boolean fullscreen) throws LWJGLException { if (fullscreen) { @@ -552,6 +556,7 @@ final class LinuxDisplay implements DisplayImplementation { lockAWT(); try { warp_atom = getWarpAtom(); + delete_atom = internAtom("WM_DELETE_WINDOW", false); current_displaymode_extension = getBestDisplayModeExtension(); if (current_displaymode_extension == NONE) throw new LWJGLException("No display mode extension is available"); @@ -629,18 +634,56 @@ final class LinuxDisplay implements DisplayImplementation { return peer_info; } + private void processEvents() { + while (LinuxEvent.getPending(getDisplay()) > 0) { + event_buffer.nextEvent(getDisplay()); + long event_window = event_buffer.getWindow(); + if (event_window != getWindow()) + continue; + if (event_buffer.filterEvent(event_window)) + continue; + switch (event_buffer.getType()) { + case LinuxEvent.ClientMessage: + if (event_buffer.getClientMessageType() == warp_atom) { + handleWarpEvent(event_buffer.getClientData(0), event_buffer.getClientData(1)); + } else if ((event_buffer.getClientFormat() == 32) && (event_buffer.getClientData(0) == delete_atom)) + handleCloseEvent(); + break; + case LinuxEvent.MapNotify: + handleMapNotifyEvent(); + break; + case LinuxEvent.UnmapNotify: + handleUnmapNotifyEvent(); + break; + case LinuxEvent.Expose: + handleExposeEvent(); + break; + case LinuxEvent.ButtonPress: /* Fall through */ + case LinuxEvent.ButtonRelease: + handleButtonEvent(event_buffer.getButtonTime(), event_buffer.getButtonType(), event_buffer.getButtonButton(), event_buffer.getButtonState()); + break; + case LinuxEvent.MotionNotify: + handlePointerMotionEvent(event_buffer.getButtonTime(), event_buffer.getButtonRoot(), event_buffer.getButtonXRoot(), event_buffer.getButtonYRoot(), event_buffer.getButtonX(), event_buffer.getButtonY(), event_buffer.getButtonState()); + break; + case LinuxEvent.KeyPress: /* Fall through */ + case LinuxEvent.KeyRelease: + handleKeyEvent(event_buffer.getKeyAddress(), event_buffer.getKeyTime(), event_buffer.getKeyType(), event_buffer.getKeyKeyCode(), event_buffer.getKeyState()); + break; + default: + break; + } + } + } + public void update() { lockAWT(); try { - nUpdate(getDisplay(), getWindow(), warp_atom); + processEvents(); checkInput(); - } catch (LWJGLException e) { - LWJGLUtil.log("Caught exception while processing messages: " + e); } finally { unlockAWT(); } } - private native void nUpdate(long display, long window, long warp_atom) throws LWJGLException; public void reshape(int x, int y, int width, int height) { lockAWT(); @@ -1023,7 +1066,6 @@ final class LinuxDisplay implements DisplayImplementation { private static native void nSetWindowIcon(long display, long window, ByteBuffer icon, int icons_size, int width, int height); - /* Callbacks from nUpdate() */ private void handleButtonEvent(long millis, int type, int button, int state) { if (mouse != null) mouse.handleButtonEvent(grab, millis, type, (byte)button); diff --git a/src/java/org/lwjgl/opengl/LinuxEvent.java b/src/java/org/lwjgl/opengl/LinuxEvent.java new file mode 100644 index 00000000..11e6a680 --- /dev/null +++ b/src/java/org/lwjgl/opengl/LinuxEvent.java @@ -0,0 +1,173 @@ +/* + * 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; + +import java.nio.ByteBuffer; + +/** + * Wrapper class for X11 events. + * + * @author elias_naur + * @version $Revision: 2286 $ + * $Id: LinuxPeerInfo.java 2286 2006-03-23 19:32:21Z matzon $ + */ +final class LinuxEvent { + public final static int KeyPress = 2; + public final static int KeyRelease = 3; + public final static int ButtonPress = 4; + public final static int ButtonRelease = 5; + public final static int MotionNotify = 6; + public final static int UnmapNotify = 18; + public final static int MapNotify = 19; + public final static int Expose = 12; + public final static int ClientMessage = 33; + + private final ByteBuffer event_buffer; + + public LinuxEvent() { + this.event_buffer = createEventBuffer(); + } + private static native ByteBuffer createEventBuffer(); + + public final static native int getPending(long display); + + public final boolean filterEvent(long window) { + return nFilterEvent(event_buffer, window); + } + private static native boolean nFilterEvent(ByteBuffer event_buffer, long window); + + public final void nextEvent(long display) { + nNextEvent(display, event_buffer); + } + private static native void nNextEvent(long display, ByteBuffer event_buffer); + + public final int getType() { + return nGetType(event_buffer); + } + private static native int nGetType(ByteBuffer event_buffer); + + public final long getWindow() { + return nGetWindow(event_buffer); + } + private static native long nGetWindow(ByteBuffer event_buffer); + + /* ClientMessage methods */ + + public final long getClientMessageType() { + return nGetClientMessageType(event_buffer); + } + private static native long nGetClientMessageType(ByteBuffer event_buffer); + + public final int getClientData(int index) { + return nGetClientData(event_buffer, index); + } + private static native int nGetClientData(ByteBuffer event_buffer, int index); + + public final int getClientFormat() { + return nGetClientFormat(event_buffer); + } + private static native int nGetClientFormat(ByteBuffer event_buffer); + + /* Button methods */ + + public final long getButtonTime() { + return nGetButtonTime(event_buffer); + } + private static native long nGetButtonTime(ByteBuffer event_buffer); + + public final int getButtonState() { + return nGetButtonState(event_buffer); + } + private static native int nGetButtonState(ByteBuffer event_buffer); + + public final int getButtonType() { + return nGetButtonType(event_buffer); + } + private static native int nGetButtonType(ByteBuffer event_buffer); + + public final int getButtonButton() { + return nGetButtonButton(event_buffer); + } + private static native int nGetButtonButton(ByteBuffer event_buffer); + + public final long getButtonRoot() { + return nGetButtonRoot(event_buffer); + } + private static native long nGetButtonRoot(ByteBuffer event_buffer); + + public final int getButtonXRoot() { + return nGetButtonXRoot(event_buffer); + } + private static native int nGetButtonXRoot(ByteBuffer event_buffer); + + public final int getButtonYRoot() { + return nGetButtonYRoot(event_buffer); + } + private static native int nGetButtonYRoot(ByteBuffer event_buffer); + + public final int getButtonX() { + return nGetButtonX(event_buffer); + } + private static native int nGetButtonX(ByteBuffer event_buffer); + + public final int getButtonY() { + return nGetButtonY(event_buffer); + } + private static native int nGetButtonY(ByteBuffer event_buffer); + + /* Key methods */ + + public final long getKeyAddress() { + return nGetKeyAddress(event_buffer); + } + private static native int nGetKeyAddress(ByteBuffer event_buffer); + + public final long getKeyTime() { + return nGetKeyTime(event_buffer); + } + private static native int nGetKeyTime(ByteBuffer event_buffer); + + public final int getKeyType() { + return nGetKeyType(event_buffer); + } + private static native int nGetKeyType(ByteBuffer event_buffer); + + public final int getKeyKeyCode() { + return nGetKeyKeyCode(event_buffer); + } + private static native int nGetKeyKeyCode(ByteBuffer event_buffer); + + public final int getKeyState() { + return nGetKeyState(event_buffer); + } + private static native int nGetKeyState(ByteBuffer event_buffer); +} diff --git a/src/native/linux/org_lwjgl_opengl_Display.c b/src/native/linux/org_lwjgl_opengl_Display.c index 665a2eab..099152cc 100644 --- a/src/native/linux/org_lwjgl_opengl_Display.c +++ b/src/native/linux/org_lwjgl_opengl_Display.c @@ -69,7 +69,6 @@ typedef struct { static GLXWindow glx_window = None; -static Atom delete_atom; static Colormap cmap; static int current_depth; static Pixmap current_icon_pixmap; @@ -158,73 +157,6 @@ static bool isLegacyFullscreen(jint window_mode) { return window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_LEGACY; } -static void handleMessages(JNIEnv *env, jobject disp_obj, Display *disp, Window window, Atom warp_atom) { - XEvent event; - jclass disp_class = (*env)->GetObjectClass(env, disp_obj); - if (disp_class == NULL) - return; - jmethodID handleKeyEvent_method = (*env)->GetMethodID(env, disp_class, "handleKeyEvent", "(JJIII)V"); - if (handleKeyEvent_method == NULL) - return; - jmethodID handleButtonEvent_method = (*env)->GetMethodID(env, disp_class, "handleButtonEvent", "(JIII)V"); - if (handleButtonEvent_method == NULL) - return; - jmethodID handlePointerMotionEvent_method = (*env)->GetMethodID(env, disp_class, "handlePointerMotionEvent", "(JJIIIII)V"); - if (handlePointerMotionEvent_method == NULL) - return; - jmethodID handleWarpEvent_method = (*env)->GetMethodID(env, disp_class, "handleWarpEvent", "(II)V"); - if (handleWarpEvent_method == NULL) - return; - jmethodID handleMapNotifyEvent_method = (*env)->GetMethodID(env, disp_class, "handleMapNotifyEvent", "()V"); - if (handleMapNotifyEvent_method == NULL) - return; - jmethodID handleUnmapNotifyEvent_method = (*env)->GetMethodID(env, disp_class, "handleUnmapNotifyEvent", "()V"); - if (handleUnmapNotifyEvent_method == NULL) - return; - jmethodID handleExposeEvent_method = (*env)->GetMethodID(env, disp_class, "handleExposeEvent", "()V"); - if (handleExposeEvent_method == NULL) - return; - jmethodID handleCloseEvent_method = (*env)->GetMethodID(env, disp_class, "handleCloseEvent", "()V"); - if (handleCloseEvent_method == NULL) - return; - while (!(*env)->ExceptionOccurred(env) && XPending(disp) > 0) { - XNextEvent(disp, &event); - if (XFilterEvent(&event, None) == True) - continue; - // Ignore events from old windows - if (event.xany.window != window) - continue; - switch (event.type) { - case ClientMessage: - if (event.xclient.message_type == warp_atom) { - (*env)->CallVoidMethod(env, disp_obj, 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)) - (*env)->CallVoidMethod(env, disp_obj, handleCloseEvent_method); - break; - case MapNotify: - (*env)->CallVoidMethod(env, disp_obj, handleMapNotifyEvent_method); - break; - case UnmapNotify: - (*env)->CallVoidMethod(env, disp_obj, handleUnmapNotifyEvent_method); - break; - case Expose: - (*env)->CallVoidMethod(env, disp_obj, handleExposeEvent_method); - break; - case ButtonPress: /* Fall through */ - case ButtonRelease: - (*env)->CallVoidMethod(env, disp_obj, handleButtonEvent_method, (jlong)event.xbutton.time, (jint)event.xbutton.type, (jint)event.xbutton.button, (jint)event.xbutton.state); - break; - case MotionNotify: - (*env)->CallVoidMethod(env, disp_obj, handlePointerMotionEvent_method, (jlong)event.xbutton.time, (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: - (*env)->CallVoidMethod(env, disp_obj, handleKeyEvent_method, (jlong)(intptr_t)&(event.xkey), (jlong)event.xkey.time, (jint)event.xkey.type, (jint)event.xkey.keycode, (jint)event.xkey.state); - break; - } - } -} - static void setWindowTitle(Display *disp, Window window, const char *title) { XStoreName(disp, window, title); } @@ -356,7 +288,7 @@ static Window createWindow(JNIEnv* env, Display *disp, int screen, jint window_m size_hints->max_height = height; XSetWMNormalHints(disp, win, size_hints); XFree(size_hints); - delete_atom = XInternAtom(disp, "WM_DELETE_WINDOW", False); + Atom delete_atom = XInternAtom(disp, "WM_DELETE_WINDOW", False); XSetWMProtocols(disp, win, &delete_atom, 1); if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) { Atom fullscreen_atom = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False); @@ -373,13 +305,6 @@ static Window createWindow(JNIEnv* env, Display *disp, int screen, jint window_m return win; } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUpdate(JNIEnv *env, jobject disp_obj, jlong display, jlong window_ptr, jlong warp_atom_ptr) { - Display *disp = (Display *)(intptr_t)display; - Window window = (Window)window_ptr; - Atom warp_atom = (Atom)warp_atom_ptr; - handleMessages(env, disp_obj, disp, window, warp_atom); -} - JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jlong display, jint screen, jobject peer_info_handle, jobject mode, jint window_mode, jint x, jint y) { Display *disp = (Display *)(intptr_t)display; X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); diff --git a/src/native/linux/org_lwjgl_opengl_LinuxEvent.c b/src/native/linux/org_lwjgl_opengl_LinuxEvent.c new file mode 100644 index 00000000..e67f4043 --- /dev/null +++ b/src/native/linux/org_lwjgl_opengl_LinuxEvent.c @@ -0,0 +1,161 @@ +/* + * 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_opengl_LinuxEvent.c 2598 2006-10-24 08:33:09Z elias_naur $ + * + * @author elias_naur + * @version $Revision: 2598 $ + */ + +#include +#include +#include +#include +#include "common_tools.h" +#include "org_lwjgl_opengl_LinuxEvent.h" + +JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxEvent_createEventBuffer(JNIEnv *env, jclass unused) { + return newJavaManagedByteBuffer(env, sizeof(XEvent)); +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_getPending(JNIEnv *env, jclass unused, jlong display_ptr) { + Display *disp = (Display *)(intptr_t)display_ptr; + return XPending(disp); +} + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxEvent_nFilterEvent(JNIEnv *env, jclass unused, jobject event_buffer, jlong window_ptr) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + Window window = (Window)window_ptr; + return XFilterEvent(event, window) == True ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxEvent_nNextEvent(JNIEnv *env, jclass unused, jlong display_ptr, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + Display *disp = (Display *)(intptr_t)display_ptr; + XNextEvent(disp, event); +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetType(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->type; +} + +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetWindow(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xany.window; +} + +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetClientMessageType(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xclient.message_type; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetClientData(JNIEnv *env, jclass unused, jobject event_buffer, jint index) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xclient.data.l[index]; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetClientFormat(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xclient.format; +} + +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonTime(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.time; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonState(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.state; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonType(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.type; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonButton(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.button; +} + +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonRoot(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.root; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonXRoot(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.x_root; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonYRoot(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.y_root; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonX(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.x; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetButtonY(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xbutton.y; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetKeyAddress(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return (jlong)(intptr_t)&(event->xkey); +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetKeyTime(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xkey.time; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetKeyType(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xkey.type; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetKeyKeyCode(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xkey.keycode; +} + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxEvent_nGetKeyState(JNIEnv *env, jclass unused, jobject event_buffer) { + XEvent *event = (XEvent *)(*env)->GetDirectBufferAddress(env, event_buffer); + return event->xkey.state; +}