On Fri, 11 Sep 2026 05:28:16 GMT, Prasanta Sadhukhan <[email protected]> wrote:
> Few ModalFocusTransferTests tests were failing in macos due to focus not > coming back to expected component. > The `FocusTransferDWFDocModalTest, FocusTransferDWFModelessTest, > FocusTransferDWFNonModalTest` > tests opens in this sequence Dialog → Window → Frame (DWF) and when Frame > closes, > it expects the focus to come back to Window but it goes back to Dialog. > It does not seem to be timing failures as waiting longer in the test doesn't > fix this. > The tests expose a macOS AWT focus-model gap for java.awt.Window. > On macOS, an ordinary Window is treated as a “simple window” > https://github.com/openjdk/jdk/blob/7f068889b2d65a5ae2e10124da0f79eb20067521/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java#L1304-L1306 > A simple Window is deliberately not made the native macOS key window. > Instead, AWT gives native focus to its nearest Frame or Dialog owner, then > synthesizes Java-level focus events for the Window > > When Frame closes, AppKit activates the native Dialog and > `LWWindowPeer.notifyActivation()` translated that Java focus for the Dialog. > But the logical previous focused window was the Window, so its Open button > never regained focus. > > The same issue occurs in the Frame → Window → Dialog (FWD) tests which are > `FocusTransferFWDAppModal*Test, FocusTransferFWDDocModal*Test, > FocusTransferFWDModeless*Test and FocusTransferFWDNonModal*Test` > The native Frame is reactivated after the Dialog closes, but Java focus > should return to the intermediate Window. > > As mentioned, waiting longer in the test doesn't fix this...the wrong Java > focused window is selected deterministically after the native activation > event. > > I tried with a native Cocoa program mimicking Dialog->Window->Frame opening > testing which component regains focus when Frame is closed and it turns out > to be Window unlike Java's Dialog so it is a product issue. > > A product fix is done so that it preserves the existing macOS design—an AWT > Window is still not made natively focusable. > Instead it restores the correct Java-level focus history > When a native Frame or Dialog gains focus while a simple Window has Java > focus, it records that Window as its possible restore target > When the simple Window’s nearest native owner becomes active, > AWT restores Java focus to the remembered Window, but only when it is still > visible, focusable, and unblocked. > > The static handoff reference is made WeakReference as > a strong static reference retained a disposed peer, which retained its > MainFrame and all child components,... I'm struggling to understand this fix. Some of the variable naming may be confusing me. Eg "hiddenFocusedWindow". Why would we restore focus to a hidden window ? What exactly does "hidden" mean here ? Should these be synchronized methods ? I'm not sure if volatile is enough. And the static var worries me .. what if we have two window hierarchies of the pattern Frame -> Window -> Dialog or Dialog -> Window -> Frame or even just one of something like Frame -> Window -> Dialog -> Frame -> Window -> Dialog ------------- PR Comment: https://git.openjdk.org/jdk/pull/32831#issuecomment-5688362943
