Linux: Attempt to avoid race condition when tracking Display parent focus
This commit is contained in:
parent
c499f33bcf
commit
bf25259325
|
@ -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)
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue