Describe the bug
Popups have no mechanism to reduce their maximum width or height based on a provided margin around the window. For context menus where rememberPopupPositionProviderAtPosition() accepts an argument windowMargin, this means that (in 1.4.3) a context menu with a height exceeding the height of the window will be shifted down by this windowMargin but its height will still be the window height.
In 1.5.0-dev1152 the behavior is changed (because PopupLayout now does position.x.coerceIn(0, windowSize.width - contentSize.width)), so that the popup is not cut off, but the windowMargin is no longer respected when the popup size is larger than the window size. Ideally it would coerce the size to windowSize.width - contentSize.width) - 2 * windowMargin at most.
Affected platforms
Desktop
Versions
Kotlin version*: 1.9.0
Compose Multiplatform version*: 1.4.3 and 1.5.0-dev1152
OS version(s)* (required for Desktop and iOS issues): Linux Mint 21.2 Cinnamon
OS architecture (x86 or arm64): x86
JDK (for desktop issues): 11
To Reproduce
This isn't trivial to clearly reproduce since DefaultContextMenuRepresentation doesn't allow configuring the windowMargin and its default of 4 dp is too small to be obviously noticeable. The issue can be demonstrated on the bug/windowMargin branch of my project: https://github.com/dzirbel/compose-material-context-menu/tree/bug/windowMargin with ./gradlew :demo:run.
Expected behavior
Context menu sizes should be bounded by windowSize - 2 * windowMargin. This could be done in a few ways:
Popup() accepts a windowMargin parameter and context menus provide it (from their PopupPositionProviders)
PopupPositionProvider.calculatePosition() returns a Rect instead of an IntOffset and Popup uses the Rect size, allowing arbitrary margins (for example, if a popup wanted more margin on the top than the bottom)
etc
Screenshots
With a windowMargin of 30 dp to make the discrepancy clear (the scrollbar is all the way at the bottom); in 1.4.3:
Describe the bug Popups have no mechanism to reduce their maximum width or height based on a provided margin around the window. For context menus where
rememberPopupPositionProviderAtPosition()
accepts an argumentwindowMargin
, this means that (in 1.4.3) a context menu with a height exceeding the height of the window will be shifted down by thiswindowMargin
but its height will still be the window height.In
1.5.0-dev1152
the behavior is changed (because PopupLayout now doesposition.x.coerceIn(0, windowSize.width - contentSize.width)
), so that the popup is not cut off, but thewindowMargin
is no longer respected when the popup size is larger than the window size. Ideally it would coerce the size towindowSize.width - contentSize.width) - 2 * windowMargin
at most.Affected platforms
Versions
To Reproduce This isn't trivial to clearly reproduce since
DefaultContextMenuRepresentation
doesn't allow configuring thewindowMargin
and its default of 4 dp is too small to be obviously noticeable. The issue can be demonstrated on thebug/windowMargin
branch of my project: https://github.com/dzirbel/compose-material-context-menu/tree/bug/windowMargin with./gradlew :demo:run
.Of note:
windowMargin
is provided at 30 dp hereExpected behavior Context menu sizes should be bounded by
windowSize - 2 * windowMargin
. This could be done in a few ways:Popup()
accepts awindowMargin
parameter and context menus provide it (from theirPopupPositionProvider
s)PopupPositionProvider.calculatePosition()
returns aRect
instead of anIntOffset
andPopup
uses theRect
size, allowing arbitrary margins (for example, if a popup wanted more margin on the top than the bottom)Screenshots With a
windowMargin
of 30 dp to make the discrepancy clear (the scrollbar is all the way at the bottom); in 1.4.3:and in 1.5.0-dev1152:
Additional context See also discussion in https://github.com/JetBrains/compose-multiplatform/issues/3493; cc @m-sasha