diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index e23f464569..7d9ca68a82 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -1110,6 +1110,10 @@ impl AppContext { } } } + + pub fn has_active_drag(&self) -> bool { + self.active_drag.is_some() + } } impl Context for AppContext { diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 2d48ec5a11..84636630f3 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -193,6 +193,12 @@ impl Deref for MouseExitEvent { #[derive(Debug, Clone, Default)] pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>); +impl ExternalPaths { + pub fn paths(&self) -> &[PathBuf] { + &self.0 + } +} + impl Render for ExternalPaths { type Element = Div; diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 1e26a7cf07..cab41067ce 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -4,12 +4,12 @@ use crate::{ DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model, - ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent, - MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, - PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, - RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, - Style, SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task, Underline, - UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, + ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent, Path, + Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, + PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, + RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, SubscriberSet, + Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext, + WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, }; use anyhow::{anyhow, Context as _, Result}; use collections::HashMap; @@ -1269,10 +1269,9 @@ impl<'a> WindowContext<'a> { cursor_offset: position, }); } - InputEvent::MouseDown(MouseDownEvent { + InputEvent::MouseMove(MouseMoveEvent { position, - button: MouseButton::Left, - click_count: 1, + pressed_button: Some(MouseButton::Left), modifiers: Modifiers::default(), }) } @@ -1285,6 +1284,7 @@ impl<'a> WindowContext<'a> { }) } FileDropEvent::Submit { position } => { + self.activate(true); self.window.mouse_position = position; InputEvent::MouseUp(MouseUpEvent { button: MouseButton::Left, diff --git a/crates/gpui2_macros/src/action.rs b/crates/gpui2_macros/src/action.rs index abc75a8759..296e3f08b1 100644 --- a/crates/gpui2_macros/src/action.rs +++ b/crates/gpui2_macros/src/action.rs @@ -38,6 +38,7 @@ pub fn action(input: TokenStream) -> TokenStream { let build_impl = if is_unit_struct { quote! { + let _ = value; Ok(std::boxed::Box::new(Self {})) } } else { diff --git a/crates/recent_projects2/src/projects.rs b/crates/recent_projects2/src/projects.rs new file mode 100644 index 0000000000..2c4809dbd7 --- /dev/null +++ b/crates/recent_projects2/src/projects.rs @@ -0,0 +1 @@ +gpui::actions!(OpenRecent); diff --git a/crates/recent_projects2/src/recent_projects.rs b/crates/recent_projects2/src/recent_projects.rs index 0c11f2b9c7..d2c13b40a3 100644 --- a/crates/recent_projects2/src/recent_projects.rs +++ b/crates/recent_projects2/src/recent_projects.rs @@ -1,9 +1,10 @@ mod highlighted_workspace_location; +mod projects; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Result, Task, - View, ViewContext, WeakView, + AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Result, Task, View, + ViewContext, WeakView, }; use highlighted_workspace_location::HighlightedWorkspaceLocation; use ordered_float::OrderedFloat; @@ -16,7 +17,7 @@ use workspace::{ WORKSPACE_DB, }; -actions!(OpenRecent); +pub use projects::OpenRecent; pub fn init(cx: &mut AppContext) { cx.observe_new_views(RecentProjects::register).detach(); diff --git a/crates/terminal2/src/terminal2.rs b/crates/terminal2/src/terminal2.rs index 6036d65d6e..b429bda710 100644 --- a/crates/terminal2/src/terminal2.rs +++ b/crates/terminal2/src/terminal2.rs @@ -50,7 +50,7 @@ use std::{ use thiserror::Error; use gpui::{ - px, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, Hsla, Keystroke, + actions, px, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, Hsla, Keystroke, ModelContext, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, ScrollWheelEvent, Size, Task, TouchPhase, }; @@ -58,6 +58,16 @@ use gpui::{ use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str}; use lazy_static::lazy_static; +actions!( + Clear, + Copy, + Paste, + ShowCharacterPalette, + SearchTest, + SendText, + SendKeystroke, +); + ///Scrolling is unbearably sluggish by default. Alacritty supports a configurable ///Scroll multiplier that is set to 3 by default. This will be removed when I ///Implement scroll bars. diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index 4a37ca91b7..d61ba5988e 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -1,9 +1,9 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use gpui::{ black, div, point, px, red, relative, transparent_black, AnyElement, AsyncWindowContext, - AvailableSpace, Bounds, DispatchPhase, Element, ElementId, FocusHandle, Font, FontStyle, - FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, IntoElement, - LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels, + AvailableSpace, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, + FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, + IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, Size, StatefulInteractiveElement, Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, View, WhiteSpace, WindowContext, }; @@ -643,13 +643,11 @@ impl TerminalElement { let connection = connection.clone(); let focus = focus.clone(); move |e, cx| { - if e.pressed_button.is_some() { - if focus.is_focused(cx) { - connection.update(cx, |terminal, cx| { - terminal.mouse_drag(e, origin, bounds); - cx.notify(); - }) - } + if e.pressed_button.is_some() && focus.is_focused(cx) && !cx.has_active_drag() { + connection.update(cx, |terminal, cx| { + terminal.mouse_drag(e, origin, bounds); + cx.notify(); + }) } } }) @@ -806,7 +804,28 @@ impl Element for TerminalElement { .map(|cursor| cursor.bounding_rect(origin)), }; - let mut this = self.register_mouse_listeners(origin, layout.mode, bounds, cx); + let terminal_focus_handle = self.focus.clone(); + let terminal_handle = self.terminal.clone(); + let mut this: TerminalElement = self + .register_mouse_listeners(origin, layout.mode, bounds, cx) + .drag_over::(|style| { + // todo!() why does not it work? z-index of elements? + style.bg(cx.theme().colors().ghost_element_hover) + }) + .on_drop::(move |external_paths, cx| { + cx.focus(&terminal_focus_handle); + let mut new_text = external_paths + .read(cx) + .paths() + .iter() + .map(|path| format!(" {path:?}")) + .join(""); + new_text.push(' '); + terminal_handle.update(cx, |terminal, _| { + // todo!() long paths are not displayed properly albeit the text is there + terminal.paste(&new_text); + }); + }); let interactivity = mem::take(&mut this.interactivity); diff --git a/crates/terminal_view2/src/terminal_view.rs b/crates/terminal_view2/src/terminal_view.rs index 75b019f2ef..5a81b494b3 100644 --- a/crates/terminal_view2/src/terminal_view.rs +++ b/crates/terminal_view2/src/terminal_view.rs @@ -9,9 +9,9 @@ pub mod terminal_panel; // use crate::terminal_element::TerminalElement; use editor::{scroll::autoscroll::Autoscroll, Editor}; use gpui::{ - actions, div, Action, AnyElement, AppContext, Div, EventEmitter, FocusEvent, FocusHandle, - Focusable, FocusableElement, FocusableView, KeyContext, KeyDownEvent, Keystroke, Model, - MouseButton, MouseDownEvent, Pixels, Render, Subscription, Task, View, VisualContext, WeakView, + div, Action, AnyElement, AppContext, Div, EventEmitter, FocusEvent, FocusHandle, Focusable, + FocusableElement, FocusableView, KeyContext, KeyDownEvent, Keystroke, Model, MouseButton, + MouseDownEvent, Pixels, Render, Subscription, Task, View, VisualContext, WeakView, }; use language::Bias; use persistence::TERMINAL_DB; @@ -22,7 +22,7 @@ use terminal::{ term::{search::RegexSearch, TermMode}, }, terminal_settings::{TerminalBlink, TerminalSettings, WorkingDirectory}, - Event, MaybeNavigationTarget, Terminal, + Clear, Copy, Event, MaybeNavigationTarget, Paste, ShowCharacterPalette, Terminal, }; use terminal_element::TerminalElement; use ui::{h_stack, prelude::*, ContextMenu, Icon, IconElement, Label}; @@ -60,8 +60,6 @@ pub struct SendText(String); #[derive(Clone, Debug, Default, Deserialize, PartialEq, Action)] pub struct SendKeystroke(String); -actions!(Clear, Copy, Paste, ShowCharacterPalette, SearchTest); - pub fn init(cx: &mut AppContext) { terminal_panel::init(cx); terminal::init(cx); diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index a0a90293d6..7bae7bc419 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -133,13 +133,13 @@ pub struct Dock { panel_entries: Vec, is_open: bool, active_panel_index: usize, + focus_handle: FocusHandle, + focus_subscription: Subscription, } impl FocusableView for Dock { - fn focus_handle(&self, cx: &AppContext) -> FocusHandle { - self.panel_entries[self.active_panel_index] - .panel - .focus_handle(cx) + fn focus_handle(&self, _: &AppContext) -> FocusHandle { + self.focus_handle.clone() } } @@ -190,12 +190,20 @@ pub struct PanelButtons { } impl Dock { - pub fn new(position: DockPosition) -> Self { + pub fn new(position: DockPosition, cx: &mut ViewContext<'_, Self>) -> Self { + let focus_handle = cx.focus_handle(); + let focus_subscription = cx.on_focus(&focus_handle, |dock, cx| { + if let Some(active_entry) = dock.panel_entries.get(dock.active_panel_index) { + active_entry.panel.focus_handle(cx).focus(cx) + } + }); Self { position, panel_entries: Default::default(), active_panel_index: 0, is_open: false, + focus_handle, + focus_subscription, } } @@ -207,6 +215,7 @@ impl Dock { self.is_open } + // todo!() // pub fn has_focus(&self, cx: &WindowContext) -> bool { // self.visible_panel() // .map_or(false, |panel| panel.has_focus(cx)) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index abf9089929..50eb69eec5 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -566,9 +566,9 @@ impl Workspace { cx.emit(Event::WorkspaceCreated(weak_handle.clone())); - let left_dock = cx.build_view(|_| Dock::new(DockPosition::Left)); - let bottom_dock = cx.build_view(|_| Dock::new(DockPosition::Bottom)); - let right_dock = cx.build_view(|_| Dock::new(DockPosition::Right)); + let left_dock = cx.build_view(|cx| Dock::new(DockPosition::Left, cx)); + let bottom_dock = cx.build_view(|cx| Dock::new(DockPosition::Bottom, cx)); + let right_dock = cx.build_view(|cx| Dock::new(DockPosition::Right, cx)); let left_dock_buttons = cx.build_view(|cx| PanelButtons::new(left_dock.clone(), weak_handle.clone(), cx)); let bottom_dock_buttons =