java-cef
                                
                                 java-cef copied to clipboard
                                
                                    java-cef copied to clipboard
                            
                            
                            
                        Windows: Browser window always keeps focus
Original report by me.
What steps will reproduce the problem?
- Create a JCEF application with multiple windows. For example, by applying the attached multiwindow.patch to the detailed sample app.
- Click the "createBrowser" button to create the browser window.
- Try to focus the Java Application Window.
What is the expected output? What do you see instead?
It should be possible to switch focus between the Java windows. Instead, the browser window always keeps focus.
What version of the product are you using? On what operating system?
Current master build on Windows 10.
The problem is due to the FocusParent call in Java_org_cef_browser_CefBrowser_1N_N_1SetFocus: https://bitbucket.org/chromiumembedded/java-cef/src/694bda5a7d1c006c982fd0254a2195d28e2f7074/native/CefBrowser_N.cpp?at=master&fileviewer=file-view-default#CefBrowser_N.cpp-1269
Commenting out that call will work around the problem.
Original comment by Andrei Pivkine (Bitbucket: andreiPiv, GitHub: andreiPiv).
Much thanks, I will give the workaround a try.
I also found some issues between 1 Browser in 1 Java window focus issue
The current workaround I'm using in Java:
#!java
final KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
	
focusManager.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() {
			
	 boolean cefWasPermanentFocusOwner = false;
	 
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		System.out.println("Perm Focus Owner: " + focusManager.getPermanentFocusOwner());
		System.out.println("Focus Owner: " + focusManager.getFocusOwner());
		if (ChromiumBrowser.isInternalCefCanvas(evt.getOldValue())) {
			cefWasPermanentFocusOwner = true;
			return;
		}
		
		if(evt.getOldValue() instanceof Component) {
			
			Component c = (Component)evt.getOldValue();
			
                       //Currently browsers are given name "CEFBrowser"
			if(c.getName() == "CEFBrowser") { 
				System.out.println("CEF browser found!");
				cefWasPermanentFocusOwner = true;
			}
		}
		if (!cefWasPermanentFocusOwner)
			return;
		if (!(evt.getNewValue() instanceof Component))
			return;
		
		final Component newValue = (Component)evt.getNewValue();
		Class<? extends Component> clazz = newValue.getClass();
		if (JTextComponent.class.isAssignableFrom(clazz) || JComboBox.class.isAssignableFrom(clazz)) {
			cefWasPermanentFocusOwner = false;
			System.out.println("Resetting the owner!");
			focusManager.clearGlobalFocusOwner();
			newValue.requestFocusInWindow();
		}
	}
});
Original comment by János Gerevich (Bitbucket: JohnTheHun, GitHub: JohnTheHun).
I commented it the line you were referring to, but getting focus in a multi-window environment is still not working good: i have to click multiple times until the other window finally receives focus and comes to front.
(I didn't use / do anything with your attached patch file, I just ran the following under java-cef\src\tools
run.bat win64 Release detailed
and used the test menu / new window )
My Java_org_cef_browser_CefBrowser_1N_N_1SetFocus looks like this:
#!c++
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1SetFocus(JNIEnv* env,
                                               jobject obj,
                                               jboolean enable) {
  CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
  if (browser->GetHost()->IsWindowRenderingDisabled()) {
    browser->GetHost()->SendFocusEvent(enable != JNI_FALSE);
  } else {
    browser->GetHost()->SetFocus(enable != JNI_FALSE);
  }
#if defined(OS_WIN)
  if (enable == JNI_FALSE) {
    HWND browserHandle = browser->GetHost()->GetWindowHandle();
    if (CefCurrentlyOn(TID_UI)) {
      //FocusParent(browserHandle);
    } else
      CefPostTask(TID_UI, base::Bind(&FocusParent, browserHandle));
  }
#endif
}
Original comment by János Gerevich (Bitbucket: JohnTheHun, GitHub: JohnTheHun).
Can any of you upload or send me a 64bit jcef.dll which by your experience handles window focus with multiple browser windows correctly? So I can test it in my environment. (JCEF Version: 3.3396.184.gc995bbd, CEF Version: 3.3396.1775.g5340bb0)
Original comment by Mike van Afferden (Bitbucket: locosmike, GitHub: locosmike).
We've had a similar issue to this one in our JCEF app (we only use a single Java window in our app): Once the JCEF browser window looses focus, the app icon on the task bar at the bottom of the screen (Windows 10 Pro x64) starts blinking. This usually happens, when an application in the background requests focus.
We fixed the issues by changing the if condition in line 1270 of Java_org_cef_browser_CefBrowser_1N_N_1SetFocus to if (enable != JNI_FALSE). We guess that it was a typo in the code as this change fixed the behaviour of our JCEF app.
You can see the change in our forked repository at GitHub. We also cloned the AppVeyor project of guusdk so you can check out the resulting binary distribution files too.
Original comment by János Gerevich (Bitbucket: JohnTheHun, GitHub: JohnTheHun).
Many thanks, Mike's solution seems to work for me. I hope this doesn't ruin anything important.
Original comment by Andrei Pivkine (Bitbucket: andreiPiv, GitHub: andreiPiv).
There is also another FocusParent code in focus_handler.cpp
There is also an issue where FocusParent might be called on a component that is not visible. This can cause an issue with focus and appear to hang the Java application.
My solution was to remove both FocusParent calls and handling setting focus to the parent in Java
Original comment by János Gerevich (Bitbucket: JohnTheHun, GitHub: JohnTheHun).
Andrei, is this focus handling java code the code you pasted a few comments before? In focus_handler.cpp did you just comment out the 64. line "FocusParent(browserHandle);" ? Could you paste the code you now use in focus_handler.cpp? Thanks
Issue #310 was marked as a duplicate of this issue.