mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[rdct] IJPL-171305. Add check for closing tabbed project view in closeWindow API
- Remote Development has a special handlers for the case when all projects are closed to ask a user if they need to shut down a backend process. On macOS when tabbed project view feature is enabled, we need to separate cases when projects are closed via tab or application process close. We need it to keep all opened projects open if a user declines the operation in the confirmation dialog. Updated check in windowClosing() API to support check for tabbed project view; - Add tests to verify macOS tabbed project view cases. (cherry picked from commit 826fb0605b47f89ee9c43315deb99b615daa12b7) IJ-CR-154038 GitOrigin-RevId: 56f092de57486d566d5fb6f76f541c993c09b8f3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4efd15a0ca
commit
ce99bf0c1d
+38
-4
@@ -13,10 +13,15 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame
|
||||
import com.intellij.ui.mac.MergeAllWindowsAction
|
||||
import com.intellij.ui.mac.WindowTabsComponent
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.intellij.util.SystemProperties
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
open class CloseProjectWindowHelper {
|
||||
companion object {
|
||||
@@ -33,16 +38,44 @@ open class CloseProjectWindowHelper {
|
||||
protected open val isShowWelcomeScreenFromSettings: Boolean
|
||||
get() = GeneralSettings.getInstance().isShowWelcomeScreen
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected open fun couldReturnToWelcomeScreen(projects: Array<Project>): Boolean {
|
||||
return projects.any { project -> couldReturnToWelcomeScreen(project) }
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected open fun isMacOsTabbedProjectView(project: Project?): Boolean {
|
||||
if (!SystemInfo.isMac) {
|
||||
return false
|
||||
}
|
||||
val projectFrame = WindowManager.getInstance().getFrame(project) ?: return false
|
||||
return MergeAllWindowsAction.isTabbedWindow(projectFrame)
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected open fun isCloseTab(project: Project?): Boolean {
|
||||
project ?: return false
|
||||
|
||||
val frame = WindowManager.getInstance().getFrame(project) ?: return false
|
||||
return frame.rootPane.getClientProperty(WindowTabsComponent.CLOSE_TAB_KEY) == true
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
open fun windowClosing(project: Project?) {
|
||||
WriteIntentReadAction.run {
|
||||
|
||||
val numberOfOpenedProjects = getNumberOfOpenedProjects()
|
||||
val isMacOsTabbedProjectView = isMacOsTabbedProjectView(project)
|
||||
|
||||
// Exit on Linux and Windows if the only opened project frame is closed.
|
||||
// On macOS behaviour is different - to exit app, quit action should be used, otherwise welcome frame is shown.
|
||||
// If welcome screen is disabled, behaviour on all OS is the same.
|
||||
if (numberOfOpenedProjects > 1 ||
|
||||
// On macOS behavior is different - to exit app, quit action should be used, otherwise welcome frame is shown.
|
||||
// If the Welcome screen is disabled, behavior on all OS is the same.
|
||||
if (!isMacOsTabbedProjectView && numberOfOpenedProjects > 1 ||
|
||||
isMacOsTabbedProjectView && isCloseTab(project) ||
|
||||
isMacOsTabbedProjectView && couldReturnToWelcomeScreen(projects = WindowManager.getInstance().allProjectFrames.mapNotNull { it.project }.toTypedArray()) ||
|
||||
serviceIfCreated<LightEditService>()?.project != null ||
|
||||
(numberOfOpenedProjects == 1 && couldReturnToWelcomeScreen(project))) {
|
||||
(numberOfOpenedProjects == 1 && couldReturnToWelcomeScreen(project))
|
||||
) {
|
||||
closeProjectAndShowWelcomeFrameIfNoProjectOpened(project)
|
||||
}
|
||||
else {
|
||||
@@ -74,4 +107,5 @@ open class CloseProjectWindowHelper {
|
||||
return project?.let { SHOW_WELCOME_FRAME_FOR_PROJECT.get(project) }
|
||||
?: (isShowWelcomeScreen && !PlatformUtils.isDataSpell() && !PlatformUtils.isDataGrip())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -59,6 +59,7 @@ import java.util.*;
|
||||
@ApiStatus.Internal
|
||||
public final class WindowTabsComponent extends JBTabsImpl {
|
||||
private static final String TITLE_LISTENER_KEY = "TitleListener";
|
||||
public static final String CLOSE_TAB_KEY = "CloseTab";
|
||||
|
||||
private static final int TAB_HEIGHT = 30;
|
||||
|
||||
@@ -506,6 +507,7 @@ public final class WindowTabsComponent extends JBTabsImpl {
|
||||
}
|
||||
|
||||
private static void closeTab(@NotNull IdeFrameImpl tabFrame, boolean closeOthers) {
|
||||
tabFrame.getRootPane().putClientProperty(CLOSE_TAB_KEY, Boolean.TRUE);
|
||||
Foundation.executeOnMainThread(true, false, () -> {
|
||||
ID window = MacUtil.getWindowFromJavaWindow(tabFrame);
|
||||
Foundation.invoke(window, closeOthers ? "performCloseOtherTabs:" : "performClose:", ID.NIL);
|
||||
|
||||
@@ -3,10 +3,19 @@ package com.intellij.wm
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.wm.impl.CloseProjectWindowHelper
|
||||
import com.intellij.testFramework.ProjectRule
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Test
|
||||
|
||||
class CloseProjectWindowHelperTest {
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
@ClassRule
|
||||
val projectRule = ProjectRule()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on Windows closing last project leads to exit`() {
|
||||
val helper = object : TestCloseProjectWindowHelper() {
|
||||
@@ -33,7 +42,7 @@ class CloseProjectWindowHelperTest {
|
||||
assertThat(helper.wasShowWelcomeFrameIfNoProjectOpenedCalled).isTrue()
|
||||
}
|
||||
|
||||
// well, not clear is listener will be called for case when no opened projects atl all, but just t o be sure
|
||||
// well, not clear is listener will be called for the case when no opened projects at all, but just to be sure
|
||||
@Test
|
||||
fun `on Windows closing if no opened projects leads to exit`() {
|
||||
val helper = object : TestCloseProjectWindowHelper() {
|
||||
@@ -59,6 +68,51 @@ class CloseProjectWindowHelperTest {
|
||||
assertThat(helper.wasQuitAppCalled).isTrue()
|
||||
assertThat(helper.wasShowWelcomeFrameIfNoProjectOpenedCalled).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on macOS closing a tab with tabbed project view`() {
|
||||
val helper = object : TestCloseProjectWindowHelper() {
|
||||
override val isMacSystemMenu = true
|
||||
|
||||
override fun isMacOsTabbedProjectView(project: Project?): Boolean = true
|
||||
override fun isCloseTab(project: Project?): Boolean = true
|
||||
override fun couldReturnToWelcomeScreen(projects: Array<Project>): Boolean = false
|
||||
}
|
||||
|
||||
helper.windowClosing(null)
|
||||
assertThat(helper.wasQuitAppCalled).isFalse()
|
||||
assertThat(helper.wasShowWelcomeFrameIfNoProjectOpenedCalled).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on macOS closing an application with tabbed project view when should show welcome screen`() {
|
||||
val helper = object : TestCloseProjectWindowHelper() {
|
||||
override val isMacSystemMenu = true
|
||||
|
||||
override fun isMacOsTabbedProjectView(project: Project?): Boolean = true
|
||||
override fun isCloseTab(project: Project?): Boolean = false
|
||||
override fun couldReturnToWelcomeScreen(projects: Array<Project>): Boolean = true
|
||||
}
|
||||
|
||||
helper.windowClosing(null)
|
||||
assertThat(helper.wasQuitAppCalled).isFalse()
|
||||
assertThat(helper.wasShowWelcomeFrameIfNoProjectOpenedCalled).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on macOS closing an application with tabbed project view when should not show welcome screen`() {
|
||||
val helper = object : TestCloseProjectWindowHelper() {
|
||||
override val isMacSystemMenu = true
|
||||
|
||||
override fun isMacOsTabbedProjectView(project: Project?): Boolean = true
|
||||
override fun isCloseTab(project: Project?): Boolean = false
|
||||
override fun couldReturnToWelcomeScreen(projects: Array<Project>): Boolean = false
|
||||
}
|
||||
|
||||
helper.windowClosing(null)
|
||||
assertThat(helper.wasQuitAppCalled).isTrue()
|
||||
assertThat(helper.wasShowWelcomeFrameIfNoProjectOpenedCalled).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
open class TestCloseProjectWindowHelper : CloseProjectWindowHelper() {
|
||||
|
||||
Reference in New Issue
Block a user