Fix message loop handling and improve BrowserProcessHandler (#15)

* add: implement MessagePumpChecker for message loop management

* update: refactor message loop handling and improve MessagePumpChecker

* update: refactor message loop handling to use MessageLoopTimer and improve BrowserProcessHandler

* update: reorganize imports and enhance browser process handler integration

* update: support Bevy 0.18 and improve message loop handling

* update: remove unused FpsOverlayPlugin and clean up dependencies

* update: simplify cef and cef-dll-sys version specifications in Cargo.toml

---------

Co-authored-by: not-elm <elmgameinfo@gmail.com>
This commit is contained in:
elm
2026-02-01 12:00:56 +09:00
committed by GitHub
parent 8f38892009
commit 5be6380474
10 changed files with 160 additions and 79 deletions

View File

@@ -5,6 +5,7 @@ mod client_handler;
mod context_menu_handler;
mod display_handler;
mod localhost;
mod message_pump;
mod renderer_handler;
mod request_context_handler;
@@ -14,5 +15,6 @@ pub use browsers::*;
pub use client_handler::*;
pub use context_menu_handler::*;
pub use localhost::*;
pub use message_pump::*;
pub use renderer_handler::*;
pub use request_context_handler::*;

View File

@@ -1,3 +1,4 @@
use crate::browser_process::MessageLoopTimer;
use crate::browser_process::browser_process_handler::BrowserProcessHandlerBuilder;
use crate::util::{SCHEME_CEF, cef_scheme_flags};
use cef::rc::{Rc, RcImpl};
@@ -6,19 +7,21 @@ use cef::{
SchemeRegistrar, WrapApp,
};
use cef_dll_sys::{_cef_app_t, cef_base_ref_counted_t};
use std::sync::mpsc::Sender;
/// ## Reference
///
/// - [`CefApp Class Reference`](https://cef-builds.spotifycdn.com/docs/106.1/classCefApp.html)
#[derive(Default)]
pub struct BrowserProcessAppBuilder {
object: *mut RcImpl<_cef_app_t, Self>,
message_loop_working_requester: Sender<MessageLoopTimer>,
}
impl BrowserProcessAppBuilder {
pub fn build() -> cef::App {
pub fn build(message_loop_working_requester: Sender<MessageLoopTimer>) -> cef::App {
cef::App::new(Self {
object: core::ptr::null_mut(),
message_loop_working_requester,
})
}
}
@@ -30,7 +33,10 @@ impl Clone for BrowserProcessAppBuilder {
rc_impl.interface.add_ref();
self.object
};
Self { object }
Self {
object,
message_loop_working_requester: self.message_loop_working_requester.clone(),
}
}
}
@@ -58,16 +64,18 @@ impl ImplApp for BrowserProcessAppBuilder {
// command_line.append_switch(Some(&" disable-gpu-shader-disk-cache".into()));
}
fn browser_process_handler(&self) -> Option<BrowserProcessHandler> {
Some(BrowserProcessHandlerBuilder::build())
}
fn on_register_custom_schemes(&self, registrar: Option<&mut SchemeRegistrar>) {
if let Some(registrar) = registrar {
registrar.add_custom_scheme(Some(&SCHEME_CEF.into()), cef_scheme_flags() as _);
}
}
fn browser_process_handler(&self) -> Option<BrowserProcessHandler> {
Some(BrowserProcessHandlerBuilder::build(
self.message_loop_working_requester.clone(),
))
}
#[inline]
fn get_raw(&self) -> *mut _cef_app_t {
self.object as *mut cef::sys::_cef_app_t

View File

@@ -1,17 +1,23 @@
use crate::prelude::MessageLoopTimer;
use cef::rc::{Rc, RcImpl};
use cef::*;
use std::sync::mpsc::Sender;
/// ## Reference
///
/// - [`CefBrowserProcessHandler Class Reference`](https://cef-builds.spotifycdn.com/docs/106.1/classCefBrowserProcessHandler.html)
pub struct BrowserProcessHandlerBuilder {
object: *mut RcImpl<cef_dll_sys::cef_browser_process_handler_t, Self>,
message_loop_working_requester: Sender<MessageLoopTimer>,
}
impl BrowserProcessHandlerBuilder {
pub fn build() -> BrowserProcessHandler {
pub fn build(
message_loop_working_requester: Sender<MessageLoopTimer>,
) -> BrowserProcessHandler {
BrowserProcessHandler::new(Self {
object: core::ptr::null_mut(),
message_loop_working_requester,
})
}
}
@@ -39,7 +45,10 @@ impl Clone for BrowserProcessHandlerBuilder {
rc_impl
};
Self { object }
Self {
object,
message_loop_working_requester: self.message_loop_working_requester.clone(),
}
}
}
@@ -56,6 +65,13 @@ impl ImplBrowserProcessHandler for BrowserProcessHandlerBuilder {
command_line.append_switch(Some(&"ignore-ssl-errors".into()));
command_line.append_switch(Some(&"enable-logging=stderr".into()));
}
fn on_schedule_message_pump_work(&self, delay_ms: i64) {
let _ = self
.message_loop_working_requester
.send(MessageLoopTimer::new(delay_ms));
}
#[inline]
fn get_raw(&self) -> *mut cef_dll_sys::_cef_browser_process_handler_t {
self.object.cast()

View File

@@ -0,0 +1,39 @@
use bevy::prelude::Deref;
use std::sync::mpsc::Receiver;
use std::time::{Duration, Instant};
/// Maximum delay between message loop iterations (~30fps).
/// Following CEF's official cefclient pattern (`kMaxTimerDelay = 1000/30`).
const MAX_TIMER_DELAY_MS: u64 = 1000 / 30;
#[repr(transparent)]
#[derive(Debug, Deref)]
pub struct MessageLoopWorkingReceiver(pub Receiver<MessageLoopTimer>);
#[derive(Debug)]
pub struct MessageLoopTimer(Instant);
impl MessageLoopTimer {
pub fn new(delay_ms: i64) -> Self {
let fire_time = if delay_ms <= 0 {
Instant::now()
} else {
Instant::now() + Duration::from_millis(delay_ms as u64)
};
Self(fire_time)
}
#[inline]
pub fn is_finished(&self) -> bool {
self.0 <= Instant::now()
}
}
#[derive(Debug, Deref)]
pub struct MessageLoopWorkingMaxDelayTimer(MessageLoopTimer);
impl Default for MessageLoopWorkingMaxDelayTimer {
fn default() -> Self {
Self(MessageLoopTimer::new(MAX_TIMER_DELAY_MS as i64))
}
}

View File

@@ -1,6 +1,7 @@
mod browser_process;
#[cfg(target_os = "macos")]
mod debug;
mod render_process;
mod util;

View File

@@ -57,6 +57,7 @@ impl ImplApp for RenderProcessAppBuilder {
}
impl WrapApp for RenderProcessAppBuilder {
#[inline]
fn wrap_rc(&mut self, object: *mut RcImpl<_cef_app_t, Self>) {
self.object = object;
}