Status Update
Comments
pa...@google.com <pa...@google.com>
ch...@gmail.com <ch...@gmail.com> #2
Thanks for reporting this!
The intention here was for parentWidth
to be hidden and it will be fixed soon. I see the potential convenience of exposing parentWidth
and parentHeight
, but in general it leads to a not very clean data flow: it would mean that after telling the layout system my size I receive the size back although my initial calculation is still in scope. I am afraid this would bring more confusion than convenience longer term.
Just as a background, the reason we have parentWidth
and not parentHeight
is that it is needed to calculate horizontally mirrored positioning of children for layout direction RTL when placeRelative
is used.
ap...@google.com <ap...@google.com> #3
Branch: androidx-master-dev
commit 36b705d1dd148fc57e8089a94d485e0bfcd05d0f
Author: Mihai Popa <popam@google.com>
Date: Mon Sep 14 11:59:30 2020
Hide parentWidth and parentLD in PlacementScope
When writing a custom layout, parentWidth and parentLayoutDirection
should not be read from the placement block as they are available or
calculated in the measure block. This CL is making them protected in
PlacementScope. The CL also merges the PlacementScope implementations
used for modifiers and layout nodes, which is now possible after the
modules' merging.
Relnote: PlacementScope#parentWidth and PlacementScope#parentLayoutDirection can no longer be read from the placement block of a custom layout.
Fixes: 168295623
Test: tests in foundation-layout
Change-Id: Icc1ae00d774147c5fa7006c4bb408c99c7731690
M compose/ui/ui/api/current.txt
M compose/ui/ui/api/public_plus_experimental_current.txt
M compose/ui/ui/api/restricted_current.txt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/MeasureScope.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Placeable.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt
pa...@google.com <pa...@google.com> #4
I actually found a reason for exposing both parentWidth
and parentHeight
in PlacementScope
and that is modifiers. I wanted to write a modifier that places a composable using a percent which requires access to the parent's size. This currently does not seem possible using modifiers.
Description
Build #AI-192.6817.14.36.5959023, built on October 22, 2019
Runtime version: 1.8.0_212-release-1586-b4-5784211 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Linux 5.0.0-32-generic
GC: ParNew, ConcurrentMarkSweep
Memory: 1981M
Cores: 8
Registry: ide.new.welcome.screen.force=true, debugger.watches.in.variables=false
Non-Bundled Plugins: CheckStyle-IDEA
Version of Gradle Plugin: 4.0.0-alpha01
Version of Gradle: 5.6.1
Version of Kotlin: 1.3.60-eap-25
OS: Ubuntu 19.04
-----------
Steps to Reproduce:
1. UnZIP the attached project and import it into Android Studio
2. Run the app
3. Start recording a screencast (e.g., from Android Studio)
4. Tap the "Show Popup" button to show an empty Popup
5. Wait a moment
6. Tap the "Show Popup" button again to dismiss that Popup
7. Stop recording the screencast
8. Look at the screencast
Expected Results: The screencast to be completely empty, as we are recording the functionality of an activity that has FLAG_SECURE set
Actual Results: The Popup appears in the screencast when that "Show Popup" button was clicked, and vanishes from the screencast when that "Show Popup" button was clicked again
The attached MP4 is a screencast taken of this app, using a Pixel 4 running Android 10.
----
If you are going to create a Window with WindowManager, you need to see whether we are in a secure window now and propagate that secure status. Otherwise, we wind up in the same situation that we have with the View-based UI framework, where FLAG_SECURE misses lots of content (menus, Spinner, dialogs, toasts, etc.), because we do not control those windows and cannot set FLAG_SECURE on them. See
PopupLayout has access to composeView. If that View is owned by an activity, you can find the activity's window, see if it has FLAG_SECURE set upon it, and if so put FLAG_SECURE on the window created by the PopupLayout. This is not ideal, as it will not handle some edge cases (e.g., composeView is not owned by an activity) but AFAIK there is no way for a View to get its Window (or that window's flags) in all cases.
A more flexible possibility is to have a WindowSecurityPolicy enum, with values like:
- NORMAL for an insecure window
- SECURE for a secure window
- INHERIT to use the aforementioned "see what the current window uses" approach
Then, have Popup() take a WindowSecurityPolicy parameter, defaulted to INHERIT. This would allow developers that are directly calling Popup() to positively specify a policy if desired. If the policy is SECURE, or it is INHERIT and the current window has FLAG_SECURE set, apply FLAG_SECURE to the window created by the Popup.
My concern with Popup in particular is that it might get used elsewhere within the Compose libraries. If Popup (and DropdownPopup) were only ever going to be used directly by outside developers, you could say that it is up to us to implement SecurePopup and SecureDropdownPopup. However, my guess is that Compose will use Popup internally, which exacerbates the problem if Popup cannot handle FLAG_SECURE itself. For example, if a Frobozz composable supplied by Compose uses Popup internally, now you are asking the community to maintain a SecureFrobozz that uses a SecurePopup. We wind up having community-maintained parallel composables to those in Compose itself, just to address security issues.
Thanks for considering this!