Skip to content

Commit 04ce71c

Browse files
committed
feat: Improve tray position detection and update Windows binaries
1 parent de7ffc4 commit 04ce71c

File tree

3 files changed

+60
-7
lines changed

3 files changed

+60
-7
lines changed

src/commonMain/kotlin/com/kdroid/composetray/utils/TrayPosition.kt

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ internal object TrayClickTracker {
3030
Collections.synchronizedMap(mutableMapOf())
3131

3232
fun updateClickPosition(x: Int, y: Int) {
33-
val screenSize = Toolkit.getDefaultToolkit().screenSize
33+
val screenSize = getLogicalScreenSize()
3434
val position = convertPositionToCorner(x, y, screenSize.width, screenSize.height)
3535
val pos = TrayClickPosition(x, y, position)
3636
lastClickPosition.set(pos)
3737
runCatching { saveTrayClickPosition(x, y, position) }
3838
}
3939

4040
fun updateClickPosition(instanceId: String, x: Int, y: Int) {
41-
val screenSize = Toolkit.getDefaultToolkit().screenSize
41+
val screenSize = getLogicalScreenSize()
4242
val position = convertPositionToCorner(x, y, screenSize.width, screenSize.height)
4343
val pos = TrayClickPosition(x, y, position)
4444
perInstancePositions[instanceId] = pos
@@ -63,11 +63,38 @@ internal object TrayClickTracker {
6363
fun getLastClickPosition(instanceId: String): TrayClickPosition? = perInstancePositions[instanceId]
6464
}
6565

66-
internal fun convertPositionToCorner(x: Int, y: Int, width: Int, height: Int): TrayPosition = when {
67-
x < width / 2 && y < height / 2 -> TrayPosition.TOP_LEFT
68-
x >= width / 2 && y < height / 2 -> TrayPosition.TOP_RIGHT
69-
x < width / 2 && y >= height / 2 -> TrayPosition.BOTTOM_LEFT
70-
else -> TrayPosition.BOTTOM_RIGHT
66+
/**
67+
* Get logical screen size (DPI-independent on Windows).
68+
* On Windows, Toolkit.getDefaultToolkit().screenSize returns logical coordinates.
69+
*/
70+
private fun getLogicalScreenSize(): java.awt.Dimension {
71+
return Toolkit.getDefaultToolkit().screenSize
72+
}
73+
74+
internal fun convertPositionToCorner(x: Int, y: Int, width: Int, height: Int): TrayPosition {
75+
// Use smarter margins based on typical taskbar/panel size
76+
// 100px from edge = probably within taskbar/panel area
77+
val edgeThreshold = 100
78+
79+
val isNearTop = y < edgeThreshold
80+
val isNearBottom = y > height - edgeThreshold
81+
val isNearLeft = x < edgeThreshold
82+
val isNearRight = x > width - edgeThreshold
83+
84+
return when {
85+
// Strong edge detection first
86+
isNearTop && isNearLeft -> TrayPosition.TOP_LEFT
87+
isNearTop && isNearRight -> TrayPosition.TOP_RIGHT
88+
isNearTop -> TrayPosition.TOP_RIGHT // Default top to right
89+
isNearBottom && isNearLeft -> TrayPosition.BOTTOM_LEFT
90+
isNearBottom && isNearRight -> TrayPosition.BOTTOM_RIGHT
91+
isNearBottom -> TrayPosition.BOTTOM_RIGHT // Default bottom to right
92+
// Fallback: use quadrant-based detection
93+
x >= width / 2 && y < height / 2 -> TrayPosition.TOP_RIGHT
94+
x < width / 2 && y < height / 2 -> TrayPosition.TOP_LEFT
95+
x >= width / 2 -> TrayPosition.BOTTOM_RIGHT
96+
else -> TrayPosition.BOTTOM_LEFT
97+
}
7198
}
7299

73100
private const val PROPERTIES_FILE = "tray_position.properties"
@@ -430,6 +457,32 @@ private fun dpiAwareHalfIconOffset(): Int {
430457
}
431458
}
432459

460+
/**
461+
* Detects the Windows taskbar height based on DPI scaling.
462+
* Default taskbar: 40px at 100%, 48px at 125%, 60px at 150%, etc.
463+
*/
464+
private fun getWindowsTaskbarHeight(): Int {
465+
return try {
466+
val dpi = Toolkit.getDefaultToolkit().screenResolution
467+
val scale = dpi / 96.0
468+
// Taskbar default height: 40px at 100% scaling
469+
(40 * scale).roundToInt().coerceIn(32, 72)
470+
} catch (_: Throwable) {
471+
40
472+
}
473+
}
474+
475+
/**
476+
* Gets the appropriate bar size (taskbar/menubar/panel) for the current OS.
477+
*/
478+
private fun getSystemBarSize(): Int {
479+
return when (getOperatingSystem()) {
480+
OperatingSystem.WINDOWS -> getWindowsTaskbarHeight()
481+
OperatingSystem.MACOS -> 25 // macOS menu bar
482+
else -> 28 // Linux panel (GNOME/KDE average)
483+
}
484+
}
485+
433486
internal fun isPointWithinMacStatusItem(px: Int, py: Int): Boolean {
434487
if (getOperatingSystem() != OperatingSystem.MACOS) return false
435488
val (ix, iy) = getStatusItemXYForMac()
1 KB
Binary file not shown.
0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)