LinuxDisplay - fix remaining issues with focus handling when running in xembed mode.
This commit is contained in:
parent
7782156962
commit
e49bfe3c40
|
@ -136,11 +136,14 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
private boolean close_requested;
|
private boolean close_requested;
|
||||||
private long current_cursor;
|
private long current_cursor;
|
||||||
private long blank_cursor;
|
private long blank_cursor;
|
||||||
|
private boolean mouseInside = true;
|
||||||
|
|
||||||
private Canvas parent;
|
private Canvas parent;
|
||||||
private long parent_window;
|
private long parent_window;
|
||||||
private boolean xembedded;
|
private boolean xembedded;
|
||||||
private boolean parent_focus;
|
private long parent_proxy_focus_window;
|
||||||
private boolean mouseInside = true;
|
private boolean parent_focused;
|
||||||
|
private long last_window_focus = 0;
|
||||||
|
|
||||||
private LinuxKeyboard keyboard;
|
private LinuxKeyboard keyboard;
|
||||||
private LinuxMouse mouse;
|
private LinuxMouse mouse;
|
||||||
|
@ -148,12 +151,12 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
private final FocusListener focus_listener = new FocusListener() {
|
private final FocusListener focus_listener = new FocusListener() {
|
||||||
public void focusGained(FocusEvent e) {
|
public void focusGained(FocusEvent e) {
|
||||||
synchronized (GlobalLock.lock) {
|
synchronized (GlobalLock.lock) {
|
||||||
focused = true;
|
parent_focused = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void focusLost(FocusEvent e) {
|
public void focusLost(FocusEvent e) {
|
||||||
synchronized (GlobalLock.lock) {
|
synchronized (GlobalLock.lock) {
|
||||||
focused = false;
|
parent_focused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -460,9 +463,7 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.addFocusListener(focus_listener);
|
parent.addFocusListener(focus_listener);
|
||||||
if (parent.isFocusOwner()) {
|
if (parent.isFocusOwner()) {
|
||||||
nGrabKeyboard(getDisplay(), current_window);
|
parent_focused = true;
|
||||||
focused = true;
|
|
||||||
input_released = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -480,8 +481,11 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
private static native long getRootWindow(long display, int screen);
|
private static native long getRootWindow(long display, int screen);
|
||||||
private static native boolean hasProperty(long display, long window, long property);
|
private static native boolean hasProperty(long display, long window, long property);
|
||||||
private static native long getParentWindow(long display, long window) throws LWJGLException;
|
private static native long getParentWindow(long display, long window) throws LWJGLException;
|
||||||
|
private static native int getChildCount(long display, long window) throws LWJGLException;
|
||||||
private static native void mapRaised(long display, long window);
|
private static native void mapRaised(long display, long window);
|
||||||
private static native void reparentWindow(long display, long window, long parent, int x, int y);
|
private static native void reparentWindow(long display, long window, long parent, int x, int y);
|
||||||
|
private static native long nGetInputFocus(long display) throws LWJGLException;
|
||||||
|
private static native void nSetInputFocus(long display, long window, long time);
|
||||||
|
|
||||||
private static boolean isAncestorXEmbedded(long window) throws LWJGLException {
|
private static boolean isAncestorXEmbedded(long window) throws LWJGLException {
|
||||||
long xembed_atom = internAtom("_XEMBED_INFO", true);
|
long xembed_atom = internAtom("_XEMBED_INFO", true);
|
||||||
|
@ -743,8 +747,6 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
return peer_info;
|
return peer_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static native void setInputFocus(long display, long window, long time);
|
|
||||||
|
|
||||||
private void relayEventToParent(LinuxEvent event_buffer, int event_mask) {
|
private void relayEventToParent(LinuxEvent event_buffer, int event_mask) {
|
||||||
tmp_event_buffer.copyFrom(event_buffer);
|
tmp_event_buffer.copyFrom(event_buffer);
|
||||||
tmp_event_buffer.setWindow(parent_window);
|
tmp_event_buffer.setWindow(parent_window);
|
||||||
|
@ -904,17 +906,92 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
private void checkInput() {
|
private void checkInput() {
|
||||||
if (parent == null) return;
|
if (parent == null) return;
|
||||||
|
|
||||||
if (focused != keyboard_grabbed) {
|
if (xembedded) {
|
||||||
if (focused) {
|
long current_focus_window = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
current_focus_window = nGetInputFocus(getDisplay());
|
||||||
|
} catch (LWJGLException e) {
|
||||||
|
return; // fail silently as it can fail whilst splitting browser tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_window_focus != current_focus_window || parent_focused != focused) {
|
||||||
|
if (isParentWindowActive(current_focus_window)) {
|
||||||
|
if (parent_focused) {
|
||||||
|
nSetInputFocus(getDisplay(), current_window, CurrentTime);
|
||||||
|
last_window_focus = current_window;
|
||||||
|
focused = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// return focus to the parent proxy focus window
|
||||||
|
nSetInputFocus(getDisplay(), parent_proxy_focus_window, CurrentTime);
|
||||||
|
last_window_focus = parent_proxy_focus_window;
|
||||||
|
focused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last_window_focus = current_focus_window;
|
||||||
|
focused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (parent_focused != keyboard_grabbed) {
|
||||||
|
if (parent_focused) {
|
||||||
grabKeyboard();
|
grabKeyboard();
|
||||||
input_released = false;
|
input_released = false;
|
||||||
|
focused = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ungrabKeyboard();
|
ungrabKeyboard();
|
||||||
input_released = true;
|
input_released = true;
|
||||||
|
focused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will check if the parent window is active when running
|
||||||
|
* in xembed mode. Every xembed embedder window has a focus proxy
|
||||||
|
* window that recieves all the input. This method will test whether
|
||||||
|
* the provided window handle is the focus proxy, if so it will get its
|
||||||
|
* parent window and then test whether this is indeed the window that
|
||||||
|
* belongs to our current_window. If so then parent window is active.
|
||||||
|
*
|
||||||
|
* @param window - the window handle to test
|
||||||
|
*/
|
||||||
|
private boolean isParentWindowActive(long window) {
|
||||||
|
try {
|
||||||
|
// parent window already active as window is current_window
|
||||||
|
if (window == current_window) return true;
|
||||||
|
|
||||||
|
// xembed focus proxy will have no children
|
||||||
|
if (getChildCount(getDisplay(), window) != 0) return false;
|
||||||
|
|
||||||
|
// get parent, will be xembed embedder window and ancestor of current_window
|
||||||
|
long parent_window = getParentWindow(getDisplay(), window);
|
||||||
|
|
||||||
|
// parent must not be None
|
||||||
|
if (parent_window == None) return false;
|
||||||
|
|
||||||
|
// scroll current_window's ancestors to find parent_window
|
||||||
|
long w = current_window;
|
||||||
|
|
||||||
|
while (w != None) {
|
||||||
|
w = getParentWindow(getDisplay(), w);
|
||||||
|
if (w == parent_window) {
|
||||||
|
parent_proxy_focus_window = window; // save focus proxy window
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (LWJGLException e) {
|
||||||
|
LWJGLUtil.log("Failed to detect if parent window is active: " + e.getMessage());
|
||||||
|
return true; // on failure assume still active
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // failed to find an active parent window
|
||||||
|
}
|
||||||
|
|
||||||
private void setFocused(boolean got_focus, int focus_detail) {
|
private void setFocused(boolean got_focus, int focus_detail) {
|
||||||
if (focused == got_focus || focus_detail == NotifyDetailNone || focus_detail == NotifyPointer || focus_detail == NotifyPointerRoot || parent != null)
|
if (focused == got_focus || focus_detail == NotifyDetailNone || focus_detail == NotifyPointer || focus_detail == NotifyPointerRoot || parent != null)
|
||||||
|
@ -929,8 +1006,6 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static native long nGetInputFocus(long display);
|
|
||||||
|
|
||||||
private void releaseInput() {
|
private void releaseInput() {
|
||||||
if (isLegacyFullscreen() || input_released)
|
if (isLegacyFullscreen() || input_released)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -380,6 +380,22 @@ JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getParentWindow(JNIEn
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getChildCount(JNIEnv *env, jclass unused, jlong display, jlong window_ptr) {
|
||||||
|
Display *disp = (Display *)(intptr_t)display;
|
||||||
|
Window window = (Window)window_ptr;
|
||||||
|
Window root, parent;
|
||||||
|
Window *children;
|
||||||
|
unsigned int nchildren;
|
||||||
|
if (XQueryTree(disp, window, &root, &parent, &children, &nchildren) == 0) {
|
||||||
|
throwException(env, "XQueryTree failed");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if (children != NULL)
|
||||||
|
XFree(children);
|
||||||
|
|
||||||
|
return nchildren;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_hasProperty(JNIEnv *env, jclass unusued, jlong display, jlong window_ptr, jlong property_ptr) {
|
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_hasProperty(JNIEnv *env, jclass unusued, jlong display, jlong window_ptr, jlong property_ptr) {
|
||||||
Display *disp = (Display *)(intptr_t)display;
|
Display *disp = (Display *)(intptr_t)display;
|
||||||
Window window = (Window)window_ptr;
|
Window window = (Window)window_ptr;
|
||||||
|
@ -399,7 +415,15 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_hasProperty(JNIEnv
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_setInputFocus(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr, jlong time) {
|
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetInputFocus(JNIEnv *env, jclass unused, jlong display_ptr) {
|
||||||
|
Display *disp = (Display *)(intptr_t)display_ptr;
|
||||||
|
int revert_mode;
|
||||||
|
Window win;
|
||||||
|
XGetInputFocus(disp, &win, &revert_mode);
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetInputFocus(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr, jlong time) {
|
||||||
Display *disp = (Display *)(intptr_t)display;
|
Display *disp = (Display *)(intptr_t)display;
|
||||||
Window window = (Window)window_ptr;
|
Window window = (Window)window_ptr;
|
||||||
XSetInputFocus(disp, window, RevertToParent, time);
|
XSetInputFocus(disp, window, RevertToParent, time);
|
||||||
|
@ -574,14 +598,6 @@ JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateBlankCursor(JN
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetInputFocus(JNIEnv *env, jclass unused, jlong display_ptr) {
|
|
||||||
Display *disp = (Display *)(intptr_t)display_ptr;
|
|
||||||
int revert_mode;
|
|
||||||
Window win;
|
|
||||||
XGetInputFocus(disp, &win, &revert_mode);
|
|
||||||
return win;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIconifyWindow(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jint screen) {
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIconifyWindow(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jint screen) {
|
||||||
Display *disp = (Display *)(intptr_t)display_ptr;
|
Display *disp = (Display *)(intptr_t)display_ptr;
|
||||||
Window win = (Window)window_ptr;
|
Window win = (Window)window_ptr;
|
||||||
|
|
Loading…
Reference in New Issue