From: <ka...@us...> - 2011-07-02 20:50:33
|
Revision: 3555 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3555&view=rev Author: kappa1 Date: 2011-07-02 20:50:27 +0000 (Sat, 02 Jul 2011) Log Message: ----------- LinuxDisplay - fix remaining issues with focus handling when running in xembed mode. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2011-06-26 11:50:23 UTC (rev 3554) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2011-07-02 20:50:27 UTC (rev 3555) @@ -136,11 +136,14 @@ private boolean close_requested; private long current_cursor; private long blank_cursor; + private boolean mouseInside = true; + private Canvas parent; private long parent_window; private boolean xembedded; - private boolean parent_focus; - private boolean mouseInside = true; + private long parent_proxy_focus_window; + private boolean parent_focused; + private long last_window_focus = 0; private LinuxKeyboard keyboard; private LinuxMouse mouse; @@ -148,12 +151,12 @@ private final FocusListener focus_listener = new FocusListener() { public void focusGained(FocusEvent e) { synchronized (GlobalLock.lock) { - focused = true; + parent_focused = true; } } public void focusLost(FocusEvent e) { synchronized (GlobalLock.lock) { - focused = false; + parent_focused = false; } } }; @@ -460,9 +463,7 @@ if (parent != null) { parent.addFocusListener(focus_listener); if (parent.isFocusOwner()) { - nGrabKeyboard(getDisplay(), current_window); - focused = true; - input_released = false; + parent_focused = true; } } } finally { @@ -480,9 +481,12 @@ private static native long getRootWindow(long display, int screen); 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 int getChildCount(long display, long window) throws LWJGLException; 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 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 { long xembed_atom = internAtom("_XEMBED_INFO", true); if (xembed_atom != None) { @@ -743,8 +747,6 @@ return peer_info; } - static native void setInputFocus(long display, long window, long time); - private void relayEventToParent(LinuxEvent event_buffer, int event_mask) { tmp_event_buffer.copyFrom(event_buffer); tmp_event_buffer.setWindow(parent_window); @@ -900,22 +902,97 @@ unlockAWT(); } } - + private void checkInput() { if (parent == null) return; - if (focused != keyboard_grabbed) { - if (focused) { - grabKeyboard(); - input_released = false; + if (xembedded) { + 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 } - else { - ungrabKeyboard(); - input_released = true; + + 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(); + input_released = false; + focused = true; + } + else { + ungrabKeyboard(); + 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) { if (focused == got_focus || focus_detail == NotifyDetailNone || focus_detail == NotifyPointer || focus_detail == NotifyPointerRoot || parent != null) return; @@ -928,8 +1005,6 @@ releaseInput(); } } - - static native long nGetInputFocus(long display); private void releaseInput() { if (isLegacyFullscreen() || input_released) Modified: trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c =================================================================== --- trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c 2011-06-26 11:50:23 UTC (rev 3554) +++ trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c 2011-07-02 20:50:27 UTC (rev 3555) @@ -380,6 +380,22 @@ 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) { Display *disp = (Display *)(intptr_t)display; Window window = (Window)window_ptr; @@ -399,7 +415,15 @@ 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; Window window = (Window)window_ptr; XSetInputFocus(disp, window, RevertToParent, time); @@ -574,14 +598,6 @@ 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) { Display *disp = (Display *)(intptr_t)display_ptr; Window win = (Window)window_ptr; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |