From e9aa87fab39fad6f18b4bcee7e9627038e663049 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Wed, 28 Oct 2026 10:45:10 +0000 Subject: [PATCH 1/3] fix(desktop-gpui): size the recording bar's window to the bar so the space above it stays clickable --- apps/desktop-gpui/src/app_windows.rs | 45 ++++++++++++++++++++++-- apps/desktop-gpui/src/controls_window.rs | 38 ++++++++++++++++---- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/apps/desktop-gpui/src/app_windows.rs b/apps/desktop-gpui/src/app_windows.rs index 50f47b27f9..85f4161520 100644 --- a/apps/desktop-gpui/src/app_windows.rs +++ b/apps/desktop-gpui/src/app_windows.rs @@ -40,7 +40,14 @@ use crate::{ /// Matches the Tauri `InProgressRecording` window and /// `fake_window.rs` position math. pub const CONTROLS_WIDTH: f32 = 320.; +/// The window's height with an issue card above the bar. pub const CONTROLS_HEIGHT: f32 = 150.; +/// The bar alone, with its padding. A transparent window takes every click +/// inside its frame, so without an issue to show the window is only this +/// tall and the app under the empty space above the bar stays clickable. +pub const CONTROLS_BAR_HEIGHT: f32 = 64.; +/// Where the window can change height in place, keeping the bar still. +const CONTROLS_FIT_TO_ISSUE: bool = cfg!(any(target_os = "macos", windows)); const CONTROLS_BOTTOM_OFFSET: f64 = 120.; const TARGET_CONTROLS_OFFSET_Y: f64 = 48.; @@ -6898,6 +6905,35 @@ fn controls_origin(config: &StartConfig) -> (f64, f64) { } } +/// Grow the bar's window upward to make room for an issue card above the +/// bar, or shrink it back to the bar alone, leaving the bar where it is. +/// `setFrame` re-enters gpui, so call this from a task. +pub(crate) fn fit_controls_to_issue(native: &platform::NativeWindow, issue: bool, scale: f32) { + let height = f64::from(if issue { + CONTROLS_HEIGHT + } else { + CONTROLS_BAR_HEIGHT + }); + let (x, y, width, current) = platform::window_frame(native); + if width <= 0. { + return; + } + // AppKit frames have a bottom-left origin: a new height keeps the bottom. + #[cfg(target_os = "macos")] + { + let _ = (current, scale); + platform::set_window_frame(native, x, y, width, height); + } + // Windows frames are physical pixels from the top-left. + #[cfg(windows)] + { + let height = height * f64::from(scale); + platform::set_window_frame(native, x, y + current - height, width, height); + } + #[cfg(not(any(target_os = "macos", windows)))] + let _ = (native, x, y, current, height, scale); +} + /// Open the bar. Returns the native window number for capture exclusion. fn open_controls( config: &StartConfig, @@ -6909,9 +6945,14 @@ fn open_controls( return None; } let (x, y) = controls_origin(config); + let height = if CONTROLS_FIT_TO_ISSUE { + CONTROLS_BAR_HEIGHT + } else { + CONTROLS_HEIGHT + }; let bounds = Bounds { - origin: point(px(x as f32), px(y as f32)), - size: size(px(CONTROLS_WIDTH), px(CONTROLS_HEIGHT)), + origin: point(px(x as f32), px(y as f32 + CONTROLS_HEIGHT - height)), + size: size(px(CONTROLS_WIDTH), px(height)), }; let display = config .target diff --git a/apps/desktop-gpui/src/controls_window.rs b/apps/desktop-gpui/src/controls_window.rs index 37a723cd7a..4802f8d266 100644 --- a/apps/desktop-gpui/src/controls_window.rs +++ b/apps/desktop-gpui/src/controls_window.rs @@ -36,6 +36,8 @@ pub struct ControlsWindow { _tick: gpui::Task<()>, ticking_live: bool, level_bar: Entity, + /// Whether the window is sized for the issue card. + issue_room: bool, } #[derive(Clone, Copy)] @@ -63,6 +65,7 @@ impl ControlsWindow { crate::theme::bind_window(window, cx); let theme = Theme::for_window(window, cx, false); cx.observe_in(&session, window, |this, _, window, cx| { + this.fit_to_issue(window, cx); let live = this.timer_is_live(cx); if live != this.ticking_live { this.ticking_live = live; @@ -90,12 +93,40 @@ impl ControlsWindow { _tick: gpui::Task::ready(()), ticking_live: false, level_bar, + issue_room: false, }; this.ticking_live = this.timer_is_live(cx); this._tick = Self::spawn_tick(window, cx); + // Once the platform window is finished: an issue may already be up. + cx.defer_in(window, |this, window, cx| this.fit_to_issue(window, cx)); this } + fn issue(&self, cx: &gpui::App) -> Option { + let session = self.session.read(cx); + session.error.clone().or_else(|| { + session + .storage_warning + .then(|| tr::controls::low_storage().to_owned()) + }) + } + + fn fit_to_issue(&mut self, window: &mut Window, cx: &mut Context) { + let issue = self.issue(cx).is_some(); + if issue == self.issue_room { + return; + } + self.issue_room = issue; + let Some(native) = crate::platform::native_window(window) else { + return; + }; + let scale = window.scale_factor(); + cx.spawn(async move |_, _| { + crate::app_windows::fit_controls_to_issue(&native, issue, scale); + }) + .detach(); + } + fn timer_is_live(&self, cx: &gpui::App) -> bool { matches!( self.session.read(cx).phase, @@ -511,12 +542,7 @@ impl ControlsWindow { impl Render for ControlsWindow { fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { self.theme.refresh(window, cx, false); - let session = self.session.read(cx); - let issue = session.error.clone().or_else(|| { - session - .storage_warning - .then(|| tr::controls::low_storage().to_owned()) - }); + let issue = self.issue(cx); div() .size_full() From 37ab805cb02ab5a8de9bfc05224a280788dd3902 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Wed, 28 Oct 2026 10:57:04 +0000 Subject: [PATCH 2/3] chore(desktop-gpui): drop a comment that restates the field --- apps/desktop-gpui/src/controls_window.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/desktop-gpui/src/controls_window.rs b/apps/desktop-gpui/src/controls_window.rs index 4802f8d266..02c298d9ea 100644 --- a/apps/desktop-gpui/src/controls_window.rs +++ b/apps/desktop-gpui/src/controls_window.rs @@ -36,7 +36,6 @@ pub struct ControlsWindow { _tick: gpui::Task<()>, ticking_live: bool, level_bar: Entity, - /// Whether the window is sized for the issue card. issue_room: bool, } From 4adb86613062faa07addbbaf3e384356070516cc Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Wed, 28 Oct 2026 13:23:54 +0000 Subject: [PATCH 3/3] chore(desktop-gpui): drop two comments that restate the declarations --- apps/desktop-gpui/src/app_windows.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/desktop-gpui/src/app_windows.rs b/apps/desktop-gpui/src/app_windows.rs index 85f4161520..748984e898 100644 --- a/apps/desktop-gpui/src/app_windows.rs +++ b/apps/desktop-gpui/src/app_windows.rs @@ -40,13 +40,11 @@ use crate::{ /// Matches the Tauri `InProgressRecording` window and /// `fake_window.rs` position math. pub const CONTROLS_WIDTH: f32 = 320.; -/// The window's height with an issue card above the bar. pub const CONTROLS_HEIGHT: f32 = 150.; /// The bar alone, with its padding. A transparent window takes every click /// inside its frame, so without an issue to show the window is only this /// tall and the app under the empty space above the bar stays clickable. pub const CONTROLS_BAR_HEIGHT: f32 = 64.; -/// Where the window can change height in place, keeping the bar still. const CONTROLS_FIT_TO_ISSUE: bool = cfg!(any(target_os = "macos", windows)); const CONTROLS_BOTTOM_OFFSET: f64 = 120.; const TARGET_CONTROLS_OFFSET_Y: f64 = 48.;