Moved native cursor origin to middle of the window

This commit is contained in:
Elias Naur 2003-10-11 11:03:06 +00:00
parent 9c427cd029
commit 43b2d67a71
3 changed files with 68 additions and 70 deletions

View File

@ -125,8 +125,9 @@ public class Mouse {
*
* 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
* The initial position of the cursor is the middle of the window,
* that is, {window_width/2, window_height/2}.
* 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.

View File

@ -45,6 +45,7 @@
#include <X11/extensions/xf86vmode.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <Window.h>
#include "org_lwjgl_input_Mouse.h"
#include "extxcursor.h"
@ -87,11 +88,19 @@ static int cap(int val, int min, int max) {
}
static void setCursorPos(int x, int y) {
y = getWindowHeight() - 1 - y;
current_x = cap(x, 0, getWindowWidth() - 1);
current_y = cap(y, 0, getWindowHeight() - 1);
}
static void centerCursor() {
// transform to OpenGL coordinate system center
int x = getWindowWidth()/2;
int y = (int)ceil(getWindowHeight()/2.0f);
setCursorPos(x, y);
last_x = current_x;
last_y = current_y;
}
/*
* Class: org_lwjgl_input_Mouse
* Method: initIDs
@ -179,6 +188,37 @@ void releasePointer(void) {
updateGrab();
}
static void doWarpPointer(void ) {
centerCursor();
XWarpPointer(getCurrentDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, current_x, current_y);
XEvent event;
// Try to catch the warp pointer event
for (int i = 0; i < WARP_RETRY; i++) {
XMaskEvent(getCurrentDisplay(), PointerMotionMask, &event);
if (event.xmotion.x > current_x - POINTER_WARP_BORDER &&
event.xmotion.x < current_x + POINTER_WARP_BORDER &&
event.xmotion.y > current_y - POINTER_WARP_BORDER &&
event.xmotion.y < current_y + POINTER_WARP_BORDER)
break;
#ifdef _DEBUG
printf("Skipped event searching for warp event %d, %d\n", event.xmotion.x, event.xmotion.y);
#endif
}
#ifdef _DEBUG
if (i == WARP_RETRY)
printf("Never got warp event\n");
#endif
}
static void warpPointer(void) {
if (!pointer_grabbed || native_cursor)
return;
// Reset pointer to middle of screen if outside a certain inner border
if (current_x < POINTER_WARP_BORDER || current_y < POINTER_WARP_BORDER ||
current_x > getWindowWidth() - POINTER_WARP_BORDER || current_y > getWindowHeight() - POINTER_WARP_BORDER)
doWarpPointer();
}
/*
* Class: org_lwjgl_input_Mouse
* Method: nIsNativeCursorSupported
@ -209,8 +249,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nSetNativeCursor
if (cursor_handle != 0) {
Cursor cursor = (Cursor)cursor_handle;
if (!native_cursor) {
setCursorPos(0, 0);
XWarpPointer(getCurrentDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, current_x, current_y);
doWarpPointer();
native_cursor = true;
}
XDefineCursor(getCurrentDisplay(), getCurrentWindow(), cursor);
@ -271,8 +310,8 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nCreate
(JNIEnv * env, jclass clazz)
{
int i;
setCursorPos(0, 0);
current_z = last_x = last_y = last_z = 0;
centerCursor();
current_z = last_z = 0;
for (i = 0; i < NUM_BUTTONS; i++)
buttons[i] = JNI_FALSE;
if (!blankCursor()) {
@ -351,37 +390,6 @@ void handlePointerMotion(XMotionEvent *event) {
setCursorPos(event->x, event->y);
}
static void warpPointer(void) {
int i;
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 ||
current_x > getWindowWidth() - POINTER_WARP_BORDER || current_y > getWindowHeight() - POINTER_WARP_BORDER) {
setCursorPos(getWindowWidth()>>1, getWindowHeight()>>1);
last_x = current_x;
last_y = current_y;
XWarpPointer(getCurrentDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, current_x, current_y);
XEvent event;
// Try to catch the warp pointer event
for (i = 0; i < WARP_RETRY; i++) {
XMaskEvent(getCurrentDisplay(), PointerMotionMask, &event);
if (event.xmotion.x > current_x - POINTER_WARP_BORDER &&
event.xmotion.x < current_x + POINTER_WARP_BORDER &&
event.xmotion.y > current_y - POINTER_WARP_BORDER &&
event.xmotion.y < current_y + POINTER_WARP_BORDER)
break;
#ifdef _DEBUG
printf("Skipped event searching for warp event %d, %d\n", event.xmotion.x, event.xmotion.y);
#endif
}
#ifdef _DEBUG
if (i == WARP_RETRY)
printf("Never got warp event\n");
#endif
}
}
/*
* Class: org_lwjgl_input_Mouse
* Method: nPoll
@ -394,7 +402,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll
int moved_y = current_y - last_y;
int moved_z = current_z - last_z;
env->SetStaticIntField(clazz, fid_dx, (jint)moved_x);
env->SetStaticIntField(clazz, fid_dy, (jint)moved_y);
env->SetStaticIntField(clazz, fid_dy, (jint)-moved_y);
env->SetStaticIntField(clazz, fid_dwheel, (jint)moved_z);
last_x = current_x;
last_y = current_y;

View File

@ -41,6 +41,7 @@
#define WIN32_LEAN_AND_MEAN
#include "org_lwjgl_input_Mouse.h"
#include <windows.h>
#include <math.h>
#undef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x0300
#include "Window.h"
@ -49,13 +50,11 @@
static LPDIRECTINPUTDEVICE mDIDevice; // DI Device instance
static int mButtoncount = 0; // Temporary buttoncount
static bool mHaswheel; // Temporary wheel check
static JNIEnv* mEnvironment; // JNIEnvironment copy
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
static jclass clsMouse;
static jfieldID fidMButtons;
static jfieldID fidMDX;
static jfieldID fidMDY;
@ -72,8 +71,8 @@ void ShutdownMouse();
void CreateMouse();
void SetupMouse();
void InitializeMouseFields();
void CacheMouseFields();
void UpdateMouseFields();
void CacheMouseFields(JNIEnv *env, jclass clsMouse);
void UpdateMouseFields(JNIEnv *env, jclass clsMouse);
static void getScreenClientRect(RECT* clientRect, RECT* windowRect)
{
@ -89,11 +88,8 @@ static void getScreenClientRect(RECT* clientRect, RECT* windowRect)
* Initializes any field ids
*/
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_initIDs(JNIEnv * env, jclass clazz) {
mEnvironment = env;
clsMouse = clazz;
/* Cache fields in Mouse */
CacheMouseFields();
CacheMouseFields(env, clazz);
}
JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nHasWheel(JNIEnv *, jclass) {
@ -110,11 +106,8 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetButtonCount(JNIEnv *, jcla
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nCreate(JNIEnv *env, jclass clazz) {
HRESULT hr;
mEnvironment = env;
clsMouse = clazz;
ShowCursor(FALSE);
CacheMouseFields();
CacheMouseFields(env, clazz);
/* skip enumeration, since we only want system mouse */
CreateMouse();
@ -177,12 +170,12 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nSetNativeCursor
SetClassLong(hwnd, GCL_HCURSOR, (LONG)cursor);
SetCursor(cursor);
if (!usingNativeCursor) {
/* Reset cursor position to 0, 0 */
/* Reset cursor position to middle of the window */
RECT clientRect;
GetWindowRect(hwnd, &windowRect);
getScreenClientRect(&clientRect, &windowRect);
cursorPos.x = clientRect.left;
cursorPos.y = clientRect.bottom - 1;
cursorPos.x = (clientRect.left + clientRect.right)/2;
cursorPos.y = (int)ceil((clientRect.top + clientRect.bottom)/2.0f);
SetCursorPos(cursorPos.x, cursorPos.y);
ShowCursor(TRUE);
usingNativeCursor = true;
@ -230,8 +223,6 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetMinCursorSize
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy(JNIEnv *env, jclass clazz) {
mEnvironment = env;
clsMouse = clazz;
ShowCursor(TRUE);
ShutdownMouse();
}
@ -243,9 +234,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy(JNIEnv *env, jclass c
*/
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll(JNIEnv * env, jclass clazz) {
mDIDevice->Acquire();
mEnvironment = env;
clsMouse = clazz;
UpdateMouseFields();
UpdateMouseFields(env, clazz);
}
/**
@ -381,7 +370,7 @@ static void getGDICursorDelta(int* return_dx, int* return_dy) {
/**
* Updates the fields on the Mouse
*/
void UpdateMouseFields() {
static void UpdateMouseFields(JNIEnv *env, jclass clsMouse) {
HRESULT hRes;
DIMOUSESTATE diMouseState; // State of Mouse
int dx, dy;
@ -418,9 +407,9 @@ void UpdateMouseFields() {
}
dy = -dy;
mEnvironment->SetStaticIntField(clsMouse, fidMDX, (jint)dx);
mEnvironment->SetStaticIntField(clsMouse, fidMDY, (jint)dy);
mEnvironment->SetStaticIntField(clsMouse, fidMDWheel, (jint)diMouseState.lZ);
env->SetStaticIntField(clsMouse, fidMDX, (jint)dx);
env->SetStaticIntField(clsMouse, fidMDY, (jint)dy);
env->SetStaticIntField(clsMouse, fidMDWheel, (jint)diMouseState.lZ);
for (int i = 0; i < mButtoncount; i++) {
if (diMouseState.rgbButtons[i] != 0) {
@ -429,16 +418,16 @@ void UpdateMouseFields() {
diMouseState.rgbButtons[i] = JNI_FALSE;
}
}
jbooleanArray mButtonsArray = (jbooleanArray) mEnvironment->GetStaticObjectField(clsMouse, fidMButtons);
mEnvironment->SetBooleanArrayRegion(mButtonsArray, 0, mButtoncount, diMouseState.rgbButtons);
jbooleanArray mButtonsArray = (jbooleanArray) env->GetStaticObjectField(clsMouse, fidMButtons);
env->SetBooleanArrayRegion(mButtonsArray, 0, mButtoncount, diMouseState.rgbButtons);
}
/**
* Caches the field ids for quicker access
*/
void CacheMouseFields() {
fidMButtons = mEnvironment->GetStaticFieldID(clsMouse, "buttons", "[Z");
fidMDX = mEnvironment->GetStaticFieldID(clsMouse, "dx", "I");
fidMDY = mEnvironment->GetStaticFieldID(clsMouse, "dy", "I");
fidMDWheel = mEnvironment->GetStaticFieldID(clsMouse, "dwheel", "I");
void CacheMouseFields(JNIEnv* env, jclass clsMouse) {
fidMButtons = env->GetStaticFieldID(clsMouse, "buttons", "[Z");
fidMDX = env->GetStaticFieldID(clsMouse, "dx", "I");
fidMDY = env->GetStaticFieldID(clsMouse, "dy", "I");
fidMDWheel = env->GetStaticFieldID(clsMouse, "dwheel", "I");
}