mirror of
https://github.com/shadowfacts/lwjgl2-arm64.git
synced 2026-04-21 06:14:10 +00:00
Native cursors implemented
This commit is contained in:
parent
fd75f7a959
commit
e886d95122
20 changed files with 1351 additions and 238 deletions
91
src/java/org/lwjgl/input/Cursor.java
Normal file
91
src/java/org/lwjgl/input/Cursor.java
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2002 Lightweight Java Game Library 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 'Light Weight Java Game Library' 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.input;
|
||||
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* A class representing a native cursor. Instances of this
|
||||
* class can be used with Mouse.setCursor(), if available.
|
||||
*
|
||||
* @author elias_naur <elias_naur@users.sourceforge.net>
|
||||
* @version $Revision$
|
||||
*/
|
||||
|
||||
public class Cursor {
|
||||
/**
|
||||
* The native handle to the cursor
|
||||
*/
|
||||
private final int nativeHandle;
|
||||
|
||||
/**
|
||||
* Constructs a new Cursor, with the given parameters. Mouse must have been created before you can create
|
||||
* Cursor objects. Cursor images are in ARGB format, but only one bit transparancy is guaranteed to be supported.
|
||||
* So to maximize portability, lwjgl applications should only create cursor images with 0x00 or 0xff as alpha values.
|
||||
*
|
||||
* @param width cursor image width
|
||||
* @param height cursor image height
|
||||
* @param xHotspot the x coordinate of the cursor hotspot
|
||||
* @param yHotspot the y coordinate of the cursor hotspot
|
||||
* @param cursorAddress the address of an int array containing the cursor image
|
||||
* @throws Exception if the cursor could not be created for any reason
|
||||
*/
|
||||
public Cursor(int width, int height, int xHotspot, int yHotspot, int imageAddress) throws Exception {
|
||||
assert Mouse.isCreated();
|
||||
nativeHandle = nCreateCursor(width, height, xHotspot, yHotspot, imageAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the native cursor. Cursor must not be current.
|
||||
*/
|
||||
public void destroy() {
|
||||
nDestroyCursor(nativeHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the native handle associated with the cursor object.
|
||||
*/
|
||||
public int getHandle() {
|
||||
return nativeHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Native method to create a native cursor
|
||||
*/
|
||||
private static native int nCreateCursor(int width, int height, int xHotspot, int yHotspot, int imageAddresses);
|
||||
|
||||
/**
|
||||
* Native method to destroy a native cursor
|
||||
*/
|
||||
private static native void nDestroyCursor(int handle);
|
||||
}
|
||||
|
|
@ -70,6 +70,9 @@ public class Mouse {
|
|||
/** Does this mouse support a scroll wheel */
|
||||
public static boolean hasWheel = false;
|
||||
|
||||
/** The current native cursor, if any */
|
||||
private static Cursor currentCursor;
|
||||
|
||||
static {
|
||||
initialize();
|
||||
}
|
||||
|
|
@ -80,6 +83,83 @@ public class Mouse {
|
|||
private Mouse() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently bound native cursor, if any.
|
||||
*
|
||||
* @return the currently bound native cursor, if any.
|
||||
public Cursor getNativeCursor() {
|
||||
return currentCursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check native cursor support
|
||||
* @return true if native cursors are supported
|
||||
*/
|
||||
public static boolean isNativeCursorSupported() {
|
||||
return nIsNativeCursorSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* Native function to determine native cursor support
|
||||
*/
|
||||
private static native boolean nIsNativeCursorSupported();
|
||||
|
||||
/**
|
||||
* Binds a native cursor. If the cursor argument is null, the
|
||||
* native cursor is disabled, as if native cursors were not supported.
|
||||
* The Mouse must be created before a native cursor can be bound.
|
||||
*
|
||||
* NOTE: The native cursor is not constrained to the window, but
|
||||
* relative events will not be generated if the cursor is outside.
|
||||
* The initial position of the cursor is in the upper left corner of
|
||||
* the window, and the cursor will be moved to this origin when a
|
||||
* native cursor is set and the previous cursor is null.
|
||||
*
|
||||
* @param cursor the native cursor object to bind. May be null.
|
||||
* @return The previous Cursor object set, or null.
|
||||
* @throws Exception if the cursor could not be set for any reason
|
||||
*/
|
||||
public static Cursor setNativeCursor(Cursor cursor) throws Exception {
|
||||
assert created && isNativeCursorSupported();
|
||||
Cursor oldCursor = currentCursor;
|
||||
currentCursor = cursor;
|
||||
if (currentCursor != null) {
|
||||
nSetNativeCursor(currentCursor.getHandle());
|
||||
} else {
|
||||
nSetNativeCursor(Sys.NULL);
|
||||
}
|
||||
return oldCursor;
|
||||
}
|
||||
|
||||
/** Native method to set the native cursor */
|
||||
private static native void nSetNativeCursor(int handle);
|
||||
|
||||
/**
|
||||
* Gets the minimum size of a native cursor. Can only be called if
|
||||
* The Mouse is created and isNativeCursorSupported() returns true
|
||||
*
|
||||
* @return the maximum size of a native cursor
|
||||
*/
|
||||
public static int getMinCursorSize() {
|
||||
return nGetMinCursorSize();
|
||||
}
|
||||
|
||||
/** Native method returning the minimum cursor size */
|
||||
private static native int nGetMinCursorSize();
|
||||
|
||||
/**
|
||||
* Gets the maximum size of a native cursor. Can only be called if
|
||||
* The Mouse is created and isNativeCursorSupported() returns true
|
||||
*
|
||||
* @return the maximum size of a native cursor
|
||||
*/
|
||||
public static int getMaxCursorSize() {
|
||||
return nGetMaxCursorSize();
|
||||
}
|
||||
|
||||
/** Native method returning the maximum cursor size */
|
||||
private static native int nGetMaxCursorSize();
|
||||
|
||||
/**
|
||||
* Static initialization
|
||||
*/
|
||||
|
|
@ -104,13 +184,14 @@ public class Mouse {
|
|||
if (!nCreate())
|
||||
throw new Exception("The mouse could not be created.");
|
||||
created = true;
|
||||
currentCursor = null;
|
||||
|
||||
//set mouse buttons
|
||||
buttons = new boolean[buttonCount];
|
||||
}
|
||||
|
||||
/**
|
||||
* Native method to create the mouse
|
||||
* Native method to create the mouse.
|
||||
*
|
||||
* @return true if the mouse was created
|
||||
*/
|
||||
|
|
@ -124,13 +205,16 @@ public class Mouse {
|
|||
}
|
||||
|
||||
/**
|
||||
* "Destroy" the mouse
|
||||
* "Destroy" the mouse. Remember to reset the native cursor if
|
||||
* setNativeCursor() has been called with anything else than null.
|
||||
*/
|
||||
public static void destroy() {
|
||||
assert currentCursor == null;
|
||||
if (!created)
|
||||
return;
|
||||
created = false;
|
||||
buttons = null;
|
||||
currentCursor = null;
|
||||
|
||||
nDestroy();
|
||||
}
|
||||
|
|
@ -163,4 +247,4 @@ public class Mouse {
|
|||
assert created : "The mouse has not been created.";
|
||||
return buttons[button];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
361
src/java/org/lwjgl/test/input/HWCursorTest.java
Normal file
361
src/java/org/lwjgl/test/input/HWCursorTest.java
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Lightweight Java Game Library 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 'Lightweight Java Game Library' 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.input;
|
||||
|
||||
import org.lwjgl.*;
|
||||
import org.lwjgl.input.*;
|
||||
import org.lwjgl.opengl.*;
|
||||
import org.lwjgl.vector.Vector2f;
|
||||
|
||||
import java.nio.*;
|
||||
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* Tests switching between windowed and fullscreen - including hardware cursor test
|
||||
*
|
||||
* @author Brian Matzon <brian@matzon.dk>
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class HWCursorTest {
|
||||
|
||||
/** Intended deiplay mode */
|
||||
private DisplayMode mode;
|
||||
|
||||
/** GL instance */
|
||||
private GL gl;
|
||||
|
||||
/** GLU instance */
|
||||
private GLU glu;
|
||||
|
||||
/** The native cursor */
|
||||
private static Cursor cursor = null;
|
||||
|
||||
/** The mouse cursor position */
|
||||
private static int mouse_x;
|
||||
private static int mouse_y;
|
||||
|
||||
/**
|
||||
* Executes the test
|
||||
*/
|
||||
public void execute() {
|
||||
initialize();
|
||||
|
||||
mainLoop();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the test
|
||||
*/
|
||||
private void initialize() {
|
||||
try {
|
||||
//find displaymode
|
||||
mode = findDisplayMode(800, 600, 16);
|
||||
|
||||
// start of in windowed mode
|
||||
gl = new GL("Test", 50, 50, mode.width, mode.height, mode.bpp, 0, 0, 0);
|
||||
gl.create();
|
||||
glu = new GLU(gl);
|
||||
|
||||
glInit();
|
||||
|
||||
Keyboard.create();
|
||||
initNativeCursor();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void initNativeCursor() {
|
||||
try {
|
||||
Mouse.create();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (!Mouse.isNativeCursorSupported()) {
|
||||
System.out.println("No HW cursor support!");
|
||||
System.exit(0);
|
||||
}
|
||||
System.out.println("Maximum native cursor size: " + Mouse.getMaxCursorSize() + ", min size: " + Mouse.getMinCursorSize());
|
||||
mouse_x = mouse_y = 0;
|
||||
// int num_images = 3;
|
||||
int image_size = Mouse.getMaxCursorSize()*Mouse.getMaxCursorSize();
|
||||
IntBuffer cursor_images = ByteBuffer.allocateDirect(/*num_images**/image_size*4).order(ByteOrder.nativeOrder()).asIntBuffer();
|
||||
/* IntBuffer delays = ByteBuffer.allocateDirect(num_images*4).order(ByteOrder.nativeOrder()).asIntBuffer();
|
||||
delays.put(0, 500);
|
||||
delays.put(1, 500);
|
||||
delays.put(2, 500);*/
|
||||
int color_scale = 255/Mouse.getMaxCursorSize();
|
||||
int bit_mask = 0x81000000;
|
||||
for (int j = 0; j < image_size; j++) {
|
||||
if (j % 4 == 0)
|
||||
bit_mask = (~bit_mask) & 0x81000000;
|
||||
int color = (j*color_scale/Mouse.getMaxCursorSize()) << 16;
|
||||
cursor_images.put(0*image_size + j, 0x00000020 | color | bit_mask);
|
||||
}
|
||||
/* for (int j = 0; j < image_size; j++) {
|
||||
int color = (j*color_scale/Mouse.getMaxCursorSize()) << 8;
|
||||
cursor_images.put(1*image_size + j, 0x80000000 | color);
|
||||
}
|
||||
for (int j = 0; j < image_size; j++) {
|
||||
int color = j*color_scale/Mouse.getMaxCursorSize();
|
||||
cursor_images.put(2*image_size + j, 0x80000000 | color);
|
||||
}*/
|
||||
try {
|
||||
cursor = new Cursor(Mouse.getMaxCursorSize(), Mouse.getMaxCursorSize(), Mouse.getMaxCursorSize()/2, Mouse.getMaxCursorSize()/2/*, num_images*/, Sys.getDirectBufferAddress(cursor_images)/*, Sys.getDirectBufferAddress(delays)*/);
|
||||
Mouse.setNativeCursor(cursor);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the main loop of the "test"
|
||||
*/
|
||||
private void mainLoop() {
|
||||
while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)
|
||||
&& !gl.isCloseRequested()) {
|
||||
// allow subsystem to get a chance to run too
|
||||
gl.tick();
|
||||
|
||||
if (!gl.isMinimized()) {
|
||||
// check keyboard input
|
||||
processKeyboard();
|
||||
|
||||
render();
|
||||
|
||||
// paint window
|
||||
gl.paint();
|
||||
} else {
|
||||
|
||||
// no need to render/paint if nothing has changed (ie. window dragged over)
|
||||
if (gl.isDirty()) {
|
||||
render();
|
||||
gl.paint();
|
||||
}
|
||||
|
||||
// don't waste cpu time, sleep more
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException inte) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the logic
|
||||
*/
|
||||
private void render() {
|
||||
//clear background
|
||||
gl.clear(GL.COLOR_BUFFER_BIT);
|
||||
|
||||
// draw white quad
|
||||
gl.pushMatrix();
|
||||
{
|
||||
gl.translatef(mouse_x, 600 - mouse_y, 0);
|
||||
gl.color3f(1.0f, 1.0f, 1.0f);
|
||||
gl.begin(GL.QUADS);
|
||||
{
|
||||
gl.vertex2i(-50, -50);
|
||||
gl.vertex2i(50, -50);
|
||||
gl.vertex2i(50, 50);
|
||||
gl.vertex2i(-50, 50);
|
||||
}
|
||||
gl.end();
|
||||
}
|
||||
gl.popMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes keyboard input
|
||||
*/
|
||||
private void processKeyboard() {
|
||||
Keyboard.poll();
|
||||
Mouse.poll();
|
||||
|
||||
if (Mouse.dx != 0 || Mouse.dy != 0) {
|
||||
mouse_x += Mouse.dx;
|
||||
mouse_y += Mouse.dy;
|
||||
System.out.println("mouse_x " + mouse_x + " mouse_y " + mouse_y);
|
||||
}
|
||||
|
||||
//check for fullscreen key
|
||||
if (Keyboard.isKeyDown(Keyboard.KEY_F)) {
|
||||
|
||||
try {
|
||||
Keyboard.destroy();
|
||||
try {
|
||||
Mouse.setNativeCursor(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
cursor.destroy();
|
||||
Mouse.destroy();
|
||||
gl.destroy();
|
||||
|
||||
Display.setDisplayMode(mode);
|
||||
gl = new GL("Test", mode.bpp, 0, 0, 0);
|
||||
gl.create();
|
||||
glu = new GLU(gl);
|
||||
|
||||
glInit();
|
||||
|
||||
Keyboard.create();
|
||||
initNativeCursor();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//check for window key
|
||||
if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
|
||||
try {
|
||||
Keyboard.destroy();
|
||||
try {
|
||||
Mouse.setNativeCursor(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
cursor.destroy();
|
||||
Mouse.destroy();
|
||||
gl.destroy();
|
||||
|
||||
Display.resetDisplayMode();
|
||||
gl = new GL("Test", 50, 50, mode.width, mode.height, mode.bpp, 0, 0, 0);
|
||||
gl.create();
|
||||
glu = new GLU(gl);
|
||||
|
||||
glInit();
|
||||
|
||||
Keyboard.create();
|
||||
initNativeCursor();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (Keyboard.isKeyDown(Keyboard.KEY_M)) {
|
||||
try {
|
||||
Mouse.setNativeCursor(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (Keyboard.isKeyDown(Keyboard.KEY_N)) {
|
||||
try {
|
||||
Mouse.setNativeCursor(cursor);
|
||||
mouse_x = mouse_y = 0;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the test
|
||||
*/
|
||||
private void cleanup() {
|
||||
Keyboard.destroy();
|
||||
try {
|
||||
Mouse.setNativeCursor(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
cursor.destroy();
|
||||
Mouse.destroy();
|
||||
Display.resetDisplayMode();
|
||||
gl.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a displaymode, if one such is available
|
||||
*
|
||||
* @param width Required width
|
||||
* @param height Required height
|
||||
* @param bpp Minimum required bits per pixel
|
||||
* @return
|
||||
*/
|
||||
private DisplayMode findDisplayMode(int width, int height, int bpp) {
|
||||
DisplayMode[] modes = Display.getAvailableDisplayModes();
|
||||
for (int i = 0; i < modes.length; i++) {
|
||||
if (modes[i].width == width
|
||||
&& modes[i].height == height
|
||||
&& modes[i].bpp >= bpp) {
|
||||
return modes[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes OGL
|
||||
*/
|
||||
private void glInit() {
|
||||
// Go into orthographic projection mode.
|
||||
gl.determineAvailableExtensions();
|
||||
gl.matrixMode(GL.PROJECTION);
|
||||
gl.loadIdentity();
|
||||
glu.ortho2D(0, mode.width, 0, mode.height);
|
||||
gl.matrixMode(GL.MODELVIEW);
|
||||
gl.loadIdentity();
|
||||
gl.viewport(0, 0, mode.width, mode.height);
|
||||
|
||||
//set clear color to black
|
||||
gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
//sync frame (only works on windows)
|
||||
if (GL.WGL_EXT_swap_control) {
|
||||
GL.wglSwapIntervalEXT(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test entry point
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
System.out.println(
|
||||
"Change between fullscreen and windowed mode, by pressing F and W respectively. Enable hw cursor with N and disable it with M.");
|
||||
System.out.println(
|
||||
"Move quad using arrowkeys, and change rotation using +/-");
|
||||
HWCursorTest cursorTest = new HWCursorTest();
|
||||
cursorTest.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -3331,7 +3331,6 @@ int extgl_Open(void)
|
|||
void extgl_Close(void)
|
||||
{
|
||||
#ifdef _X11
|
||||
printf("closing handles\n");
|
||||
dlclose(lib_glu_handle);
|
||||
dlclose(lib_gl_handle);
|
||||
#endif
|
||||
|
|
|
|||
31
src/native/common/org_lwjgl_input_Cursor.h
Normal file
31
src/native/common/org_lwjgl_input_Cursor.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class org_lwjgl_input_Cursor */
|
||||
|
||||
#ifndef _Included_org_lwjgl_input_Cursor
|
||||
#define _Included_org_lwjgl_input_Cursor
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Inaccessible static: _00024assertionsDisabled */
|
||||
/* Inaccessible static: class_00024org_00024lwjgl_00024input_00024Cursor */
|
||||
/*
|
||||
* Class: org_lwjgl_input_Cursor
|
||||
* Method: nCreateCursor
|
||||
* Signature: (IIIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor
|
||||
(JNIEnv *, jclass, jint, jint, jint, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Cursor
|
||||
* Method: nDestroyCursor
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Cursor_nDestroyCursor
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -15,7 +15,40 @@ extern "C" {
|
|||
/* Inaccessible static: dwheel */
|
||||
/* Inaccessible static: buttonCount */
|
||||
/* Inaccessible static: hasWheel */
|
||||
/* Inaccessible static: class_000240 */
|
||||
/* Inaccessible static: currentCursor */
|
||||
/* Inaccessible static: class_00024org_00024lwjgl_00024input_00024Mouse */
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nIsNativeCursorSupported
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nIsNativeCursorSupported
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nSetNativeCursor
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nSetNativeCursor
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGetMinCursorSize
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMinCursorSize
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGetMaxCursorSize
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMaxCursorSize
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: initIDs
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ NATIVE = \
|
|||
org_lwjgl_input_Controller.cpp \
|
||||
org_lwjgl_input_Keyboard.cpp \
|
||||
org_lwjgl_input_Mouse.cpp \
|
||||
org_lwjgl_input_Cursor.cpp \
|
||||
org_lwjgl_opengl_BaseGL.cpp \
|
||||
org_lwjgl_Window.cpp
|
||||
|
||||
org_lwjgl_Window.cpp \
|
||||
extxcursor.cpp
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,11 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
/*
|
||||
* update input grabbing(keyboard, mouse)
|
||||
*/
|
||||
extern void updateInput(void);
|
||||
|
||||
/*
|
||||
* release input (keyboard, mouse)
|
||||
*/
|
||||
|
|
@ -99,6 +104,16 @@
|
|||
*/
|
||||
extern Window getCurrentWindow(void);
|
||||
|
||||
/*
|
||||
* Return true if a native cursor is active
|
||||
*/
|
||||
extern bool isNativeCursor(void);
|
||||
|
||||
/*
|
||||
* Return true if we are in fullscreen mode
|
||||
*/
|
||||
extern bool isFullscreen(void);
|
||||
|
||||
/*
|
||||
* Utility function to throw an Exception
|
||||
*/
|
||||
|
|
|
|||
63
src/native/linux/extxcursor.cpp
Normal file
63
src/native/linux/extxcursor.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include "extxcursor.h"
|
||||
|
||||
static void * xcursor_handle = NULL;
|
||||
static const char *xcursor_lib_name = "libXcursor.so.1";
|
||||
static bool load_success;
|
||||
|
||||
XcursorSupportsARGBPROC XcursorSupportsARGB = NULL;
|
||||
XcursorSupportsAnimPROC XcursorSupportsAnim = NULL;
|
||||
XcursorImageCreatePROC XcursorImageCreate = NULL;
|
||||
XcursorImageDestroyPROC XcursorImageDestroy = NULL;
|
||||
XcursorImagesCreatePROC XcursorImagesCreate = NULL;
|
||||
XcursorImagesDestroyPROC XcursorImagesDestroy = NULL;
|
||||
XcursorImagesLoadCursorPROC XcursorImagesLoadCursor = NULL;
|
||||
|
||||
static void * loadHandle(const char * func_name) {
|
||||
void * func_pointer = dlsym(xcursor_handle, func_name);
|
||||
if (func_pointer == NULL) {
|
||||
load_success = false;
|
||||
return NULL;
|
||||
}
|
||||
return func_pointer;
|
||||
}
|
||||
|
||||
static bool loadFunctionPointers(void) {
|
||||
XcursorSupportsARGB = (XcursorSupportsARGBPROC)loadHandle("XcursorSupportsARGB");
|
||||
XcursorSupportsAnim = (XcursorSupportsAnimPROC)loadHandle("XcursorSupportsAnim");
|
||||
XcursorImageCreate = (XcursorImageCreatePROC)loadHandle("XcursorImageCreate");
|
||||
XcursorImageDestroy = (XcursorImageDestroyPROC)loadHandle("XcursorImageDestroy");
|
||||
XcursorImagesCreate = (XcursorImagesCreatePROC)loadHandle("XcursorImagesCreate");
|
||||
XcursorImagesDestroy = (XcursorImagesDestroyPROC)loadHandle("XcursorImagesDestroy");
|
||||
XcursorImagesLoadCursor = (XcursorImagesLoadCursorPROC)loadHandle("XcursorImagesLoadCursor");
|
||||
return load_success;
|
||||
}
|
||||
|
||||
bool loadXcursor(void) {
|
||||
load_success = true;
|
||||
xcursor_handle = dlopen(xcursor_lib_name, RTLD_GLOBAL | RTLD_LAZY);
|
||||
if (xcursor_handle == NULL) {
|
||||
printf("Could not load %s: %s\n", xcursor_lib_name, dlerror());
|
||||
return false;
|
||||
}
|
||||
loadFunctionPointers();
|
||||
return load_success;
|
||||
}
|
||||
|
||||
bool isXcursorLoaded(void) {
|
||||
return load_success;
|
||||
}
|
||||
|
||||
void closeXcursor(void) {
|
||||
load_success = false;
|
||||
dlclose(xcursor_handle);
|
||||
xcursor_handle = NULL;
|
||||
XcursorSupportsARGB = NULL;
|
||||
XcursorSupportsAnim = NULL;
|
||||
XcursorImageCreate = NULL;
|
||||
XcursorImageDestroy = NULL;
|
||||
XcursorImagesCreate = NULL;
|
||||
XcursorImagesDestroy = NULL;
|
||||
XcursorImagesLoadCursor = NULL;
|
||||
}
|
||||
51
src/native/linux/extxcursor.h
Normal file
51
src/native/linux/extxcursor.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include <X11/Xlib.h>
|
||||
|
||||
#define XcursorTrue 1
|
||||
#define XcursorFalse 0
|
||||
|
||||
typedef int XcursorBool;
|
||||
|
||||
typedef int XcursorBool;
|
||||
typedef unsigned int XcursorUInt;
|
||||
|
||||
typedef XcursorUInt XcursorDim;
|
||||
typedef XcursorUInt XcursorPixel;
|
||||
|
||||
typedef struct _XcursorImage {
|
||||
XcursorUInt version; /* version of the image data */
|
||||
XcursorDim size; /* nominal size for matching */
|
||||
XcursorDim width; /* actual width */
|
||||
XcursorDim height; /* actual height */
|
||||
XcursorDim xhot; /* hot spot x (must be inside image) */
|
||||
XcursorDim yhot; /* hot spot y (must be inside image) */
|
||||
XcursorUInt delay; /* animation delay to next frame (ms) */
|
||||
XcursorPixel *pixels; /* pointer to pixels */
|
||||
} XcursorImage;
|
||||
|
||||
/*
|
||||
* Other data structures exposed by the library API
|
||||
*/
|
||||
typedef struct _XcursorImages {
|
||||
int nimage; /* number of images */
|
||||
XcursorImage **images; /* array of XcursorImage pointers */
|
||||
} XcursorImages;
|
||||
|
||||
typedef XcursorBool (* XcursorSupportsARGBPROC ) (Display *dpy);
|
||||
typedef XcursorBool (* XcursorSupportsAnimPROC ) (Display *dpy);
|
||||
typedef XcursorImage * (* XcursorImageCreatePROC) (int width, int height);
|
||||
typedef void (* XcursorImageDestroyPROC) (XcursorImage *image);
|
||||
typedef XcursorImages * (* XcursorImagesCreatePROC) (int size);
|
||||
typedef void (* XcursorImagesDestroyPROC) (XcursorImages *images);
|
||||
typedef Cursor (* XcursorImagesLoadCursorPROC) (Display *dpy, const XcursorImages *images);
|
||||
|
||||
extern XcursorSupportsARGBPROC XcursorSupportsARGB;
|
||||
extern XcursorSupportsAnimPROC XcursorSupportsAnim;
|
||||
extern XcursorImageCreatePROC XcursorImageCreate;
|
||||
extern XcursorImageDestroyPROC XcursorImageDestroy;
|
||||
extern XcursorImagesCreatePROC XcursorImagesCreate;
|
||||
extern XcursorImagesDestroyPROC XcursorImagesDestroy;
|
||||
extern XcursorImagesLoadCursorPROC XcursorImagesLoadCursor;
|
||||
|
||||
bool loadXcursor(void);
|
||||
bool isXcursorLoaded(void);
|
||||
void closeXcursor(void);
|
||||
|
|
@ -68,15 +68,6 @@ static void waitMapped(Display *disp, Window win) {
|
|||
} while ((event.type != MapNotify) || (event.xmap.event != win));
|
||||
}
|
||||
|
||||
bool releaseInput(void) {
|
||||
if (current_fullscreen || input_released)
|
||||
return false;
|
||||
releaseKeyboard();
|
||||
releasePointer();
|
||||
input_released = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void acquireInput(void) {
|
||||
if (input_released) {
|
||||
acquireKeyboard();
|
||||
|
|
@ -85,6 +76,30 @@ static void acquireInput(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void doReleaseInput(void) {
|
||||
releaseKeyboard();
|
||||
releasePointer();
|
||||
input_released = true;
|
||||
}
|
||||
|
||||
void updateInput(void) {
|
||||
if (!input_released) {
|
||||
doReleaseInput();
|
||||
acquireInput();
|
||||
}
|
||||
}
|
||||
|
||||
bool releaseInput(void) {
|
||||
if (current_fullscreen || input_released)
|
||||
return false;
|
||||
doReleaseInput();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isFullscreen(void) {
|
||||
return current_fullscreen;
|
||||
}
|
||||
|
||||
static void handleMessages(JNIEnv *env, jobject window_obj) {
|
||||
XEvent event;
|
||||
while (XPending(current_disp) > 0) {
|
||||
|
|
@ -108,6 +123,7 @@ static void handleMessages(JNIEnv *env, jobject window_obj) {
|
|||
env->SetBooleanField(window_obj, env->GetFieldID(env->GetObjectClass(window_obj), "minimized", "Z"), JNI_TRUE);
|
||||
break;
|
||||
case Expose:
|
||||
// XSetInputFocus(current_disp, current_win, RevertToParent, CurrentTime);
|
||||
env->SetBooleanField(window_obj, env->GetFieldID(env->GetObjectClass(window_obj), "dirty", "Z"), JNI_TRUE);
|
||||
break;
|
||||
case ButtonPress:
|
||||
|
|
@ -183,6 +199,7 @@ void createWindow(JNIEnv* env, Display *disp, int screen, XVisualInfo *vis_info,
|
|||
XMapRaised(disp, win);
|
||||
waitMapped(disp, win);
|
||||
XClearWindow(disp, win);
|
||||
XSetInputFocus(current_disp, current_win, RevertToParent, CurrentTime);
|
||||
XSync(disp, True);
|
||||
}
|
||||
|
||||
|
|
|
|||
45
src/native/linux/org_lwjgl_input_Cursor.cpp
Normal file
45
src/native/linux/org_lwjgl_input_Cursor.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#include "org_lwjgl_input_Cursor.h"
|
||||
#include "extxcursor.h"
|
||||
#include "Window.h"
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Cursor
|
||||
* Method: nCreateCursor
|
||||
* Signature: (IIIIIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor
|
||||
(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, /*jint num_cursors,*/ jint image_address/*, jint delay_addresses*/)
|
||||
{
|
||||
XcursorPixel *pixels = (XcursorPixel *)image_address;
|
||||
/* int *delays = (int *)delay_addresses;
|
||||
int stride = width*height;*/
|
||||
int num_cursors = 1;
|
||||
XcursorImages *cursor_images = XcursorImagesCreate(num_cursors);
|
||||
if (cursor_images == NULL)
|
||||
throwException(env, "Could not allocate cursor.");
|
||||
cursor_images->nimage = num_cursors;
|
||||
// for (int i = 0; i < num_cursors; i++) {
|
||||
XcursorImage *cursor_image = XcursorImageCreate(width, height);
|
||||
cursor_image->xhot = x_hotspot;
|
||||
cursor_image->yhot = y_hotspot;
|
||||
cursor_image->pixels = pixels;
|
||||
// cursor_image->pixels = &(pixels[stride*i]);
|
||||
cursor_image->delay = 0/*delays[i]*/;
|
||||
cursor_images->images[0] = cursor_image;
|
||||
// }
|
||||
Cursor cursor = XcursorImagesLoadCursor(getCurrentDisplay(), cursor_images);
|
||||
XcursorImagesDestroy(cursor_images);
|
||||
return (jint)cursor;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Cursor
|
||||
* Method: nDestroyCursor
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Cursor_nDestroyCursor
|
||||
(JNIEnv *env, jclass clazz, jint cursor_handle)
|
||||
{
|
||||
Cursor cursor = (Cursor)cursor_handle;
|
||||
XFreeCursor(getCurrentDisplay(), cursor);
|
||||
}
|
||||
|
|
@ -83,28 +83,34 @@ static void setRepeatMode(int mode) {
|
|||
XChangeKeyboardControl(getCurrentDisplay(), KBAutoRepeatMode, &repeat_mode);
|
||||
}
|
||||
|
||||
static int grabKeyboard(void) {
|
||||
int result = XGrabKeyboard(getCurrentDisplay(), getCurrentWindow(), False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
if (result == GrabSuccess) {
|
||||
keyboard_grabbed = true;
|
||||
static void grabKeyboard(void) {
|
||||
if (isFullscreen() || !isNativeCursor()) {
|
||||
if (!keyboard_grabbed) {
|
||||
int result = XGrabKeyboard(getCurrentDisplay(), getCurrentWindow(), False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
if (result == GrabSuccess) {
|
||||
keyboard_grabbed = true;
|
||||
setRepeatMode(AutoRepeatModeOff);
|
||||
}
|
||||
}
|
||||
} else
|
||||
setRepeatMode(AutoRepeatModeOff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ungrabKeyboard(void) {
|
||||
keyboard_grabbed = false;
|
||||
XUngrabKeyboard(getCurrentDisplay(), CurrentTime);
|
||||
if (keyboard_grabbed) {
|
||||
keyboard_grabbed = false;
|
||||
XUngrabKeyboard(getCurrentDisplay(), CurrentTime);
|
||||
}
|
||||
setRepeatMode(AutoRepeatModeDefault);
|
||||
}
|
||||
|
||||
static void updateGrab(void) {
|
||||
if (!created)
|
||||
return;
|
||||
if (should_grab) {
|
||||
if (!keyboard_grabbed)
|
||||
grabKeyboard();
|
||||
grabKeyboard();
|
||||
} else {
|
||||
if (keyboard_grabbed)
|
||||
ungrabKeyboard();
|
||||
ungrabKeyboard();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,8 +171,7 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Keyboard_nCreate
|
|||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_nDestroy
|
||||
(JNIEnv * env, jclass clazz)
|
||||
{
|
||||
if (keyboard_grabbed)
|
||||
ungrabKeyboard();
|
||||
ungrabKeyboard();
|
||||
created = false;
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +264,6 @@ void handleKeyEvent(XKeyEvent *event) {
|
|||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_nPoll
|
||||
(JNIEnv * env, jclass clazz, jint buf)
|
||||
{
|
||||
updateGrab();
|
||||
memcpy((unsigned char*)buf, key_buf, KEYBOARD_SIZE*sizeof(unsigned char));
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +279,6 @@ JNIEXPORT int JNICALL Java_org_lwjgl_input_Keyboard_nRead
|
|||
int buf_count = 0;
|
||||
int num_events = 0;
|
||||
|
||||
updateGrab();
|
||||
while (buf_count < KEYBOARD_BUFFER_SIZE * 2 && (key_event = nextEventElement()) != NULL) {
|
||||
num_events++;
|
||||
unsigned char keycode = getKeycode(key_event);
|
||||
|
|
@ -286,7 +289,6 @@ JNIEXPORT int JNICALL Java_org_lwjgl_input_Keyboard_nRead
|
|||
if (translation_enabled)
|
||||
num_events += translateEvent(&buf_count, key_event);
|
||||
}
|
||||
|
||||
return num_events;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include <string.h>
|
||||
#include <Window.h>
|
||||
#include "org_lwjgl_input_Mouse.h"
|
||||
#include "extxcursor.h"
|
||||
|
||||
#define NUM_BUTTONS 3
|
||||
|
||||
|
|
@ -55,9 +56,10 @@
|
|||
// scale the mouse wheel according to win32
|
||||
#define WHEEL_SCALE 120
|
||||
|
||||
static bool pointer_grabbed;
|
||||
static bool pointer_grabbed = false;
|
||||
static bool created = false;
|
||||
static bool should_grab = false;
|
||||
static bool native_cursor = false;
|
||||
|
||||
static jfieldID fid_has_wheel = NULL;
|
||||
static jfieldID fid_button_count = NULL;
|
||||
|
|
@ -75,6 +77,9 @@ static int current_z;
|
|||
static unsigned char buttons[NUM_BUTTONS];
|
||||
|
||||
static Cursor blank_cursor;
|
||||
static Cursor current_cursor;
|
||||
|
||||
static int grab_mask = FocusChangeMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
|
|
@ -118,30 +123,39 @@ static int blankCursor(void) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int grabPointer(void) {
|
||||
int result;
|
||||
int mask = FocusChangeMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
|
||||
result = XGrabPointer(getCurrentDisplay(), getCurrentWindow(), False, mask, GrabModeAsync, GrabModeAsync, getCurrentWindow(), blank_cursor, CurrentTime);
|
||||
if (result == GrabSuccess) {
|
||||
pointer_grabbed = true;
|
||||
XWarpPointer(getCurrentDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, current_x, current_y);
|
||||
XF86VidModeSetViewPort(getCurrentDisplay(), getCurrentScreen(), 0, 0); // make sure we have a centered window
|
||||
bool isNativeCursor(void) {
|
||||
return native_cursor;
|
||||
}
|
||||
|
||||
static void grabPointer(void) {
|
||||
if (isFullscreen() || !native_cursor) {
|
||||
if (!pointer_grabbed) {
|
||||
int result;
|
||||
result = XGrabPointer(getCurrentDisplay(), getCurrentWindow(), False, grab_mask, GrabModeAsync,
|
||||
GrabModeAsync, getCurrentWindow(), current_cursor, CurrentTime);
|
||||
if (result == GrabSuccess) {
|
||||
pointer_grabbed = true;
|
||||
// make sure we have a centered window
|
||||
XF86VidModeSetViewPort(getCurrentDisplay(), getCurrentScreen(), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ungrabPointer(void) {
|
||||
pointer_grabbed = false;
|
||||
XUngrabPointer(getCurrentDisplay(), CurrentTime);
|
||||
if (pointer_grabbed) {
|
||||
pointer_grabbed = false;
|
||||
XUngrabPointer(getCurrentDisplay(), CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
static void updateGrab(void) {
|
||||
if (!created)
|
||||
return;
|
||||
if (should_grab) {
|
||||
if (!pointer_grabbed)
|
||||
grabPointer();
|
||||
grabPointer();
|
||||
} else {
|
||||
if (pointer_grabbed)
|
||||
ungrabPointer();
|
||||
ungrabPointer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,6 +169,73 @@ void releasePointer(void) {
|
|||
updateGrab();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nIsNativeCursorSupported
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nIsNativeCursorSupported
|
||||
(JNIEnv *env, jclass clazz) {
|
||||
if (!isXcursorLoaded())
|
||||
return false;
|
||||
XcursorBool argb_supported = XcursorSupportsARGB(getCurrentDisplay());
|
||||
XcursorBool anim_supported = XcursorSupportsAnim(getCurrentDisplay());
|
||||
return argb_supported && anim_supported ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nSetNativeCursor
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nSetNativeCursor
|
||||
(JNIEnv *env, jclass clazz, jint cursor_handle)
|
||||
{
|
||||
Cursor cursor = (Cursor)cursor_handle;
|
||||
if (cursor != None) {
|
||||
if (!native_cursor) {
|
||||
current_x = current_y = 0;
|
||||
XWarpPointer(getCurrentDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, current_x, current_y);
|
||||
native_cursor = true;
|
||||
}
|
||||
XDefineCursor(getCurrentDisplay(), getCurrentWindow(), cursor);
|
||||
current_cursor = cursor;
|
||||
updateInput();
|
||||
} else {
|
||||
if (native_cursor) {
|
||||
current_cursor = blank_cursor;
|
||||
XUndefineCursor(getCurrentDisplay(), getCurrentWindow());
|
||||
native_cursor = false;
|
||||
updateInput();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGetMaxCursorSize
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMinCursorSize
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGetMaxCursorSize
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMaxCursorSize
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
unsigned int width_return = 0;
|
||||
unsigned int height_return = 0;
|
||||
XQueryBestCursor(getCurrentDisplay(), getCurrentWindow(), 0xffffffff, 0xffffffff, &width_return, &height_return);
|
||||
return width_return > height_return ? height_return : width_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nCreate
|
||||
|
|
@ -164,21 +245,24 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate
|
|||
(JNIEnv * env, jclass clazz)
|
||||
{
|
||||
int i;
|
||||
|
||||
env->SetStaticIntField(clazz, fid_button_count, NUM_BUTTONS);
|
||||
env->SetStaticBooleanField(clazz, fid_has_wheel, JNI_TRUE);
|
||||
current_x = current_y = current_z = last_x = last_y = last_z = pointer_grabbed = 0;
|
||||
current_x = current_y = current_z = last_x = last_y = last_z;
|
||||
for (i = 0; i < NUM_BUTTONS; i++)
|
||||
buttons[i] = JNI_FALSE;
|
||||
if (!blankCursor()) {
|
||||
#ifdef _DEBUG
|
||||
printf("Could create blank cursor\n");
|
||||
printf("Could not create blank cursor\n");
|
||||
#endif
|
||||
return JNI_FALSE;
|
||||
}
|
||||
current_cursor = blank_cursor;
|
||||
native_cursor = false;
|
||||
created = true;
|
||||
should_grab = true;
|
||||
pointer_grabbed = false;
|
||||
updateGrab();
|
||||
loadXcursor();
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -190,60 +274,66 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate
|
|||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy
|
||||
(JNIEnv * env, jclass clazz)
|
||||
{
|
||||
if (pointer_grabbed)
|
||||
ungrabPointer();
|
||||
closeXcursor();
|
||||
ungrabPointer();
|
||||
XFreeCursor(getCurrentDisplay(), blank_cursor);
|
||||
created = false;
|
||||
should_grab = false;
|
||||
}
|
||||
|
||||
void handleButtonPress(XButtonEvent *event) {
|
||||
switch (event->button) {
|
||||
case Button1:
|
||||
buttons[0] = JNI_TRUE;
|
||||
break;
|
||||
case Button2:
|
||||
buttons[2] = JNI_TRUE;
|
||||
break;
|
||||
case Button3:
|
||||
buttons[1] = JNI_TRUE;
|
||||
break;
|
||||
case Button4:
|
||||
current_z += WHEEL_SCALE;
|
||||
break;
|
||||
case Button5:
|
||||
current_z -= WHEEL_SCALE;
|
||||
break;
|
||||
default: assert(0);
|
||||
if (pointer_grabbed || native_cursor) {
|
||||
switch (event->button) {
|
||||
case Button1:
|
||||
buttons[0] = JNI_TRUE;
|
||||
break;
|
||||
case Button2:
|
||||
buttons[2] = JNI_TRUE;
|
||||
break;
|
||||
case Button3:
|
||||
buttons[1] = JNI_TRUE;
|
||||
break;
|
||||
case Button4:
|
||||
current_z += WHEEL_SCALE;
|
||||
break;
|
||||
case Button5:
|
||||
current_z -= WHEEL_SCALE;
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleButtonRelease(XButtonEvent *event) {
|
||||
switch (event->button) {
|
||||
case Button1:
|
||||
buttons[0] = JNI_FALSE;
|
||||
break;
|
||||
case Button2:
|
||||
buttons[2] = JNI_FALSE;
|
||||
break;
|
||||
case Button3:
|
||||
buttons[1] = JNI_FALSE;
|
||||
break;
|
||||
case Button4: /* Fall through */
|
||||
case Button5:
|
||||
break;
|
||||
default: assert(0);
|
||||
if (pointer_grabbed || native_cursor) {
|
||||
switch (event->button) {
|
||||
case Button1:
|
||||
buttons[0] = JNI_FALSE;
|
||||
break;
|
||||
case Button2:
|
||||
buttons[2] = JNI_FALSE;
|
||||
break;
|
||||
case Button3:
|
||||
buttons[1] = JNI_FALSE;
|
||||
break;
|
||||
case Button4: /* Fall through */
|
||||
case Button5:
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handlePointerMotion(XMotionEvent *event) {
|
||||
current_x = event->x;
|
||||
current_y = event->y;
|
||||
if (pointer_grabbed || native_cursor) {
|
||||
current_x = event->x;
|
||||
current_y = event->y;
|
||||
}
|
||||
}
|
||||
|
||||
static void warpPointer(void) {
|
||||
int i;
|
||||
if (!pointer_grabbed)
|
||||
if (!pointer_grabbed || native_cursor)
|
||||
return;
|
||||
// Reset pointer to middle of screen if inside a certain inner border
|
||||
if (current_x < POINTER_WARP_BORDER || current_y < POINTER_WARP_BORDER ||
|
||||
|
|
@ -279,7 +369,6 @@ static void warpPointer(void) {
|
|||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll
|
||||
(JNIEnv * env, jclass clazz)
|
||||
{
|
||||
updateGrab();
|
||||
int moved_x = current_x - last_x;
|
||||
int moved_y = current_y - last_y;
|
||||
int moved_z = current_z - last_z;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
extern LPDIRECTINPUT lpdi; // DirectInput
|
||||
extern bool isFullScreen; // Whether we're fullscreen or not
|
||||
extern bool isMinimized; // Whether we're minimized or not
|
||||
extern RECT clientSize;
|
||||
#endif /* _PRIVATE_WINDOW_H_ */
|
||||
|
||||
/*
|
||||
|
|
@ -82,7 +83,6 @@
|
|||
*/
|
||||
WINDOW_H_API void closeWindow();
|
||||
|
||||
|
||||
/*
|
||||
* Utility function to throw an Exception
|
||||
*/
|
||||
|
|
@ -93,4 +93,4 @@
|
|||
*/
|
||||
WINDOW_H_API void throwRuntimeException(JNIEnv * env, const char * err);
|
||||
|
||||
#endif /* _LWJGL_WINDOW_H_INCLUDED_ */
|
||||
#endif /* _LWJGL_WINDOW_H_INCLUDED_ */
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ bool isMinimized = false; // Whether we're minimized or not
|
|||
JNIEnv * environment = NULL; // Cached environment
|
||||
jobject window; // Cached Java Window instance handle
|
||||
extern HINSTANCE dll_handle; // Handle to the LWJGL dll
|
||||
RECT clientSize;
|
||||
|
||||
#define WINDOWCLASSNAME "LWJGL"
|
||||
|
||||
|
|
@ -140,9 +141,7 @@ void closeWindow()
|
|||
}
|
||||
|
||||
// Show the mouse
|
||||
if (isFullScreen) {
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -153,8 +152,9 @@ void appActivate(bool active)
|
|||
if (active) {
|
||||
SetForegroundWindow(hwnd);
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
} else if (isFullScreen)
|
||||
} else if (isFullScreen) {
|
||||
ShowWindow(hwnd, SW_MINIMIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -239,7 +239,7 @@ bool registerWindow()
|
|||
windowClass.cbWndExtra = 0;
|
||||
windowClass.hInstance = dll_handle;
|
||||
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
windowClass.hCursor = NULL/*LoadCursor(NULL, IDC_ARROW)*/;
|
||||
windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
windowClass.lpszMenuName = NULL;
|
||||
windowClass.lpszClassName = WINDOWCLASSNAME;
|
||||
|
|
@ -283,7 +283,6 @@ bool createWindow(const char * title, int x, int y, int width, int height, bool
|
|||
|
||||
// If we're not a fullscreen window, adjust the height to account for the
|
||||
// height of the title bar:
|
||||
RECT clientSize;
|
||||
clientSize.bottom = height;
|
||||
clientSize.left = 0;
|
||||
clientSize.right = width;
|
||||
|
|
@ -296,16 +295,13 @@ bool createWindow(const char * title, int x, int y, int width, int height, bool
|
|||
exstyle // extended window style
|
||||
);
|
||||
|
||||
clientSize.bottom -= clientSize.top;
|
||||
clientSize.right -= clientSize.left;
|
||||
|
||||
// Create the window now, using that class:
|
||||
hwnd = CreateWindowEx (
|
||||
exstyle,
|
||||
WINDOWCLASSNAME,
|
||||
title,
|
||||
windowflags,
|
||||
x, y, clientSize.right, clientSize.bottom,
|
||||
x, y, clientSize.right - clientSize.left, clientSize.bottom - clientSize.top,
|
||||
NULL,
|
||||
NULL,
|
||||
dll_handle,
|
||||
|
|
@ -332,9 +328,7 @@ bool createWindow(const char * title, int x, int y, int width, int height, bool
|
|||
|
||||
// 3. Hide the mouse if necessary
|
||||
isFullScreen = fullscreen == JNI_TRUE;
|
||||
if (isFullScreen) {
|
||||
ShowCursor(FALSE);
|
||||
}
|
||||
ShowCursor(FALSE);
|
||||
|
||||
// 4. Create DirectInput
|
||||
if (!createDirectInput()) {
|
||||
|
|
|
|||
|
|
@ -51,45 +51,45 @@
|
|||
extern HINSTANCE dll_handle;
|
||||
extern HWND hwnd;
|
||||
|
||||
IDirectInput* cDI; // DI instance
|
||||
IDirectInputDevice2* cDIDevice; // DI Device instance
|
||||
DIJOYSTATE2 cJS; // State of Controller
|
||||
static IDirectInput* cDI; // DI instance
|
||||
static IDirectInputDevice2* cDIDevice; // DI Device instance
|
||||
static DIJOYSTATE2 cJS; // State of Controller
|
||||
|
||||
int cButtoncount = 0; // Temporary buttoncount
|
||||
bool cHasx; // Temporary xaxis check
|
||||
bool cHasrx; // Temporary rotational xaxis check
|
||||
bool cHasy; // Temporary yaxis check
|
||||
bool cHasry; // Temporary rotational yaxis check
|
||||
bool cHasz; // Temporary zaxis check
|
||||
bool cHasrz; // Temporary rotational zaxis check
|
||||
bool cHaspov; // Temporary pov check
|
||||
bool cHasslider; // Temporary slider check
|
||||
static int cButtoncount = 0; // Temporary buttoncount
|
||||
static bool cHasx; // Temporary xaxis check
|
||||
static bool cHasrx; // Temporary rotational xaxis check
|
||||
static bool cHasy; // Temporary yaxis check
|
||||
static bool cHasry; // Temporary rotational yaxis check
|
||||
static bool cHasz; // Temporary zaxis check
|
||||
static bool cHasrz; // Temporary rotational zaxis check
|
||||
static bool cHaspov; // Temporary pov check
|
||||
static bool cHasslider; // Temporary slider check
|
||||
|
||||
JNIEnv* cEnvironment; // JNIEnvironment copy
|
||||
static JNIEnv* cEnvironment; // JNIEnvironment copy
|
||||
|
||||
bool cCreate_success; // bool used to determine successfull creation
|
||||
bool cFirstTimeInitialization = true; // boolean to determine first time initialization
|
||||
static bool cCreate_success; // bool used to determine successfull creation
|
||||
static bool cFirstTimeInitialization = true; // boolean to determine first time initialization
|
||||
|
||||
// Cached fields of Controller.java
|
||||
jclass clsController;
|
||||
jfieldID fidCButtonCount;
|
||||
jfieldID fidCHasXAxis;
|
||||
jfieldID fidCHasRXAxis;
|
||||
jfieldID fidCHasYAxis;
|
||||
jfieldID fidCHasRYAxis;
|
||||
jfieldID fidCHasZAxis;
|
||||
jfieldID fidCHasRZAxis;
|
||||
jfieldID fidCHasPOV;
|
||||
jfieldID fidCHasSlider;
|
||||
jfieldID fidCButtons;
|
||||
jfieldID fidCX;
|
||||
jfieldID fidCRX;
|
||||
jfieldID fidCY;
|
||||
jfieldID fidCRY;
|
||||
jfieldID fidCZ;
|
||||
jfieldID fidCRZ;
|
||||
jfieldID fidCPOV;
|
||||
jfieldID fidCSlider;
|
||||
static jclass clsController;
|
||||
static jfieldID fidCButtonCount;
|
||||
static jfieldID fidCHasXAxis;
|
||||
static jfieldID fidCHasRXAxis;
|
||||
static jfieldID fidCHasYAxis;
|
||||
static jfieldID fidCHasRYAxis;
|
||||
static jfieldID fidCHasZAxis;
|
||||
static jfieldID fidCHasRZAxis;
|
||||
static jfieldID fidCHasPOV;
|
||||
static jfieldID fidCHasSlider;
|
||||
static jfieldID fidCButtons;
|
||||
static jfieldID fidCX;
|
||||
static jfieldID fidCRX;
|
||||
static jfieldID fidCY;
|
||||
static jfieldID fidCRY;
|
||||
static jfieldID fidCZ;
|
||||
static jfieldID fidCRZ;
|
||||
static jfieldID fidCPOV;
|
||||
static jfieldID fidCSlider;
|
||||
|
||||
// Function prototypes (defined in the cpp file, since header file is generic across platforms
|
||||
void EnumerateControllerCapabilities();
|
||||
|
|
|
|||
111
src/native/win32/org_lwjgl_input_Cursor.cpp
Executable file
111
src/native/win32/org_lwjgl_input_Cursor.cpp
Executable file
|
|
@ -0,0 +1,111 @@
|
|||
#include <windows.h>
|
||||
#include "org_lwjgl_input_Cursor.h"
|
||||
#include "Window.h"
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Cursor
|
||||
* Method: nCreateCursor
|
||||
* Signature: (IIIIIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor
|
||||
(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, jint image_address)
|
||||
{
|
||||
int *pixels = (int *)image_address;
|
||||
|
||||
BITMAPINFO bitmapInfo;
|
||||
|
||||
char *ptrCursorImage;
|
||||
HBITMAP colorDIB;
|
||||
HBITMAP colorBitmap;
|
||||
int x, y;
|
||||
|
||||
memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
|
||||
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.bmiHeader.biWidth = width;
|
||||
bitmapInfo.bmiHeader.biHeight = -height;
|
||||
bitmapInfo.bmiHeader.biPlanes = 1;
|
||||
|
||||
bitmapInfo.bmiHeader.biBitCount = 24;
|
||||
bitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
colorDIB = CreateDIBSection(hdc, (BITMAPINFO*)&(bitmapInfo),
|
||||
DIB_RGB_COLORS,
|
||||
(void**)&(ptrCursorImage),
|
||||
NULL, 0);
|
||||
int *srcPtr = pixels;
|
||||
char *dstPtr = ptrCursorImage;
|
||||
if (!dstPtr) {
|
||||
throwException(env, "Could not allocate DIB section.");
|
||||
return 0;
|
||||
}
|
||||
for (y = 0; y < height; y++ ) {
|
||||
for (x = 0; x < width; x++ ) {
|
||||
dstPtr[2] = (*srcPtr >> 0x10) & 0xFF;
|
||||
dstPtr[1] = (*srcPtr >> 0x08) & 0xFF;
|
||||
dstPtr[0] = *srcPtr & 0xFF;
|
||||
|
||||
srcPtr++;
|
||||
dstPtr += 3;
|
||||
}
|
||||
}
|
||||
|
||||
colorBitmap = CreateDIBitmap(hdc,
|
||||
(BITMAPINFOHEADER*)&bitmapInfo.bmiHeader,
|
||||
CBM_INIT,
|
||||
(void *)ptrCursorImage,
|
||||
(BITMAPINFO*)&bitmapInfo,
|
||||
DIB_RGB_COLORS);
|
||||
|
||||
DeleteObject(colorDIB);
|
||||
|
||||
// Convert alpha map to pixel packed mask
|
||||
int bitWidth = width >> 3;
|
||||
int scanlinePad = bitWidth & (sizeof(WORD) - 1);
|
||||
int imageSize = (bitWidth + scanlinePad)*height; // Size in bits
|
||||
unsigned char *maskPixels = new unsigned char[imageSize];
|
||||
memset(maskPixels, 0, imageSize);
|
||||
int pixelCount = 0;
|
||||
int maskCount = 0;
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < bitWidth; x++) {
|
||||
unsigned char col0 = (pixels[pixelCount++] & 0x01000000) >> 17;
|
||||
unsigned char col1 = (pixels[pixelCount++] & 0x01000000) >> 18;
|
||||
unsigned char col2 = (pixels[pixelCount++] & 0x01000000) >> 19;
|
||||
unsigned char col3 = (pixels[pixelCount++] & 0x01000000) >> 20;
|
||||
unsigned char col4 = (pixels[pixelCount++] & 0x01000000) >> 21;
|
||||
unsigned char col5 = (pixels[pixelCount++] & 0x01000000) >> 22;
|
||||
unsigned char col6 = (pixels[pixelCount++] & 0x01000000) >> 23;
|
||||
unsigned char col7 = (pixels[pixelCount++] & 0x01000000) >> 24;
|
||||
unsigned char mask = col0 | col1 | col2 | col3 | col4 | col5 | col6 | col7;
|
||||
maskPixels[maskCount++] = ~mask; // 1 is tranparant, 0 opaque
|
||||
}
|
||||
|
||||
HBITMAP cursorMask = CreateBitmap(width, height, 1, 1, maskPixels);
|
||||
|
||||
HCURSOR cursor = NULL;
|
||||
ICONINFO iconInfo;
|
||||
memset(&iconInfo, 0, sizeof(ICONINFO));
|
||||
iconInfo.hbmMask = cursorMask;
|
||||
iconInfo.hbmColor = colorBitmap;
|
||||
iconInfo.fIcon = FALSE;
|
||||
iconInfo.xHotspot = x_hotspot;
|
||||
iconInfo.yHotspot = y_hotspot;
|
||||
cursor = CreateIconIndirect(&iconInfo);
|
||||
DeleteObject(colorBitmap);
|
||||
DeleteObject(cursorMask);
|
||||
delete[] maskPixels;
|
||||
|
||||
return (jint)cursor;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Cursor
|
||||
* Method: nDestroyCursor
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Cursor_nDestroyCursor
|
||||
(JNIEnv *env, jclass clazz, jint cursor_handle)
|
||||
{
|
||||
HCURSOR cursor = (HCURSOR)cursor_handle;
|
||||
DestroyCursor(cursor);
|
||||
}
|
||||
|
|
@ -48,10 +48,11 @@
|
|||
#include "Window.h"
|
||||
|
||||
#define KEYBOARD_BUFFER_SIZE 50
|
||||
BYTE readBuffer[KEYBOARD_BUFFER_SIZE*4];
|
||||
LPDIRECTINPUTDEVICE lpdiKeyboard = NULL;
|
||||
jfieldID fid_readBuffer;
|
||||
bool translationEnabled;
|
||||
|
||||
static BYTE readBuffer[KEYBOARD_BUFFER_SIZE*4];
|
||||
static LPDIRECTINPUTDEVICE lpdiKeyboard = NULL;
|
||||
static jfieldID fid_readBuffer;
|
||||
static bool translationEnabled;
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -46,25 +46,26 @@
|
|||
#include "Window.h"
|
||||
#include <dinput.h>
|
||||
|
||||
extern HINSTANCE dll_handle;
|
||||
LPDIRECTINPUTDEVICE mDIDevice; // DI Device instance
|
||||
DIMOUSESTATE diMouseState; // State of Mouse
|
||||
static LPDIRECTINPUTDEVICE mDIDevice; // DI Device instance
|
||||
static int mButtoncount = 0; // Temporary buttoncount
|
||||
static bool mHaswheel; // Temporary wheel check
|
||||
static JNIEnv* mEnvironment; // JNIEnvironment copy
|
||||
|
||||
int mButtoncount = 0; // Temporary buttoncount
|
||||
bool mHaswheel; // Temporary wheel check
|
||||
JNIEnv* mEnvironment; // JNIEnvironment copy
|
||||
|
||||
bool mCreate_success; // bool used to determine successfull creation
|
||||
bool mFirstTimeInitialization = true; // boolean to determine first time initialization
|
||||
static bool mCreate_success; // bool used to determine successfull creation
|
||||
static bool mFirstTimeInitialization = true; // boolean to determine first time initialization
|
||||
|
||||
// Cached fields of Mouse.java
|
||||
jclass clsMouse;
|
||||
jfieldID fidMButtonCount;
|
||||
jfieldID fidMButtons;
|
||||
jfieldID fidMDX;
|
||||
jfieldID fidMDY;
|
||||
jfieldID fidMDWheel;
|
||||
jfieldID fidMHasWheel;
|
||||
static jclass clsMouse;
|
||||
static jfieldID fidMButtonCount;
|
||||
static jfieldID fidMButtons;
|
||||
static jfieldID fidMDX;
|
||||
static jfieldID fidMDY;
|
||||
static jfieldID fidMDWheel;
|
||||
static jfieldID fidMHasWheel;
|
||||
|
||||
static POINT cursorPos;
|
||||
static RECT windowRect;
|
||||
static bool usingNativeCursor;
|
||||
|
||||
// Function prototypes (defined in the cpp file, since header file is generic across platforms
|
||||
void EnumerateMouseCapabilities();
|
||||
|
|
@ -77,6 +78,16 @@ void CacheMouseFields();
|
|||
void UpdateMouseFields();
|
||||
void SetMouseCapabilities();
|
||||
|
||||
static void getScreenClientRect(RECT* clientRect, RECT* windowRect)
|
||||
{
|
||||
GetClientRect(hwnd, clientRect);
|
||||
// transform clientRect to screen coordinates
|
||||
clientRect->top = -clientSize.top + windowRect->top;
|
||||
clientRect->left = -clientSize.left + windowRect->left;
|
||||
clientRect->bottom += clientRect->top;
|
||||
clientRect->right += clientRect->left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes any field ids
|
||||
*/
|
||||
|
|
@ -92,51 +103,131 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_initIDs(JNIEnv * env, jclass c
|
|||
* Called when the Mouse instance is to be created
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate(JNIEnv *env, jclass clazz) {
|
||||
HRESULT hr;
|
||||
HRESULT hr;
|
||||
|
||||
mEnvironment = env;
|
||||
clsMouse = clazz;
|
||||
mEnvironment = env;
|
||||
clsMouse = clazz;
|
||||
|
||||
CacheMouseFields();
|
||||
CacheMouseFields();
|
||||
|
||||
/* skip enumeration, since we only want system mouse */
|
||||
CreateMouse();
|
||||
/* skip enumeration, since we only want system mouse */
|
||||
CreateMouse();
|
||||
|
||||
//check for first time initialization - need to detect capabilities
|
||||
if (mFirstTimeInitialization) {
|
||||
mFirstTimeInitialization = false;
|
||||
|
||||
/* Enumerate capabilities of Mouse */
|
||||
EnumerateMouseCapabilities();
|
||||
if (!mCreate_success) {
|
||||
#if _DEBUG
|
||||
printf("EnumerateMouseCapabilities failed\n");
|
||||
#endif
|
||||
ShutdownMouse();
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/* Do setup of Mouse */
|
||||
SetupMouse();
|
||||
|
||||
/* Set capabilities */
|
||||
SetMouseCapabilities();
|
||||
} else {
|
||||
if(mCreate_success) {
|
||||
/* Do setup of Mouse */
|
||||
SetupMouse();
|
||||
}
|
||||
}
|
||||
|
||||
/* Aquire the Mouse */
|
||||
hr = mDIDevice->Acquire();
|
||||
if(FAILED(hr)) {
|
||||
//check for first time initialization - need to detect capabilities
|
||||
if (mFirstTimeInitialization) {
|
||||
mFirstTimeInitialization = false;
|
||||
/* Enumerate capabilities of Mouse */
|
||||
EnumerateMouseCapabilities();
|
||||
if (!mCreate_success) {
|
||||
#if _DEBUG
|
||||
printf("Failed to acquire mouse\n");
|
||||
printf("EnumerateMouseCapabilities failed\n");
|
||||
#endif
|
||||
}
|
||||
ShutdownMouse();
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/* Do setup of Mouse */
|
||||
SetupMouse();
|
||||
|
||||
return mCreate_success ? JNI_TRUE : JNI_FALSE;
|
||||
/* Set capabilities */
|
||||
SetMouseCapabilities();
|
||||
} else {
|
||||
if(mCreate_success) {
|
||||
/* Do setup of Mouse */
|
||||
SetupMouse();
|
||||
}
|
||||
}
|
||||
/* Aquire the Mouse */
|
||||
hr = mDIDevice->Acquire();
|
||||
if(FAILED(hr)) {
|
||||
#if _DEBUG
|
||||
printf("Failed to acquire mouse\n");
|
||||
#endif
|
||||
}
|
||||
return mCreate_success ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nIsNativeCursorSupported
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nIsNativeCursorSupported
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nSetNativeCursor
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nSetNativeCursor
|
||||
(JNIEnv *env, jclass clazz, jint cursor_handle)
|
||||
{
|
||||
if (cursor_handle != NULL) {
|
||||
if (mDIDevice == NULL)
|
||||
throwException(env, "null device!");
|
||||
mDIDevice->Unacquire();
|
||||
if(mDIDevice->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK) {
|
||||
#if _DEBUG
|
||||
printf("SetCooperativeLevel failed\n");
|
||||
#endif
|
||||
throwException(env, "Could not set the CooperativeLevel.");
|
||||
return;
|
||||
}
|
||||
HCURSOR cursor = (HCURSOR)cursor_handle;
|
||||
SetClassLong(hwnd, GCL_HCURSOR, (LONG)cursor);
|
||||
SetCursor(cursor);
|
||||
if (!usingNativeCursor) {
|
||||
/* Reset cursor position to 0, 0 */
|
||||
RECT clientRect;
|
||||
GetWindowRect(hwnd, &windowRect);
|
||||
getScreenClientRect(&clientRect, &windowRect);
|
||||
SetCursorPos(clientRect.left, clientRect.top);
|
||||
cursorPos.x = clientRect.left;
|
||||
cursorPos.y = clientRect.top;
|
||||
while (ShowCursor(TRUE) < 0)
|
||||
;
|
||||
usingNativeCursor = true;
|
||||
}
|
||||
} else {
|
||||
while (ShowCursor(FALSE) >= 0)
|
||||
;
|
||||
SetClassLong(hwnd, GCL_HCURSOR, (LONG)NULL);
|
||||
SetCursor(NULL);
|
||||
mDIDevice->Unacquire();
|
||||
if(mDIDevice->SetCooperativeLevel(hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND) != DI_OK) {
|
||||
#if _DEBUG
|
||||
printf("SetCooperativeLevel failed\n");
|
||||
#endif
|
||||
throwException(env, "Could not set the CooperativeLevel.");
|
||||
return;
|
||||
}
|
||||
usingNativeCursor = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGetMaxCursorSize
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMaxCursorSize
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
return GetSystemMetrics(SM_CXCURSOR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGetMaxCursorSize
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMinCursorSize
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
return GetSystemMetrics(SM_CXCURSOR);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -177,25 +268,25 @@ void ShutdownMouse() {
|
|||
* Enumerates the capabilities of the Mouse attached to the system
|
||||
*/
|
||||
void EnumerateMouseCapabilities() {
|
||||
HRESULT hr;
|
||||
hr = mDIDevice->EnumObjects(EnumMouseObjectsCallback, NULL, DIDFT_ALL);
|
||||
if FAILED(hr) {
|
||||
HRESULT hr;
|
||||
hr = mDIDevice->EnumObjects(EnumMouseObjectsCallback, NULL, DIDFT_ALL);
|
||||
if FAILED(hr) {
|
||||
#if _DEBUG
|
||||
printf("EnumObjects failed\n");
|
||||
printf("EnumObjects failed\n");
|
||||
#endif
|
||||
mCreate_success = false;
|
||||
return;
|
||||
}
|
||||
mCreate_success = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//check for > 4 buttons - need to clamp since we're using dx 5
|
||||
if(mButtoncount > 4) {
|
||||
mButtoncount = 4;
|
||||
//check for > 4 buttons - need to clamp since we're using dx 5
|
||||
if(mButtoncount > 4) {
|
||||
mButtoncount = 4;
|
||||
#ifdef _DEBUG
|
||||
printf("WARNING: Clamping to 4 mouse buttons");
|
||||
printf("WARNING: Clamping to 4 mouse buttons\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
mCreate_success = true;
|
||||
mCreate_success = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -259,46 +350,80 @@ void SetupMouse() {
|
|||
mCreate_success = true;
|
||||
}
|
||||
|
||||
static void getGDICursorDelta(int* return_dx, int* return_dy) {
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
|
||||
POINT newCursorPos;
|
||||
GetCursorPos(&newCursorPos);
|
||||
RECT clientRect;
|
||||
RECT newWindowRect;
|
||||
GetWindowRect(hwnd, &newWindowRect);
|
||||
cursorPos.x += newWindowRect.left - windowRect.left;
|
||||
cursorPos.y += newWindowRect.top - windowRect.top;
|
||||
windowRect = newWindowRect;
|
||||
getScreenClientRect(&clientRect, &windowRect);
|
||||
// Clip the position to the client rect
|
||||
if (newCursorPos.x < clientRect.right && newCursorPos.x >= clientRect.left &&
|
||||
newCursorPos.y < clientRect.bottom && newCursorPos.y >= clientRect.top) {
|
||||
dx = newCursorPos.x - cursorPos.x;
|
||||
dy = newCursorPos.y - cursorPos.y;
|
||||
cursorPos.x += dx;
|
||||
cursorPos.y += dy;
|
||||
}
|
||||
*return_dx = dx;
|
||||
*return_dy = dy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the fields on the Mouse
|
||||
*/
|
||||
void UpdateMouseFields() {
|
||||
HRESULT hRes;
|
||||
HRESULT hRes;
|
||||
DIMOUSESTATE diMouseState; // State of Mouse
|
||||
int dx, dy;
|
||||
|
||||
// get data from the Mouse
|
||||
hRes = mDIDevice->GetDeviceState(sizeof(DIMOUSESTATE), &diMouseState);
|
||||
if (hRes != DI_OK) {
|
||||
// Don't allow the mouse to drift when failed
|
||||
diMouseState.lX = 0;
|
||||
diMouseState.lY = 0;
|
||||
diMouseState.lZ = 0;
|
||||
// did the read fail because we lost input for some reason?
|
||||
// if so, then attempt to reacquire.
|
||||
if(hRes == DIERR_INPUTLOST || hRes == DIERR_NOTACQUIRED) {
|
||||
mDIDevice->Acquire();
|
||||
// get data from the Mouse
|
||||
hRes = mDIDevice->GetDeviceState(sizeof(DIMOUSESTATE), &diMouseState);
|
||||
if (hRes != DI_OK) {
|
||||
// Don't allow the mouse to drift when failed
|
||||
diMouseState.lX = 0;
|
||||
diMouseState.lY = 0;
|
||||
diMouseState.lZ = 0;
|
||||
// did the read fail because we lost input for some reason?
|
||||
// if so, then attempt to reacquire.
|
||||
if(hRes == DIERR_INPUTLOST || hRes == DIERR_NOTACQUIRED) {
|
||||
mDIDevice->Acquire();
|
||||
#if _DEBUG
|
||||
printf("DIERR_INPUTLOST, reaquiring input : mCreate_success=%d\n", mCreate_success);
|
||||
printf("DIERR_INPUTLOST, reaquiring input : mCreate_success=%d\n", mCreate_success);
|
||||
#endif
|
||||
} else {
|
||||
} else {
|
||||
#if _DEBUG
|
||||
printf("Error getting mouse state: %d\n", hRes);
|
||||
printf("Error getting mouse state: %d\n", hRes);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mEnvironment->SetStaticIntField(clsMouse, fidMDX, (jint) diMouseState.lX);
|
||||
mEnvironment->SetStaticIntField(clsMouse, fidMDY, (jint) diMouseState.lY);
|
||||
mEnvironment->SetStaticIntField(clsMouse, fidMDWheel, (jint) diMouseState.lZ);
|
||||
if (usingNativeCursor) {
|
||||
getGDICursorDelta(&dx, &dy);
|
||||
} else {
|
||||
dx = diMouseState.lX;
|
||||
dy = diMouseState.lY;
|
||||
}
|
||||
|
||||
mEnvironment->SetStaticIntField(clsMouse, fidMDX, (jint)dx);
|
||||
mEnvironment->SetStaticIntField(clsMouse, fidMDY, (jint)dy);
|
||||
mEnvironment->SetStaticIntField(clsMouse, fidMDWheel, (jint)diMouseState.lZ);
|
||||
|
||||
for (int i = 0; i < mButtoncount; i++) {
|
||||
if (diMouseState.rgbButtons[i] != 0) {
|
||||
diMouseState.rgbButtons[i] = JNI_TRUE;
|
||||
} else {
|
||||
diMouseState.rgbButtons[i] = JNI_FALSE;
|
||||
}
|
||||
}
|
||||
jbooleanArray mButtonsArray = (jbooleanArray) mEnvironment->GetStaticObjectField(clsMouse, fidMButtons);
|
||||
mEnvironment->SetBooleanArrayRegion(mButtonsArray, 0, mButtoncount, diMouseState.rgbButtons);
|
||||
for (int i = 0; i < mButtoncount; i++) {
|
||||
if (diMouseState.rgbButtons[i] != 0) {
|
||||
diMouseState.rgbButtons[i] = JNI_TRUE;
|
||||
} else {
|
||||
diMouseState.rgbButtons[i] = JNI_FALSE;
|
||||
}
|
||||
}
|
||||
jbooleanArray mButtonsArray = (jbooleanArray) mEnvironment->GetStaticObjectField(clsMouse, fidMButtons);
|
||||
mEnvironment->SetBooleanArrayRegion(mButtonsArray, 0, mButtoncount, diMouseState.rgbButtons);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue