Desktop: make Ctrl+-/= zoom actually work
Two compounding bugs: 1. Nodes skipped in a plain recomposition kept their old captured density, so changing the zoom state left the tree unscaled — wrap the CompositionLocalProvider in key(zoom) to force full-tree recompose. 2. Compose focus routing missed the shortcut depending on which child held focus — add an AWT KeyboardFocusManager dispatcher below Compose (also accepts Ctrl+Up/Down, numpad +/-, Ctrl+0 reset). User-confirmed zooming works on the live app.
This commit is contained in:
parent
b45e9ff216
commit
5859a082d2
1 changed files with 44 additions and 2 deletions
|
|
@ -5,7 +5,9 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -35,6 +37,41 @@ fun main() = application {
|
|||
val screen by state.screen.collectAsState()
|
||||
// Ctrl+= / Ctrl+- zoom the whole app; Ctrl+0 resets (after a zoom).
|
||||
var zoom by remember { mutableStateOf(1f) }
|
||||
// Belt-and-braces: Compose's focus routing can miss shortcuts depending
|
||||
// on which child holds focus, so also hook the AWT key pipeline directly.
|
||||
// Debug print lets us confirm from the dev log whether keys reach the JVM.
|
||||
DisposableEffect(Unit) {
|
||||
val mgr = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
val disp = java.awt.KeyEventDispatcher { e ->
|
||||
if (e.id == java.awt.event.KeyEvent.KEY_PRESSED &&
|
||||
e.modifiers == java.awt.event.KeyEvent.CTRL_MASK
|
||||
) {
|
||||
when (e.keyCode) {
|
||||
java.awt.event.KeyEvent.VK_EQUALS,
|
||||
java.awt.event.KeyEvent.VK_PLUS,
|
||||
java.awt.event.KeyEvent.VK_ADD,
|
||||
java.awt.event.KeyEvent.VK_UP -> {
|
||||
zoom = (zoom * 1.1f).coerceAtMost(3f)
|
||||
System.err.println("[zoom] ${zoom}"); true
|
||||
}
|
||||
java.awt.event.KeyEvent.VK_MINUS,
|
||||
java.awt.event.KeyEvent.VK_SUBTRACT,
|
||||
java.awt.event.KeyEvent.VK_DOWN -> {
|
||||
zoom = (zoom / 1.1f).coerceAtLeast(0.4f)
|
||||
System.err.println("[zoom] ${zoom}"); true
|
||||
}
|
||||
java.awt.event.KeyEvent.VK_0,
|
||||
java.awt.event.KeyEvent.VK_NUMPAD0 -> {
|
||||
if (zoom != 1f) { zoom = 1f; System.err.println("[zoom] reset"); true }
|
||||
else false
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
} else false
|
||||
}
|
||||
mgr.addKeyEventDispatcher(disp)
|
||||
onDispose { mgr.removeKeyEventDispatcher(disp) }
|
||||
}
|
||||
Window(
|
||||
onCloseRequest = ::exitApplication,
|
||||
title = "SHONAR Desktop" + run {
|
||||
|
|
@ -56,10 +93,10 @@ fun main() = application {
|
|||
Modifier.fillMaxSize().onPreviewKeyEvent { e ->
|
||||
if (e.type != KeyEventType.KeyDown || !e.isCtrlPressed) return@onPreviewKeyEvent false
|
||||
when (e.key) {
|
||||
Key.Equals, Key.Plus, Key.NumPadAdd -> {
|
||||
Key.Equals, Key.Plus, Key.NumPadAdd, Key.DirectionUp -> {
|
||||
zoom = (zoom * 1.1f).coerceAtMost(3f); true
|
||||
}
|
||||
Key.Minus, Key.NumPadSubtract -> {
|
||||
Key.Minus, Key.NumPadSubtract, Key.DirectionDown -> {
|
||||
zoom = (zoom / 1.1f).coerceAtLeast(0.4f); true
|
||||
}
|
||||
Key.Zero, Key.NumPad0 -> {
|
||||
|
|
@ -69,6 +106,10 @@ fun main() = application {
|
|||
}
|
||||
},
|
||||
) {
|
||||
// key(zoom) forces the whole tree to recompose when zoom
|
||||
// changes: nodes skipped in a plain recomposition keep their
|
||||
// old captured density, which made Ctrl+-/= a no-op.
|
||||
key(zoom) {
|
||||
CompositionLocalProvider(
|
||||
LocalDensity provides ScaledDensity(baseDensity, zoom),
|
||||
) {
|
||||
|
|
@ -84,4 +125,5 @@ fun main() = application {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue