Give notification popups a fixed-size surface to stop resize scaling

The popups used one Wayland layer surface per output sized to their content
(implicitWidth/Height bound to the toast column), so every time a toast was
added or removed the surface resized. During that resize the compositor
briefly scaled a stale buffer, stretching or squishing the cards mid-
transition -- worst with only one or two toasts, where each resize is a
larger relative change.

Make the surface full-screen and fixed, like the OSD overlay, so adding or
removing a toast only changes the content inside it and the surface never
resizes. Mask the input region to the toast column so the otherwise-
invisible full-screen overlay stays click-through.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scott Jones
2026-07-24 11:47:53 -04:00
co-authored by Claude Opus 4.8
parent 2c8639ffbd
commit b1a9d7912e
+15 -14
View File
@@ -787,26 +787,27 @@ Item {
readonly property var popupPlacement: NotificationLogic.popupPlacement(
service.barPosition, service.barClearance, Style.gapsOut)
anchors {
top: popupWindow.popupPlacement.anchors.top
bottom: popupWindow.popupPlacement.anchors.bottom
left: popupWindow.popupPlacement.anchors.left
right: popupWindow.popupPlacement.anchors.right
}
margins {
top: popupWindow.popupPlacement.margins.top
bottom: popupWindow.popupPlacement.margins.bottom
left: popupWindow.popupPlacement.margins.left
right: popupWindow.popupPlacement.margins.right
}
// Full-screen, fixed-size surface (like the OSD overlay). Adding or
// removing a toast changes only the content inside; the Wayland surface
// never resizes, so the compositor can't briefly scale a stale buffer --
// which is what stretched/squished the cards during count changes.
anchors { top: true; bottom: true; left: true; right: true }
implicitWidth: popupColumn.implicitWidth
implicitHeight: popupColumn.implicitHeight
// Keep the surface click-through except over the toast column, so the
// rest of the (invisible) full-screen overlay never eats input.
mask: Region {
x: popupColumn.x
y: popupColumn.y
width: popupColumn.width
height: popupColumn.height
}
ColumnLayout {
id: popupColumn
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: popupWindow.popupPlacement.margins.top
anchors.rightMargin: popupWindow.popupPlacement.margins.right
spacing: Style.space(8)
Repeater {