popover: Revert defer_to focus on Popover open. (#1571)

Revert #1559 added defer to focus.

Removed the behavior of focus back to was focused handle on close
Popover, this is not correct for Popover.
This commit is contained in:
Jason Lee 2025-11-12 17:29:22 +08:00 committed by GitHub
parent f26f01909e
commit a2c16bfae6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 76 additions and 18 deletions

View file

@ -9,6 +9,7 @@ use gpui_component::{
divider::Divider, divider::Divider,
h_flex, h_flex,
input::{Input, InputState}, input::{Input, InputState},
list::{List, ListDelegate, ListItem, ListState},
popover::Popover, popover::Popover,
v_flex, v_flex,
}; };
@ -63,6 +64,48 @@ impl Focusable for Form {
} }
} }
struct DropdownListDelegate {
parent: Entity<PopoverStory>,
}
impl ListDelegate for DropdownListDelegate {
type Item = ListItem;
fn items_count(&self, _: usize, _: &App) -> usize {
10
}
fn render_item(
&self,
ix: gpui_component::IndexPath,
_: &mut Window,
_: &mut App,
) -> Option<Self::Item> {
Some(ListItem::new(ix).child(format!("Item {}", ix.row)))
}
fn set_selected_index(
&mut self,
_: Option<gpui_component::IndexPath>,
_: &mut Window,
_: &mut Context<gpui_component::list::ListState<Self>>,
) {
}
fn confirm(&mut self, _: bool, _: &mut Window, cx: &mut Context<ListState<Self>>) {
self.parent.update(cx, |this, cx| {
this.list_popover_open = false;
cx.notify();
})
}
fn cancel(&mut self, _: &mut Window, cx: &mut Context<ListState<Self>>) {
self.parent.update(cx, |this, cx| {
this.list_popover_open = false;
cx.notify();
})
}
}
impl EventEmitter<DismissEvent> for Form {} impl EventEmitter<DismissEvent> for Form {}
impl Render for Form { impl Render for Form {
@ -81,7 +124,7 @@ impl Render for Form {
.primary() .primary()
.on_click(cx.listener(move |_, _, _, cx| { .on_click(cx.listener(move |_, _, _, cx| {
parent.update(cx, |this, cx| { parent.update(cx, |this, cx| {
this.form_open = false; this.form_popover_open = false;
cx.notify(); cx.notify();
}) })
})), })),
@ -92,7 +135,9 @@ impl Render for Form {
pub struct PopoverStory { pub struct PopoverStory {
focus_handle: FocusHandle, focus_handle: FocusHandle,
form: Entity<Form>, form: Entity<Form>,
form_open: bool, list: Entity<ListState<DropdownListDelegate>>,
form_popover_open: bool,
list_popover_open: bool,
checked: bool, checked: bool,
message: String, message: String,
} }
@ -118,13 +163,18 @@ impl PopoverStory {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self { fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let form = Form::new(cx.entity(), window, cx); let form = Form::new(cx.entity(), window, cx);
let parent = cx.entity();
let list = cx
.new(|cx| ListState::new(DropdownListDelegate { parent }, window, cx).searchable(true));
cx.focus_self(window); cx.focus_self(window);
Self { Self {
form, form,
list,
checked: true, checked: true,
form_open: false, form_popover_open: false,
list_popover_open: false,
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
message: "".to_string(), message: "".to_string(),
} }
@ -201,20 +251,37 @@ impl Render for PopoverStory {
) )
.child( .child(
section("Popover with Form").child( section("Popover with Form").child(
Popover::new("info-bottom-left") Popover::new("popover-form")
.p_0() .p_0()
.text_sm() .text_sm()
.trigger(Button::new("pop").outline().label("Popup Form")) .trigger(Button::new("pop").outline().label("Popup Form"))
.track_focus(&form.focus_handle(cx)) .track_focus(&form.focus_handle(cx))
.open(self.form_open) .open(self.form_popover_open)
.on_open_change(cx.listener(move |this, open, _, cx| { .on_open_change(cx.listener(move |this, open, _, cx| {
println!("Popover form open changed: {}", open); println!("Popover form open changed: {}", open);
this.form_open = *open; this.form_popover_open = *open;
cx.notify(); cx.notify();
})) }))
.child(form.clone()), .child(form.clone()),
), ),
) )
.child(
section("Popover with List").child(
Popover::new("popover-list")
.p_0()
.text_sm()
.open(self.list_popover_open)
.on_open_change(cx.listener(move |this, open, _, cx| {
this.list_popover_open = *open;
cx.notify();
}))
.trigger(Button::new("pop").outline().label("Popup List"))
.track_focus(&self.list.focus_handle(cx))
.child(List::new(&self.list))
.w_64()
.h(px(200.)),
),
)
.child( .child(
section("Right click to open Popover").child( section("Right click to open Popover").child(
Popover::new("popover-right-click") Popover::new("popover-right-click")

View file

@ -193,7 +193,6 @@ pub struct PopoverState {
focus_handle: FocusHandle, focus_handle: FocusHandle,
pub(crate) tracked_focus_handle: Option<FocusHandle>, pub(crate) tracked_focus_handle: Option<FocusHandle>,
trigger_bounds: Option<Bounds<Pixels>>, trigger_bounds: Option<Bounds<Pixels>>,
previous_focus: Option<FocusHandle>,
open: bool, open: bool,
on_open_change: Option<Rc<dyn Fn(&bool, &mut Window, &mut App)>>, on_open_change: Option<Rc<dyn Fn(&bool, &mut Window, &mut App)>>,
@ -206,7 +205,6 @@ impl PopoverState {
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
tracked_focus_handle: None, tracked_focus_handle: None,
trigger_bounds: None, trigger_bounds: None,
previous_focus: None,
open: default_open, open: default_open,
on_open_change: None, on_open_change: None,
_dismiss_subscription: None, _dismiss_subscription: None,
@ -236,17 +234,13 @@ impl PopoverState {
self.open = !self.open; self.open = !self.open;
if self.open { if self.open {
let state = cx.entity(); let state = cx.entity();
self.previous_focus = window.focused(cx);
let focus_handle = if let Some(tracked_focus_handle) = self.tracked_focus_handle.clone() let focus_handle = if let Some(tracked_focus_handle) = self.tracked_focus_handle.clone()
{ {
tracked_focus_handle tracked_focus_handle
} else { } else {
self.focus_handle.clone() self.focus_handle.clone()
}; };
focus_handle.focus(window);
cx.defer_in(window, move |_, window, _| {
focus_handle.focus(window);
});
self._dismiss_subscription = self._dismiss_subscription =
Some( Some(
@ -258,9 +252,6 @@ impl PopoverState {
}), }),
); );
} else { } else {
if let Some(previous_focus) = self.previous_focus.take() {
window.focus(&previous_focus);
}
self._dismiss_subscription = None; self._dismiss_subscription = None;
} }
@ -309,7 +300,7 @@ impl RenderOnce for Popover {
}); });
let open = state.read(cx).open; let open = state.read(cx).open;
let focus_handle = state.focus_handle(cx); let focus_handle = state.read(cx).focus_handle.clone();
let trigger_bounds = state.read(cx).trigger_bounds; let trigger_bounds = state.read(cx).trigger_bounds;
let Some(trigger) = self.trigger else { let Some(trigger) = self.trigger else {
@ -364,8 +355,8 @@ impl RenderOnce for Popover {
.child( .child(
v_flex() v_flex()
.id("content") .id("content")
.key_context(CONTEXT)
.track_focus(&focus_handle) .track_focus(&focus_handle)
.key_context(CONTEXT)
.on_action(window.listener_for(&state, PopoverState::on_action_cancel)) .on_action(window.listener_for(&state, PopoverState::on_action_cancel))
.size_full() .size_full()
.occlude() .occlude()