Linux: Attempt to avoid race condition when tracking Display parent focus

This commit is contained in:
Elias Naur 2008-04-06 21:34:22 +00:00
parent c499f33bcf
commit bf25259325
2 changed files with 28 additions and 9 deletions

View File

@ -623,8 +623,6 @@ final class LinuxDisplay implements DisplayImplementation {
private native static void setInputFocus(long display, long window); private native static void setInputFocus(long display, long window);
private void processEvents() { private void processEvents() {
if (!focused && parent != null && parent.isFocusOwner())
setInputFocus(getDisplay(), getWindow());
while (LinuxEvent.getPending(getDisplay()) > 0) { while (LinuxEvent.getPending(getDisplay()) > 0) {
event_buffer.nextEvent(getDisplay()); event_buffer.nextEvent(getDisplay());
long event_window = event_buffer.getWindow(); long event_window = event_buffer.getWindow();
@ -742,15 +740,30 @@ final class LinuxDisplay implements DisplayImplementation {
} }
private void checkInput() { private void checkInput() {
focused = nGetInputFocus(getDisplay()) == getWindow(); long current_focus = nGetInputFocus(getDisplay());
focused = current_focus == getWindow();
if (focused) { if (focused) {
focused_at_least_once = true; focused_at_least_once = true;
acquireInput(); acquireInput();
} else if (focused_at_least_once) { } else {
releaseInput(); if (focused_at_least_once)
releaseInput();
if (parent != null && parent.isFocusOwner()) {
// Normally, a real time stamp from an event should be passed to XSetInputFocus instead of CurrentTime, but we don't get timestamps
// from awt. Instead we grab the server and check if the focus changed to avoid a race where our window is made unviewable while focusing it.
grabServer(getDisplay());
try {
if (nGetInputFocus(getDisplay()) == current_focus)
setInputFocus(getDisplay(), getWindow());
} finally {
ungrabServer(getDisplay());
}
}
} }
} }
static native long nGetInputFocus(long display); static native long nGetInputFocus(long display);
private static native void grabServer(long display);
private static native void ungrabServer(long display);
private void releaseInput() { private void releaseInput() {
if (isLegacyFullscreen() || input_released) if (isLegacyFullscreen() || input_released)

View File

@ -327,14 +327,20 @@ static Window createWindow(JNIEnv* env, Display *disp, int screen, jint window_m
return win; return win;
} }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_grabServer(JNIEnv *env, jclass unused, jlong display) {
Display *disp = (Display *)(intptr_t)display;
XGrabServer(disp);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_ungrabServer(JNIEnv *env, jclass unused, jlong display) {
Display *disp = (Display *)(intptr_t)display;
XUngrabServer(disp);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_setInputFocus(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr) { JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_setInputFocus(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr) {
Display *disp = (Display *)(intptr_t)display; Display *disp = (Display *)(intptr_t)display;
Window window = (Window)window_ptr; Window window = (Window)window_ptr;
// Normally, a real time stamp from an event should be passed instead of CurrentTime, but we don't get timestamps
// from awt. Instead we grab the server before and ungrab it after the request
XGrabServer(disp);
XSetInputFocus(disp, window, RevertToParent, CurrentTime); XSetInputFocus(disp, window, RevertToParent, CurrentTime);
XUngrabServer(disp);
} }
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jlong display, jint screen, jobject peer_info_handle, jobject mode, jint window_mode, jint x, jint y, jboolean undecorated, jlong parent_handle) { JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jlong display, jint screen, jobject peer_info_handle, jobject mode, jint window_mode, jint x, jint y, jboolean undecorated, jlong parent_handle) {