From 1e719c19c9f579a1658b46f63defec916c4a7480 Mon Sep 17 00:00:00 2001 From: Sergei Tachenov Date: Thu, 15 Jan 2026 16:16:30 +0200 Subject: [PATCH] [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 --- .../com/intellij/openapi/ui/JBPopupMenu.java | 2 ++ .../src/META-INF/PlatformExtensions.xml | 1 + .../src/com/intellij/util/ui/WaylandUtil.kt | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/JBPopupMenu.java b/platform/platform-api/src/com/intellij/openapi/ui/JBPopupMenu.java index 057305e81bdb..d73446e5edb3 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/JBPopupMenu.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/JBPopupMenu.java @@ -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; diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index af3591c96f8d..4d298d99a01f 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -1836,6 +1836,7 @@ key="settings.name" bundle="messages.MinimapBundle"/> + diff --git a/platform/util/ui/src/com/intellij/util/ui/WaylandUtil.kt b/platform/util/ui/src/com/intellij/util/ui/WaylandUtil.kt index c5649a255fd1..80dd132cce77 100644 --- a/platform/util/ui/src/com/intellij/util/ui/WaylandUtil.kt +++ b/platform/util/ui/src/com/intellij/util/ui/WaylandUtil.kt @@ -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) {