[terminal] IJPL-188621 Update font settings on the backend after resetting

Extract the existing approach of modifying the settings to the utils.
Otherwise, the value on the backend may be out of sync and then replace the updated value.

GitOrigin-RevId: 435ec38adc52935ac994b9a645d62e92998b31e2
This commit is contained in:
Konstantin Hudyakov
2025-06-13 15:07:37 +03:00
committed by intellij-monorepo-bot
parent aa82ce5f70
commit 1bd253cf76
3 changed files with 44 additions and 27 deletions

View File

@@ -15,7 +15,9 @@ import com.intellij.openapi.editor.colors.impl.AppFontOptions
import com.intellij.openapi.editor.colors.impl.FontPreferencesImpl
import com.intellij.openapi.editor.impl.FontFamilyService
import com.intellij.openapi.util.Disposer
import kotlinx.coroutines.CoroutineScope
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.terminal.block.ui.updateFrontendSettingsAndSync
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
import kotlin.math.pow
@@ -26,7 +28,7 @@ import kotlin.math.roundToInt
storages = [Storage("terminal-font.xml")],
)
@ApiStatus.Internal
class TerminalFontSettingsService : AppFontOptions<TerminalFontSettingsState>() {
class TerminalFontSettingsService(private val coroutineScope: CoroutineScope) : AppFontOptions<TerminalFontSettingsState>() {
companion object {
@JvmStatic fun getInstance(): TerminalFontSettingsService = service<TerminalFontSettingsService>()
@@ -121,15 +123,17 @@ class TerminalFontSettingsService : AppFontOptions<TerminalFontSettingsState>()
*/
fun resetNonMonospacedFontsOnce(storedState: TerminalFontSettingsState): Boolean {
return RunOnceUtil.runOnceForApp("TerminalFontSettingsService.fixStoredNonMonospacedFonts") {
val adjustedState = if (!FontFamilyService.isMonospaced(storedState.FONT_FAMILY)) {
val newState = TerminalFontSettingsState(getConsoleFontPreferences())
newState.FONT_SIZE_2D = storedState.FONT_SIZE_2D
newState.LINE_SPACING = storedState.LINE_SPACING
newState
}
else storedState
updateFrontendSettingsAndSync(coroutineScope) {
val adjustedState = if (!FontFamilyService.isMonospaced(storedState.FONT_FAMILY)) {
val newState = TerminalFontSettingsState(getConsoleFontPreferences())
newState.FONT_SIZE_2D = storedState.FONT_SIZE_2D
newState.LINE_SPACING = storedState.LINE_SPACING
newState
}
else storedState
super.loadState(adjustedState)
super.loadState(adjustedState)
}
}
}

View File

@@ -1,22 +1,19 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.terminal
import com.intellij.configurationStore.saveSettingsForRemoteDevelopment
import com.intellij.ide.util.RunOnceUtil
import com.intellij.idea.AppMode
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.*
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.progress.withCurrentThreadCoroutineScope
import com.intellij.openapi.util.registry.Registry
import com.intellij.terminal.TerminalUiSettingsManager
import com.intellij.terminal.TerminalUiSettingsManager.CursorShape
import com.intellij.util.PlatformUtils
import com.intellij.util.application
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.Nls
import org.jetbrains.plugins.terminal.block.ui.updateFrontendSettingsAndSync
import org.jetbrains.plugins.terminal.settings.TerminalLocalOptions
import java.util.concurrent.CopyOnWriteArrayList
@@ -235,25 +232,12 @@ class TerminalOptionsProvider(private val coroutineScope: CoroutineScope) : Pers
private fun performSettingsInitializationOnce() {
RunOnceUtil.runOnceForApp("TerminalOptionsProvider.migration.2025.1.1") {
// If the settings update is happened in IDE backend, let's skip it.
// Because we should receive the values from the frontend and use it.
// Otherwise, there can be a race when updating is performed both on backend and frontend simultaneously.
if (AppMode.isRemoteDevHost()) return@runOnceForApp
try {
updateFrontendSettingsAndSync(coroutineScope) {
migrateCursorShape()
// Disable the terminal engine migration.
// Now it is Reworked by default, not depending on the previously set settings.
//initializeTerminalEngine()
}
finally {
// Trigger sending the updated values to the backend
coroutineScope.launch {
withCurrentThreadCoroutineScope {
saveSettingsForRemoteDevelopment(application)
}
}
}
}
}

View File

@@ -1,11 +1,13 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.terminal.block.ui
import com.intellij.configurationStore.saveSettingsForRemoteDevelopment
import com.intellij.execution.filters.HyperlinkInfo
import com.intellij.execution.filters.HyperlinkWithPopupMenuInfo
import com.intellij.execution.impl.EditorHyperlinkSupport
import com.intellij.ide.ui.AntialiasingType
import com.intellij.ide.ui.UISettings
import com.intellij.idea.AppMode
import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.application.ApplicationManager
@@ -34,6 +36,7 @@ import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.fileEditor.impl.zoomIndicator.ZoomIndicatorManager
import com.intellij.openapi.ide.CopyPasteManager
import com.intellij.openapi.options.advanced.AdvancedSettings
import com.intellij.openapi.progress.withCurrentThreadCoroutineScope
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Key
@@ -44,6 +47,7 @@ import com.intellij.ui.components.JBLayeredPane
import com.intellij.ui.scale.JBUIScale
import com.intellij.util.Alarm
import com.intellij.util.DocumentUtil
import com.intellij.util.application
import com.intellij.util.asSafely
import com.intellij.util.concurrency.ThreadingAssertions
import com.intellij.util.concurrency.annotations.RequiresBlockingContext
@@ -58,6 +62,8 @@ import com.jediterm.terminal.model.TerminalLine
import com.jediterm.terminal.model.TerminalTextBuffer
import com.jediterm.terminal.ui.AwtTransformers
import com.jediterm.terminal.util.CharUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.intellij.lang.annotations.MagicConstant
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.terminal.block.output.TextAttributesProvider
@@ -579,4 +585,27 @@ fun sanitizeLineSeparators(text: String): String {
}
// Now convert this into what the terminal typically expects.
return t.replace("\n", "\r")
}
/**
* Should be used when you need to change the frontend terminal settings that are synced with the backend.
* See [org.jetbrains.plugins.terminal.TerminalRemoteSettingsInfoProvider].
* It prohibits simultaneous update of the setting on both frontend and backend by executing it only on the frontend.
* And then launches sending the updates to the backend in the provided [coroutineScope].
*/
internal fun updateFrontendSettingsAndSync(coroutineScope: CoroutineScope, doUpdate: () -> Unit) {
// Update the settings only on the IDE Frontend (or monolith).
if (AppMode.isRemoteDevHost()) return
try {
doUpdate()
}
finally {
// Trigger sending the updated values to the backend
coroutineScope.launch {
withCurrentThreadCoroutineScope {
saveSettingsForRemoteDevelopment(application)
}
}
}
}