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