diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 076afa8db7..a3a071453e 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -755,6 +755,26 @@ impl Interactivity { } } + // If this element can be focused, register a mouse down listener + // that will automatically transfer focus when hitting the element. + // This behavior can be suppressed by using `cx.prevent_default()`. + if let Some(focus_handle) = element_state.focus_handle.clone() { + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + move |event: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble + && !cx.default_prevented() + && interactive_bounds.visibly_contains(&event.position, cx) + { + cx.focus(&focus_handle); + // If there is a parent that is also focusable, prevent it + // from trasferring focus because we already did so. + cx.prevent_default(); + } + } + }); + } + for listener in self.mouse_down_listeners.drain(..) { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 7ec69f4d0e..77eb4e27be 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1332,8 +1332,9 @@ impl<'a> WindowContext<'a> { /// Dispatch a mouse or keyboard event on the window. pub fn dispatch_event(&mut self, event: InputEvent) -> bool { - // Handlers may set this to false by calling `stop_propagation` + // Handlers may set this to false by calling `stop_propagation`. self.app.propagate_event = true; + // Handlers may set this to true by calling `prevent_default`. self.window.default_prevented = false; let event = match event {