diff --git a/desktop/src/com/unciv/app/desktop/DesktopDisplay.kt b/desktop/src/com/unciv/app/desktop/DesktopDisplay.kt index 9c506a505e..27cc6c0301 100644 --- a/desktop/src/com/unciv/app/desktop/DesktopDisplay.kt +++ b/desktop/src/com/unciv/app/desktop/DesktopDisplay.kt @@ -1,6 +1,7 @@ package com.unciv.app.desktop import com.badlogic.gdx.Gdx +import com.badlogic.gdx.Graphics.Monitor import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics @@ -8,7 +9,11 @@ import com.unciv.models.metadata.GameSettings import com.unciv.models.translations.tr import com.unciv.utils.PlatformDisplay import com.unciv.utils.ScreenMode +import java.awt.GraphicsConfiguration +import java.awt.GraphicsDevice import java.awt.GraphicsEnvironment +import java.awt.Toolkit +import kotlin.math.roundToInt enum class DesktopScreenMode : ScreenMode { @@ -49,8 +54,8 @@ enum class DesktopScreenMode : ScreenMode { protected fun setWindowedMode(settings: GameSettings): Boolean { // Calling AWT after Gdx is fully initialized seems icky, but seems to have no side effects // Found no equivalent in Gdx - available _desktop_ surface without taskbars etc - val graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment() - val maximumWindowBounds = graphicsEnvironment.maximumWindowBounds + // *for the primary monitor* - no saving window sizes that span over several monitors + val maximumWindowBounds = getMaximumWindowBounds() // Make sure an inappropriate saved size doesn't make the window unusable val width = settings.windowState.width.coerceIn(120, maximumWindowBounds.width) @@ -71,6 +76,49 @@ enum class DesktopScreenMode : ScreenMode { operator fun get(id: Int) = values()[id] private fun getWindow() = (Gdx.graphics as? Lwjgl3Graphics)?.window + + /** Replacement for buggy `GraphicsEnvironment.maximumWindowBounds` */ + // Notes: maximumWindowBounds seems to scale by the High DPI setting on Windows, + // and it always uses the default device. GraphicsConfiguration.getBounds() delivers x/y + // as true pixels, while width/height are similarly scaled. Toolkit.getScreenInsets + // delivers scaled values (observed - no documentation found). + internal fun getMaximumWindowBounds( + monitor: Monitor = Lwjgl3ApplicationConfiguration.getPrimaryMonitor() + ): java.awt.Rectangle { + // Identify AWT equivalent to Gdx monitor + val graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment() + for (device in graphicsEnvironment.screenDevices) { + for (config in device.configurations) { + val bounds = config.bounds + if (bounds.x == monitor.virtualX && bounds.y == monitor.virtualY) + return getMaximumWindowBounds(device, config, bounds) + } + } + // Fallback should that fail (this is without insets) + val mode = Lwjgl3ApplicationConfiguration.getDisplayMode(monitor) + return java.awt.Rectangle(monitor.virtualX, monitor.virtualY, mode.width, mode.height) + } + + private fun getMaximumWindowBounds( + device: GraphicsDevice, + config: GraphicsConfiguration, + bounds: java.awt.Rectangle + ): java.awt.Rectangle { + val displayWidth = device.displayMode.width + val displayHeight = device.displayMode.height + val scalePercent = (displayWidth.toDouble() / bounds.width * 100).roundToInt() * 0.01 + val insets = Toolkit.getDefaultToolkit().getScreenInsets(config) + val unscaledInsetLeft = (insets.left * scalePercent).roundToInt() + val unscaledInsetRight = (insets.right * scalePercent).roundToInt() + val unscaledInsetTop = (insets.top * scalePercent).roundToInt() + val unscaledInsetBottom = (insets.bottom * scalePercent).roundToInt() + return java.awt.Rectangle( + bounds.x + unscaledInsetLeft, + bounds.y + unscaledInsetTop, + displayWidth - unscaledInsetLeft - unscaledInsetRight, + displayHeight - unscaledInsetTop - unscaledInsetBottom + ) + } } } diff --git a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt index e3f9171899..57af05ef9d 100644 --- a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt +++ b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt @@ -4,6 +4,7 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.glutils.HdpiMode +import com.unciv.app.desktop.DesktopScreenMode.Companion.getMaximumWindowBounds import com.unciv.json.json import com.unciv.logic.files.SETTINGS_FILE_NAME import com.unciv.logic.files.UncivFiles @@ -13,7 +14,6 @@ import com.unciv.ui.components.Fonts import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.utils.Display import com.unciv.utils.Log -import java.awt.GraphicsEnvironment import kotlin.math.max internal object DesktopLauncher { @@ -59,8 +59,7 @@ internal object DesktopLauncher { if (settings.isFreshlyCreated) { settings.screenSize = ScreenSize.Large // By default we guess that Desktops have larger screens // LibGDX not yet configured, use regular java class - val graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment() - val maximumWindowBounds = graphicsEnvironment.maximumWindowBounds + val maximumWindowBounds = getMaximumWindowBounds() settings.windowState = WindowState( width = maximumWindowBounds.width, height = maximumWindowBounds.height