1use crate::{
2 elements::AnyRootElement,
3 geometry::rect::RectF,
4 json::{self, ToJson},
5 keymap_matcher::{Binding, Keystroke, MatchResult},
6 platform::{
7 self, Appearance, CursorStyle, Event, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent,
8 MouseButton, MouseMovedEvent, PromptLevel, WindowBounds,
9 },
10 scene::{
11 CursorRegion, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover,
12 MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene,
13 },
14 text_layout::TextLayoutCache,
15 util::post_inc,
16 Action, AnyView, AnyViewHandle, AppContext, BorrowAppContext, Effect, Element, Entity, Handle,
17 ModelContext, ModelHandle, MouseRegion, MouseRegionId, ParentId, SceneBuilder, Subscription,
18 UpdateModel, UpdateView, View, ViewContext, ViewHandle, WindowInvalidation,
19};
20use anyhow::{anyhow, bail, Result};
21use collections::{HashMap, HashSet};
22use pathfinder_geometry::vector::{vec2f, Vector2F};
23use postage::oneshot;
24use serde_json::json;
25use smallvec::SmallVec;
26use sqlez::{
27 bindable::{Bind, Column, StaticColumnCount},
28 statement::Statement,
29};
30use std::{
31 any::TypeId,
32 ops::{Deref, DerefMut, Range},
33};
34use util::ResultExt;
35use uuid::Uuid;
36
37use super::Reference;
38
39pub struct Window {
40 pub(crate) root_view: Option<AnyViewHandle>,
41 pub(crate) focused_view_id: Option<usize>,
42 pub(crate) is_active: bool,
43 pub(crate) is_fullscreen: bool,
44 pub(crate) invalidation: Option<WindowInvalidation>,
45 pub(crate) platform_window: Box<dyn platform::Window>,
46 pub(crate) rendered_views: HashMap<usize, Box<dyn AnyRootElement>>,
47 titlebar_height: f32,
48 appearance: Appearance,
49 cursor_regions: Vec<CursorRegion>,
50 mouse_regions: Vec<(MouseRegion, usize)>,
51 last_mouse_moved_event: Option<Event>,
52 pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
53 pub(crate) clicked_region_ids: HashSet<MouseRegionId>,
54 pub(crate) clicked_button: Option<MouseButton>,
55 mouse_position: Vector2F,
56 text_layout_cache: TextLayoutCache,
57}
58
59impl Window {
60 pub fn new<V, F>(
61 window_id: usize,
62 platform_window: Box<dyn platform::Window>,
63 cx: &mut AppContext,
64 build_view: F,
65 ) -> Self
66 where
67 F: FnOnce(&mut ViewContext<V>) -> V,
68 V: View,
69 {
70 let titlebar_height = platform_window.titlebar_height();
71 let appearance = platform_window.appearance();
72 let mut window = Self {
73 root_view: None,
74 focused_view_id: None,
75 is_active: false,
76 invalidation: None,
77 is_fullscreen: false,
78 platform_window,
79 rendered_views: Default::default(),
80 cursor_regions: Default::default(),
81 mouse_regions: Default::default(),
82 text_layout_cache: TextLayoutCache::new(cx.font_system.clone()),
83 last_mouse_moved_event: None,
84 hovered_region_ids: Default::default(),
85 clicked_region_ids: Default::default(),
86 clicked_button: None,
87 mouse_position: vec2f(0., 0.),
88 titlebar_height,
89 appearance,
90 };
91
92 let mut window_context = WindowContext::mutable(cx, &mut window, window_id);
93 let root_view = window_context
94 .build_and_insert_view(ParentId::Root, |cx| Some(build_view(cx)))
95 .unwrap();
96 if let Some(mut invalidation) = window_context.window.invalidation.take() {
97 window_context.invalidate(&mut invalidation, appearance);
98 }
99 window.focused_view_id = Some(root_view.id());
100 window.root_view = Some(root_view.into_any());
101 window
102 }
103
104 pub fn root_view(&self) -> &AnyViewHandle {
105 &self
106 .root_view
107 .as_ref()
108 .expect("root_view called during window construction")
109 }
110}
111
112pub struct WindowContext<'a> {
113 pub(crate) app_context: Reference<'a, AppContext>,
114 pub(crate) window: Reference<'a, Window>,
115 pub(crate) window_id: usize,
116 pub(crate) refreshing: bool,
117 pub(crate) removed: bool,
118}
119
120impl Deref for WindowContext<'_> {
121 type Target = AppContext;
122
123 fn deref(&self) -> &Self::Target {
124 &self.app_context
125 }
126}
127
128impl DerefMut for WindowContext<'_> {
129 fn deref_mut(&mut self) -> &mut Self::Target {
130 &mut self.app_context
131 }
132}
133
134impl BorrowAppContext for WindowContext<'_> {
135 fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
136 self.app_context.read_with(f)
137 }
138
139 fn update<T, F: FnOnce(&mut AppContext) -> T>(&mut self, f: F) -> T {
140 self.app_context.update(f)
141 }
142}
143
144impl UpdateModel for WindowContext<'_> {
145 fn update_model<T: Entity, R>(
146 &mut self,
147 handle: &ModelHandle<T>,
148 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> R,
149 ) -> R {
150 self.app_context.update_model(handle, update)
151 }
152}
153
154impl UpdateView for WindowContext<'_> {
155 type Output<S> = S;
156
157 fn update_view<T, S>(
158 &mut self,
159 handle: &ViewHandle<T>,
160 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
161 ) -> S
162 where
163 T: View,
164 {
165 self.update_any_view(handle.view_id, |view, cx| {
166 let mut cx = ViewContext::mutable(cx, handle.view_id);
167 update(
168 view.as_any_mut()
169 .downcast_mut()
170 .expect("downcast is type safe"),
171 &mut cx,
172 )
173 })
174 .expect("view is already on the stack")
175 }
176}
177
178impl<'a> WindowContext<'a> {
179 pub fn mutable(
180 app_context: &'a mut AppContext,
181 window: &'a mut Window,
182 window_id: usize,
183 ) -> Self {
184 Self {
185 app_context: Reference::Mutable(app_context),
186 window: Reference::Mutable(window),
187 window_id,
188 refreshing: false,
189 removed: false,
190 }
191 }
192
193 pub fn immutable(app_context: &'a AppContext, window: &'a Window, window_id: usize) -> Self {
194 Self {
195 app_context: Reference::Immutable(app_context),
196 window: Reference::Immutable(window),
197 window_id,
198 refreshing: false,
199 removed: false,
200 }
201 }
202
203 pub fn remove_window(&mut self) {
204 self.removed = true;
205 }
206
207 pub fn window_id(&self) -> usize {
208 self.window_id
209 }
210
211 pub fn app_context(&mut self) -> &mut AppContext {
212 &mut self.app_context
213 }
214
215 pub fn root_view(&self) -> &AnyViewHandle {
216 self.window.root_view()
217 }
218
219 pub fn window_size(&self) -> Vector2F {
220 self.window.platform_window.content_size()
221 }
222
223 pub fn text_layout_cache(&self) -> &TextLayoutCache {
224 &self.window.text_layout_cache
225 }
226
227 pub(crate) fn update_any_view<F, T>(&mut self, view_id: usize, f: F) -> Option<T>
228 where
229 F: FnOnce(&mut dyn AnyView, &mut Self) -> T,
230 {
231 let window_id = self.window_id;
232 let mut view = self.views.remove(&(window_id, view_id))?;
233 let result = f(view.as_mut(), self);
234 self.views.insert((window_id, view_id), view);
235 Some(result)
236 }
237
238 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut WindowContext)) {
239 let window_id = self.window_id;
240 self.app_context.defer(move |cx| {
241 cx.update_window(window_id, |cx| callback(cx));
242 })
243 }
244
245 pub fn update_global<T, F, U>(&mut self, update: F) -> U
246 where
247 T: 'static,
248 F: FnOnce(&mut T, &mut Self) -> U,
249 {
250 AppContext::update_global_internal(self, |global, cx| update(global, cx))
251 }
252
253 pub fn update_default_global<T, F, U>(&mut self, update: F) -> U
254 where
255 T: 'static + Default,
256 F: FnOnce(&mut T, &mut Self) -> U,
257 {
258 AppContext::update_default_global_internal(self, |global, cx| update(global, cx))
259 }
260
261 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
262 where
263 E: Entity,
264 E::Event: 'static,
265 H: Handle<E>,
266 F: 'static + FnMut(H, &E::Event, &mut WindowContext),
267 {
268 self.subscribe_internal(handle, move |emitter, event, cx| {
269 callback(emitter, event, cx);
270 true
271 })
272 }
273
274 pub fn subscribe_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
275 where
276 E: Entity,
277 E::Event: 'static,
278 H: Handle<E>,
279 F: 'static + FnMut(H, &E::Event, &mut WindowContext) -> bool,
280 {
281 let window_id = self.window_id;
282 self.app_context
283 .subscribe_internal(handle, move |emitter, event, cx| {
284 cx.update_window(window_id, |cx| callback(emitter, event, cx))
285 .unwrap_or(false)
286 })
287 }
288
289 pub(crate) fn observe_window_activation<F>(&mut self, callback: F) -> Subscription
290 where
291 F: 'static + FnMut(bool, &mut WindowContext) -> bool,
292 {
293 let window_id = self.window_id;
294 let subscription_id = post_inc(&mut self.next_subscription_id);
295 self.pending_effects
296 .push_back(Effect::WindowActivationObservation {
297 window_id,
298 subscription_id,
299 callback: Box::new(callback),
300 });
301 Subscription::WindowActivationObservation(
302 self.window_activation_observations
303 .subscribe(window_id, subscription_id),
304 )
305 }
306
307 pub(crate) fn observe_fullscreen<F>(&mut self, callback: F) -> Subscription
308 where
309 F: 'static + FnMut(bool, &mut WindowContext) -> bool,
310 {
311 let window_id = self.window_id;
312 let subscription_id = post_inc(&mut self.next_subscription_id);
313 self.pending_effects
314 .push_back(Effect::WindowFullscreenObservation {
315 window_id,
316 subscription_id,
317 callback: Box::new(callback),
318 });
319 Subscription::WindowActivationObservation(
320 self.window_activation_observations
321 .subscribe(window_id, subscription_id),
322 )
323 }
324
325 pub(crate) fn observe_window_bounds<F>(&mut self, callback: F) -> Subscription
326 where
327 F: 'static + FnMut(WindowBounds, Uuid, &mut WindowContext) -> bool,
328 {
329 let window_id = self.window_id;
330 let subscription_id = post_inc(&mut self.next_subscription_id);
331 self.pending_effects
332 .push_back(Effect::WindowBoundsObservation {
333 window_id,
334 subscription_id,
335 callback: Box::new(callback),
336 });
337 Subscription::WindowBoundsObservation(
338 self.window_bounds_observations
339 .subscribe(window_id, subscription_id),
340 )
341 }
342
343 pub fn observe_keystrokes<F>(&mut self, callback: F) -> Subscription
344 where
345 F: 'static
346 + FnMut(&Keystroke, &MatchResult, Option<&Box<dyn Action>>, &mut WindowContext) -> bool,
347 {
348 let window_id = self.window_id;
349 let subscription_id = post_inc(&mut self.next_subscription_id);
350 self.keystroke_observations
351 .add_callback(window_id, subscription_id, Box::new(callback));
352 Subscription::KeystrokeObservation(
353 self.keystroke_observations
354 .subscribe(window_id, subscription_id),
355 )
356 }
357
358 /// Return keystrokes that would dispatch the given action on the given view.
359 pub(crate) fn keystrokes_for_action(
360 &mut self,
361 view_id: usize,
362 action: &dyn Action,
363 ) -> Option<SmallVec<[Keystroke; 2]>> {
364 let window_id = self.window_id;
365 let mut contexts = Vec::new();
366 let mut handler_depth = None;
367 for (i, view_id) in self.ancestors(view_id).enumerate() {
368 if let Some(view) = self.views.get(&(window_id, view_id)) {
369 if let Some(actions) = self.actions.get(&view.as_any().type_id()) {
370 if actions.contains_key(&action.as_any().type_id()) {
371 handler_depth = Some(i);
372 }
373 }
374 contexts.push(view.keymap_context(self));
375 }
376 }
377
378 if self.global_actions.contains_key(&action.as_any().type_id()) {
379 handler_depth = Some(contexts.len())
380 }
381
382 self.keystroke_matcher
383 .bindings_for_action_type(action.as_any().type_id())
384 .find_map(|b| {
385 handler_depth
386 .map(|highest_handler| {
387 if (0..=highest_handler).any(|depth| b.match_context(&contexts[depth..])) {
388 Some(b.keystrokes().into())
389 } else {
390 None
391 }
392 })
393 .flatten()
394 })
395 }
396
397 pub fn available_actions(
398 &self,
399 view_id: usize,
400 ) -> impl Iterator<Item = (&'static str, Box<dyn Action>, SmallVec<[&Binding; 1]>)> {
401 let window_id = self.window_id;
402 let mut contexts = Vec::new();
403 let mut handler_depths_by_action_type = HashMap::<TypeId, usize>::default();
404 for (depth, view_id) in self.ancestors(view_id).enumerate() {
405 if let Some(view) = self.views.get(&(window_id, view_id)) {
406 contexts.push(view.keymap_context(self));
407 let view_type = view.as_any().type_id();
408 if let Some(actions) = self.actions.get(&view_type) {
409 handler_depths_by_action_type.extend(
410 actions
411 .keys()
412 .copied()
413 .map(|action_type| (action_type, depth)),
414 );
415 }
416 }
417 }
418
419 handler_depths_by_action_type.extend(
420 self.global_actions
421 .keys()
422 .copied()
423 .map(|action_type| (action_type, contexts.len())),
424 );
425
426 self.action_deserializers
427 .iter()
428 .filter_map(move |(name, (type_id, deserialize))| {
429 if let Some(action_depth) = handler_depths_by_action_type.get(type_id).copied() {
430 Some((
431 *name,
432 deserialize("{}").ok()?,
433 self.keystroke_matcher
434 .bindings_for_action_type(*type_id)
435 .filter(|b| {
436 (0..=action_depth).any(|depth| b.match_context(&contexts[depth..]))
437 })
438 .collect(),
439 ))
440 } else {
441 None
442 }
443 })
444 }
445
446 pub fn dispatch_keystroke(&mut self, keystroke: &Keystroke) -> bool {
447 let window_id = self.window_id;
448 if let Some(focused_view_id) = self.focused_view_id() {
449 let dispatch_path = self
450 .ancestors(focused_view_id)
451 .filter_map(|view_id| {
452 self.views
453 .get(&(window_id, view_id))
454 .map(|view| (view_id, view.keymap_context(self)))
455 })
456 .collect();
457
458 let match_result = self
459 .keystroke_matcher
460 .push_keystroke(keystroke.clone(), dispatch_path);
461 let mut handled_by = None;
462
463 let keystroke_handled = match &match_result {
464 MatchResult::None => false,
465 MatchResult::Pending => true,
466 MatchResult::Matches(matches) => {
467 for (view_id, action) in matches {
468 if self.handle_dispatch_action_from_effect(Some(*view_id), action.as_ref())
469 {
470 self.keystroke_matcher.clear_pending();
471 handled_by = Some(action.boxed_clone());
472 break;
473 }
474 }
475 handled_by.is_some()
476 }
477 };
478
479 self.keystroke(
480 window_id,
481 keystroke.clone(),
482 handled_by,
483 match_result.clone(),
484 );
485 keystroke_handled
486 } else {
487 self.keystroke(window_id, keystroke.clone(), None, MatchResult::None);
488 false
489 }
490 }
491
492 pub fn dispatch_event(&mut self, event: Event, event_reused: bool) -> bool {
493 let mut mouse_events = SmallVec::<[_; 2]>::new();
494 let mut notified_views: HashSet<usize> = Default::default();
495 let window_id = self.window_id;
496
497 // 1. Handle platform event. Keyboard events get dispatched immediately, while mouse events
498 // get mapped into the mouse-specific MouseEvent type.
499 // -> These are usually small: [Mouse Down] or [Mouse up, Click] or [Mouse Moved, Mouse Dragged?]
500 // -> Also updates mouse-related state
501 match &event {
502 Event::KeyDown(e) => return self.dispatch_key_down(e),
503
504 Event::KeyUp(e) => return self.dispatch_key_up(e),
505
506 Event::ModifiersChanged(e) => return self.dispatch_modifiers_changed(e),
507
508 Event::MouseDown(e) => {
509 // Click events are weird because they can be fired after a drag event.
510 // MDN says that browsers handle this by starting from 'the most
511 // specific ancestor element that contained both [positions]'
512 // So we need to store the overlapping regions on mouse down.
513
514 // If there is already clicked_button stored, don't replace it.
515 if self.window.clicked_button.is_none() {
516 self.window.clicked_region_ids = self
517 .window
518 .mouse_regions
519 .iter()
520 .filter_map(|(region, _)| {
521 if region.bounds.contains_point(e.position) {
522 Some(region.id())
523 } else {
524 None
525 }
526 })
527 .collect();
528
529 self.window.clicked_button = Some(e.button);
530 }
531
532 mouse_events.push(MouseEvent::Down(MouseDown {
533 region: Default::default(),
534 platform_event: e.clone(),
535 }));
536 mouse_events.push(MouseEvent::DownOut(MouseDownOut {
537 region: Default::default(),
538 platform_event: e.clone(),
539 }));
540 }
541
542 Event::MouseUp(e) => {
543 // NOTE: The order of event pushes is important! MouseUp events MUST be fired
544 // before click events, and so the MouseUp events need to be pushed before
545 // MouseClick events.
546 mouse_events.push(MouseEvent::Up(MouseUp {
547 region: Default::default(),
548 platform_event: e.clone(),
549 }));
550 mouse_events.push(MouseEvent::UpOut(MouseUpOut {
551 region: Default::default(),
552 platform_event: e.clone(),
553 }));
554 mouse_events.push(MouseEvent::Click(MouseClick {
555 region: Default::default(),
556 platform_event: e.clone(),
557 }));
558 }
559
560 Event::MouseMoved(
561 e @ MouseMovedEvent {
562 position,
563 pressed_button,
564 ..
565 },
566 ) => {
567 let mut style_to_assign = CursorStyle::Arrow;
568 for region in self.window.cursor_regions.iter().rev() {
569 if region.bounds.contains_point(*position) {
570 style_to_assign = region.style;
571 break;
572 }
573 }
574
575 if self
576 .window
577 .platform_window
578 .is_topmost_for_position(*position)
579 {
580 self.platform().set_cursor_style(style_to_assign);
581 }
582
583 if !event_reused {
584 if pressed_button.is_some() {
585 mouse_events.push(MouseEvent::Drag(MouseDrag {
586 region: Default::default(),
587 prev_mouse_position: self.window.mouse_position,
588 platform_event: e.clone(),
589 }));
590 } else if let Some(clicked_button) = self.window.clicked_button {
591 // Mouse up event happened outside the current window. Simulate mouse up button event
592 let button_event = e.to_button_event(clicked_button);
593 mouse_events.push(MouseEvent::Up(MouseUp {
594 region: Default::default(),
595 platform_event: button_event.clone(),
596 }));
597 mouse_events.push(MouseEvent::UpOut(MouseUpOut {
598 region: Default::default(),
599 platform_event: button_event.clone(),
600 }));
601 mouse_events.push(MouseEvent::Click(MouseClick {
602 region: Default::default(),
603 platform_event: button_event.clone(),
604 }));
605 }
606
607 mouse_events.push(MouseEvent::Move(MouseMove {
608 region: Default::default(),
609 platform_event: e.clone(),
610 }));
611 }
612
613 mouse_events.push(MouseEvent::Hover(MouseHover {
614 region: Default::default(),
615 platform_event: e.clone(),
616 started: false,
617 }));
618 mouse_events.push(MouseEvent::MoveOut(MouseMoveOut {
619 region: Default::default(),
620 }));
621
622 self.window.last_mouse_moved_event = Some(event.clone());
623 }
624
625 Event::MouseExited(event) => {
626 // When the platform sends a MouseExited event, synthesize
627 // a MouseMoved event whose position is outside the window's
628 // bounds so that hover and cursor state can be updated.
629 return self.dispatch_event(
630 Event::MouseMoved(MouseMovedEvent {
631 position: event.position,
632 pressed_button: event.pressed_button,
633 modifiers: event.modifiers,
634 }),
635 event_reused,
636 );
637 }
638
639 Event::ScrollWheel(e) => mouse_events.push(MouseEvent::ScrollWheel(MouseScrollWheel {
640 region: Default::default(),
641 platform_event: e.clone(),
642 })),
643 }
644
645 if let Some(position) = event.position() {
646 self.window.mouse_position = position;
647 }
648
649 // 2. Dispatch mouse events on regions
650 let mut any_event_handled = false;
651 for mut mouse_event in mouse_events {
652 let mut valid_regions = Vec::new();
653
654 // GPUI elements are arranged by z_index but sibling elements can register overlapping
655 // mouse regions. As such, hover events are only fired on overlapping elements which
656 // are at the same z-index as the topmost element which overlaps with the mouse.
657 match &mouse_event {
658 MouseEvent::Hover(_) => {
659 let mut highest_z_index = None;
660 let mouse_position = self.window.mouse_position.clone();
661 let window = &mut *self.window;
662 for (region, z_index) in window.mouse_regions.iter().rev() {
663 // Allow mouse regions to appear transparent to hovers
664 if !region.hoverable {
665 continue;
666 }
667
668 let contains_mouse = region.bounds.contains_point(mouse_position);
669
670 if contains_mouse && highest_z_index.is_none() {
671 highest_z_index = Some(z_index);
672 }
673
674 // This unwrap relies on short circuiting boolean expressions
675 // The right side of the && is only executed when contains_mouse
676 // is true, and we know above that when contains_mouse is true
677 // highest_z_index is set.
678 if contains_mouse && z_index == highest_z_index.unwrap() {
679 //Ensure that hover entrance events aren't sent twice
680 if window.hovered_region_ids.insert(region.id()) {
681 valid_regions.push(region.clone());
682 if region.notify_on_hover {
683 notified_views.insert(region.id().view_id());
684 }
685 }
686 } else {
687 // Ensure that hover exit events aren't sent twice
688 if window.hovered_region_ids.remove(®ion.id()) {
689 valid_regions.push(region.clone());
690 if region.notify_on_hover {
691 notified_views.insert(region.id().view_id());
692 }
693 }
694 }
695 }
696 }
697
698 MouseEvent::Down(_) | MouseEvent::Up(_) => {
699 for (region, _) in self.window.mouse_regions.iter().rev() {
700 if region.bounds.contains_point(self.window.mouse_position) {
701 valid_regions.push(region.clone());
702 if region.notify_on_click {
703 notified_views.insert(region.id().view_id());
704 }
705 }
706 }
707 }
708
709 MouseEvent::Click(e) => {
710 // Only raise click events if the released button is the same as the one stored
711 if self
712 .window
713 .clicked_button
714 .map(|clicked_button| clicked_button == e.button)
715 .unwrap_or(false)
716 {
717 // Clear clicked regions and clicked button
718 let clicked_region_ids = std::mem::replace(
719 &mut self.window.clicked_region_ids,
720 Default::default(),
721 );
722 self.window.clicked_button = None;
723
724 // Find regions which still overlap with the mouse since the last MouseDown happened
725 for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
726 if clicked_region_ids.contains(&mouse_region.id()) {
727 if mouse_region
728 .bounds
729 .contains_point(self.window.mouse_position)
730 {
731 valid_regions.push(mouse_region.clone());
732 }
733 }
734 }
735 }
736 }
737
738 MouseEvent::Drag(_) => {
739 for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
740 if self.window.clicked_region_ids.contains(&mouse_region.id()) {
741 valid_regions.push(mouse_region.clone());
742 }
743 }
744 }
745
746 MouseEvent::MoveOut(_) | MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => {
747 for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
748 // NOT contains
749 if !mouse_region
750 .bounds
751 .contains_point(self.window.mouse_position)
752 {
753 valid_regions.push(mouse_region.clone());
754 }
755 }
756 }
757
758 _ => {
759 for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
760 // Contains
761 if mouse_region
762 .bounds
763 .contains_point(self.window.mouse_position)
764 {
765 valid_regions.push(mouse_region.clone());
766 }
767 }
768 }
769 }
770
771 //3. Fire region events
772 let hovered_region_ids = self.window.hovered_region_ids.clone();
773 for valid_region in valid_regions.into_iter() {
774 let mut handled = false;
775 mouse_event.set_region(valid_region.bounds);
776 if let MouseEvent::Hover(e) = &mut mouse_event {
777 e.started = hovered_region_ids.contains(&valid_region.id())
778 }
779 // Handle Down events if the MouseRegion has a Click or Drag handler. This makes the api more intuitive as you would
780 // not expect a MouseRegion to be transparent to Down events if it also has a Click handler.
781 // This behavior can be overridden by adding a Down handler
782 if let MouseEvent::Down(e) = &mouse_event {
783 let has_click = valid_region
784 .handlers
785 .contains(MouseEvent::click_disc(), Some(e.button));
786 let has_drag = valid_region
787 .handlers
788 .contains(MouseEvent::drag_disc(), Some(e.button));
789 let has_down = valid_region
790 .handlers
791 .contains(MouseEvent::down_disc(), Some(e.button));
792 if !has_down && (has_click || has_drag) {
793 handled = true;
794 }
795 }
796
797 // `event_consumed` should only be true if there are any handlers for this event.
798 let mut event_consumed = handled;
799 if let Some(callbacks) = valid_region.handlers.get(&mouse_event.handler_key()) {
800 for callback in callbacks {
801 handled = true;
802 let view_id = valid_region.id().view_id();
803 self.update_any_view(view_id, |view, cx| {
804 handled = callback(mouse_event.clone(), view.as_any_mut(), cx, view_id);
805 });
806 event_consumed |= handled;
807 any_event_handled |= handled;
808 }
809 }
810
811 any_event_handled |= handled;
812
813 // For bubbling events, if the event was handled, don't continue dispatching.
814 // This only makes sense for local events which return false from is_capturable.
815 if event_consumed && mouse_event.is_capturable() {
816 break;
817 }
818 }
819 }
820
821 for view_id in notified_views {
822 self.notify_view(window_id, view_id);
823 }
824
825 any_event_handled
826 }
827
828 pub fn dispatch_key_down(&mut self, event: &KeyDownEvent) -> bool {
829 let window_id = self.window_id;
830 if let Some(focused_view_id) = self.window.focused_view_id {
831 for view_id in self.ancestors(focused_view_id).collect::<Vec<_>>() {
832 if let Some(mut view) = self.views.remove(&(window_id, view_id)) {
833 let handled = view.key_down(event, self, view_id);
834 self.views.insert((window_id, view_id), view);
835 if handled {
836 return true;
837 }
838 } else {
839 log::error!("view {} does not exist", view_id)
840 }
841 }
842 }
843
844 false
845 }
846
847 pub fn dispatch_key_up(&mut self, event: &KeyUpEvent) -> bool {
848 let window_id = self.window_id;
849 if let Some(focused_view_id) = self.window.focused_view_id {
850 for view_id in self.ancestors(focused_view_id).collect::<Vec<_>>() {
851 if let Some(mut view) = self.views.remove(&(window_id, view_id)) {
852 let handled = view.key_up(event, self, view_id);
853 self.views.insert((window_id, view_id), view);
854 if handled {
855 return true;
856 }
857 } else {
858 log::error!("view {} does not exist", view_id)
859 }
860 }
861 }
862
863 false
864 }
865
866 pub fn dispatch_modifiers_changed(&mut self, event: &ModifiersChangedEvent) -> bool {
867 let window_id = self.window_id;
868 if let Some(focused_view_id) = self.window.focused_view_id {
869 for view_id in self.ancestors(focused_view_id).collect::<Vec<_>>() {
870 if let Some(mut view) = self.views.remove(&(window_id, view_id)) {
871 let handled = view.modifiers_changed(event, self, view_id);
872 self.views.insert((window_id, view_id), view);
873 if handled {
874 return true;
875 }
876 } else {
877 log::error!("view {} does not exist", view_id)
878 }
879 }
880 }
881
882 false
883 }
884
885 pub fn invalidate(&mut self, invalidation: &mut WindowInvalidation, appearance: Appearance) {
886 self.start_frame();
887 self.window.appearance = appearance;
888 for view_id in &invalidation.removed {
889 invalidation.updated.remove(view_id);
890 self.window.rendered_views.remove(view_id);
891 }
892 for view_id in &invalidation.updated {
893 let titlebar_height = self.window.titlebar_height;
894 let hovered_region_ids = self.window.hovered_region_ids.clone();
895 let clicked_region_ids = self
896 .window
897 .clicked_button
898 .map(|button| (self.window.clicked_region_ids.clone(), button));
899
900 let element = self
901 .render_view(RenderParams {
902 view_id: *view_id,
903 titlebar_height,
904 hovered_region_ids,
905 clicked_region_ids,
906 refreshing: false,
907 appearance,
908 })
909 .unwrap();
910 self.window.rendered_views.insert(*view_id, element);
911 }
912 }
913
914 pub fn render_view(&mut self, params: RenderParams) -> Result<Box<dyn AnyRootElement>> {
915 let window_id = self.window_id;
916 let view_id = params.view_id;
917 let mut view = self
918 .views
919 .remove(&(window_id, view_id))
920 .ok_or_else(|| anyhow!("view not found"))?;
921 let element = view.render(self, view_id);
922 self.views.insert((window_id, view_id), view);
923 Ok(element)
924 }
925
926 pub fn build_scene(&mut self) -> Result<Scene> {
927 let window_size = self.window.platform_window.content_size();
928 let scale_factor = self.window.platform_window.scale_factor();
929
930 let root_view_id = self.window.root_view().id();
931 let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap();
932 rendered_root.layout(SizeConstraint::strict(window_size), self)?;
933
934 let mut scene_builder = SceneBuilder::new(scale_factor);
935 rendered_root.paint(
936 &mut scene_builder,
937 Vector2F::zero(),
938 RectF::from_points(Vector2F::zero(), window_size),
939 self,
940 )?;
941 self.window
942 .rendered_views
943 .insert(root_view_id, rendered_root);
944
945 self.window.text_layout_cache.finish_frame();
946 let scene = scene_builder.build();
947 self.window.cursor_regions = scene.cursor_regions();
948 self.window.mouse_regions = scene.mouse_regions();
949
950 if self.window_is_active() {
951 if let Some(event) = self.window.last_mouse_moved_event.clone() {
952 self.dispatch_event(event, true);
953 }
954 }
955
956 Ok(scene)
957 }
958
959 pub fn rect_for_text_range(&self, range_utf16: Range<usize>) -> Option<RectF> {
960 let root_view_id = self.window.root_view().id();
961 self.window
962 .rendered_views
963 .get(&root_view_id)?
964 .rect_for_text_range(range_utf16, self)
965 .log_err()
966 .flatten()
967 }
968
969 pub fn debug_elements(&self) -> Option<json::Value> {
970 let view = self.window.root_view();
971 Some(json!({
972 "root_view": view.debug_json(self),
973 "root_element": self.window.rendered_views.get(&view.id())
974 .and_then(|root_element| {
975 root_element.debug(self).log_err()
976 })
977 }))
978 }
979
980 pub fn set_window_title(&mut self, title: &str) {
981 self.window.platform_window.set_title(title);
982 }
983
984 pub fn set_window_edited(&mut self, edited: bool) {
985 self.window.platform_window.set_edited(edited);
986 }
987
988 pub fn is_topmost_window_for_position(&self, position: Vector2F) -> bool {
989 self.window
990 .platform_window
991 .is_topmost_for_position(position)
992 }
993
994 pub fn activate_window(&self) {
995 self.window.platform_window.activate();
996 }
997
998 pub fn window_is_active(&self) -> bool {
999 self.window.is_active
1000 }
1001
1002 pub fn window_is_fullscreen(&self) -> bool {
1003 self.window.is_fullscreen
1004 }
1005
1006 pub(crate) fn handle_dispatch_action_from_effect(
1007 &mut self,
1008 view_id: Option<usize>,
1009 action: &dyn Action,
1010 ) -> bool {
1011 if let Some(view_id) = view_id {
1012 self.halt_action_dispatch = false;
1013 self.visit_dispatch_path(view_id, |view_id, capture_phase, cx| {
1014 cx.update_any_view(view_id, |view, cx| {
1015 let type_id = view.as_any().type_id();
1016 if let Some((name, mut handlers)) = cx
1017 .actions_mut(capture_phase)
1018 .get_mut(&type_id)
1019 .and_then(|h| h.remove_entry(&action.id()))
1020 {
1021 for handler in handlers.iter_mut().rev() {
1022 cx.halt_action_dispatch = true;
1023 handler(view, action, cx, view_id);
1024 if cx.halt_action_dispatch {
1025 break;
1026 }
1027 }
1028 cx.actions_mut(capture_phase)
1029 .get_mut(&type_id)
1030 .unwrap()
1031 .insert(name, handlers);
1032 }
1033 });
1034
1035 !cx.halt_action_dispatch
1036 });
1037 }
1038
1039 if !self.halt_action_dispatch {
1040 self.halt_action_dispatch = self.dispatch_global_action_any(action);
1041 }
1042
1043 self.pending_effects
1044 .push_back(Effect::ActionDispatchNotification {
1045 action_id: action.id(),
1046 });
1047 self.halt_action_dispatch
1048 }
1049
1050 /// Returns an iterator over all of the view ids from the passed view up to the root of the window
1051 /// Includes the passed view itself
1052 pub(crate) fn ancestors(&self, mut view_id: usize) -> impl Iterator<Item = usize> + '_ {
1053 std::iter::once(view_id)
1054 .into_iter()
1055 .chain(std::iter::from_fn(move || {
1056 if let Some(ParentId::View(parent_id)) =
1057 self.parents.get(&(self.window_id, view_id))
1058 {
1059 view_id = *parent_id;
1060 Some(view_id)
1061 } else {
1062 None
1063 }
1064 }))
1065 }
1066
1067 /// Returns the id of the parent of the given view, or none if the given
1068 /// view is the root.
1069 pub(crate) fn parent(&self, view_id: usize) -> Option<usize> {
1070 if let Some(ParentId::View(view_id)) = self.parents.get(&(self.window_id, view_id)) {
1071 Some(*view_id)
1072 } else {
1073 None
1074 }
1075 }
1076
1077 // Traverses the parent tree. Walks down the tree toward the passed
1078 // view calling visit with true. Then walks back up the tree calling visit with false.
1079 // If `visit` returns false this function will immediately return.
1080 fn visit_dispatch_path(
1081 &mut self,
1082 view_id: usize,
1083 mut visit: impl FnMut(usize, bool, &mut WindowContext) -> bool,
1084 ) {
1085 // List of view ids from the leaf to the root of the window
1086 let path = self.ancestors(view_id).collect::<Vec<_>>();
1087
1088 // Walk down from the root to the leaf calling visit with capture_phase = true
1089 for view_id in path.iter().rev() {
1090 if !visit(*view_id, true, self) {
1091 return;
1092 }
1093 }
1094
1095 // Walk up from the leaf to the root calling visit with capture_phase = false
1096 for view_id in path.iter() {
1097 if !visit(*view_id, false, self) {
1098 return;
1099 }
1100 }
1101 }
1102
1103 pub fn focused_view_id(&self) -> Option<usize> {
1104 self.window.focused_view_id
1105 }
1106
1107 pub fn is_child_focused(&self, view: &AnyViewHandle) -> bool {
1108 if let Some(focused_view_id) = self.focused_view_id() {
1109 self.ancestors(focused_view_id)
1110 .skip(1) // Skip self id
1111 .any(|parent| parent == view.view_id)
1112 } else {
1113 false
1114 }
1115 }
1116
1117 pub fn window_bounds(&self) -> WindowBounds {
1118 self.window.platform_window.bounds()
1119 }
1120
1121 pub fn window_appearance(&self) -> Appearance {
1122 self.window.appearance
1123 }
1124
1125 pub fn window_display_uuid(&self) -> Option<Uuid> {
1126 self.window.platform_window.screen().display_uuid()
1127 }
1128
1129 pub fn show_character_palette(&self) {
1130 self.window.platform_window.show_character_palette();
1131 }
1132
1133 pub fn minimize_window(&self) {
1134 self.window.platform_window.minimize();
1135 }
1136
1137 pub fn zoom_window(&self) {
1138 self.window.platform_window.zoom();
1139 }
1140
1141 pub fn toggle_full_screen(&self) {
1142 self.window.platform_window.toggle_full_screen();
1143 }
1144
1145 pub fn prompt(
1146 &self,
1147 level: PromptLevel,
1148 msg: &str,
1149 answers: &[&str],
1150 ) -> oneshot::Receiver<usize> {
1151 self.window.platform_window.prompt(level, msg, answers)
1152 }
1153
1154 pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
1155 where
1156 V: View,
1157 F: FnOnce(&mut ViewContext<V>) -> V,
1158 {
1159 let root_view = self
1160 .build_and_insert_view(ParentId::Root, |cx| Some(build_root_view(cx)))
1161 .unwrap();
1162 self.window.root_view = Some(root_view.clone().into_any());
1163 self.window.focused_view_id = Some(root_view.id());
1164 root_view
1165 }
1166
1167 pub(crate) fn build_and_insert_view<T, F>(
1168 &mut self,
1169 parent_id: ParentId,
1170 build_view: F,
1171 ) -> Option<ViewHandle<T>>
1172 where
1173 T: View,
1174 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
1175 {
1176 let window_id = self.window_id;
1177 let view_id = post_inc(&mut self.next_entity_id);
1178 // Make sure we can tell child views about their parentu
1179 self.parents.insert((window_id, view_id), parent_id);
1180 let mut cx = ViewContext::mutable(self, view_id);
1181 let handle = if let Some(view) = build_view(&mut cx) {
1182 self.views.insert((window_id, view_id), Box::new(view));
1183 self.window
1184 .invalidation
1185 .get_or_insert_with(Default::default)
1186 .updated
1187 .insert(view_id);
1188 Some(ViewHandle::new(window_id, view_id, &self.ref_counts))
1189 } else {
1190 self.parents.remove(&(window_id, view_id));
1191 None
1192 };
1193 handle
1194 }
1195}
1196
1197pub struct RenderParams {
1198 pub view_id: usize,
1199 pub titlebar_height: f32,
1200 pub hovered_region_ids: HashSet<MouseRegionId>,
1201 pub clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
1202 pub refreshing: bool,
1203 pub appearance: Appearance,
1204}
1205
1206#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
1207pub enum Axis {
1208 #[default]
1209 Horizontal,
1210 Vertical,
1211}
1212
1213impl Axis {
1214 pub fn invert(self) -> Self {
1215 match self {
1216 Self::Horizontal => Self::Vertical,
1217 Self::Vertical => Self::Horizontal,
1218 }
1219 }
1220
1221 pub fn component(&self, point: Vector2F) -> f32 {
1222 match self {
1223 Self::Horizontal => point.x(),
1224 Self::Vertical => point.y(),
1225 }
1226 }
1227}
1228
1229impl ToJson for Axis {
1230 fn to_json(&self) -> serde_json::Value {
1231 match self {
1232 Axis::Horizontal => json!("horizontal"),
1233 Axis::Vertical => json!("vertical"),
1234 }
1235 }
1236}
1237
1238impl StaticColumnCount for Axis {}
1239impl Bind for Axis {
1240 fn bind(&self, statement: &Statement, start_index: i32) -> anyhow::Result<i32> {
1241 match self {
1242 Axis::Horizontal => "Horizontal",
1243 Axis::Vertical => "Vertical",
1244 }
1245 .bind(statement, start_index)
1246 }
1247}
1248
1249impl Column for Axis {
1250 fn column(statement: &mut Statement, start_index: i32) -> anyhow::Result<(Self, i32)> {
1251 String::column(statement, start_index).and_then(|(axis_text, next_index)| {
1252 Ok((
1253 match axis_text.as_str() {
1254 "Horizontal" => Axis::Horizontal,
1255 "Vertical" => Axis::Vertical,
1256 _ => bail!("Stored serialized item kind is incorrect"),
1257 },
1258 next_index,
1259 ))
1260 })
1261 }
1262}
1263
1264pub trait Vector2FExt {
1265 fn along(self, axis: Axis) -> f32;
1266}
1267
1268impl Vector2FExt for Vector2F {
1269 fn along(self, axis: Axis) -> f32 {
1270 match axis {
1271 Axis::Horizontal => self.x(),
1272 Axis::Vertical => self.y(),
1273 }
1274 }
1275}
1276
1277#[derive(Copy, Clone, Debug)]
1278pub struct SizeConstraint {
1279 pub min: Vector2F,
1280 pub max: Vector2F,
1281}
1282
1283impl SizeConstraint {
1284 pub fn new(min: Vector2F, max: Vector2F) -> Self {
1285 Self { min, max }
1286 }
1287
1288 pub fn strict(size: Vector2F) -> Self {
1289 Self {
1290 min: size,
1291 max: size,
1292 }
1293 }
1294
1295 pub fn strict_along(axis: Axis, max: f32) -> Self {
1296 match axis {
1297 Axis::Horizontal => Self {
1298 min: vec2f(max, 0.0),
1299 max: vec2f(max, f32::INFINITY),
1300 },
1301 Axis::Vertical => Self {
1302 min: vec2f(0.0, max),
1303 max: vec2f(f32::INFINITY, max),
1304 },
1305 }
1306 }
1307
1308 pub fn max_along(&self, axis: Axis) -> f32 {
1309 match axis {
1310 Axis::Horizontal => self.max.x(),
1311 Axis::Vertical => self.max.y(),
1312 }
1313 }
1314
1315 pub fn min_along(&self, axis: Axis) -> f32 {
1316 match axis {
1317 Axis::Horizontal => self.min.x(),
1318 Axis::Vertical => self.min.y(),
1319 }
1320 }
1321
1322 pub fn constrain(&self, size: Vector2F) -> Vector2F {
1323 vec2f(
1324 size.x().min(self.max.x()).max(self.min.x()),
1325 size.y().min(self.max.y()).max(self.min.y()),
1326 )
1327 }
1328}
1329
1330impl Default for SizeConstraint {
1331 fn default() -> Self {
1332 SizeConstraint {
1333 min: Vector2F::zero(),
1334 max: Vector2F::splat(f32::INFINITY),
1335 }
1336 }
1337}
1338
1339impl ToJson for SizeConstraint {
1340 fn to_json(&self) -> serde_json::Value {
1341 json!({
1342 "min": self.min.to_json(),
1343 "max": self.max.to_json(),
1344 })
1345 }
1346}
1347
1348pub struct ChildView {
1349 view_id: usize,
1350 view_name: &'static str,
1351}
1352
1353impl ChildView {
1354 pub fn new(view: &AnyViewHandle, cx: &AppContext) -> Self {
1355 let view_name = cx.view_ui_name(view.window_id(), view.id()).unwrap();
1356 Self {
1357 view_id: view.id(),
1358 view_name,
1359 }
1360 }
1361}
1362
1363impl<V: View> Element<V> for ChildView {
1364 type LayoutState = ();
1365 type PaintState = ();
1366
1367 fn layout(
1368 &mut self,
1369 constraint: SizeConstraint,
1370 _: &mut V,
1371 cx: &mut ViewContext<V>,
1372 ) -> (Vector2F, Self::LayoutState) {
1373 if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) {
1374 let size = rendered_view
1375 .layout(constraint, cx)
1376 .log_err()
1377 .unwrap_or(Vector2F::zero());
1378 cx.window.rendered_views.insert(self.view_id, rendered_view);
1379 (size, ())
1380 } else {
1381 log::error!(
1382 "layout called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
1383 self.view_id,
1384 self.view_name
1385 );
1386 (Vector2F::zero(), ())
1387 }
1388 }
1389
1390 fn paint(
1391 &mut self,
1392 scene: &mut SceneBuilder,
1393 bounds: RectF,
1394 visible_bounds: RectF,
1395 _: &mut Self::LayoutState,
1396 _: &mut V,
1397 cx: &mut ViewContext<V>,
1398 ) {
1399 if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) {
1400 rendered_view
1401 .paint(scene, bounds.origin(), visible_bounds, cx)
1402 .log_err();
1403 cx.window.rendered_views.insert(self.view_id, rendered_view);
1404 } else {
1405 log::error!(
1406 "paint called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
1407 self.view_id,
1408 self.view_name
1409 );
1410 }
1411 }
1412
1413 fn rect_for_text_range(
1414 &self,
1415 range_utf16: Range<usize>,
1416 _: RectF,
1417 _: RectF,
1418 _: &Self::LayoutState,
1419 _: &Self::PaintState,
1420 _: &V,
1421 cx: &ViewContext<V>,
1422 ) -> Option<RectF> {
1423 if let Some(rendered_view) = cx.window.rendered_views.get(&self.view_id) {
1424 rendered_view
1425 .rect_for_text_range(range_utf16, &cx.window_context)
1426 .log_err()
1427 .flatten()
1428 } else {
1429 log::error!(
1430 "rect_for_text_range called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
1431 self.view_id,
1432 self.view_name
1433 );
1434 None
1435 }
1436 }
1437
1438 fn debug(
1439 &self,
1440 bounds: RectF,
1441 _: &Self::LayoutState,
1442 _: &Self::PaintState,
1443 _: &V,
1444 cx: &ViewContext<V>,
1445 ) -> serde_json::Value {
1446 json!({
1447 "type": "ChildView",
1448 "view_id": self.view_id,
1449 "bounds": bounds.to_json(),
1450 "view": if let Some(view) = cx.views.get(&(cx.window_id, self.view_id)) {
1451 view.debug_json(cx)
1452 } else {
1453 json!(null)
1454 },
1455 "child": if let Some(element) = cx.window.rendered_views.get(&self.view_id) {
1456 element.debug(&cx.window_context).log_err().unwrap_or_else(|| json!(null))
1457 } else {
1458 json!(null)
1459 }
1460 })
1461 }
1462}