Skip to content

Commit 0b9a61e

Browse files
committed
Refactor TrayApp to improve window positioning and visibility handling, ensuring dynamic recalculation and off-screen management for hidden states
1 parent ce7001d commit 0b9a61e

1 file changed

Lines changed: 28 additions & 13 deletions

File tree

  • src/commonMain/kotlin/com/kdroid/composetray/tray/api

src/commonMain/kotlin/com/kdroid/composetray/tray/api/TrayApp.kt

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -468,16 +468,11 @@ fun ApplicationScope.TrayApp(
468468
// Main popup window - always mounted once created to preserve states
469469
// Uses hybrid approach: moves off-screen instead of unmounting
470470
if (windowCreated) {
471-
// Calculate position: off-screen when hidden, correct position when visible
472-
val widthPx = windowSize.width.value.toInt()
473-
val heightPx = windowSize.height.value.toInt()
474-
val windowPosition = if (shouldShowWindow) {
475-
// Visible: use correct position near tray icon
476-
getTrayWindowPositionForInstance(tray.instanceKey(), widthPx, heightPx)
477-
} else {
478-
// Hidden: move far off-screen to avoid taskbar appearance
479-
WindowPosition(-10000.dp, -10000.dp)
480-
}
471+
// Start off-screen
472+
val dialogState = rememberDialogState(
473+
position = WindowPosition(-10000.dp, -10000.dp),
474+
size = windowSize
475+
)
481476

482477
DialogWindow(
483478
onCloseRequest = { requestHide() },
@@ -488,7 +483,7 @@ fun ApplicationScope.TrayApp(
488483
alwaysOnTop = shouldShowWindow, // Only on top when visible
489484
transparent = true,
490485
visible = true, // Always visible to the system
491-
state = rememberDialogState(position = windowPosition, size = windowSize)
486+
state = dialogState
492487
) {
493488
DisposableEffect(Unit) {
494489
// Set window name for monitoring
@@ -542,9 +537,26 @@ fun ApplicationScope.TrayApp(
542537
}
543538
}
544539

545-
// React to visibility changes
546-
LaunchedEffect(shouldShowWindow) {
540+
// React to visibility changes and reposition window
541+
// IMPORTANT: Position is recalculated each time window shows because:
542+
// - The tray icon might have moved (user moved taskbar, changed resolution, etc.)
543+
// - Window size might have changed
544+
LaunchedEffect(shouldShowWindow, windowSize) {
547545
if (shouldShowWindow) {
546+
// Recalculate position when showing (tray icon might have moved)
547+
// or when window size changes
548+
val widthPx = windowSize.width.value.toInt()
549+
val heightPx = windowSize.height.value.toInt()
550+
val newPosition = getTrayWindowPositionForInstance(
551+
tray.instanceKey(),
552+
widthPx,
553+
heightPx
554+
)
555+
dialogState.position = newPosition
556+
557+
// Update size if changed
558+
dialogState.size = windowSize
559+
548560
// Window is becoming visible
549561
runCatching { WindowVisibilityMonitor.recompute() }
550562
invokeLater {
@@ -557,6 +569,9 @@ fun ApplicationScope.TrayApp(
557569
}
558570
}
559571
} else {
572+
// Move window off-screen when hiding
573+
dialogState.position = WindowPosition(-10000.dp, -10000.dp)
574+
560575
// Window is becoming hidden
561576
runCatching { WindowVisibilityMonitor.recompute() }
562577
}

0 commit comments

Comments
 (0)