Delay focus_in event for window activation till after layout

This commit is contained in:
Antonio Scandurra 2023-05-05 10:47:42 +02:00
parent b9ed327b94
commit 080a1f00a3

View file

@ -1470,6 +1470,7 @@ impl AppContext {
.push_back(Effect::Focus(FocusEffect::View {
window_id,
view_id: Some(view_id),
is_forced: false,
}));
}
@ -1492,7 +1493,7 @@ impl AppContext {
let mut refreshing = false;
let mut updated_windows = HashSet::default();
let mut focus_changes = HashMap::default();
let mut focus_effects = HashMap::<usize, FocusEffect>::default();
loop {
self.remove_dropped_entities();
if let Some(effect) = self.pending_effects.pop_front() {
@ -1567,8 +1568,15 @@ impl AppContext {
self.handle_entity_release_effect(view_id, view.as_any())
}
Effect::Focus(effect) => {
focus_changes.insert(effect.window_id(), effect);
Effect::Focus(mut effect) => {
if focus_effects
.get(&effect.window_id())
.map_or(false, |prev_effect| prev_effect.is_forced())
{
effect.force();
}
focus_effects.insert(effect.window_id(), effect);
}
Effect::FocusObservation {
@ -1609,7 +1617,22 @@ impl AppContext {
Effect::ActivateWindow {
window_id,
is_active,
} => self.handle_window_activation_effect(window_id, is_active),
} => {
if self.handle_window_activation_effect(window_id, is_active)
&& is_active
{
focus_effects
.entry(window_id)
.or_insert_with(|| FocusEffect::View {
window_id,
view_id: self
.read_window(window_id, |cx| cx.focused_view_id())
.flatten(),
is_forced: true,
})
.force();
}
}
Effect::WindowFullscreenObservation {
window_id,
@ -1692,7 +1715,7 @@ impl AppContext {
});
}
for (_, effect) in focus_changes.drain() {
for (_, effect) in focus_effects.drain() {
self.handle_focus_effect(effect);
}
@ -1846,28 +1869,18 @@ impl AppContext {
});
}
fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) {
fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) -> bool {
self.update_window(window_id, |cx| {
if cx.window.is_active == active {
return;
return false;
}
cx.window.is_active = active;
if let Some(focused_id) = cx.window.focused_view_id {
for view_id in cx.ancestors(focused_id).collect::<Vec<_>>() {
cx.update_any_view(view_id, |view, cx| {
if active {
view.focus_in(focused_id, cx, view_id);
} else {
view.focus_out(focused_id, cx, view_id);
}
});
}
}
let mut observations = cx.window_activation_observations.clone();
observations.emit(window_id, |callback| callback(active, cx));
});
true
})
.unwrap_or(false)
}
fn handle_focus_effect(&mut self, effect: FocusEffect) {
@ -1877,41 +1890,37 @@ impl AppContext {
FocusEffect::View { view_id, .. } => view_id,
FocusEffect::ViewParent { view_id, .. } => cx.ancestors(view_id).skip(1).next(),
};
if cx.window.focused_view_id == focused_id {
return;
}
let focus_changed = cx.window.focused_view_id != focused_id;
let blurred_id = cx.window.focused_view_id;
cx.window.focused_view_id = focused_id;
let blurred_parents = blurred_id
.map(|blurred_id| cx.ancestors(blurred_id).collect::<Vec<_>>())
.unwrap_or_default();
let focused_parents = focused_id
.map(|focused_id| cx.ancestors(focused_id).collect::<Vec<_>>())
.unwrap_or_default();
if let Some(blurred_id) = blurred_id {
for view_id in blurred_parents.iter().copied() {
if let Some(mut view) = cx.views.remove(&(window_id, view_id)) {
view.focus_out(blurred_id, cx, view_id);
cx.views.insert((window_id, view_id), view);
if focus_changed {
if let Some(blurred_id) = blurred_id {
for view_id in cx.ancestors(blurred_id).collect::<Vec<_>>() {
if let Some(mut view) = cx.views.remove(&(window_id, view_id)) {
view.focus_out(blurred_id, cx, view_id);
cx.views.insert((window_id, view_id), view);
}
}
}
let mut subscriptions = cx.focus_observations.clone();
subscriptions.emit(blurred_id, |callback| callback(false, cx));
let mut subscriptions = cx.focus_observations.clone();
subscriptions.emit(blurred_id, |callback| callback(false, cx));
}
}
if let Some(focused_id) = focused_id {
for view_id in focused_parents {
if let Some(mut view) = cx.views.remove(&(window_id, view_id)) {
view.focus_in(focused_id, cx, view_id);
cx.views.insert((window_id, view_id), view);
if focus_changed || effect.is_forced() {
if let Some(focused_id) = focused_id {
for view_id in cx.ancestors(focused_id).collect::<Vec<_>>() {
if let Some(mut view) = cx.views.remove(&(window_id, view_id)) {
view.focus_in(focused_id, cx, view_id);
cx.views.insert((window_id, view_id), view);
}
}
}
let mut subscriptions = cx.focus_observations.clone();
subscriptions.emit(focused_id, |callback| callback(true, cx));
let mut subscriptions = cx.focus_observations.clone();
subscriptions.emit(focused_id, |callback| callback(true, cx));
}
}
});
}
@ -1963,7 +1972,11 @@ impl AppContext {
pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
self.pending_effects
.push_back(Effect::Focus(FocusEffect::View { window_id, view_id }));
.push_back(Effect::Focus(FocusEffect::View {
window_id,
view_id,
is_forced: false,
}));
}
fn spawn_internal<F, Fut, T>(&mut self, task_name: Option<&'static str>, f: F) -> Task<T>
@ -2064,10 +2077,12 @@ pub enum FocusEffect {
View {
window_id: usize,
view_id: Option<usize>,
is_forced: bool,
},
ViewParent {
window_id: usize,
view_id: usize,
is_forced: bool,
},
}
@ -2078,6 +2093,20 @@ impl FocusEffect {
FocusEffect::ViewParent { window_id, .. } => *window_id,
}
}
fn is_forced(&self) -> bool {
match self {
FocusEffect::View { is_forced, .. } => *is_forced,
FocusEffect::ViewParent { is_forced, .. } => *is_forced,
}
}
fn force(&mut self) {
match self {
FocusEffect::View { is_forced, .. } => *is_forced = true,
FocusEffect::ViewParent { is_forced, .. } => *is_forced = true,
}
}
}
pub enum Effect {
@ -2866,6 +2895,7 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
.push_back(Effect::Focus(FocusEffect::ViewParent {
window_id,
view_id,
is_forced: false,
}));
}