IJPL-207199 Popups are shown on top of other windows

In Wayland, focus transfer between windows is not "atomic": indeterminate amount of time can pass between focus lost and gain, and the corresponding even would have null for the 'opposite window' property. When a popup is shown, the keyboard focus remains on the parent window.
 So if a popup is shown as a top-level window, make sure it is NOT canceled on window deactivation.
The existing cancellation logic remains valid for regular popups, however.

GitOrigin-RevId: fd55354e5b3930736c4b7f3442d91d9f96506bd1
This commit is contained in:
Maxim Kartashev
2025-09-16 10:46:38 +00:00
committed by intellij-monorepo-bot
parent 205cd88fa1
commit d281245b4b
5 changed files with 4 additions and 15 deletions
@@ -106,6 +106,7 @@ public final class SearchEverywhereManagerImpl implements SearchEverywhereManage
.setProject(myProject)
.setModalContext(false)
.setNormalWindowLevel(StartupUiUtil.isWaylandToolkit())
.setCancelOnWindowDeactivation(!StartupUiUtil.isWaylandToolkit())
.setCancelOnClickOutside(true)
.setRequestFocus(true)
.setCancelKeyEnabled(false)
@@ -45,19 +45,6 @@ public final class IdePopupManager implements IdeEventQueue.EventDispatcher {
return false;
}
if (StartupUiUtil.isWaylandToolkit()) {
// Reasons for skipping 'focus lost'-like events on Wayland:
// - When a new popup window appears, the main frame looses focus, but the "opposite window"
// for that event is null (because Wayland); this can be solved by waiting a bit
// (several hundreds ms) for
// KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow()
// to become non-null.
// - When a (popup) window is dragged, it also looses focus (because Wayland); this one is
// not solvable because there's no guarantee that the focus will get back, nor is there
// a notification that the drag is actually happening.
return false;
}
if (!isPopupActive()) return false;
Window sourceWindow = ((WindowEvent)e).getWindow();
@@ -359,7 +359,7 @@ object Switcher : BaseSwitcherAction(null) {
.setModalContext(false)
.setFocusable(true)
.setRequestFocus(true)
.setCancelOnWindowDeactivation(true)
.setCancelOnWindowDeactivation(!pinned || !StartupUiUtil.isWaylandToolkit())
.setCancelOnOtherWindowOpen(true)
.setMovable(pinned)
.setDimensionServiceKey(if (pinned) project else null, if (pinned) "SwitcherDM" else null, false)
@@ -394,7 +394,7 @@ object Switcher : BaseSwitcherAction(null), ActionRemoteBehaviorSpecification.Fr
.setModalContext(false)
.setFocusable(true)
.setRequestFocus(true)
.setCancelOnWindowDeactivation(true)
.setCancelOnWindowDeactivation(!pinned || !StartupUiUtil.isWaylandToolkit())
.setCancelOnOtherWindowOpen(true)
.setMovable(pinned)
.setDimensionServiceKey(if (pinned) project else null, if (pinned) "SwitcherDM" else null, false)
@@ -214,6 +214,7 @@ class SeFrontendService(val project: Project?, private val coroutineScope: Corou
.setProject(project)
.setModalContext(false)
.setNormalWindowLevel(StartupUiUtil.isWaylandToolkit())
.setCancelOnWindowDeactivation(!StartupUiUtil.isWaylandToolkit())
.setCancelOnClickOutside(true)
.setRequestFocus(true)
.setCancelKeyEnabled(false)