Skip to content

Commit bcd5cf3

Browse files
committed
fix(linux): drive CEF with chromium's own message pump
1 parent 71528d0 commit bcd5cf3

3 files changed

Lines changed: 40 additions & 26 deletions

File tree

‎src/external_message_pump/linux.rs‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,6 @@ impl PlatformPump {
136136
pub(super) fn is_timer_pending(&self) -> bool {
137137
get_time_interval_milliseconds(self.source_state.delayed_work_time) > 0
138138
}
139-
140-
pub(super) fn deadline(&self) -> Option<Instant> {
141-
self.source_state.delayed_work_time
142-
}
143139
}
144140

145141
impl Drop for PlatformPump {

‎src/external_message_pump/mod.rs‎

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,6 @@ impl CefExternalPump {
9595
pub(crate) fn do_work(&self) {
9696
self.state.do_work();
9797
}
98-
99-
/// When the platform timer is next due. This is only needed by event loops
100-
/// that do not block in the GLib main context themselves.
101-
#[cfg(any(
102-
target_os = "linux",
103-
target_os = "dragonfly",
104-
target_os = "freebsd",
105-
target_os = "netbsd",
106-
target_os = "openbsd"
107-
))]
108-
pub(crate) fn next_deadline(&self) -> Option<std::time::Instant> {
109-
self.state.platform.lock().ok().and_then(|p| p.deadline())
110-
}
11198
}
11299

113100
/// Platform-independent pump state, shared with the [`PlatformPump`] backend.

‎src/runtime.rs‎

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,16 @@ pub(crate) struct WinitCefApp<T: UserEvent> {
397397
exit_code: Arc<std::sync::atomic::AtomicI32>,
398398
}
399399

400+
/// Stands in for the scheduling callbacks `external_message_pump` would provide.
401+
#[cfg(any(
402+
target_os = "linux",
403+
target_os = "dragonfly",
404+
target_os = "freebsd",
405+
target_os = "netbsd",
406+
target_os = "openbsd"
407+
))]
408+
const CEF_WORK_INTERVAL: std::time::Duration = std::time::Duration::from_millis(4);
409+
400410
impl<T: UserEvent> WinitCefApp<T> {
401411
fn new(
402412
context: RuntimeContext<T>,
@@ -842,11 +852,10 @@ impl<T: UserEvent> WinitCefApp<T> {
842852
}
843853
}
844854

845-
/// Service the default GLib main context so the external message pump's GLib
846-
/// timeout (and any GTK work CEF schedules) gets dispatched, then arm winit to
847-
/// wake when the next tick is due. CEF is driven by that timeout firing, not
848-
/// from here. Windows/macOS need no equivalent: their pump timers live on the
849-
/// native loop winit already runs.
855+
/// Without `external_message_pump` nothing tells us when Chromium has work, so
856+
/// poll it. The GLib iteration only covers GTK work CEF schedules itself:
857+
/// `MessagePumpGlib`'s sources return early unless the pump is inside `Run()`,
858+
/// which only `do_message_loop_work` enters.
850859
#[cfg(any(
851860
target_os = "linux",
852861
target_os = "dragonfly",
@@ -859,9 +868,11 @@ impl<T: UserEvent> WinitCefApp<T> {
859868
while context.pending() {
860869
context.iteration(false);
861870
}
862-
if let Some(deadline) = self.context.cef_pump.next_deadline() {
863-
event_loop.set_control_flow(winit::event_loop::ControlFlow::WaitUntil(deadline));
864-
}
871+
872+
cef::do_message_loop_work();
873+
event_loop.set_control_flow(winit::event_loop::ControlFlow::WaitUntil(
874+
std::time::Instant::now() + CEF_WORK_INTERVAL,
875+
));
865876
}
866877
}
867878

@@ -1495,10 +1506,30 @@ impl<T: UserEvent> CefRuntime<T> {
14951506
"CEF browser process unexpectedly returned from execute_process"
14961507
);
14971508

1509+
// CEF's `MessagePumpExternal::Run` is a 10ms time slice with a no-op `Quit`,
1510+
// so nested run loops end immediately — HTML5 drag and native context menus
1511+
// both need one that lasts. Chromium's own `MessagePumpGlib` is a real loop.
1512+
#[cfg(any(
1513+
target_os = "linux",
1514+
target_os = "dragonfly",
1515+
target_os = "freebsd",
1516+
target_os = "netbsd",
1517+
target_os = "openbsd"
1518+
))]
1519+
const EXTERNAL_MESSAGE_PUMP: i32 = 0;
1520+
#[cfg(not(any(
1521+
target_os = "linux",
1522+
target_os = "dragonfly",
1523+
target_os = "freebsd",
1524+
target_os = "netbsd",
1525+
target_os = "openbsd"
1526+
)))]
1527+
const EXTERNAL_MESSAGE_PUMP: i32 = 1;
1528+
14981529
let settings = cef::Settings {
14991530
no_sandbox: !cfg!(feature = "sandbox") as i32,
15001531
cache_path: cache_path.to_string_lossy().to_string().as_str().into(),
1501-
external_message_pump: 1,
1532+
external_message_pump: EXTERNAL_MESSAGE_PUMP,
15021533
// Comma-delimited; empty keeps CEF's http/https-only default. The
15031534
// defaults stay included because exclude_defaults is left 0.
15041535
cookieable_schemes_list: cef_config.cookieable_schemes.join(",").as_str().into(),

0 commit comments

Comments
 (0)