[air] IJAI-241 resolve merge conflicts

GitOrigin-RevId: e2943783cd9003c2e7a4180af8939cf526a5e5c0
This commit is contained in:
Nikita Katkov
2026-08-10 23:57:58 +00:00
committed by intellij-monorepo-bot
parent f7ea55de56
commit 3ec4fcb9d9
7 changed files with 51 additions and 52 deletions
@@ -30,7 +30,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.SimpleModificationTracker
import com.intellij.openapi.wm.IdeRootPaneNorthExtension
import com.intellij.openapi.wm.ex.ProjectFrameActionExclusionService
import com.intellij.openapi.wm.ex.ProjectFrameTypeService
import com.intellij.util.cancelOnDispose
import com.intellij.util.concurrency.AppExecutorUtil
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
@@ -116,7 +116,7 @@ open class RiderMainToolbarRootPaneManager(private val project: Project) : Simpl
@RequiresBackgroundThread
private fun correctedToolbarActions(panel: JPanel): Map<String, ActionGroup?> {
val toolbarGroup = getToolbarGroup() ?: return emptyMap()
val excludedActionIds = service<ProjectFrameActionExclusionService>().getExcludedActionIds(panel.projectFrameTypeId(), ActionPlaces.MAIN_TOOLBAR)
val excludedActionIds = service<ProjectFrameTypeService>().getExcludedActionIds(panel.projectFrameTypeId(), ActionPlaces.MAIN_TOOLBAR)
val leftGroup = sideGroup(toolbarGroup, excludedActionIds, ::isLeftSideAction)
val rightGroup = sideGroup(toolbarGroup, excludedActionIds, ::isRightSideAction)
@@ -26,7 +26,7 @@ class ProjectFrameCapabilitiesServiceTest {
val uiPolicyRef = AtomicReference(
ProjectFrameUiPolicy(
projectPaneToActivateId = "pane-1",
toolWindowLayoutProfileId = "layout-profile-1",
startupToolWindowIdToActivate = "toolwindow-1",
)
)
val capabilitiesComputationCount = AtomicInteger()
@@ -59,16 +59,16 @@ class ProjectFrameCapabilitiesServiceTest {
val service = ProjectFrameCapabilitiesService()
assertThat(service.getUiPolicy(project)?.projectPaneToActivateId).isEqualTo("pane-1")
assertThat(service.getUiPolicy(project)?.toolWindowLayoutProfileId).isEqualTo("layout-profile-1")
assertThat(service.getUiPolicy(project)?.startupToolWindowIdToActivate).isEqualTo("toolwindow-1")
uiPolicyRef.set(
ProjectFrameUiPolicy(
projectPaneToActivateId = "pane-2",
toolWindowLayoutProfileId = "layout-profile-2",
startupToolWindowIdToActivate = "toolwindow-2",
)
)
assertThat(service.getUiPolicy(project)?.projectPaneToActivateId).isEqualTo("pane-2")
assertThat(service.getUiPolicy(project)?.toolWindowLayoutProfileId).isEqualTo("layout-profile-2")
assertThat(service.getUiPolicy(project)?.startupToolWindowIdToActivate).isEqualTo("toolwindow-2")
assertThat(service.getAll(project)).isEqualTo(setOf(ProjectFrameCapability.WELCOME_EXPERIENCE))
assertThat(service.has(project, ProjectFrameCapability.WELCOME_EXPERIENCE)).isTrue()
@@ -4,7 +4,7 @@ package com.intellij.openapi.wm.impl
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.ex.ProjectFrameCapabilitiesService
import com.intellij.openapi.wm.ex.ProjectFrameTypeService
import com.intellij.toolWindow.ToolWindowLayoutApplyMode
import com.intellij.toolWindow.ToolWindowLayoutProfile
import com.intellij.toolWindow.ToolWindowLayoutProfileService
@@ -17,11 +17,11 @@ internal data class ProjectFrameToolWindowLayoutProfile(
)
internal fun resolveProjectFrameToolWindowLayoutProfile(
projectFrameTypeId: String?,
project: Project,
isNewUi: Boolean,
): ProjectFrameToolWindowLayoutProfile? {
val uiPolicy = service<ProjectFrameCapabilitiesService>().getUiPolicy(project) ?: return null
val profileId = uiPolicy.toolWindowLayoutProfileId ?: return null
val profileId = service<ProjectFrameTypeService>().getToolWindowLayoutProfileId(projectFrameTypeId) ?: return null
val profile = service<ToolWindowLayoutProfileService>().getProfile(project = project, profileId = profileId, isNewUi = isNewUi)
?: return null
return ProjectFrameToolWindowLayoutProfile(profileId = profileId, profile = profile)
@@ -55,7 +55,7 @@ import com.intellij.openapi.wm.ToolWindowType
import com.intellij.openapi.wm.WINDOW_INFO_DEFAULT_TOOL_WINDOW_PANE_ID
import com.intellij.openapi.wm.WindowInfo
import com.intellij.openapi.wm.WindowManager
import com.intellij.openapi.wm.ex.ProjectFrameCapabilitiesService
import com.intellij.openapi.wm.ex.ProjectFrameTypeService
import com.intellij.openapi.wm.ex.ToolWindowEx
import com.intellij.openapi.wm.ex.ToolWindowManagerEx
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
@@ -198,18 +198,12 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
delay = SystemProperties.getIntProperty("actionSystem.keyGestureDblClickTime", 300),
coroutineScope = coroutineScope,
)
val projectFrameLayoutProfile = resolveProjectFrameToolWindowLayoutProfile(project = project, isNewUi = isNewUi)
if (state.noStateLoaded) {
loadDefault(projectFrameLayoutProfile)
}
@Suppress("LeakingThis")
state.scheduledLayout.afterChange(this) { dl ->
dl?.let { toolWindowSetInitializer.scheduleSetLayout(it) }
}
state.scheduledLayout.get()?.let { toolWindowSetInitializer.scheduleSetLayout(it) }
applyProjectFrameLayoutPolicy(projectFrameLayoutProfile) { layout ->
toolWindowSetInitializer.scheduleSetLayout(layout)
}
// the frame-type layout profile is resolved in `doInit`, once `projectFrameTypeId` is known
}
}
@@ -426,6 +420,22 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
projectFrameTypeId: String? = this.projectFrameTypeId,
) {
this.projectFrameTypeId = projectFrameTypeId
// Resolved here rather than in the constructor: the layout profile is keyed by frame type, and
// `projectFrameTypeId` is only known now. `initUi` below consumes whatever layout we schedule.
val projectFrameLayoutProfile = resolveProjectFrameToolWindowLayoutProfile(
projectFrameTypeId = projectFrameTypeId,
project = project,
isNewUi = isNewUi,
)
if (state.noStateLoaded) {
// `noStateLoaded` is set exactly when no layout was scheduled, so this cannot overwrite a restored one.
loadDefault(projectFrameLayoutProfile)
}
applyProjectFrameLayoutPolicy(projectFrameLayoutProfile) { layout ->
toolWindowSetInitializer.scheduleSetLayout(layout)
}
withContext(ModalityState.any().asContextElement()) {
val defaultPaneInitialization = launch(Dispatchers.EDT) {
this@ToolWindowManagerImpl.projectFrame = pane.frame
@@ -526,7 +536,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
}
private fun getProjectFrameToolWindowLayoutProfileId(): String? {
return service<ProjectFrameCapabilitiesService>().getUiPolicy(project)?.toolWindowLayoutProfileId
return service<ProjectFrameTypeService>().getToolWindowLayoutProfileId(projectFrameTypeId)
}
private fun getDefaultToolWindowPaneIfInitialized(): ToolWindowPane {
@@ -557,12 +567,7 @@ open class ToolWindowManagerImpl @NonInjectable @TestOnly internal constructor(
}
}
private fun loadDefault(
projectFrameLayoutProfile: ProjectFrameToolWindowLayoutProfile? = resolveProjectFrameToolWindowLayoutProfile(
project = project,
isNewUi = isNewUi,
),
) {
private fun loadDefault(projectFrameLayoutProfile: ProjectFrameToolWindowLayoutProfile?) {
val layout = projectFrameLayoutProfile?.profile?.layout ?: ToolWindowDefaultLayoutManager.getInstance().getLayoutCopy()
toolWindowSetInitializer.scheduleSetLayout(layout)
}
@@ -50,7 +50,7 @@ import com.intellij.openapi.keymap.impl.ui.ActionsTreeUtil
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.util.IconLoader
import com.intellij.openapi.util.SystemInfoRt
import com.intellij.openapi.wm.ex.ProjectFrameActionExclusionService
import com.intellij.openapi.wm.ex.ProjectFrameTypeService
import com.intellij.openapi.wm.impl.IdeBackgroundUtil
import com.intellij.openapi.wm.impl.ToolbarComboButton
import com.intellij.openapi.wm.impl.customFrameDecorations.header.CustomWindowHeaderUtil
@@ -563,7 +563,7 @@ private suspend fun computeMainActionGroups(
customActionSchema: CustomActionsSchema,
projectFrameTypeId: String? = null,
): List<Pair<ActionGroup, HorizontalLayout.Group>> {
val excludedActionIds = serviceAsync<ProjectFrameActionExclusionService>().getExcludedActionIds(projectFrameTypeId, ActionPlaces.MAIN_TOOLBAR)
val excludedActionIds = serviceAsync<ProjectFrameTypeService>().getExcludedActionIds(projectFrameTypeId, ActionPlaces.MAIN_TOOLBAR)
val result = ArrayList<Pair<ActionGroup, HorizontalLayout.Group>>(3)
for (info in getMainToolbarGroups()) {
customActionSchema.getCorrectedActionAsync(info.id, info.name)?.let { actionGroup ->
@@ -581,7 +581,7 @@ internal fun blockingComputeMainActionGroups(
customActionSchema: CustomActionsSchema,
projectFrameTypeId: String? = null,
): List<Pair<ActionGroup, HorizontalLayout.Group>> {
val excludedActionIds = service<ProjectFrameActionExclusionService>().getExcludedActionIds(projectFrameTypeId, ActionPlaces.MAIN_TOOLBAR)
val excludedActionIds = service<ProjectFrameTypeService>().getExcludedActionIds(projectFrameTypeId, ActionPlaces.MAIN_TOOLBAR)
return getMainToolbarGroups()
.mapNotNull { info ->
customActionSchema.getCorrectedAction(info.id, info.name)?.let { actionGroup ->
@@ -12,7 +12,6 @@ import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.UI
import com.intellij.openapi.application.asContextElement
import com.intellij.openapi.components.service
import com.intellij.openapi.components.serviceAsync
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.ExtensionPointListener
@@ -26,7 +25,7 @@ import com.intellij.openapi.wm.ToolWindowAnchor
import com.intellij.openapi.wm.ToolWindowEP
import com.intellij.openapi.wm.ToolWindowFactory
import com.intellij.openapi.wm.WINDOW_INFO_DEFAULT_TOOL_WINDOW_PANE_ID
import com.intellij.openapi.wm.ex.ProjectFrameCapabilitiesService
import com.intellij.openapi.wm.ex.ProjectFrameTypeService
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
import com.intellij.openapi.wm.impl.DesktopLayout
import com.intellij.openapi.wm.impl.ToolWindowManagerAppLevelHelper
@@ -378,8 +377,8 @@ private fun beanToTask(
@OptIn(ExperimentalCoroutinesApi::class)
internal suspend fun computeToolWindowBeans(project: Project, projectFrameTypeId: String? = null): List<RegisterToolWindowTaskData> {
val projectFrameToolWindowLayoutProfileId = service<ProjectFrameCapabilitiesService>().getUiPolicy(project)?.toolWindowLayoutProfileId
val suppressedToolWindowIds = service<ProjectFrameToolWindowLayoutService>().getSuppressedToolWindowIds(
val projectFrameToolWindowLayoutProfileId = serviceAsync<ProjectFrameTypeService>().getToolWindowLayoutProfileId(projectFrameTypeId)
val suppressedToolWindowIds = serviceAsync<ProjectFrameToolWindowLayoutService>().getSuppressedToolWindowIds(
frameType = projectFrameTypeId,
profileId = projectFrameToolWindowLayoutProfileId,
)
@@ -11,10 +11,8 @@ import com.intellij.openapi.wm.ToolWindowAnchor
import com.intellij.openapi.wm.ToolWindowEP
import com.intellij.openapi.wm.ToolWindowFactory
import com.intellij.openapi.wm.ToolWindowId
import com.intellij.openapi.wm.ex.ProjectFrameCapabilitiesProvider
import com.intellij.openapi.wm.ex.ProjectFrameCapabilitiesService
import com.intellij.openapi.wm.ex.ProjectFrameCapability
import com.intellij.openapi.wm.ex.ProjectFrameUiPolicy
import com.intellij.openapi.wm.ex.ProjectFrameTypeBean
import com.intellij.openapi.wm.ex.ProjectFrameTypeService
import com.intellij.testFramework.ExtensionTestUtil
import com.intellij.testFramework.junit5.TestApplication
import com.intellij.testFramework.junit5.TestDisposable
@@ -199,18 +197,27 @@ class ProjectFrameToolWindowLayoutServiceTest {
}
@Test
fun uiPolicyLayoutProfileSuppressesToolWindowEpWhenFrameTypeIsMissing() {
registerSuppressedToolWindowLayout()
fun frameTypeProfileSuppressesToolWindowEpWhenLayoutFrameTypeDoesNotMatch() {
registerLayoutBean(
ProjectFrameToolWindowLayoutBean().apply {
id = "dedicated"
frameType = "OTHER"
toolWindows = listOf(suppressedToolWindow("Suppressed"))
}
)
CountingToolWindowFactory.createdCount = 0
ExtensionTestUtil.maskExtensions(ToolWindowEP.EP_NAME, listOf(suppressedToolWindowEp()), disposable, fireEvents = false)
ExtensionTestUtil.maskExtensions(
ProjectFrameCapabilitiesService.EP_NAME,
listOf(testUiPolicyProvider { "dedicated" }),
ProjectFrameTypeService.EP_NAME,
listOf(ProjectFrameTypeBean().apply {
id = "DEDICATED"
toolWindowLayoutProfile = "dedicated"
}),
disposable,
fireEvents = false,
)
val tasks = runBlocking { computeToolWindowBeans(project, projectFrameTypeId = null) }
val tasks = runBlocking { computeToolWindowBeans(project, projectFrameTypeId = "DEDICATED") }
assertThat(tasks).isEmpty()
assertThat(CountingToolWindowFactory.createdCount).isEqualTo(0)
@@ -259,18 +266,6 @@ private fun suppressedToolWindowEp(): ToolWindowEP {
}
}
private fun testUiPolicyProvider(profileIdProvider: () -> String?): ProjectFrameCapabilitiesProvider {
return object : ProjectFrameCapabilitiesProvider {
override fun getCapabilities(project: Project): Set<ProjectFrameCapability> {
return emptySet()
}
override fun getUiPolicy(project: Project, capabilities: Set<ProjectFrameCapability>): ProjectFrameUiPolicy? {
return profileIdProvider()?.let { ProjectFrameUiPolicy(toolWindowLayoutProfileId = it) }
}
}
}
private const val AGENT_SESSIONS_TOOL_WINDOW_ID = "agent.workbench.sessions"
class CountingToolWindowFactory : ToolWindowFactory {