Merge remote-tracking branch 'origin/main' into new-thread

Danilo Leal created

Change summary

.github/workflows/autofix_pr.yml                     |  5 -
.github/workflows/run_tests.yml                      |  9 +--
crates/agent/src/tools/streaming_edit_file_tool.rs   |  4 
crates/agent_ui/src/agent_diff.rs                    |  1 
crates/agent_ui/src/conversation_view/thread_view.rs |  1 
crates/agent_ui/src/inline_assistant.rs              |  1 
crates/agent_ui/src/message_editor.rs                |  1 
crates/debugger_ui/src/session/running/console.rs    |  1 
crates/editor/src/editor.rs                          | 13 ++++
crates/editor/src/element.rs                         | 17 ++-----
crates/gpui_linux/src/linux/x11/client.rs            | 17 +++++++
crates/gpui_linux/src/linux/x11/window.rs            | 31 ++++++++-----
crates/inspector_ui/src/div_inspector.rs             |  1 
crates/keymap_editor/src/keymap_editor.rs            |  1 
crates/repl/src/notebook/cell.rs                     |  3 +
crates/sidebar/src/sidebar.rs                        |  6 ++
crates/terminal_view/src/terminal_view.rs            |  4 +
crates/theme_settings/src/settings.rs                |  3 
crates/theme_settings/src/theme_settings.rs          | 19 +++++++-
crates/zed/src/zed.rs                                |  4 
tooling/xtask/src/tasks/workflows/autofix_pr.rs      |  9 +--
tooling/xtask/src/tasks/workflows/run_tests.rs       | 18 ++-----
22 files changed, 105 insertions(+), 64 deletions(-)

Detailed changes

.github/workflows/autofix_pr.yml 🔗

@@ -45,10 +45,9 @@ jobs:
         version: '9'
     - name: autofix_pr::run_autofix::install_cargo_machete
       if: ${{ inputs.run_clippy }}
-      uses: clechasseur/rs-cargo@8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386
+      uses: taiki-e/install-action@02cc5f8ca9f2301050c0c099055816a41ee05507
       with:
-        command: install
-        args: cargo-machete@0.7.0
+        tool: cargo-machete@0.7.0
     - name: autofix_pr::run_autofix::run_cargo_fix
       if: ${{ inputs.run_clippy }}
       run: cargo fix --workspace --release --all-targets --all-features --allow-dirty --allow-staged

.github/workflows/run_tests.yml 🔗

@@ -618,14 +618,11 @@ jobs:
         cache: rust
         path: ~/.rustup
     - name: run_tests::check_dependencies::install_cargo_machete
-      uses: clechasseur/rs-cargo@8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386
+      uses: taiki-e/install-action@02cc5f8ca9f2301050c0c099055816a41ee05507
       with:
-        command: install
-        args: cargo-machete@0.7.0
+        tool: cargo-machete@0.7.0
     - name: run_tests::check_dependencies::run_cargo_machete
-      uses: clechasseur/rs-cargo@8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386
-      with:
-        command: machete
+      run: cargo machete
     - name: run_tests::check_dependencies::check_cargo_lock
       run: cargo update --locked --workspace
     - name: run_tests::check_dependencies::check_vulnerable_dependencies

crates/agent/src/tools/streaming_edit_file_tool.rs 🔗

@@ -189,9 +189,9 @@ pub enum StreamingEditFileToolOutput {
     },
     Error {
         error: String,
-        #[serde(default)]
+        #[serde(default, skip_serializing_if = "Option::is_none")]
         input_path: Option<PathBuf>,
-        #[serde(default)]
+        #[serde(default, skip_serializing_if = "String::is_empty")]
         diff: String,
     },
 }

crates/agent_ui/src/agent_diff.rs 🔗

@@ -98,6 +98,7 @@ impl AgentDiffPane {
             editor
                 .set_render_diff_hunk_controls(diff_hunk_controls(&thread, workspace.clone()), cx);
             editor.register_addon(AgentDiffAddon);
+            editor.disable_mouse_wheel_zoom();
             editor
         });
 

crates/agent_ui/src/conversation_view/thread_view.rs 🔗

@@ -5170,6 +5170,7 @@ impl ThreadView {
                         let mut editor =
                             Editor::for_multibuffer(buffer, Some(project.clone()), window, cx);
                         editor.set_breadcrumb_header(thread_title);
+                        editor.disable_mouse_wheel_zoom();
                         editor
                     })),
                     None,

crates/agent_ui/src/inline_assistant.rs 🔗

@@ -1483,6 +1483,7 @@ impl InlineAssistant {
                     editor.set_show_wrap_guides(false, cx);
                     editor.set_show_gutter(false, cx);
                     editor.set_offset_content(false, cx);
+                    editor.disable_mouse_wheel_zoom();
                     editor.scroll_manager.set_forbid_vertical_scroll(true);
                     editor.set_read_only(true);
                     editor.set_show_edit_predictions(Some(false), window, cx);

crates/agent_ui/src/message_editor.rs 🔗

@@ -422,6 +422,7 @@ impl MessageEditor {
             editor.set_show_indent_guides(false, cx);
             editor.set_show_completions_on_input(Some(true));
             editor.set_soft_wrap();
+            editor.disable_mouse_wheel_zoom();
             editor.set_use_modal_editing(true);
             editor.set_context_menu_options(ContextMenuOptions {
                 min_entries_visible: 12,

crates/debugger_ui/src/session/running/console.rs 🔗

@@ -84,6 +84,7 @@ impl Console {
             editor.set_show_indent_guides(false, cx);
             editor.set_show_edit_predictions(Some(false), window, cx);
             editor.set_use_modal_editing(false);
+            editor.disable_mouse_wheel_zoom();
             editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
             editor
         });

crates/editor/src/editor.rs 🔗

@@ -1183,6 +1183,7 @@ pub struct Editor {
     delegate_open_excerpts: bool,
     enable_lsp_data: bool,
     enable_runnables: bool,
+    enable_mouse_wheel_zoom: bool,
     show_line_numbers: Option<bool>,
     use_relative_line_numbers: Option<bool>,
     show_git_diff_gutter: Option<bool>,
@@ -1972,6 +1973,9 @@ impl Editor {
         clone.read_only = self.read_only;
         clone.buffers_with_disabled_indent_guides =
             self.buffers_with_disabled_indent_guides.clone();
+        clone.enable_mouse_wheel_zoom = self.enable_mouse_wheel_zoom;
+        clone.enable_lsp_data = self.enable_lsp_data;
+        clone.enable_runnables = self.enable_runnables;
         clone
     }
 
@@ -2419,8 +2423,9 @@ impl Editor {
             delegate_expand_excerpts: false,
             delegate_stage_and_restore: false,
             delegate_open_excerpts: false,
-            enable_lsp_data: true,
-            enable_runnables: true,
+            enable_lsp_data: full_mode,
+            enable_runnables: full_mode,
+            enable_mouse_wheel_zoom: full_mode,
             show_git_diff_gutter: None,
             show_code_actions: None,
             show_runnables: None,
@@ -26082,6 +26087,10 @@ impl Editor {
         self.enable_runnables = false;
     }
 
+    pub fn disable_mouse_wheel_zoom(&mut self) {
+        self.enable_mouse_wheel_zoom = false;
+    }
+
     fn update_data_on_scroll(&mut self, window: &mut Window, cx: &mut Context<'_, Self>) {
         self.register_visible_buffers(cx);
         self.colorize_brackets(false, cx);

crates/editor/src/element.rs 🔗

@@ -7673,22 +7673,18 @@ impl EditorElement {
 
             move |event: &ScrollWheelEvent, phase, window, cx| {
                 if phase == DispatchPhase::Bubble && hitbox.should_handle_scroll(window) {
-                    if event.modifiers.secondary() {
+                    delta = delta.coalesce(event.delta);
+
+                    if event.modifiers.secondary() && editor.read(cx).enable_mouse_wheel_zoom {
                         let delta_y = match event.delta {
                             ScrollDelta::Pixels(pixels) => pixels.y.into(),
                             ScrollDelta::Lines(lines) => lines.y,
                         };
 
                         if delta_y > 0.0 {
-                            window.dispatch_action(
-                                Box::new(zed_actions::IncreaseBufferFontSize { persist: false }),
-                                cx,
-                            );
+                            theme_settings::increase_buffer_font_size(cx);
                         } else if delta_y < 0.0 {
-                            window.dispatch_action(
-                                Box::new(zed_actions::DecreaseBufferFontSize { persist: false }),
-                                cx,
-                            );
+                            theme_settings::decrease_buffer_font_size(cx);
                         }
 
                         cx.stop_propagation();
@@ -7701,10 +7697,7 @@ impl EditorElement {
                             }
                         };
 
-                        delta = delta.coalesce(event.delta);
                         editor.update(cx, |editor, cx| {
-                            let position_map: &PositionMap = &position_map;
-
                             let line_height = position_map.line_height;
                             let glyph_width = position_map.em_layout_width;
                             let (delta, axis) = match delta {

crates/gpui_linux/src/linux/x11/client.rs 🔗

@@ -214,6 +214,8 @@ pub struct X11ClientState {
 
     pointer_device_states: BTreeMap<xinput::DeviceId, PointerDeviceState>,
 
+    pub(crate) supports_xinput_gestures: bool,
+
     pub(crate) common: LinuxCommon,
     pub(crate) clipboard: Clipboard,
     pub(crate) clipboard_item: Option<ClipboardItem>,
@@ -345,7 +347,8 @@ impl X11Client {
 
         // Announce to X server that XInput up to 2.4 is supported.
         // Version 2.4 is needed for gesture events (GesturePinchBegin/Update/End).
-        // If the server only supports an older version, gesture events simply won't be delivered.
+        // The server responds with the highest version it supports; if < 2.4,
+        // we must not request gesture event masks in XISelectEvents.
         let xinput_version = get_reply(
             || "XInput XiQueryVersion failed",
             xcb_connection.xinput_xi_query_version(2, 4),
@@ -354,6 +357,14 @@ impl X11Client {
             xinput_version.major_version >= 2,
             "XInput version >= 2 required."
         );
+        let supports_xinput_gestures = xinput_version.major_version > 2
+            || (xinput_version.major_version == 2 && xinput_version.minor_version >= 4);
+        log::info!(
+            "XInput version: {}.{}, gesture support: {}",
+            xinput_version.major_version,
+            xinput_version.minor_version,
+            supports_xinput_gestures,
+        );
 
         let pointer_device_states =
             current_pointer_device_states(&xcb_connection, &BTreeMap::new()).unwrap_or_default();
@@ -535,6 +546,8 @@ impl X11Client {
 
             pointer_device_states,
 
+            supports_xinput_gestures,
+
             clipboard,
             clipboard_item: None,
             xdnd_state: Xdnd::default(),
@@ -1593,6 +1606,7 @@ impl LinuxClient for X11Client {
         let scale_factor = state.scale_factor;
         let appearance = state.common.appearance;
         let compositor_gpu = state.compositor_gpu.take();
+        let supports_xinput_gestures = state.supports_xinput_gestures;
         let window = X11Window::new(
             handle,
             X11ClientStatePtr(Rc::downgrade(&self.0)),
@@ -1608,6 +1622,7 @@ impl LinuxClient for X11Client {
             scale_factor,
             appearance,
             parent_window,
+            supports_xinput_gestures,
         )?;
         check_reply(
             || "Failed to set XdndAware property",

crates/gpui_linux/src/linux/x11/window.rs 🔗

@@ -423,6 +423,7 @@ impl X11WindowState {
         scale_factor: f32,
         appearance: WindowAppearance,
         parent_window: Option<X11WindowStatePtr>,
+        supports_xinput_gestures: bool,
     ) -> anyhow::Result<Self> {
         let x_screen_index = params
             .display_id
@@ -660,25 +661,27 @@ impl X11WindowState {
                 ),
             )?;
 
+            let mut xi_event_mask = xinput::XIEventMask::MOTION
+                | xinput::XIEventMask::BUTTON_PRESS
+                | xinput::XIEventMask::BUTTON_RELEASE
+                | xinput::XIEventMask::ENTER
+                | xinput::XIEventMask::LEAVE;
+            if supports_xinput_gestures {
+                // x11rb 0.13 doesn't define XIEventMask constants for gesture
+                // events, so we construct them from the event opcodes (each
+                // XInput event type N maps to mask bit N).
+                xi_event_mask |=
+                    xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_BEGIN_EVENT)
+                        | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_UPDATE_EVENT)
+                        | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_END_EVENT);
+            }
             check_reply(
                 || "X11 XiSelectEvents failed.",
                 xcb.xinput_xi_select_events(
                     x_window,
                     &[xinput::EventMask {
                         deviceid: XINPUT_ALL_DEVICE_GROUPS,
-                        mask: vec![
-                            xinput::XIEventMask::MOTION
-                                | xinput::XIEventMask::BUTTON_PRESS
-                                | xinput::XIEventMask::BUTTON_RELEASE
-                                | xinput::XIEventMask::ENTER
-                                | xinput::XIEventMask::LEAVE
-                                // x11rb 0.13 doesn't define XIEventMask constants for gesture
-                                // events, so we construct them from the event opcodes (each
-                                // XInput event type N maps to mask bit N).
-                                | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_BEGIN_EVENT)
-                                | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_UPDATE_EVENT)
-                                | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_END_EVENT),
-                        ],
+                        mask: vec![xi_event_mask],
                     }],
                 ),
             )?;
@@ -855,6 +858,7 @@ impl X11Window {
         scale_factor: f32,
         appearance: WindowAppearance,
         parent_window: Option<X11WindowStatePtr>,
+        supports_xinput_gestures: bool,
     ) -> anyhow::Result<Self> {
         let ptr = X11WindowStatePtr {
             state: Rc::new(RefCell::new(X11WindowState::new(
@@ -872,6 +876,7 @@ impl X11Window {
                 scale_factor,
                 appearance,
                 parent_window,
+                supports_xinput_gestures,
             )?)),
             callbacks: Rc::new(RefCell::new(Callbacks::default())),
             xcb: xcb.clone(),

crates/inspector_ui/src/div_inspector.rs 🔗

@@ -498,6 +498,7 @@ impl DivInspector {
             editor.set_show_breakpoints(false, cx);
             editor.set_show_git_diff_gutter(false, cx);
             editor.set_show_runnables(false, cx);
+            editor.disable_mouse_wheel_zoom();
             editor.set_show_edit_predictions(Some(false), window, cx);
             editor.set_minimap_visibility(MinimapVisibility::Disabled, window, cx);
             editor

crates/keymap_editor/src/keymap_editor.rs 🔗

@@ -3318,6 +3318,7 @@ impl ActionArgumentsEditor {
                         window,
                         cx,
                     );
+                    editor.disable_mouse_wheel_zoom();
                     editor.set_searchable(false);
                     editor.disable_scrollbars_and_minimap(window, cx);
                     editor.set_show_edit_predictions(Some(false), window, cx);

crates/repl/src/notebook/cell.rs 🔗

@@ -378,6 +378,7 @@ impl MarkdownCell {
             editor.set_show_gutter(false, cx);
             editor.set_text_style_refinement(refinement);
             editor.set_use_modal_editing(true);
+            editor.disable_mouse_wheel_zoom();
             editor
         });
 
@@ -641,6 +642,7 @@ impl CodeCell {
                 ..Default::default()
             };
 
+            editor.disable_mouse_wheel_zoom();
             editor.set_show_gutter(false, cx);
             editor.set_text_style_refinement(refinement);
             editor.set_use_modal_editing(true);
@@ -718,6 +720,7 @@ impl CodeCell {
                 ..Default::default()
             };
 
+            editor.disable_mouse_wheel_zoom();
             editor.set_text(source.clone(), window, cx);
             editor.set_show_gutter(false, cx);
             editor.set_text_style_refinement(refinement);

crates/sidebar/src/sidebar.rs 🔗

@@ -1771,6 +1771,7 @@ impl Sidebar {
 
                 let menu =
                     ContextMenu::build_persistent(window, cx, move |menu, _window, menu_cx| {
+                        let weak_menu = menu_cx.weak_entity();
                         let mut menu = menu
                             .header("Project Folders")
                             .end_slot_action(Box::new(menu::EndSlot));
@@ -1783,6 +1784,7 @@ impl Sidebar {
                             let path = path.clone();
                             let project_group_key = project_group_key.clone();
                             let multi_workspace = multi_workspace.clone();
+                            let weak_menu = weak_menu.clone();
                             menu = menu.entry_with_end_slot_on_hover(
                                 name.clone(),
                                 None,
@@ -1799,6 +1801,7 @@ impl Sidebar {
                                             );
                                         })
                                         .ok();
+                                    weak_menu.update(cx, |_, cx| cx.emit(DismissEvent)).ok();
                                 },
                             );
                         }
@@ -1809,6 +1812,7 @@ impl Sidebar {
                             {
                                 let project_group_key = project_group_key.clone();
                                 let multi_workspace = multi_workspace.clone();
+                                let weak_menu = weak_menu.clone();
                                 move |window, cx| {
                                     multi_workspace
                                         .update(cx, |multi_workspace, cx| {
@@ -1819,13 +1823,13 @@ impl Sidebar {
                                             );
                                         })
                                         .ok();
+                                    weak_menu.update(cx, |_, cx| cx.emit(DismissEvent)).ok();
                                 }
                             },
                         );
 
                         let project_group_key = project_group_key.clone();
                         let multi_workspace = multi_workspace.clone();
-                        let weak_menu = menu_cx.weak_entity();
                         menu.separator()
                             .entry("Remove Project", None, move |window, cx| {
                                 multi_workspace

crates/terminal_view/src/terminal_view.rs 🔗

@@ -1356,7 +1356,9 @@ impl Item for TerminalView {
         h_flex()
             .gap_1()
             .group("term-tab-icon")
-            .track_focus(&self.focus_handle)
+            .when(!params.selected, |this| {
+                this.track_focus(&self.focus_handle)
+            })
             .on_action(move |action: &RenameTerminal, window, cx| {
                 self_handle
                     .update(cx, |this, cx| this.rename_terminal(action, window, cx))

crates/theme_settings/src/settings.rs 🔗

@@ -490,7 +490,8 @@ pub fn adjusted_font_size(size: Pixels, cx: &App) -> Pixels {
     clamp_font_size(adjusted_font_size)
 }
 
-/// Adjusts the buffer font size.
+/// Adjusts the buffer font size, without persisting the result in the settings.
+/// This will be effective until the app is restarted.
 pub fn adjust_buffer_font_size(cx: &mut App, f: impl FnOnce(Pixels) -> Pixels) {
     let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size;
     let adjusted_size = cx

crates/theme_settings/src/theme_settings.rs 🔗

@@ -12,7 +12,7 @@ use std::sync::Arc;
 
 use ::settings::{IntoGpui, Settings, SettingsStore};
 use anyhow::{Context as _, Result};
-use gpui::{App, Font, HighlightStyle, Pixels, Refineable};
+use gpui::{App, Font, HighlightStyle, Pixels, Refineable, px};
 use gpui_util::ResultExt;
 use theme::{
     AccentColors, Appearance, AppearanceContent, DEFAULT_DARK_THEME, DEFAULT_ICON_THEME_NAME,
@@ -26,11 +26,12 @@ pub use crate::schema::{
     ThemeColorsContent, ThemeContent, ThemeFamilyContent, ThemeStyleContent,
     WindowBackgroundContent, status_colors_refinement, syntax_overrides, theme_colors_refinement,
 };
+use crate::settings::adjust_buffer_font_size;
 pub use crate::settings::{
     AgentFontSize, BufferLineHeight, FontFamilyName, IconThemeName, IconThemeSelection,
     ThemeAppearanceMode, ThemeName, ThemeSelection, ThemeSettings, adjust_agent_buffer_font_size,
-    adjust_agent_ui_font_size, adjust_buffer_font_size, adjust_ui_font_size, adjusted_font_size,
-    appearance_to_mode, clamp_font_size, default_theme, observe_buffer_font_size_adjustment,
+    adjust_agent_ui_font_size, adjust_ui_font_size, adjusted_font_size, appearance_to_mode,
+    clamp_font_size, default_theme, observe_buffer_font_size_adjustment,
     reset_agent_buffer_font_size, reset_agent_ui_font_size, reset_buffer_font_size,
     reset_ui_font_size, set_icon_theme, set_mode, set_theme, setup_ui_font,
 };
@@ -410,3 +411,15 @@ pub fn merge_accent_colors(
         accent_colors.0 = Arc::from(colors);
     }
 }
+
+/// Increases the buffer font size by 1 pixel, without persisting the result in the settings.
+/// This will be effective until the app is restarted.
+pub fn increase_buffer_font_size(cx: &mut App) {
+    adjust_buffer_font_size(cx, |size| size + px(1.0));
+}
+
+/// Decreases the buffer font size by 1 pixel, without persisting the result in the settings.
+/// This will be effective until the app is restarted.
+pub fn decrease_buffer_font_size(cx: &mut App) {
+    adjust_buffer_font_size(cx, |size| size - px(1.0));
+}

crates/zed/src/zed.rs 🔗

@@ -928,7 +928,7 @@ fn register_actions(
                             .insert(f32::from(theme_settings::clamp_font_size(buffer_font_size)).into());
                     });
                 } else {
-                    theme_settings::adjust_buffer_font_size(cx, |size| size + px(1.0));
+                    theme_settings::increase_buffer_font_size(cx);
                 }
             }
         })
@@ -945,7 +945,7 @@ fn register_actions(
                             .insert(f32::from(theme_settings::clamp_font_size(buffer_font_size)).into());
                     });
                 } else {
-                    theme_settings::adjust_buffer_font_size(cx, |size| size - px(1.0));
+                    theme_settings::decrease_buffer_font_size(cx);
                 }
             }
         })

tooling/xtask/src/tasks/workflows/autofix_pr.rs 🔗

@@ -62,12 +62,11 @@ fn run_autofix(pr_number: &WorkflowInput, run_clippy: &WorkflowInput) -> NamedJo
 
     fn install_cargo_machete() -> Step<Use> {
         named::uses(
-            "clechasseur",
-            "rs-cargo",
-            "8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386", // v2
+            "taiki-e",
+            "install-action",
+            "02cc5f8ca9f2301050c0c099055816a41ee05507",
         )
-        .add_with(("command", "install"))
-        .add_with(("args", "cargo-machete@0.7.0"))
+        .add_with(("tool", "cargo-machete@0.7.0"))
     }
 
     fn run_cargo_fmt() -> Step<Run> {

tooling/xtask/src/tasks/workflows/run_tests.rs 🔗

@@ -408,21 +408,15 @@ fn check_style() -> NamedJob {
 fn check_dependencies() -> NamedJob {
     fn install_cargo_machete() -> Step<Use> {
         named::uses(
-            "clechasseur",
-            "rs-cargo",
-            "8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386", // v2
+            "taiki-e",
+            "install-action",
+            "02cc5f8ca9f2301050c0c099055816a41ee05507",
         )
-        .add_with(("command", "install"))
-        .add_with(("args", "cargo-machete@0.7.0"))
+        .add_with(("tool", "cargo-machete@0.7.0"))
     }
 
-    fn run_cargo_machete() -> Step<Use> {
-        named::uses(
-            "clechasseur",
-            "rs-cargo",
-            "8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386", // v2
-        )
-        .add_with(("command", "machete"))
+    fn run_cargo_machete() -> Step<Run> {
+        named::bash("cargo machete")
     }
 
     fn check_cargo_lock() -> Step<Run> {