Originally this issue was supposed to resolve problems with some system tests 
(`MenuDoubleShortcutTest`, `TextAreaBehaviorTest` and others) failing on my 
Windows machine. In the process of figuring this out I found out the problem is 
Windows `::SetForegroundWindow()` API refusing to give focus to JFX Stage upon 
calling `Stage.show()`.

The problem happened only when running system tests via Gradle, and with more 
investigation it turned out the culprit is actually running tests via a Gradle 
Daemon, which is the default behavior. According to [SetForegroundWindow API 
remarks](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setforegroundwindow)
 there is a list of conditions a process must meet to be granted a privilege of 
receiving focus, which is supposed to prevent focus stealing. While we do meet 
the required conditions, we don't meet "one of" additional conditions listed in 
the reference:
- Gradle daemon is a background process, so tests started by it do not meet 
`The calling process is the foreground process.` and `The calling process was 
started by the foreground process.` conditions
- We most probably run the tests from the terminal, so `There is currently no 
foreground window, and thus no foreground process.` condition fails - the 
foreground window is the Terminal itself.
- Each test has fresh-started JFX stage so `The calling process received the 
last input event.` condition cannot be met and would require either Robot 
workarounds or manual interaction before each test case.
- There is no debugger involved in the process (at least most of the time) so 
`Either the foreground process or the calling process is being debugged.` is 
also not met.

As such, Windows refuses to grant JFX Stage focus, which fails some system 
tests relying on it.

While we cannot remedy these conditions in-code (outside of hacky solutions I 
found with `AttachThreadInput` API which I am not a fan of) the only solution 
seems to be running the tests on Windows via either `gradle --no-daemon` or by 
setting `org.gradle.daemon=false` property somewhere in `gradle.properties`.

In the process of debugging this problem I wrote a canary test to detect 
whether a Stage receives focus right after calling `show()`. I ran this test on 
all (accessible to me) platforms (Windows, Linux, macOS) - on both Linux and 
macOS the test passes regardless of whether the Gradle deamon is used or not. 
On my Windows machine (Win 11 24H2) it fails when testing through Gradle Daemon 
(among tests mentioned in the first paragraph) and succeeds when `--no-daemon` 
flag is used.

I figured the test could be added to the repository and serve as a helper if 
someone else encounters similar problems.

-------------

Commit messages:
 - Add StageFocusTest

Changes: https://git.openjdk.org/jfx/pull/1804/files
  Webrev: https://webrevs.openjdk.org/?repo=jfx&pr=1804&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8351357
  Stats: 116 lines in 1 file changed: 116 ins; 0 del; 0 mod
  Patch: https://git.openjdk.org/jfx/pull/1804.diff
  Fetch: git fetch https://git.openjdk.org/jfx.git pull/1804/head:pull/1804

PR: https://git.openjdk.org/jfx/pull/1804

Reply via email to