diff --git a/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt b/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt index 5cacc81c14df..fe5d4f6a2039 100644 --- a/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt +++ b/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt @@ -27,8 +27,8 @@ import com.intellij.openapi.vfs.newvfs.NewVirtualFile import com.intellij.openapi.vfs.newvfs.RefreshQueue import com.intellij.openapi.wm.IdeFrame import com.intellij.project.stateStore -import com.intellij.util.application import com.intellij.util.awaitCancellationAndInvoke +import com.intellij.util.ui.EDT import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.* @@ -55,7 +55,9 @@ internal class SaveAndSyncHandlerImpl(private val coroutineScope: CoroutineScope private val saveQueue = ArrayDeque() private val currentJob = AtomicReference() - private val eventPublisher = application.messageBus.syncPublisher(SaveAndSyncHandlerListener.TOPIC) + private val eventPublisher: SaveAndSyncHandlerListener + get() = ApplicationManager.getApplication().messageBus.syncPublisher(SaveAndSyncHandlerListener.TOPIC) + private val forceExecuteImmediatelyState = AtomicBoolean() init { @@ -65,6 +67,7 @@ internal class SaveAndSyncHandlerImpl(private val coroutineScope: CoroutineScope refreshRequests .debounce(300.milliseconds) .collect { + val eventPublisher = eventPublisher withContext(Dispatchers.EDT) { blockingContext { eventPublisher.beforeRefresh() @@ -131,6 +134,7 @@ internal class SaveAndSyncHandlerImpl(private val coroutineScope: CoroutineScope } private suspend fun processTasks(forceExecuteImmediately: Boolean) { + val eventPublisher = eventPublisher while (true) { if (blockSaveOnFrameDeactivationCount.get() != 0) { return @@ -245,7 +249,7 @@ internal class SaveAndSyncHandlerImpl(private val coroutineScope: CoroutineScope override fun saveSettingsUnderModalProgress(componentManager: ComponentManager): Boolean { // saveSettingsUnderModalProgress is intended to be called only in EDT because // otherwise wrapping into a modal progress task is not required and `saveSettings` should be called directly - ApplicationManager.getApplication().assertIsDispatchThread() + EDT.assertIsEdt() var isSavedSuccessfully = true var isAutoSaveCancelled = false @@ -267,11 +271,10 @@ internal class SaveAndSyncHandlerImpl(private val coroutineScope: CoroutineScope } val project = (componentManager as? Project)?.takeIf { !it.isDefault } - runBlockingModalWithRawProgressReporter(owner = if (project == null) ModalTaskOwner.guess() else ModalTaskOwner.project(project), - title = getProgressTitle(componentManager), - cancellation = TaskCancellation.nonCancellable() - ) { - // ensure that is fully cancelled + runWithModalProgressBlocking(owner = if (project == null) ModalTaskOwner.guess() else ModalTaskOwner.project(project), + title = getProgressTitle(componentManager), + cancellation = TaskCancellation.nonCancellable()) { + // ensure that is fully canceled currentJob?.join() isSavedSuccessfully = saveSettings(componentManager, forceSavingAllSettings = true) diff --git a/platform/core-impl/src/com/intellij/openapi/command/impl/CoreCommandProcessor.java b/platform/core-impl/src/com/intellij/openapi/command/impl/CoreCommandProcessor.java index be227384f844..cc73a6f4b002 100644 --- a/platform/core-impl/src/com/intellij/openapi/command/impl/CoreCommandProcessor.java +++ b/platform/core-impl/src/com/intellij/openapi/command/impl/CoreCommandProcessor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.command.impl; import com.intellij.openapi.application.Application; @@ -11,6 +11,7 @@ import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.NlsContexts; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.concurrency.ThreadingAssertions; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import com.intellij.util.messages.MessageBus; @@ -290,7 +291,7 @@ public class CoreCommandProcessor extends CommandProcessorEx { @Override public void enterModal() { - ApplicationManager.getApplication().assertWriteIntentLockAcquired(); + ThreadingAssertions.assertWriteIntentReadAccess(); CommandDescriptor currentCommand = myCurrentCommand; myInterruptedCommands.push(currentCommand); if (currentCommand != null) { @@ -300,7 +301,7 @@ public class CoreCommandProcessor extends CommandProcessorEx { @Override public void leaveModal() { - ApplicationManager.getApplication().assertWriteIntentLockAcquired(); + ThreadingAssertions.assertWriteIntentReadAccess(); CommandLog.LOG.assertTrue(myCurrentCommand == null, "Command must not run: " + myCurrentCommand); myCurrentCommand = myInterruptedCommands.pop(); @@ -311,7 +312,7 @@ public class CoreCommandProcessor extends CommandProcessorEx { @Override public void setCurrentCommandName(String name) { - ApplicationManager.getApplication().assertWriteIntentLockAcquired(); + ThreadingAssertions.assertWriteIntentReadAccess(); CommandDescriptor currentCommand = myCurrentCommand; CommandLog.LOG.assertTrue(currentCommand != null); currentCommand.myName = name; @@ -319,7 +320,7 @@ public class CoreCommandProcessor extends CommandProcessorEx { @Override public void setCurrentCommandGroupId(Object groupId) { - ApplicationManager.getApplication().assertWriteIntentLockAcquired(); + ThreadingAssertions.assertWriteIntentReadAccess(); CommandDescriptor currentCommand = myCurrentCommand; CommandLog.LOG.assertTrue(currentCommand != null); currentCommand.myGroupId = groupId; diff --git a/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandlerListener.java b/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandlerListener.java index eb96da31b17b..942b5fb2fcb8 100644 --- a/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandlerListener.java +++ b/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandlerListener.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide; import com.intellij.util.messages.Topic; @@ -7,7 +7,7 @@ import org.jetbrains.annotations.ApiStatus; @ApiStatus.Experimental public interface SaveAndSyncHandlerListener { @Topic.AppLevel - Topic TOPIC = Topic.create("SaveAndSyncHandler events", SaveAndSyncHandlerListener.class); + Topic TOPIC = new Topic<>("SaveAndSyncHandler events", SaveAndSyncHandlerListener.class); default void beforeRefresh() {} diff --git a/platform/platform-impl/src/com/intellij/ide/gdpr/Agreements.kt b/platform/platform-impl/src/com/intellij/ide/gdpr/Agreements.kt index 4faabc6c5b99..7149791ef3b7 100644 --- a/platform/platform-impl/src/com/intellij/ide/gdpr/Agreements.kt +++ b/platform/platform-impl/src/com/intellij/ide/gdpr/Agreements.kt @@ -5,8 +5,9 @@ package com.intellij.ide.gdpr import com.intellij.diagnostic.LoadingState import com.intellij.idea.AppExitCodes -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationNamesInfo +import com.intellij.openapi.application.ex.ApplicationEx +import com.intellij.openapi.application.ex.ApplicationManagerEx import com.intellij.openapi.application.impl.ApplicationInfoImpl import com.intellij.openapi.options.ShowSettingsUtil import com.intellij.openapi.ui.DialogWrapper @@ -32,7 +33,8 @@ fun showEndUserAndDataSharingAgreements(agreement: EndUserAgreement.Document) { text = bundle.getString("userAgreement.dialog.exit"), action = { if (LoadingState.COMPONENTS_REGISTERED.isOccurred) { - ApplicationManager.getApplication().exit(true, true, false, AppExitCodes.PRIVACY_POLICY_REJECTION) + ApplicationManagerEx.getApplicationEx().exit(ApplicationEx.EXIT_CONFIRMED or ApplicationEx.FORCE_EXIT, + AppExitCodes.PRIVACY_POLICY_REJECTION) } else { exitProcess(AppExitCodes.PRIVACY_POLICY_REJECTION) diff --git a/platform/platform-impl/src/com/intellij/idea/eua.kt b/platform/platform-impl/src/com/intellij/idea/eua.kt index 644623ef91a6..11edc6fb9c15 100644 --- a/platform/platform-impl/src/com/intellij/idea/eua.kt +++ b/platform/platform-impl/src/com/intellij/idea/eua.kt @@ -26,7 +26,8 @@ internal suspend fun loadEuaDocument(appInfoDeferred: Deferred Boolean)? { +internal suspend fun prepareShowEuaIfNeededTask(document: EndUserAgreement.Document?, + asyncScope: CoroutineScope): (suspend () -> Boolean)? { val updateCached = asyncScope.launch(CoroutineName("eua cache updating") + Dispatchers.IO) { EndUserAgreement.updateCachedContentToLatestBundledVersion() } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index fc6bbd2cab23..9b1958db35af 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -26,13 +26,17 @@ import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.ui.popup.StackingPopupDispatcher; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.WindowStateService; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.registry.RegistryManager; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; -import com.intellij.openapi.wm.impl.*; +import com.intellij.openapi.wm.impl.IdeFrameDecorator; +import com.intellij.openapi.wm.impl.IdeFrameImpl; +import com.intellij.openapi.wm.impl.IdeGlassPaneImpl; +import com.intellij.openapi.wm.impl.ProjectFrameHelper; import com.intellij.openapi.wm.impl.customFrameDecorations.header.CustomFrameDialogContent; import com.intellij.openapi.wm.impl.customFrameDecorations.header.CustomHeader; import com.intellij.reference.SoftReference; @@ -77,34 +81,38 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { private final List myDisposeActions = new ArrayList<>(); private Project myProject; - protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent, @NotNull DialogWrapper.IdeModalityType ideModalityType) { + protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, + @Nullable Project project, + boolean canBeParent, + @NotNull DialogWrapper.IdeModalityType ideModalityType) { boolean headless = isHeadlessEnv(); myWrapper = wrapper; - WindowManagerEx windowManager = getWindowManager(); - Window window = null; - if (windowManager != null) { - if (project == null && LoadingState.COMPONENTS_LOADED.isOccurred()) { - //noinspection deprecation - project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext()); - } - - myProject = project; - - window = windowManager.suggestParentWindow(project); - if (window == null) { - Window focusedWindow = windowManager.getMostRecentFocusedWindow(); - if (focusedWindow instanceof IdeFrameImpl) { - window = focusedWindow; + if (LoadingState.COMPONENTS_LOADED.isOccurred()) { + WindowManagerEx windowManager = getWindowManager(); + if (windowManager != null) { + if (project == null && LoadingState.COMPONENTS_LOADED.isOccurred()) { + //noinspection deprecation + project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext()); } - } - if (window == null) { - for (ProjectFrameHelper frameHelper : windowManager.getProjectFrameHelpers()) { - IdeFrameImpl frame = frameHelper.getFrame(); - if (frame.isActive()) { - window = frameHelper.getFrame(); - break; + + myProject = project; + + window = windowManager.suggestParentWindow(project); + if (window == null) { + Window focusedWindow = windowManager.getMostRecentFocusedWindow(); + if (focusedWindow instanceof IdeFrameImpl) { + window = focusedWindow; + } + } + if (window == null) { + for (ProjectFrameHelper frameHelper : windowManager.getProjectFrameHelpers()) { + IdeFrameImpl frame = frameHelper.getFrame(); + if (frame.isActive()) { + window = frameHelper.getFrame(); + break; + } } } } @@ -152,7 +160,10 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { myCanBeParent = headless || canBeParent; } - protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, Window owner, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType) { + protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, + Window owner, + boolean canBeParent, + DialogWrapper.IdeModalityType ideModalityType) { boolean headless = isHeadlessEnv(); myWrapper = wrapper; myDialog = createDialog(headless, owner, wrapper, null, DialogWrapper.IdeModalityType.IDE); @@ -168,12 +179,8 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { } private static WindowManagerEx getWindowManager() { - WindowManagerEx windowManager = null; - Application application = LoadingState.CONFIGURATION_STORE_INITIALIZED.isOccurred() ? ApplicationManager.getApplication() : null; - if (application != null) { - windowManager = WindowManagerEx.getInstanceEx(); - } - return windowManager; + Application app = LoadingState.COMPONENTS_LOADED.isOccurred() ? ApplicationManager.getApplication() : null; + return app == null ? null : WindowManagerEx.getInstanceEx(); } private static AbstractDialog createDialog(boolean headless, @@ -403,10 +410,9 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { ((CustomFrameDialogContent)contentPane).updateLayout(); } - Application application = ApplicationManager.getApplication(); - if (application != null && application.getServiceIfCreated(ActionManager.class) != null) { - ShortcutSet shortcutSet = ActionUtil.getShortcutSet(IdeActions.ACTION_EDITOR_ESCAPE); - anCancelAction.registerCustomShortcutSet(shortcutSet, rootPane); + Application app = LoadingState.COMPONENTS_LOADED.isOccurred() ? ApplicationManager.getApplication() : null; + if (app != null && app.getServiceIfCreated(ActionManager.class) != null) { + anCancelAction.registerCustomShortcutSet(ActionUtil.getShortcutSet(IdeActions.ACTION_EDITOR_ESCAPE), rootPane); } else { anCancelAction.registerCustomShortcutSet(CommonShortcuts.ESCAPE, rootPane); @@ -414,25 +420,24 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { myDisposeActions.add(() -> anCancelAction.unregisterCustomShortcutSet(rootPane)); - if (!myCanBeParent) { + if (app != null && !myCanBeParent) { WindowManagerEx windowManager = getWindowManager(); if (windowManager != null) { windowManager.doNotSuggestAsParent(myDialog.getWindow()); } } - final CommandProcessorEx commandProcessor = - application != null ? (CommandProcessorEx)CommandProcessor.getInstance() : null; - final boolean appStarted = commandProcessor != null; + CommandProcessorEx commandProcessor = app == null ? null : (CommandProcessorEx)CommandProcessor.getInstance(); + boolean appStarted = commandProcessor != null; boolean changeModalityState = appStarted && myDialog.isModal() && !isProgressDialog(); // ProgressWindow starts a modality state itself Project project = myProject; - boolean perProjectModality = isPerProjectModality(); + boolean perProjectModality = project != null && isPerProjectModality(); if (changeModalityState) { commandProcessor.enterModal(); - if (perProjectModality && project != null) { + if (perProjectModality) { LaterInvocator.enterModal(project, myDialog.getWindow()); } else { @@ -444,7 +449,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { hidePopupsIfNeeded(); } - if (SystemInfo.isMac) { + if (SystemInfoRt.isMac) { final Disposable tb = TouchbarSupport.showWindowActions(myDialog.getContentPane()); if (tb != null) { myDisposeActions.add(() -> Disposer.dispose(tb)); @@ -487,7 +492,9 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { //hopefully this whole code will go away private void hidePopupsIfNeeded() { - if (!SystemInfo.isMac) return; + if (!SystemInfoRt.isMac) { + return; + } StackingPopupDispatcher.getInstance().hidePersistentPopups(); myDisposeActions.add(() -> StackingPopupDispatcher.getInstance().restorePersistentPopups()); @@ -723,7 +730,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { if (LOG.isDebugEnabled()) { LOG.debug("The initial size after coercing it to be at least the packed size: " + initial); } - if (!SystemInfo.isLinux && Registry.is("ide.dialog.wrapper.resize.by.tables", false)) { + if (!SystemInfoRt.isLinux && Registry.is("ide.dialog.wrapper.resize.by.tables", false)) { // [kb] temporary workaround for IDEA-253643 maximize(initial, getSizeForTableContainer(getContentPane())); } @@ -812,7 +819,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { wrapper.beforeShowCallback(); } - if (!SystemInfo.isMac || !WindowRoundedCornersManager.isAvailable()) { + if (!SystemInfoRt.isMac || !WindowRoundedCornersManager.isAvailable()) { setBackground(UIUtil.getPanelBackground()); } if (LOG.isDebugEnabled()) { @@ -929,7 +936,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { @Override public void paint(Graphics g) { - if (!SystemInfo.isMac) { // avoid rendering problems with non-aqua (alloy) LaFs under mac + if (!SystemInfoRt.isMac) { // avoid rendering problems with non-aqua (alloy) LaFs under mac // actually, it's a bad idea to globally enable this for dialog graphics since renderers, for example, may not // inherit graphics so rendering hints won't be applied and trees or lists may render ugly. UISettings.setupAntialiasing(g); @@ -1140,7 +1147,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { } private static @Nullable RegistryManager getRegistryManager() { - Application application = ApplicationManager.getApplication(); - return application != null ? application.getServiceIfCreated(RegistryManager.class) : null; + Application app = LoadingState.COMPONENTS_LOADED.isOccurred() ? ApplicationManager.getApplication() : null; + return app == null ? null : app.getServiceIfCreated(RegistryManager.class); } }