Repository navigation
fix(hud): drop the growth reserve on Linux so the HUD hugs its content #1501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,9 +52,10 @@ import { | |
| computeHudToastsHeight, | ||
| computeHudWindowSize, | ||
| HUD_BAR_BOTTOM, | ||
| HUD_GROWTH_RESERVE, | ||
| HUD_POPOVER_GAP, | ||
| HUD_STACK_GAP, | ||
| HUD_TOOLTIP_STACK_HEIGHT, | ||
| hudGrowthReserve, | ||
| } from "./hudGeometry"; | ||
| import styles from "./LaunchWindow.module.css"; | ||
|
|
||
|
|
@@ -435,43 +436,64 @@ export function LaunchWindow() { | |
| : 0; | ||
|
|
||
| // The two floating surfaces get their own CSS caps (a 470px-tall language | ||
| // list would look absurd), but the *window* always reserves room for the | ||
| // taller of them. Sizing the reserve to whichever happens to be open would | ||
| // mean the window grows when the panel opens — and since the stack is | ||
| // bottom-anchored, growing upward moves every bit of content down in window | ||
| // list would look absurd). On Windows and macOS the *window* always reserves | ||
| // room for the taller of them: sizing the reserve to whichever happens to be | ||
| // open would mean the window grows when the panel opens — and since the stack | ||
| // is bottom-anchored, growing upward moves every bit of content down in window | ||
| // coordinates, which the renderer repaints a frame or two after the native | ||
| // resize lands. That gap is visible as exactly the position judder this | ||
| // whole architecture exists to remove. So: reserve the maximum, always. | ||
| // resize lands. That gap is visible as exactly the position judder this whole | ||
| // architecture exists to remove. Linux cannot afford that reserve: its HUD is | ||
| // not click-through, so the empty space intercepts desktop clicks whenever no | ||
| // panel is open. There the window follows the measured stack instead. | ||
| const popoverMaxHeight = computeHudPopoverMaxHeight(barHeight, availableHeight); | ||
| const modalMaxHeight = computeHudModalMaxHeight(barHeight, availableHeight); | ||
| const anchorEl = hudAnchorRef.current; | ||
| anchorEl?.style.setProperty("--hud-popover-max-h", `${popoverMaxHeight}px`); | ||
| anchorEl?.style.setProperty("--hud-modal-max-h", `${modalMaxHeight}px`); | ||
|
|
||
| // Measured after the caps above are applied: the anchor is the whole stack, | ||
| // bar plus whatever is open above it, so its height is exactly the content | ||
| // that has to be on screen right now. | ||
| const anchorRect = anchorEl?.getBoundingClientRect(); | ||
| const stackRect = anchorRect?.width && anchorRect.height ? anchorRect : barRect; | ||
| const stackHeight = stackRect.height || barHeight; | ||
|
|
||
| const platform = getPlatform(); | ||
| const isLinux = platform === "linux"; | ||
| const growthReserve = hudGrowthReserve(platform); | ||
| const toastsHeight = hudToastsHeightRef.current; | ||
| const { required, granted } = computeHudWindowSize({ | ||
| barWidth, | ||
| barHeight, | ||
| noticeHeight, | ||
| // On Linux the measured stack already contains any notice, so counting the | ||
| // notice again would reserve its height twice. | ||
| noticeHeight: isLinux ? 0 : noticeHeight, | ||
| availableHeight, | ||
| stackMaxHeight: Math.max(popoverMaxHeight, modalMaxHeight), | ||
| openStackHeight: isLinux | ||
| ? Math.max(HUD_TOOLTIP_STACK_HEIGHT, stackHeight - barHeight) | ||
| : undefined, | ||
| toastsHeight, | ||
| growthReserve, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| }); | ||
|
|
||
| const allocated = hudAllocatedSizeRef.current; | ||
| // A different orientation is a different shape entirely (wide-short vs | ||
| // narrow-tall), so the previous allocation says nothing useful. | ||
| const orientationChanged = allocated.orientation !== trayLayout; | ||
| // Grow the moment the content stops fitting. Shrink only once the content | ||
| // has fallen a whole reserve below what was granted — that asymmetry is the | ||
| // hysteresis: the bar can grow into its reserve (recording controls, a | ||
| // longer source name) and back out again without a single native resize, | ||
| // while a one-off bad reading (an unstyled first paint in dev, say) can't | ||
| // leave the overlay permanently oversized. | ||
| // Grow the moment the content stops fitting. On Windows and macOS shrink only | ||
| // once the content has fallen a whole reserve below what was granted — that | ||
| // asymmetry is the hysteresis: the bar can grow into its reserve (recording | ||
| // controls, a longer source name) and back out again without a single native | ||
| // resize, while a one-off bad reading (an unstyled first paint in dev, say) | ||
| // can't leave the overlay permanently oversized. Linux has no reserve to fall | ||
| // back into, so it resizes symmetrically and never keeps dead space. | ||
| const needsResize = | ||
| orientationChanged || | ||
| required.width > allocated.width || | ||
| required.height > allocated.height || | ||
| granted.width + HUD_GROWTH_RESERVE < allocated.width || | ||
| granted.height + HUD_GROWTH_RESERVE < allocated.height; | ||
| granted.width + growthReserve < allocated.width || | ||
| granted.height + growthReserve < allocated.height; | ||
|
|
||
| // The main process keeps this rect on screen, not the window: the window is | ||
| // mostly transparent reserve, and clamping it would strand the bar at the | ||
|
|
@@ -481,15 +503,12 @@ export function LaunchWindow() { | |
| // and since the stack is centred and pinned HUD_BAR_BOTTOM above the window's | ||
| // bottom edge (LaunchWindow.module.css), the rect the granted size will | ||
| // produce is computed exactly rather than measured a frame late. | ||
| const anchorRect = anchorEl?.getBoundingClientRect(); | ||
| const stackRect = anchorRect?.width && anchorRect.height ? anchorRect : barRect; | ||
| const stackHeight = stackRect.height || barHeight; | ||
| // Toasts sit above the stack, and they are just as visible: a toast pushed off the top | ||
| // of the screen is an error nobody reads. | ||
| setHudToastBottom(computeHudToastBottom(stackHeight)); | ||
| const visible = addHudToastsToStack( | ||
| { width: stackRect.width || barWidth, height: stackHeight }, | ||
| hudToastsHeightRef.current, | ||
| toastsHeight, | ||
| ); | ||
| const contentFor = (size: { width: number; height: number }) => ({ | ||
| x: (size.width - visible.width) / 2, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
Repository: getopenscreen/openscreen
Length of output: 24325
Scope the zero-resize comments to Windows and macOS.
On Linux, the anchor height drives the window size. Popover and content height changes now call
setHudOverlaySize. The two comments at lines 385-400 and 549-552 still state that opening a popover never causes a native resize. Update them so they describe the platform split.Suggested fix