Compare commits
1 Commits
fix_devcon
...
blink-mana
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2acd48f439 |
@@ -1,8 +1,8 @@
|
||||
use gpui::Context;
|
||||
use gpui::{Context, FocusHandle};
|
||||
use settings::SettingsStore;
|
||||
use smol::Timer;
|
||||
use std::time::Duration;
|
||||
use ui::App;
|
||||
use ui::{App, Window};
|
||||
|
||||
pub struct BlinkManager {
|
||||
blink_interval: Duration,
|
||||
@@ -11,21 +11,34 @@ pub struct BlinkManager {
|
||||
blinking_paused: bool,
|
||||
/// Whether the cursor should be visibly rendered or not.
|
||||
visible: bool,
|
||||
/// Whether the blinking currently enabled.
|
||||
enabled: bool,
|
||||
/// The focus handle to use to determine if the cursor should be blinking.
|
||||
focus_handle: FocusHandle,
|
||||
/// Whether the blinking is enabled in the settings.
|
||||
blink_enabled_in_settings: fn(&App) -> bool,
|
||||
is_enabled: Box<dyn Fn(&App) -> bool>,
|
||||
}
|
||||
|
||||
impl BlinkManager {
|
||||
pub fn new(
|
||||
blink_interval: Duration,
|
||||
blink_enabled_in_settings: fn(&App) -> bool,
|
||||
focus_handle: FocusHandle,
|
||||
is_enabled: impl Fn(&App) -> bool + 'static,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
// Make sure we blink the cursors if the setting is re-enabled
|
||||
cx.observe_global::<SettingsStore>(move |this, cx| {
|
||||
this.blink_cursors(this.blink_epoch, cx)
|
||||
cx.observe_global_in::<SettingsStore>(window, move |this, window, cx| {
|
||||
this.refresh(window, cx);
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.on_focus(&focus_handle, window, move |this, window, cx| {
|
||||
this.visible = false;
|
||||
this.refresh(window, cx);
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.on_blur(&focus_handle, window, move |this, _window, _cx| {
|
||||
this.visible = false;
|
||||
})
|
||||
.detach();
|
||||
|
||||
@@ -34,48 +47,64 @@ impl BlinkManager {
|
||||
blink_epoch: 0,
|
||||
blinking_paused: false,
|
||||
visible: true,
|
||||
enabled: false,
|
||||
blink_enabled_in_settings,
|
||||
focus_handle,
|
||||
is_enabled: Box::new(is_enabled),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.blink_cursors(self.blink_epoch, window, cx)
|
||||
}
|
||||
|
||||
fn next_blink_epoch(&mut self) -> usize {
|
||||
self.blink_epoch += 1;
|
||||
self.blink_epoch
|
||||
}
|
||||
|
||||
pub fn pause_blinking(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn pause_blinking(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.show_cursor(cx);
|
||||
|
||||
let epoch = self.next_blink_epoch();
|
||||
let interval = self.blink_interval;
|
||||
cx.spawn(async move |this, cx| {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
Timer::after(interval).await;
|
||||
this.update(cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.resume_cursor_blinking(epoch, window, cx)
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut Context<Self>) {
|
||||
fn resume_cursor_blinking(
|
||||
&mut self,
|
||||
epoch: usize,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if epoch == self.blink_epoch {
|
||||
self.blinking_paused = false;
|
||||
self.blink_cursors(epoch, cx);
|
||||
self.blink_cursors(epoch, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn blink_cursors(&mut self, epoch: usize, cx: &mut Context<Self>) {
|
||||
if (self.blink_enabled_in_settings)(cx) {
|
||||
if epoch == self.blink_epoch && self.enabled && !self.blinking_paused {
|
||||
fn blink_cursors(&mut self, epoch: usize, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if (self.is_enabled)(cx) {
|
||||
if epoch == self.blink_epoch
|
||||
&& self.focus_handle.is_focused(window)
|
||||
&& !self.blinking_paused
|
||||
{
|
||||
self.visible = !self.visible;
|
||||
cx.notify();
|
||||
|
||||
let epoch = self.next_blink_epoch();
|
||||
let interval = self.blink_interval;
|
||||
cx.spawn(async move |this, cx| {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
Timer::after(interval).await;
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| this.blink_cursors(epoch, cx))
|
||||
.ok();
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.blink_cursors(epoch, window, cx)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
@@ -92,25 +121,6 @@ impl BlinkManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable the blinking of the cursor.
|
||||
pub fn enable(&mut self, cx: &mut Context<Self>) {
|
||||
if self.enabled {
|
||||
return;
|
||||
}
|
||||
|
||||
self.enabled = true;
|
||||
// Set cursors as invisible and start blinking: this causes cursors
|
||||
// to be visible during the next render.
|
||||
self.visible = false;
|
||||
self.blink_cursors(self.blink_epoch, cx);
|
||||
}
|
||||
|
||||
/// Disable the blinking of the cursor.
|
||||
pub fn disable(&mut self, _cx: &mut Context<Self>) {
|
||||
self.visible = false;
|
||||
self.enabled = false;
|
||||
}
|
||||
|
||||
pub fn visible(&self) -> bool {
|
||||
self.visible
|
||||
}
|
||||
|
||||
@@ -1886,16 +1886,26 @@ impl Editor {
|
||||
|
||||
let selections = SelectionsCollection::new();
|
||||
|
||||
let focus_handle = cx.focus_handle();
|
||||
|
||||
let blink_manager = cx.new(|cx| {
|
||||
let mut blink_manager = BlinkManager::new(
|
||||
CURSOR_BLINK_INTERVAL,
|
||||
|cx| EditorSettings::get_global(cx).cursor_blink,
|
||||
cx,
|
||||
);
|
||||
if is_minimap {
|
||||
blink_manager.disable(cx);
|
||||
BlinkManager::new(
|
||||
CURSOR_BLINK_INTERVAL,
|
||||
focus_handle.clone(),
|
||||
|_cx| false,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
BlinkManager::new(
|
||||
CURSOR_BLINK_INTERVAL,
|
||||
focus_handle.clone(),
|
||||
|cx| EditorSettings::get_global(cx).cursor_blink,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
blink_manager
|
||||
});
|
||||
|
||||
let soft_wrap_mode_override =
|
||||
@@ -2095,7 +2105,6 @@ impl Editor {
|
||||
|
||||
let inlay_hint_settings =
|
||||
inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
|
||||
let focus_handle = cx.focus_handle();
|
||||
if !is_minimap {
|
||||
cx.on_focus(&focus_handle, window, Self::handle_focus)
|
||||
.detach();
|
||||
@@ -2292,15 +2301,7 @@ impl Editor {
|
||||
cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
|
||||
observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
|
||||
cx.observe_window_activation(window, |editor, window, cx| {
|
||||
let active = window.is_window_active();
|
||||
editor.blink_manager.update(cx, |blink_manager, cx| {
|
||||
if active {
|
||||
blink_manager.enable(cx);
|
||||
} else {
|
||||
blink_manager.disable(cx);
|
||||
}
|
||||
});
|
||||
if active {
|
||||
if window.is_window_active() {
|
||||
editor.show_mouse_cursor(cx);
|
||||
}
|
||||
}),
|
||||
@@ -3321,7 +3322,9 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
self.blink_manager.update(cx, BlinkManager::pause_blinking);
|
||||
self.blink_manager.update(cx, |blink_manager, cx| {
|
||||
blink_manager.pause_blinking(window, cx)
|
||||
});
|
||||
cx.emit(EditorEvent::SelectionsChanged { local });
|
||||
|
||||
let selections = &self.selections.disjoint_anchors_arc();
|
||||
@@ -22161,7 +22164,6 @@ impl Editor {
|
||||
blame.update(cx, GitBlame::focus)
|
||||
}
|
||||
|
||||
self.blink_manager.update(cx, BlinkManager::enable);
|
||||
self.show_cursor_names(window, cx);
|
||||
self.buffer.update(cx, |buffer, cx| {
|
||||
buffer.finalize_last_transaction(cx);
|
||||
@@ -22209,7 +22211,6 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn handle_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.blink_manager.update(cx, BlinkManager::disable);
|
||||
self.buffer
|
||||
.update(cx, |buffer, cx| buffer.remove_active_selections(cx));
|
||||
|
||||
|
||||
@@ -234,17 +234,25 @@ impl TerminalView {
|
||||
|
||||
let scroll_handle = TerminalScrollHandle::new(terminal.read(cx));
|
||||
|
||||
let blink_manager = cx.new(|cx| {
|
||||
BlinkManager::new(
|
||||
CURSOR_BLINK_INTERVAL,
|
||||
|cx| {
|
||||
!matches!(
|
||||
TerminalSettings::get_global(cx).blinking,
|
||||
TerminalBlink::Off
|
||||
)
|
||||
},
|
||||
cx,
|
||||
)
|
||||
let blink_manager = cx.new({
|
||||
let weak_this = cx.weak_entity();
|
||||
let focus_handle = focus_handle.clone();
|
||||
|
||||
move |cx| {
|
||||
BlinkManager::new(
|
||||
CURSOR_BLINK_INTERVAL,
|
||||
focus_handle,
|
||||
move |cx| match TerminalSettings::get_global(cx).blinking {
|
||||
TerminalBlink::Off => false,
|
||||
TerminalBlink::On => true,
|
||||
TerminalBlink::TerminalControlled => weak_this
|
||||
.read_with(cx, |this, _cx| this.blinking_terminal_enabled)
|
||||
.unwrap_or(false),
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
let _subscriptions = vec![
|
||||
@@ -434,11 +442,6 @@ impl TerminalView {
|
||||
let breadcrumb_visibility_changed = self.show_breadcrumbs != settings.toolbar.breadcrumbs;
|
||||
self.show_breadcrumbs = settings.toolbar.breadcrumbs;
|
||||
|
||||
let should_blink = match settings.blinking {
|
||||
TerminalBlink::Off => false,
|
||||
TerminalBlink::On => true,
|
||||
TerminalBlink::TerminalControlled => self.blinking_terminal_enabled,
|
||||
};
|
||||
let new_cursor_shape = settings.cursor_shape;
|
||||
let old_cursor_shape = self.cursor_shape;
|
||||
if old_cursor_shape != new_cursor_shape {
|
||||
@@ -448,15 +451,6 @@ impl TerminalView {
|
||||
});
|
||||
}
|
||||
|
||||
self.blink_manager.update(
|
||||
cx,
|
||||
if should_blink {
|
||||
BlinkManager::enable
|
||||
} else {
|
||||
BlinkManager::disable
|
||||
},
|
||||
);
|
||||
|
||||
if breadcrumb_visibility_changed {
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
@@ -656,8 +650,10 @@ impl TerminalView {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pause_cursor_blinking(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.blink_manager.update(cx, BlinkManager::pause_blinking);
|
||||
pub fn pause_cursor_blinking(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.blink_manager.update(cx, |blink_manager, cx| {
|
||||
blink_manager.pause_blinking(window, cx)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn terminal(&self) -> &Entity<Terminal> {
|
||||
@@ -873,21 +869,9 @@ fn subscribe_for_terminal_events(
|
||||
|
||||
Event::BlinkChanged(blinking) => {
|
||||
terminal_view.blinking_terminal_enabled = *blinking;
|
||||
|
||||
// If in terminal-controlled mode and focused, update blink manager
|
||||
if matches!(
|
||||
TerminalSettings::get_global(cx).blinking,
|
||||
TerminalBlink::TerminalControlled
|
||||
) && terminal_view.focus_handle.is_focused(window)
|
||||
{
|
||||
terminal_view.blink_manager.update(cx, |manager, cx| {
|
||||
if *blinking {
|
||||
manager.enable(cx);
|
||||
} else {
|
||||
manager.disable(cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
terminal_view
|
||||
.blink_manager
|
||||
.update(cx, |this, cx| this.refresh(window, cx));
|
||||
}
|
||||
|
||||
Event::TitleChanged => {
|
||||
@@ -1013,22 +997,11 @@ impl TerminalView {
|
||||
terminal.focus_in();
|
||||
});
|
||||
|
||||
let should_blink = match TerminalSettings::get_global(cx).blinking {
|
||||
TerminalBlink::Off => false,
|
||||
TerminalBlink::On => true,
|
||||
TerminalBlink::TerminalControlled => self.blinking_terminal_enabled,
|
||||
};
|
||||
|
||||
if should_blink {
|
||||
self.blink_manager.update(cx, BlinkManager::enable);
|
||||
}
|
||||
|
||||
window.invalidate_character_coordinates();
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn focus_out(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.blink_manager.update(cx, BlinkManager::disable);
|
||||
self.terminal.update(cx, |terminal, _| {
|
||||
terminal.focus_out();
|
||||
terminal.set_cursor_shape(CursorShape::Hollow);
|
||||
|
||||
Reference in New Issue
Block a user