From f188a1400b770c4f413e405938ff16442ea7f089 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 20 Nov 2002 10:33:37 +0000 Subject: [PATCH] Improved pointer and keyboard handling under windowed mode --- src/native/linux/org_lwjgl_Display.cpp | 29 ++++++---- src/native/linux/org_lwjgl_input_Keyboard.cpp | 40 ++++++++++++-- src/native/linux/org_lwjgl_input_Mouse.cpp | 54 ++++++++++++++++--- 3 files changed, 102 insertions(+), 21 deletions(-) diff --git a/src/native/linux/org_lwjgl_Display.cpp b/src/native/linux/org_lwjgl_Display.cpp index 909b02d7..8afad4da 100644 --- a/src/native/linux/org_lwjgl_Display.cpp +++ b/src/native/linux/org_lwjgl_Display.cpp @@ -55,6 +55,7 @@ Display * disp; int screen; int current_fullscreen; +int current_focused; Window win; XF86VidModeModeInfo **avail_modes; XVisualInfo * vis_info; @@ -67,18 +68,29 @@ void waitMapped(Display *disp, Window win) { } while ((event.type != MapNotify) || (event.xmap.event != win)); } +int isFocused(void) { + XEvent event; + while (XCheckMaskEvent(disp, EnterWindowMask | LeaveWindowMask, &event)) { + if (event.type == EnterNotify) + current_focused = 1; + else if (event.type == LeaveNotify) + current_focused = 0; + } + return current_focused; +} + int getDisplayModes(Display *disp, int screen, int *num_modes, XF86VidModeModeInfo ***avail_modes) { int event_base, error_base, xvid_ver, xvid_rev; if (!XF86VidModeQueryExtension(disp, &event_base, &error_base)) { #ifdef _DEBUG - printf("XF86VidMode extention not available\n"); + printf("XF86VidMode extension not available\n"); #endif return 0; } XF86VidModeQueryVersion(disp, &xvid_ver, &xvid_rev); #ifdef _DEBUG - printf("XF86VidMode extention version %i.%i\n", xvid_ver, xvid_rev); + printf("XF86VidMode extension version %i.%i\n", xvid_ver, xvid_rev); #endif XF86VidModeGetAllModeLines(disp, screen, num_modes, avail_modes); return 1; @@ -94,6 +106,7 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_nCreate(JNIEnv * env, jclass c int num_modes, i; current_fullscreen = fullscreen; + current_focused = 0; disp = XOpenDisplay(NULL); if (disp == NULL) { #ifdef _DEBUG @@ -122,9 +135,8 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_nCreate(JNIEnv * env, jclass c cmap = XCreateColormap(disp, root_win, vis_info->visual, AllocNone); attribs.colormap = cmap; - attribs.event_mask = ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; + attribs.event_mask = StructureNotifyMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; attribs.background_pixel = 0xFF000000; - attribs.event_mask = StructureNotifyMask; attribmask = CWColormap | CWBackPixel | CWEventMask; if (fullscreen) { attribmask |= CWOverrideRedirect; @@ -134,9 +146,9 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_nCreate(JNIEnv * env, jclass c #ifdef _DEBUG printf("Created window\n"); #endif + XMapRaised(disp, win); + waitMapped(disp, win); if (fullscreen) { - XMapRaised(disp, win); - waitMapped(disp, win); for ( i = 0; i < num_modes; ++i ) { #ifdef _DEBUG printf("Mode %d: %dx%d\n", i, avail_modes[i]->hdisplay, avail_modes[i]->vdisplay); @@ -155,13 +167,10 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_nCreate(JNIEnv * env, jclass c } } XF86VidModeSetViewPort(disp, screen, 0, 0); - } else { - XMapWindow(disp, win); - waitMapped(disp, win); } XClearWindow(disp, win); XSync(disp, True); - + isFocused(); return JNI_TRUE; } diff --git a/src/native/linux/org_lwjgl_input_Keyboard.cpp b/src/native/linux/org_lwjgl_input_Keyboard.cpp index 4bbaa24b..fbb9a5e8 100644 --- a/src/native/linux/org_lwjgl_input_Keyboard.cpp +++ b/src/native/linux/org_lwjgl_input_Keyboard.cpp @@ -52,8 +52,13 @@ jfieldID fid_readBuffer; jfieldID fid_readBufferAddress; unsigned char key_buf[KEYBOARD_SIZE]; +int keyboard_grabbed; + extern Display *disp; extern Window win; +extern int current_fullscreen; + +extern int isFocused(void); /* * Class: org_lwjgl_input_Keyboard @@ -74,6 +79,34 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_initIDs fid_readBufferAddress = env->GetStaticFieldID(clazz, "readBufferAddress", "I"); } +int grabKeyboard(void) { + int result = XGrabKeyboard(disp, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); + if (result == GrabSuccess) + keyboard_grabbed = 1; + return result; +} + +void ungrabKeyboard(void) { + keyboard_grabbed = 0; + XUngrabKeyboard(disp, CurrentTime); +} + +int updateKeyboardGrab(void) { + if (current_fullscreen) { + if (!keyboard_grabbed) + return grabKeyboard(); + } else { + if (isFocused()) { + if (!keyboard_grabbed) + return grabKeyboard(); + } else { + if (keyboard_grabbed) + ungrabKeyboard(); + } + } + return GrabSuccess; +} + /* * Class: org_lwjgl_input_Keyboard * Method: nCreate @@ -82,8 +115,8 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_initIDs JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Keyboard_nCreate (JNIEnv * env, jclass clazz) { - int result = XGrabKeyboard(disp, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); - if (result != GrabSuccess) { + keyboard_grabbed = 0; + if (updateKeyboardGrab() != GrabSuccess) { #ifdef _DEBUG printf("Could not grab keyboard\n"); #endif @@ -101,13 +134,14 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Keyboard_nCreate JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_nDestroy (JNIEnv * env, jclass clazz) { - XUngrabKeyboard(disp, CurrentTime); + ungrabKeyboard(); } int checkKeyEvents(unsigned char *result_buf) { XEvent event; int count = 0; int buf_count = 0; + updateKeyboardGrab(); while (XCheckMaskEvent(disp, KeyPressMask | KeyReleaseMask, &event)) { unsigned char keycode = (unsigned char)((event.xkey.keycode - 8) & 0xff); if (result_buf != NULL) { diff --git a/src/native/linux/org_lwjgl_input_Mouse.cpp b/src/native/linux/org_lwjgl_input_Mouse.cpp index 09ab9331..8fd00f23 100644 --- a/src/native/linux/org_lwjgl_input_Mouse.cpp +++ b/src/native/linux/org_lwjgl_input_Mouse.cpp @@ -50,6 +50,9 @@ extern Display *disp; extern Window win; +extern int current_fullscreen; + +int pointer_grabbed; jfieldID fid_button; jfieldID fid_dx; @@ -66,6 +69,8 @@ unsigned char buttons[NUM_BUTTONS]; Cursor blank_cursor; +extern int isFocused(void); + /* * Class: org_lwjgl_input_Mouse * Method: initIDs @@ -113,10 +118,42 @@ int blankCursor(void) { XColor dummy_color; blank_cursor = XCreatePixmapCursor(disp, mask, mask, &dummy_color, &dummy_color, 0, 0); XFreePixmap(disp, mask); - XDefineCursor(disp, win, blank_cursor); return 1; } +int grabPointer(void) { + int result; + int mask = EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask; + if (current_fullscreen) + result = XGrabPointer(disp, win, False, mask, GrabModeAsync, GrabModeAsync, win, blank_cursor, CurrentTime); + else + result = XGrabPointer(disp, win, False, mask, GrabModeAsync, GrabModeAsync, None, blank_cursor, CurrentTime); + if (result == GrabSuccess) + pointer_grabbed = 1; + return result; +} + +void ungrabPointer(void) { + pointer_grabbed = 0; + XUngrabPointer(disp, CurrentTime); +} + +int updatePointerGrab(void) { + if (current_fullscreen) { + if (!pointer_grabbed) + return grabPointer(); + } else { + if (isFocused()) { + if (!pointer_grabbed) + return grabPointer(); + } else { + if (pointer_grabbed) + ungrabPointer(); + } + } + return GrabSuccess; +} + /* * Class: org_lwjgl_input_Mouse * Method: nCreate @@ -126,19 +163,19 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate (JNIEnv * env, jclass clazz) { int i; - current_x = current_y = current_z = last_x = last_y = last_z = 0; + + current_x = current_y = current_z = last_x = last_y = last_z = pointer_grabbed = 0; for (i = 0; i < NUM_BUTTONS; i++) buttons[i] = 0; if (!blankCursor()) { #ifdef _DEBUG - printf("Could not blank cursor\n"); + printf("Could create blank cursor\n"); #endif return JNI_FALSE; } - int result = XGrabPointer(disp, win, False, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); - if (result != GrabSuccess) { + if (updatePointerGrab() != GrabSuccess) { #ifdef _DEBUG - printf("Could not grab mouse\n"); + printf("Could not grab pointer\n"); #endif return JNI_FALSE; } @@ -172,14 +209,15 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nHasZValue(JNIEnv *env, jc JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy (JNIEnv * env, jclass clazz) { - XUndefineCursor(disp, win); + if (pointer_grabbed) + ungrabPointer(); XFreeCursor(disp, blank_cursor); - XUngrabPointer(disp, CurrentTime); } int checkPointer() { XEvent event; int count = 0; + updatePointerGrab(); while (XCheckMaskEvent(disp, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &event)) { count++; switch (event.type) {