-
Notifications
You must be signed in to change notification settings - Fork 50
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
native-activity: Propagate NativeWindow
redraw/resize and ContentRectChanged
callbacks to main loop
#70
Conversation
Ah, yep, good catch. |
@rib I don't recall whether |
Lines 438 to 443 in f88f914
|
Hopefully not. I was all ready to write something like "told you so ;-p" (with less snark) here because I was going to guess that this was an unintentional regression from when I ported the It looks like my first incarnation of We might want to review this patch to check if there are a few other also: https://developer.android.com/ndk/reference/struct/a-native-activity-callbacks |
It looks like we also need to handle |
See above, at least the resize is already handled.
And I would have said "just port
I was going to validate (probably by copy-pasting and sorting) whether we assign to all members of |
NativeWindow
resize event to main loopNativeWindow
redraw/resize and ContentRectChanged
callbacks to main loop
@@ -396,6 +397,18 @@ impl WaitableNativeActivityState { | |||
}); | |||
} | |||
|
|||
pub fn notify_window_resized(&self, native_window: *mut ndk_sys::ANativeWindow) { | |||
let mut guard = self.mutex.lock().unwrap(); | |||
debug_assert_eq!(guard.window.as_ref().unwrap().ptr().as_ptr(), native_window); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel a little uneasy about asserting the value of the .window
state here, which is conceptually owned by the android_main()
thread, not the Java main thread - but I thiink this might be OK, due to the unique way that window state change are explicitly synchronized between the Java and android_main()
thread.
It could be good to have a comment above this explaining why we think it's safe to assert this.
The assertion relies on the fact that set_window()
(called by on_native_window_created
and on_native_window_destroyed
) will always synchronize .pending_window
-> .window
changes between the Java and android_main
thread, and assumes the android_main()
thread will never spontaneously / pre-emptively clear the .window
to None.
It also assumes that the ANativeActivity doesn't do anything surprising and ever send a spurious resized event before onNativeWindowCreated
or after onNativeWindowDestroyed
. That seems like it should be a fair/logical assumption but also not 100% sure that's guaranteed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah exactly, this assert is here may we eventually queue up a pending_window
which hasn't been adopted by the main loop yet, but a resize already arrives.
That should be fine though as the main loop will have to process TermWindow
+InitWindow
first, before picking up the window
. If Android calls all these callbacks from a single Java thread (it does, right) we can't ever have set_window
and notify_window_resized
run concurrently anyway, and as you say set_window
will block until the main thread adopted the window (i.e. running in lockstep at that point).
In other words pending_window
should never be Some
outside of set_window()
, so we can't even check that hence the window
must always be adopted by the main loop.
Then this assert is only validating that Android isn't sending us garbage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fwiw I think this is also going to be interesting with multiple activities, where we could solely use the NativeWindow
pointer to distinguish windows. And could a single activity somehow have multiple windows (i.e. they also give us the pointer in onNativeWindowDestroyed
which could be used for validation).
|
||
pub fn notify_window_redraw_needed(&self, native_window: *mut ndk_sys::ANativeWindow) { | ||
let mut guard = self.mutex.lock().unwrap(); | ||
debug_assert_eq!(guard.window.as_ref().unwrap().ptr().as_ptr(), native_window); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same initial thought as above - it could be good to at least add a comment explaining why we think it's safe to assert this.
@@ -436,6 +449,12 @@ impl WaitableNativeActivityState { | |||
guard.pending_window = None; | |||
} | |||
|
|||
unsafe fn set_content_rect(&self, rect: *const ndk_sys::ARect) { | |||
let mut guard = self.mutex.lock().unwrap(); | |||
guard.content_rect = *rect; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the first event where we have extra state that is passed side-band without synchronization and we maybe need to consider if this is OK like this.
Hypothetically I suppose you could end up with the Java thread buffering multiple commands (including multiple calls to set_content_rect
) before they are picked up by the android_main()
thread and the android_main()
thread will always just see the most recent content_rect
from the Activity
.
That sounds like the ideal behaviour here though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes they'd get buffered up, and we might want to "deduplicate" this event when it's in the pipe?
OTOH I figured this might be why you left these MainEvent
s as non_exhaustive
:
android-activity/android-activity/src/lib.rs
Lines 203 to 204 in 36ddfaa
#[non_exhaustive] | |
ContentRectChanged {}, |
So that we could perhaps remove the getter altogether and only pass the value to the user once, letting them deal with that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also don't see if/how we could use pending_content_rect
in this case unless also implementing special synchronization.
I would love to see this one in a released version 🙂 I tested it on a few devices, it works for me and solves a few issues I have. Anything I can do to help it moving along? |
I can aim to have a look at landing this soon, yep. I might just add a few extra comments to the code as noted above, and/or remove the window assertion. The change itself looks good to me. |
Some items were imported in scope while most of the code uses fully qualified names.
thanks for the added comments @MarijnS95, will merge now we can look at bumping the MSRV separately to address the current CI issue |
Yeah |
Could a version not bumping the MSRV with this PR be published? From a semver point of view, this can be published in a patch, the MSRV bump would need to be a minor version and require updating all the ecosystem to propagate... |
@mockersf the solution is to stop using Regardless, the issue is that the CI cannot build+install |
Since Rust 1.68 bumped the version of the ndk that the standard library links with to version 25 there's some special significance for why the latest It probably is a good general baseline for any Android projects based on Rust at this point - and I would generally recommend that Rust Android projects all aim to move to at least NDK v25 and Rust 1.68+ too ideally. The solution isn't to "stop using In this case Yeah, it could be good to be able to do a patch release for this without bumping the msrv too aggressively - though at the same time 1.68 is particularly significant for Android. In terms of semver I don't think msrv changes require an semver bump. Obviously it could be seen as bad etiquate to be inconsiderate of downstream msrv policies though. Looking at the Bevy project it looks like the policy there is "the latest stable release":
and so since the latest stable release is 1.68, maybe you'd actually be ok with a 1.68 bump @mockersf ? @MarijnS95: Besides taking a jibe at It's not that I want to follow an aggressive msrv policy here but it certainly is tempting to at least set the bar at 1.68, due to the android ndk update that comes along with that. If we do have big concerns with bumping to 1.68 then we should be able to tweak the CI to just use an older version of cargo ndk I guess. |
I don't have any problem with bumping the MSRV as high as you want, 1.68 is good for me. As you noticed, Bevy is "latest stable". I'm mostly hoping for a patch release because in a strict SemVer interpretation, any bump of the MSRV is a breaking change, so at least a minor release (since this crate is still in the 0.X range). And that would mean I'll have to wait for a winit update before it's usable in Bevy. As It depends on how strict you want to be with SemVer. |
Just for good measure, we're all saying the exact same thing:
I've seen various interpretations of this. Personally I mostly align with the view that an MSRV bump should be breaking, unless the new MSRV is over 6 months old. It is always super annoying if external crates/tools bump their MSRV too eagerly, breaking downstream consumer projects and/or their CI (as is happening here... though because IIRC we install the latest In our case we have to watch what TL;DR:
|
As far as I can see there has not been a release with this bug fix. Are you still planning a patch release? |
@NiklasEi FWIW that was a suggestion, not an action as I am not the release manager for |
Yeah, sorry, I'd like to make a release of android-activity too, though I also had a few things I was hoping to look at addressing for a next release so held off a little bit. One thing I had wanted to do was update all the rust-android-examples and smoke test the Activity.finish() change which I've basically done - I just need to disable to the openxr example in CI for now. I'd also like to have an api that exposes the equivalent of getUnicodeChar which we really need in Winit but that's going to be a bit more fiddly than I was initially expecting so can probably let that slide for now. |
@rib fwiw we could have a simple patch release soon-ish and plan the next breaking release (will we need/have any?) right before the next winit drop which is supposedly scheduled for August. |
Okey, just published a 0.4.2 release - sorry for the delay with releasing here: https://github.com/rust-mobile/android-activity/releases/tag/v0.4.2 |
Fixes rust-windowing/winit#2760