JDK-6595651 : Focus transfers broken for applications embedding AWT across processes
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows
  • CPU: generic
  • Submitted: 2007-08-22
  • Updated: 2008-04-23
  • Resolved: 2008-04-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u10Resolved 7 b25Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
The fixes for 6458497 and 6506966 that went into the Windows port of awt_Component.cpp have broken focus transfers in the new out-of-process Java Plug-In. The basic problem is that the AWT EmbeddedFrame is placed into the component hierarchy of the browser, which is now a different process. When we attempt to transfer focus to the applet, the code in AwtComponent::AwtSetFocus() sees that the current focus owner's process ID is different from the Java process and blocks the focus transfer.

Discussion with ###@###.### and others indicates that to cover this case, as well as the case where the out-of-process applet opens a top-level frame, the following logic is needed. When an EmbeddedFrame (WEmbeddedFrame) is created, it should record the process ID of the HWND into which it is embedded. Future focus transfers should be permitted from that process ID to the one of the Java process.

Comments
SUGGESTED FIX --- /export/work/son/tests/java/awt/6595651/v0/webrev/./src/windows/native/sun/windows/awt_Frame.cpp- 2007-09-13 14:09:42.000000000 +0400 +++ awt_Frame.cpp 2007-09-04 11:23:03.000000000 +0400 @@ -184,20 +184,20 @@ if (handle != 0) { isEmbedded = TRUE; } } frame->m_isEmbedded = isEmbedded; - - if (isEmbedded) { + + if (isEmbedded) { hwndParent = (HWND)handle; RECT rect; ::GetClientRect(hwndParent, &rect); //Fix for 6328675: SWT_AWT.new_Frame doesn't occupy client area under JDK6 frame->m_isUndecorated = true; - /* + /* * Fix for BugTraq ID 4337754. - * Initialize m_peerObject before the first call + * Initialize m_peerObject before the first call * to AwtFrame::GetClassName(). */ frame->m_peerObject = env->NewGlobalRef(self); frame->RegisterClass(); DWORD exStyle = WS_EX_NOPARENTNOTIFY; @@ -219,33 +219,34 @@ frame->LinkObjects(env, self); frame->SubclassHWND(); // Update target's dimensions to reflect this embedded window. ::GetClientRect(frame->m_hwnd, &rect); - ::MapWindowPoints(frame->m_hwnd, hwndParent, (LPPOINT)&rect, - 2); + ::MapWindowPoints(frame->m_hwnd, hwndParent, (LPPOINT)&rect, 2); env->SetIntField(target, AwtComponent::xID, rect.left); env->SetIntField(target, AwtComponent::yID, rect.top); env->SetIntField(target, AwtComponent::widthID, rect.right-rect.left); env->SetIntField(target, AwtComponent::heightID, rect.bottom-rect.top); frame->InitPeerGraphicsConfig(env, self); - } else { - jint state = env->GetIntField(target, AwtFrame::stateID); - DWORD exStyle; - DWORD style; + + AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent); + } else { + jint state = env->GetIntField(target, AwtFrame::stateID); + DWORD exStyle; + DWORD style; // for input method windows, use minimal decorations inputMethodWindowCls = env->FindClass("sun/awt/im/InputMethodWindow"); if ((inputMethodWindowCls != NULL) && env->IsInstanceOf(target, inputMethodWindowCls)) { //for below-the-spot composition window, use no decoration if (env->GetBooleanField(target, AwtFrame::undecoratedID) == JNI_TRUE){ exStyle = 0; style = WS_POPUP|WS_CLIPCHILDREN; - frame->m_isUndecorated = TRUE; + frame->m_isUndecorated = TRUE; } else { exStyle = WS_EX_PALETTEWINDOW; style = WS_CLIPCHILDREN; } frame->m_isInputMethodWindow = TRUE; --- /export/work/son/tests/java/awt/6595651/v0/webrev/./src/windows/native/sun/windows/awt_Toolkit.h- 2007-09-13 14:09:42.000000000 +0400 +++ awt_Toolkit.h 2007-09-04 11:23:55.000000000 +0400 @@ -424,21 +424,28 @@ WM_PALETTECHANGED event from occurring immediately after a WM_DISPLAYCHANGED event. */ private: BOOL m_displayChanged; /* Tracks displayChanged events */ + // 0 means we are not embedded. + DWORD m_embedderProcessID; public: BOOL HasDisplayChanged() { return m_displayChanged; } void ResetDisplayChanged() { m_displayChanged = FALSE; } + void RegisterEmbedderProcessId(HWND); + BOOL IsEmbedderProcessId(const DWORD processID) const + { + return m_embedderProcessID && (processID == m_embedderProcessID); + } private: static JNIEnv *m_env; static HANDLE m_thread; public: static void SetEnv(JNIEnv *env); - static JNIEnv* GetEnv(); + static JNIEnv* GetEnv(); }; /* * Class to encapsulate the extraction of the java string contents * into a buffer and the cleanup of the buffer --- /export/work/son/tests/java/awt/6595651/v0/webrev/./src/windows/native/sun/windows/awt_Toolkit.cpp- 2007-09-13 14:09:42.000000000 +0400 +++ awt_Toolkit.cpp 2007-09-04 11:22:07.000000000 +0400 @@ -352,10 +352,11 @@ m_pModalDialog = NULL; m_peer = NULL; m_dllHandle = NULL; m_displayChanged = FALSE; + m_embedderProcessID = 0; // XXX: keyboard mapping should really be moved out of AwtComponent AwtComponent::InitDynamicKeyMapTable(); // initialize kb state array @@ -1440,53 +1441,27 @@ // Should never get here. DASSERT(FALSE); } } -/* - * Returns a reference to the class java.awt.Component. - */ -jclass -getComponentClass(JNIEnv *env) +// for now we support only one embedder, but should be ready for future +void AwtToolkit::RegisterEmbedderProcessId(HWND embedder) { - static jclass componentCls = NULL; - - // get global reference of java/awt/Component class (run only once) - if (componentCls == NULL) { - jclass componentClsLocal = env->FindClass("java/awt/Component"); - DASSERT(componentClsLocal != NULL); - if (componentClsLocal == NULL) { - /* exception already thrown */ - return NULL; - } - componentCls = (jclass)env->NewGlobalRef(componentClsLocal); - env->DeleteLocalRef(componentClsLocal); + if (m_embedderProcessID) { + // we already set embedder process and do not expect + // two different processes to embed the same AwtToolkit + return; } - return componentCls; -} - - -/* - * Returns a reference to the class java.awt.MenuComponent. - */ -jclass -getMenuComponentClass(JNIEnv *env) -{ - static jclass menuComponentCls = NULL; - - // get global reference of java/awt/MenuComponent class (run only once) - if (menuComponentCls == NULL) { - jclass menuComponentClsLocal = env->FindClass("java/awt/MenuComponent"); - DASSERT(menuComponentClsLocal != NULL); - if (menuComponentClsLocal == NULL) { - /* exception already thrown */ - return NULL; + while((::GetWindowLong(embedder, GWL_STYLE) & WS_CHILD) == WS_CHILD) + { + HWND parent = ::GetParent(embedder); + if (NULL == parent) { + break; } - menuComponentCls = (jclass)env->NewGlobalRef(menuComponentClsLocal); - env->DeleteLocalRef(menuComponentClsLocal); + embedder = parent; } - return menuComponentCls; + ::GetWindowThreadProcessId(embedder, &m_embedderProcessID); } JNIEnv* AwtToolkit::m_env; HANDLE AwtToolkit::m_thread; --- /export/work/son/tests/java/awt/6595651/v0/webrev/./src/windows/native/sun/windows/awt_Component.cpp- 2007-09-13 14:09:43.000000000 +0400 +++ awt_Component.cpp 2007-09-04 12:44:31.000000000 +0400 @@ -2188,12 +2188,15 @@ HWND fgWindow = ::GetForegroundWindow(); if (NULL != fgWindow) { DWORD fgProcessID; ::GetWindowThreadProcessId(fgWindow, &fgProcessID); - if (fgProcessID != ::GetCurrentProcessId()) { - // fix for 6458497. we shouldn't request focus if it is out of our application. + if (fgProcessID != ::GetCurrentProcessId() + && !AwtToolkit::GetInstance().IsEmbedderProcessId(fgProcessID)) + { + // fix for 6458497. we shouldn't request focus if it is out of both + // our and embedder process. return FALSE; } } AwtFrame *owner = GetContainer()->GetOwningFrameOrDialog();
30-08-2007

EVALUATION we just disallow cross-process focus requests, to fix the problem we should be more flexible.
29-08-2007

EVALUATION Description contains good explanation of the cause of the problem.
27-08-2007