mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
IJPL-158075 updateHeadersRunnable - use flow instead of alarm
GitOrigin-RevId: 6984b38a83886070e434b522846716de4cfd2432
This commit is contained in:
committed by
intellij-monorepo-bot
parent
184812fb0d
commit
7a927bdadf
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:Suppress("ReplaceGetOrSet", "ReplacePutWithAssignment", "OverridingDeprecatedMember", "ReplaceNegatedIsEmptyWithIsNotEmpty",
|
||||
"PrivatePropertyName")
|
||||
@file:OptIn(FlowPreview::class)
|
||||
|
||||
package com.intellij.openapi.wm.impl
|
||||
|
||||
@@ -27,6 +28,7 @@ import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.application.asContextElement
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.components.serviceAsync
|
||||
import com.intellij.openapi.components.serviceIfCreated
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.diagnostic.debug
|
||||
@@ -58,7 +60,6 @@ import com.intellij.openapi.wm.ex.ToolWindowEx
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerEx
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerListener.ToolWindowManagerEventType
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerListener.ToolWindowManagerEventType.*
|
||||
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
||||
import com.intellij.serviceContainer.NonInjectable
|
||||
import com.intellij.toolWindow.*
|
||||
@@ -70,6 +71,10 @@ import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import com.intellij.util.messages.SimpleMessageBusConnection
|
||||
import com.intellij.util.ui.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import org.intellij.lang.annotations.MagicConstant
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
@@ -203,7 +208,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
internal class ToolWindowManagerAppLevelHelper {
|
||||
internal class ToolWindowManagerAppLevelHelper(coroutineScope: CoroutineScope) {
|
||||
companion object {
|
||||
private fun handleFocusEvent(event: FocusEvent) {
|
||||
if (event.id == FocusEvent.FOCUS_LOST) {
|
||||
@@ -284,16 +289,23 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
val awtFocusListener = MyListener()
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(awtFocusListener, AWTEvent.FOCUS_EVENT_MASK or AWTEvent.WINDOW_FOCUS_EVENT_MASK)
|
||||
|
||||
val updateHeadersRunnable = {
|
||||
for (project in getOpenedProjects()) {
|
||||
(getInstance(project) as ToolWindowManagerImpl).updateToolWindowHeaders()
|
||||
}
|
||||
val updateHeadersRequests = MutableSharedFlow<Unit>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
coroutineScope.launch {
|
||||
updateHeadersRequests
|
||||
.debounce(50)
|
||||
.collectLatest {
|
||||
for (project in getOpenedProjects()) {
|
||||
val toolWindowManager = project.serviceAsync<ToolWindowManager>() as ToolWindowManagerImpl
|
||||
withContext(Dispatchers.EDT) {
|
||||
toolWindowManager.updateToolWindowHeaders()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val updateHeadersAlarm = SingleAlarm(updateHeadersRunnable, 50, ApplicationManager.getApplication())
|
||||
val focusListener = PropertyChangeListener { updateHeadersAlarm.cancelAndRequest() }
|
||||
val focusListener = PropertyChangeListener { check(updateHeadersRequests.tryEmit(Unit)) }
|
||||
FocusUtil.addFocusOwnerListener(ApplicationManager.getApplication(), focusListener)
|
||||
|
||||
val connection = ApplicationManager.getApplication().messageBus.connect()
|
||||
val connection = ApplicationManager.getApplication().messageBus.connect(coroutineScope)
|
||||
connection.subscribe(ProjectCloseListener.TOPIC, object : ProjectCloseListener {
|
||||
override fun projectClosingBeforeSave(project: Project) {
|
||||
val manager = (project.serviceIfCreated<ToolWindowManager>() as ToolWindowManagerImpl?) ?: return
|
||||
@@ -349,7 +361,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
|
||||
false
|
||||
}, ApplicationManager.getApplication())
|
||||
}, coroutineScope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,7 +418,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
|
||||
private fun updateToolWindowHeaders() {
|
||||
focusManager.doWhenFocusSettlesDown(ExpirableRunnable.forProject(project) {
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(ExpirableRunnable.forProject(project) {
|
||||
for (entry in idToEntry.values) {
|
||||
if (entry.readOnlyWindowInfo.isVisible) {
|
||||
val decorator = entry.toolWindow.decorator ?: continue
|
||||
@@ -487,9 +499,11 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun init(frameHelperDeferred: Deferred<ProjectFrameHelper>,
|
||||
reopeningEditorJob: Job,
|
||||
taskListDeferred: Deferred<List<RegisterToolWindowTask>>) {
|
||||
suspend fun init(
|
||||
frameHelperDeferred: Deferred<ProjectFrameHelper>,
|
||||
reopeningEditorJob: Job,
|
||||
taskListDeferred: Deferred<List<RegisterToolWindowTask>>,
|
||||
) {
|
||||
doInit(frameHelperDeferred = frameHelperDeferred,
|
||||
connection = project.messageBus.connect(coroutineScope),
|
||||
reopeningEditorJob = reopeningEditorJob,
|
||||
@@ -497,10 +511,12 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
suspend fun doInit(frameHelperDeferred: Deferred<ProjectFrameHelper>,
|
||||
connection: SimpleMessageBusConnection,
|
||||
reopeningEditorJob: Job,
|
||||
taskListDeferred: Deferred<List<RegisterToolWindowTask>>?) {
|
||||
suspend fun doInit(
|
||||
frameHelperDeferred: Deferred<ProjectFrameHelper>,
|
||||
connection: SimpleMessageBusConnection,
|
||||
reopeningEditorJob: Job,
|
||||
taskListDeferred: Deferred<List<RegisterToolWindowTask>>?,
|
||||
) {
|
||||
withContext(ModalityState.any().asContextElement()) {
|
||||
val frameHelper = frameHelperDeferred.await()
|
||||
launch(Dispatchers.EDT) {
|
||||
@@ -636,10 +652,12 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun activateToolWindow(entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
autoFocusContents: Boolean = true,
|
||||
source: ToolWindowEventSource? = null) {
|
||||
internal fun activateToolWindow(
|
||||
entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
autoFocusContents: Boolean = true,
|
||||
source: ToolWindowEventSource? = null,
|
||||
) {
|
||||
LOG.debug { "activateToolWindow($entry)" }
|
||||
|
||||
if (isUnifiedToolWindowSizesEnabled()) {
|
||||
@@ -727,11 +745,13 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
return info
|
||||
}
|
||||
|
||||
private fun deactivateToolWindow(info: WindowInfoImpl,
|
||||
entry: ToolWindowEntry,
|
||||
dirtyMode: Boolean = false,
|
||||
mutation: Mutation? = null,
|
||||
source: ToolWindowEventSource? = null) {
|
||||
private fun deactivateToolWindow(
|
||||
info: WindowInfoImpl,
|
||||
entry: ToolWindowEntry,
|
||||
dirtyMode: Boolean = false,
|
||||
mutation: Mutation? = null,
|
||||
source: ToolWindowEventSource? = null,
|
||||
) {
|
||||
LOG.debug { "deactivateToolWindow(${info.id})" }
|
||||
|
||||
setHiddenState(info, entry, source)
|
||||
@@ -857,11 +877,13 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
hideToolWindow(id = id, hideSide = hideSide, source = null)
|
||||
}
|
||||
|
||||
open fun hideToolWindow(id: String,
|
||||
hideSide: Boolean = false,
|
||||
moveFocus: Boolean = true,
|
||||
removeFromStripe: Boolean = false,
|
||||
source: ToolWindowEventSource? = null) {
|
||||
open fun hideToolWindow(
|
||||
id: String,
|
||||
hideSide: Boolean = false,
|
||||
moveFocus: Boolean = true,
|
||||
removeFromStripe: Boolean = false,
|
||||
source: ToolWindowEventSource? = null,
|
||||
) {
|
||||
EDT.assertIsEdt()
|
||||
|
||||
val entry = idToEntry.get(id)!!
|
||||
@@ -892,12 +914,14 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
revalidateStripeButtons()
|
||||
}
|
||||
|
||||
private fun executeHide(entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
dirtyMode: Boolean,
|
||||
hideSide: Boolean = false,
|
||||
mutation: Mutation? = null,
|
||||
source: ToolWindowEventSource? = null) {
|
||||
private fun executeHide(
|
||||
entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
dirtyMode: Boolean,
|
||||
hideSide: Boolean = false,
|
||||
mutation: Mutation? = null,
|
||||
source: ToolWindowEventSource? = null,
|
||||
) {
|
||||
// hide and deactivate
|
||||
deactivateToolWindow(info, entry, dirtyMode = dirtyMode, mutation = mutation, source = source)
|
||||
|
||||
@@ -950,10 +974,12 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
/**
|
||||
* @param dirtyMode if `true` then all UI operations are performed in dirty mode.
|
||||
*/
|
||||
private fun showToolWindowImpl(entry: ToolWindowEntry,
|
||||
toBeShownInfo: WindowInfoImpl,
|
||||
dirtyMode: Boolean,
|
||||
source: ToolWindowEventSource? = null): Boolean {
|
||||
private fun showToolWindowImpl(
|
||||
entry: ToolWindowEntry,
|
||||
toBeShownInfo: WindowInfoImpl,
|
||||
dirtyMode: Boolean,
|
||||
source: ToolWindowEventSource? = null,
|
||||
): Boolean {
|
||||
if (!entry.toolWindow.isAvailable) {
|
||||
return false
|
||||
}
|
||||
@@ -1069,10 +1095,12 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
return result.entry
|
||||
}
|
||||
|
||||
internal fun registerToolWindow(preparedTask: PreparedRegisterToolWindowTask,
|
||||
buttonManager: ToolWindowButtonManager,
|
||||
layout: DesktopLayout,
|
||||
ensureToolWindowActionRegistered: Boolean): RegisterToolWindowResult {
|
||||
internal fun registerToolWindow(
|
||||
preparedTask: PreparedRegisterToolWindowTask,
|
||||
buttonManager: ToolWindowButtonManager,
|
||||
layout: DesktopLayout,
|
||||
ensureToolWindowActionRegistered: Boolean,
|
||||
): RegisterToolWindowResult {
|
||||
val task = preparedTask.task
|
||||
|
||||
LOG.debug { "registerToolWindow($task)" }
|
||||
@@ -1525,7 +1553,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fireStateChanged(MoreButtonUpdated)
|
||||
fireStateChanged(ToolWindowManagerEventType.MoreButtonUpdated)
|
||||
}
|
||||
|
||||
override fun setShowNames(value: Boolean) {
|
||||
@@ -1538,7 +1566,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fireStateChanged(ShowNames)
|
||||
fireStateChanged(ToolWindowManagerEventType.ShowNames)
|
||||
}
|
||||
|
||||
override fun setSideCustomWidth(toolbar: ToolWindowToolbar, width: Int) {
|
||||
@@ -1551,7 +1579,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fireStateChanged(SideCustomWidth)
|
||||
fireStateChanged(ToolWindowManagerEventType.SideCustomWidth)
|
||||
}
|
||||
|
||||
override fun invokeLater(runnable: Runnable) {
|
||||
@@ -1563,7 +1591,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
|
||||
override val focusManager: IdeFocusManager
|
||||
get() = IdeFocusManager.getInstance(project)!!
|
||||
get() = IdeFocusManager.getGlobalInstance()
|
||||
|
||||
override fun canShowNotification(toolWindowId: String): Boolean {
|
||||
val readOnlyWindowInfo = idToEntry.get(toolWindowId)?.readOnlyWindowInfo
|
||||
@@ -1862,13 +1890,15 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun doSetAnchor(entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
paneId: String,
|
||||
anchor: ToolWindowAnchor,
|
||||
order: Int,
|
||||
currentInfo: WindowInfo? = null,
|
||||
layoutState: DesktopLayout?) {
|
||||
private fun doSetAnchor(
|
||||
entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
paneId: String,
|
||||
anchor: ToolWindowAnchor,
|
||||
order: Int,
|
||||
currentInfo: WindowInfo? = null,
|
||||
layoutState: DesktopLayout?,
|
||||
) {
|
||||
if (isNewUi && currentInfo != null) {
|
||||
entry.removeStripeButton(currentInfo.anchor, currentInfo.isSplit)
|
||||
}
|
||||
@@ -1952,10 +1982,12 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
fireStateChanged(ToolWindowManagerEventType.SetSideToolAndAnchor, entry.toolWindow)
|
||||
}
|
||||
|
||||
private fun hideIfNeededAndShowAfterTask(entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
source: ToolWindowEventSource? = null,
|
||||
task: () -> Unit) {
|
||||
private fun hideIfNeededAndShowAfterTask(
|
||||
entry: ToolWindowEntry,
|
||||
info: WindowInfoImpl,
|
||||
source: ToolWindowEventSource? = null,
|
||||
task: () -> Unit,
|
||||
) {
|
||||
val wasVisible = entry.readOnlyWindowInfo.isVisible
|
||||
val wasFocused = entry.toolWindow.isActive
|
||||
if (wasVisible) {
|
||||
@@ -2359,7 +2391,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
layoutState.setUnifiedAnchorWeight(anchor, dockingAreaWeight)
|
||||
LOG.debug { "Moved/resized tool window ${info.id}, updated weight=${toolWindowWeight}, docking area weight=${dockingAreaWeight}" }
|
||||
}
|
||||
fireStateChanged(MovedOrResized, toolWindow)
|
||||
fireStateChanged(ToolWindowManagerEventType.MovedOrResized, toolWindow)
|
||||
}
|
||||
|
||||
private fun dockingAreaComponentSizeCanBeTrusted(dockingAreaComponent: Component): Boolean {
|
||||
@@ -2384,7 +2416,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
|
||||
private fun getAdjustedWeight(
|
||||
toolWindowPane: ToolWindowPane,
|
||||
anchor: ToolWindowAnchor,
|
||||
component: Component
|
||||
component: Component,
|
||||
): Float {
|
||||
val wholeSize = toolWindowPane.rootPane.size
|
||||
return getAdjustedRatio(
|
||||
@@ -2503,8 +2535,10 @@ private enum class KeyState {
|
||||
WAITING, PRESSED, RELEASED, HOLD
|
||||
}
|
||||
|
||||
private fun areAllModifiersPressed(@MagicConstant(flagsFromClass = InputEvent::class) modifiers: Int,
|
||||
@MagicConstant(flagsFromClass = InputEvent::class) mask: Int): Boolean {
|
||||
private fun areAllModifiersPressed(
|
||||
@MagicConstant(flagsFromClass = InputEvent::class) modifiers: Int,
|
||||
@MagicConstant(flagsFromClass = InputEvent::class) mask: Int,
|
||||
): Boolean {
|
||||
return (modifiers xor mask) == 0
|
||||
}
|
||||
|
||||
@@ -2549,7 +2583,7 @@ private fun getActivateToolWindowVKsMask(): Int {
|
||||
@Suppress("DEPRECATION")
|
||||
baseModifiers = baseModifiers and (InputEvent.SHIFT_MASK or InputEvent.CTRL_MASK or InputEvent.META_MASK or InputEvent.ALT_MASK)
|
||||
|
||||
// If the keymap either doesn't define an ActivateProjectToolWindow shortcut,
|
||||
// If the keymap either doesn't define an ActivateProjectToolWindow shortcut
|
||||
// or defines it with multiple modifiers, fall back to the default behavior.
|
||||
if (baseModifiers.countOneBits() == 1) {
|
||||
return baseModifiers
|
||||
|
||||
Reference in New Issue
Block a user