Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to change opacity for compose view #1022

Merged
merged 7 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,9 @@ internal class UIViewComposeSceneLayer(
}

private fun createSkikoUIView(renderDelegate: RenderingUIView.Delegate): RenderingUIView =
RenderingUIView(
renderDelegate = renderDelegate,
transparency = true,
)
RenderingUIView(renderDelegate = renderDelegate).apply {
opaque = false
}

private fun createComposeScene(
invalidate: () -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ class ComposeUIViewControllerConfiguration {

@ExperimentalComposeApi
var platformLayers: Boolean = true

/**
* Determines whether the Compose view should have an opaque background.
* Warning: disabling opaque layer may affect performance.
*/
@ExperimentalComposeApi
var opaque: Boolean = true
MatkovIvan marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,12 @@ internal class ComposeContainer(
}
}

@OptIn(ExperimentalComposeApi::class)
override fun loadView() {
view = UIView().apply {
backgroundColor = UIColor.whiteColor
setClipsToBounds(true)
opaque = configuration.opaque
backgroundColor = if (configuration.opaque) UIColor.whiteColor else UIColor.clearColor
} // rootView needs to interop with UIKit
}

Expand Down Expand Up @@ -273,11 +275,11 @@ internal class ComposeContainer(
fun createComposeSceneContext(platformContext: PlatformContext): ComposeSceneContext =
ComposeSceneContextImpl(platformContext)

@OptIn(ExperimentalComposeApi::class)
private fun createSkikoUIView(renderRelegate: RenderingUIView.Delegate): RenderingUIView =
RenderingUIView(
renderDelegate = renderRelegate,
transparency = false,
)
RenderingUIView(renderDelegate = renderRelegate).apply {
opaque = configuration.opaque
}

@OptIn(ExperimentalComposeApi::class)
private fun createComposeScene(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,7 @@ internal class InflightCommandBuffers(

internal class MetalRedrawer(
private val metalLayer: CAMetalLayer,
private val callbacks: MetalRedrawerCallbacks,
private val transparency: Boolean,
private val callbacks: MetalRedrawerCallbacks
) {
// Workaround for KN compiler bug
// Type mismatch: inferred type is objcnames.protocols.MTLDeviceProtocol but platform.Metal.MTLDeviceProtocol was expected
Expand Down Expand Up @@ -228,6 +227,13 @@ internal class MetalRedrawer(
displayLinkConditions.needsToBeProactive = value
}

var opaque: Boolean = true
set(value) {
field = value

updateLayerOpacity()
}

/**
* `true` if Metal rendering is synchronized with changes of UIKit interop views, `false` otherwise
*/
Expand All @@ -237,10 +243,14 @@ internal class MetalRedrawer(

// If active, make metalLayer transparent, opaque otherwise.
// Rendering into opaque CAMetalLayer allows direct-to-screen optimization.
metalLayer.setOpaque(!value && !transparency)
updateLayerOpacity()
metalLayer.drawsAsynchronously = !value
}

private fun updateLayerOpacity() {
metalLayer.setOpaque(!isInteropActive && opaque)
}

/**
* null after [dispose] call
*/
Expand Down Expand Up @@ -283,6 +293,8 @@ internal class MetalRedrawer(
UIApplication.sharedApplication.applicationState != UIApplicationState.UIApplicationStateBackground

caDisplayLink.addToRunLoop(NSRunLoop.mainRunLoop, NSRunLoopCommonModes)

updateLayerOpacity()
}

fun dispose() {
Expand Down Expand Up @@ -337,7 +349,7 @@ internal class MetalRedrawer(
height.toFloat()
)
).also { canvas ->
canvas.clear(if (transparency) Color.TRANSPARENT else Color.WHITE)
canvas.clear(if (metalLayer.opaque) Color.WHITE else Color.TRANSPARENT)
callbacks.render(canvas, lastRenderTimestamp)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import platform.UIKit.*

internal class RenderingUIView(
private val renderDelegate: Delegate,
private val transparency: Boolean,
) : UIView(
frame = CGRectMake(
x = 0.0,
Expand Down Expand Up @@ -68,13 +67,17 @@ internal class RenderingUIView(

override fun retrieveInteropTransaction(): UIKitInteropTransaction =
renderDelegate.retrieveInteropTransaction()
},
transparency = transparency,
}
)

override fun setOpaque(opaque: Boolean) {
super.setOpaque(opaque)

redrawer.opaque = opaque
}

init {
userInteractionEnabled = false
opaque = !transparency

metalLayer.also {
// Workaround for KN compiler bug
Expand All @@ -87,7 +90,6 @@ internal class RenderingUIView(
it.backgroundColor =
CGColorCreate(CGColorSpaceCreateDeviceRGB(), pinned.addressOf(0))
}
it.setOpaque(!transparency)//todo check if remove
it.framebufferOnly = false
}
}
Expand Down
Loading