reworked animated native cursors, to use X animation when required
added initial setGrabbed(boolean) feature - Work in progress both needs verification on linux
This commit is contained in:
parent
438e790987
commit
86eb042b81
|
@ -36,6 +36,7 @@ import java.nio.ByteBuffer;
|
|||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.Display;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.LWJGLException;
|
||||
|
||||
|
@ -100,22 +101,39 @@ public class Cursor {
|
|||
IntBuffer images_copy = ByteBuffer.allocateDirect(images.remaining()*4).order(ByteOrder.nativeOrder()).asIntBuffer();
|
||||
flipImages(width, height, numImages, images, images_copy);
|
||||
|
||||
// Win32 doesn't (afaik) allow for animation based cursors, except when they're
|
||||
// in the .ani format, which we don't support.
|
||||
// The cursor animation was therefor developed using java side time tracking.
|
||||
// unfortunately X flickers when changing cursor. We therefor check for either
|
||||
// Win32 or X and do accordingly. This hasn't been implemented on Mac, but we
|
||||
// might want to split it into a X/Win/Mac cursor if it gets too cluttered
|
||||
|
||||
switch(Display.getPlatform()) {
|
||||
case Display.PLATFORM_GLX:
|
||||
// create our cursor elements
|
||||
cursors = new CursorElement[1];
|
||||
cursors[0] = new CursorElement();
|
||||
cursors[0].cursorHandle = nCreateCursor(width, height, xHotspot, yHotspot, numImages, images_copy, images_copy.position(), delays, delays.position());
|
||||
break;
|
||||
case Display.PLATFORM_WGL:
|
||||
// create our cursor elements
|
||||
cursors = new CursorElement[numImages];
|
||||
for(int i=0; i<numImages; i++) {
|
||||
cursors[i] = new CursorElement();
|
||||
cursors[i].cursorHandle = nCreateCursor(width, height, xHotspot, yHotspot, 1, images_copy, images_copy.position());
|
||||
cursors[i].cursorHandle = nCreateCursor(width, height, xHotspot, yHotspot, 1, images_copy, images_copy.position(), null, 0);
|
||||
cursors[i].delay = (delays != null) ? delays.get(i) : 0;
|
||||
cursors[i].timeout = System.currentTimeMillis();
|
||||
|
||||
// offset to next image
|
||||
images_copy.position(width*height*(i+1));
|
||||
}
|
||||
|
||||
// set index
|
||||
index = 0;
|
||||
break;
|
||||
case Display.PLATFORM_AGL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Flips the images so they're oriented according to opengl
|
||||
|
@ -202,7 +220,7 @@ public class Cursor {
|
|||
/**
|
||||
* Native method to create a native cursor
|
||||
*/
|
||||
private static native long nCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset);
|
||||
private static native long nCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset);
|
||||
|
||||
/**
|
||||
* Native method to destroy a native cursor
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.Display;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.opengl.Window;
|
||||
import org.lwjgl.LWJGLException;
|
||||
|
@ -123,6 +124,8 @@ public class Mouse {
|
|||
/** Buffer size in events */
|
||||
private final static int BUFFER_SIZE = 50;
|
||||
|
||||
private static boolean isGrabbed;
|
||||
|
||||
/**
|
||||
* Mouse cannot be constructed.
|
||||
*/
|
||||
|
@ -172,8 +175,7 @@ public class Mouse {
|
|||
* @throws LWJGLException if the cursor could not be set for any reason
|
||||
*/
|
||||
public static Cursor setNativeCursor(Cursor cursor) throws LWJGLException {
|
||||
if (!created)
|
||||
throw new IllegalStateException("Create the Mouse before setting the native cursor");
|
||||
if (!created) throw new IllegalStateException("Create the Mouse before setting the native cursor");
|
||||
if ((getNativeCursorCaps() & CURSOR_ONE_BIT_TRANSPARENCY) == 0)
|
||||
throw new IllegalStateException("Mouse doesn't support native cursors");
|
||||
Cursor oldCursor = currentCursor;
|
||||
|
@ -183,6 +185,7 @@ public class Mouse {
|
|||
currentCursor.setTimeout();
|
||||
x = Window.getWidth() / 2;
|
||||
y = Window.getHeight() / 2;
|
||||
isGrabbed = false;
|
||||
} else {
|
||||
nSetNativeCursor(0);
|
||||
}
|
||||
|
@ -243,13 +246,10 @@ public class Mouse {
|
|||
*/
|
||||
public static void create() throws LWJGLException {
|
||||
|
||||
if (!Window.isCreated())
|
||||
throw new IllegalStateException("Window must be created prior to creating mouse");
|
||||
if (!Window.isCreated()) throw new IllegalStateException("Window must be created prior to creating mouse");
|
||||
|
||||
initialize();
|
||||
if (created) {
|
||||
return;
|
||||
}
|
||||
if (created) { return; }
|
||||
nCreate();
|
||||
hasWheel = nHasWheel();
|
||||
created = true;
|
||||
|
@ -297,12 +297,10 @@ public class Mouse {
|
|||
try {
|
||||
setNativeCursor(null);
|
||||
} catch (LWJGLException e) {
|
||||
if (Sys.DEBUG)
|
||||
e.printStackTrace();
|
||||
if (Sys.DEBUG) e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!created)
|
||||
return;
|
||||
if (!created) return;
|
||||
created = false;
|
||||
buttons = null;
|
||||
coord_buffer = null;
|
||||
|
@ -341,8 +339,7 @@ public class Mouse {
|
|||
* @see org.lwjgl.input.Mouse#enableBuffer()
|
||||
*/
|
||||
public static void poll() {
|
||||
if (!created)
|
||||
throw new IllegalStateException("Mouse must be created before you can poll it");
|
||||
if (!created) throw new IllegalStateException("Mouse must be created before you can poll it");
|
||||
nPoll(coord_buffer, buttons);
|
||||
|
||||
int poll_dx = coord_buffer.get(0);
|
||||
|
@ -370,8 +367,7 @@ public class Mouse {
|
|||
y = Window.getHeight();
|
||||
}
|
||||
}
|
||||
if (readBuffer != null)
|
||||
read();
|
||||
if (readBuffer != null) read();
|
||||
}
|
||||
|
||||
private static void read() {
|
||||
|
@ -393,8 +389,7 @@ public class Mouse {
|
|||
* @return true if the specified button is down
|
||||
*/
|
||||
public static boolean isButtonDown(int button) {
|
||||
if (!created)
|
||||
throw new IllegalStateException("Mouse must be created before you can poll the button state");
|
||||
if (!created) throw new IllegalStateException("Mouse must be created before you can poll the button state");
|
||||
if (button >= buttonCount || button < 0)
|
||||
return false;
|
||||
else
|
||||
|
@ -429,8 +424,7 @@ public class Mouse {
|
|||
* Enable mouse button buffering. Must be called after the mouse is created.
|
||||
*/
|
||||
public static void enableBuffer() throws LWJGLException {
|
||||
if (!created)
|
||||
throw new IllegalStateException("Mouse must be created before you can enable buffering");
|
||||
if (!created) throw new IllegalStateException("Mouse must be created before you can enable buffering");
|
||||
readBuffer = BufferUtils.createByteBuffer(2 * BUFFER_SIZE);
|
||||
readBuffer.limit(0);
|
||||
nEnableBuffer();
|
||||
|
@ -458,8 +452,7 @@ public class Mouse {
|
|||
* @return true if a mouse event was read, false otherwise
|
||||
*/
|
||||
public static boolean next() {
|
||||
if (!created)
|
||||
throw new IllegalStateException("Mouse must be created before you can read events");
|
||||
if (!created) throw new IllegalStateException("Mouse must be created before you can read events");
|
||||
if (readBuffer == null)
|
||||
throw new IllegalStateException("Event buffering must be enabled before you can read events");
|
||||
|
||||
|
@ -540,18 +533,34 @@ public class Mouse {
|
|||
return hasWheel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether or not the mouse has grabbed the cursor
|
||||
*/
|
||||
public static boolean isGrabbed() {
|
||||
return isGrabbed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the mouse has grabbed the cursor
|
||||
* (and thus hidden).
|
||||
*/
|
||||
public static void setGrabbed(boolean grab) {
|
||||
isGrabbed = grab;
|
||||
nGrabMouse(isGrabbed);
|
||||
}
|
||||
private static native void nGrabMouse(boolean grab);
|
||||
|
||||
/**
|
||||
* Updates the cursor, so that animation can be changed if needed.
|
||||
* This method is called automatically by the window on its update.
|
||||
*/
|
||||
public static void updateCursor() {
|
||||
if(currentCursor != null && currentCursor.hasTimedOut()) {
|
||||
if (Display.getPlatform() == Display.PLATFORM_WGL && currentCursor != null && currentCursor.hasTimedOut()) {
|
||||
currentCursor.nextCursor();
|
||||
try {
|
||||
setNativeCursor(currentCursor);
|
||||
} catch (LWJGLException e) {
|
||||
if (Sys.DEBUG)
|
||||
e.printStackTrace();
|
||||
if (Sys.DEBUG) e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -346,6 +346,11 @@ public class HWCursorTest {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
|
||||
Mouse.setGrabbed(!Mouse.isGrabbed());
|
||||
System.out.println("Grabbed: " + Mouse.isGrabbed());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -242,6 +242,7 @@ public class MouseTest {
|
|||
if (Mouse.getDX() == Mouse.getDY() && Mouse.getDX() == 0 && Mouse.getDWheel() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// determine direction moved
|
||||
// ============================
|
||||
if(Mouse.getDX() > 0) {
|
||||
|
@ -259,8 +260,8 @@ public class MouseTest {
|
|||
if(Mouse.getDY() < 0) {
|
||||
direction = 2;
|
||||
}
|
||||
// ----------------------------
|
||||
|
||||
// ----------------------------
|
||||
if(direction > -1) {
|
||||
|
||||
// based on which button was last pushed, update model
|
||||
|
@ -316,6 +317,10 @@ public class MouseTest {
|
|||
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
|
||||
closing = true;
|
||||
}
|
||||
|
||||
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
|
||||
Mouse.setGrabbed(!Mouse.isGrabbed());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,7 +16,7 @@ extern "C" {
|
|||
* Signature: (IIIIILjava/nio/IntBuffer;I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor
|
||||
(JNIEnv *, jclass, jint, jint, jint, jint, jint, jobject, jint);
|
||||
(JNIEnv *, jclass, jint, jint, jint, jint, jint, jobject, jint, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Cursor
|
||||
|
|
|
@ -104,6 +104,14 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy
|
|||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll
|
||||
(JNIEnv *, jclass, jobject, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGrabMouse
|
||||
* Signature: (Z)Z
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nGrabMouse
|
||||
(JNIEnv * env, jclass clazz, jboolean grab);
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nEnableBuffer
|
||||
|
|
|
@ -50,11 +50,14 @@
|
|||
* Signature: (IIIIIII)I
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor
|
||||
(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset)
|
||||
(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset, jobject delay_buffer, jint delays_offset)
|
||||
{
|
||||
Display *disp = incDisplay(env);
|
||||
if (disp == NULL)
|
||||
return 0;
|
||||
const int *delays = NULL;
|
||||
if (delay_buffer != NULL)
|
||||
delays = (const int *)env->GetDirectBufferAddress(delay_buffer) + delays_offset;
|
||||
XcursorPixel *pixels = (XcursorPixel *)env->GetDirectBufferAddress(image_buffer) + images_offset;
|
||||
int stride = width*height;
|
||||
XcursorImages *cursor_images = XcursorImagesCreate(num_images);
|
||||
|
@ -66,6 +69,8 @@ JNIEXPORT jlong JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor
|
|||
cursor_image->xhot = x_hotspot;
|
||||
cursor_image->yhot = y_hotspot;
|
||||
cursor_image->pixels = &(pixels[stride*i]);
|
||||
if (num_images > 1)
|
||||
cursor_image->delay = delays[i];
|
||||
cursor_images->images[i] = cursor_image;
|
||||
}
|
||||
Cursor cursor = XcursorImagesLoadCursor(disp, cursor_images);
|
||||
|
|
|
@ -399,3 +399,17 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nRead(JNIEnv *env, jclass claz
|
|||
int buffer_size = env->GetDirectBufferCapacity(buffer) - buffer_position;
|
||||
return copyEvents(&event_queue, buffer_ptr + buffer_position, buffer_size, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGrabMouse
|
||||
* Signature: (Z)Z
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nGrabMouse
|
||||
(JNIEnv * env, jclass clazz, jboolean grab) {
|
||||
if(native_cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do it?
|
||||
}
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "org_lwjgl_input_Cursor.h"
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset) {
|
||||
JNIEXPORT jlong JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset, jobject delay_buffer, jint delays_offset) {
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Cursor_nDestroyCursor(JNIEnv *env, jclass clazz, jlong cursor_handle) {
|
||||
|
|
|
@ -257,3 +257,13 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nRead(JNIEnv *env, jclass claz
|
|||
int buffer_size = env->GetDirectBufferCapacity(buffer) - buffer_position;
|
||||
return copyEvents(&event_queue, buffer_ptr + buffer_position, buffer_size, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGrabMouse
|
||||
* Signature: (Z)Z
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nGrabMouse
|
||||
(JNIEnv * env, jclass clazz, jboolean grab) {
|
||||
// do it?
|
||||
}
|
|
@ -50,7 +50,7 @@
|
|||
* Signature: (IIIIIIIII)I
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_org_lwjgl_input_Cursor_nCreateCursor
|
||||
(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset)
|
||||
(JNIEnv *env, jclass clazz, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset, jobject delay_buffer, jint delays_offset)
|
||||
{
|
||||
int *pixels = (int *)env->GetDirectBufferAddress(image_buffer) + images_offset;
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ static bool mFirstTimeInitialization = true; // boolean to determine first time
|
|||
static POINT cursorPos;
|
||||
static RECT windowRect;
|
||||
static bool usingNativeCursor;
|
||||
static int mouseMask = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
|
||||
|
||||
// Function prototypes (defined in the cpp file, since header file is generic across platforms
|
||||
void EnumerateMouseCapabilities();
|
||||
|
@ -97,8 +98,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nCreate(JNIEnv *env, jclass cl
|
|||
return;
|
||||
}
|
||||
|
||||
ShowCursor(FALSE);
|
||||
|
||||
/* skip enumeration, since we only want system mouse */
|
||||
CreateMouse();
|
||||
|
||||
|
@ -240,19 +239,18 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nSetNativeCursor
|
|||
cursorPos.x = (clientRect.left + clientRect.right)/2;
|
||||
cursorPos.y = clientRect.bottom - 1 - (clientRect.bottom - clientRect.top)/2;
|
||||
SetCursorPos(cursorPos.x, cursorPos.y);
|
||||
ShowCursor(TRUE);
|
||||
usingNativeCursor = true;
|
||||
}
|
||||
} else {
|
||||
if (usingNativeCursor) {
|
||||
SetClassLong(hwnd, GCL_HCURSOR, (LONG)NULL);
|
||||
SetCursor(NULL);
|
||||
ShowCursor(TRUE);
|
||||
mDIDevice->Unacquire();
|
||||
if(mDIDevice->SetCooperativeLevel(hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND) != DI_OK) {
|
||||
if(mDIDevice->SetCooperativeLevel(hwnd, mouseMask) != DI_OK) {
|
||||
throwException(env, "Could not set the CooperativeLevel.");
|
||||
return;
|
||||
}
|
||||
ShowCursor(FALSE);
|
||||
usingNativeCursor = false;
|
||||
mDIDevice->Acquire();
|
||||
}
|
||||
|
@ -287,12 +285,11 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMinCursorSize
|
|||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy(JNIEnv *env, jclass clazz) {
|
||||
ShowCursor(TRUE);
|
||||
ShutdownMouse();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Controller
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nPoll
|
||||
* Signature: ()V
|
||||
*/
|
||||
|
@ -301,6 +298,30 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll(JNIEnv * env, jclass cla
|
|||
UpdateMouseFields(env, clazz, coord_buffer_obj, button_buffer_obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_lwjgl_input_Mouse
|
||||
* Method: nGrabMouse
|
||||
* Signature: (Z)Z
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nGrabMouse
|
||||
(JNIEnv * env, jclass clazz, jboolean grab) {
|
||||
if(usingNativeCursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(grab) {
|
||||
mouseMask = DISCL_EXCLUSIVE | DISCL_FOREGROUND;
|
||||
} else {
|
||||
mouseMask = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
|
||||
}
|
||||
mDIDevice->Unacquire();
|
||||
if(mDIDevice->SetCooperativeLevel(hwnd, mouseMask) != DI_OK) {
|
||||
throwException(env, "Could not set the CooperativeLevel.");
|
||||
return;
|
||||
}
|
||||
mDIDevice->Acquire();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown DI
|
||||
*/
|
||||
|
@ -384,7 +405,7 @@ void SetupMouse() {
|
|||
mDIDevice->SetProperty(DIPROP_BUFFERSIZE, &dipropdw.diph);
|
||||
|
||||
// set the cooperative level
|
||||
if(mDIDevice->SetCooperativeLevel(hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND) != DI_OK) {
|
||||
if(mDIDevice->SetCooperativeLevel(hwnd, mouseMask) != DI_OK) {
|
||||
printfDebug("SetCooperativeLevel failed\n");
|
||||
mCreate_success = false;
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue