Merge pull request #2053 from zed-industries/on-move-out
Hide hovers when mouse leaves area & window focus is lost
This commit is contained in:
commit
b54b77b9ec
9 changed files with 105 additions and 38 deletions
|
@ -44,7 +44,7 @@ use gpui::{
|
||||||
ViewContext, ViewHandle, WeakViewHandle,
|
ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||||
use hover_popover::{hide_hover, HoverState};
|
use hover_popover::{hide_hover, HideHover, HoverState};
|
||||||
pub use items::MAX_TAB_TITLE_LEN;
|
pub use items::MAX_TAB_TITLE_LEN;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
pub use language::{char_kind, CharKind};
|
pub use language::{char_kind, CharKind};
|
||||||
|
@ -1321,7 +1321,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hide_hover(self, cx);
|
hide_hover(self, &HideHover, cx);
|
||||||
|
|
||||||
if old_cursor_position.to_display_point(&display_map).row()
|
if old_cursor_position.to_display_point(&display_map).row()
|
||||||
!= new_cursor_position.to_display_point(&display_map).row()
|
!= new_cursor_position.to_display_point(&display_map).row()
|
||||||
|
@ -1696,7 +1696,7 @@ impl Editor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if hide_hover(self, cx) {
|
if hide_hover(self, &HideHover, cx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6176,7 +6176,7 @@ impl View for Editor {
|
||||||
cx.defer(move |cx| {
|
cx.defer(move |cx| {
|
||||||
if let Some(editor) = handle.upgrade(cx) {
|
if let Some(editor) = handle.upgrade(cx) {
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
hide_hover(editor, cx);
|
hide_hover(editor, &HideHover, cx);
|
||||||
hide_link_definition(editor, cx);
|
hide_link_definition(editor, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -6225,7 +6225,7 @@ impl View for Editor {
|
||||||
self.buffer
|
self.buffer
|
||||||
.update(cx, |buffer, cx| buffer.remove_active_selections(cx));
|
.update(cx, |buffer, cx| buffer.remove_active_selections(cx));
|
||||||
self.hide_context_menu(cx);
|
self.hide_context_menu(cx);
|
||||||
hide_hover(self, cx);
|
hide_hover(self, &HideHover, cx);
|
||||||
cx.emit(Event::Blurred);
|
cx.emit(Event::Blurred);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
display_map::{BlockStyle, DisplaySnapshot, TransformBlock},
|
display_map::{BlockStyle, DisplaySnapshot, TransformBlock},
|
||||||
git::{diff_hunk_to_display, DisplayDiffHunk},
|
git::{diff_hunk_to_display, DisplayDiffHunk},
|
||||||
hover_popover::{
|
hover_popover::{
|
||||||
HoverAt, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT,
|
HideHover, HoverAt, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT,
|
||||||
},
|
},
|
||||||
link_go_to_definition::{
|
link_go_to_definition::{
|
||||||
GoToFetchedDefinition, GoToFetchedTypeDefinition, UpdateGoToDefinitionLink,
|
GoToFetchedDefinition, GoToFetchedTypeDefinition, UpdateGoToDefinitionLink,
|
||||||
|
@ -114,6 +114,7 @@ impl EditorElement {
|
||||||
fn attach_mouse_handlers(
|
fn attach_mouse_handlers(
|
||||||
view: &WeakViewHandle<Editor>,
|
view: &WeakViewHandle<Editor>,
|
||||||
position_map: &Arc<PositionMap>,
|
position_map: &Arc<PositionMap>,
|
||||||
|
has_popovers: bool,
|
||||||
visible_bounds: RectF,
|
visible_bounds: RectF,
|
||||||
text_bounds: RectF,
|
text_bounds: RectF,
|
||||||
gutter_bounds: RectF,
|
gutter_bounds: RectF,
|
||||||
|
@ -190,6 +191,11 @@ impl EditorElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.on_move_out(move |_, cx| {
|
||||||
|
if has_popovers {
|
||||||
|
cx.dispatch_action(HideHover);
|
||||||
|
}
|
||||||
|
})
|
||||||
.on_scroll({
|
.on_scroll({
|
||||||
let position_map = position_map.clone();
|
let position_map = position_map.clone();
|
||||||
move |e, cx| {
|
move |e, cx| {
|
||||||
|
@ -1870,6 +1876,7 @@ impl Element for EditorElement {
|
||||||
Self::attach_mouse_handlers(
|
Self::attach_mouse_handlers(
|
||||||
&self.view,
|
&self.view,
|
||||||
&layout.position_map,
|
&layout.position_map,
|
||||||
|
layout.hover_popovers.is_some(),
|
||||||
visible_bounds,
|
visible_bounds,
|
||||||
text_bounds,
|
text_bounds,
|
||||||
gutter_bounds,
|
gutter_bounds,
|
||||||
|
|
|
@ -29,12 +29,16 @@ pub struct HoverAt {
|
||||||
pub point: Option<DisplayPoint>,
|
pub point: Option<DisplayPoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
pub struct HideHover;
|
||||||
|
|
||||||
actions!(editor, [Hover]);
|
actions!(editor, [Hover]);
|
||||||
impl_internal_actions!(editor, [HoverAt]);
|
impl_internal_actions!(editor, [HoverAt, HideHover]);
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(hover);
|
cx.add_action(hover);
|
||||||
cx.add_action(hover_at);
|
cx.add_action(hover_at);
|
||||||
|
cx.add_action(hide_hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bindable action which uses the most recent selection head to trigger a hover
|
/// Bindable action which uses the most recent selection head to trigger a hover
|
||||||
|
@ -50,7 +54,7 @@ pub fn hover_at(editor: &mut Editor, action: &HoverAt, cx: &mut ViewContext<Edit
|
||||||
if let Some(point) = action.point {
|
if let Some(point) = action.point {
|
||||||
show_hover(editor, point, false, cx);
|
show_hover(editor, point, false, cx);
|
||||||
} else {
|
} else {
|
||||||
hide_hover(editor, cx);
|
hide_hover(editor, &HideHover, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +62,7 @@ pub fn hover_at(editor: &mut Editor, action: &HoverAt, cx: &mut ViewContext<Edit
|
||||||
/// Hides the type information popup.
|
/// Hides the type information popup.
|
||||||
/// Triggered by the `Hover` action when the cursor is not over a symbol or when the
|
/// Triggered by the `Hover` action when the cursor is not over a symbol or when the
|
||||||
/// selections changed.
|
/// selections changed.
|
||||||
pub fn hide_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
|
pub fn hide_hover(editor: &mut Editor, _: &HideHover, cx: &mut ViewContext<Editor>) -> bool {
|
||||||
let did_hide = editor.hover_state.info_popover.take().is_some()
|
let did_hide = editor.hover_state.info_popover.take().is_some()
|
||||||
| editor.hover_state.diagnostic_popover.take().is_some();
|
| editor.hover_state.diagnostic_popover.take().is_some();
|
||||||
|
|
||||||
|
@ -67,6 +71,10 @@ pub fn hide_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
|
||||||
|
|
||||||
editor.clear_background_highlights::<HoverState>(cx);
|
editor.clear_background_highlights::<HoverState>(cx);
|
||||||
|
|
||||||
|
if did_hide {
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
did_hide
|
did_hide
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +129,7 @@ fn show_hover(
|
||||||
// Hover triggered from same location as last time. Don't show again.
|
// Hover triggered from same location as last time. Don't show again.
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
hide_hover(editor, cx);
|
hide_hover(editor, &HideHover, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use workspace::WorkspaceId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||||
hover_popover::hide_hover,
|
hover_popover::{hide_hover, HideHover},
|
||||||
persistence::DB,
|
persistence::DB,
|
||||||
Anchor, DisplayPoint, Editor, EditorMode, Event, MultiBufferSnapshot, ToPoint,
|
Anchor, DisplayPoint, Editor, EditorMode, Event, MultiBufferSnapshot, ToPoint,
|
||||||
};
|
};
|
||||||
|
@ -307,7 +307,7 @@ impl Editor {
|
||||||
) {
|
) {
|
||||||
let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
|
|
||||||
hide_hover(self, cx);
|
hide_hover(self, &HideHover, cx);
|
||||||
self.scroll_manager.set_scroll_position(
|
self.scroll_manager.set_scroll_position(
|
||||||
scroll_position,
|
scroll_position,
|
||||||
&map,
|
&map,
|
||||||
|
@ -323,7 +323,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
|
pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
|
||||||
hide_hover(self, cx);
|
hide_hover(self, &HideHover, cx);
|
||||||
let top_row = scroll_anchor
|
let top_row = scroll_anchor
|
||||||
.top_anchor
|
.top_anchor
|
||||||
.to_point(&self.buffer().read(cx).snapshot(cx))
|
.to_point(&self.buffer().read(cx).snapshot(cx))
|
||||||
|
@ -337,7 +337,7 @@ impl Editor {
|
||||||
scroll_anchor: ScrollAnchor,
|
scroll_anchor: ScrollAnchor,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
hide_hover(self, cx);
|
hide_hover(self, &HideHover, cx);
|
||||||
let top_row = scroll_anchor
|
let top_row = scroll_anchor
|
||||||
.top_anchor
|
.top_anchor
|
||||||
.to_point(&self.buffer().read(cx).snapshot(cx))
|
.to_point(&self.buffer().read(cx).snapshot(cx))
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
scene::{
|
scene::{
|
||||||
CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover,
|
CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover,
|
||||||
MouseMove, MouseScrollWheel, MouseUp, MouseUpOut,
|
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
|
||||||
},
|
},
|
||||||
DebugContext, Element, ElementBox, EventContext, LayoutContext, MeasurementContext,
|
DebugContext, Element, ElementBox, EventContext, LayoutContext, MeasurementContext,
|
||||||
MouseButton, MouseRegion, MouseState, PaintContext, RenderContext, SizeConstraint, View,
|
MouseButton, MouseRegion, MouseState, PaintContext, RenderContext, SizeConstraint, View,
|
||||||
|
@ -82,6 +82,14 @@ impl<Tag> MouseEventHandler<Tag> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_move_out(
|
||||||
|
mut self,
|
||||||
|
handler: impl Fn(MouseMoveOut, &mut EventContext) + 'static,
|
||||||
|
) -> Self {
|
||||||
|
self.handlers = self.handlers.on_move_out(handler);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_down(
|
pub fn on_down(
|
||||||
mut self,
|
mut self,
|
||||||
button: MouseButton,
|
button: MouseButton,
|
||||||
|
|
|
@ -66,12 +66,6 @@ const NSNormalWindowLevel: NSInteger = 0;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const NSPopUpWindowLevel: NSInteger = 101;
|
const NSPopUpWindowLevel: NSInteger = 101;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const NSTrackingMouseMoved: NSUInteger = 0x02;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const NSTrackingActiveAlways: NSUInteger = 0x80;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const NSTrackingInVisibleRect: NSUInteger = 0x200;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const NSWindowAnimationBehaviorUtilityWindow: NSInteger = 4;
|
const NSWindowAnimationBehaviorUtilityWindow: NSInteger = 4;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -469,15 +463,7 @@ impl Window {
|
||||||
native_window.setTitlebarAppearsTransparent_(YES);
|
native_window.setTitlebarAppearsTransparent_(YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tracking_area: id = msg_send![class!(NSTrackingArea), alloc];
|
native_window.setAcceptsMouseMovedEvents_(YES);
|
||||||
let _: () = msg_send![
|
|
||||||
tracking_area,
|
|
||||||
initWithRect: NSRect::new(NSPoint::new(0., 0.), NSSize::new(0., 0.))
|
|
||||||
options: NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingInVisibleRect
|
|
||||||
owner: native_view
|
|
||||||
userInfo: nil
|
|
||||||
];
|
|
||||||
let _: () = msg_send![native_view, addTrackingArea: tracking_area.autorelease()];
|
|
||||||
|
|
||||||
native_view.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable);
|
native_view.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable);
|
||||||
native_view.setWantsBestResolutionOpenGLSurface_(YES);
|
native_view.setWantsBestResolutionOpenGLSurface_(YES);
|
||||||
|
@ -873,11 +859,10 @@ extern "C" fn handle_key_down(this: &Object, _: Sel, native_event: id) {
|
||||||
|
|
||||||
extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: bool) -> BOOL {
|
extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: bool) -> BOOL {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
|
|
||||||
let mut window_state_borrow = window_state.as_ref().borrow_mut();
|
let mut window_state_borrow = window_state.as_ref().borrow_mut();
|
||||||
|
|
||||||
let event =
|
let window_height = window_state_borrow.content_size().y();
|
||||||
unsafe { Event::from_native(native_event, Some(window_state_borrow.content_size().y())) };
|
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
||||||
|
|
||||||
if let Some(event) = event {
|
if let Some(event) = event {
|
||||||
if key_equivalent {
|
if key_equivalent {
|
||||||
|
@ -902,6 +887,7 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||||
function_is_held = event.keystroke.function;
|
function_is_held = event.keystroke.function;
|
||||||
Some((event, None))
|
Some((event, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => return NO,
|
_ => return NO,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -968,9 +954,11 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let weak_window_state = Rc::downgrade(&window_state);
|
let weak_window_state = Rc::downgrade(&window_state);
|
||||||
let mut window_state_borrow = window_state.as_ref().borrow_mut();
|
let mut window_state_borrow = window_state.as_ref().borrow_mut();
|
||||||
|
let is_active = unsafe { window_state_borrow.native_window.isKeyWindow() == YES };
|
||||||
|
|
||||||
|
let window_height = window_state_borrow.content_size().y();
|
||||||
|
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
||||||
|
|
||||||
let event =
|
|
||||||
unsafe { Event::from_native(native_event, Some(window_state_borrow.content_size().y())) };
|
|
||||||
if let Some(event) = event {
|
if let Some(event) = event {
|
||||||
match &event {
|
match &event {
|
||||||
Event::MouseMoved(
|
Event::MouseMoved(
|
||||||
|
@ -989,12 +977,16 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
))
|
))
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event::MouseMoved(_) if !is_active => return,
|
||||||
|
|
||||||
Event::MouseUp(MouseButtonEvent {
|
Event::MouseUp(MouseButtonEvent {
|
||||||
button: MouseButton::Left,
|
button: MouseButton::Left,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
window_state_borrow.synthetic_drag_counter += 1;
|
window_state_borrow.synthetic_drag_counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
Event::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
||||||
// Only raise modifiers changed event when they have actually changed
|
// Only raise modifiers changed event when they have actually changed
|
||||||
if let Some(Event::ModifiersChanged(ModifiersChangedEvent {
|
if let Some(Event::ModifiersChanged(ModifiersChangedEvent {
|
||||||
|
@ -1008,6 +1000,7 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
|
|
||||||
window_state_borrow.previous_modifiers_changed_event = Some(event.clone());
|
window_state_borrow.previous_modifiers_changed_event = Some(event.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
platform::{CursorStyle, Event},
|
platform::{CursorStyle, Event},
|
||||||
scene::{
|
scene::{
|
||||||
CursorRegion, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover,
|
CursorRegion, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover,
|
||||||
MouseMove, MouseScrollWheel, MouseUp, MouseUpOut, Scene,
|
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene,
|
||||||
},
|
},
|
||||||
text_layout::TextLayoutCache,
|
text_layout::TextLayoutCache,
|
||||||
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, Appearance,
|
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, Appearance,
|
||||||
|
@ -245,8 +245,11 @@ impl Presenter {
|
||||||
// -> Also updates mouse-related state
|
// -> Also updates mouse-related state
|
||||||
match &event {
|
match &event {
|
||||||
Event::KeyDown(e) => return cx.dispatch_key_down(self.window_id, e),
|
Event::KeyDown(e) => return cx.dispatch_key_down(self.window_id, e),
|
||||||
|
|
||||||
Event::KeyUp(e) => return cx.dispatch_key_up(self.window_id, e),
|
Event::KeyUp(e) => return cx.dispatch_key_up(self.window_id, e),
|
||||||
|
|
||||||
Event::ModifiersChanged(e) => return cx.dispatch_modifiers_changed(self.window_id, e),
|
Event::ModifiersChanged(e) => return cx.dispatch_modifiers_changed(self.window_id, e),
|
||||||
|
|
||||||
Event::MouseDown(e) => {
|
Event::MouseDown(e) => {
|
||||||
// Click events are weird because they can be fired after a drag event.
|
// Click events are weird because they can be fired after a drag event.
|
||||||
// MDN says that browsers handle this by starting from 'the most
|
// MDN says that browsers handle this by starting from 'the most
|
||||||
|
@ -279,6 +282,7 @@ impl Presenter {
|
||||||
platform_event: e.clone(),
|
platform_event: e.clone(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::MouseUp(e) => {
|
Event::MouseUp(e) => {
|
||||||
// NOTE: The order of event pushes is important! MouseUp events MUST be fired
|
// NOTE: The order of event pushes is important! MouseUp events MUST be fired
|
||||||
// before click events, and so the MouseUp events need to be pushed before
|
// before click events, and so the MouseUp events need to be pushed before
|
||||||
|
@ -296,6 +300,7 @@ impl Presenter {
|
||||||
platform_event: e.clone(),
|
platform_event: e.clone(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::MouseMoved(
|
Event::MouseMoved(
|
||||||
e @ MouseMovedEvent {
|
e @ MouseMovedEvent {
|
||||||
position,
|
position,
|
||||||
|
@ -347,9 +352,13 @@ impl Presenter {
|
||||||
platform_event: e.clone(),
|
platform_event: e.clone(),
|
||||||
started: false,
|
started: false,
|
||||||
}));
|
}));
|
||||||
|
mouse_events.push(MouseEvent::MoveOut(MouseMoveOut {
|
||||||
|
region: Default::default(),
|
||||||
|
}));
|
||||||
|
|
||||||
self.last_mouse_moved_event = Some(event.clone());
|
self.last_mouse_moved_event = Some(event.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::ScrollWheel(e) => mouse_events.push(MouseEvent::ScrollWheel(MouseScrollWheel {
|
Event::ScrollWheel(e) => mouse_events.push(MouseEvent::ScrollWheel(MouseScrollWheel {
|
||||||
region: Default::default(),
|
region: Default::default(),
|
||||||
platform_event: e.clone(),
|
platform_event: e.clone(),
|
||||||
|
@ -407,6 +416,7 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEvent::Down(_) | MouseEvent::Up(_) => {
|
MouseEvent::Down(_) | MouseEvent::Up(_) => {
|
||||||
for (region, _) in self.mouse_regions.iter().rev() {
|
for (region, _) in self.mouse_regions.iter().rev() {
|
||||||
if region.bounds.contains_point(self.mouse_position) {
|
if region.bounds.contains_point(self.mouse_position) {
|
||||||
|
@ -417,6 +427,7 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEvent::Click(e) => {
|
MouseEvent::Click(e) => {
|
||||||
// Only raise click events if the released button is the same as the one stored
|
// Only raise click events if the released button is the same as the one stored
|
||||||
if self
|
if self
|
||||||
|
@ -439,6 +450,7 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEvent::Drag(_) => {
|
MouseEvent::Drag(_) => {
|
||||||
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
||||||
if self.clicked_region_ids.contains(&mouse_region.id()) {
|
if self.clicked_region_ids.contains(&mouse_region.id()) {
|
||||||
|
@ -447,7 +459,7 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => {
|
MouseEvent::MoveOut(_) | MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => {
|
||||||
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
||||||
// NOT contains
|
// NOT contains
|
||||||
if !mouse_region.bounds.contains_point(self.mouse_position) {
|
if !mouse_region.bounds.contains_point(self.mouse_position) {
|
||||||
|
@ -455,6 +467,7 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
||||||
// Contains
|
// Contains
|
||||||
|
|
|
@ -21,6 +21,11 @@ impl Deref for MouseMove {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct MouseMoveOut {
|
||||||
|
pub region: RectF,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct MouseDrag {
|
pub struct MouseDrag {
|
||||||
pub region: RectF,
|
pub region: RectF,
|
||||||
|
@ -138,6 +143,7 @@ impl Deref for MouseScrollWheel {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum MouseEvent {
|
pub enum MouseEvent {
|
||||||
Move(MouseMove),
|
Move(MouseMove),
|
||||||
|
MoveOut(MouseMoveOut),
|
||||||
Drag(MouseDrag),
|
Drag(MouseDrag),
|
||||||
Hover(MouseHover),
|
Hover(MouseHover),
|
||||||
Down(MouseDown),
|
Down(MouseDown),
|
||||||
|
@ -152,6 +158,7 @@ impl MouseEvent {
|
||||||
pub fn set_region(&mut self, region: RectF) {
|
pub fn set_region(&mut self, region: RectF) {
|
||||||
match self {
|
match self {
|
||||||
MouseEvent::Move(r) => r.region = region,
|
MouseEvent::Move(r) => r.region = region,
|
||||||
|
MouseEvent::MoveOut(r) => r.region = region,
|
||||||
MouseEvent::Drag(r) => r.region = region,
|
MouseEvent::Drag(r) => r.region = region,
|
||||||
MouseEvent::Hover(r) => r.region = region,
|
MouseEvent::Hover(r) => r.region = region,
|
||||||
MouseEvent::Down(r) => r.region = region,
|
MouseEvent::Down(r) => r.region = region,
|
||||||
|
@ -168,6 +175,7 @@ impl MouseEvent {
|
||||||
pub fn is_capturable(&self) -> bool {
|
pub fn is_capturable(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
MouseEvent::Move(_) => true,
|
MouseEvent::Move(_) => true,
|
||||||
|
MouseEvent::MoveOut(_) => false,
|
||||||
MouseEvent::Drag(_) => true,
|
MouseEvent::Drag(_) => true,
|
||||||
MouseEvent::Hover(_) => false,
|
MouseEvent::Hover(_) => false,
|
||||||
MouseEvent::Down(_) => true,
|
MouseEvent::Down(_) => true,
|
||||||
|
@ -185,6 +193,10 @@ impl MouseEvent {
|
||||||
discriminant(&MouseEvent::Move(Default::default()))
|
discriminant(&MouseEvent::Move(Default::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn move_out_disc() -> Discriminant<MouseEvent> {
|
||||||
|
discriminant(&MouseEvent::MoveOut(Default::default()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn drag_disc() -> Discriminant<MouseEvent> {
|
pub fn drag_disc() -> Discriminant<MouseEvent> {
|
||||||
discriminant(&MouseEvent::Drag(Default::default()))
|
discriminant(&MouseEvent::Drag(Default::default()))
|
||||||
}
|
}
|
||||||
|
@ -220,6 +232,7 @@ impl MouseEvent {
|
||||||
pub fn handler_key(&self) -> HandlerKey {
|
pub fn handler_key(&self) -> HandlerKey {
|
||||||
match self {
|
match self {
|
||||||
MouseEvent::Move(_) => HandlerKey::new(Self::move_disc(), None),
|
MouseEvent::Move(_) => HandlerKey::new(Self::move_disc(), None),
|
||||||
|
MouseEvent::MoveOut(_) => HandlerKey::new(Self::move_out_disc(), None),
|
||||||
MouseEvent::Drag(e) => HandlerKey::new(Self::drag_disc(), e.pressed_button),
|
MouseEvent::Drag(e) => HandlerKey::new(Self::drag_disc(), e.pressed_button),
|
||||||
MouseEvent::Hover(_) => HandlerKey::new(Self::hover_disc(), None),
|
MouseEvent::Hover(_) => HandlerKey::new(Self::hover_disc(), None),
|
||||||
MouseEvent::Down(e) => HandlerKey::new(Self::down_disc(), Some(e.button)),
|
MouseEvent::Down(e) => HandlerKey::new(Self::down_disc(), Some(e.button)),
|
||||||
|
|
|
@ -12,7 +12,7 @@ use super::{
|
||||||
MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover, MouseMove, MouseUp,
|
MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover, MouseMove, MouseUp,
|
||||||
MouseUpOut,
|
MouseUpOut,
|
||||||
},
|
},
|
||||||
MouseScrollWheel,
|
MouseMoveOut, MouseScrollWheel,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -124,6 +124,14 @@ impl MouseRegion {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_move_out(
|
||||||
|
mut self,
|
||||||
|
handler: impl Fn(MouseMoveOut, &mut EventContext) + 'static,
|
||||||
|
) -> Self {
|
||||||
|
self.handlers = self.handlers.on_move_out(handler);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_scroll(
|
pub fn on_scroll(
|
||||||
mut self,
|
mut self,
|
||||||
handler: impl Fn(MouseScrollWheel, &mut EventContext) + 'static,
|
handler: impl Fn(MouseScrollWheel, &mut EventContext) + 'static,
|
||||||
|
@ -289,6 +297,23 @@ impl HandlerSet {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_move_out(
|
||||||
|
mut self,
|
||||||
|
handler: impl Fn(MouseMoveOut, &mut EventContext) + 'static,
|
||||||
|
) -> Self {
|
||||||
|
self.insert(MouseEvent::move_out_disc(), None,
|
||||||
|
Rc::new(move |region_event, cx| {
|
||||||
|
if let MouseEvent::MoveOut(e) = region_event {
|
||||||
|
handler(e, cx);
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::MoveOut, found {:?}",
|
||||||
|
region_event);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_down(
|
pub fn on_down(
|
||||||
mut self,
|
mut self,
|
||||||
button: MouseButton,
|
button: MouseButton,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue