mirror of
https://github.com/jlengrand/compose-multiplatform.git
synced 2026-03-10 08:11:20 +00:00
Set NSSupportsAutomaticGraphicsSwitching in native Mac distributions by default
Resolves #545
This commit is contained in:
committed by
Alexey Tsvetkov
parent
da8a6a44a0
commit
826f130b99
@@ -91,12 +91,29 @@ internal fun Project.configurePackagingTasks(apps: Collection<Application>) {
|
||||
destinationDir.set(project.layout.buildDirectory.dir("compose/tmp/${app.name}/runtime"))
|
||||
}
|
||||
|
||||
val createDistributable = tasks.composeTask<AbstractJPackageTask>(
|
||||
taskName("createDistributable", app),
|
||||
args = listOf(TargetFormat.AppImage)
|
||||
) {
|
||||
configurePackagingTask(app, createRuntimeImage = createRuntimeImage)
|
||||
}
|
||||
|
||||
val packageFormats = app.nativeDistributions.targetFormats.map { targetFormat ->
|
||||
val packageFormat = tasks.composeTask<AbstractJPackageTask>(
|
||||
taskName("package", app, targetFormat.name),
|
||||
args = listOf(targetFormat)
|
||||
) {
|
||||
configurePackagingTask(app, createRuntimeImage = createRuntimeImage)
|
||||
// On Mac we want to patch bundled Info.plist file,
|
||||
// so we create an app image, change its Info.plist,
|
||||
// then create an installer based on the app image.
|
||||
// We could create an installer the same way on other platforms, but
|
||||
// in some cases there are failures with JDK 15.
|
||||
// See [AbstractJPackageTask.patchInfoPlistIfNeeded]
|
||||
if (currentOS != OS.MacOS) {
|
||||
configurePackagingTask(app, createRuntimeImage = createRuntimeImage)
|
||||
} else {
|
||||
configurePackagingTask(app, createAppImage = createDistributable)
|
||||
}
|
||||
}
|
||||
|
||||
if (targetFormat.isCompatibleWith(OS.MacOS)) {
|
||||
@@ -130,13 +147,6 @@ internal fun Project.configurePackagingTasks(apps: Collection<Application>) {
|
||||
configurePackageUberJarForCurrentOS(app)
|
||||
}
|
||||
|
||||
val createDistributable = tasks.composeTask<AbstractJPackageTask>(
|
||||
taskName("createDistributable", app),
|
||||
args = listOf(TargetFormat.AppImage)
|
||||
) {
|
||||
configurePackagingTask(app, createRuntimeImage = createRuntimeImage)
|
||||
}
|
||||
|
||||
val runDistributable = project.tasks.composeTask<AbstractRunDistributableTask>(
|
||||
taskName("runDistributable", app),
|
||||
args = listOf(createDistributable)
|
||||
|
||||
@@ -356,10 +356,49 @@ abstract class AbstractJPackageTask @Inject constructor(
|
||||
|
||||
override fun checkResult(result: ExecResult) {
|
||||
super.checkResult(result)
|
||||
patchInfoPlistIfNeeded()
|
||||
val outputFile = findOutputFileOrDir(destinationDir.ioFile, targetFormat)
|
||||
logger.lifecycle("The distribution is written to ${outputFile.canonicalPath}")
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/JetBrains/compose-jb/issues/545
|
||||
*
|
||||
* Patching Info.plist is necessary to avoid duplicating and supporting
|
||||
* properties set by jpackage.
|
||||
*
|
||||
* Info.plist is patched only on macOS for app image.
|
||||
* Packaged installers receive patched Info.plist through
|
||||
* prebuilt [appImage].
|
||||
*/
|
||||
private fun patchInfoPlistIfNeeded() {
|
||||
if (currentOS != OS.MacOS || targetFormat != TargetFormat.AppImage) return
|
||||
|
||||
val infoPlist = destinationDir.ioFile.resolve("${packageName.get()}.app/Contents/Info.plist")
|
||||
if (!infoPlist.exists()) return
|
||||
|
||||
val content = infoPlist.readText()
|
||||
val nsSupportsAutomaticGraphicsSwitching = "<key>NSSupportsAutomaticGraphicsSwitching</key>"
|
||||
val stringToAppend = "$nsSupportsAutomaticGraphicsSwitching<true/>"
|
||||
if (content.indexOf(nsSupportsAutomaticGraphicsSwitching) >= 0) return
|
||||
|
||||
/**
|
||||
* Dirty hack: to avoid parsing plist file, let's find known expected key substring,
|
||||
* and insert the necessary keys before it.
|
||||
*/
|
||||
val knownExpectedKey = "<key>NSHighResolutionCapable</key>"
|
||||
val i = content.indexOf(knownExpectedKey)
|
||||
if (i >= 0) {
|
||||
val newContent = buildString {
|
||||
append(content.substring(0, i))
|
||||
appendln(stringToAppend)
|
||||
append(" ")
|
||||
appendln(content.substring(i, content.length))
|
||||
}
|
||||
infoPlist.writeText(newContent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun initState() {
|
||||
val mappingFile = libsMappingFile.ioFile
|
||||
if (mappingFile.exists()) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.compose.test.*
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assumptions
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.nio.charset.Charset
|
||||
import java.util.jar.JarFile
|
||||
|
||||
class DesktopApplicationTest : GradlePluginTestBase() {
|
||||
@@ -150,6 +151,9 @@ class DesktopApplicationTest : GradlePluginTestBase() {
|
||||
gradle(":runDistributable").build().checks { check ->
|
||||
check.taskOutcome(":runDistributable", TaskOutcome.SUCCESS)
|
||||
check.logContains("Hello, from Mac OS!")
|
||||
val appDir = testWorkDir.resolve("build/compose/binaries/main/app/TestPackage.app/Contents/")
|
||||
val infoPlist = appDir.resolve("Info.plist").checkExists().checkExists()
|
||||
infoPlist.readText().checkContains("<key>NSSupportsAutomaticGraphicsSwitching</key><true/>")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,12 +39,8 @@ internal class BuildResultChecks(private val result: BuildResult) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BuildResult.checkOutputLogContains(substring: String) {
|
||||
if (output.contains(substring)) return
|
||||
|
||||
println("Test output:")
|
||||
output.lineSequence().forEach {
|
||||
println(" > $it")
|
||||
internal fun String.checkContains(substring: String) {
|
||||
if (!contains(substring)) {
|
||||
throw AssertionError("String '$substring' is not found in text:\n$this")
|
||||
}
|
||||
throw AssertionError("Test output does not contain the expected string: '$substring'")
|
||||
}
|
||||
Reference in New Issue
Block a user