java-cef icon indicating copy to clipboard operation
java-cef copied to clipboard

Windows: Browser window always keeps focus

Open magreenblatt opened this issue 7 years ago • 8 comments

Original report by me.


What steps will reproduce the problem?

  1. Create a JCEF application with multiple windows. For example, by applying the attached multiwindow.patch to the detailed sample app.
  2. Click the "createBrowser" button to create the browser window.
  3. 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.

magreenblatt avatar Apr 18 '18 16:04 magreenblatt

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();
		}
	}
});

magreenblatt avatar May 01 '18 23:05 magreenblatt

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
}

magreenblatt avatar Jul 04 '18 07:07 magreenblatt

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)

magreenblatt avatar Jul 04 '18 18:07 magreenblatt

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.

magreenblatt avatar Aug 13 '18 06:08 magreenblatt

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.

magreenblatt avatar Aug 16 '18 17:08 magreenblatt

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

magreenblatt avatar Aug 16 '18 17:08 magreenblatt

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

magreenblatt avatar Aug 17 '18 05:08 magreenblatt

Issue #310 was marked as a duplicate of this issue.

magreenblatt avatar Jul 31 '20 18:07 magreenblatt