linux: Add an option to disable middle-click paste (#16572)

Micah created

Release Notes:

- Added an editor setting to toggle Linux middle-click pasting (enabled by default)

Change summary

assets/settings/default.json         |  2 +
crates/editor/src/editor_settings.rs |  6 +++++
crates/editor/src/element.rs         | 32 +++++++++++++++--------------
3 files changed, 25 insertions(+), 15 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -227,6 +227,8 @@
     // Whether to show diagnostic indicators in the scrollbar.
     "diagnostics": true
   },
+  // Enable middle-click paste on Linux.
+  "middle_click_paste": true,
   // What to do when multibuffer is double clicked in some of its excerpts
   // (parts of singleton buffers).
   // May take 2 values:

crates/editor/src/editor_settings.rs 🔗

@@ -23,6 +23,7 @@ pub struct EditorSettings {
     pub multi_cursor_modifier: MultiCursorModifier,
     pub redact_private_values: bool,
     pub expand_excerpt_lines: u32,
+    pub middle_click_paste: bool,
     #[serde(default)]
     pub double_click_in_multibuffer: DoubleClickInMultibuffer,
     pub search_wrap: bool,
@@ -233,6 +234,11 @@ pub struct EditorSettingsContent {
     /// Default: 3
     pub expand_excerpt_lines: Option<u32>,
 
+    /// Whether to enable middle-click paste on Linux
+    ///
+    /// Default: true
+    pub middle_click_paste: Option<bool>,
+
     /// What to do when multibuffer is double clicked in some of its excerpts
     /// (parts of singleton buffers).
     ///

crates/editor/src/element.rs 🔗

@@ -658,22 +658,24 @@ impl EditorElement {
             }
 
             #[cfg(target_os = "linux")]
-            if let Some(text) = cx.read_from_primary().and_then(|item| item.text()) {
-                let point_for_position =
-                    position_map.point_for_position(text_hitbox.bounds, event.position);
-                let position = point_for_position.previous_valid;
-
-                editor.select(
-                    SelectPhase::Begin {
-                        position,
-                        add: false,
-                        click_count: 1,
-                    },
-                    cx,
-                );
-                editor.insert(&text, cx);
+            if EditorSettings::get_global(cx).middle_click_paste {
+                if let Some(text) = cx.read_from_primary().and_then(|item| item.text()) {
+                    let point_for_position =
+                        position_map.point_for_position(text_hitbox.bounds, event.position);
+                    let position = point_for_position.previous_valid;
+
+                    editor.select(
+                        SelectPhase::Begin {
+                            position,
+                            add: false,
+                            click_count: 1,
+                        },
+                        cx,
+                    );
+                    editor.insert(&text, cx);
+                }
+                cx.stop_propagation()
             }
-            cx.stop_propagation()
         }
     }