DesktopStateDriver.kt 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package org.mjdev.desktop.state
  2. import androidx.compose.runtime.Composable
  3. import androidx.compose.runtime.DisposableEffect
  4. import androidx.compose.runtime.rememberCoroutineScope
  5. import org.mjdev.desktop.helpers.keyevents.GlobalKeyListener
  6. import org.mjdev.desktop.helpers.mouseevents.CompositorMouseSource
  7. import org.mjdev.desktop.helpers.mouseevents.GlobalClickListener
  8. import org.mjdev.desktop.helpers.mouseevents.GlobalMouseListener
  9. import java.awt.event.KeyEvent
  10. /**
  11. * Feeds raw global input into [DesktopState]: pointer moves (compositor feed when running, AWT
  12. * polling otherwise), clicks (for dismiss-on-click-outside), and Escape. One place wires the
  13. * whole desktop's input, replacing the per-window global handlers that used to fight each other.
  14. */
  15. @Suppress("FunctionName")
  16. @Composable
  17. fun DesktopStateDriver(desktopState: DesktopState) {
  18. val scope = rememberCoroutineScope()
  19. DisposableEffect(desktopState) {
  20. // pointer: prefer the compositor's reliable feed, fall back to AWT global polling
  21. val ipc = CompositorMouseSource.connect(scope) { p -> desktopState.onPointerMove(p.x, p.y) }
  22. val awtPointer =
  23. if (ipc == null) {
  24. GlobalMouseListener(scope = scope) { p -> desktopState.onPointerMove(p.x, p.y) }
  25. } else {
  26. null
  27. }
  28. val clicks = GlobalClickListener { x, y, _ -> desktopState.onClick(x, y) }
  29. val keys =
  30. GlobalKeyListener { event ->
  31. if (event.id != KeyEvent.KEY_RELEASED) return@GlobalKeyListener
  32. when (event.keyCode) {
  33. // Escape closes whatever is open (menu or control center); the bar stays if
  34. // nothing overlaps it — DesktopPolicy works that out.
  35. KeyEvent.VK_ESCAPE -> desktopState.onEscape()
  36. // Super / Menu key toggles the apps menu: opening it also closes the control
  37. // center and keeps the bar visible.
  38. KeyEvent.VK_WINDOWS, KeyEvent.VK_CONTEXT_MENU -> desktopState.toggleMenu()
  39. }
  40. }
  41. onDispose {
  42. ipc?.dispose()
  43. awtPointer?.dispose()
  44. clicks.dispose()
  45. keys.dispose()
  46. }
  47. }
  48. }