terminal_view: Reuse editor's blink manager (#43351)
Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Generated
-1
@@ -17135,7 +17135,6 @@ dependencies = [
|
||||
"serde_json",
|
||||
"settings",
|
||||
"shellexpand 2.1.2",
|
||||
"smol",
|
||||
"task",
|
||||
"terminal",
|
||||
"theme",
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
use crate::EditorSettings;
|
||||
use gpui::Context;
|
||||
use settings::Settings;
|
||||
use settings::SettingsStore;
|
||||
use smol::Timer;
|
||||
use std::time::Duration;
|
||||
use ui::App;
|
||||
|
||||
pub struct BlinkManager {
|
||||
blink_interval: Duration,
|
||||
blink_epoch: usize,
|
||||
/// Whether the blinking is paused.
|
||||
blinking_paused: bool,
|
||||
/// Whether the cursor should be visibly rendered or not.
|
||||
visible: bool,
|
||||
/// Whether the blinking currently enabled.
|
||||
enabled: bool,
|
||||
/// Whether the blinking is enabled in the settings.
|
||||
blink_enabled_in_settings: fn(&App) -> bool,
|
||||
}
|
||||
|
||||
impl BlinkManager {
|
||||
pub fn new(blink_interval: Duration, cx: &mut Context<Self>) -> Self {
|
||||
pub fn new(
|
||||
blink_interval: Duration,
|
||||
blink_enabled_in_settings: fn(&App) -> bool,
|
||||
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)
|
||||
@@ -27,6 +35,7 @@ impl BlinkManager {
|
||||
blinking_paused: false,
|
||||
visible: true,
|
||||
enabled: false,
|
||||
blink_enabled_in_settings,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +64,7 @@ impl BlinkManager {
|
||||
}
|
||||
|
||||
fn blink_cursors(&mut self, epoch: usize, cx: &mut Context<Self>) {
|
||||
if EditorSettings::get_global(cx).cursor_blink {
|
||||
if (self.blink_enabled_in_settings)(cx) {
|
||||
if epoch == self.blink_epoch && self.enabled && !self.blinking_paused {
|
||||
self.visible = !self.visible;
|
||||
cx.notify();
|
||||
@@ -83,6 +92,7 @@ impl BlinkManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable the blinking of the cursor.
|
||||
pub fn enable(&mut self, cx: &mut Context<Self>) {
|
||||
if self.enabled {
|
||||
return;
|
||||
@@ -95,6 +105,7 @@ impl BlinkManager {
|
||||
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;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
//!
|
||||
//! If you're looking to improve Vim mode, you should check out Vim crate that wraps Editor and overrides its behavior.
|
||||
pub mod actions;
|
||||
mod blink_manager;
|
||||
pub mod blink_manager;
|
||||
mod bracket_colorization;
|
||||
mod clangd_ext;
|
||||
pub mod code_context_menus;
|
||||
@@ -1888,7 +1888,11 @@ impl Editor {
|
||||
let selections = SelectionsCollection::new();
|
||||
|
||||
let blink_manager = cx.new(|cx| {
|
||||
let mut blink_manager = BlinkManager::new(CURSOR_BLINK_INTERVAL, 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);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
shellexpand.workspace = true
|
||||
smol.workspace = true
|
||||
terminal.workspace = true
|
||||
theme.workspace = true
|
||||
ui.workspace = true
|
||||
|
||||
@@ -7,7 +7,7 @@ mod terminal_slash_command;
|
||||
pub mod terminal_tab_tooltip;
|
||||
|
||||
use assistant_slash_command::SlashCommandRegistry;
|
||||
use editor::{EditorSettings, actions::SelectAll};
|
||||
use editor::{EditorSettings, actions::SelectAll, blink_manager::BlinkManager};
|
||||
use gpui::{
|
||||
Action, AnyElement, App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
KeyContext, KeyDownEvent, Keystroke, MouseButton, MouseDownEvent, Pixels, Render,
|
||||
@@ -51,7 +51,6 @@ use workspace::{
|
||||
|
||||
use serde::Deserialize;
|
||||
use settings::{Settings, SettingsStore, TerminalBlink, WorkingDirectory};
|
||||
use smol::Timer;
|
||||
use zed_actions::assistant::InlineAssist;
|
||||
|
||||
use std::{
|
||||
@@ -126,12 +125,10 @@ pub struct TerminalView {
|
||||
has_bell: bool,
|
||||
context_menu: Option<(Entity<ContextMenu>, gpui::Point<Pixels>, Subscription)>,
|
||||
cursor_shape: CursorShape,
|
||||
blink_state: bool,
|
||||
blink_manager: Entity<BlinkManager>,
|
||||
mode: TerminalMode,
|
||||
blinking_terminal_enabled: bool,
|
||||
cwd_serialized: bool,
|
||||
blinking_paused: bool,
|
||||
blink_epoch: usize,
|
||||
hover: Option<HoverTarget>,
|
||||
hover_tooltip_update: Task<()>,
|
||||
workspace_id: Option<WorkspaceId>,
|
||||
@@ -237,6 +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 _subscriptions = vec![
|
||||
focus_in,
|
||||
focus_out,
|
||||
cx.observe(&blink_manager, |_, _, cx| cx.notify()),
|
||||
cx.observe_global::<SettingsStore>(Self::settings_changed),
|
||||
];
|
||||
Self {
|
||||
terminal,
|
||||
workspace: workspace_handle,
|
||||
@@ -245,10 +261,8 @@ impl TerminalView {
|
||||
focus_handle,
|
||||
context_menu: None,
|
||||
cursor_shape,
|
||||
blink_state: true,
|
||||
blink_manager,
|
||||
blinking_terminal_enabled: false,
|
||||
blinking_paused: false,
|
||||
blink_epoch: 0,
|
||||
hover: None,
|
||||
hover_tooltip_update: Task::ready(()),
|
||||
mode: TerminalMode::Standalone,
|
||||
@@ -259,11 +273,7 @@ impl TerminalView {
|
||||
scroll_handle,
|
||||
cwd_serialized: false,
|
||||
ime_state: None,
|
||||
_subscriptions: vec![
|
||||
focus_in,
|
||||
focus_out,
|
||||
cx.observe_global::<SettingsStore>(Self::settings_changed),
|
||||
],
|
||||
_subscriptions,
|
||||
_terminal_subscriptions: terminal_subscriptions,
|
||||
}
|
||||
}
|
||||
@@ -424,6 +434,11 @@ 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 {
|
||||
@@ -433,6 +448,15 @@ impl TerminalView {
|
||||
});
|
||||
}
|
||||
|
||||
self.blink_manager.update(
|
||||
cx,
|
||||
if should_blink {
|
||||
BlinkManager::enable
|
||||
} else {
|
||||
BlinkManager::disable
|
||||
},
|
||||
);
|
||||
|
||||
if breadcrumb_visibility_changed {
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
@@ -610,9 +634,8 @@ impl TerminalView {
|
||||
}
|
||||
|
||||
pub fn should_show_cursor(&self, focused: bool, cx: &mut Context<Self>) -> bool {
|
||||
//Don't blink the cursor when not focused, blinking is disabled, or paused
|
||||
// Always show cursor when not focused or in special modes
|
||||
if !focused
|
||||
|| self.blinking_paused
|
||||
|| self
|
||||
.terminal
|
||||
.read(cx)
|
||||
@@ -623,45 +646,17 @@ impl TerminalView {
|
||||
return true;
|
||||
}
|
||||
|
||||
// When focused, check blinking settings and blink manager state
|
||||
match TerminalSettings::get_global(cx).blinking {
|
||||
//If the user requested to never blink, don't blink it.
|
||||
TerminalBlink::Off => true,
|
||||
//If the terminal is controlling it, check terminal mode
|
||||
TerminalBlink::TerminalControlled => {
|
||||
!self.blinking_terminal_enabled || self.blink_state
|
||||
TerminalBlink::On | TerminalBlink::TerminalControlled => {
|
||||
self.blink_manager.read(cx).visible()
|
||||
}
|
||||
TerminalBlink::On => self.blink_state,
|
||||
}
|
||||
}
|
||||
|
||||
fn blink_cursors(&mut self, epoch: usize, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if epoch == self.blink_epoch && !self.blinking_paused {
|
||||
self.blink_state = !self.blink_state;
|
||||
cx.notify();
|
||||
|
||||
let epoch = self.next_blink_epoch();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
Timer::after(CURSOR_BLINK_INTERVAL).await;
|
||||
this.update_in(cx, |this, window, cx| this.blink_cursors(epoch, window, cx))
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pause_cursor_blinking(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.blink_state = true;
|
||||
cx.notify();
|
||||
|
||||
let epoch = self.next_blink_epoch();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
Timer::after(CURSOR_BLINK_INTERVAL).await;
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.resume_cursor_blinking(epoch, window, cx)
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
pub fn pause_cursor_blinking(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.blink_manager.update(cx, BlinkManager::pause_blinking);
|
||||
}
|
||||
|
||||
pub fn terminal(&self) -> &Entity<Terminal> {
|
||||
@@ -685,23 +680,6 @@ impl TerminalView {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn next_blink_epoch(&mut self) -> usize {
|
||||
self.blink_epoch += 1;
|
||||
self.blink_epoch
|
||||
}
|
||||
|
||||
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, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
///Attempt to paste the clipboard into the terminal
|
||||
fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.terminal.update(cx, |term, _| term.copy(None));
|
||||
@@ -893,11 +871,21 @@ 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.blinking_terminal_enabled = *blinking;
|
||||
) && terminal_view.focus_handle.is_focused(window)
|
||||
{
|
||||
terminal_view.blink_manager.update(cx, |manager, cx| {
|
||||
if *blinking {
|
||||
manager.enable(cx);
|
||||
} else {
|
||||
manager.disable(cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1023,12 +1011,23 @@ impl TerminalView {
|
||||
terminal.set_cursor_shape(self.cursor_shape);
|
||||
terminal.focus_in();
|
||||
});
|
||||
self.blink_cursors(self.blink_epoch, window, cx);
|
||||
|
||||
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, _: &mut Window, cx: &mut Context<Self>) {
|
||||
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