diff --git a/build.xml b/build.xml index f9e581f3..a63035d7 100644 --- a/build.xml +++ b/build.xml @@ -494,6 +494,7 @@ + diff --git a/src/java/org/lwjgl/input/Keyboard.java b/src/java/org/lwjgl/input/Keyboard.java index a556283e..a91ef40c 100644 --- a/src/java/org/lwjgl/input/Keyboard.java +++ b/src/java/org/lwjgl/input/Keyboard.java @@ -42,7 +42,7 @@ import org.lwjgl.BufferUtils; import org.lwjgl.LWJGLException; import org.lwjgl.Sys; import org.lwjgl.opengl.Display; -import org.lwjgl.opengl.DisplayImplementation; +import org.lwjgl.opengl.InputImplementation; /** *
@@ -264,7 +264,7 @@ public class Keyboard { /** One time initialization */ private static boolean initialized; - private static DisplayImplementation implementation; + private static InputImplementation implementation; /** * Keyboard cannot be constructed. @@ -282,6 +282,24 @@ public class Keyboard { initialized = true; } + /** + * "Create" the keyboard with the given implementation. This is used + * reflectively from AWTInputAdapter. + * + * @throws LWJGLException if the keyboard could not be created for any reason + */ + private static void create(InputImplementation impl) throws LWJGLException { + if (created) + throw new IllegalStateException("Destroy the Keyboard first."); + if (!initialized) + initialize(); + implementation = impl; + implementation.createKeyboard(); + created = true; + readBuffer = ByteBuffer.allocate(EVENT_SIZE*BUFFER_SIZE); + reset(); + } + /** * "Create" the keyboard. The display must first have been created. The * reason for this is so the keyboard has a window to "focus" in. @@ -289,17 +307,7 @@ public class Keyboard { * @throws LWJGLException if the keyboard could not be created for any reason */ public static void create() throws LWJGLException { - if (!Display.isCreated()) - throw new IllegalStateException("Display must be created before you can create Keyboard"); - if (!initialized) - initialize(); - if (created) - return; - implementation = Mouse.getImplementation(); - implementation.createKeyboard(); - created = true; - readBuffer = ByteBuffer.allocate(EVENT_SIZE*BUFFER_SIZE); - reset(); + create(Mouse.createImplementation()); } private static void reset() { diff --git a/src/java/org/lwjgl/input/Mouse.java b/src/java/org/lwjgl/input/Mouse.java index 74c5dad4..4416da7b 100644 --- a/src/java/org/lwjgl/input/Mouse.java +++ b/src/java/org/lwjgl/input/Mouse.java @@ -40,8 +40,8 @@ import org.lwjgl.BufferUtils; import org.lwjgl.LWJGLException; import org.lwjgl.LWJGLUtil; import org.lwjgl.Sys; -import org.lwjgl.opengl.DisplayImplementation; import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.InputImplementation; import java.lang.reflect.Method; import java.security.AccessController; @@ -57,7 +57,7 @@ import java.security.PrivilegedActionException; * n buttons supported, n being a native limit. A scrolly wheel is also * supported, if one such is available. Movement is reported as delta from * last position or as an absolute position. If the window has been created - * the absolute position will be clamped to 0 - Display (width | height) + * the absolute position will be clamped to 0 - width | height. * * @author cix_foo * @author elias_naur @@ -134,10 +134,10 @@ public class Mouse { private static boolean isGrabbed; - private static DisplayImplementation implementation; + private static InputImplementation implementation; - /** Whether we're running windows - which need to manually update cursor animation */ - private static final boolean isWindows = LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS; + /** Whether we're running windows - which need to manually update cursor animation */ + private static final boolean isWindows = LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS; /** * Mouse cannot be constructed. @@ -220,13 +220,19 @@ public class Mouse { readBuffer.position(readBuffer.limit()); } - static DisplayImplementation getImplementation() { + static InputImplementation getImplementation() { + return implementation; + } + + static InputImplementation createImplementation() { + if (!Display.isCreated()) throw new IllegalStateException("Display must be created."); + /* Use reflection since we can't make Display.getImplementation * public */ try { - return (DisplayImplementation)AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception{ + return (InputImplementation)AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { Method getImplementation_method = Display.class.getDeclaredMethod("getImplementation", null); getImplementation_method.setAccessible(true); return getImplementation_method.invoke(null, null); @@ -238,19 +244,17 @@ public class Mouse { } /** - * "Create" the mouse. The display must first have been created. - * Initially, the mouse is not grabbed and the delta values are reported - * with respect to the center of the display. + * "Create" the mouse with the given custom implementation. This is used + * reflectively by AWTInputAdapter. * * @throws LWJGLException if the mouse could not be created for any reason */ - public static void create() throws LWJGLException { - if (!Display.isCreated()) throw new IllegalStateException("Display must be created prior to creating mouse"); - + private static void create(InputImplementation impl) throws LWJGLException { + if (created) + throw new IllegalStateException("Destroy the mouse first."); if (!initialized) initialize(); - if (created) return; - implementation = getImplementation(); + implementation = impl; implementation.createMouse(); hasWheel = implementation.hasWheel(); created = true; @@ -259,13 +263,24 @@ public class Mouse { buttonCount = implementation.getButtonCount(); buttons = BufferUtils.createByteBuffer(buttonCount); coord_buffer = BufferUtils.createIntBuffer(3); - if (currentCursor != null) + if (currentCursor != null && implementation.getNativeCursorCapabilities() != 0) setNativeCursor(currentCursor); readBuffer = ByteBuffer.allocate(EVENT_SIZE * BUFFER_SIZE); readBuffer.limit(0); setGrabbed(isGrabbed); } + /** + * "Create" the mouse. The display must first have been created. + * Initially, the mouse is not grabbed and the delta values are reported + * with respect to the center of the display. + * + * @throws LWJGLException if the mouse could not be created for any reason + */ + public static void create() throws LWJGLException { + create(createImplementation()); + } + /** * @return true if the mouse has been created */ @@ -327,8 +342,8 @@ public class Mouse { x = poll_coord1; y = poll_coord2; } - x = Math.min(Display.getDisplayMode().getWidth() - 1, Math.max(0, x)); - y = Math.min(Display.getDisplayMode().getHeight() - 1, Math.max(0, y)); + x = Math.min(implementation.getWidth() - 1, Math.max(0, x)); + y = Math.min(implementation.getHeight() - 1, Math.max(0, y)); dwheel += poll_dwheel; read(); } @@ -404,8 +419,8 @@ public class Mouse { event_x = new_event_x; event_y = new_event_y; } - event_x = Math.min(Display.getDisplayMode().getWidth() - 1, Math.max(0, event_x)); - event_y = Math.min(Display.getDisplayMode().getHeight() - 1, Math.max(0, event_y)); + event_x = Math.min(implementation.getWidth() - 1, Math.max(0, event_x)); + event_y = Math.min(implementation.getHeight() - 1, Math.max(0, event_y)); event_dwheel = readBuffer.getInt(); event_nanos = readBuffer.getLong(); return true; @@ -476,8 +491,8 @@ public class Mouse { } /** - * Retrieves the absolute position. If the Display has been created - * x will be clamped to 0...width-1. + * Retrieves the absolute position. It will be clamped to + * 0...width-1. * * @return Absolute x axis position of mouse */ @@ -486,8 +501,8 @@ public class Mouse { } /** - * Retrieves the absolute position. If the Display has been created - * y will be clamped to 0...height-1. + * Retrieves the absolute position. It will be clamped to + * 0...height-1. * * @return Absolute y axis position of mouse */ diff --git a/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java index b11c1cef..8df7c472 100644 --- a/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java +++ b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java @@ -46,7 +46,7 @@ interface AWTCanvasImplementation { /** * Return an opaque handle to the canvas peer information required to create a context from it. */ - public PeerInfo createPeerInfo(AWTGLCanvas canvas, PixelFormat pixel_format) throws LWJGLException; + PeerInfo createPeerInfo(AWTGLCanvas canvas, PixelFormat pixel_format) throws LWJGLException; /** * Find a proper GraphicsConfiguration from the given GraphicsDevice and PixelFormat. @@ -54,5 +54,13 @@ interface AWTCanvasImplementation { * @return A GraphicsConfiguration matching the given GraphicsConfiguration and PixelFormat. * @throws LWJGLException if no suitable configuration could be found. */ - public GraphicsConfiguration findConfiguration(GraphicsDevice device, PixelFormat pixel_format) throws LWJGLException; + GraphicsConfiguration findConfiguration(GraphicsDevice device, PixelFormat pixel_format) throws LWJGLException; + + /** + * Create an AWTCanvasInputImplementation for a specified AWTGLCanvas. + * + * @return A platform specific AWTCanvasInputImplementation. + * @param canvas An AWTGLCanvas + */ + AWTCanvasInputImplementation createInput(AWTGLCanvas canvas) throws LWJGLException; } diff --git a/src/java/org/lwjgl/opengl/AWTCanvasInputImplementation.java b/src/java/org/lwjgl/opengl/AWTCanvasInputImplementation.java new file mode 100644 index 00000000..3f2353fe --- /dev/null +++ b/src/java/org/lwjgl/opengl/AWTCanvasInputImplementation.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002-2006 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 org.lwjgl.LWJGLException; + +/** + * + * @author elias_naur + * @version $Revision: 2286 $ + * $Id: AWTCanvasImplementation.java 2286 2006-03-23 19:32:21Z matzon $ + */ +interface AWTCanvasInputImplementation extends InputImplementation { + void processInput(PeerInfo peer_info); + void update(); + void init(); + void destroy(); +} diff --git a/src/java/org/lwjgl/opengl/AWTGLCanvas.java b/src/java/org/lwjgl/opengl/AWTGLCanvas.java index f3bf5660..94e4775d 100644 --- a/src/java/org/lwjgl/opengl/AWTGLCanvas.java +++ b/src/java/org/lwjgl/opengl/AWTGLCanvas.java @@ -81,6 +81,9 @@ public class AWTGLCanvas extends Canvas implements Drawable, ComponentListener, /** Tracks whether initGL() needs to be called */ private boolean first_run; + /** Track the input adapter, if any */ + private volatile AWTCanvasInputImplementation awt_input; + static { Sys.initialize(); String class_name; @@ -109,6 +112,16 @@ public class AWTGLCanvas extends Canvas implements Drawable, ComponentListener, } } + /** + * Used from AWTInputAdapter + */ + static AWTCanvasImplementation getImplementation() { + return implementation; + } + + void setInput(AWTCanvasInputImplementation awt_input) { + this.awt_input = awt_input; + } private void setUpdate() { synchronized(SYNC_LOCK) { @@ -271,8 +284,9 @@ public class AWTGLCanvas extends Canvas implements Drawable, ComponentListener, */ public final void paint(Graphics g) { try { - if (peer_info == null) + if (peer_info == null) { this.peer_info = implementation.createPeerInfo(this, pixel_format); + } peer_info.lockAndGetHandle(); try { if (context == null) { @@ -288,6 +302,9 @@ public class AWTGLCanvas extends Canvas implements Drawable, ComponentListener, context.update(); update_context = false; } + AWTCanvasInputImplementation current_input = awt_input; + if (current_input != null) + current_input.processInput(peer_info); if (first_run) { first_run = false; initGL(); diff --git a/src/java/org/lwjgl/opengl/AWTInputAdapter.java b/src/java/org/lwjgl/opengl/AWTInputAdapter.java new file mode 100644 index 00000000..1433d1fb --- /dev/null +++ b/src/java/org/lwjgl/opengl/AWTInputAdapter.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002-2006 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 org.lwjgl.LWJGLException; +import org.lwjgl.input.Mouse; +import org.lwjgl.input.Keyboard; +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; + +import java.lang.reflect.Method; + +import java.awt.Canvas; + +/** + * This is the static class for using LWJGL input (Mouse and Keyboard) + * with an AWTGLCanvas. + * + * @author Elias Naur + * @version $Revision: 2286 $ + * $Id: AWTCanvasImplementation.java 2286 2006-03-23 19:32:21Z matzon $ + */ +public final class AWTInputAdapter { + private static AWTCanvasInputImplementation awt_input; + + /** + * Create AWTInputAdapter with the specified AWTGLCanvas. Use + * update() to receive input. + * + * @param canvas The canvas to receive input from. + */ + public static synchronized void create(AWTGLCanvas canvas) throws LWJGLException { + if (awt_input != null) + throw new IllegalStateException("You need to destroy() the adapter."); + awt_input = AWTGLCanvas.getImplementation().createInput(canvas); + // Invoke Mouse.create(awt_input) and Keyboard.create(awt_input) + try { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + private void invokeCreate(Class input_class) throws Exception { + Method create_method = input_class.getDeclaredMethod("create", new Class[]{InputImplementation.class}); + create_method.setAccessible(true); + create_method.invoke(null, new Object[]{awt_input}); + } + + public Object run() throws Exception { + invokeCreate(Mouse.class); + invokeCreate(Keyboard.class); + return null; + } + }); + } catch (PrivilegedActionException e) { + Throwable cause = e.getCause(); + if (cause instanceof LWJGLException) + throw (LWJGLException)cause; + else + throw new Error(cause); + } + awt_input.init(); + } + + public static synchronized void destroy() { + if (awt_input != null) { + awt_input.destroy(); + awt_input = null; + } + } + + public static synchronized void update() { + if (awt_input == null) + throw new IllegalStateException("You need to create() the adapter."); + awt_input.update(); + Display.pollDevices(); + } +} diff --git a/src/java/org/lwjgl/opengl/AbstractAWTInput.java b/src/java/org/lwjgl/opengl/AbstractAWTInput.java new file mode 100644 index 00000000..7df5adc3 --- /dev/null +++ b/src/java/org/lwjgl/opengl/AbstractAWTInput.java @@ -0,0 +1,167 @@ +/* + * 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.IntBuffer; +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; +import org.lwjgl.LWJGLUtil; + +import java.awt.event.FocusListener; +import java.awt.Cursor; + +/** + * + * @author elias_naur + * @version $Revision: 2586 $ + * $Id: LinuxAWTGLCanvasPeerInfo.java 2586 2006-10-20 11:51:34Z elias_naur $ + */ +abstract class AbstractAWTInput implements AWTCanvasInputImplementation { + private AWTGLCanvas canvas; + + private volatile int current_height; + private volatile int current_width; + private KeyboardEventQueue keyboard_queue; + private MouseEventQueue mouse_queue; + private volatile boolean grab; + + protected AbstractAWTInput(AWTGLCanvas canvas) throws LWJGLException { + this.canvas = canvas; + } + + public synchronized void grabMouse(boolean grab) { + this.grab = grab; + if (mouse_queue != null) + mouse_queue.setGrabbed(grab); + } + + protected boolean isGrabbed() { + return grab; + } + + protected final AWTGLCanvas getCanvas() { + return canvas; + } + + public final void init() { + canvas.setInput(this); + } + + public synchronized void destroy() { + canvas.setInput(null); + canvas = null; + } + + public final int getWidth() { + return current_width; + } + + public final int getHeight() { + return current_height; + } + + public synchronized void processInput(PeerInfo peer_info) { + current_width = canvas.getWidth(); + current_height = canvas.getHeight(); + } + + public boolean hasWheel() { + return AWTUtil.hasWheel(); + } + + public int getButtonCount() { + return AWTUtil.getButtonCount(); + } + + public void createMouse() throws LWJGLException { + mouse_queue = new MouseEventQueue(canvas); + mouse_queue.register(); + } + + public void destroyMouse() { + mouse_queue.unregister(); + } + + public int getNativeCursorCapabilities() { + return AWTUtil.getNativeCursorCapabilities(); + } + + public void setCursorPosition(int x, int y) { + AWTUtil.setCursorPosition(canvas, x, y); + } + + public void setNativeCursor(Object handle) throws LWJGLException { + canvas.setCursor((Cursor)handle); + } + + public int getMinCursorSize() { + return AWTUtil.getMinCursorSize(); + } + + public int getMaxCursorSize() { + return AWTUtil.getMaxCursorSize(); + } + + public synchronized void createKeyboard() throws LWJGLException { + keyboard_queue = new KeyboardEventQueue(canvas); + keyboard_queue.register(); + } + + public synchronized void destroyKeyboard() { + if (keyboard_queue != null) + keyboard_queue.unregister(); + } + + public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException { + return AWTUtil.createCursor(width, height, xHotspot, yHotspot, numImages, images, delays); + } + + public void destroyCursor(Object cursor_handle) { + } + + public synchronized void readMouse(ByteBuffer buffer) { + mouse_queue.copyEvents(buffer); + } + + public synchronized void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) { + mouse_queue.poll(coord_buffer, buttons); + } + + public synchronized void readKeyboard(ByteBuffer buffer) { + keyboard_queue.copyEvents(buffer); + } + + public synchronized void pollKeyboard(ByteBuffer keyDownBuffer) { + keyboard_queue.poll(keyDownBuffer); + } +} diff --git a/src/java/org/lwjgl/opengl/DisplayImplementation.java b/src/java/org/lwjgl/opengl/DisplayImplementation.java index 22642ee7..1d1b2bae 100644 --- a/src/java/org/lwjgl/opengl/DisplayImplementation.java +++ b/src/java/org/lwjgl/opengl/DisplayImplementation.java @@ -44,7 +44,7 @@ import java.nio.IntBuffer; import org.lwjgl.LWJGLException; -public interface DisplayImplementation { +interface DisplayImplementation extends InputImplementation { void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException; @@ -124,88 +124,6 @@ public interface DisplayImplementation { */ DisplayMode[] getAvailableDisplayModes() throws LWJGLException; - /* - * Mouse methods - */ - /** Query of wheel support */ - boolean hasWheel(); - - /** Query of button count */ - int getButtonCount(); - - /** - * Method to create the mouse. - */ - void createMouse() throws LWJGLException; - - /** - * Method the destroy the mouse - */ - void destroyMouse(); - - /** - * Method to poll the mouse - */ - void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons); - - /** - * Method to read the keyboard buffer - */ - void readMouse(ByteBuffer buffer); - - void grabMouse(boolean grab); - - /** - * Function to determine native cursor support - */ - int getNativeCursorCapabilities(); - - /** Method to set the native cursor position */ - void setCursorPosition(int x, int y); - - /** Method to set the native cursor */ - void setNativeCursor(Object handle) throws LWJGLException; - - /** Method returning the minimum cursor size */ - int getMinCursorSize(); - - /** Method returning the maximum cursor size */ - int getMaxCursorSize(); - - /* - * Keyboard methods - */ - - /** - * Method to create the keyboard - */ - void createKeyboard() throws LWJGLException; - - /** - * Method to destroy the keyboard - */ - void destroyKeyboard(); - - /** - * Method to poll the keyboard. - * - * @param keyDownBuffer the address of a 256-byte buffer to place - * key states in. - */ - void pollKeyboard(ByteBuffer keyDownBuffer); - - /** - * Method to read the keyboard buffer - */ - void readKeyboard(ByteBuffer buffer); - -// int isStateKeySet(int key); - - /** Native cursor handles */ - Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException; - - void destroyCursor(Object cursor_handle); - /* Pbuffer */ int getPbufferCapabilities(); diff --git a/src/java/org/lwjgl/opengl/InputImplementation.java b/src/java/org/lwjgl/opengl/InputImplementation.java new file mode 100644 index 00000000..6f4afce0 --- /dev/null +++ b/src/java/org/lwjgl/opengl/InputImplementation.java @@ -0,0 +1,133 @@ +/* + * 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; + +/** + * This is the input implementation interface. Mouse and Keyboard delegates + * to implementors of this interface. There is one InputImplementation + * for each supported platform. + * @author elias_naur + */ + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import org.lwjgl.LWJGLException; + +public interface InputImplementation { + /* + * Mouse methods + */ + /** Query of wheel support */ + boolean hasWheel(); + + /** Query of button count */ + int getButtonCount(); + + /** + * Method to create the mouse. + */ + void createMouse() throws LWJGLException; + + /** + * Method the destroy the mouse + */ + void destroyMouse(); + + /** + * Method to poll the mouse + */ + void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons); + + /** + * Method to read the keyboard buffer + */ + void readMouse(ByteBuffer buffer); + + void grabMouse(boolean grab); + + /** + * Function to determine native cursor support + */ + int getNativeCursorCapabilities(); + + /** Method to set the native cursor position */ + void setCursorPosition(int x, int y); + + /** Method to set the native cursor */ + void setNativeCursor(Object handle) throws LWJGLException; + + /** Method returning the minimum cursor size */ + int getMinCursorSize(); + + /** Method returning the maximum cursor size */ + int getMaxCursorSize(); + + /* + * Keyboard methods + */ + + /** + * Method to create the keyboard + */ + void createKeyboard() throws LWJGLException; + + /** + * Method to destroy the keyboard + */ + void destroyKeyboard(); + + /** + * Method to poll the keyboard. + * + * @param keyDownBuffer the address of a 256-byte buffer to place + * key states in. + */ + void pollKeyboard(ByteBuffer keyDownBuffer); + + /** + * Method to read the keyboard buffer + */ + void readKeyboard(ByteBuffer buffer); + +// int isStateKeySet(int key); + + /** Native cursor handles */ + Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException; + + void destroyCursor(Object cursor_handle); + + int getWidth(); + + int getHeight(); +} diff --git a/src/java/org/lwjgl/opengl/KeyboardEventQueue.java b/src/java/org/lwjgl/opengl/KeyboardEventQueue.java index 9850698a..c2900135 100644 --- a/src/java/org/lwjgl/opengl/KeyboardEventQueue.java +++ b/src/java/org/lwjgl/opengl/KeyboardEventQueue.java @@ -32,8 +32,7 @@ package org.lwjgl.opengl; /** - * A java implementation of a LWJGL compatible Keyboard event queue. - * Currently only used by the Mac OS X implementation. + * An AWT implementation of a LWJGL compatible Keyboard event queue. * @author elias_naur */ diff --git a/src/java/org/lwjgl/opengl/LinuxAWTInput.java b/src/java/org/lwjgl/opengl/LinuxAWTInput.java new file mode 100644 index 00000000..b0cbca5d --- /dev/null +++ b/src/java/org/lwjgl/opengl/LinuxAWTInput.java @@ -0,0 +1,233 @@ +/* + * 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.IntBuffer; +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; +import org.lwjgl.LWJGLUtil; + +import java.awt.event.FocusEvent; + +/** + * + * @author elias_naur + * @version $Revision: 2586 $ + * $Id: LinuxAWTGLCanvasPeerInfo.java 2586 2006-10-20 11:51:34Z elias_naur $ + */ +final class LinuxAWTInput extends AbstractAWTInput { + private final long display; + private final long input_window; + private final LinuxEvent event = new LinuxEvent(); + + private long cached_window; + private LinuxMouse cached_mouse; +// private LinuxKeyboard cached_keyboard; + private long blank_cursor = LinuxDisplay.None; + private boolean input_grabbed; + private boolean input_released; + + public LinuxAWTInput(AWTGLCanvas canvas) throws LWJGLException { + super(canvas); + LinuxDisplay.lockAWT(); + try { + this.display = LinuxDisplay.openDisplay(); + this.input_window = createInputOnlyWindow(display, LinuxDisplay.nGetDefaultScreen(display)); + } finally { + LinuxDisplay.unlockAWT(); + } + } + private static native long createInputOnlyWindow(long display, int screen); + + public synchronized void destroy() { + super.destroy(); + LinuxDisplay.lockAWT(); + try { + destroyCursor(); + LinuxDisplay.nDestroyWindow(display, input_window); + LinuxDisplay.closeDisplay(display); + } finally { + LinuxDisplay.unlockAWT(); + } + } + + private void ungrabInputLocked() { + LinuxDisplay.lockAWT(); + try { + ungrabInput(); + } finally { + LinuxDisplay.unlockAWT(); + } + } + + private void ungrabInput() { + if (input_grabbed) { +// LinuxDisplay.nUngrabKeyboard(display); + LinuxDisplay.nUngrabPointer(display); + LinuxDisplay.nSetRepeatMode(display, LinuxDisplay.AutoRepeatModeDefault); + input_grabbed = false; + } + } + + private void grabInput(long window) { + if (!input_grabbed) { +// int res1 = LinuxDisplay.nGrabKeyboard(display, window); + LinuxDisplay.nSetRepeatMode(display, LinuxDisplay.AutoRepeatModeOff); + int res2 = LinuxDisplay.nGrabPointer(display, window, blank_cursor); + if (/*res1 == LinuxDisplay.GrabSuccess && */res2 == LinuxDisplay.GrabSuccess) + input_grabbed = true; + } + } + + private final void destroyCursor() { + if (blank_cursor != LinuxDisplay.None) + LinuxDisplay.nDestroyCursor(display, blank_cursor); + } + + public synchronized void processInput(PeerInfo peer_info) { + super.processInput(peer_info); + LinuxDisplay.lockAWT(); + try { + LinuxPeerInfo linux_peer_info = (LinuxPeerInfo)peer_info; + long new_window = linux_peer_info.getDrawable(); + if (new_window != cached_window) { + ungrabInput(); + cached_window = new_window; + try { + cached_mouse = new LinuxMouse(display, new_window, input_window); +// cached_keyboard = new LinuxKeyboard(display, new_window); + } catch (LWJGLException e) { + LWJGLUtil.log("Failed to create input devices: " + e); + } + destroyCursor(); + this.blank_cursor = LinuxDisplay.nCreateBlankCursor(display, new_window); + } + checkFocus(); + if (!input_grabbed && shouldGrab()) + grabInput(new_window); + } finally { + LinuxDisplay.unlockAWT(); + } + } + + private void checkFocus() { + if (getCanvas().hasFocus()) { + input_released = false; + } else { + input_released = true; + ungrabInput(); + } + } + + private boolean shouldGrab() { + return !input_released && isGrabbed(); + } + + public synchronized void update() { + LinuxDisplay.lockAWT(); + try { + while (LinuxEvent.getPending(display) > 0) { + event.nextEvent(display); + if (shouldGrab()) { + long event_window = event.getWindow(); + boolean processed = event.filterEvent(event_window) || + cached_mouse.filterEvent(isGrabbed(), shouldGrab(), event)/* || + cached_keyboard.filterEvent(event)*/; + } + } + } finally { + LinuxDisplay.unlockAWT(); + } + } + + public synchronized void grabMouse(boolean grab) { + if (grab != isGrabbed()) { + super.grabMouse(grab); + if (cached_mouse != null) + cached_mouse.changeGrabbed(grab, shouldGrab()); + ungrabInputLocked(); + } + } + +/* public synchronized void pollKeyboard(ByteBuffer keyDownBuffer) { + if (isGrabbed()) { + LinuxDisplay.lockAWT(); + try { + if (cached_keyboard != null) + cached_keyboard.poll(keyDownBuffer); + } finally { + LinuxDisplay.unlockAWT(); + } + } else + super.pollKeyboard(keyDownBuffer); + } + + public synchronized void readKeyboard(ByteBuffer buffer) { + if (isGrabbed()) { + LinuxDisplay.lockAWT(); + try { + if (cached_keyboard != null) + cached_keyboard.read(buffer); + } finally { + LinuxDisplay.unlockAWT(); + } + } else + super.readKeyboard(buffer); + } +*/ + public synchronized void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) { + if (isGrabbed()) { + LinuxDisplay.lockAWT(); + try { + if (cached_mouse != null) + cached_mouse.poll(isGrabbed(), coord_buffer, buttons); + } finally { + LinuxDisplay.unlockAWT(); + } + } else + super.pollMouse(coord_buffer, buttons); + } + + public synchronized void readMouse(ByteBuffer buffer) { + if (isGrabbed()) { + LinuxDisplay.lockAWT(); + try { + if (cached_mouse != null) + cached_mouse.read(buffer); + } finally { + LinuxDisplay.unlockAWT(); + } + } else + super.readMouse(buffer); + } +} diff --git a/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java b/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java index 32b77651..798d3b45 100644 --- a/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java +++ b/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java @@ -119,4 +119,8 @@ final class LinuxCanvasImplementation implements AWTCanvasImplementation { } } private static native int nFindVisualIDFromFormat(long display, int screen, PixelFormat pixel_format) throws LWJGLException; + + public AWTCanvasInputImplementation createInput(AWTGLCanvas canvas) throws LWJGLException { + return new LinuxAWTInput(canvas); + } } diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java index 40cd89cf..a8cb0724 100644 --- a/src/java/org/lwjgl/opengl/LinuxDisplay.java +++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java @@ -50,9 +50,9 @@ import org.lwjgl.input.Keyboard; final class LinuxDisplay implements DisplayImplementation { /* X11 constants */ public final static int GrabSuccess = 0; - private final static int AutoRepeatModeOff = 0; - private final static int AutoRepeatModeOn = 1; - private final static int AutoRepeatModeDefault = 2; + public final static int AutoRepeatModeOff = 0; + public final static int AutoRepeatModeOn = 1; + public final static int AutoRepeatModeDefault = 2; public final static int None = 0; /** Window mode enum */ @@ -754,7 +754,7 @@ final class LinuxDisplay implements DisplayImplementation { releaseInput(); } } - private static native long nGetInputFocus(long display); + static native long nGetInputFocus(long display); private void releaseInput() { if (isLegacyFullscreen() || input_released) @@ -789,7 +789,7 @@ final class LinuxDisplay implements DisplayImplementation { } } } - private static native void nSetRepeatMode(long display, int mode); + static native void nSetRepeatMode(long display, int mode); public void grabMouse(boolean new_grab) { lockAWT(); @@ -1054,4 +1054,12 @@ final class LinuxDisplay implements DisplayImplementation { } private static native void nSetWindowIcon(long display, long window, ByteBuffer icon, int icons_size, int width, int height); + + public int getWidth() { + return Display.getDisplayMode().getWidth(); + } + + public int getHeight() { + return Display.getDisplayMode().getHeight(); + } } diff --git a/src/java/org/lwjgl/opengl/LinuxPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxPeerInfo.java index 7889e5aa..3f91dcbe 100644 --- a/src/java/org/lwjgl/opengl/LinuxPeerInfo.java +++ b/src/java/org/lwjgl/opengl/LinuxPeerInfo.java @@ -44,4 +44,14 @@ abstract class LinuxPeerInfo extends PeerInfo { super(createHandle()); } private static native ByteBuffer createHandle(); + + public final long getDisplay() { + return nGetDisplay(getHandle()); + } + private static native long nGetDisplay(ByteBuffer handle); + + public final long getDrawable() { + return nGetDrawable(getHandle()); + } + private static native long nGetDrawable(ByteBuffer handle); } diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java b/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java index 56de7e3d..657fb62b 100644 --- a/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java +++ b/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java @@ -62,4 +62,8 @@ final class MacOSXCanvasImplementation implements AWTCanvasImplementation { */ return null; } + + public AWTCanvasInputImplementation createInput(AWTGLCanvas canvas) throws LWJGLException { + throw new UnsupportedOperationException(); + } } diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplay.java b/src/java/org/lwjgl/opengl/MacOSXDisplay.java index 81256dc9..685ea16e 100644 --- a/src/java/org/lwjgl/opengl/MacOSXDisplay.java +++ b/src/java/org/lwjgl/opengl/MacOSXDisplay.java @@ -303,7 +303,7 @@ final class MacOSXDisplay implements DisplayImplementation { public void createMouse() throws LWJGLException { MacOSXGLCanvas canvas = frame.getCanvas(); - this.mouse_queue = new MouseEventQueue(canvas); + this.mouse_queue = new MacOSXMouseEventQueue(canvas); mouse_queue.register(); } @@ -520,4 +520,12 @@ final class MacOSXDisplay implements DisplayImplementation { return 1; } + + public int getWidth() { + return Display.getDisplayMode().getWidth(); + } + + public int getHeight() { + return Display.getDisplayMode().getHeight(); + } } diff --git a/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java new file mode 100644 index 00000000..a8492846 --- /dev/null +++ b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java @@ -0,0 +1,76 @@ +/* + * 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; + +/** + * An AWT implementation of a LWJGL compatible Mouse event queue. + * @author elias_naur + */ + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.Component; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.input.Mouse; + +final class MacOSXMouseEventQueue extends MouseEventQueue { + private final IntBuffer delta_buffer = BufferUtils.createIntBuffer(2); + + MacOSXMouseEventQueue(Component component) { + super(component); + } + + protected void resetCursorToCenter() { + super.resetCursorToCenter(); + /* Clear accumulated deltas */ + ((MacOSXDisplay)Display.getImplementation()).getMouseDeltas(delta_buffer); + } + + protected void updateDeltas(long nanos) { + super.updateDeltas(nanos); + synchronized ( this ) { + ((MacOSXDisplay)Display.getImplementation()).getMouseDeltas(delta_buffer); + int dx = delta_buffer.get(0); + int dy = -delta_buffer.get(1); + if ( dx != 0 || dy != 0 ) { + putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos); + addDelta(dx, dy); + } + } + } +} diff --git a/src/java/org/lwjgl/opengl/MouseEventQueue.java b/src/java/org/lwjgl/opengl/MouseEventQueue.java index 3ba43c7c..8d919948 100644 --- a/src/java/org/lwjgl/opengl/MouseEventQueue.java +++ b/src/java/org/lwjgl/opengl/MouseEventQueue.java @@ -48,7 +48,7 @@ import java.nio.IntBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.input.Mouse; -final class MouseEventQueue extends EventQueue implements MouseListener, MouseMotionListener, MouseWheelListener { +class MouseEventQueue extends EventQueue implements MouseListener, MouseMotionListener, MouseWheelListener { private static final int WHEEL_SCALE = 120; public static final int NUM_BUTTONS = 3; @@ -56,7 +56,6 @@ final class MouseEventQueue extends EventQueue implements MouseListener, MouseMo private boolean grabbed; - private final IntBuffer delta_buffer = BufferUtils.createIntBuffer(2); /** The accumulated mouse deltas returned by poll() */ private int accum_dx; @@ -107,11 +106,9 @@ final class MouseEventQueue extends EventQueue implements MouseListener, MouseMo return component.getHeight() - 1 - y; } - private void resetCursorToCenter() { + protected void resetCursorToCenter() { clearEvents(); accum_dx = accum_dy = 0; - /* Clear accumulated deltas */ - ((MacOSXDisplay)Display.getImplementation()).getMouseDeltas(delta_buffer); } private void putMouseEvent(byte button, byte state, int dz, long nanos) { @@ -121,7 +118,7 @@ final class MouseEventQueue extends EventQueue implements MouseListener, MouseMo putMouseEventWithCoords(button, state, last_x, last_y, dz, nanos); } - private void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) { + protected void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) { event.clear(); event.put(button).put(state).putInt(coord1).putInt(coord2).putInt(dz).putLong(nanos); event.flip(); @@ -149,13 +146,17 @@ final class MouseEventQueue extends EventQueue implements MouseListener, MouseMo return; int dx = x - last_x; int dy = y - last_y; - accum_dx += dx; - accum_dy += dy; + addDelta(dx, dy); last_x = x; last_y = y; putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos); } + protected void addDelta(int dx, int dy) { + accum_dx += dx; + accum_dy += dy; + } + public void mouseClicked(MouseEvent e) { } @@ -242,19 +243,7 @@ final class MouseEventQueue extends EventQueue implements MouseListener, MouseMo putMouseEvent((byte)-1, (byte)0, amount, nanos); } - private void updateDeltas(long nanos) { - if (!grabbed) - return; - synchronized ( this ) { - ((MacOSXDisplay)Display.getImplementation()).getMouseDeltas(delta_buffer); - int dx = delta_buffer.get(0); - int dy = -delta_buffer.get(1); - if ( dx != 0 || dy != 0 ) { - putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos); - accum_dx += dx; - accum_dy += dy; - } - } + protected void updateDeltas(long nanos) { } public void mouseWheelMoved(MouseWheelEvent e) { diff --git a/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java b/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java index 3242025c..f8ac9bf0 100644 --- a/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java +++ b/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java @@ -65,6 +65,10 @@ final class WindowsCanvasImplementation implements AWTCanvasImplementation { }); } + public AWTCanvasInputImplementation createInput(AWTGLCanvas canvas) throws LWJGLException { + throw new UnsupportedOperationException(); + } + public PeerInfo createPeerInfo(AWTGLCanvas canvas, PixelFormat pixel_format) throws LWJGLException { return new WindowsAWTGLCanvasPeerInfo(canvas, pixel_format); } diff --git a/src/java/org/lwjgl/opengl/WindowsDisplay.java b/src/java/org/lwjgl/opengl/WindowsDisplay.java index f916429f..8b908bcd 100644 --- a/src/java/org/lwjgl/opengl/WindowsDisplay.java +++ b/src/java/org/lwjgl/opengl/WindowsDisplay.java @@ -589,4 +589,12 @@ final class WindowsDisplay implements DisplayImplementation { return new WindowsDirectInput3(getDllInstance()); } } + + public int getWidth() { + return Display.getDisplayMode().getWidth(); + } + + public int getHeight() { + return Display.getDisplayMode().getHeight(); + } } diff --git a/src/java/org/lwjgl/test/opengl/awt/AWTInputAdapterTest.java b/src/java/org/lwjgl/test/opengl/awt/AWTInputAdapterTest.java new file mode 100644 index 00000000..82f3b937 --- /dev/null +++ b/src/java/org/lwjgl/test/opengl/awt/AWTInputAdapterTest.java @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2002-2005 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.test.opengl.awt; + +import java.awt.Frame; +import java.awt.Color; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.nio.FloatBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.input.Mouse; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.ARBTransposeMatrix; +import org.lwjgl.opengl.AWTGLCanvas; +import org.lwjgl.opengl.AWTInputAdapter; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GLContext; + +/** + *

+ * Gears demo using AWTInputAdapter input + *

+ * @version $Revision$ + * @author Brian Matzon + * @author Elias Naur + * $Id$ + */ +public class AWTInputAdapterTest extends Frame { + /** AWT GL canvas */ + private AWTGLCanvas canvas0; + + private float view_rotx = 20.0f; + + private float view_roty = 30.0f; + + private float view_rotz = 0.0f; + + private int gear1; + + private int gear2; + + private int gear3; + + private float angle = 0.0f; + + /** + * C'tor + */ + public AWTInputAdapterTest() throws LWJGLException { + setTitle("Gears"); + setSize(300, 300); + setBackground(Color.BLACK); + add(canvas0 = new AWTGLCanvas() { + long startTime = 0; + long fps = 0; + int current_width; + int current_height; + public void paintGL() { + + if(startTime == 0) { + setup(); + startTime = System.currentTimeMillis() + 5000; + } + + try { + angle += 2.0f; + if (getWidth() != current_width || getHeight() != current_height) { + current_width = getWidth(); + current_height = getHeight(); + GL11.glViewport(0, 0, current_width, current_height); + } + GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); + + GL11.glPushMatrix(); + GL11.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); + GL11.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); + GL11.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); + + GL11.glPushMatrix(); + GL11.glTranslatef(-3.0f, -2.0f, 0.0f); + GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f); + GL11.glCallList(gear1); + GL11.glPopMatrix(); + + GL11.glPushMatrix(); + GL11.glTranslatef(3.1f, -2.0f, 0.0f); + GL11.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f); + GL11.glCallList(gear2); + GL11.glPopMatrix(); + + GL11.glPushMatrix(); + GL11.glTranslatef(-3.1f, 4.2f, 0.0f); + GL11.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f); + GL11.glCallList(gear3); + GL11.glPopMatrix(); + + GL11.glPopMatrix(); + swapBuffers(); + repaint(); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } + if (startTime > System.currentTimeMillis()) { + fps++; + } else { + long timeUsed = 5000 + (startTime - System.currentTimeMillis()); + startTime = System.currentTimeMillis() + 5000; + System.out.println(fps + " frames in " + (float) (timeUsed / 1000f) + " seconds = " + + (fps / (timeUsed / 1000f))); + fps = 0; + } + AWTInputAdapter.update(); + while (Mouse.next()) { + view_roty += Mouse.getEventDX()*.1; + view_rotx -= Mouse.getEventDY()*.1; + } + while (Keyboard.next()) { + if (Keyboard.getEventKeyState()) { + switch (Keyboard.getEventKey()) { + case Keyboard.KEY_ESCAPE: + System.exit(0); + break; + case Keyboard.KEY_G: + Mouse.setGrabbed(!Mouse.isGrabbed()); + break; + default: + break; + } + } + if (Keyboard.getEventCharacter() != Keyboard.CHAR_NONE) + System.out.println("Typed: " + Keyboard.getEventCharacter()); + } + if (Keyboard.isKeyDown(Keyboard.KEY_UP)) + view_rotx -= .1; + else if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) + view_rotx += .1; + if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) + view_roty -= .1; + else if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) + view_roty += .1; + } + }); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dispose(); + System.exit(0); + } + }); + AWTInputAdapter.create(canvas0); + canvas0.setFocusable(true); + canvas0.requestFocus(); + setResizable(true); + setVisible(true); + } + + private void setup() { + // setup ogl + FloatBuffer pos = BufferUtils.createFloatBuffer(4).put(new float[] { 5.0f, 5.0f, 10.0f, 0.0f}); + FloatBuffer red = BufferUtils.createFloatBuffer(4).put(new float[] { 0.8f, 0.1f, 0.0f, 1.0f}); + FloatBuffer green = BufferUtils.createFloatBuffer(4).put(new float[] { 0.0f, 0.8f, 0.2f, 1.0f}); + FloatBuffer blue = BufferUtils.createFloatBuffer(4).put(new float[] { 0.2f, 0.2f, 1.0f, 1.0f}); + pos.flip(); + red.flip(); + green.flip(); + blue.flip(); + + GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, pos); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_LIGHT0); + GL11.glEnable(GL11.GL_DEPTH_TEST); + + /* make the gears */ + gear1 = GL11.glGenLists(1); + GL11.glNewList(gear1, GL11.GL_COMPILE); + GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red); + gear(1.0f, 4.0f, 1.0f, 20, 0.7f); + GL11.glEndList(); + + gear2 = GL11.glGenLists(1); + GL11.glNewList(gear2, GL11.GL_COMPILE); + GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, green); + gear(0.5f, 2.0f, 2.0f, 10, 0.7f); + GL11.glEndList(); + + gear3 = GL11.glGenLists(1); + GL11.glNewList(gear3, GL11.GL_COMPILE); + GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue); + gear(1.3f, 2.0f, 0.5f, 10, 0.7f); + GL11.glEndList(); + + GL11.glEnable(GL11.GL_NORMALIZE); + + GL11.glMatrixMode(GL11.GL_PROJECTION); + + System.err.println("Use the arrow keys and the mouse to rotate the gears. Press 'G' to toggle mouse grabbing."); + System.err.println("GL_VENDOR: " + GL11.glGetString(GL11.GL_VENDOR)); + System.err.println("GL_RENDERER: " + GL11.glGetString(GL11.GL_RENDERER)); + System.err.println("GL_VERSION: " + GL11.glGetString(GL11.GL_VERSION)); + System.err.println(); + System.err.println("glLoadTransposeMatrixfARB() supported: " + GLContext.getCapabilities().GL_ARB_transpose_matrix); + if (!GLContext.getCapabilities().GL_ARB_transpose_matrix) { + // --- not using extensions + GL11.glLoadIdentity(); + } else { + // --- using extensions + final FloatBuffer identityTranspose = BufferUtils.createFloatBuffer(16).put( + new float[] { 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 1}); + identityTranspose.flip(); + ARBTransposeMatrix.glLoadTransposeMatrixARB(identityTranspose); + } + + float h = (float) 300 / (float) 300; + GL11.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + GL11.glLoadIdentity(); + GL11.glTranslatef(0.0f, 0.0f, -40.0f); + } + + /** + * Draw a gear wheel. You'll probably want to call this function when + * building a display list since we do a lot of trig here. + * + * @param inner_radius radius of hole at center + * @param outer_radius radius at center of teeth + * @param width width of gear + * @param teeth number of teeth + * @param tooth_depth depth of tooth + */ + private void gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) { + int i; + float r0, r1, r2; + float angle, da; + float u, v, len; + + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0f; + r2 = outer_radius + tooth_depth / 2.0f; + + da = 2.0f * (float) Math.PI / teeth / 4.0f; + + GL11.glShadeModel(GL11.GL_FLAT); + + GL11.glNormal3f(0.0f, 0.0f, 1.0f); + + /* draw front face */ + GL11.glBegin(GL11.GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0f * (float) Math.PI / teeth; + GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); + if (i < teeth) { + GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), + width * 0.5f); + } + } + GL11.glEnd(); + + /* draw front sides of teeth */ + GL11.glBegin(GL11.GL_QUADS); + for (i = 0; i < teeth; i++) { + angle = i * 2.0f * (float) Math.PI / teeth; + GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f); + } + GL11.glEnd(); + + /* draw back face */ + GL11.glBegin(GL11.GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0f * (float) Math.PI / teeth; + GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); + GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); + GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); + } + GL11.glEnd(); + + /* draw back sides of teeth */ + GL11.glBegin(GL11.GL_QUADS); + for (i = 0; i < teeth; i++) { + angle = i * 2.0f * (float) Math.PI / teeth; + GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); + } + GL11.glEnd(); + + /* draw outward faces of teeth */ + GL11.glBegin(GL11.GL_QUAD_STRIP); + for (i = 0; i < teeth; i++) { + angle = i * 2.0f * (float) Math.PI / teeth; + GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); + u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle); + v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle); + len = (float) Math.sqrt(u * u + v * v); + u /= len; + v /= len; + GL11.glNormal3f(v, -u, 0.0f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f); + GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f); + GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f); + u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da); + v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da); + GL11.glNormal3f(v, -u, 0.0f); + GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); + GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f); + } + GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f); + GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f); + GL11.glEnd(); + + GL11.glShadeModel(GL11.GL_SMOOTH); + + /* draw inside radius cylinder */ + GL11.glBegin(GL11.GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0f * (float) Math.PI / teeth; + GL11.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f); + GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); + GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); + } + GL11.glEnd(); + } + + public static void main(String[] args) throws LWJGLException { + new AWTInputAdapterTest(); + } +} diff --git a/src/native/linux/org_lwjgl_opengl_LinuxAWTInput.c b/src/native/linux/org_lwjgl_opengl_LinuxAWTInput.c new file mode 100644 index 00000000..24b043fe --- /dev/null +++ b/src/native/linux/org_lwjgl_opengl_LinuxAWTInput.c @@ -0,0 +1,51 @@ +/* + * 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_LinuxAWTInput.h" + +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxAWTInput_createInputOnlyWindow(JNIEnv *env, jclass unused, jlong display_ptr, jint screen) { + Display *disp = (Display *)(intptr_t)display_ptr; + Window window = XCreateWindow(disp, RootWindow(disp, screen), 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, 0, NULL); + return window; +} diff --git a/src/native/linux/org_lwjgl_opengl_LinuxPeerInfo.c b/src/native/linux/org_lwjgl_opengl_LinuxPeerInfo.c index cb35c4d3..ab41a551 100644 --- a/src/native/linux/org_lwjgl_opengl_LinuxPeerInfo.c +++ b/src/native/linux/org_lwjgl_opengl_LinuxPeerInfo.c @@ -46,3 +46,13 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxPeerInfo_createHandle (JNIEnv *env, jclass clazz) { return newJavaManagedByteBuffer(env, sizeof(X11PeerInfo)); } + +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxPeerInfo_nGetDisplay(JNIEnv *env, jclass unused, jobject handle) { + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, handle); + return (jlong)(intptr_t)peer_info->display; +} + +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxPeerInfo_nGetDrawable(JNIEnv *env, jclass unused, jobject handle) { + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, handle); + return peer_info->drawable; +}