mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-10 16:02:25 +01:00
This is to fix the drawing after coming back from the media menu to the navigtion app. For organic maps the change from yesterday was fine. For flitsmeister it freezes the screen.
This commit is contained in:
1 parent
5f557a5973
commit
fbaeb0cc57
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