diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb9b6d1f7cb25cb689d624bb361529cde4251f79..60dc4c1f528a34ae2e74fc237650ab7a21516fb8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@v3 with: clean: false - submodules: 'recursive' + submodules: "recursive" - name: cargo fmt run: cargo fmt --all -- --check @@ -56,13 +56,13 @@ jobs: - name: Install Node uses: actions/setup-node@v3 with: - node-version: '18' + node-version: "18" - name: Checkout repo uses: actions/checkout@v3 with: clean: false - submodules: 'recursive' + submodules: "recursive" - name: Limit target directory size run: script/clear-target-dir-if-larger-than 70 @@ -79,9 +79,6 @@ jobs: - name: Build other binaries run: cargo build --workspace --bins --all-features - - name: Generate license file - run: script/generate-licenses - bundle: name: Bundle app runs-on: @@ -106,13 +103,13 @@ jobs: - name: Install Node uses: actions/setup-node@v3 with: - node-version: '18' + node-version: "18" - name: Checkout repo uses: actions/checkout@v3 with: clean: false - submodules: 'recursive' + submodules: "recursive" - name: Limit target directory size run: script/clear-target-dir-if-larger-than 70 diff --git a/Cargo.lock b/Cargo.lock index f614dcbeacae12cfd67bc0544e3bcdb57f04a715..0c951dd44179a5cd156e814849ed2dd8c475fc5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5059,8 +5059,8 @@ dependencies = [ name = "menu2" version = "0.1.0" dependencies = [ + "gpui2", "serde", - "serde_derive", ] [[package]] diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index b8b91b16468c0e97e25946c3e24be5a9e062dd21..3c9cd5e31eb38c80b771d677877c6bc557d6a9a4 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -27,7 +27,6 @@ impl Render for GoToLine { type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - dbg!("rendering GoToLine"); div().bg(red()).w(px(100.0)).h(px(100.0)) } } diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index b7e4cc0c6007b8b2df1352b3cf1eb280b39e8842..a3ab4263217c61795c36d064555bc118129d77bf 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -618,7 +618,7 @@ impl AppContext { window_handle .update(self, |_, cx| { if cx.window.focus == focused { - let mut listeners = mem::take(&mut cx.window.focus_listeners); + let mut listeners = mem::take(&mut cx.window.current_frame.focus_listeners); let focused = focused .map(|id| FocusHandle::for_id(id, &cx.window.focus_handles).unwrap()); let blurred = cx @@ -634,8 +634,8 @@ impl AppContext { } } - listeners.extend(cx.window.focus_listeners.drain(..)); - cx.window.focus_listeners = listeners; + listeners.extend(cx.window.current_frame.focus_listeners.drain(..)); + cx.window.current_frame.focus_listeners = listeners; } }) .ok(); diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 9b8c9dbf855d79ad0c36843250ded199e7b02c6b..d88a4119b7232838042ebe53f984b9468e1309c0 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -37,7 +37,7 @@ where { pub fn id(self, id: impl Into) -> Div, F> { Div { - interactivity: id.into().into(), + interactivity: StatefulInteractivity::new(id.into(), self.interactivity), focus: self.focus, children: self.children, group: self.group, diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index d43c6b59926de499959304d5af754bc8a97aec07..e1160227637c8374fa47e922a0fabb509308ec1e 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -30,7 +30,7 @@ where .map(|component| component.render()) .collect() }), - interactivity: id.into(), + interactivity: StatefulInteractivity::new(id, StatelessInteractivity::default()), scroll_handle: None, } } diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 308c39fe7ffe912456fc6ec677d98ecb8fb3982b..a546c1b40b9cbb073f3539133c29b1714fffd951 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -189,10 +189,10 @@ pub trait StatelessInteractive: Element { { self.stateless_interactivity().key_listeners.push(( TypeId::of::(), - Box::new(move |view, event, _, phase, cx| { - let event = event.downcast_ref().unwrap(); + Box::new(move |view, action, _dipatch_context, phase, cx| { + let action = action.downcast_ref().unwrap(); if phase == DispatchPhase::Capture { - listener(view, event, cx) + listener(view, action, cx) } None }), @@ -210,10 +210,10 @@ pub trait StatelessInteractive: Element { { self.stateless_interactivity().key_listeners.push(( TypeId::of::(), - Box::new(move |view, event, _, phase, cx| { - let event = event.downcast_ref().unwrap(); + Box::new(move |view, action, _dispatch_context, phase, cx| { + let action = action.downcast_ref().unwrap(); if phase == DispatchPhase::Bubble { - listener(view, event, cx) + listener(view, action, cx) } None @@ -407,6 +407,8 @@ pub trait ElementInteractivity: 'static { ) -> R { if let Some(stateful) = self.as_stateful_mut() { cx.with_element_id(stateful.id.clone(), |global_id, cx| { + // In addition to any key down/up listeners registered directly on the element, + // we also add a key listener to match actions from the keymap. stateful.key_listeners.push(( TypeId::of::(), Box::new(move |_, key_down, context, phase, cx| { @@ -774,6 +776,21 @@ pub struct StatefulInteractivity { tooltip_builder: Option>, } +impl StatefulInteractivity { + pub fn new(id: ElementId, stateless: StatelessInteractivity) -> Self { + Self { + id, + stateless, + click_listeners: SmallVec::new(), + active_style: StyleRefinement::default(), + group_active_style: None, + drag_listener: None, + hover_listener: None, + tooltip_builder: None, + } + } +} + impl ElementInteractivity for StatefulInteractivity { fn as_stateful(&self) -> Option<&StatefulInteractivity> { Some(self) @@ -792,21 +809,6 @@ impl ElementInteractivity for StatefulInteractivity { } } -impl From for StatefulInteractivity { - fn from(id: ElementId) -> Self { - Self { - id, - stateless: StatelessInteractivity::default(), - click_listeners: SmallVec::new(), - drag_listener: None, - hover_listener: None, - tooltip_builder: None, - active_style: StyleRefinement::default(), - group_active_style: None, - } - } -} - type DropListener = dyn Fn(&mut V, AnyView, &mut ViewContext) + 'static; pub struct StatelessInteractivity { @@ -1284,14 +1286,8 @@ mod test { fn render(&mut self, _: &mut gpui::ViewContext) -> Self::Element { div().id("testview").child( div() - .on_key_down(|this: &mut TestView, _, _, _| { - dbg!("ola!"); - this.saw_key_down = true - }) - .on_action(|this: &mut TestView, _: &TestAction, _| { - dbg!("ola!"); - this.saw_action = true - }) + .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true) + .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true) .track_focus(&self.focus_handle), ) } diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index c176479a67f7f51ae47ae7efada8ee04102dee38..87e89adfa0e15d18512d2a1a748ea5a212a48489 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -27,8 +27,8 @@ pub(crate) struct SceneBuilder { polychrome_sprites: Vec, } -impl SceneBuilder { - pub fn new() -> SceneBuilder { +impl Default for SceneBuilder { + fn default() -> Self { SceneBuilder { layers_by_order: BTreeMap::new(), splitter: BspSplitter::new(), @@ -40,7 +40,9 @@ impl SceneBuilder { polychrome_sprites: Vec::new(), } } +} +impl SceneBuilder { pub fn build(&mut self) -> Scene { // Map each layer id to a float between 0. and 1., with 1. closer to the viewer. let mut layer_z_values = vec![0.; self.layers_by_order.len()]; diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index b50dbf01347e8275ab78025a3065b14a92fe0cf4..cf138eb1ef50437de1dffbfbfa1d1b4fcdb4d2be 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -132,7 +132,12 @@ impl FocusHandle { if self.id == ancestor_id { return true; } else { - ancestor = cx.window.focus_parents_by_child.get(&ancestor_id).copied(); + ancestor = cx + .window + .current_frame + .focus_parents_by_child + .get(&ancestor_id) + .copied(); } } false @@ -175,19 +180,8 @@ pub struct Window { pub(crate) layout_engine: TaffyLayoutEngine, pub(crate) root_view: Option, pub(crate) element_id_stack: GlobalElementId, - prev_frame_element_states: HashMap, - element_states: HashMap, - prev_frame_key_matchers: HashMap, - key_matchers: HashMap, - z_index_stack: StackingOrder, - content_mask_stack: Vec>, - element_offset_stack: Vec>, - mouse_listeners: HashMap>, - key_dispatch_stack: Vec, - freeze_key_dispatch_stack: bool, - focus_stack: Vec, - focus_parents_by_child: HashMap, - pub(crate) focus_listeners: Vec, + pub(crate) previous_frame: Frame, + pub(crate) current_frame: Frame, pub(crate) focus_handles: Arc>>, default_prevented: bool, mouse_position: Point, @@ -198,12 +192,27 @@ pub struct Window { bounds_observers: SubscriberSet<(), AnyObserver>, active: bool, activation_observers: SubscriberSet<(), AnyObserver>, - pub(crate) scene_builder: SceneBuilder, pub(crate) dirty: bool, pub(crate) last_blur: Option>, pub(crate) focus: Option, } +#[derive(Default)] +pub(crate) struct Frame { + element_states: HashMap, + key_matchers: HashMap, + mouse_listeners: HashMap>, + pub(crate) focus_listeners: Vec, + key_dispatch_stack: Vec, + freeze_key_dispatch_stack: bool, + focus_parents_by_child: HashMap, + pub(crate) scene_builder: SceneBuilder, + z_index_stack: StackingOrder, + content_mask_stack: Vec>, + element_offset_stack: Vec>, + focus_stack: Vec, +} + impl Window { pub(crate) fn new( handle: AnyWindowHandle, @@ -270,19 +279,8 @@ impl Window { layout_engine: TaffyLayoutEngine::new(), root_view: None, element_id_stack: GlobalElementId::default(), - prev_frame_element_states: HashMap::default(), - element_states: HashMap::default(), - prev_frame_key_matchers: HashMap::default(), - key_matchers: HashMap::default(), - z_index_stack: StackingOrder(SmallVec::new()), - content_mask_stack: Vec::new(), - element_offset_stack: Vec::new(), - mouse_listeners: HashMap::default(), - key_dispatch_stack: Vec::new(), - freeze_key_dispatch_stack: false, - focus_stack: Vec::new(), - focus_parents_by_child: HashMap::default(), - focus_listeners: Vec::new(), + previous_frame: Frame::default(), + current_frame: Frame::default(), focus_handles: Arc::new(RwLock::new(SlotMap::with_key())), default_prevented: true, mouse_position, @@ -293,7 +291,6 @@ impl Window { bounds_observers: SubscriberSet::new(), active: false, activation_observers: SubscriberSet::new(), - scene_builder: SceneBuilder::new(), dirty: true, last_blur: None, focus: None, @@ -667,8 +664,9 @@ impl<'a> WindowContext<'a> { &mut self, handler: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - let order = self.window.z_index_stack.clone(); + let order = self.window.current_frame.z_index_stack.clone(); self.window + .current_frame .mouse_listeners .entry(TypeId::of::()) .or_default() @@ -692,9 +690,9 @@ impl<'a> WindowContext<'a> { /// Called during painting to invoke the given closure in a new stacking context. The given /// z-index is interpreted relative to the previous call to `stack`. pub fn stack(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R { - self.window.z_index_stack.push(z_index); + self.window.current_frame.z_index_stack.push(z_index); let result = f(self); - self.window.z_index_stack.pop(); + self.window.current_frame.z_index_stack.pop(); result } @@ -712,8 +710,8 @@ impl<'a> WindowContext<'a> { let mut shadow_bounds = bounds; shadow_bounds.origin += shadow.offset; shadow_bounds.dilate(shadow.spread_radius); - window.scene_builder.insert( - &window.z_index_stack, + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, Shadow { order: 0, bounds: shadow_bounds.scale(scale_factor), @@ -740,8 +738,8 @@ impl<'a> WindowContext<'a> { let content_mask = self.content_mask(); let window = &mut *self.window; - window.scene_builder.insert( - &window.z_index_stack, + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, Quad { order: 0, bounds: bounds.scale(scale_factor), @@ -761,9 +759,10 @@ impl<'a> WindowContext<'a> { path.content_mask = content_mask; path.color = color.into(); let window = &mut *self.window; - window - .scene_builder - .insert(&window.z_index_stack, path.scale(scale_factor)); + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, + path.scale(scale_factor), + ); } /// Paint an underline into the scene for the current frame at the current z-index. @@ -785,8 +784,8 @@ impl<'a> WindowContext<'a> { }; let content_mask = self.content_mask(); let window = &mut *self.window; - window.scene_builder.insert( - &window.z_index_stack, + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, Underline { order: 0, bounds: bounds.scale(scale_factor), @@ -839,8 +838,8 @@ impl<'a> WindowContext<'a> { }; let content_mask = self.content_mask().scale(scale_factor); let window = &mut *self.window; - window.scene_builder.insert( - &window.z_index_stack, + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, MonochromeSprite { order: 0, bounds, @@ -890,8 +889,8 @@ impl<'a> WindowContext<'a> { let content_mask = self.content_mask().scale(scale_factor); let window = &mut *self.window; - window.scene_builder.insert( - &window.z_index_stack, + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, PolychromeSprite { order: 0, bounds, @@ -932,8 +931,8 @@ impl<'a> WindowContext<'a> { let content_mask = self.content_mask().scale(scale_factor); let window = &mut *self.window; - window.scene_builder.insert( - &window.z_index_stack, + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, MonochromeSprite { order: 0, bounds, @@ -968,8 +967,8 @@ impl<'a> WindowContext<'a> { let corner_radii = corner_radii.scale(scale_factor); let window = &mut *self.window; - window.scene_builder.insert( - &window.z_index_stack, + window.current_frame.scene_builder.insert( + &window.current_frame.z_index_stack, PolychromeSprite { order: 0, bounds, @@ -1014,7 +1013,7 @@ impl<'a> WindowContext<'a> { } self.window.root_view = Some(root_view); - let scene = self.window.scene_builder.build(); + let scene = self.window.current_frame.scene_builder.build(); self.window.platform_window.draw(scene); let cursor_style = self @@ -1030,39 +1029,21 @@ impl<'a> WindowContext<'a> { self.window.dirty = false; } + /// Rotate the current frame and the previous frame, then clear the current frame. + /// We repopulate all state in the current frame during each paint. fn start_frame(&mut self) { self.text_system().start_frame(); let window = &mut *self.window; - - // Move the current frame element states to the previous frame. - // The new empty element states map will be populated for any element states we - // reference during the upcoming frame. - mem::swap( - &mut window.element_states, - &mut window.prev_frame_element_states, - ); - window.element_states.clear(); - - // Make the current key matchers the previous, and then clear the current. - // An empty key matcher map will be created for every identified element in the - // upcoming frame. - mem::swap( - &mut window.key_matchers, - &mut window.prev_frame_key_matchers, - ); - window.key_matchers.clear(); - - // Clear mouse event listeners, because elements add new element listeners - // when the upcoming frame is painted. - window.mouse_listeners.values_mut().for_each(Vec::clear); - - // Clear focus state, because we determine what is focused when the new elements - // in the upcoming frame are initialized. - window.focus_listeners.clear(); - window.key_dispatch_stack.clear(); - window.focus_parents_by_child.clear(); - window.freeze_key_dispatch_stack = false; + mem::swap(&mut window.previous_frame, &mut window.current_frame); + let frame = &mut window.current_frame; + frame.element_states.clear(); + frame.key_matchers.clear(); + frame.mouse_listeners.values_mut().for_each(Vec::clear); + frame.focus_listeners.clear(); + frame.key_dispatch_stack.clear(); + frame.focus_parents_by_child.clear(); + frame.freeze_key_dispatch_stack = false; } /// Dispatch a mouse or keyboard event on the window. @@ -1126,6 +1107,7 @@ impl<'a> WindowContext<'a> { if let Some(any_mouse_event) = event.mouse_event() { if let Some(mut handlers) = self .window + .current_frame .mouse_listeners .remove(&any_mouse_event.type_id()) { @@ -1160,18 +1142,19 @@ impl<'a> WindowContext<'a> { // Just in case any handlers added new handlers, which is weird, but possible. handlers.extend( self.window + .current_frame .mouse_listeners .get_mut(&any_mouse_event.type_id()) .into_iter() .flat_map(|handlers| handlers.drain(..)), ); self.window + .current_frame .mouse_listeners .insert(any_mouse_event.type_id(), handlers); } } else if let Some(any_key_event) = event.keyboard_event() { - let mut did_handle_action = false; - let key_dispatch_stack = mem::take(&mut self.window.key_dispatch_stack); + let key_dispatch_stack = mem::take(&mut self.window.current_frame.key_dispatch_stack); let key_event_type = any_key_event.type_id(); let mut context_stack = SmallVec::<[&DispatchContext; 16]>::new(); @@ -1191,7 +1174,6 @@ impl<'a> WindowContext<'a> { self.dispatch_action(action, &key_dispatch_stack[..ix]); } if !self.app.propagate_event { - did_handle_action = true; break; } } @@ -1220,7 +1202,6 @@ impl<'a> WindowContext<'a> { } if !self.app.propagate_event { - did_handle_action = true; break; } } @@ -1233,11 +1214,10 @@ impl<'a> WindowContext<'a> { } drop(context_stack); - self.window.key_dispatch_stack = key_dispatch_stack; - return did_handle_action; + self.window.current_frame.key_dispatch_stack = key_dispatch_stack; } - true + !self.app.propagate_event } /// Attempt to map a keystroke to an action based on the keymap. @@ -1249,13 +1229,14 @@ impl<'a> WindowContext<'a> { ) -> KeyMatch { let key_match = self .window + .current_frame .key_matchers .get_mut(element_id) .unwrap() .match_keystroke(keystroke, context_stack); if key_match.is_some() { - for matcher in self.window.key_matchers.values_mut() { + for matcher in self.window.current_frame.key_matchers.values_mut() { matcher.clear_pending(); } } @@ -1527,11 +1508,12 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { window.element_id_stack.push(id.into()); let global_id = window.element_id_stack.clone(); - if window.key_matchers.get(&global_id).is_none() { - window.key_matchers.insert( + if window.current_frame.key_matchers.get(&global_id).is_none() { + window.current_frame.key_matchers.insert( global_id.clone(), window - .prev_frame_key_matchers + .previous_frame + .key_matchers .remove(&global_id) .unwrap_or_else(|| KeyMatcher::new(keymap)), ); @@ -1551,9 +1533,12 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { f: impl FnOnce(&mut Self) -> R, ) -> R { let mask = mask.intersect(&self.content_mask()); - self.window_mut().content_mask_stack.push(mask); + self.window_mut() + .current_frame + .content_mask_stack + .push(mask); let result = f(self); - self.window_mut().content_mask_stack.pop(); + self.window_mut().current_frame.content_mask_stack.pop(); result } @@ -1569,15 +1554,19 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { }; let offset = self.element_offset() + offset; - self.window_mut().element_offset_stack.push(offset); + self.window_mut() + .current_frame + .element_offset_stack + .push(offset); let result = f(self); - self.window_mut().element_offset_stack.pop(); + self.window_mut().current_frame.element_offset_stack.pop(); result } /// Obtain the current element offset. fn element_offset(&self) -> Point { self.window() + .current_frame .element_offset_stack .last() .copied() @@ -1599,9 +1588,15 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { self.with_element_id(id, |global_id, cx| { if let Some(any) = cx .window_mut() + .current_frame .element_states .remove(&global_id) - .or_else(|| cx.window_mut().prev_frame_element_states.remove(&global_id)) + .or_else(|| { + cx.window_mut() + .previous_frame + .element_states + .remove(&global_id) + }) { // Using the extra inner option to avoid needing to reallocate a new box. let mut state_box = any @@ -1612,11 +1607,15 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { .expect("element state is already on the stack"); let (result, state) = f(Some(state), cx); state_box.replace(state); - cx.window_mut().element_states.insert(global_id, state_box); + cx.window_mut() + .current_frame + .element_states + .insert(global_id, state_box); result } else { let (result, state) = f(None, cx); cx.window_mut() + .current_frame .element_states .insert(global_id, Box::new(Some(state))); result @@ -1644,6 +1643,7 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { /// Obtain the current content mask. fn content_mask(&self) -> ContentMask { self.window() + .current_frame .content_mask_stack .last() .cloned() @@ -1728,9 +1728,9 @@ impl<'a, V: 'static> ViewContext<'a, V> { } pub fn with_z_index(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R { - self.window.z_index_stack.push(z_index); + self.window.current_frame.z_index_stack.push(z_index); let result = f(self); - self.window.z_index_stack.pop(); + self.window.current_frame.z_index_stack.pop(); result } @@ -1885,11 +1885,14 @@ impl<'a, V: 'static> ViewContext<'a, V> { listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, ) { let handle = self.view().downgrade(); - self.window.focus_listeners.push(Box::new(move |event, cx| { - handle - .update(cx, |view, cx| listener(view, event, cx)) - .log_err(); - })); + self.window + .current_frame + .focus_listeners + .push(Box::new(move |event, cx| { + handle + .update(cx, |view, cx| listener(view, event, cx)) + .log_err(); + })); } pub fn with_key_listeners( @@ -1897,8 +1900,8 @@ impl<'a, V: 'static> ViewContext<'a, V> { key_listeners: impl IntoIterator)>, f: impl FnOnce(&mut Self) -> R, ) -> R { - let old_stack_len = self.window.key_dispatch_stack.len(); - if !self.window.freeze_key_dispatch_stack { + let old_stack_len = self.window.current_frame.key_dispatch_stack.len(); + if !self.window.current_frame.freeze_key_dispatch_stack { for (event_type, listener) in key_listeners { let handle = self.view().downgrade(); let listener = Box::new( @@ -1914,19 +1917,22 @@ impl<'a, V: 'static> ViewContext<'a, V> { .flatten() }, ); - self.window - .key_dispatch_stack - .push(KeyDispatchStackFrame::Listener { + self.window.current_frame.key_dispatch_stack.push( + KeyDispatchStackFrame::Listener { event_type, listener, - }); + }, + ); } } let result = f(self); - if !self.window.freeze_key_dispatch_stack { - self.window.key_dispatch_stack.truncate(old_stack_len); + if !self.window.current_frame.freeze_key_dispatch_stack { + self.window + .current_frame + .key_dispatch_stack + .truncate(old_stack_len); } result @@ -1941,16 +1947,17 @@ impl<'a, V: 'static> ViewContext<'a, V> { return f(self); } - if !self.window.freeze_key_dispatch_stack { + if !self.window.current_frame.freeze_key_dispatch_stack { self.window + .current_frame .key_dispatch_stack .push(KeyDispatchStackFrame::Context(context)); } let result = f(self); - if !self.window.freeze_key_dispatch_stack { - self.window.key_dispatch_stack.pop(); + if !self.window.previous_frame.freeze_key_dispatch_stack { + self.window.previous_frame.key_dispatch_stack.pop(); } result @@ -1961,20 +1968,21 @@ impl<'a, V: 'static> ViewContext<'a, V> { focus_handle: FocusHandle, f: impl FnOnce(&mut Self) -> R, ) -> R { - if let Some(parent_focus_id) = self.window.focus_stack.last().copied() { + if let Some(parent_focus_id) = self.window.current_frame.focus_stack.last().copied() { self.window + .current_frame .focus_parents_by_child .insert(focus_handle.id, parent_focus_id); } - self.window.focus_stack.push(focus_handle.id); + self.window.current_frame.focus_stack.push(focus_handle.id); if Some(focus_handle.id) == self.window.focus { - self.window.freeze_key_dispatch_stack = true; + self.window.current_frame.freeze_key_dispatch_stack = true; } let result = f(self); - self.window.focus_stack.pop(); + self.window.current_frame.focus_stack.pop(); result } diff --git a/crates/menu2/Cargo.toml b/crates/menu2/Cargo.toml index 5fc33ddb11d41416c4b64aa15d7e3d1564952f94..0585f988858279552ce09a6abde7addd99c387fb 100644 --- a/crates/menu2/Cargo.toml +++ b/crates/menu2/Cargo.toml @@ -9,5 +9,5 @@ path = "src/menu2.rs" doctest = false [dependencies] -serde.workspace = true -serde_derive.workspace = true +gpui = { package = "gpui2", path = "../gpui2" } +serde = { workspace = true } diff --git a/crates/menu2/src/menu2.rs b/crates/menu2/src/menu2.rs index da21bdcd2282cd4834f42eb67839553ea5c6ae91..e5e8242f37ecc92090c08718f55763a94426a0f9 100644 --- a/crates/menu2/src/menu2.rs +++ b/crates/menu2/src/menu2.rs @@ -1,25 +1,12 @@ -use serde_derive::Deserialize; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct Cancel; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct Confirm; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct SecondaryConfirm; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct SelectPrev; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct SelectNext; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct SelectFirst; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct SelectLast; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq)] -pub struct ShowContextMenu; +use gpui::actions; + +actions!( + Cancel, + Confirm, + SecondaryConfirm, + SelectPrev, + SelectNext, + SelectFirst, + SelectLast, + ShowContextMenu +);