mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-02 08:20:09 +00:00
Fix draw helper, add helper traits for selecting groupings of input events
This commit is contained in:
parent
db433586aa
commit
cae35d3334
10 changed files with 243 additions and 169 deletions
|
@ -1,11 +1,11 @@
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
|
Action, AnyElement, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
|
||||||
BackgroundExecutor, ClipboardItem, Context, Entity, EventEmitter, ForegroundExecutor,
|
AvailableSpace, BackgroundExecutor, ClipboardItem, Context, Entity, EventEmitter,
|
||||||
InputEvent, IntoElement, Keystroke, Model, ModelContext, Pixels, Platform, Render, Result,
|
ForegroundExecutor, InputEvent, Keystroke, Model, ModelContext, Pixels, Platform, Point,
|
||||||
Size, Task, TestDispatcher, TestPlatform, TestWindow, TextSystem, View, ViewContext,
|
Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow, TextSystem, View,
|
||||||
VisualContext, WindowContext, WindowHandle, WindowOptions,
|
ViewContext, VisualContext, WindowContext, WindowHandle, WindowOptions,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
use futures::{Stream, StreamExt};
|
use futures::{Stream, StreamExt};
|
||||||
|
@ -167,10 +167,14 @@ impl TestAppContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a new window with no content.
|
/// Adds a new window with no content.
|
||||||
pub fn add_empty_window(&mut self) -> AnyWindowHandle {
|
pub fn add_empty_window(&mut self) -> &mut VisualTestContext {
|
||||||
let mut cx = self.app.borrow_mut();
|
let mut cx = self.app.borrow_mut();
|
||||||
cx.open_window(WindowOptions::default(), |cx| cx.new_view(|_| EmptyView {}))
|
let window = cx.open_window(WindowOptions::default(), |cx| cx.new_view(|_| ()));
|
||||||
.any_handle
|
drop(cx);
|
||||||
|
let cx = Box::new(VisualTestContext::from_window(*window.deref(), self));
|
||||||
|
cx.run_until_parked();
|
||||||
|
// it might be nice to try and cleanup these at the end of each test.
|
||||||
|
Box::leak(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a new window, and returns its root view and a `VisualTestContext` which can be used
|
/// Adds a new window, and returns its root view and a `VisualTestContext` which can be used
|
||||||
|
@ -609,9 +613,32 @@ impl<'a> VisualTestContext {
|
||||||
self.cx.simulate_input(self.window, input)
|
self.cx.simulate_input(self.window, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw an element to the window. Useful for simulating events or actions
|
||||||
|
pub fn draw(
|
||||||
|
&mut self,
|
||||||
|
origin: Point<Pixels>,
|
||||||
|
space: Size<AvailableSpace>,
|
||||||
|
f: impl FnOnce(&mut WindowContext) -> AnyElement,
|
||||||
|
) {
|
||||||
|
self.update(|cx| {
|
||||||
|
let entity_id = cx
|
||||||
|
.window
|
||||||
|
.root_view
|
||||||
|
.as_ref()
|
||||||
|
.expect("Can't draw to this window without a root view")
|
||||||
|
.entity_id();
|
||||||
|
cx.with_view_id(entity_id, |cx| {
|
||||||
|
f(cx).draw(origin, space, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.refresh();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Simulate an event from the platform, e.g. a SrollWheelEvent
|
/// Simulate an event from the platform, e.g. a SrollWheelEvent
|
||||||
pub fn simulate_event(&mut self, event: InputEvent) {
|
/// Make sure you've called [VisualTestContext::draw] first!
|
||||||
self.update(|cx| cx.dispatch_event(event));
|
pub fn simulate_event<E: InputEvent>(&mut self, event: E) {
|
||||||
|
self.update(|cx| cx.dispatch_event(event.to_platform_input()));
|
||||||
self.background_executor.run_until_parked();
|
self.background_executor.run_until_parked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,12 +796,3 @@ impl AnyWindowHandle {
|
||||||
self.update(cx, |_, cx| cx.new_view(build_view)).unwrap()
|
self.update(cx, |_, cx| cx.new_view(build_view)).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An EmptyView for testing.
|
|
||||||
pub struct EmptyView {}
|
|
||||||
|
|
||||||
impl Render for EmptyView {
|
|
||||||
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> impl IntoElement {
|
|
||||||
div()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, AnyElement, AvailableSpace, BorrowAppContext, BorrowWindow, Bounds, ContentMask,
|
point, px, AnyElement, AvailableSpace, BorrowAppContext, BorrowWindow, Bounds, ContentMask,
|
||||||
DispatchPhase, Element, IntoElement, IsZero, Pixels, Point, ScrollWheelEvent, Size, Style,
|
DispatchPhase, Element, IntoElement, Pixels, Point, ScrollWheelEvent, Size, Style,
|
||||||
StyleRefinement, Styled, WindowContext,
|
StyleRefinement, Styled, WindowContext,
|
||||||
};
|
};
|
||||||
use collections::VecDeque;
|
use collections::VecDeque;
|
||||||
|
@ -584,36 +584,33 @@ impl<'a> sum_tree::SeekTarget<'a, ListItemSummary, ListItemSummary> for Height {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use crate::{self as gpui, Entity, TestAppContext};
|
use gpui::{ScrollDelta, ScrollWheelEvent};
|
||||||
|
|
||||||
|
use crate::{self as gpui, TestAppContext};
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_reset_after_paint_before_scroll(cx: &mut TestAppContext) {
|
fn test_reset_after_paint_before_scroll(cx: &mut TestAppContext) {
|
||||||
use crate::{div, list, point, px, size, Element, ListState, Styled};
|
use crate::{div, list, point, px, size, Element, ListState, Styled};
|
||||||
|
|
||||||
let (v, cx) = cx.add_window_view(|_| ());
|
let cx = cx.add_empty_window();
|
||||||
|
|
||||||
let state = ListState::new(5, crate::ListAlignment::Top, px(10.), |_, _| {
|
let state = ListState::new(5, crate::ListAlignment::Top, px(10.), |_, _| {
|
||||||
div().h(px(10.)).w_full().into_any()
|
div().h(px(10.)).w_full().into_any()
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.update(|cx| {
|
cx.draw(
|
||||||
cx.with_view_id(v.entity_id(), |cx| {
|
point(px(0.), px(0.)),
|
||||||
list(state.clone())
|
size(px(100.), px(20.)).into(),
|
||||||
.w_full()
|
|_| list(state.clone()).w_full().h_full().z_index(10).into_any(),
|
||||||
.h_full()
|
);
|
||||||
.z_index(10)
|
|
||||||
.into_any()
|
|
||||||
.draw(point(px(0.0), px(0.0)), size(px(100.), px(20.)).into(), cx)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
state.reset(5);
|
state.reset(5);
|
||||||
|
|
||||||
cx.simulate_event(gpui::InputEvent::ScrollWheel(gpui::ScrollWheelEvent {
|
cx.simulate_event(ScrollWheelEvent {
|
||||||
position: point(px(1.), px(1.)),
|
position: point(px(1.), px(1.)),
|
||||||
delta: gpui::ScrollDelta::Pixels(point(px(0.), px(-500.))),
|
delta: ScrollDelta::Pixels(point(px(0.), px(-500.))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
});
|
||||||
|
|
||||||
assert_eq!(state.logical_scroll_top().item_ix, 0);
|
assert_eq!(state.logical_scroll_top().item_ix, 0);
|
||||||
assert_eq!(state.logical_scroll_top().offset_in_item, px(0.));
|
assert_eq!(state.logical_scroll_top().offset_in_item, px(0.));
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
div, point, Element, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
|
point, seal::Sealed, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{any::Any, default, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf};
|
use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
|
||||||
|
|
||||||
|
pub trait InputEvent: Sealed + 'static {
|
||||||
|
fn to_platform_input(self) -> PlatformInput;
|
||||||
|
}
|
||||||
|
pub trait KeyEvent: InputEvent {}
|
||||||
|
pub trait MouseEvent: InputEvent {}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct KeyDownEvent {
|
pub struct KeyDownEvent {
|
||||||
|
@ -10,16 +16,40 @@ pub struct KeyDownEvent {
|
||||||
pub is_held: bool,
|
pub is_held: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for KeyDownEvent {}
|
||||||
|
impl InputEvent for KeyDownEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::KeyDown(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl KeyEvent for KeyDownEvent {}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct KeyUpEvent {
|
pub struct KeyUpEvent {
|
||||||
pub keystroke: Keystroke,
|
pub keystroke: Keystroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for KeyUpEvent {}
|
||||||
|
impl InputEvent for KeyUpEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::KeyUp(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl KeyEvent for KeyUpEvent {}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct ModifiersChangedEvent {
|
pub struct ModifiersChangedEvent {
|
||||||
pub modifiers: Modifiers,
|
pub modifiers: Modifiers,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for ModifiersChangedEvent {}
|
||||||
|
impl InputEvent for ModifiersChangedEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::ModifiersChanged(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl KeyEvent for ModifiersChangedEvent {}
|
||||||
|
|
||||||
impl Deref for ModifiersChangedEvent {
|
impl Deref for ModifiersChangedEvent {
|
||||||
type Target = Modifiers;
|
type Target = Modifiers;
|
||||||
|
|
||||||
|
@ -46,6 +76,14 @@ pub struct MouseDownEvent {
|
||||||
pub click_count: usize,
|
pub click_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for MouseDownEvent {}
|
||||||
|
impl InputEvent for MouseDownEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::MouseDown(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MouseEvent for MouseDownEvent {}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct MouseUpEvent {
|
pub struct MouseUpEvent {
|
||||||
pub button: MouseButton,
|
pub button: MouseButton,
|
||||||
|
@ -54,38 +92,20 @@ pub struct MouseUpEvent {
|
||||||
pub click_count: usize,
|
pub click_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for MouseUpEvent {}
|
||||||
|
impl InputEvent for MouseUpEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::MouseUp(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MouseEvent for MouseUpEvent {}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct ClickEvent {
|
pub struct ClickEvent {
|
||||||
pub down: MouseDownEvent,
|
pub down: MouseDownEvent,
|
||||||
pub up: MouseUpEvent,
|
pub up: MouseUpEvent,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Drag<S, R, V, E>
|
|
||||||
where
|
|
||||||
R: Fn(&mut V, &mut ViewContext<V>) -> E,
|
|
||||||
V: 'static,
|
|
||||||
E: IntoElement,
|
|
||||||
{
|
|
||||||
pub state: S,
|
|
||||||
pub render_drag_handle: R,
|
|
||||||
view_element_types: PhantomData<(V, E)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, R, V, E> Drag<S, R, V, E>
|
|
||||||
where
|
|
||||||
R: Fn(&mut V, &mut ViewContext<V>) -> E,
|
|
||||||
V: 'static,
|
|
||||||
E: Element,
|
|
||||||
{
|
|
||||||
pub fn new(state: S, render_drag_handle: R) -> Self {
|
|
||||||
Drag {
|
|
||||||
state,
|
|
||||||
render_drag_handle,
|
|
||||||
view_element_types: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
pub enum MouseButton {
|
pub enum MouseButton {
|
||||||
Left,
|
Left,
|
||||||
|
@ -131,6 +151,14 @@ pub struct MouseMoveEvent {
|
||||||
pub modifiers: Modifiers,
|
pub modifiers: Modifiers,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for MouseMoveEvent {}
|
||||||
|
impl InputEvent for MouseMoveEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::MouseMove(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MouseEvent for MouseMoveEvent {}
|
||||||
|
|
||||||
impl MouseMoveEvent {
|
impl MouseMoveEvent {
|
||||||
pub fn dragging(&self) -> bool {
|
pub fn dragging(&self) -> bool {
|
||||||
self.pressed_button == Some(MouseButton::Left)
|
self.pressed_button == Some(MouseButton::Left)
|
||||||
|
@ -145,6 +173,14 @@ pub struct ScrollWheelEvent {
|
||||||
pub touch_phase: TouchPhase,
|
pub touch_phase: TouchPhase,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for ScrollWheelEvent {}
|
||||||
|
impl InputEvent for ScrollWheelEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::ScrollWheel(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MouseEvent for ScrollWheelEvent {}
|
||||||
|
|
||||||
impl Deref for ScrollWheelEvent {
|
impl Deref for ScrollWheelEvent {
|
||||||
type Target = Modifiers;
|
type Target = Modifiers;
|
||||||
|
|
||||||
|
@ -202,6 +238,14 @@ pub struct MouseExitEvent {
|
||||||
pub modifiers: Modifiers,
|
pub modifiers: Modifiers,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for MouseExitEvent {}
|
||||||
|
impl InputEvent for MouseExitEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::MouseExited(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MouseEvent for MouseExitEvent {}
|
||||||
|
|
||||||
impl Deref for MouseExitEvent {
|
impl Deref for MouseExitEvent {
|
||||||
type Target = Modifiers;
|
type Target = Modifiers;
|
||||||
|
|
||||||
|
@ -221,7 +265,7 @@ impl ExternalPaths {
|
||||||
|
|
||||||
impl Render for ExternalPaths {
|
impl Render for ExternalPaths {
|
||||||
fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
div() // Intentionally left empty because the platform will render icons for the dragged files
|
() // Intentionally left empty because the platform will render icons for the dragged files
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,8 +284,16 @@ pub enum FileDropEvent {
|
||||||
Exited,
|
Exited,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sealed for FileDropEvent {}
|
||||||
|
impl InputEvent for FileDropEvent {
|
||||||
|
fn to_platform_input(self) -> PlatformInput {
|
||||||
|
PlatformInput::FileDrop(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MouseEvent for FileDropEvent {}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum InputEvent {
|
pub enum PlatformInput {
|
||||||
KeyDown(KeyDownEvent),
|
KeyDown(KeyDownEvent),
|
||||||
KeyUp(KeyUpEvent),
|
KeyUp(KeyUpEvent),
|
||||||
ModifiersChanged(ModifiersChangedEvent),
|
ModifiersChanged(ModifiersChangedEvent),
|
||||||
|
@ -253,19 +305,19 @@ pub enum InputEvent {
|
||||||
FileDrop(FileDropEvent),
|
FileDrop(FileDropEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputEvent {
|
impl PlatformInput {
|
||||||
pub fn position(&self) -> Option<Point<Pixels>> {
|
pub fn position(&self) -> Option<Point<Pixels>> {
|
||||||
match self {
|
match self {
|
||||||
InputEvent::KeyDown { .. } => None,
|
PlatformInput::KeyDown { .. } => None,
|
||||||
InputEvent::KeyUp { .. } => None,
|
PlatformInput::KeyUp { .. } => None,
|
||||||
InputEvent::ModifiersChanged { .. } => None,
|
PlatformInput::ModifiersChanged { .. } => None,
|
||||||
InputEvent::MouseDown(event) => Some(event.position),
|
PlatformInput::MouseDown(event) => Some(event.position),
|
||||||
InputEvent::MouseUp(event) => Some(event.position),
|
PlatformInput::MouseUp(event) => Some(event.position),
|
||||||
InputEvent::MouseMove(event) => Some(event.position),
|
PlatformInput::MouseMove(event) => Some(event.position),
|
||||||
InputEvent::MouseExited(event) => Some(event.position),
|
PlatformInput::MouseExited(event) => Some(event.position),
|
||||||
InputEvent::ScrollWheel(event) => Some(event.position),
|
PlatformInput::ScrollWheel(event) => Some(event.position),
|
||||||
InputEvent::FileDrop(FileDropEvent::Exited) => None,
|
PlatformInput::FileDrop(FileDropEvent::Exited) => None,
|
||||||
InputEvent::FileDrop(
|
PlatformInput::FileDrop(
|
||||||
FileDropEvent::Entered { position, .. }
|
FileDropEvent::Entered { position, .. }
|
||||||
| FileDropEvent::Pending { position, .. }
|
| FileDropEvent::Pending { position, .. }
|
||||||
| FileDropEvent::Submit { position, .. },
|
| FileDropEvent::Submit { position, .. },
|
||||||
|
@ -275,29 +327,29 @@ impl InputEvent {
|
||||||
|
|
||||||
pub fn mouse_event(&self) -> Option<&dyn Any> {
|
pub fn mouse_event(&self) -> Option<&dyn Any> {
|
||||||
match self {
|
match self {
|
||||||
InputEvent::KeyDown { .. } => None,
|
PlatformInput::KeyDown { .. } => None,
|
||||||
InputEvent::KeyUp { .. } => None,
|
PlatformInput::KeyUp { .. } => None,
|
||||||
InputEvent::ModifiersChanged { .. } => None,
|
PlatformInput::ModifiersChanged { .. } => None,
|
||||||
InputEvent::MouseDown(event) => Some(event),
|
PlatformInput::MouseDown(event) => Some(event),
|
||||||
InputEvent::MouseUp(event) => Some(event),
|
PlatformInput::MouseUp(event) => Some(event),
|
||||||
InputEvent::MouseMove(event) => Some(event),
|
PlatformInput::MouseMove(event) => Some(event),
|
||||||
InputEvent::MouseExited(event) => Some(event),
|
PlatformInput::MouseExited(event) => Some(event),
|
||||||
InputEvent::ScrollWheel(event) => Some(event),
|
PlatformInput::ScrollWheel(event) => Some(event),
|
||||||
InputEvent::FileDrop(event) => Some(event),
|
PlatformInput::FileDrop(event) => Some(event),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keyboard_event(&self) -> Option<&dyn Any> {
|
pub fn keyboard_event(&self) -> Option<&dyn Any> {
|
||||||
match self {
|
match self {
|
||||||
InputEvent::KeyDown(event) => Some(event),
|
PlatformInput::KeyDown(event) => Some(event),
|
||||||
InputEvent::KeyUp(event) => Some(event),
|
PlatformInput::KeyUp(event) => Some(event),
|
||||||
InputEvent::ModifiersChanged(event) => Some(event),
|
PlatformInput::ModifiersChanged(event) => Some(event),
|
||||||
InputEvent::MouseDown(_) => None,
|
PlatformInput::MouseDown(_) => None,
|
||||||
InputEvent::MouseUp(_) => None,
|
PlatformInput::MouseUp(_) => None,
|
||||||
InputEvent::MouseMove(_) => None,
|
PlatformInput::MouseMove(_) => None,
|
||||||
InputEvent::MouseExited(_) => None,
|
PlatformInput::MouseExited(_) => None,
|
||||||
InputEvent::ScrollWheel(_) => None,
|
PlatformInput::ScrollWheel(_) => None,
|
||||||
InputEvent::FileDrop(_) => None,
|
PlatformInput::FileDrop(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod test;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId, FontMetrics,
|
Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId, FontMetrics,
|
||||||
FontRun, ForegroundExecutor, GlobalPixels, GlyphId, InputEvent, Keymap, LineLayout, Pixels,
|
FontRun, ForegroundExecutor, GlobalPixels, GlyphId, Keymap, LineLayout, Pixels, PlatformInput,
|
||||||
Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result, Scene, SharedString,
|
Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result, Scene, SharedString,
|
||||||
Size, TaskLabel,
|
Size, TaskLabel,
|
||||||
};
|
};
|
||||||
|
@ -88,7 +88,7 @@ pub(crate) trait Platform: 'static {
|
||||||
fn on_resign_active(&self, callback: Box<dyn FnMut()>);
|
fn on_resign_active(&self, callback: Box<dyn FnMut()>);
|
||||||
fn on_quit(&self, callback: Box<dyn FnMut()>);
|
fn on_quit(&self, callback: Box<dyn FnMut()>);
|
||||||
fn on_reopen(&self, callback: Box<dyn FnMut()>);
|
fn on_reopen(&self, callback: Box<dyn FnMut()>);
|
||||||
fn on_event(&self, callback: Box<dyn FnMut(InputEvent) -> bool>);
|
fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>);
|
||||||
|
|
||||||
fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap);
|
fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap);
|
||||||
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>);
|
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>);
|
||||||
|
@ -155,7 +155,7 @@ pub trait PlatformWindow {
|
||||||
fn zoom(&self);
|
fn zoom(&self);
|
||||||
fn toggle_full_screen(&self);
|
fn toggle_full_screen(&self);
|
||||||
fn on_request_frame(&self, callback: Box<dyn FnMut()>);
|
fn on_request_frame(&self, callback: Box<dyn FnMut()>);
|
||||||
fn on_input(&self, callback: Box<dyn FnMut(InputEvent) -> bool>);
|
fn on_input(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>);
|
||||||
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>);
|
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>);
|
||||||
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>);
|
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>);
|
||||||
fn on_fullscreen(&self, callback: Box<dyn FnMut(bool)>);
|
fn on_fullscreen(&self, callback: Box<dyn FnMut(bool)>);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, InputEvent, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent,
|
point, px, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
||||||
MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection,
|
MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels,
|
||||||
Pixels, ScrollDelta, ScrollWheelEvent, TouchPhase,
|
PlatformInput, ScrollDelta, ScrollWheelEvent, TouchPhase,
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType},
|
appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType},
|
||||||
|
@ -82,7 +82,7 @@ unsafe fn read_modifiers(native_event: id) -> Modifiers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputEvent {
|
impl PlatformInput {
|
||||||
pub unsafe fn from_native(native_event: id, window_height: Option<Pixels>) -> Option<Self> {
|
pub unsafe fn from_native(native_event: id, window_height: Option<Pixels>) -> Option<Self> {
|
||||||
let event_type = native_event.eventType();
|
let event_type = native_event.eventType();
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use super::{events::key_to_native, BoolExt};
|
use super::{events::key_to_native, BoolExt};
|
||||||
use crate::{
|
use crate::{
|
||||||
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
||||||
ForegroundExecutor, InputEvent, Keymap, MacDispatcher, MacDisplay, MacDisplayLinker,
|
ForegroundExecutor, Keymap, MacDispatcher, MacDisplay, MacDisplayLinker, MacTextSystem,
|
||||||
MacTextSystem, MacWindow, Menu, MenuItem, PathPromptOptions, Platform, PlatformDisplay,
|
MacWindow, Menu, MenuItem, PathPromptOptions, Platform, PlatformDisplay, PlatformInput,
|
||||||
PlatformTextSystem, PlatformWindow, Result, SemanticVersion, VideoTimestamp, WindowOptions,
|
PlatformTextSystem, PlatformWindow, Result, SemanticVersion, VideoTimestamp, WindowOptions,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
@ -153,7 +153,7 @@ pub struct MacPlatformState {
|
||||||
resign_active: Option<Box<dyn FnMut()>>,
|
resign_active: Option<Box<dyn FnMut()>>,
|
||||||
reopen: Option<Box<dyn FnMut()>>,
|
reopen: Option<Box<dyn FnMut()>>,
|
||||||
quit: Option<Box<dyn FnMut()>>,
|
quit: Option<Box<dyn FnMut()>>,
|
||||||
event: Option<Box<dyn FnMut(InputEvent) -> bool>>,
|
event: Option<Box<dyn FnMut(PlatformInput) -> bool>>,
|
||||||
menu_command: Option<Box<dyn FnMut(&dyn Action)>>,
|
menu_command: Option<Box<dyn FnMut(&dyn Action)>>,
|
||||||
validate_menu_command: Option<Box<dyn FnMut(&dyn Action) -> bool>>,
|
validate_menu_command: Option<Box<dyn FnMut(&dyn Action) -> bool>>,
|
||||||
will_open_menu: Option<Box<dyn FnMut()>>,
|
will_open_menu: Option<Box<dyn FnMut()>>,
|
||||||
|
@ -637,7 +637,7 @@ impl Platform for MacPlatform {
|
||||||
self.0.lock().reopen = Some(callback);
|
self.0.lock().reopen = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&self, callback: Box<dyn FnMut(InputEvent) -> bool>) {
|
fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {
|
||||||
self.0.lock().event = Some(callback);
|
self.0.lock().event = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,7 +976,7 @@ unsafe fn get_mac_platform(object: &mut Object) -> &MacPlatform {
|
||||||
|
|
||||||
extern "C" fn send_event(this: &mut Object, _sel: Sel, native_event: id) {
|
extern "C" fn send_event(this: &mut Object, _sel: Sel, native_event: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(event) = InputEvent::from_native(native_event, None) {
|
if let Some(event) = PlatformInput::from_native(native_event, None) {
|
||||||
let platform = get_mac_platform(this);
|
let platform = get_mac_platform(this);
|
||||||
let mut lock = platform.0.lock();
|
let mut lock = platform.0.lock();
|
||||||
if let Some(mut callback) = lock.event.take() {
|
if let Some(mut callback) = lock.event.take() {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use super::{display_bounds_from_native, ns_string, MacDisplay, MetalRenderer, NSRange};
|
use super::{display_bounds_from_native, ns_string, MacDisplay, MetalRenderer, NSRange};
|
||||||
use crate::{
|
use crate::{
|
||||||
display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, ExternalPaths,
|
display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, ExternalPaths,
|
||||||
FileDropEvent, ForegroundExecutor, GlobalPixels, InputEvent, KeyDownEvent, Keystroke,
|
FileDropEvent, ForegroundExecutor, GlobalPixels, KeyDownEvent, Keystroke, Modifiers,
|
||||||
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
|
||||||
Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
|
PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,
|
||||||
PromptLevel, Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions,
|
PromptLevel, Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions,
|
||||||
};
|
};
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
@ -319,7 +319,7 @@ struct MacWindowState {
|
||||||
renderer: MetalRenderer,
|
renderer: MetalRenderer,
|
||||||
kind: WindowKind,
|
kind: WindowKind,
|
||||||
request_frame_callback: Option<Box<dyn FnMut()>>,
|
request_frame_callback: Option<Box<dyn FnMut()>>,
|
||||||
event_callback: Option<Box<dyn FnMut(InputEvent) -> bool>>,
|
event_callback: Option<Box<dyn FnMut(PlatformInput) -> bool>>,
|
||||||
activate_callback: Option<Box<dyn FnMut(bool)>>,
|
activate_callback: Option<Box<dyn FnMut(bool)>>,
|
||||||
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||||
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
||||||
|
@ -333,7 +333,7 @@ struct MacWindowState {
|
||||||
synthetic_drag_counter: usize,
|
synthetic_drag_counter: usize,
|
||||||
last_fresh_keydown: Option<Keystroke>,
|
last_fresh_keydown: Option<Keystroke>,
|
||||||
traffic_light_position: Option<Point<Pixels>>,
|
traffic_light_position: Option<Point<Pixels>>,
|
||||||
previous_modifiers_changed_event: Option<InputEvent>,
|
previous_modifiers_changed_event: Option<PlatformInput>,
|
||||||
// State tracking what the IME did after the last request
|
// State tracking what the IME did after the last request
|
||||||
ime_state: ImeState,
|
ime_state: ImeState,
|
||||||
// Retains the last IME Text
|
// Retains the last IME Text
|
||||||
|
@ -928,7 +928,7 @@ impl PlatformWindow for MacWindow {
|
||||||
self.0.as_ref().lock().request_frame_callback = Some(callback);
|
self.0.as_ref().lock().request_frame_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_input(&self, callback: Box<dyn FnMut(InputEvent) -> bool>) {
|
fn on_input(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {
|
||||||
self.0.as_ref().lock().event_callback = Some(callback);
|
self.0.as_ref().lock().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,9 +1053,9 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||||
let mut lock = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
|
|
||||||
let window_height = lock.content_size().height;
|
let window_height = lock.content_size().height;
|
||||||
let event = unsafe { InputEvent::from_native(native_event, Some(window_height)) };
|
let event = unsafe { PlatformInput::from_native(native_event, Some(window_height)) };
|
||||||
|
|
||||||
if let Some(InputEvent::KeyDown(event)) = event {
|
if let Some(PlatformInput::KeyDown(event)) = event {
|
||||||
// For certain keystrokes, macOS will first dispatch a "key equivalent" event.
|
// For certain keystrokes, macOS will first dispatch a "key equivalent" event.
|
||||||
// If that event isn't handled, it will then dispatch a "key down" event. GPUI
|
// If that event isn't handled, it will then dispatch a "key down" event. GPUI
|
||||||
// makes no distinction between these two types of events, so we need to ignore
|
// makes no distinction between these two types of events, so we need to ignore
|
||||||
|
@ -1102,7 +1102,7 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||||
.flatten()
|
.flatten()
|
||||||
.is_some();
|
.is_some();
|
||||||
if !is_composing {
|
if !is_composing {
|
||||||
handled = callback(InputEvent::KeyDown(event));
|
handled = callback(PlatformInput::KeyDown(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !handled {
|
if !handled {
|
||||||
|
@ -1146,11 +1146,11 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
let is_active = unsafe { lock.native_window.isKeyWindow() == YES };
|
let is_active = unsafe { lock.native_window.isKeyWindow() == YES };
|
||||||
|
|
||||||
let window_height = lock.content_size().height;
|
let window_height = lock.content_size().height;
|
||||||
let event = unsafe { InputEvent::from_native(native_event, Some(window_height)) };
|
let event = unsafe { PlatformInput::from_native(native_event, Some(window_height)) };
|
||||||
|
|
||||||
if let Some(mut event) = event {
|
if let Some(mut event) = event {
|
||||||
match &mut event {
|
match &mut event {
|
||||||
InputEvent::MouseDown(
|
PlatformInput::MouseDown(
|
||||||
event @ MouseDownEvent {
|
event @ MouseDownEvent {
|
||||||
button: MouseButton::Left,
|
button: MouseButton::Left,
|
||||||
modifiers: Modifiers { control: true, .. },
|
modifiers: Modifiers { control: true, .. },
|
||||||
|
@ -1172,7 +1172,7 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
// Because we map a ctrl-left_down to a right_down -> right_up let's ignore
|
// Because we map a ctrl-left_down to a right_down -> right_up let's ignore
|
||||||
// the ctrl-left_up to avoid having a mismatch in button down/up events if the
|
// the ctrl-left_up to avoid having a mismatch in button down/up events if the
|
||||||
// user is still holding ctrl when releasing the left mouse button
|
// user is still holding ctrl when releasing the left mouse button
|
||||||
InputEvent::MouseUp(
|
PlatformInput::MouseUp(
|
||||||
event @ MouseUpEvent {
|
event @ MouseUpEvent {
|
||||||
button: MouseButton::Left,
|
button: MouseButton::Left,
|
||||||
modifiers: Modifiers { control: true, .. },
|
modifiers: Modifiers { control: true, .. },
|
||||||
|
@ -1194,7 +1194,7 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
};
|
};
|
||||||
|
|
||||||
match &event {
|
match &event {
|
||||||
InputEvent::MouseMove(
|
PlatformInput::MouseMove(
|
||||||
event @ MouseMoveEvent {
|
event @ MouseMoveEvent {
|
||||||
pressed_button: Some(_),
|
pressed_button: Some(_),
|
||||||
..
|
..
|
||||||
|
@ -1216,15 +1216,15 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InputEvent::MouseMove(_) if !(is_active || lock.kind == WindowKind::PopUp) => return,
|
PlatformInput::MouseMove(_) if !(is_active || lock.kind == WindowKind::PopUp) => return,
|
||||||
|
|
||||||
InputEvent::MouseUp(MouseUpEvent { .. }) => {
|
PlatformInput::MouseUp(MouseUpEvent { .. }) => {
|
||||||
lock.synthetic_drag_counter += 1;
|
lock.synthetic_drag_counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputEvent::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
PlatformInput::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(InputEvent::ModifiersChanged(ModifiersChangedEvent {
|
if let Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||||
modifiers: prev_modifiers,
|
modifiers: prev_modifiers,
|
||||||
})) = &lock.previous_modifiers_changed_event
|
})) = &lock.previous_modifiers_changed_event
|
||||||
{
|
{
|
||||||
|
@ -1258,7 +1258,7 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||||
key: ".".into(),
|
key: ".".into(),
|
||||||
ime_key: None,
|
ime_key: None,
|
||||||
};
|
};
|
||||||
let event = InputEvent::KeyDown(KeyDownEvent {
|
let event = PlatformInput::KeyDown(KeyDownEvent {
|
||||||
keystroke: keystroke.clone(),
|
keystroke: keystroke.clone(),
|
||||||
is_held: false,
|
is_held: false,
|
||||||
});
|
});
|
||||||
|
@ -1655,7 +1655,7 @@ extern "C" fn dragging_entered(this: &Object, _: Sel, dragging_info: id) -> NSDr
|
||||||
if send_new_event(&window_state, {
|
if send_new_event(&window_state, {
|
||||||
let position = drag_event_position(&window_state, dragging_info);
|
let position = drag_event_position(&window_state, dragging_info);
|
||||||
let paths = external_paths_from_event(dragging_info);
|
let paths = external_paths_from_event(dragging_info);
|
||||||
InputEvent::FileDrop(FileDropEvent::Entered { position, paths })
|
PlatformInput::FileDrop(FileDropEvent::Entered { position, paths })
|
||||||
}) {
|
}) {
|
||||||
window_state.lock().external_files_dragged = true;
|
window_state.lock().external_files_dragged = true;
|
||||||
NSDragOperationCopy
|
NSDragOperationCopy
|
||||||
|
@ -1669,7 +1669,7 @@ extern "C" fn dragging_updated(this: &Object, _: Sel, dragging_info: id) -> NSDr
|
||||||
let position = drag_event_position(&window_state, dragging_info);
|
let position = drag_event_position(&window_state, dragging_info);
|
||||||
if send_new_event(
|
if send_new_event(
|
||||||
&window_state,
|
&window_state,
|
||||||
InputEvent::FileDrop(FileDropEvent::Pending { position }),
|
PlatformInput::FileDrop(FileDropEvent::Pending { position }),
|
||||||
) {
|
) {
|
||||||
NSDragOperationCopy
|
NSDragOperationCopy
|
||||||
} else {
|
} else {
|
||||||
|
@ -1679,7 +1679,10 @@ extern "C" fn dragging_updated(this: &Object, _: Sel, dragging_info: id) -> NSDr
|
||||||
|
|
||||||
extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) {
|
extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
send_new_event(&window_state, InputEvent::FileDrop(FileDropEvent::Exited));
|
send_new_event(
|
||||||
|
&window_state,
|
||||||
|
PlatformInput::FileDrop(FileDropEvent::Exited),
|
||||||
|
);
|
||||||
window_state.lock().external_files_dragged = false;
|
window_state.lock().external_files_dragged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1688,7 +1691,7 @@ extern "C" fn perform_drag_operation(this: &Object, _: Sel, dragging_info: id) -
|
||||||
let position = drag_event_position(&window_state, dragging_info);
|
let position = drag_event_position(&window_state, dragging_info);
|
||||||
if send_new_event(
|
if send_new_event(
|
||||||
&window_state,
|
&window_state,
|
||||||
InputEvent::FileDrop(FileDropEvent::Submit { position }),
|
PlatformInput::FileDrop(FileDropEvent::Submit { position }),
|
||||||
) {
|
) {
|
||||||
YES
|
YES
|
||||||
} else {
|
} else {
|
||||||
|
@ -1712,7 +1715,10 @@ fn external_paths_from_event(dragging_info: *mut Object) -> ExternalPaths {
|
||||||
|
|
||||||
extern "C" fn conclude_drag_operation(this: &Object, _: Sel, _: id) {
|
extern "C" fn conclude_drag_operation(this: &Object, _: Sel, _: id) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
send_new_event(&window_state, InputEvent::FileDrop(FileDropEvent::Exited));
|
send_new_event(
|
||||||
|
&window_state,
|
||||||
|
PlatformInput::FileDrop(FileDropEvent::Exited),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn synthetic_drag(
|
async fn synthetic_drag(
|
||||||
|
@ -1727,7 +1733,7 @@ async fn synthetic_drag(
|
||||||
if lock.synthetic_drag_counter == drag_id {
|
if lock.synthetic_drag_counter == drag_id {
|
||||||
if let Some(mut callback) = lock.event_callback.take() {
|
if let Some(mut callback) = lock.event_callback.take() {
|
||||||
drop(lock);
|
drop(lock);
|
||||||
callback(InputEvent::MouseMove(event.clone()));
|
callback(PlatformInput::MouseMove(event.clone()));
|
||||||
window_state.lock().event_callback = Some(callback);
|
window_state.lock().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1737,7 +1743,7 @@ async fn synthetic_drag(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_new_event(window_state_lock: &Mutex<MacWindowState>, e: InputEvent) -> bool {
|
fn send_new_event(window_state_lock: &Mutex<MacWindowState>, e: PlatformInput) -> bool {
|
||||||
let window_state = window_state_lock.lock().event_callback.take();
|
let window_state = window_state_lock.lock().event_callback.take();
|
||||||
if let Some(mut callback) = window_state {
|
if let Some(mut callback) = window_state {
|
||||||
callback(e);
|
callback(e);
|
||||||
|
|
|
@ -239,7 +239,7 @@ impl Platform for TestPlatform {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&self, _callback: Box<dyn FnMut(crate::InputEvent) -> bool>) {
|
fn on_event(&self, _callback: Box<dyn FnMut(crate::PlatformInput) -> bool>) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
px, AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, InputEvent, KeyDownEvent,
|
px, AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, KeyDownEvent, Keystroke,
|
||||||
Keystroke, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
|
Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow,
|
||||||
Size, TestPlatform, TileId, WindowAppearance, WindowBounds, WindowOptions,
|
Point, Size, TestPlatform, TileId, WindowAppearance, WindowBounds, WindowOptions,
|
||||||
};
|
};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -19,7 +19,7 @@ pub struct TestWindowState {
|
||||||
platform: Weak<TestPlatform>,
|
platform: Weak<TestPlatform>,
|
||||||
sprite_atlas: Arc<dyn PlatformAtlas>,
|
sprite_atlas: Arc<dyn PlatformAtlas>,
|
||||||
pub(crate) should_close_handler: Option<Box<dyn FnMut() -> bool>>,
|
pub(crate) should_close_handler: Option<Box<dyn FnMut() -> bool>>,
|
||||||
input_callback: Option<Box<dyn FnMut(InputEvent) -> bool>>,
|
input_callback: Option<Box<dyn FnMut(PlatformInput) -> bool>>,
|
||||||
active_status_change_callback: Option<Box<dyn FnMut(bool)>>,
|
active_status_change_callback: Option<Box<dyn FnMut(bool)>>,
|
||||||
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||||
moved_callback: Option<Box<dyn FnMut()>>,
|
moved_callback: Option<Box<dyn FnMut()>>,
|
||||||
|
@ -85,7 +85,7 @@ impl TestWindow {
|
||||||
self.0.lock().active_status_change_callback = Some(callback);
|
self.0.lock().active_status_change_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn simulate_input(&mut self, event: InputEvent) -> bool {
|
pub fn simulate_input(&mut self, event: PlatformInput) -> bool {
|
||||||
let mut lock = self.0.lock();
|
let mut lock = self.0.lock();
|
||||||
let Some(mut callback) = lock.input_callback.take() else {
|
let Some(mut callback) = lock.input_callback.take() else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -97,7 +97,7 @@ impl TestWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn simulate_keystroke(&mut self, keystroke: Keystroke, is_held: bool) {
|
pub fn simulate_keystroke(&mut self, keystroke: Keystroke, is_held: bool) {
|
||||||
if self.simulate_input(InputEvent::KeyDown(KeyDownEvent {
|
if self.simulate_input(PlatformInput::KeyDown(KeyDownEvent {
|
||||||
keystroke: keystroke.clone(),
|
keystroke: keystroke.clone(),
|
||||||
is_held,
|
is_held,
|
||||||
})) {
|
})) {
|
||||||
|
@ -220,7 +220,7 @@ impl PlatformWindow for TestWindow {
|
||||||
|
|
||||||
fn on_request_frame(&self, _callback: Box<dyn FnMut()>) {}
|
fn on_request_frame(&self, _callback: Box<dyn FnMut()>) {}
|
||||||
|
|
||||||
fn on_input(&self, callback: Box<dyn FnMut(crate::InputEvent) -> bool>) {
|
fn on_input(&self, callback: Box<dyn FnMut(crate::PlatformInput) -> bool>) {
|
||||||
self.0.lock().input_callback = Some(callback)
|
self.0.lock().input_callback = Some(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,14 @@ use crate::{
|
||||||
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
|
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
|
||||||
DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect,
|
DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect,
|
||||||
Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FontId, GlobalElementId, GlyphId, Hsla,
|
Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FontId, GlobalElementId, GlyphId, Hsla,
|
||||||
ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeystrokeEvent, LayoutId,
|
ImageData, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, KeystrokeEvent, LayoutId,
|
||||||
Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent,
|
Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent,
|
||||||
Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
|
MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
||||||
PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams,
|
PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render,
|
||||||
RenderSvgParams, ScaledPixels, Scene, Shadow, SharedString, Size, Style, SubscriberSet,
|
RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, Scene, Shadow,
|
||||||
Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext,
|
SharedString, Size, Style, SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task,
|
||||||
WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
|
Underline, UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions,
|
||||||
|
SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
use collections::{FxHashMap, FxHashSet};
|
use collections::{FxHashMap, FxHashSet};
|
||||||
|
@ -968,7 +969,7 @@ impl<'a> WindowContext<'a> {
|
||||||
/// Register a mouse event listener on the window for the next frame. The type of event
|
/// Register a mouse event listener on the window for the next frame. The type of event
|
||||||
/// is determined by the first parameter of the given listener. When the next frame is rendered
|
/// is determined by the first parameter of the given listener. When the next frame is rendered
|
||||||
/// the listener will be cleared.
|
/// the listener will be cleared.
|
||||||
pub fn on_mouse_event<Event: 'static>(
|
pub fn on_mouse_event<Event: MouseEvent>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static,
|
mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static,
|
||||||
) {
|
) {
|
||||||
|
@ -996,7 +997,7 @@ impl<'a> WindowContext<'a> {
|
||||||
///
|
///
|
||||||
/// This is a fairly low-level method, so prefer using event handlers on elements unless you have
|
/// This is a fairly low-level method, so prefer using event handlers on elements unless you have
|
||||||
/// a specific need to register a global listener.
|
/// a specific need to register a global listener.
|
||||||
pub fn on_key_event<Event: 'static>(
|
pub fn on_key_event<Event: KeyEvent>(
|
||||||
&mut self,
|
&mut self,
|
||||||
listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static,
|
listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static,
|
||||||
) {
|
) {
|
||||||
|
@ -1617,7 +1618,7 @@ impl<'a> WindowContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dispatch a mouse or keyboard event on the window.
|
/// Dispatch a mouse or keyboard event on the window.
|
||||||
pub fn dispatch_event(&mut self, event: InputEvent) -> bool {
|
pub fn dispatch_event(&mut self, event: PlatformInput) -> bool {
|
||||||
// Handlers may set this to false by calling `stop_propagation`.
|
// Handlers may set this to false by calling `stop_propagation`.
|
||||||
self.app.propagate_event = true;
|
self.app.propagate_event = true;
|
||||||
// Handlers may set this to true by calling `prevent_default`.
|
// Handlers may set this to true by calling `prevent_default`.
|
||||||
|
@ -1626,37 +1627,37 @@ impl<'a> WindowContext<'a> {
|
||||||
let event = match event {
|
let event = match event {
|
||||||
// Track the mouse position with our own state, since accessing the platform
|
// Track the mouse position with our own state, since accessing the platform
|
||||||
// API for the mouse position can only occur on the main thread.
|
// API for the mouse position can only occur on the main thread.
|
||||||
InputEvent::MouseMove(mouse_move) => {
|
PlatformInput::MouseMove(mouse_move) => {
|
||||||
self.window.mouse_position = mouse_move.position;
|
self.window.mouse_position = mouse_move.position;
|
||||||
self.window.modifiers = mouse_move.modifiers;
|
self.window.modifiers = mouse_move.modifiers;
|
||||||
InputEvent::MouseMove(mouse_move)
|
PlatformInput::MouseMove(mouse_move)
|
||||||
}
|
}
|
||||||
InputEvent::MouseDown(mouse_down) => {
|
PlatformInput::MouseDown(mouse_down) => {
|
||||||
self.window.mouse_position = mouse_down.position;
|
self.window.mouse_position = mouse_down.position;
|
||||||
self.window.modifiers = mouse_down.modifiers;
|
self.window.modifiers = mouse_down.modifiers;
|
||||||
InputEvent::MouseDown(mouse_down)
|
PlatformInput::MouseDown(mouse_down)
|
||||||
}
|
}
|
||||||
InputEvent::MouseUp(mouse_up) => {
|
PlatformInput::MouseUp(mouse_up) => {
|
||||||
self.window.mouse_position = mouse_up.position;
|
self.window.mouse_position = mouse_up.position;
|
||||||
self.window.modifiers = mouse_up.modifiers;
|
self.window.modifiers = mouse_up.modifiers;
|
||||||
InputEvent::MouseUp(mouse_up)
|
PlatformInput::MouseUp(mouse_up)
|
||||||
}
|
}
|
||||||
InputEvent::MouseExited(mouse_exited) => {
|
PlatformInput::MouseExited(mouse_exited) => {
|
||||||
self.window.modifiers = mouse_exited.modifiers;
|
self.window.modifiers = mouse_exited.modifiers;
|
||||||
InputEvent::MouseExited(mouse_exited)
|
PlatformInput::MouseExited(mouse_exited)
|
||||||
}
|
}
|
||||||
InputEvent::ModifiersChanged(modifiers_changed) => {
|
PlatformInput::ModifiersChanged(modifiers_changed) => {
|
||||||
self.window.modifiers = modifiers_changed.modifiers;
|
self.window.modifiers = modifiers_changed.modifiers;
|
||||||
InputEvent::ModifiersChanged(modifiers_changed)
|
PlatformInput::ModifiersChanged(modifiers_changed)
|
||||||
}
|
}
|
||||||
InputEvent::ScrollWheel(scroll_wheel) => {
|
PlatformInput::ScrollWheel(scroll_wheel) => {
|
||||||
self.window.mouse_position = scroll_wheel.position;
|
self.window.mouse_position = scroll_wheel.position;
|
||||||
self.window.modifiers = scroll_wheel.modifiers;
|
self.window.modifiers = scroll_wheel.modifiers;
|
||||||
InputEvent::ScrollWheel(scroll_wheel)
|
PlatformInput::ScrollWheel(scroll_wheel)
|
||||||
}
|
}
|
||||||
// Translate dragging and dropping of external files from the operating system
|
// Translate dragging and dropping of external files from the operating system
|
||||||
// to internal drag and drop events.
|
// to internal drag and drop events.
|
||||||
InputEvent::FileDrop(file_drop) => match file_drop {
|
PlatformInput::FileDrop(file_drop) => match file_drop {
|
||||||
FileDropEvent::Entered { position, paths } => {
|
FileDropEvent::Entered { position, paths } => {
|
||||||
self.window.mouse_position = position;
|
self.window.mouse_position = position;
|
||||||
if self.active_drag.is_none() {
|
if self.active_drag.is_none() {
|
||||||
|
@ -1666,7 +1667,7 @@ impl<'a> WindowContext<'a> {
|
||||||
cursor_offset: position,
|
cursor_offset: position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
InputEvent::MouseMove(MouseMoveEvent {
|
PlatformInput::MouseMove(MouseMoveEvent {
|
||||||
position,
|
position,
|
||||||
pressed_button: Some(MouseButton::Left),
|
pressed_button: Some(MouseButton::Left),
|
||||||
modifiers: Modifiers::default(),
|
modifiers: Modifiers::default(),
|
||||||
|
@ -1674,7 +1675,7 @@ impl<'a> WindowContext<'a> {
|
||||||
}
|
}
|
||||||
FileDropEvent::Pending { position } => {
|
FileDropEvent::Pending { position } => {
|
||||||
self.window.mouse_position = position;
|
self.window.mouse_position = position;
|
||||||
InputEvent::MouseMove(MouseMoveEvent {
|
PlatformInput::MouseMove(MouseMoveEvent {
|
||||||
position,
|
position,
|
||||||
pressed_button: Some(MouseButton::Left),
|
pressed_button: Some(MouseButton::Left),
|
||||||
modifiers: Modifiers::default(),
|
modifiers: Modifiers::default(),
|
||||||
|
@ -1683,21 +1684,21 @@ impl<'a> WindowContext<'a> {
|
||||||
FileDropEvent::Submit { position } => {
|
FileDropEvent::Submit { position } => {
|
||||||
self.activate(true);
|
self.activate(true);
|
||||||
self.window.mouse_position = position;
|
self.window.mouse_position = position;
|
||||||
InputEvent::MouseUp(MouseUpEvent {
|
PlatformInput::MouseUp(MouseUpEvent {
|
||||||
button: MouseButton::Left,
|
button: MouseButton::Left,
|
||||||
position,
|
position,
|
||||||
modifiers: Modifiers::default(),
|
modifiers: Modifiers::default(),
|
||||||
click_count: 1,
|
click_count: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FileDropEvent::Exited => InputEvent::MouseUp(MouseUpEvent {
|
FileDropEvent::Exited => PlatformInput::MouseUp(MouseUpEvent {
|
||||||
button: MouseButton::Left,
|
button: MouseButton::Left,
|
||||||
position: Point::default(),
|
position: Point::default(),
|
||||||
modifiers: Modifiers::default(),
|
modifiers: Modifiers::default(),
|
||||||
click_count: 1,
|
click_count: 1,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
InputEvent::KeyDown(_) | InputEvent::KeyUp(_) => event,
|
PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(any_mouse_event) = event.mouse_event() {
|
if let Some(any_mouse_event) = event.mouse_event() {
|
||||||
|
@ -2976,7 +2977,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||||
/// Add a listener for any mouse event that occurs in the window.
|
/// Add a listener for any mouse event that occurs in the window.
|
||||||
/// This is a fairly low level method.
|
/// This is a fairly low level method.
|
||||||
/// Typically, you'll want to use methods on UI elements, which perform bounds checking etc.
|
/// Typically, you'll want to use methods on UI elements, which perform bounds checking etc.
|
||||||
pub fn on_mouse_event<Event: 'static>(
|
pub fn on_mouse_event<Event: MouseEvent>(
|
||||||
&mut self,
|
&mut self,
|
||||||
handler: impl Fn(&mut V, &Event, DispatchPhase, &mut ViewContext<V>) + 'static,
|
handler: impl Fn(&mut V, &Event, DispatchPhase, &mut ViewContext<V>) + 'static,
|
||||||
) {
|
) {
|
||||||
|
@ -2989,7 +2990,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a callback to be invoked when the given Key Event is dispatched to the window.
|
/// Register a callback to be invoked when the given Key Event is dispatched to the window.
|
||||||
pub fn on_key_event<Event: 'static>(
|
pub fn on_key_event<Event: KeyEvent>(
|
||||||
&mut self,
|
&mut self,
|
||||||
handler: impl Fn(&mut V, &Event, DispatchPhase, &mut ViewContext<V>) + 'static,
|
handler: impl Fn(&mut V, &Event, DispatchPhase, &mut ViewContext<V>) + 'static,
|
||||||
) {
|
) {
|
||||||
|
|
Loading…
Reference in a new issue