Detailed changes
@@ -6451,6 +6451,13 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+[[package]]
+name = "focus_follows_mouse"
+version = "0.1.0"
+dependencies = [
+ "gpui",
+]
+
[[package]]
name = "foldhash"
version = "0.1.5"
@@ -21521,6 +21528,7 @@ dependencies = [
"component",
"db",
"feature_flags",
+ "focus_follows_mouse",
"fs",
"futures 0.3.31",
"git",
@@ -78,6 +78,7 @@ members = [
"crates/feedback",
"crates/file_finder",
"crates/file_icons",
+ "crates/focus_follows_mouse",
"crates/fs",
"crates/fs_benchmarks",
"crates/fuzzy",
@@ -225,6 +225,8 @@
// 3. Hide on both typing and cursor movement:
// "on_typing_and_movement"
"hide_mouse": "on_typing_and_movement",
+ // Determines whether the focused panel follows the mouse location.
+ "focus_follows_mouse": false,
// Determines how snippets are sorted relative to other completion items.
//
// 1. Place snippets at the top of the completion list:
@@ -0,0 +1,14 @@
+[package]
+name = "focus_follows_mouse"
+version = "0.1.0"
+publish.workspace = true
+edition.workspace = true
+
+[lib]
+path = "src/focus_follows_mouse.rs"
+
+[dependencies]
+gpui.workspace = true
+
+[lints]
+workspace = true
@@ -0,0 +1 @@
+../../LICENSE-GPL
@@ -0,0 +1,17 @@
+use gpui::{Context, Focusable, StatefulInteractiveElement};
+
+pub trait FocusFollowsMouse<E: Focusable>: StatefulInteractiveElement {
+ fn focus_follows_mouse(self, enabled: bool, cx: &Context<E>) -> Self {
+ if enabled {
+ self.on_hover(cx.listener(move |this, enter, window, cx| {
+ if *enter {
+ window.focus(&this.focus_handle(cx), cx);
+ }
+ }))
+ } else {
+ self
+ }
+ }
+}
+
+impl<E: Focusable, T: StatefulInteractiveElement> FocusFollowsMouse<E> for T {}
@@ -996,6 +996,7 @@ impl VsCodeSettings {
}
}),
zoomed_padding: None,
+ focus_follows_mouse: None,
}
}
@@ -122,6 +122,9 @@ pub struct WorkspaceSettingsContent {
/// What draws window decorations/titlebar, the client application (Zed) or display server
/// Default: client
pub window_decorations: Option<WindowDecorations>,
+ /// Whether the focused panel follows the mouse location
+ /// Default: false
+ pub focus_follows_mouse: Option<bool>,
}
#[with_fallible_options]
@@ -67,6 +67,7 @@ util.workspace = true
uuid.workspace = true
vim_mode_setting.workspace = true
zed_actions.workspace = true
+focus_follows_mouse = { version = "0.1.0", path = "../focus_follows_mouse" }
[target.'cfg(target_os = "windows")'.dependencies]
windows.workspace = true
@@ -15,6 +15,7 @@ use crate::{
};
use anyhow::Result;
use collections::{BTreeSet, HashMap, HashSet, VecDeque};
+use focus_follows_mouse::FocusFollowsMouse;
use futures::{StreamExt, stream::FuturesUnordered};
use gpui::{
Action, AnyElement, App, AsyncWindowContext, ClickEvent, ClipboardItem, Context, Corner, Div,
@@ -413,6 +414,7 @@ pub struct Pane {
pinned_tab_count: usize,
diagnostics: HashMap<ProjectPath, DiagnosticSeverity>,
zoom_out_on_close: bool,
+ focus_follows_mouse: bool,
diagnostic_summary_update: Task<()>,
/// If a certain project item wants to get recreated with specific data, it can persist its data before the recreation here.
pub project_item_restoration_data: HashMap<ProjectItemKind, Box<dyn Any + Send>>,
@@ -585,6 +587,7 @@ impl Pane {
pinned_tab_count: 0,
diagnostics: Default::default(),
zoom_out_on_close: true,
+ focus_follows_mouse: WorkspaceSettings::get_global(cx).focus_follows_mouse,
diagnostic_summary_update: Task::ready(()),
project_item_restoration_data: HashMap::default(),
welcome_page: None,
@@ -752,7 +755,6 @@ impl Pane {
fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let tab_bar_settings = TabBarSettings::get_global(cx);
- let new_max_tabs = WorkspaceSettings::get_global(cx).max_tabs;
if let Some(display_nav_history_buttons) = self.display_nav_history_buttons.as_mut() {
*display_nav_history_buttons = tab_bar_settings.show_nav_history_buttons;
@@ -765,6 +767,12 @@ impl Pane {
self.nav_history.0.lock().preview_item_id = None;
}
+ let workspace_settings = WorkspaceSettings::get_global(cx);
+
+ self.focus_follows_mouse = workspace_settings.focus_follows_mouse;
+
+ let new_max_tabs = workspace_settings.max_tabs;
+
if self.use_max_tabs && new_max_tabs != self.max_tabs {
self.max_tabs = new_max_tabs;
self.close_items_on_settings_change(window, cx);
@@ -4429,6 +4437,7 @@ impl Render for Pane {
placeholder.child(self.welcome_page.clone().unwrap())
}
}
+ .focus_follows_mouse(self.focus_follows_mouse, cx)
})
.child(
// drag target
@@ -35,6 +35,7 @@ pub struct WorkspaceSettings {
pub use_system_window_tabs: bool,
pub zoomed_padding: bool,
pub window_decorations: settings::WindowDecorations,
+ pub focus_follows_mouse: bool,
}
#[derive(Copy, Clone, PartialEq, Debug, Default)]
@@ -113,6 +114,7 @@ impl Settings for WorkspaceSettings {
use_system_window_tabs: workspace.use_system_window_tabs.unwrap(),
zoomed_padding: workspace.zoomed_padding.unwrap(),
window_decorations: workspace.window_decorations.unwrap(),
+ focus_follows_mouse: workspace.focus_follows_mouse.unwrap(),
}
}
}