mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-10 16:02:25 +01:00
Merge pull request #8 from Brian5647/fix-map-freeze
fix the drawing after coming back from the media menu to navigation app
This commit is contained in:
2 files changed
+40
-19
No files matched your search
@@ -83,12 +83,16 @@ fun CarHome() {
|
||||
val navigator = LocalCarNavigator.current
|
||||
val panel = navigator.sidePanel
|
||||
|
||||
// Coming back to the map from another screen: make sure the nav app is drawing into a live
|
||||
// surface. The first composition is skipped, since the surface is only just being lent.
|
||||
// Leaving the map for another screen: hand the nav app a fresh surface while it's covered, so
|
||||
// it has redrawn by the time the map comes back - a new surface shows black until the app's
|
||||
// next frame. Coming back only replaces one that died meanwhile. Nothing happens before Home
|
||||
// has first been shown, since the surface is only just being lent.
|
||||
val onHome = navigator.current == CarScreen.Home
|
||||
val seenHome = remember { booleanArrayOf(false) }
|
||||
LaunchedEffect(onHome) {
|
||||
if (onHome && seenHome[0]) CarServices.nav.refreshSurface()
|
||||
if (seenHome[0]) {
|
||||
if (onHome) CarServices.nav.replaceDeadSurface() else CarServices.nav.renewSurface()
|
||||
}
|
||||
if (onHome) seenHome[0] = true
|
||||
}
|
||||
val splitScreen = phase == CarMedia.Phase.READY && now.isActive && panel != SidePanel.NONE
|
||||
|
||||
@@ -455,31 +455,48 @@ class CarAppConnection(private val context: Context) {
|
||||
|
||||
private val _surfaceEpoch = MutableStateFlow(0)
|
||||
|
||||
/** Bumped when the lent surface turns out to be dead, so the stage builds a fresh one. */
|
||||
/** Bumped to throw the lent surface away, so the stage builds a fresh one. */
|
||||
val surfaceEpoch: StateFlow<Int> = _surfaceEpoch.asStateFlow()
|
||||
|
||||
/**
|
||||
* Lends the app its surface again: called when the map comes back into view. An app that
|
||||
* draws through its own VirtualDisplay (Organic Maps does) can be left pointing at a surface
|
||||
* that has since died, and draws black until it's told about a live one. Taking the surface
|
||||
* back and lending it again repoints it; a surface that has itself died is replaced.
|
||||
* Lends the app a fresh surface: called as the map goes out of view, so the app has redrawn
|
||||
* on the new one by the time it comes back. An app that draws through its own VirtualDisplay
|
||||
* (Organic Maps does) can be left pointing at a surface that has since died, and draws black
|
||||
* until it's told about a live one.
|
||||
*
|
||||
* Always a new surface, never the same one lent again: such an app (Flitsmeister does) builds
|
||||
* its new display on the re-lent surface before releasing the old, and the old one's
|
||||
* disconnect then takes the shared BufferQueue's connection with it - the map freezes on its
|
||||
* last frame for good. The stage's key on [surfaceEpoch] swaps in a new SurfaceView, which
|
||||
* lends itself as it comes up.
|
||||
*/
|
||||
fun refreshSurface() {
|
||||
fun renewSurface() {
|
||||
main.post {
|
||||
val current = lent ?: return@post
|
||||
if (!current.surface.isValid) {
|
||||
GearslipLog.w("host: the lent surface died; building a new one")
|
||||
lent = null
|
||||
sendSurfaceDestroyed(current)
|
||||
_surfaceEpoch.value = _surfaceEpoch.value + 1
|
||||
return@post
|
||||
}
|
||||
GearslipLog.i("host: lending the surface again as the map comes back")
|
||||
sendSurfaceDestroyed(current)
|
||||
sendSurfaceAvailable()
|
||||
GearslipLog.i("host: building a fresh surface as the map goes out of view")
|
||||
replaceSurface(current)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called as the map comes back into view: replaces the surface only if it died while the map
|
||||
* was covered, since a new one shows black until the app's next frame.
|
||||
*/
|
||||
fun replaceDeadSurface() {
|
||||
main.post {
|
||||
val current = lent ?: return@post
|
||||
if (current.surface.isValid) return@post
|
||||
GearslipLog.w("host: the lent surface died; building a new one")
|
||||
replaceSurface(current)
|
||||
}
|
||||
}
|
||||
|
||||
private fun replaceSurface(current: Lent) {
|
||||
lent = null
|
||||
sendSurfaceDestroyed(current)
|
||||
_surfaceEpoch.value = _surfaceEpoch.value + 1
|
||||
}
|
||||
|
||||
private fun sendSurfaceAvailable() {
|
||||
val callback = surfaceCallback ?: return
|
||||
val surface = lent ?: return
|
||||
|
||||
Reference in new issue
Block a user