Revert "compositor: Unify the cross process and in-process API (#36443)" (#36533)

This reverts commit 4c55104b36.

This commit introduced an issue where messages from script to the
compositor no longer woke up the embedder. There is a larger issue
here, but this change exacerbated it.

Fixes #36528.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-04-15 11:15:14 +02:00 committed by GitHub
parent f8b6b9f7b6
commit fe4306fc30
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 215 additions and 95 deletions

View file

@ -7,6 +7,7 @@
use std::fmt::{Debug, Error, Formatter};
use base::id::{PipelineId, WebViewId};
use crossbeam_channel::{Receiver, Sender};
use embedder_traits::{
AnimationState, EventLoopWaker, MouseButton, MouseButtonAction, TouchEventResult,
};
@ -21,6 +22,7 @@ use webrender_api::DocumentId;
pub mod display_list;
pub mod rendering_context;
use core::fmt;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
@ -41,7 +43,11 @@ use webrender_api::{
/// Sends messages to the compositor.
#[derive(Clone)]
pub struct CompositorProxy {
pub sender: IpcSender<CompositorMsg>,
pub sender: Sender<CompositorMsg>,
/// Access to [`Self::sender`] that is possible to send across an IPC
/// channel. These messages are routed via the router thread to
/// [`Self::sender`].
pub cross_process_compositor_api: CrossProcessCompositorApi,
pub event_loop_waker: Box<dyn EventLoopWaker>,
}
@ -52,14 +58,24 @@ impl CompositorProxy {
}
self.event_loop_waker.wake();
}
}
pub fn cross_process_compositor_api(&self) -> CrossProcessCompositorApi {
CrossProcessCompositorApi(self.sender.clone())
/// The port that the compositor receives messages on.
pub struct CompositorReceiver {
pub receiver: Receiver<CompositorMsg>,
}
impl CompositorReceiver {
pub fn try_recv_compositor_msg(&mut self) -> Option<CompositorMsg> {
self.receiver.try_recv().ok()
}
pub fn recv_compositor_msg(&mut self) -> CompositorMsg {
self.receiver.recv().unwrap()
}
}
/// Messages from (or via) the constellation thread to the compositor.
#[derive(Deserialize, IntoStaticStr, Serialize)]
#[derive(IntoStaticStr)]
pub enum CompositorMsg {
/// Alerts the compositor that the given pipeline has changed whether it is running animations.
ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
@ -96,6 +112,32 @@ pub enum CompositorMsg {
/// WebDriver mouse move event
WebDriverMouseMoveEvent(WebViewId, f32, f32),
/// Messages forwarded to the compositor by the constellation from other crates. These
/// messages are mainly passed on from the compositor to WebRender.
CrossProcess(CrossProcessCompositorMessage),
}
pub struct SendableFrameTree {
pub pipeline: CompositionPipeline,
pub children: Vec<SendableFrameTree>,
}
/// The subset of the pipeline that is needed for layer composition.
#[derive(Clone)]
pub struct CompositionPipeline {
pub id: PipelineId,
pub webview_id: WebViewId,
}
impl Debug for CompositorMsg {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
let string: &'static str = self.into();
write!(formatter, "{string}")
}
}
#[derive(Deserialize, Serialize)]
pub enum CrossProcessCompositorMessage {
/// Inform WebRender of the existence of this pipeline.
SendInitialTransaction(WebRenderPipelineId),
/// Perform a scroll operation.
@ -155,29 +197,31 @@ pub enum CompositorMsg {
GetAvailableScreenSize(WebViewId, IpcSender<DeviceIndependentIntSize>),
}
impl Debug for CompositorMsg {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
let string: &'static str = self.into();
write!(formatter, "{string}")
impl fmt::Debug for CrossProcessCompositorMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AddImage(..) => f.write_str("AddImage"),
Self::GenerateFontKeys(..) => f.write_str("GenerateFontKeys"),
Self::AddSystemFont(..) => f.write_str("AddSystemFont"),
Self::SendInitialTransaction(..) => f.write_str("SendInitialTransaction"),
Self::SendScrollNode(..) => f.write_str("SendScrollNode"),
Self::SendDisplayList { .. } => f.write_str("SendDisplayList"),
Self::HitTest(..) => f.write_str("HitTest"),
Self::GenerateImageKey(..) => f.write_str("GenerateImageKey"),
Self::UpdateImages(..) => f.write_str("UpdateImages"),
Self::RemoveFonts(..) => f.write_str("RemoveFonts"),
Self::AddFontInstance(..) => f.write_str("AddFontInstance"),
Self::AddFont(..) => f.write_str("AddFont"),
Self::GetClientWindowRect(..) => f.write_str("GetClientWindowRect"),
Self::GetScreenSize(..) => f.write_str("GetScreenSize"),
Self::GetAvailableScreenSize(..) => f.write_str("GetAvailableScreenSize"),
}
}
}
#[derive(Deserialize, Serialize)]
pub struct SendableFrameTree {
pub pipeline: CompositionPipeline,
pub children: Vec<SendableFrameTree>,
}
/// The subset of the pipeline that is needed for layer composition.
#[derive(Clone, Deserialize, Serialize)]
pub struct CompositionPipeline {
pub id: PipelineId,
pub webview_id: WebViewId,
}
/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance.
#[derive(Clone, Deserialize, Serialize)]
pub struct CrossProcessCompositorApi(pub IpcSender<CompositorMsg>);
pub struct CrossProcessCompositorApi(pub IpcSender<CrossProcessCompositorMessage>);
impl CrossProcessCompositorApi {
/// Create a new [`CrossProcessCompositorApi`] struct that does not have a listener on the other
@ -188,13 +232,18 @@ impl CrossProcessCompositorApi {
}
/// Get the sender for this proxy.
pub fn sender(&self) -> &IpcSender<CompositorMsg> {
pub fn sender(&self) -> &IpcSender<CrossProcessCompositorMessage> {
&self.0
}
/// Inform WebRender of the existence of this pipeline.
pub fn send_initial_transaction(&self, pipeline: WebRenderPipelineId) {
if let Err(e) = self.0.send(CompositorMsg::SendInitialTransaction(pipeline)) {
if let Err(e) = self
.0
.send(CrossProcessCompositorMessage::SendInitialTransaction(
pipeline,
))
{
warn!("Error sending initial transaction: {}", e);
}
}
@ -207,7 +256,7 @@ impl CrossProcessCompositorApi {
point: LayoutPoint,
scroll_id: ExternalScrollId,
) {
if let Err(e) = self.0.send(CompositorMsg::SendScrollNode(
if let Err(e) = self.0.send(CrossProcessCompositorMessage::SendScrollNode(
webview_id,
pipeline_id,
point,
@ -226,7 +275,7 @@ impl CrossProcessCompositorApi {
) {
let (display_list_data, display_list_descriptor) = list.into_data();
let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
if let Err(e) = self.0.send(CompositorMsg::SendDisplayList {
if let Err(e) = self.0.send(CrossProcessCompositorMessage::SendDisplayList {
webview_id,
display_list_descriptor,
display_list_receiver,
@ -261,7 +310,9 @@ impl CrossProcessCompositorApi {
) -> Vec<CompositorHitTestResult> {
let (sender, receiver) = ipc::channel().unwrap();
self.0
.send(CompositorMsg::HitTest(pipeline, point, flags, sender))
.send(CrossProcessCompositorMessage::HitTest(
pipeline, point, flags, sender,
))
.expect("error sending hit test");
receiver.recv().expect("error receiving hit test result")
}
@ -269,7 +320,9 @@ impl CrossProcessCompositorApi {
/// Create a new image key. Blocks until the key is available.
pub fn generate_image_key(&self) -> Option<ImageKey> {
let (sender, receiver) = ipc::channel().unwrap();
self.0.send(CompositorMsg::GenerateImageKey(sender)).ok()?;
self.0
.send(CrossProcessCompositorMessage::GenerateImageKey(sender))
.ok()?;
receiver.recv().ok()
}
@ -279,14 +332,19 @@ impl CrossProcessCompositorApi {
descriptor: ImageDescriptor,
data: SerializableImageData,
) {
if let Err(e) = self.0.send(CompositorMsg::AddImage(key, descriptor, data)) {
if let Err(e) = self.0.send(CrossProcessCompositorMessage::AddImage(
key, descriptor, data,
)) {
warn!("Error sending image update: {}", e);
}
}
/// Perform an image resource update operation.
pub fn update_images(&self, updates: Vec<ImageUpdate>) {
if let Err(e) = self.0.send(CompositorMsg::UpdateImages(updates)) {
if let Err(e) = self
.0
.send(CrossProcessCompositorMessage::UpdateImages(updates))
{
warn!("error sending image updates: {}", e);
}
}
@ -299,7 +357,10 @@ impl CrossProcessCompositorApi {
if keys.is_empty() && instance_keys.is_empty() {
return;
}
let _ = self.0.send(CompositorMsg::RemoveFonts(keys, instance_keys));
let _ = self.0.send(CrossProcessCompositorMessage::RemoveFonts(
keys,
instance_keys,
));
}
pub fn add_font_instance(
@ -309,7 +370,7 @@ impl CrossProcessCompositorApi {
size: f32,
flags: FontInstanceFlags,
) {
let _x = self.0.send(CompositorMsg::AddFontInstance(
let _x = self.0.send(CrossProcessCompositorMessage::AddFontInstance(
font_instance_key,
font_key,
size,
@ -318,11 +379,15 @@ impl CrossProcessCompositorApi {
}
pub fn add_font(&self, font_key: FontKey, data: Arc<IpcSharedMemory>, index: u32) {
let _ = self.0.send(CompositorMsg::AddFont(font_key, data, index));
let _ = self.0.send(CrossProcessCompositorMessage::AddFont(
font_key, data, index,
));
}
pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
let _ = self.0.send(CompositorMsg::AddSystemFont(font_key, handle));
let _ = self.0.send(CrossProcessCompositorMessage::AddSystemFont(
font_key, handle,
));
}
pub fn fetch_font_keys(
@ -331,7 +396,7 @@ impl CrossProcessCompositorApi {
number_of_font_instance_keys: usize,
) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
let (sender, receiver) = ipc_channel::ipc::channel().expect("Could not create IPC channel");
let _ = self.0.send(CompositorMsg::GenerateFontKeys(
let _ = self.0.send(CrossProcessCompositorMessage::GenerateFontKeys(
number_of_font_keys,
number_of_font_instance_keys,
sender,