diff --git a/web/model_resolution_picker.js b/web/model_resolution_picker.js index 47ad165..a7ff1fb 100644 --- a/web/model_resolution_picker.js +++ b/web/model_resolution_picker.js @@ -259,11 +259,20 @@ function mountPicker(node) { // The stylesheet, fonts or a wrapped status line can change the content height after a render // (the first fit may even see an unstyled panel): refit whenever a child's box changes. The // children are created once by the view, so observing them at mount covers every render. + // The refit runs on the next frame, never inside the observer delivery: measuring there forces a + // layout while the stylesheet may be applying, and WebKit then reports an undelivered-notifications + // loop error for the observed children. if (typeof ResizeObserver === 'function') { + let refitScheduled = false; const observer = new ResizeObserver(() => { - if (scope.signal.aborted) return; - const measured = measurePanel(); - if (measured && measured !== panelHeight) fitNodeHeight(); + if (scope.signal.aborted || refitScheduled) return; + refitScheduled = true; + requestAnimationFrame(() => { + refitScheduled = false; + if (scope.signal.aborted) return; + const measured = measurePanel(); + if (measured && measured !== panelHeight) fitNodeHeight(); + }); }); for (const child of view.element.children) observer.observe(child); scope.cleanup(() => observer.disconnect()); diff --git a/web/ui/README.md b/web/ui/README.md index 27857b5..d3a25f2 100644 --- a/web/ui/README.md +++ b/web/ui/README.md @@ -128,10 +128,11 @@ render the extension sets the node height to the host's `computeSize()` while keeping the width. The measurement is retried for up to 60 frames when the element is not attached yet (fresh mount, workflow load), skipped while the family table is still loading, and ignored when the panel is hidden by the -host. A `ResizeObserver` on the panel's children refits the node when their -boxes change later, for example when the stylesheet arrives after the first -render, so the panel children must carry no vertical margins (the stylesheet -zeroes them). +host. A `ResizeObserver` on the panel's children schedules a refit on the next +frame when their boxes change later, for example when the stylesheet arrives +after the first render; measuring inside the observer delivery would make WebKit +report an undelivered-notifications loop error. The panel children must carry no +vertical margins (the stylesheet zeroes them). ## Node Dimensions and modal dialogs