# HG changeset patch # User aivanov # Date 1424350232 0 # Node ID 77797a65dc631d67f34992f96c2fc21178c2bbf8 # Parent 57e6ba59a1b3556366268231fa2b5d6d647b8d9e 8056915: Focus lost in applet when browser window is minimized and restored Reviewed-by: ant, dtitov, dcherepanov diff -r 57e6ba59a1b3 -r 77797a65dc63 jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Wed Feb 18 11:15:24 2015 -0800 +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Thu Feb 19 12:50:32 2015 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -686,7 +686,12 @@ if (toFocus != null) { if (parent instanceof EmbeddedFrame) { - ((EmbeddedFrame)parent).synthesizeWindowActivation(true); + // JDK-8056915: Try to request focus to the embedder first and + // activate the embedded frame through it + if (!((EmbeddedFrame) parent).requestFocusToEmbedder()) { + // Otherwise activate the embedded frame directly + ((EmbeddedFrame) parent).synthesizeWindowActivation(true); + } } // EmbeddedFrame might have focus before the applet was added. // Thus after its activation the most recent focus owner will be diff -r 57e6ba59a1b3 -r 77797a65dc63 jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java --- a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java Wed Feb 18 11:15:24 2015 -0800 +++ b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java Thu Feb 19 12:50:32 2015 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -361,6 +361,15 @@ public void synthesizeWindowActivation(boolean doActivate) {} /** + * Requests the focus to the embedder. + * + * @return {@code true} if focus request was successful, and {@code false} otherwise. + */ + public boolean requestFocusToEmbedder() { + return false; + } + + /** * Moves this embedded frame to a new location. The top-left corner of * the new location is specified by the x and y * parameters relative to the native parent component. diff -r 57e6ba59a1b3 -r 77797a65dc63 jdk/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java Wed Feb 18 11:15:24 2015 -0800 +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java Thu Feb 19 12:50:32 2015 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,11 @@ private static int pScale = 0; private static final int MAX_BAND_SIZE = (1024*30); + /** + * This flag is set to {@code true} if this embedded frame is hosted by Internet Explorer. + */ + private boolean isEmbeddedInIE = false; + private static String printScale = AccessController.doPrivileged( new GetPropertyAction("sun.java2d.print.pluginscalefactor")); @@ -244,6 +249,14 @@ } } + @SuppressWarnings("deprecation") + public boolean requestFocusToEmbedder() { + if (isEmbeddedInIE) { + return ((WEmbeddedFramePeer) getPeer()).requestFocusToEmbedder(); + } + return false; + } + public void registerAccelerator(AWTKeyStroke stroke) {} public void unregisterAccelerator(AWTKeyStroke stroke) {} diff -r 57e6ba59a1b3 -r 77797a65dc63 jdk/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java Wed Feb 18 11:15:24 2015 -0800 +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java Thu Feb 19 12:50:32 2015 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,4 +78,11 @@ // false on other systems. return !Win32GraphicsEnvironment.isDWMCompositionEnabled(); } + + /** + * Sets the focus to plugin control window, the parent of embedded frame. + * Eventually, it will synthesizeWindowActivation to activate the embedded frame, + * if plugin control window gets the focus. + */ + public native boolean requestFocusToEmbedder(); } diff -r 57e6ba59a1b3 -r 77797a65dc63 jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp Wed Feb 18 11:15:24 2015 -0800 +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp Thu Feb 19 12:50:32 2015 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,15 @@ HHOOK mouseHook; HHOOK modalHook; }; + + +// Communication with plugin control + +// The value must be the same as in AxControl.h +#define WM_AX_REQUEST_FOCUS_TO_EMBEDDER (WM_USER + 197) + +static bool SetFocusToPluginControl(HWND hwndPlugin); + /************************************************************************ * AwtFrame fields */ @@ -93,6 +102,7 @@ jmethodID AwtFrame::setExtendedStateMID; jmethodID AwtFrame::activateEmbeddingTopLevelMID; +jfieldID AwtFrame::isEmbeddedInIEID; Hashtable AwtFrame::sm_BlockedThreads("AWTBlockedThreads"); @@ -104,6 +114,7 @@ m_parentWnd = NULL; menuBar = NULL; m_isEmbedded = FALSE; + m_isEmbeddedInIE = FALSE; m_isLightweight = FALSE; m_ignoreWmSize = FALSE; m_isMenuDropped = FALSE; @@ -199,6 +210,13 @@ if (isEmbedded) { hwndParent = (HWND)handle; + + // JDK-8056915: Handle focus communication between plugin and frame + frame->m_isEmbeddedInIE = IsEmbeddedInIE(hwndParent); + if (frame->m_isEmbeddedInIE) { + env->SetBooleanField(target, isEmbeddedInIEID, JNI_TRUE); + } + RECT rect; ::GetClientRect(hwndParent, &rect); //Fix for 6328675: SWT_AWT.new_Frame doesn't occupy client area under JDK6 @@ -338,6 +356,21 @@ return frame; } +/* + * Returns true if the frame is embedded into Internet Explorer. + * The function checks the class name of the parent window of the embedded frame. + */ +BOOL AwtFrame::IsEmbeddedInIE(HWND hwndParent) +{ + const char *pluginClass = "Java Plug-in Control Window"; + #define PARENT_CLASS_BUFFER_SIZE 64 + char parentClass[PARENT_CLASS_BUFFER_SIZE]; + + return (::GetClassNameA(hwndParent, parentClass, PARENT_CLASS_BUFFER_SIZE) > 0) + && (strncmp(parentClass, pluginClass, PARENT_CLASS_BUFFER_SIZE) == 0); +} + + LRESULT AwtFrame::ProxyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, MsgRouting &mr) { LRESULT retValue = 0L; @@ -1039,6 +1072,19 @@ if (IsLightweightFrame()) { return TRUE; } + if (isMouseEventCause && IsEmbeddedFrame() && m_isEmbeddedInIE) { + HWND hwndProxy = GetProxyFocusOwner(); + // Do nothing if this frame is focused already + if (::GetFocus() != hwndProxy) { + // Fix for JDK-8056915: + // If window activated with mouse, set focus to plugin control window + // first to preserve focus owner inside browser window + if (SetFocusToPluginControl(::GetParent(GetHWnd()))) { + return TRUE; + } + // Plugin control window is already focused, so do normal processing + } + } return AwtWindow::AwtSetActiveWindow(isMouseEventCause); } @@ -1819,6 +1865,9 @@ AwtFrame::activateEmbeddingTopLevelMID = env->GetMethodID(cls, "activateEmbeddingTopLevel", "()V"); DASSERT(AwtFrame::activateEmbeddingTopLevelMID != NULL); + AwtFrame::isEmbeddedInIEID = env->GetFieldID(cls, "isEmbeddedInIE", "Z"); + DASSERT(AwtFrame::isEmbeddedInIEID != NULL); + CATCH_BAD_ALLOC; } @@ -1911,4 +1960,44 @@ CATCH_BAD_ALLOC; } +JNIEXPORT jboolean JNICALL +Java_sun_awt_windows_WEmbeddedFramePeer_requestFocusToEmbedder(JNIEnv *env, jobject self) +{ + jboolean result = JNI_FALSE; + + TRY; + + AwtFrame *frame = NULL; + + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + frame = (AwtFrame *)pData; + + // JDK-8056915: During initial applet activation, set focus to plugin control window + HWND hwndParent = ::GetParent(frame->GetHWnd()); + + result = SetFocusToPluginControl(hwndParent); + + CATCH_BAD_ALLOC_RET(JNI_FALSE); +ret: + return result; +} + } /* extern "C" */ + +static bool SetFocusToPluginControl(HWND hwndPlugin) +{ + HWND hwndFocus = ::GetFocus(); + + if (hwndFocus == hwndPlugin) { + return false; + } + + ::SetFocus(hwndPlugin); + DWORD dwError = ::GetLastError(); + if (dwError != ERROR_SUCCESS) { + // If direct call failed, use a special message to set focus + return (::SendMessage(hwndPlugin, WM_AX_REQUEST_FOCUS_TO_EMBEDDER, 0, 0) == 0); + } + return true; +} diff -r 57e6ba59a1b3 -r 77797a65dc63 jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.h --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.h Wed Feb 18 11:15:24 2015 -0800 +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.h Thu Feb 19 12:50:32 2015 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,9 @@ /* method id for WEmbeddedFrame.requestActivate() method */ static jmethodID activateEmbeddingTopLevelMID; + /* field id for WEmbeddedFrame.isEmbeddedInIE */ + static jfieldID isEmbeddedInIEID; + AwtFrame(); virtual ~AwtFrame(); @@ -171,6 +174,13 @@ /* The frame is an EmbeddedFrame. */ BOOL m_isEmbedded; + /* Fix for JDK-8056915: + The embedded frame must gain focus by setting focus to its parent. */ + BOOL m_isEmbeddedInIE; + + /* Checks whether the frame is embedded in IE */ + static BOOL IsEmbeddedInIE(HWND hwndParent); + /* The frame is a LightweightFrame */ BOOL m_isLightweight;