editor: Fix signature help popover goes off screen (#28566)

Closes #27731

Uses similar logic as other popovers for layouting signature help
popover.

Release Notes:

- Fixed case where signature help popover goes off the screen.
This commit is contained in:
Smit Barmase 2025-04-11 14:50:42 +05:30 committed by GitHub
parent d4736a5427
commit bd4c9b45b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 26 deletions

View file

@ -18,7 +18,8 @@ use crate::{
}, },
git::blame::{BlameRenderer, GitBlame, GlobalBlameRenderer}, git::blame::{BlameRenderer, GitBlame, GlobalBlameRenderer},
hover_popover::{ hover_popover::{
self, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT, hover_at, self, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT,
POPOVER_RIGHT_OFFSET, hover_at,
}, },
inlay_hint_settings, inlay_hint_settings,
items::BufferSearchHighlights, items::BufferSearchHighlights,
@ -3958,7 +3959,8 @@ impl EditorElement {
for mut hover_popover in hover_popovers { for mut hover_popover in hover_popovers {
let size = hover_popover.layout_as_root(AvailableSpace::min_size(), window, cx); let size = hover_popover.layout_as_root(AvailableSpace::min_size(), window, cx);
let horizontal_offset = let horizontal_offset =
(text_hitbox.top_right().x - (hovered_point.x + size.width)).min(Pixels::ZERO); (text_hitbox.top_right().x - POPOVER_RIGHT_OFFSET - (hovered_point.x + size.width))
.min(Pixels::ZERO);
overall_height += HOVER_POPOVER_GAP + size.height; overall_height += HOVER_POPOVER_GAP + size.height;
@ -4110,6 +4112,7 @@ impl EditorElement {
fn layout_signature_help( fn layout_signature_help(
&self, &self,
hitbox: &Hitbox, hitbox: &Hitbox,
text_hitbox: &Hitbox,
content_origin: gpui::Point<Pixels>, content_origin: gpui::Point<Pixels>,
scroll_pixel_position: gpui::Point<Pixels>, scroll_pixel_position: gpui::Point<Pixels>,
newest_selection_head: Option<DisplayPoint>, newest_selection_head: Option<DisplayPoint>,
@ -4126,20 +4129,6 @@ impl EditorElement {
let Some(newest_selection_head) = newest_selection_head else { let Some(newest_selection_head) = newest_selection_head else {
return; return;
}; };
let selection_row = newest_selection_head.row();
if selection_row < start_row {
return;
}
let Some(cursor_row_layout) = line_layouts.get(selection_row.minus(start_row) as usize)
else {
return;
};
let start_x = cursor_row_layout.x_for_index(newest_selection_head.column() as usize)
- scroll_pixel_position.x
+ content_origin.x;
let start_y =
selection_row.as_f32() * line_height + content_origin.y - scroll_pixel_position.y;
let max_size = size( let max_size = size(
(120. * em_width) // Default size (120. * em_width) // Default size
@ -4158,18 +4147,42 @@ impl EditorElement {
None None
} }
}); });
if let Some(mut element) = maybe_element { let Some(mut element) = maybe_element else {
let window_size = window.viewport_size(); return;
let size = element.layout_as_root(Size::<AvailableSpace>::default(), window, cx); };
let mut point = point(start_x, start_y - size.height);
// Adjusting to ensure the popover does not overflow in the X-axis direction. let selection_row = newest_selection_head.row();
if point.x + size.width >= window_size.width { let Some(cursor_row_layout) = (selection_row >= start_row)
point.x = window_size.width - size.width; .then(|| line_layouts.get(selection_row.minus(start_row) as usize))
} .flatten()
else {
return;
};
window.defer_draw(element, point, 1) let target_x = cursor_row_layout.x_for_index(newest_selection_head.column() as usize)
} - scroll_pixel_position.x;
let target_y = selection_row.as_f32() * line_height - scroll_pixel_position.y;
let target_point = content_origin + point(target_x, target_y);
let actual_size = element.layout_as_root(max_size.into(), window, cx);
let overall_height = actual_size.height + HOVER_POPOVER_GAP;
let popover_origin = if target_point.y > overall_height {
point(target_point.x, target_point.y - actual_size.height)
} else {
point(
target_point.x,
target_point.y + line_height + HOVER_POPOVER_GAP,
)
};
let horizontal_offset = (text_hitbox.top_right().x
- POPOVER_RIGHT_OFFSET
- (popover_origin.x + actual_size.width))
.min(Pixels::ZERO);
let final_origin = point(popover_origin.x + horizontal_offset, popover_origin.y);
window.defer_draw(element, final_origin, 2);
} }
fn paint_background(&self, layout: &EditorLayout, window: &mut Window, cx: &mut App) { fn paint_background(&self, layout: &EditorLayout, window: &mut Window, cx: &mut App) {
@ -7415,6 +7428,7 @@ impl Element for EditorElement {
self.layout_signature_help( self.layout_signature_help(
&hitbox, &hitbox,
&text_hitbox,
content_origin, content_origin,
scroll_pixel_position, scroll_pixel_position,
newest_selection_head, newest_selection_head,

View file

@ -30,6 +30,7 @@ pub const HOVER_REQUEST_DELAY_MILLIS: u64 = 200;
pub const MIN_POPOVER_CHARACTER_WIDTH: f32 = 20.; pub const MIN_POPOVER_CHARACTER_WIDTH: f32 = 20.;
pub const MIN_POPOVER_LINE_HEIGHT: f32 = 4.; pub const MIN_POPOVER_LINE_HEIGHT: f32 = 4.;
pub const POPOVER_RIGHT_OFFSET: Pixels = px(8.0);
pub const HOVER_POPOVER_GAP: Pixels = px(10.); pub const HOVER_POPOVER_GAP: Pixels = px(10.);
/// Bindable action which uses the most recent selection head to trigger a hover /// Bindable action which uses the most recent selection head to trigger a hover