diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt
index 90fa3b407e4d2cd930ce18ec46b6647eb80cbc1e..310014f37cdae112271a3e432ce9ce1154e2e513 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt
@@ -37,7 +37,6 @@ import androidx.compose.ui.graphics.toAwtImage
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.unit.Density
 import androidx.compose.ui.window.FrameWindowScope
 import androidx.compose.ui.window.Window
 import org.briarproject.bramble.api.event.EventBus
@@ -64,7 +63,6 @@ import org.briarproject.briar.desktop.ui.Screen.MAIN
 import org.briarproject.briar.desktop.ui.Screen.STARTUP
 import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
 import org.briarproject.briar.desktop.utils.UiUtils.DensityDimension
-import org.briarproject.briar.desktop.utils.UiUtils.GlobalDensity
 import org.briarproject.briar.desktop.viewmodel.ViewModelProvider
 import java.awt.event.WindowEvent
 import java.awt.event.WindowFocusListener
@@ -207,13 +205,6 @@ constructor(
                 }
             }
 
-            CompositionLocalProvider(
-                LocalDensity provides Density(configuration.uiScale ?: GlobalDensity),
-            ) {
-                window.minimumSize = DensityDimension(800, 600)
-                window.preferredSize = DensityDimension(800, 600)
-            }
-
             CompositionLocalProvider(
                 LocalWindowScope provides this,
                 LocalWindowFocusState provides focusState,
@@ -228,6 +219,9 @@ constructor(
                     return@CompositionLocalProvider
                 }
 
+                window.minimumSize = DensityDimension(800, 600, configuration)
+                window.preferredSize = DensityDimension(800, 600, configuration)
+
                 val isDarkTheme = configuration.theme == DARK ||
                     (configuration.theme == AUTO && isSystemInDarkTheme())
                 BriarTheme(isDarkTheme, configuration.uiScale) {
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/UiUtils.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/UiUtils.kt
index 800f9fc5ee5e87877182a4367c39d4bdcc8cbd3b..cd88bf24c6910b3bf1d2f0d0db5c7f1e9c60ebd5 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/UiUtils.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/UiUtils.kt
@@ -22,6 +22,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.dp
+import org.briarproject.briar.desktop.settings.Configuration
 import java.awt.Dimension
 import java.awt.GraphicsConfiguration
 import java.awt.GraphicsEnvironment
@@ -31,7 +32,7 @@ object UiUtils {
         if (alias == null) name else "$alias ($name)"
 
     // See androidx.compose.ui.window.LayoutConfiguration
-    internal val GlobalDensity
+    private val GlobalDensity
         get() = GraphicsEnvironment.getLocalGraphicsEnvironment()
             .defaultScreenDevice
             .defaultConfiguration
@@ -53,7 +54,27 @@ object UiUtils {
      */
     @Composable
     fun DensityDimension(width: Int, height: Int): Dimension {
-        with(Density(LocalDensity.current.density / GlobalDensity)) {
+        return DensityDimension(width, height, LocalDensity.current.density)
+    }
+
+    /**
+     * Compute an AWT Dimension for the given width and height in dp units, taking
+     * into account the UI scale factor from the user settings as well as the global
+     * density as detected by the local graphics environment.
+     *
+     * On macOS hidpi devices, the global density is usually something like 2 while on Linux
+     * it is usually 1 independent of the actual density. The global density is taken into
+     * account by AWT itself, so we need to remove that factor from the equation, otherwise
+     * it will be accounted for twice resulting in windows that are bigger than expected.
+     */
+    @Composable
+    fun DensityDimension(width: Int, height: Int, configuration: Configuration): Dimension {
+        return DensityDimension(width, height, configuration.uiScale ?: GlobalDensity)
+    }
+
+    @Composable
+    private fun DensityDimension(width: Int, height: Int, uiScale: Float): Dimension {
+        with(Density(uiScale / GlobalDensity)) {
             return Dimension(width.dp.roundToPx(), height.dp.roundToPx())
         }
     }