From 87c92f3db314061f79d6945a9bd8d22227915d4f Mon Sep 17 00:00:00 2001 From: Albab Hasan <155961300+Albab-Hasan@users.noreply.github.com> Date: Mon, 9 Feb 2026 04:53:21 +0600 Subject: [PATCH] gpui: Reset `external_files_dragged` after successful drag-drop on macOS (#48727) after a successful file drag-drop, conclude_drag_operation did not reset external_files_dragged to false. since dragging_exited (the only place that resets this flag) is never called for successful drops (only for cancelled ones), the flag stayed true permanently. this caused synthetic drags (used for text selection during buffer scrolling) to be suppressed for the lifetime of the window. Release Notes: - N/A --------- Co-authored-by: MrSubidubi --- crates/gpui/src/platform/mac/window.rs | 53 +++++++++++++------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 65d75c6712d03c14b3bbd26e005d4d7ef66c1444..5d067c1ba0366fa930da68eb68a52301f271b056 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -2454,11 +2454,9 @@ extern "C" fn dragging_entered(this: &Object, _: Sel, dragging_info: id) -> NSDr let window_state = unsafe { get_window_state(this) }; let position = drag_event_position(&window_state, dragging_info); let paths = external_paths_from_event(dragging_info); - if let Some(event) = - paths.map(|paths| PlatformInput::FileDrop(FileDropEvent::Entered { position, paths })) - && send_new_event(&window_state, event) + if let Some(event) = paths.map(|paths| FileDropEvent::Entered { position, paths }) + && send_file_drop_event(window_state, event) { - window_state.lock().external_files_dragged = true; return NSDragOperationCopy; } NSDragOperationNone @@ -2467,10 +2465,7 @@ extern "C" fn dragging_entered(this: &Object, _: Sel, dragging_info: id) -> NSDr extern "C" fn dragging_updated(this: &Object, _: Sel, dragging_info: id) -> NSDragOperation { let window_state = unsafe { get_window_state(this) }; let position = drag_event_position(&window_state, dragging_info); - if send_new_event( - &window_state, - PlatformInput::FileDrop(FileDropEvent::Pending { position }), - ) { + if send_file_drop_event(window_state, FileDropEvent::Pending { position }) { NSDragOperationCopy } else { NSDragOperationNone @@ -2479,21 +2474,13 @@ extern "C" fn dragging_updated(this: &Object, _: Sel, dragging_info: id) -> NSDr extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) { let window_state = unsafe { get_window_state(this) }; - send_new_event( - &window_state, - PlatformInput::FileDrop(FileDropEvent::Exited), - ); - window_state.lock().external_files_dragged = false; + send_file_drop_event(window_state, FileDropEvent::Exited); } extern "C" fn perform_drag_operation(this: &Object, _: Sel, dragging_info: id) -> BOOL { let window_state = unsafe { get_window_state(this) }; let position = drag_event_position(&window_state, dragging_info); - send_new_event( - &window_state, - PlatformInput::FileDrop(FileDropEvent::Submit { position }), - ) - .to_objc() + send_file_drop_event(window_state, FileDropEvent::Submit { position }).to_objc() } fn external_paths_from_event(dragging_info: *mut Object) -> Option { @@ -2515,10 +2502,7 @@ fn external_paths_from_event(dragging_info: *mut Object) -> Option, e: PlatformInput) -> bool { - let window_state = window_state_lock.lock().event_callback.take(); - if let Some(mut callback) = window_state { - callback(e); - window_state_lock.lock().event_callback = Some(callback); +/// Sends the specified FileDropEvent using `PlatformInput::FileDrop` to the window +/// state and updates the window state according to the event passed. +fn send_file_drop_event( + window_state: Arc>, + file_drop_event: FileDropEvent, +) -> bool { + let mut window_state = window_state.lock(); + let window_event_callback = window_state.event_callback.as_mut(); + if let Some(mut callback) = window_event_callback { + let external_files_dragged = match file_drop_event { + FileDropEvent::Entered { .. } => Some(true), + FileDropEvent::Exited => Some(false), + _ => None, + }; + + callback(PlatformInput::FileDrop(file_drop_event)); + + if let Some(external_files_dragged) = external_files_dragged { + window_state.external_files_dragged = external_files_dragged; + } true } else { false