Improve inter-document focus handling (#36649)

*Describe the changes that this pull request makes here. This will be
the commit message.*
rewritten the PR #28571
Implement
[Window#focus](https://html.spec.whatwg.org/multipage/#dom-window-focus),
[Window#blur](https://html.spec.whatwg.org/multipage/#dom-window-blur)
Testing: WPT
Fixes: #8981 #9421

---------

Signed-off-by: kongbai1996 <1782765876@qq.com>
Co-authored-by: yvt <i@yvt.jp>
This commit is contained in:
Fuguo 2025-04-30 12:37:53 +08:00 committed by GitHub
parent 27570987fd
commit 0c0ee04b8e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1123 additions and 242 deletions

View file

@ -14,7 +14,7 @@ pub mod user_content_manager;
mod webdriver;
use std::ffi::c_void;
use std::fmt::{Debug, Error, Formatter};
use std::fmt::{Debug, Display, Error, Formatter};
use std::path::PathBuf;
use std::sync::Arc;
@ -784,3 +784,76 @@ pub enum AnimationState {
/// No animations are active but callbacks are queued
NoAnimationCallbacksPresent,
}
/// A sequence number generated by a script thread for its pipelines. The
/// constellation attaches the target pipeline's last seen `FocusSequenceNumber`
/// to every focus-related message it sends.
///
/// This is used to resolve the inconsistency that occurs due to bidirectional
/// focus state synchronization and provide eventual consistency. Example:
///
/// ```text
/// script constellation
/// -----------------------------------------------------------------------
/// send ActivateDocument ----------> receive ActivateDocument
/// ,---- send FocusDocument
/// |
/// focus an iframe |
/// send Focus -----------------|---> receive Focus
/// | focus the iframe's content document
/// receive FocusDocument <-----' send FocusDocument to the content pipeline --> ...
/// unfocus the iframe
/// focus the document
///
/// Final state: Final state:
/// the iframe is not focused the iframe is focused
/// ```
///
/// When the above sequence completes, from the script thread's point of view,
/// the iframe is unfocused, but from the constellation's point of view, the
/// iframe is still focused.
///
/// This inconsistency can be resolved by associating a sequence number to each
/// message. Whenever a script thread initiates a focus operation, it generates
/// and sends a brand new sequence number. The constellation attaches the
/// last-received sequence number to each message it sends. This way, the script
/// thread can discard out-dated incoming focus messages, and eventually, all
/// actors converge to the consistent state which is determined based on the
/// last focus message received by the constellation.
///
/// ```text
/// script constellation
/// -----------------------------------------------------------------------
/// send ActivateDocument ----------> receive ActivateDocument
/// ,---- send FocusDocument (0)
/// |
/// seq_number += 1 |
/// focus an iframe |
/// send Focus (1) -------------|---> receive Focus (1)
/// | focus the iframe's content document
/// receive FocusDocument (0) <-' send FocusDocument to the content pipeline --> ...
/// ignore it because 0 < 1
///
/// Final state: Final state:
/// the iframe is focused the iframe is focused
/// ```
#[derive(
Clone,
Copy,
Debug,
Default,
Deserialize,
Eq,
Hash,
MallocSizeOf,
PartialEq,
Serialize,
PartialOrd,
)]
pub struct FocusSequenceNumber(pub u64);
impl Display for FocusSequenceNumber {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
Display::fmt(&self.0, f)
}
}