Skip to content

Ship real bindings for Xamarin.AndroidX.Compose.UI.Graphics#1438

Open
Copilot wants to merge 4 commits into
mainfrom
copilot/stop-stripping-whole-package
Open

Ship real bindings for Xamarin.AndroidX.Compose.UI.Graphics#1438
Copilot wants to merge 4 commits into
mainfrom
copilot/stop-stripping-whole-package

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jun 3, 2026

Xamarin.AndroidX.Compose.UI.Graphics / .Android shipped Java-library-only, forcing every Compose consumer to type colors as raw packed long and re-implement Kotlin's Color packing by hand. This un-strips the -android recipe so Color, Brush, Shape, Path, ImageBitmap, Outline, Matrix, BlendMode, etc. are bindable.

Changes

  • ui-graphics-android/Transforms/Metadata.xml
    • Dropped <remove-node path="/api/package" />.
    • Added managedName attrs across all 9 graphics packages to force UI casing (androidx.compose.ui.graphicsAndroidX.Compose.UI.Graphics).
    • Targeted <remove-node> for two generation blockers:
      • experimental …graphics.shadow package — its title-cased namespace collides with the existing Shadow spec class (CS0101); kept the class.
      • PathIterator interface — auto-generated Invoker can't satisfy Iterator.next()'s Object return (CS0738).
  • ui-graphics-android/PublicAPI/PublicAPI.Unshipped.txt — regenerated (~1298 lines).
  • AndroidXProject.cshtml — added both Graphics packages to ComposePackagesWithBindings, removing the "C# bindings are not provided" note.
  • published-namespaces.txt — added the 6 new namespaces exposed by the un-stripped binding: AndroidX.Compose.UI.Graphics.Colorspace, .Drawscope, .Internal, .Layer, .Layer.View, and .Painter.
  • config.json — bumped nugetVersion for both Xamarin.AndroidX.Compose.UI.Graphics and Xamarin.AndroidX.Compose.UI.Graphics.Android from 1.11.21.11.2.1.
  • foundation-android/Transforms/Metadata.xml — fixed 24 build errors in foundation-android that only surfaced once UI.Graphics became bindable (the androidx.compose.foundation.shape hierarchy could finally be emitted because IShape/CornerBasedShape are now resolvable). This is purely additive — it surfaces the real RoundedCornerShape, CutCornerShape, AbsoluteRoundedCornerShape, AbsoluteCutCornerShape, and CornerBasedShape bindings (plus factories) that previously couldn't bind at all:
    • CS0111 — Kotlin inline-class (Dp) factory overloads are JVM name-mangled (RoundedCornerShape-0680j_4(F)) and collapse onto the plain RoundedCornerShape(F) overload. Removed the mangled overloads in RoundedCornerShapeKt/CutCornerShapeKt/AbsoluteRoundedCornerShapeKt/AbsoluteCutCornerShapeKt, mirroring the existing CornerSizeKt rule.
    • CS0534CornerBasedShape.copy(…) is abstract returning CornerBasedShape, but each subclass overrides it with a covariant (subclass-typed) return that the generator emits without override. Pinned managedReturn to AndroidX.Compose.Foundation.Shape.CornerBasedShape on each subclass's copy(CornerSize ×4) so the override is recognized.

Notes

  • Inline @JvmInline value class types (Color, Offset, Size, TileMode) surface as raw long/float (issue option 3b), consistent with the existing Compose bindings; no inline-class support assumed. Example shape:

    AndroidX.Compose.UI.Graphics.Shadow.Copy(long color, long offset, float blurRadius) -&gt; AndroidX.Compose.UI.Graphics.Shadow!
    
  • No -jvm/-android KMP duplicate clashes surfaced, so no <AndroidIgnoredJavaDependency> entries were required.

  • The common ui-graphics recipe stays stripped — its KMP AAR has no classes.jar — matching the ui/foundation peer precedent.

  • foundation-android's PublicAPI.Unshipped.txt will gain the new shape-class entries on the next full build; it is a build-generated, non-analyzer-gated file, so CI regenerates it cleanly.

Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
Copilot AI changed the title [WIP] Stop stripping the whole package and ship real bindings Ship real bindings for Xamarin.AndroidX.Compose.UI.Graphics Jun 3, 2026
Copilot AI requested a review from jonathanpeppers June 3, 2026 22:26
@jonathanpeppers jonathanpeppers marked this pull request as ready for review June 3, 2026 22:45
Copilot AI review requested due to automatic review settings June 3, 2026 22:45
@jonathanpeppers
Copy link
Copy Markdown
Member

@copilot do you need to update the namespaces file with cake target?

Also increment version of relevant packages by 0.0.0.1

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request changes the androidx.compose.ui:ui-graphics-android binding from “Java-library-only” to shipping real C# bindings, so Compose consumers can use the graphics API surface (e.g., Brush, Path, ImageBitmap, Outline, Matrix, BlendMode, etc.) via the Xamarin.AndroidX.Compose.UI.Graphics(.Android) NuGets rather than relying on hand-rolled equivalents.

Changes:

  • Enabled binding generation for ui-graphics-android by removing the blanket package strip and adding explicit namespace (managedName) mappings to preserve UI casing.
  • Removed two known generator blockers by stripping the androidx.compose.ui.graphics.shadow package and the PathIterator interface.
  • Updated packaging/template behavior and regenerated PublicAPI.Unshipped.txt to reflect the newly surfaced API.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.

File Description
source/AndroidXProject.cshtml Marks the two UI Graphics NuGets as “real bindings” packages so the “C# bindings are not provided” note is not appended.
source/androidx.compose.ui/ui-graphics-android/Transforms/Metadata.xml Stops stripping the entire API surface; enforces AndroidX.Compose.UI.Graphics* namespaces and removes specific generation blockers.
source/androidx.compose.ui/ui-graphics-android/PublicAPI/PublicAPI.Unshipped.txt Regenerated unshipped public API to include the newly exposed binding surface.

Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 3, 2026

@copilot do you need to update the namespaces file with cake target?

Also increment version of relevant packages by 0.0.0.1

Done in commit Update namespaces and increment ui-graphics versions to 1.11.2.1:

  • published-namespaces.txt — added the 6 new namespaces exposed by the un-stripped binding: Colorspace, Drawscope, Internal, Layer, Layer.View, and Painter (inserted in alphabetical order between AndroidX.Compose.UI.Graphics and AndroidX.Compose.UI.Graphics.Vector). These match the managedName attrs in Metadata.xml and would be picked up by the generate-namespace-file cake target after a build.

  • config.json — bumped nugetVersion for both Xamarin.AndroidX.Compose.UI.Graphics and Xamarin.AndroidX.Compose.UI.Graphics.Android from 1.11.21.11.2.1.

@jonathanpeppers
Copy link
Copy Markdown
Member

@copilot list of errors:

D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteCutCornerShape.cs(20,30): error CS0534: 'AbsoluteCutCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteCutCornerShapeKt.cs(128,89): error CS0111: Type 'AbsoluteCutCornerShapeKt' already defines a member called 'AbsoluteCutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteCutCornerShapeKt.cs(142,89): error CS0111: Type 'AbsoluteCutCornerShapeKt' already defines a member called 'AbsoluteCutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteRoundedCornerShape.cs(20,30): error CS0534: 'AbsoluteRoundedCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteRoundedCornerShapeKt.cs(128,93): error CS0111: Type 'AbsoluteRoundedCornerShapeKt' already defines a member called 'AbsoluteRoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteRoundedCornerShapeKt.cs(142,93): error CS0111: Type 'AbsoluteRoundedCornerShapeKt' already defines a member called 'AbsoluteRoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.CutCornerShape.cs(20,30): error CS0534: 'CutCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.CutCornerShapeKt.cs(128,81): error CS0111: Type 'CutCornerShapeKt' already defines a member called 'CutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.CutCornerShapeKt.cs(142,81): error CS0111: Type 'CutCornerShapeKt' already defines a member called 'CutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.RoundedCornerShape.cs(20,30): error CS0534: 'RoundedCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.RoundedCornerShapeKt.cs(141,85): error CS0111: Type 'RoundedCornerShapeKt' already defines a member called 'RoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.RoundedCornerShapeKt.cs(155,85): error CS0111: Type 'RoundedCornerShapeKt' already defines a member called 'RoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net10.0-android36.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteCutCornerShape.cs(20,30): error CS0534: 'AbsoluteCutCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteCutCornerShapeKt.cs(128,89): error CS0111: Type 'AbsoluteCutCornerShapeKt' already defines a member called 'AbsoluteCutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteCutCornerShapeKt.cs(142,89): error CS0111: Type 'AbsoluteCutCornerShapeKt' already defines a member called 'AbsoluteCutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteRoundedCornerShape.cs(20,30): error CS0534: 'AbsoluteRoundedCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteRoundedCornerShapeKt.cs(128,93): error CS0111: Type 'AbsoluteRoundedCornerShapeKt' already defines a member called 'AbsoluteRoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.AbsoluteRoundedCornerShapeKt.cs(142,93): error CS0111: Type 'AbsoluteRoundedCornerShapeKt' already defines a member called 'AbsoluteRoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.CutCornerShape.cs(20,30): error CS0534: 'CutCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.CutCornerShapeKt.cs(128,81): error CS0111: Type 'CutCornerShapeKt' already defines a member called 'CutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.CutCornerShapeKt.cs(142,81): error CS0111: Type 'CutCornerShapeKt' already defines a member called 'CutCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.RoundedCornerShape.cs(20,30): error CS0534: 'RoundedCornerShape' does not implement inherited abstract member 'CornerBasedShape.Copy(ICornerSize, ICornerSize, ICornerSize, ICornerSize)' [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.RoundedCornerShapeKt.cs(141,85): error CS0111: Type 'RoundedCornerShapeKt' already defines a member called 'RoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net9.0-android35.0\generated\src\AndroidX.Compose.Foundation.Shape.RoundedCornerShapeKt.cs(155,85): error CS0111: Type 'RoundedCornerShapeKt' already defines a member called 'RoundedCornerShape' with the same parameter types [D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\androidx.compose.foundation.foundation-android.csproj::TargetFramework=net9.0-android35.0]
    242 Warning(s)
    24 Error(s)

Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 4, 2026

@copilot list of errors:

D:\a\_work\1\s\generated\androidx.compose.foundation.foundation-android\obj\Release\net10.0-android36.0\generated\src\AndroidX.Compose.Foundation.Shape.A...

Fixed in 3c3aadb. The 24 errors were all in foundation-android's androidx.compose.foundation.shape package — they only surfaced once UI.Graphics started binding, because the shape hierarchy (CornerBasedShape & co.) couldn't be emitted while IShape was unbindable. Two root causes, both fixed in foundation-android/Transforms/Metadata.xml:

  • CS0111 (duplicate *Kt factories): Kotlin inline-class (Dp) receivers get JVM name-mangled with a -hash suffix, so RoundedCornerShape-0680j_4(F) collapses onto the plain RoundedCornerShape(F) overload. Removed the mangled overloads in RoundedCornerShapeKt/CutCornerShapeKt/AbsoluteRoundedCornerShapeKt/AbsoluteCutCornerShapeKt, exactly mirroring the existing CornerSizeKt rule right above it.
  • CS0534 (Copy(ICornerSize x4) not implemented): CornerBasedShape.copy(…) is abstract returning CornerBasedShape, but each subclass overrides it with a covariant (subclass-typed) return, which the generator emits without override. Pinned managedReturn to AndroidX.Compose.Foundation.Shape.CornerBasedShape on each subclass's copy(CornerSize x4) so the override is recognized.

Verified foundation-android now compiles cleanly end-to-end against the freshly-built UI.Graphics binding (0 errors). This is purely additive — it surfaces the real RoundedCornerShape/CutCornerShape/CornerBasedShape bindings (plus factories), which previously couldn't bind at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Xamarin.AndroidX.Compose.UI.Graphics] Stop stripping the whole package; ship real bindings

3 participants