[UI, Wayland] IJPL-222615 Introduce wayland.screen.vInsets

A workaround around the fact that the screen insets are always
zero on Wayland even if they're non-zero in reality.

Applied only to menus because it's too dangerous to apply
it platform-wide to getScreenInsets: in some places,
like the main window positioning, for example,
it's not desirable to create fake insets that would prevent
maximizing the IDE window.

GitOrigin-RevId: 1e74406a37c2e4db2c0d65d0082102afbf148bf4
This commit is contained in:
Sergei Tachenov
2026-01-16 09:42:42 +00:00
committed by intellij-monorepo-bot
parent e5820febc7
commit 1e719c19c9
3 changed files with 24 additions and 0 deletions
@@ -11,6 +11,7 @@ import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.TimerUtil;
import com.intellij.util.ui.WaylandUtilKt;
import com.intellij.util.ui.update.UiNotifyConnector;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -349,6 +350,7 @@ public class JBPopupMenu extends JPopupMenu {
}
if (configuration == null) return Short.MAX_VALUE;
Rectangle screenRectangle = ScreenUtil.getScreenRectangle(configuration);
WaylandUtilKt.addFakeScreenInsets(screenRectangle);
if (invoker != null && invoker.getParent() instanceof JMenuBar) {
var menuItemHeight = invoker.getSize().height;
@@ -1836,6 +1836,7 @@
key="settings.name" bundle="messages.MinimapBundle"/>
<registryKey key="popup.advertiser.speed.search" defaultValue="false" description="Shows speed search advertiser in popups"/>
<registryKey key="wayland.true.popups" defaultValue="true" description="Show popups in Wayland as true popups (allows remembering the location, but limits them to the IDE window)"/>
<registryKey key="wayland.screen.vInsets" defaultValue="50" description="The sum of vertical screen insets (top + bottom) assumed for Wayland (because it doesn't report the actual insets)"/>
<actionPromoter implementation="com.intellij.ide.actions.speedSearch.SpeedSearchActionPromoter"/>
<fileEditorProvider id="learnIde" implementation="com.intellij.openapi.wm.impl.welcomeScreen.learnIde.editorTab.LearnIdeFileEditorProvider"/>
@@ -3,6 +3,7 @@ package com.intellij.util.ui
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.diagnostic.fileLogger
import com.intellij.openapi.util.registry.Registry
import com.intellij.ui.ComponentUtil
import org.jetbrains.annotations.ApiStatus
import java.awt.Component
@@ -103,6 +104,26 @@ fun getNearestTopLevelAncestor(component: Component): Component? {
}
}
/**
* Slightly decreases the screen height on Wayland.
*
* Because Wayland doesn't report the actual screen insets,
* for some use cases, like trying to determine the maximum height of some menu or popup,
* the maximum size can be larger than the actual available screen space.
* This function applies a workaround for this problem by subtracting some fixed
* amount of space from the screen height.
*
* Does nothing if not running under the native Wayland toolkit.
*/
@ApiStatus.Internal
fun addFakeScreenInsets(rectangle: Rectangle) {
if (!StartupUiUtil.isWaylandToolkit()) return
val total = JBUI.scale(Registry.intValue("wayland.screen.vInsets", defaultValue = 50, minValue = 0, maxValue = 300))
val top = total / 2
rectangle.y += top
rectangle.height -= total
}
private fun fitValue(location: Int, width: Int, start1: Int, end1: Int, start2: Int, end2: Int, preferLess: Boolean): Int {
LOG.debug { "The available intervals are $start1..$end1 and $start2..$end2, the popup size is $width" }
if (location >= start1 && location + width < end1) {