mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 10:57:22 +03:00
Checkpoint
This commit is contained in:
parent
0dfe70125b
commit
eaef1c8b8e
@ -8,9 +8,10 @@ pub use model_context::*;
|
||||
use refineable::Refineable;
|
||||
|
||||
use crate::{
|
||||
current_platform, image_cache::ImageCache, AssetSource, Context, DisplayId, Executor, LayoutId,
|
||||
MainThread, MainThreadOnly, Platform, SubscriberSet, SvgRenderer, Task, TextStyle,
|
||||
TextStyleRefinement, TextSystem, View, Window, WindowContext, WindowHandle, WindowId,
|
||||
current_platform, image_cache::ImageCache, AssetSource, Context, DisplayId, Executor,
|
||||
FocusEvent, FocusHandle, FocusId, LayoutId, MainThread, MainThreadOnly, Platform,
|
||||
SubscriberSet, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, Window,
|
||||
WindowContext, WindowHandle, WindowId,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use collections::{HashMap, HashSet, VecDeque};
|
||||
@ -54,6 +55,7 @@ impl App {
|
||||
this: this.clone(),
|
||||
text_system: Arc::new(TextSystem::new(platform.text_system())),
|
||||
pending_updates: 0,
|
||||
flushing_effects: false,
|
||||
next_frame_callbacks: Default::default(),
|
||||
platform: MainThreadOnly::new(platform, executor.clone()),
|
||||
executor,
|
||||
@ -97,6 +99,7 @@ pub struct AppContext {
|
||||
this: Weak<Mutex<AppContext>>,
|
||||
pub(crate) platform: MainThreadOnly<dyn Platform>,
|
||||
text_system: Arc<TextSystem>,
|
||||
flushing_effects: bool,
|
||||
pending_updates: usize,
|
||||
pub(crate) next_frame_callbacks: HashMap<DisplayId, Vec<FrameCallback>>,
|
||||
pub(crate) executor: Executor,
|
||||
@ -119,8 +122,10 @@ impl AppContext {
|
||||
pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
|
||||
self.pending_updates += 1;
|
||||
let result = update(self);
|
||||
if self.pending_updates == 1 {
|
||||
if !self.flushing_effects && self.pending_updates == 1 {
|
||||
self.flushing_effects = true;
|
||||
self.flush_effects();
|
||||
self.flushing_effects = false;
|
||||
}
|
||||
self.pending_updates -= 1;
|
||||
result
|
||||
@ -158,6 +163,7 @@ impl AppContext {
|
||||
}
|
||||
}
|
||||
Effect::Emit { .. } => self.pending_effects.push_back(effect),
|
||||
Effect::FocusChanged { .. } => self.pending_effects.push_back(effect),
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,6 +174,9 @@ impl AppContext {
|
||||
match effect {
|
||||
Effect::Notify { emitter } => self.apply_notify_effect(emitter),
|
||||
Effect::Emit { emitter, event } => self.apply_emit_effect(emitter, event),
|
||||
Effect::FocusChanged { window_id, focused } => {
|
||||
self.apply_focus_changed(window_id, focused)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
@ -222,6 +231,24 @@ impl AppContext {
|
||||
.retain(&emitter, |handler| handler(&event, self));
|
||||
}
|
||||
|
||||
fn apply_focus_changed(&mut self, window_id: WindowId, focused: Option<FocusId>) {
|
||||
self.update_window(window_id, |cx| {
|
||||
if cx.window.focus == focused {
|
||||
let mut listeners = mem::take(&mut cx.window.focus_change_listeners);
|
||||
let focused = focused.map(FocusHandle::new);
|
||||
let blurred = cx.window.last_blur.unwrap().map(FocusHandle::new);
|
||||
let event = FocusEvent { focused, blurred };
|
||||
for listener in &listeners {
|
||||
listener(&event, cx);
|
||||
}
|
||||
|
||||
listeners.extend(cx.window.focus_change_listeners.drain(..));
|
||||
cx.window.focus_change_listeners = listeners;
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub fn to_async(&self) -> AsyncAppContext {
|
||||
AsyncAppContext(unsafe { mem::transmute(self.this.clone()) })
|
||||
}
|
||||
@ -426,6 +453,10 @@ pub(crate) enum Effect {
|
||||
emitter: EntityId,
|
||||
event: Box<dyn Any + Send + Sync + 'static>,
|
||||
},
|
||||
FocusChanged {
|
||||
window_id: WindowId,
|
||||
focused: Option<FocusId>,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,5 +1,9 @@
|
||||
use crate::{point, Keystroke, Modifiers, Pixels, Point};
|
||||
use std::{any::Any, ops::Deref};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
point, Bounds, DispatchPhase, FocusHandle, Keystroke, Modifiers, Pixels, Point, ViewContext,
|
||||
};
|
||||
use std::{any::Any, ops::Deref, sync::Arc};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct KeyDownEvent {
|
||||
@ -26,7 +30,7 @@ impl Deref for ModifiersChangedEvent {
|
||||
}
|
||||
|
||||
/// The phase of a touch motion event.
|
||||
/// Based on the winit enum of the same name,
|
||||
/// Based on the winit enum of the same name.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TouchPhase {
|
||||
Started,
|
||||
@ -50,6 +54,12 @@ pub struct MouseUpEvent {
|
||||
pub click_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseClickEvent {
|
||||
pub down: MouseDownEvent,
|
||||
pub up: MouseUpEvent,
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
@ -155,7 +165,7 @@ impl Deref for MouseExitEvent {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Event {
|
||||
pub enum InputEvent {
|
||||
KeyDown(KeyDownEvent),
|
||||
KeyUp(KeyUpEvent),
|
||||
ModifiersChanged(ModifiersChangedEvent),
|
||||
@ -166,30 +176,94 @@ pub enum Event {
|
||||
ScrollWheel(ScrollWheelEvent),
|
||||
}
|
||||
|
||||
impl Event {
|
||||
impl InputEvent {
|
||||
pub fn position(&self) -> Option<Point<Pixels>> {
|
||||
match self {
|
||||
Event::KeyDown { .. } => None,
|
||||
Event::KeyUp { .. } => None,
|
||||
Event::ModifiersChanged { .. } => None,
|
||||
Event::MouseDown(event) => Some(event.position),
|
||||
Event::MouseUp(event) => Some(event.position),
|
||||
Event::MouseMoved(event) => Some(event.position),
|
||||
Event::MouseExited(event) => Some(event.position),
|
||||
Event::ScrollWheel(event) => Some(event.position),
|
||||
InputEvent::KeyDown { .. } => None,
|
||||
InputEvent::KeyUp { .. } => None,
|
||||
InputEvent::ModifiersChanged { .. } => None,
|
||||
InputEvent::MouseDown(event) => Some(event.position),
|
||||
InputEvent::MouseUp(event) => Some(event.position),
|
||||
InputEvent::MouseMoved(event) => Some(event.position),
|
||||
InputEvent::MouseExited(event) => Some(event.position),
|
||||
InputEvent::ScrollWheel(event) => Some(event.position),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mouse_event<'a>(&'a self) -> Option<&'a dyn Any> {
|
||||
match self {
|
||||
Event::KeyDown { .. } => None,
|
||||
Event::KeyUp { .. } => None,
|
||||
Event::ModifiersChanged { .. } => None,
|
||||
Event::MouseDown(event) => Some(event),
|
||||
Event::MouseUp(event) => Some(event),
|
||||
Event::MouseMoved(event) => Some(event),
|
||||
Event::MouseExited(event) => Some(event),
|
||||
Event::ScrollWheel(event) => Some(event),
|
||||
InputEvent::KeyDown { .. } => None,
|
||||
InputEvent::KeyUp { .. } => None,
|
||||
InputEvent::ModifiersChanged { .. } => None,
|
||||
InputEvent::MouseDown(event) => Some(event),
|
||||
InputEvent::MouseUp(event) => Some(event),
|
||||
InputEvent::MouseMoved(event) => Some(event),
|
||||
InputEvent::MouseExited(event) => Some(event),
|
||||
InputEvent::ScrollWheel(event) => Some(event),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FocusEvent {
|
||||
pub blurred: Option<FocusHandle>,
|
||||
pub focused: Option<FocusHandle>,
|
||||
}
|
||||
|
||||
pub type MouseDownListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseDownEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
pub type MouseUpListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseUpEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
pub type MouseClickListener<V> =
|
||||
Arc<dyn Fn(&mut V, &MouseClickEvent, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
pub type MouseMoveListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseMoveEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub type ScrollWheelListener<V> = Arc<
|
||||
dyn Fn(&mut V, &ScrollWheelEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub type KeyDownListener<V> =
|
||||
Arc<dyn Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
pub type KeyUpListener<V> =
|
||||
Arc<dyn Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
pub struct EventListeners<V: 'static> {
|
||||
pub mouse_down: SmallVec<[MouseDownListener<V>; 2]>,
|
||||
pub mouse_up: SmallVec<[MouseUpListener<V>; 2]>,
|
||||
pub mouse_click: SmallVec<[MouseClickListener<V>; 2]>,
|
||||
pub mouse_move: SmallVec<[MouseMoveListener<V>; 2]>,
|
||||
pub scroll_wheel: SmallVec<[ScrollWheelListener<V>; 2]>,
|
||||
pub key_down: SmallVec<[KeyDownListener<V>; 2]>,
|
||||
pub key_up: SmallVec<[KeyUpListener<V>; 2]>,
|
||||
}
|
||||
|
||||
impl<V> Default for EventListeners<V> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mouse_down: SmallVec::new(),
|
||||
mouse_up: SmallVec::new(),
|
||||
mouse_click: SmallVec::new(),
|
||||
mouse_move: SmallVec::new(),
|
||||
scroll_wheel: SmallVec::new(),
|
||||
key_down: SmallVec::new(),
|
||||
key_up: SmallVec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
Bounds, DispatchPhase, Element, KeyDownEvent, KeyUpEvent, MouseButton, MouseDownEvent,
|
||||
MouseMoveEvent, MouseUpEvent, Pixels, ScrollWheelEvent, ViewContext,
|
||||
DispatchPhase, Element, EventListeners, MouseButton, MouseClickEvent, MouseDownEvent,
|
||||
MouseMoveEvent, MouseUpEvent, ScrollWheelEvent, ViewContext,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -163,67 +161,3 @@ pub trait Click: Interactive {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
type MouseDownListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseDownEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
type MouseUpListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseUpEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
type MouseClickListener<V> =
|
||||
Arc<dyn Fn(&mut V, &MouseClickEvent, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
type MouseMoveListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseMoveEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
type ScrollWheelListener<V> = Arc<
|
||||
dyn Fn(&mut V, &ScrollWheelEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub type KeyDownListener<V> =
|
||||
Arc<dyn Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
pub type KeyUpListener<V> =
|
||||
Arc<dyn Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
pub struct EventListeners<V: 'static> {
|
||||
pub mouse_down: SmallVec<[MouseDownListener<V>; 2]>,
|
||||
pub mouse_up: SmallVec<[MouseUpListener<V>; 2]>,
|
||||
pub mouse_click: SmallVec<[MouseClickListener<V>; 2]>,
|
||||
pub mouse_move: SmallVec<[MouseMoveListener<V>; 2]>,
|
||||
pub scroll_wheel: SmallVec<[ScrollWheelListener<V>; 2]>,
|
||||
pub key_down: SmallVec<[KeyDownListener<V>; 2]>,
|
||||
pub key_up: SmallVec<[KeyUpListener<V>; 2]>,
|
||||
}
|
||||
|
||||
impl<V> Default for EventListeners<V> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mouse_down: SmallVec::new(),
|
||||
mouse_up: SmallVec::new(),
|
||||
mouse_click: SmallVec::new(),
|
||||
mouse_move: SmallVec::new(),
|
||||
scroll_wheel: SmallVec::new(),
|
||||
key_down: SmallVec::new(),
|
||||
key_up: SmallVec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MouseClickEvent {
|
||||
pub down: MouseDownEvent,
|
||||
pub up: MouseUpEvent,
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ mod mac;
|
||||
mod test;
|
||||
|
||||
use crate::{
|
||||
AnyWindowHandle, Bounds, DevicePixels, Event, Executor, Font, FontId, FontMetrics, FontRun,
|
||||
GlobalPixels, GlyphId, LineLayout, Pixels, Point, RenderGlyphParams, RenderImageParams,
|
||||
RenderSvgParams, Result, Scene, SharedString, Size,
|
||||
AnyWindowHandle, Bounds, DevicePixels, Executor, Font, FontId, FontMetrics, FontRun,
|
||||
GlobalPixels, GlyphId, InputEvent, LineLayout, Pixels, Point, RenderGlyphParams,
|
||||
RenderImageParams, RenderSvgParams, Result, Scene, SharedString, Size,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use async_task::Runnable;
|
||||
@ -81,7 +81,7 @@ pub(crate) trait Platform: 'static {
|
||||
fn on_resign_active(&self, callback: Box<dyn FnMut()>);
|
||||
fn on_quit(&self, callback: Box<dyn FnMut()>);
|
||||
fn on_reopen(&self, callback: Box<dyn FnMut()>);
|
||||
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>);
|
||||
fn on_event(&self, callback: Box<dyn FnMut(InputEvent) -> bool>);
|
||||
|
||||
fn os_name(&self) -> &'static str;
|
||||
fn os_version(&self) -> Result<SemanticVersion>;
|
||||
@ -141,7 +141,7 @@ pub(crate) trait PlatformWindow {
|
||||
fn minimize(&self);
|
||||
fn zoom(&self);
|
||||
fn toggle_full_screen(&self);
|
||||
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>);
|
||||
fn on_event(&self, callback: Box<dyn FnMut(InputEvent) -> 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_fullscreen(&self, callback: Box<dyn FnMut(bool)>);
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
point, px, Event, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent,
|
||||
point, px, InputEvent, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent,
|
||||
MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection,
|
||||
Pixels, ScrollDelta, ScrollWheelEvent, TouchPhase,
|
||||
};
|
||||
@ -84,7 +84,7 @@ unsafe fn read_modifiers(native_event: id) -> Modifiers {
|
||||
}
|
||||
}
|
||||
|
||||
impl Event {
|
||||
impl InputEvent {
|
||||
pub unsafe fn from_native(native_event: id, window_height: Option<Pixels>) -> Option<Self> {
|
||||
let event_type = native_event.eventType();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::BoolExt;
|
||||
use crate::{
|
||||
AnyWindowHandle, ClipboardItem, CursorStyle, DisplayId, Event, Executor, MacDispatcher,
|
||||
AnyWindowHandle, ClipboardItem, CursorStyle, DisplayId, Executor, InputEvent, MacDispatcher,
|
||||
MacDisplay, MacDisplayLinker, MacTextSystem, MacWindow, PathPromptOptions, Platform,
|
||||
PlatformDisplay, PlatformTextSystem, PlatformWindow, Result, SemanticVersion, VideoTimestamp,
|
||||
WindowOptions,
|
||||
@ -153,7 +153,7 @@ pub struct MacPlatformState {
|
||||
resign_active: Option<Box<dyn FnMut()>>,
|
||||
reopen: Option<Box<dyn FnMut()>>,
|
||||
quit: Option<Box<dyn FnMut()>>,
|
||||
event: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||
event: Option<Box<dyn FnMut(InputEvent) -> bool>>,
|
||||
// menu_command: Option<Box<dyn FnMut(&dyn Action)>>,
|
||||
// validate_menu_command: Option<Box<dyn FnMut(&dyn Action) -> bool>>,
|
||||
will_open_menu: Option<Box<dyn FnMut()>>,
|
||||
@ -621,7 +621,7 @@ impl Platform for MacPlatform {
|
||||
self.0.lock().reopen = Some(callback);
|
||||
}
|
||||
|
||||
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>) {
|
||||
fn on_event(&self, callback: Box<dyn FnMut(InputEvent) -> bool>) {
|
||||
self.0.lock().event = Some(callback);
|
||||
}
|
||||
|
||||
@ -937,7 +937,7 @@ unsafe fn get_foreground_platform(object: &mut Object) -> &MacPlatform {
|
||||
|
||||
extern "C" fn send_event(this: &mut Object, _sel: Sel, native_event: id) {
|
||||
unsafe {
|
||||
if let Some(event) = Event::from_native(native_event, None) {
|
||||
if let Some(event) = InputEvent::from_native(native_event, None) {
|
||||
let platform = get_foreground_platform(this);
|
||||
if let Some(callback) = platform.0.lock().event.as_mut() {
|
||||
if !callback(event) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{display_bounds_from_native, ns_string, MacDisplay, MetalRenderer, NSRange};
|
||||
use crate::{
|
||||
display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, Event, Executor,
|
||||
GlobalPixels, KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
||||
display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, Executor, GlobalPixels,
|
||||
InputEvent, KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
||||
MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay,
|
||||
PlatformInputHandler, PlatformWindow, Point, Scene, Size, Timer, WindowAppearance,
|
||||
WindowBounds, WindowKind, WindowOptions, WindowPromptLevel,
|
||||
@ -286,7 +286,7 @@ struct MacWindowState {
|
||||
renderer: MetalRenderer,
|
||||
scene_to_render: Option<Scene>,
|
||||
kind: WindowKind,
|
||||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||
event_callback: Option<Box<dyn FnMut(InputEvent) -> bool>>,
|
||||
activate_callback: Option<Box<dyn FnMut(bool)>>,
|
||||
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
||||
@ -300,7 +300,7 @@ struct MacWindowState {
|
||||
synthetic_drag_counter: usize,
|
||||
last_fresh_keydown: Option<Keystroke>,
|
||||
traffic_light_position: Option<Point<Pixels>>,
|
||||
previous_modifiers_changed_event: Option<Event>,
|
||||
previous_modifiers_changed_event: Option<InputEvent>,
|
||||
// State tracking what the IME did after the last request
|
||||
ime_state: ImeState,
|
||||
// Retains the last IME Text
|
||||
@ -854,7 +854,7 @@ impl PlatformWindow for MacWindow {
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>) {
|
||||
fn on_event(&self, callback: Box<dyn FnMut(InputEvent) -> bool>) {
|
||||
self.0.as_ref().lock().event_callback = Some(callback);
|
||||
}
|
||||
|
||||
@ -975,9 +975,9 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||
let mut lock = window_state.as_ref().lock();
|
||||
|
||||
let window_height = lock.content_size().height;
|
||||
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
||||
let event = unsafe { InputEvent::from_native(native_event, Some(window_height)) };
|
||||
|
||||
if let Some(Event::KeyDown(event)) = event {
|
||||
if let Some(InputEvent::KeyDown(event)) = 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
|
||||
// makes no distinction between these two types of events, so we need to ignore
|
||||
@ -1045,13 +1045,13 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||
key: ime_text.clone().unwrap(),
|
||||
},
|
||||
};
|
||||
handled = callback(Event::KeyDown(event_with_ime_text));
|
||||
handled = callback(InputEvent::KeyDown(event_with_ime_text));
|
||||
}
|
||||
if !handled {
|
||||
// empty key happens when you type a deadkey in input composition.
|
||||
// (e.g. on a brazillian keyboard typing quote is a deadkey)
|
||||
if !event.keystroke.key.is_empty() {
|
||||
handled = callback(Event::KeyDown(event));
|
||||
handled = callback(InputEvent::KeyDown(event));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1097,11 +1097,11 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||
let is_active = unsafe { lock.native_window.isKeyWindow() == YES };
|
||||
|
||||
let window_height = lock.content_size().height;
|
||||
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
||||
let event = unsafe { InputEvent::from_native(native_event, Some(window_height)) };
|
||||
|
||||
if let Some(mut event) = event {
|
||||
let synthesized_second_event = match &mut event {
|
||||
Event::MouseDown(
|
||||
InputEvent::MouseDown(
|
||||
event @ MouseDownEvent {
|
||||
button: MouseButton::Left,
|
||||
modifiers: Modifiers { control: true, .. },
|
||||
@ -1118,7 +1118,7 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||
..*event
|
||||
};
|
||||
|
||||
Some(Event::MouseDown(MouseDownEvent {
|
||||
Some(InputEvent::MouseDown(MouseDownEvent {
|
||||
button: MouseButton::Right,
|
||||
..*event
|
||||
}))
|
||||
@ -1127,7 +1127,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
|
||||
// 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
|
||||
Event::MouseUp(MouseUpEvent {
|
||||
InputEvent::MouseUp(MouseUpEvent {
|
||||
button: MouseButton::Left,
|
||||
modifiers: Modifiers { control: true, .. },
|
||||
..
|
||||
@ -1140,7 +1140,7 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||
};
|
||||
|
||||
match &event {
|
||||
Event::MouseMoved(
|
||||
InputEvent::MouseMoved(
|
||||
event @ MouseMoveEvent {
|
||||
pressed_button: Some(_),
|
||||
..
|
||||
@ -1157,18 +1157,18 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||
.detach();
|
||||
}
|
||||
|
||||
Event::MouseMoved(_) if !(is_active || lock.kind == WindowKind::PopUp) => return,
|
||||
InputEvent::MouseMoved(_) if !(is_active || lock.kind == WindowKind::PopUp) => return,
|
||||
|
||||
Event::MouseUp(MouseUpEvent {
|
||||
InputEvent::MouseUp(MouseUpEvent {
|
||||
button: MouseButton::Left,
|
||||
..
|
||||
}) => {
|
||||
lock.synthetic_drag_counter += 1;
|
||||
}
|
||||
|
||||
Event::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
||||
InputEvent::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
||||
// Only raise modifiers changed event when they have actually changed
|
||||
if let Some(Event::ModifiersChanged(ModifiersChangedEvent {
|
||||
if let Some(InputEvent::ModifiersChanged(ModifiersChangedEvent {
|
||||
modifiers: prev_modifiers,
|
||||
})) = &lock.previous_modifiers_changed_event
|
||||
{
|
||||
@ -1204,7 +1204,7 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||
modifiers: Default::default(),
|
||||
key: ".".into(),
|
||||
};
|
||||
let event = Event::KeyDown(KeyDownEvent {
|
||||
let event = InputEvent::KeyDown(KeyDownEvent {
|
||||
keystroke: keystroke.clone(),
|
||||
is_held: false,
|
||||
});
|
||||
@ -1605,7 +1605,7 @@ async fn synthetic_drag(
|
||||
if lock.synthetic_drag_counter == drag_id {
|
||||
if let Some(mut callback) = lock.event_callback.take() {
|
||||
drop(lock);
|
||||
callback(Event::MouseMoved(event.clone()));
|
||||
callback(InputEvent::MouseMoved(event.clone()));
|
||||
window_state.lock().event_callback = Some(callback);
|
||||
}
|
||||
} else {
|
||||
|
@ -125,7 +125,7 @@ impl Platform for TestPlatform {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn on_event(&self, _callback: Box<dyn FnMut(crate::Event) -> bool>) {
|
||||
fn on_event(&self, _callback: Box<dyn FnMut(crate::InputEvent) -> bool>) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
use crate::{
|
||||
px, size, AnyBox, AnyView, AppContext, AsyncWindowContext, AvailableSpace, BorrowAppContext,
|
||||
Bounds, BoxShadow, Context, Corners, DevicePixels, DisplayId, Edges, Effect, Element, EntityId,
|
||||
Event, EventEmitter, FontId, GlobalElementId, GlyphId, Handle, Hsla, ImageData, IsZero,
|
||||
KeyDownEvent, KeyDownListener, KeyUpEvent, KeyUpListener, LayoutId, MainThread, MainThreadOnly,
|
||||
MonochromeSprite, MouseMoveEvent, Path, Pixels, Platform, PlatformAtlas, PlatformWindow, Point,
|
||||
PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams, RenderSvgParams,
|
||||
ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, Subscription, TaffyLayoutEngine,
|
||||
Task, Underline, UnderlineStyle, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
|
||||
EventEmitter, FocusEvent, FontId, GlobalElementId, GlyphId, Handle, Hsla, ImageData,
|
||||
InputEvent, IsZero, KeyDownEvent, KeyDownListener, KeyUpEvent, KeyUpListener, LayoutId,
|
||||
MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path, Pixels, Platform,
|
||||
PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams,
|
||||
RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
|
||||
Style, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle,
|
||||
WindowOptions, SUBPIXEL_VARIANTS,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use collections::{HashMap, HashSet};
|
||||
@ -47,13 +48,12 @@ pub struct FocusId(usize);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FocusHandle {
|
||||
id: FocusId,
|
||||
pub(crate) id: FocusId,
|
||||
}
|
||||
|
||||
impl FocusHandle {
|
||||
pub fn focus(&self, cx: &mut WindowContext) {
|
||||
cx.window.focus = Some(self.id);
|
||||
cx.notify();
|
||||
pub(crate) fn new(id: FocusId) -> Self {
|
||||
Self { id }
|
||||
}
|
||||
|
||||
pub fn is_focused(&self, cx: &WindowContext) -> bool {
|
||||
@ -95,6 +95,8 @@ pub struct Window {
|
||||
focus_stack: Vec<FocusStackFrame>,
|
||||
focus_parents_by_child: HashMap<FocusId, FocusId>,
|
||||
containing_focus: HashSet<FocusId>,
|
||||
pub(crate) focus_change_listeners:
|
||||
Vec<Arc<dyn Fn(&FocusEvent, &mut WindowContext) + Send + Sync + 'static>>,
|
||||
key_down_listeners:
|
||||
Vec<Arc<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + Send + Sync + 'static>>,
|
||||
key_up_listeners:
|
||||
@ -104,7 +106,8 @@ pub struct Window {
|
||||
scale_factor: f32,
|
||||
pub(crate) scene_builder: SceneBuilder,
|
||||
pub(crate) dirty: bool,
|
||||
focus: Option<FocusId>,
|
||||
pub(crate) last_blur: Option<Option<FocusId>>,
|
||||
pub(crate) focus: Option<FocusId>,
|
||||
next_focus_id: FocusId,
|
||||
}
|
||||
|
||||
@ -168,6 +171,7 @@ impl Window {
|
||||
focus_parents_by_child: HashMap::default(),
|
||||
containing_focus: HashSet::default(),
|
||||
mouse_listeners: HashMap::default(),
|
||||
focus_change_listeners: Vec::new(),
|
||||
key_down_listeners: Vec::new(),
|
||||
key_up_listeners: Vec::new(),
|
||||
propagate_event: true,
|
||||
@ -175,6 +179,7 @@ impl Window {
|
||||
scale_factor,
|
||||
scene_builder: SceneBuilder::new(),
|
||||
dirty: true,
|
||||
last_blur: None,
|
||||
focus: None,
|
||||
next_focus_id: FocusId(0),
|
||||
}
|
||||
@ -232,6 +237,34 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||
FocusHandle { id }
|
||||
}
|
||||
|
||||
pub fn focus(&mut self, handle: &FocusHandle) {
|
||||
if self.window.last_blur.is_none() {
|
||||
self.window.last_blur = Some(self.window.focus);
|
||||
}
|
||||
|
||||
let window_id = self.window.handle.id;
|
||||
self.window.focus = Some(handle.id);
|
||||
self.push_effect(Effect::FocusChanged {
|
||||
window_id,
|
||||
focused: Some(handle.id),
|
||||
});
|
||||
self.notify();
|
||||
}
|
||||
|
||||
pub fn blur(&mut self) {
|
||||
if self.window.last_blur.is_none() {
|
||||
self.window.last_blur = Some(self.window.focus);
|
||||
}
|
||||
|
||||
let window_id = self.window.handle.id;
|
||||
self.window.focus = None;
|
||||
self.push_effect(Effect::FocusChanged {
|
||||
window_id,
|
||||
focused: None,
|
||||
});
|
||||
self.notify();
|
||||
}
|
||||
|
||||
pub fn run_on_main<R>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut MainThread<WindowContext<'_, '_>>) -> R + Send + 'static,
|
||||
@ -720,6 +753,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||
|
||||
// Clear focus state, because we determine what is focused when the new elements
|
||||
// in the upcoming frame are initialized.
|
||||
window.focus_change_listeners.clear();
|
||||
window.key_down_listeners.clear();
|
||||
window.key_up_listeners.clear();
|
||||
window.containing_focus.clear();
|
||||
@ -730,7 +764,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||
self.text_system().end_frame();
|
||||
}
|
||||
|
||||
fn dispatch_event(&mut self, event: Event) -> bool {
|
||||
fn dispatch_event(&mut self, event: InputEvent) -> bool {
|
||||
if let Some(any_mouse_event) = event.mouse_event() {
|
||||
if let Some(MouseMoveEvent { position, .. }) = any_mouse_event.downcast_ref() {
|
||||
self.window.mouse_position = *position;
|
||||
|
Loading…
Reference in New Issue
Block a user