From 5af5828dc6b2936058698134a31fd69cf6b3ce34 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 21 Nov 2005 13:22:52 +0000 Subject: [PATCH] Linux: Moved display mode extension and window state handling up into java code --- src/java/org/lwjgl/opengl/LinuxDisplay.java | 110 ++++++++++++++++---- src/native/linux/Window.h | 17 ++- src/native/linux/display.c | 92 ++++++++-------- src/native/linux/display.h | 13 +-- src/native/linux/org_lwjgl_input_Keyboard.c | 10 +- src/native/linux/org_lwjgl_input_Mouse.c | 20 ++-- src/native/linux/org_lwjgl_opengl_Display.c | 109 ++++++++----------- 7 files changed, 203 insertions(+), 168 deletions(-) diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java index 64ea9d14..e31d7416 100644 --- a/src/java/org/lwjgl/opengl/LinuxDisplay.java +++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java @@ -47,6 +47,22 @@ import org.lwjgl.LWJGLUtil; import org.lwjgl.input.Keyboard; final class LinuxDisplay implements DisplayImplementation { + /** Window mode enum */ + private static final int FULLSCREEN_LEGACY = 1; + private static final int FULLSCREEN_NETWM = 2; + private static final int WINDOWED = 3; + + /** Current window mode */ + private static int current_window_mode = WINDOWED; + + /** Display mode switching API */ + private static final int XRANDR = 10; + private static final int XF86VIDMODE = 11; + private static final int NONE = 12; + + /** Current mode swithcing API */ + private static int current_displaymode_extension = NONE; + private static final int NUM_BUTTONS = 3; /** Keep track on the current awt lock owner to avoid @@ -62,6 +78,37 @@ final class LinuxDisplay implements DisplayImplementation { private static PeerInfo peer_info; + private static int getBestDisplayModeExtension() throws LWJGLException { + if (System.getenv("LWJGL_DISABLE_XRANDR") == null && isXrandrSupported()) { + LWJGLUtil.log("Using Xrandr for display mode switching"); + return XRANDR; + } else if (isXF86VidModeSupported()) { + LWJGLUtil.log("Using XF86VidMode for display mode switching"); + return XF86VIDMODE; + } else { + LWJGLUtil.log("No display mode extensions available"); + return NONE; + } + + } + private static native boolean isXrandrSupported() throws LWJGLException; + private static native boolean isXF86VidModeSupported() throws LWJGLException; + + private static boolean isNetWMFullscreenSupported() throws LWJGLException { + if (System.getenv("LWJGL_DISABLE_NETWM") != null) + return false; + lockAWT(); + try { + incDisplay(); + boolean supported = nIsNetWMFullscreenSupported(); + decDisplay(); + return supported; + } finally { + unlockAWT(); + } + } + private static native boolean nIsNetWMFullscreenSupported(); + /* Since Xlib is not guaranteed to be thread safe, we need a way to synchronize LWJGL * Xlib calls with AWT Xlib calls. Fortunately, JAWT implements Lock()/Unlock() to * do just that. @@ -129,12 +176,26 @@ final class LinuxDisplay implements DisplayImplementation { private static native void openDisplay() throws LWJGLException; private static native void closeDisplay(); + private static int getWindowMode(boolean fullscreen) throws LWJGLException { + if (fullscreen) { + if (current_displaymode_extension == XRANDR && isNetWMFullscreenSupported()) { + LWJGLUtil.log("Using NetWM for fullscreen window"); + return FULLSCREEN_NETWM; + } else { + LWJGLUtil.log("Using legacy mode for fullscreen window"); + return FULLSCREEN_LEGACY; + } + } else + return WINDOWED; + } + public void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException { lockAWT(); try { ByteBuffer handle = peer_info.lockAndGetHandle(); try { - nCreateWindow(handle, mode, fullscreen, x, y); + current_window_mode = getWindowMode(fullscreen); + nCreateWindow(handle, mode, current_window_mode, x, y); } finally { peer_info.unlock(); } @@ -142,7 +203,7 @@ final class LinuxDisplay implements DisplayImplementation { unlockAWT(); } } - private static native void nCreateWindow(ByteBuffer peer_info_handle, DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException; + private static native void nCreateWindow(ByteBuffer peer_info_handle, DisplayMode mode, int window_mode, int x, int y) throws LWJGLException; public void destroyWindow() { lockAWT(); @@ -154,22 +215,22 @@ final class LinuxDisplay implements DisplayImplementation { public void switchDisplayMode(DisplayMode mode) throws LWJGLException { lockAWT(); try { - nSwitchDisplayMode(mode); + nSwitchDisplayMode(current_displaymode_extension, mode); } finally { unlockAWT(); } } - private static native void nSwitchDisplayMode(DisplayMode mode) throws LWJGLException; + private static native void nSwitchDisplayMode(int extension, DisplayMode mode) throws LWJGLException; public void resetDisplayMode() { lockAWT(); try { - nResetDisplayMode(); + nResetDisplayMode(current_displaymode_extension); } finally { unlockAWT(); } } - private static native void nResetDisplayMode(); + private static native void nResetDisplayMode(int extension); public int getGammaRampLength() { lockAWT(); @@ -200,13 +261,17 @@ final class LinuxDisplay implements DisplayImplementation { public DisplayMode init() throws LWJGLException { lockAWT(); try { - DisplayMode mode = nInit(); + current_displaymode_extension = getBestDisplayModeExtension(); + if (current_displaymode_extension == NONE) + throw new LWJGLException("No display mode extension is available"); + DisplayMode mode = nInit(current_displaymode_extension); return mode; } finally { unlockAWT(); } } - private static native DisplayMode nInit() throws LWJGLException; + /** Assumes extension != NONE */ + private static native DisplayMode nInit(int extension) throws LWJGLException; public void setTitle(String title) { lockAWT(); @@ -233,11 +298,11 @@ final class LinuxDisplay implements DisplayImplementation { public boolean isActive() { lockAWT(); - boolean result = nIsActive(); + boolean result = nIsActive(current_window_mode); unlockAWT(); return result; } - private static native boolean nIsActive(); + private static native boolean nIsActive(int window_mode); public boolean isDirty() { lockAWT(); @@ -254,10 +319,10 @@ final class LinuxDisplay implements DisplayImplementation { public void update() { lockAWT(); - nUpdate(); + nUpdate(current_displaymode_extension, current_window_mode); unlockAWT(); } - private static native void nUpdate(); + private static native void nUpdate(int extension, int current_window_mode); public void reshape(int x, int y, int width, int height) { lockAWT(); @@ -269,13 +334,13 @@ final class LinuxDisplay implements DisplayImplementation { public DisplayMode[] getAvailableDisplayModes() throws LWJGLException { lockAWT(); try { - DisplayMode[] modes = nGetAvailableDisplayModes(); + DisplayMode[] modes = nGetAvailableDisplayModes(current_displaymode_extension); return modes; } finally { unlockAWT(); } } - private static native DisplayMode[] nGetAvailableDisplayModes() throws LWJGLException; + private static native DisplayMode[] nGetAvailableDisplayModes(int extension) throws LWJGLException; /* Mouse */ public boolean hasWheel() { @@ -288,10 +353,11 @@ final class LinuxDisplay implements DisplayImplementation { public void createMouse() { lockAWT(); - nCreateMouse(); + nCreateMouse(current_window_mode); unlockAWT(); } - private static native void nCreateMouse(); + private static native void nCreateMouse(int window_mode); + public void destroyMouse() { lockAWT(); nDestroyMouse(); @@ -300,6 +366,7 @@ final class LinuxDisplay implements DisplayImplementation { private static native void nDestroyMouse(); public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) { + update(); lockAWT(); nPollMouse(coord_buffer, buttons); unlockAWT(); @@ -307,6 +374,7 @@ final class LinuxDisplay implements DisplayImplementation { private static native void nPollMouse(IntBuffer coord_buffer, ByteBuffer buttons); public int readMouse(IntBuffer buffer, int buffer_position) { + update(); lockAWT(); int count = nReadMouse(buffer, buffer_position); unlockAWT(); @@ -323,10 +391,10 @@ final class LinuxDisplay implements DisplayImplementation { public void grabMouse(boolean grab) { lockAWT(); - nGrabMouse(grab); + nGrabMouse(current_window_mode, grab); unlockAWT(); } - private static native void nGrabMouse(boolean grab); + private static native void nGrabMouse(int window_mode, boolean grab); public int getNativeCursorCapabilities() { lockAWT(); @@ -386,12 +454,12 @@ final class LinuxDisplay implements DisplayImplementation { public void createKeyboard() throws LWJGLException { lockAWT(); try { - nCreateKeyboard(); + nCreateKeyboard(current_window_mode); } finally { unlockAWT(); } } - private static native void nCreateKeyboard() throws LWJGLException; + private static native void nCreateKeyboard(int window_mode) throws LWJGLException; public void destroyKeyboard() { lockAWT(); @@ -401,6 +469,7 @@ final class LinuxDisplay implements DisplayImplementation { private static native void nDestroyKeyboard(); public void pollKeyboard(ByteBuffer keyDownBuffer) { + update(); lockAWT(); nPollKeyboard(keyDownBuffer); unlockAWT(); @@ -408,6 +477,7 @@ final class LinuxDisplay implements DisplayImplementation { private static native void nPollKeyboard(ByteBuffer keyDownBuffer); public int readKeyboard(IntBuffer buffer, int buffer_position) { + update(); lockAWT(); int count = nReadKeyboard(buffer, buffer_position); unlockAWT(); diff --git a/src/native/linux/Window.h b/src/native/linux/Window.h index ec822eae..0f2ff8df 100644 --- a/src/native/linux/Window.h +++ b/src/native/linux/Window.h @@ -49,12 +49,7 @@ #include "extgl.h" #include "extgl_glx.h" - /* - * release input (keyboard, mouse) - */ - extern void handleMessages(JNIEnv *env); - - extern bool checkXError(JNIEnv *env, Display *display); + extern bool checkXError(JNIEnv *, Display *); extern Atom getWarpAtom(void); /* * Various functions to release/acquire keyboard and mouse @@ -64,9 +59,9 @@ extern void handleButtonPress(XButtonEvent *); extern void handleButtonRelease(XButtonEvent *); extern void handleKeyEvent(XKeyEvent *); - extern void updatePointerGrab(void); - extern void updateKeyboardGrab(void); - extern void setGrab(bool); + extern void updatePointerGrab(jint); + extern void updateKeyboardGrab(jint); + extern void setGrab(jint, bool); extern bool isGrabbed(void); extern bool shouldGrab(void); @@ -98,11 +93,11 @@ /* * Return true if we are in fullscreen mode */ - extern bool isFullscreen(void); + extern bool isFullscreen(jint window_mode); /* * Return true if we are in exclusive fullscreen mode */ - extern bool isLegacyFullscreen(void); + extern bool isLegacyFullscreen(jint window_mode); #endif /* _LWJGL_WINDOW_H_INCLUDED_ */ diff --git a/src/native/linux/display.c b/src/native/linux/display.c index 1ca64476..5048a92c 100644 --- a/src/native/linux/display.c +++ b/src/native/linux/display.c @@ -50,6 +50,7 @@ #include "display.h" #include "common_tools.h" #include "Window.h" +#include "org_lwjgl_opengl_LinuxDisplay.h" #define NUM_XRANDR_RETRIES 5 @@ -75,7 +76,6 @@ static unsigned short *g_ramp = NULL; static unsigned short *b_ramp = NULL; static unsigned short *current_ramp = NULL; static int current_gamma_ramp_length = 0; -static extension current_extension = NONE; int getScreenModeWidth(void) { return current_width; @@ -85,15 +85,6 @@ int getScreenModeHeight(void) { return current_height; } -extension getCurrentDisplayModeExtension(void) { - return current_extension; -} - -static bool isXrandrForceDisabled() { - char *supported_env = getenv("LWJGL_DISABLE_XRANDR"); - return supported_env != NULL; -} - static bool getXF86VidModeVersion(JNIEnv *env, Display *disp, int *major, int *minor) { int event_base, error_base; @@ -126,8 +117,6 @@ static bool getXrandrVersion(JNIEnv *env, Display *disp, int *major, int *minor) static bool isXrandrSupported(JNIEnv *env, Display *disp) { int major, minor; - if (isXrandrForceDisabled()) - return false; if (!getXrandrVersion(env, disp, &major, &minor)) return false; return major >= 1; @@ -140,17 +129,28 @@ static bool isXF86VidModeSupported(JNIEnv *env, Display *disp) { return major_ver >= 2; } -static extension getBestDisplayModeExtension(JNIEnv *env, Display *disp) { - if (isXrandrSupported(env, disp)) { - printfDebugJava(env, "Using Xrandr for display mode switching"); - return XRANDR; - } else if (isXF86VidModeSupported(env, disp)) { - printfDebugJava(env, "Using XF86VidMode for display mode switching"); - return XF86VIDMODE; - } else { - printfDebugJava(env, "No display mode extensions available"); - return NONE; +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_isXrandrSupported(JNIEnv *env, jclass unused) { + Display *disp = XOpenDisplay(NULL); + if (disp == NULL) { + throwException(env, "Could not open display"); + return JNI_FALSE; } + + jboolean result = isXrandrSupported(env, disp) ? JNI_TRUE : JNI_FALSE; + XCloseDisplay(disp); + return result; +} + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_isXF86VidModeSupported(JNIEnv *env, jclass unused) { + Display *disp = XOpenDisplay(NULL); + if (disp == NULL) { + throwException(env, "Could not open display"); + return JNI_FALSE; + } + + jboolean result = isXF86VidModeSupported(env, disp) ? JNI_TRUE : JNI_FALSE; + XCloseDisplay(disp); + return result; } static mode_info *getXrandrDisplayModes(Display *disp, int screen, int *num_modes) { @@ -204,13 +204,13 @@ static mode_info *getXF86VidModeDisplayModes(Display *disp, int screen, int *num return avail_modes; } -static mode_info *getDisplayModes(Display *disp, int screen, int *num_modes) { - switch (current_extension) { - case XF86VIDMODE: +static mode_info *getDisplayModes(Display *disp, int screen, jint extension, int *num_modes) { + switch (extension) { + case org_lwjgl_opengl_LinuxDisplay_XF86VIDMODE: return getXF86VidModeDisplayModes(disp, screen, num_modes); - case XRANDR: + case org_lwjgl_opengl_LinuxDisplay_XRANDR: return getXrandrDisplayModes(disp, screen, num_modes); - case NONE: + case org_lwjgl_opengl_LinuxDisplay_NONE: // fall through default: return NULL; @@ -255,9 +255,9 @@ static bool setXrandrMode(Display *disp, int screen, mode_info *mode) { return false; } -static bool setMode(JNIEnv *env, Display *disp, int screen, int width, int height, int freq, bool temporary) { +static bool setMode(JNIEnv *env, Display *disp, int screen, jint extension, int width, int height, int freq, bool temporary) { int num_modes, i; - mode_info *avail_modes = getDisplayModes(disp, screen, &num_modes); + mode_info *avail_modes = getDisplayModes(disp, screen, extension, &num_modes); if (avail_modes == NULL) { printfDebugJava(env, "Could not get display modes"); return false; @@ -266,20 +266,20 @@ static bool setMode(JNIEnv *env, Display *disp, int screen, int width, int heigh for ( i = 0; i < num_modes; ++i ) { printfDebugJava(env, "Mode %d: %dx%d @%d", i, avail_modes[i].width, avail_modes[i].height, avail_modes[i].freq); if (avail_modes[i].width == width && avail_modes[i].height == height && avail_modes[i].freq == freq) { - switch (current_extension) { - case XF86VIDMODE: + switch (extension) { + case org_lwjgl_opengl_LinuxDisplay_XF86VIDMODE: if (!setXF86VidModeMode(disp, screen, &avail_modes[i])) { printfDebugJava(env, "Could not switch mode"); continue; } break; - case XRANDR: + case org_lwjgl_opengl_LinuxDisplay_XRANDR: if (!setXrandrMode(disp, screen, &avail_modes[i])) { printfDebugJava(env, "Could not switch mode"); continue; } break; - case NONE: // Should never happen, since NONE imply no available display modes + case org_lwjgl_opengl_LinuxDisplay_NONE: // Should never happen, since NONE imply no available display modes default: // Should never happen continue; } @@ -331,7 +331,7 @@ int getGammaRampLength(JNIEnv *env, int screen) { return length; } -jobject initDisplay(JNIEnv *env, int screen) { +jobject initDisplay(JNIEnv *env, int screen, jint extension) { int num_modes; mode_info *avail_modes; Display *disp = XOpenDisplay(NULL); @@ -340,13 +340,7 @@ jobject initDisplay(JNIEnv *env, int screen) { return NULL; } - current_extension = getBestDisplayModeExtension(env, disp); - if (current_extension == NONE) { - throwException(env, "No display mode extension is available"); - XCloseDisplay(disp); - return NULL; - } - avail_modes = getDisplayModes(disp, screen, &num_modes); + avail_modes = getDisplayModes(disp, screen, extension, &num_modes); if (avail_modes == NULL || num_modes == 0) { throwException(env, "Could not get display modes"); XCloseDisplay(disp); @@ -395,20 +389,20 @@ static void setCurrentGamma(Display *disp, int screen, JNIEnv *env) { } } -void temporaryRestoreMode(JNIEnv *env, int screen) { +void temporaryRestoreMode(JNIEnv *env, int screen, jint extension) { Display *disp = XOpenDisplay(NULL); if (disp == NULL) { printfDebugJava(env, "Could not open display"); return; } - if (!setMode(env, disp, screen, current_width, current_height, current_freq, false)) + if (!setMode(env, disp, screen, extension, current_width, current_height, current_freq, false)) printfDebugJava(env, "Could not restore mode"); setCurrentGamma(disp, screen, NULL); XCloseDisplay(disp); // Don't propagate error to caller } -void switchDisplayMode(JNIEnv * env, jobject mode, int screen) { +void switchDisplayMode(JNIEnv * env, jobject mode, int screen, jint extension) { if (mode == NULL) { throwException(env, "mode must be non-null"); return; @@ -425,18 +419,18 @@ void switchDisplayMode(JNIEnv * env, jobject mode, int screen) { throwException(env, "Could not open display"); return; } - if (!setMode(env, disp, screen, width, height, freq, false)) + if (!setMode(env, disp, screen, extension, width, height, freq, false)) throwException(env, "Could not switch mode."); XCloseDisplay(disp); } -void resetDisplayMode(JNIEnv *env, int screen, bool temporary) { +void resetDisplayMode(JNIEnv *env, int screen, jint extension, bool temporary) { Display *disp = XOpenDisplay(NULL); if (disp == NULL) { printfDebugJava(env, "Failed to contact X Server"); return; } - if (!setMode(env, disp, screen, saved_width, saved_height, saved_freq, temporary)) { + if (!setMode(env, disp, screen, extension, saved_width, saved_height, saved_freq, temporary)) { printfDebugJava(env, "Failed to reset mode"); } if (saved_gamma_ramp_length > 0) { @@ -446,7 +440,7 @@ void resetDisplayMode(JNIEnv *env, int screen, bool temporary) { XCloseDisplay(disp); } -jobjectArray getAvailableDisplayModes(JNIEnv * env, int screen) { +jobjectArray getAvailableDisplayModes(JNIEnv * env, int screen, jint extension) { int num_modes, i; mode_info *avail_modes; Display *disp = XOpenDisplay(NULL); @@ -456,7 +450,7 @@ jobjectArray getAvailableDisplayModes(JNIEnv * env, int screen) { } int bpp = XDefaultDepth(disp, screen); - avail_modes = getDisplayModes(disp, screen, &num_modes); + avail_modes = getDisplayModes(disp, screen, extension, &num_modes); if (avail_modes == NULL) { printfDebugJava(env, "Could not get display modes"); XCloseDisplay(disp); diff --git a/src/native/linux/display.h b/src/native/linux/display.h index fe6cf7be..717f7397 100644 --- a/src/native/linux/display.h +++ b/src/native/linux/display.h @@ -45,17 +45,14 @@ #include #include "common_tools.h" -typedef enum {XRANDR, XF86VIDMODE, NONE} extension; - extern int getScreenModeWidth(void); extern int getScreenModeHeight(void); -extern jobject initDisplay(JNIEnv *env, int screen); -extern void switchDisplayMode(JNIEnv * env, jobject mode, int screen); -extern void resetDisplayMode(JNIEnv *env, int screen, bool temporary); -extern jobjectArray getAvailableDisplayModes(JNIEnv * env, int screen); +extern jobject initDisplay(JNIEnv *env, int screen, jint extension); +extern void switchDisplayMode(JNIEnv * env, jobject mode, int screen, jint extension); +extern void resetDisplayMode(JNIEnv *env, int screen, jint extension, bool temporary); +extern jobjectArray getAvailableDisplayModes(JNIEnv * env, int screen, jint extension); extern int getGammaRampLength(JNIEnv *env, int screen); extern void setGammaRamp(JNIEnv *env, jobject gamma_ramp_buffer, int screen); -extern extension getCurrentDisplayModeExtension(); -extern void temporaryRestoreMode(JNIEnv *env, int screen); +extern void temporaryRestoreMode(JNIEnv *env, int screen, jint extension); #endif diff --git a/src/native/linux/org_lwjgl_input_Keyboard.c b/src/native/linux/org_lwjgl_input_Keyboard.c index 5d2cb5f4..7f4ef2e7 100644 --- a/src/native/linux/org_lwjgl_input_Keyboard.c +++ b/src/native/linux/org_lwjgl_input_Keyboard.c @@ -87,10 +87,10 @@ static void ungrabKeyboard(void) { } } -void updateKeyboardGrab(void) { +void updateKeyboardGrab(jint window_mode) { if (!created) return; - if (isLegacyFullscreen()/* || shouldGrab()*/) { + if (isLegacyFullscreen(window_mode)) { grabKeyboard(); } else { ungrabKeyboard(); @@ -123,13 +123,13 @@ static void setupIMEventMask() { } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateKeyboard - (JNIEnv * env, jclass clazz) + (JNIEnv * env, jclass clazz, jint window_mode) { memset(key_buf, 0, KEYBOARD_SIZE*sizeof(unsigned char)); created = true; keyboard_grabbed = false; initEventQueue(&event_queue, 3); - updateKeyboardGrab(); + updateKeyboardGrab(window_mode); XModifierKeymap *modifier_map = XGetModifierMapping(getDisplay()); numlock_mask = 0; modeswitch_mask = 0; @@ -684,12 +684,10 @@ void handleKeyEvent(XKeyEvent *event) { JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollKeyboard(JNIEnv * env, jclass clazz, jobject buffer) { unsigned char *new_keyboard_buffer = (unsigned char *)(*env)->GetDirectBufferAddress(env, buffer); - handleMessages(env); memcpy(new_keyboard_buffer, key_buf, KEYBOARD_SIZE*sizeof(unsigned char)); } JNIEXPORT int JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadKeyboard(JNIEnv * env, jclass clazz, jobject buffer, jint buffer_position) { - handleMessages(env); jint* buffer_ptr = (jint *)(*env)->GetDirectBufferAddress(env, buffer); int buffer_size = ((*env)->GetDirectBufferCapacity(env, buffer))/sizeof(jint) - buffer_position; return copyEvents(&event_queue, buffer_ptr + buffer_position, buffer_size); diff --git a/src/native/linux/org_lwjgl_input_Mouse.c b/src/native/linux/org_lwjgl_input_Mouse.c index e281a48f..1c6bfa07 100644 --- a/src/native/linux/org_lwjgl_input_Mouse.c +++ b/src/native/linux/org_lwjgl_input_Mouse.c @@ -135,7 +135,7 @@ static void updateCursor(void) { XDefineCursor(getDisplay(), getCurrentWindow(), cursor); } -static void grabPointer(void) { +static void grabPointer(jint window_mode) { if (!pointer_grabbed) { int result; int grab_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask; @@ -144,7 +144,7 @@ static void grabPointer(void) { if (result == GrabSuccess) { pointer_grabbed = true; // make sure we have a centered window - if (isLegacyFullscreen()) { + if (isLegacyFullscreen(window_mode)) { XWindowAttributes win_attribs; XGetWindowAttributes(getDisplay(), getCurrentWindow(), &win_attribs); XF86VidModeSetViewPort(getDisplay(), getCurrentScreen(), win_attribs.x, win_attribs.y); @@ -162,11 +162,11 @@ static void ungrabPointer(void) { } } -void updatePointerGrab(void) { +void updatePointerGrab(jint window_mode) { if (!created) return; - if (isFullscreen() || shouldGrab()) { - grabPointer(); + if (isFullscreen(window_mode) || shouldGrab()) { + grabPointer(window_mode); } else { ungrabPointer(); } @@ -205,7 +205,7 @@ static void reset(void) { } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateMouse - (JNIEnv * env, jclass clazz) + (JNIEnv * env, jclass clazz, jint window_mode) { int i; last_y = last_x = accum_dx = accum_dy = accum_dz = 0; @@ -218,7 +218,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateMouse current_cursor = None; created = true; pointer_grabbed = false; - updatePointerGrab(); + updatePointerGrab(window_mode); initEventQueue(&event_queue, EVENT_SIZE); } @@ -314,7 +314,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollMouse(JNIEnv * en int coords_length = (*env)->GetDirectBufferCapacity(env, coord_buffer_obj); unsigned char *buttons_buffer = (unsigned char *)(*env)->GetDirectBufferAddress(env, button_buffer_obj); int buttons_length = (*env)->GetDirectBufferCapacity(env, button_buffer_obj); - handleMessages(env); if (coords_length < 3) { printfDebugJava(env, "ERROR: Not enough space in coords array: %d < 3", coords_length); return; @@ -339,7 +338,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollMouse(JNIEnv * en JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadMouse(JNIEnv *env, jclass clazz, jobject buffer, jint buffer_position) { jint* buffer_ptr = (jint *)(*env)->GetDirectBufferAddress(env, buffer); int buffer_size = ((*env)->GetDirectBufferCapacity(env, buffer))/sizeof(jint) - buffer_position; - handleMessages(env); return copyEvents(&event_queue, buffer_ptr + buffer_position, buffer_size); } @@ -347,12 +345,12 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetCursorPosition(JNI XWarpPointer(getDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, x, transformY(y)); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabMouse(JNIEnv * env, jclass clazz, jboolean new_grab) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabMouse(JNIEnv * env, jclass clazz, jint window_mode, jboolean new_grab) { Window root_return, child_return; int root_x, root_y, win_x, win_y; unsigned int mask_return; - setGrab(new_grab == JNI_TRUE ? true : false); + setGrab(window_mode, new_grab == JNI_TRUE ? true : false); reset(); XQueryPointer(getDisplay(), getCurrentWindow(), &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask_return); doHandlePointerMotion(root_x, root_y, win_x, win_y); diff --git a/src/native/linux/org_lwjgl_opengl_Display.c b/src/native/linux/org_lwjgl_opengl_Display.c index 93be2d16..f681e2db 100644 --- a/src/native/linux/org_lwjgl_opengl_Display.c +++ b/src/native/linux/org_lwjgl_opengl_Display.c @@ -68,14 +68,11 @@ typedef struct { #define MWM_HINTS_DECORATIONS (1L << 1) -typedef enum {FULLSCREEN_LEGACY, FULLSCREEN_NETWM, WINDOWED} window_mode; - static GLXWindow glx_window = None; static Atom delete_atom; static Colormap cmap; static Window current_win; -static window_mode current_window_mode; static int current_height; static int current_width; static int current_depth; @@ -156,9 +153,9 @@ static void waitMapped(Window win) { } while ((event.type != MapNotify) || (event.xmap.event != win)); } -static void updateInputGrab(void) { - updatePointerGrab(); - updateKeyboardGrab(); +static void updateInputGrab(jint window_mode) { + updatePointerGrab(window_mode); + updateKeyboardGrab(window_mode); } static void setRepeatMode(JNIEnv *env, int mode) { @@ -185,36 +182,36 @@ static void setDecorations(int dec) { XChangeProperty (getDisplay(), getCurrentWindow(), motif_hints_atom, motif_hints_atom, 32, PropModeReplace, (unsigned char *)&motif_hints, sizeof(MotifWmHints)/sizeof(long)); } -static bool releaseInput(JNIEnv *env) { - if (isLegacyFullscreen() || input_released) +static bool releaseInput(JNIEnv *env, jint extension, jint window_mode) { + if (isLegacyFullscreen(window_mode) || input_released) return false; input_released = true; setRepeatMode(env, AutoRepeatModeDefault); - updateInputGrab(); - if (current_window_mode == FULLSCREEN_NETWM) { + updateInputGrab(window_mode); + if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) { XIconifyWindow(getDisplay(), getCurrentWindow(), getCurrentScreen()); - resetDisplayMode(env, getCurrentScreen(), true); + resetDisplayMode(env, getCurrentScreen(), extension, true); } return true; } -static void acquireInput(JNIEnv *env) { - if (isLegacyFullscreen() || !input_released) +static void acquireInput(JNIEnv *env, jint extension, jint window_mode) { + if (isLegacyFullscreen(window_mode) || !input_released) return; input_released = false; setRepeatMode(env, AutoRepeatModeOff); - updateInputGrab(); - if (current_window_mode == FULLSCREEN_NETWM) { - temporaryRestoreMode(env, getCurrentScreen()); + updateInputGrab(window_mode); + if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) { + temporaryRestoreMode(env, getCurrentScreen(), extension); } } -bool isFullscreen(void) { - return current_window_mode == FULLSCREEN_LEGACY || current_window_mode == FULLSCREEN_NETWM; +bool isFullscreen(jint window_mode) { + return window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_LEGACY || window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM; } -bool isLegacyFullscreen(void) { - return current_window_mode == FULLSCREEN_LEGACY; +bool isLegacyFullscreen(jint window_mode) { + return window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_LEGACY; } bool shouldGrab(void) { @@ -225,27 +222,27 @@ bool isGrabbed(void) { return grab; } -void setGrab(bool new_grab) { +void setGrab(jint window_mode, bool new_grab) { if (new_grab != grab) { grab = new_grab; - updateInputGrab(); + updateInputGrab(window_mode); } } -static void checkInput(JNIEnv *env) { +static void checkInput(JNIEnv *env, jint extension, jint window_mode) { Window win; int revert_mode; XGetInputFocus(getDisplay(), &win, &revert_mode); if (win == current_win) { - acquireInput(env); + acquireInput(env, extension, window_mode); focused = true; } else { - releaseInput(env); + releaseInput(env, extension, window_mode); focused = false; } } -void handleMessages(JNIEnv *env) { +void handleMessages(JNIEnv *env, jint extension, jint window_mode) { XEvent event; /* Window win; int revert_mode;*/ @@ -296,7 +293,7 @@ void handleMessages(JNIEnv *env) { break; } } - checkInput(env); + checkInput(env, extension, window_mode); } static void setWindowTitle(const char *title) { @@ -339,19 +336,12 @@ static void destroyWindow(JNIEnv *env) { setRepeatMode(env, AutoRepeatModeDefault); } -static bool isNetWMForceDisabled() { - char *supported_env = getenv("LWJGL_DISABLE_NETWM"); - return supported_env != NULL; -} - static bool isNetWMFullscreenSupported(JNIEnv *env) { unsigned long nitems; Atom actual_type; int actual_format; unsigned long bytes_after; Atom *supported_list; - if (isNetWMForceDisabled()) - return false; Atom netwm_supported_atom = XInternAtom(getDisplay(), "_NET_SUPPORTED", False); int result = XGetWindowProperty(getDisplay(), RootWindow(getDisplay(), getCurrentScreen()), netwm_supported_atom, 0, 10000, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, (void *)&supported_list); if (result != Success) { @@ -371,11 +361,15 @@ static bool isNetWMFullscreenSupported(JNIEnv *env) { return supported; } +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsNetWMFullscreenSupported(JNIEnv *env, jclass unused) { + return isNetWMFullscreenSupported(env) ? JNI_TRUE : JNI_FALSE; +} + JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReshape(JNIEnv *env, jclass clazz, jint x, jint y, jint width, jint height) { XMoveWindow(getDisplay(), getCurrentWindow(), x, y); } -static bool createWindow(JNIEnv* env, X11PeerInfo *peer_info, int x, int y, int width, int height) { +static bool createWindow(JNIEnv* env, jint window_mode, X11PeerInfo *peer_info, int x, int y, int width, int height) { bool undecorated = getBooleanProperty(env, "org.lwjgl.opengl.Window.undecorated"); dirty = true; focused = true; @@ -401,7 +395,7 @@ static bool createWindow(JNIEnv* env, X11PeerInfo *peer_info, int x, int y, int attribs.background_pixel = 0xFF000000; attribs.win_gravity = NorthWestGravity; attribmask = CWColormap | CWBackPixel | CWEventMask | CWWinGravity; - if (isLegacyFullscreen()) { + if (isLegacyFullscreen(window_mode)) { attribmask |= CWOverrideRedirect; attribs.override_redirect = True; } @@ -417,7 +411,7 @@ static bool createWindow(JNIEnv* env, X11PeerInfo *peer_info, int x, int y, int } printfDebugJava(env, "Created window"); current_win = win; - if (current_window_mode != WINDOWED || undecorated) { + if (window_mode != org_lwjgl_opengl_LinuxDisplay_WINDOWED || undecorated) { // Use Motif decoration hint property and hope the window manager respects them setDecorations(0); } @@ -431,7 +425,7 @@ static bool createWindow(JNIEnv* env, X11PeerInfo *peer_info, int x, int y, int XFree(size_hints); delete_atom = XInternAtom(getDisplay(), "WM_DELETE_WINDOW", False); XSetWMProtocols(getDisplay(), win, &delete_atom, 1); - if (current_window_mode == FULLSCREEN_NETWM) { + if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) { Atom fullscreen_atom = XInternAtom(getDisplay(), "_NET_WM_STATE_FULLSCREEN", False); XChangeProperty(getDisplay(), getCurrentWindow(), XInternAtom(getDisplay(), "_NET_WM_STATE", False), XInternAtom(getDisplay(), "ATOM", False), 32, PropModeReplace, (const unsigned char*)&fullscreen_atom, 1); @@ -460,21 +454,21 @@ int getWindowHeight(void) { } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUpdate - (JNIEnv *env, jclass clazz) + (JNIEnv *env, jclass clazz, jint extension, jint window_mode) { - handleMessages(env); + handleMessages(env, extension, window_mode); } -JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetAvailableDisplayModes(JNIEnv *env, jclass clazz) { - return getAvailableDisplayModes(env, getCurrentScreen()); +JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetAvailableDisplayModes(JNIEnv *env, jclass clazz, jint extension) { + return getAvailableDisplayModes(env, getCurrentScreen(), extension); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwitchDisplayMode(JNIEnv *env, jclass clazz, jobject mode) { - switchDisplayMode(env, mode, getCurrentScreen()); +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwitchDisplayMode(JNIEnv *env, jclass clazz, jint extension, jobject mode) { + switchDisplayMode(env, mode, getCurrentScreen(), extension); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nResetDisplayMode(JNIEnv *env, jclass clazz) { - resetDisplayMode(env, getCurrentScreen(), false); +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nResetDisplayMode(JNIEnv *env, jclass clazz, jint extension) { + resetDisplayMode(env, getCurrentScreen(), extension, false); } JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetGammaRampLength(JNIEnv *env, jclass clazz) { @@ -485,22 +479,11 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetGammaRamp(JNIEnv * setGammaRamp(env, gamma_buffer, getCurrentScreen()); } -JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nInit(JNIEnv *env, jclass clazz) { - return initDisplay(env, getCurrentScreen()); +JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nInit(JNIEnv *env, jclass clazz, jint extension) { + return initDisplay(env, getCurrentScreen(), extension); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jobject peer_info_handle, jobject mode, jboolean fullscreen, jint x, jint y) { - bool current_fullscreen = fullscreen == JNI_TRUE; - if (current_fullscreen) { - if (getCurrentDisplayModeExtension() == XRANDR && isNetWMFullscreenSupported(env)) { - printfDebugJava(env, "Using NetWM for fullscreen window"); - current_window_mode = FULLSCREEN_NETWM; - } else { - printfDebugJava(env, "Using legacy mode for fullscreen window"); - current_window_mode = FULLSCREEN_LEGACY; - } - } else - current_window_mode = WINDOWED; +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jobject peer_info_handle, jobject mode, jint window_mode, jint x, jint y) { X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); GLXFBConfig *fb_config = NULL; if (peer_info->glx13) { @@ -513,7 +496,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv * jfieldID fid_height = (*env)->GetFieldID(env, cls_displayMode, "height", "I"); int width = (*env)->GetIntField(env, mode, fid_width); int height = (*env)->GetIntField(env, mode, fid_height); - bool window_created = createWindow(env, peer_info, x, y, width, height); + bool window_created = createWindow(env, window_mode, peer_info, x, y, width, height); if (!window_created) { return; } @@ -551,8 +534,8 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsCloseRequested } JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsActive - (JNIEnv *env, jclass clazz) { - return focused || isLegacyFullscreen() ? JNI_TRUE : JNI_FALSE; + (JNIEnv *env, jclass clazz, jint window_mode) { + return focused || isLegacyFullscreen(window_mode) ? JNI_TRUE : JNI_FALSE; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nLockAWT(JNIEnv *env, jclass clazz) {