mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-26 20:22:30 +00:00
Simulate mouse up if mouse was released outside window, don't report dragged payload if it was dragged from a different window
This commit is contained in:
parent
fa78b597f4
commit
227cc66594
4 changed files with 77 additions and 24 deletions
|
@ -9,6 +9,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct State<V: View> {
|
struct State<V: View> {
|
||||||
|
window_id: usize,
|
||||||
position: Vector2F,
|
position: Vector2F,
|
||||||
region_offset: Vector2F,
|
region_offset: Vector2F,
|
||||||
payload: Rc<dyn Any + 'static>,
|
payload: Rc<dyn Any + 'static>,
|
||||||
|
@ -18,6 +19,7 @@ struct State<V: View> {
|
||||||
impl<V: View> Clone for State<V> {
|
impl<V: View> Clone for State<V> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
window_id: self.window_id.clone(),
|
||||||
position: self.position.clone(),
|
position: self.position.clone(),
|
||||||
region_offset: self.region_offset.clone(),
|
region_offset: self.region_offset.clone(),
|
||||||
payload: self.payload.clone(),
|
payload: self.payload.clone(),
|
||||||
|
@ -46,11 +48,18 @@ impl<V: View> DragAndDrop<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn currently_dragged<T: Any>(&self) -> Option<(Vector2F, Rc<T>)> {
|
pub fn currently_dragged<T: Any>(&self, window_id: usize) -> Option<(Vector2F, Rc<T>)> {
|
||||||
self.currently_dragged.as_ref().and_then(
|
self.currently_dragged.as_ref().and_then(
|
||||||
|State {
|
|State {
|
||||||
position, payload, ..
|
position,
|
||||||
|
payload,
|
||||||
|
window_id: window_dragged_from,
|
||||||
|
..
|
||||||
}| {
|
}| {
|
||||||
|
if &window_id != window_dragged_from {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
payload
|
payload
|
||||||
.clone()
|
.clone()
|
||||||
.downcast::<T>()
|
.downcast::<T>()
|
||||||
|
@ -66,6 +75,7 @@ impl<V: View> DragAndDrop<V> {
|
||||||
cx: &mut EventContext,
|
cx: &mut EventContext,
|
||||||
render: Rc<impl 'static + Fn(&T, &mut RenderContext<V>) -> ElementBox>,
|
render: Rc<impl 'static + Fn(&T, &mut RenderContext<V>) -> ElementBox>,
|
||||||
) {
|
) {
|
||||||
|
let window_id = cx.window_id();
|
||||||
cx.update_global::<Self, _, _>(|this, cx| {
|
cx.update_global::<Self, _, _>(|this, cx| {
|
||||||
let region_offset = if let Some(previous_state) = this.currently_dragged.as_ref() {
|
let region_offset = if let Some(previous_state) = this.currently_dragged.as_ref() {
|
||||||
previous_state.region_offset
|
previous_state.region_offset
|
||||||
|
@ -74,6 +84,7 @@ impl<V: View> DragAndDrop<V> {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.currently_dragged = Some(State {
|
this.currently_dragged = Some(State {
|
||||||
|
window_id,
|
||||||
region_offset,
|
region_offset,
|
||||||
position: event.position,
|
position: event.position,
|
||||||
payload,
|
payload,
|
||||||
|
@ -91,34 +102,46 @@ impl<V: View> DragAndDrop<V> {
|
||||||
pub fn render(cx: &mut RenderContext<V>) -> Option<ElementBox> {
|
pub fn render(cx: &mut RenderContext<V>) -> Option<ElementBox> {
|
||||||
let currently_dragged = cx.global::<Self>().currently_dragged.clone();
|
let currently_dragged = cx.global::<Self>().currently_dragged.clone();
|
||||||
|
|
||||||
currently_dragged.map(
|
currently_dragged.and_then(
|
||||||
|State {
|
|State {
|
||||||
|
window_id,
|
||||||
region_offset,
|
region_offset,
|
||||||
position,
|
position,
|
||||||
payload,
|
payload,
|
||||||
render,
|
render,
|
||||||
}| {
|
}| {
|
||||||
|
if cx.window_id() != window_id {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let position = position + region_offset;
|
let position = position + region_offset;
|
||||||
|
|
||||||
MouseEventHandler::new::<Self, _, _>(0, cx, |_, cx| {
|
Some(
|
||||||
Container::new(render(payload, cx))
|
MouseEventHandler::new::<Self, _, _>(0, cx, |_, cx| {
|
||||||
.with_margin_left(position.x())
|
Container::new(render(payload, cx))
|
||||||
.with_margin_top(position.y())
|
.with_margin_left(position.x())
|
||||||
.aligned()
|
.with_margin_top(position.y())
|
||||||
.top()
|
.aligned()
|
||||||
.left()
|
.top()
|
||||||
.boxed()
|
.left()
|
||||||
})
|
.boxed()
|
||||||
.with_cursor_style(CursorStyle::Arrow)
|
})
|
||||||
.on_up(MouseButton::Left, |_, cx| {
|
.with_cursor_style(CursorStyle::Arrow)
|
||||||
cx.defer(|cx| {
|
.on_up(MouseButton::Left, |_, cx| {
|
||||||
cx.update_global::<Self, _, _>(|this, _| this.currently_dragged.take());
|
cx.defer(|cx| {
|
||||||
});
|
cx.update_global::<Self, _, _>(|this, _| this.currently_dragged.take());
|
||||||
cx.propogate_event();
|
});
|
||||||
})
|
cx.propogate_event();
|
||||||
// Don't block hover events or invalidations
|
})
|
||||||
.with_hoverable(false)
|
.on_up_out(MouseButton::Left, |_, cx| {
|
||||||
.boxed()
|
cx.defer(|cx| {
|
||||||
|
cx.update_global::<Self, _, _>(|this, _| this.currently_dragged.take());
|
||||||
|
});
|
||||||
|
})
|
||||||
|
// Don't block hover events or invalidations
|
||||||
|
.with_hoverable(false)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,20 @@ pub struct MouseMovedEvent {
|
||||||
pub shift: bool,
|
pub shift: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MouseMovedEvent {
|
||||||
|
pub fn to_button_event(&self, button: MouseButton) -> MouseButtonEvent {
|
||||||
|
MouseButtonEvent {
|
||||||
|
position: self.position,
|
||||||
|
button: self.pressed_button.unwrap_or(button),
|
||||||
|
ctrl: self.ctrl,
|
||||||
|
alt: self.alt,
|
||||||
|
shift: self.shift,
|
||||||
|
cmd: self.cmd,
|
||||||
|
click_count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
KeyDown(KeyDownEvent),
|
KeyDown(KeyDownEvent),
|
||||||
|
|
|
@ -310,7 +310,23 @@ impl Presenter {
|
||||||
prev_mouse_position: self.mouse_position,
|
prev_mouse_position: self.mouse_position,
|
||||||
platform_event: e.clone(),
|
platform_event: e.clone(),
|
||||||
}));
|
}));
|
||||||
|
} else if let Some(clicked_button) = self.clicked_button {
|
||||||
|
// Mouse up event happened outside the current window. Simulate mouse up button event
|
||||||
|
let button_event = e.to_button_event(clicked_button);
|
||||||
|
events_to_send.push(MouseRegionEvent::Up(UpRegionEvent {
|
||||||
|
region: Default::default(),
|
||||||
|
platform_event: button_event.clone(),
|
||||||
|
}));
|
||||||
|
events_to_send.push(MouseRegionEvent::UpOut(UpOutRegionEvent {
|
||||||
|
region: Default::default(),
|
||||||
|
platform_event: button_event.clone(),
|
||||||
|
}));
|
||||||
|
events_to_send.push(MouseRegionEvent::Click(ClickRegionEvent {
|
||||||
|
region: Default::default(),
|
||||||
|
platform_event: button_event.clone(),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
events_to_send.push(MouseRegionEvent::Move(MoveRegionEvent {
|
events_to_send.push(MouseRegionEvent::Move(MoveRegionEvent {
|
||||||
region: Default::default(),
|
region: Default::default(),
|
||||||
platform_event: e.clone(),
|
platform_event: e.clone(),
|
||||||
|
|
|
@ -1256,7 +1256,7 @@ impl Pane {
|
||||||
fn handle_dropped_item(pane: &WeakViewHandle<Pane>, index: usize, cx: &mut EventContext) {
|
fn handle_dropped_item(pane: &WeakViewHandle<Pane>, index: usize, cx: &mut EventContext) {
|
||||||
if let Some((_, dragged_item)) = cx
|
if let Some((_, dragged_item)) = cx
|
||||||
.global::<DragAndDrop<Workspace>>()
|
.global::<DragAndDrop<Workspace>>()
|
||||||
.currently_dragged::<DraggedItem>()
|
.currently_dragged::<DraggedItem>(cx.window_id)
|
||||||
{
|
{
|
||||||
cx.dispatch_action(MoveItem {
|
cx.dispatch_action(MoveItem {
|
||||||
item_id: dragged_item.item.id(),
|
item_id: dragged_item.item.id(),
|
||||||
|
@ -1277,7 +1277,7 @@ impl Pane {
|
||||||
if hovered
|
if hovered
|
||||||
&& cx
|
&& cx
|
||||||
.global::<DragAndDrop<Workspace>>()
|
.global::<DragAndDrop<Workspace>>()
|
||||||
.currently_dragged::<DraggedItem>()
|
.currently_dragged::<DraggedItem>(cx.window_id())
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
Some(theme.workspace.tab_bar.drop_target_overlay_color)
|
Some(theme.workspace.tab_bar.drop_target_overlay_color)
|
||||||
|
|
Loading…
Reference in a new issue