diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java index 86e92717c3b..2532470f809 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java @@ -87,7 +87,7 @@ public WebViewEnvironment(ICoreWebView2Environment environment) { HashMap navigations = new HashMap<>(); /** Maps BrowserFunction index to the script ID from AddScriptToExecuteOnDocumentCreated. */ private final Map functionScriptIds = new HashMap<>(); - private boolean ignoreGotFocus; + private int ignoreGotFocus; private boolean ignoreFocusIn; private String lastCustomText; @@ -898,7 +898,15 @@ void browserFocusIn(Event event) { // We need to ignore that next event, as in the meantime the user might // have moved focus to some other control and reacting on that event // would bring us back to the Browser. - ignoreGotFocus = true; + // https://github.com/eclipse-platform/eclipse.platform.swt/pull/1849#issuecomment-4753007036 + // There can be multiple focus-in events within the same event loop iteration, + // e.g., + // other.setFocus(); + // browser.setFocus(); + // other.setFocus(); + // browser.setFocus(); + // We need to apply the ignore handling to all of them, so a counter is used. + ignoreGotFocus++; controller.MoveFocus(COM.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); } @@ -1506,8 +1514,8 @@ private void asyncExec(Runnable r) { } int handleGotFocus(long pView, long pArg) { - if (ignoreGotFocus) { - ignoreGotFocus = false; + if (ignoreGotFocus > 0) { + ignoreGotFocus--; return COM.S_OK; } // https://github.com/eclipse-platform/eclipse.platform.swt/issues/1139 diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java index 0edf90a957f..ffef5ae21e7 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java @@ -3095,6 +3095,36 @@ public void test_TimerRegression_Issue2806() { } +/** + * https://github.com/eclipse-platform/eclipse.platform.swt/issues/1848 + * https://github.com/eclipse-platform/eclipse.platform.swt/pull/1849 + * + * Send two focus events to the browser within the same event loop iteration. + * Edge uses + * controller.MoveFocus(COM.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); // + * which triggers then asynchronoulsy. BOTH WebView2 events must then be handled + * (ignored) internally and not cause another call to browserFocusIn(). So we + * expect a total of 2 SWT events (not 3). + */ +@Test +public void test_EdgeAsyncFocusHandling() { + assumeTrue(isEdge, "This test is intended for Edge only"); + + shell.open(); + Text otherControl = new Text(shell, SWT.NONE); + processUiEvents(); + List focusInEvents = new ArrayList<>(); + browser.addListener(SWT.FocusIn, focusInEvents::add); + + otherControl.setFocus(); + browser.setFocus(); + otherControl.setFocus(); + browser.setFocus(); + processUiEvents(); + + assertEquals(2, focusInEvents.size()); +} + /* custom */ /** * Wait for passTest to return true. Timeout otherwise.