implement native -> browser communication

This commit is contained in:
Adam
2025-07-25 20:31:06 -07:00
parent 4f21693772
commit d2b3bc2a87
8 changed files with 35 additions and 120 deletions
+16 -4
View File
@@ -2,10 +2,11 @@ use crate::CustomEvent;
use crate::WindowSize;
use crate::render::GraphicsState;
use crate::render::WgpuContext;
use ::cef::CefString;
use ::cef::ImplBrowser;
use ::cef::ImplFrame;
use graphite_editor::application::Editor;
use graphite_editor::dispatcher::Dispatcher;
use graphite_editor::messages::prelude::Message;
use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::time::Duration;
@@ -109,10 +110,21 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
tracing::error!("Message could not be deserialized: {:?}", message);
return;
};
println!("Message received: {message:?}");
let responses = self.editor.handle_message(message);
println!("responses: {:?}", responses);
// Send response to CEF
let Some(frame) = self.cef_context.browser.as_ref().unwrap().main_frame() else {
tracing::error!("Could not get frame after editor processed messages");
return;
};
for frontend_message in responses {
let Ok(serialized_message) = serde_json::to_string(&frontend_message) else {
tracing::error!("Failed to serialize frontend message in CustomEvent::MessageReceived");
continue;
};
let message = format!("window.handle.sendMessageToFrontendFromCEF(\'{serialized_message}\')");
let code = CefString::from(message.as_str());
frame.execute_java_script(Some(&code), None, 0);
}
}
}
}
+2 -2
View File
@@ -20,7 +20,7 @@ pub(crate) trait CefEventHandler: Clone {
/// [`_cef_browser_process_handler_t::on_schedule_message_pump_work`] for more documentation.
fn schedule_cef_message_loop_work(&self, scheduled_time: Instant);
fn send_message_to_editior(&self, message: String);
fn send_message_to_editor(&self, message: String);
}
#[derive(Clone, Copy)]
@@ -118,7 +118,7 @@ impl CefEventHandler for CefHandler {
fn schedule_cef_message_loop_work(&self, scheduled_time: std::time::Instant) {
let _ = self.event_loop_proxy.send_event(CustomEvent::ScheduleBrowserWork(scheduled_time));
}
fn send_message_to_editior(&self, message: String) {
fn send_message_to_editor(&self, message: String) {
let _ = self.event_loop_proxy.send_event(CustomEvent::MessageReceived { message });
}
}
+1
View File
@@ -5,6 +5,7 @@ mod non_browser_app;
mod non_browser_render_process_handler;
mod non_browser_v8_handler;
mod render_handler;
mod utility;
pub(crate) use app::AppImpl;
pub(crate) use client::ClientImpl;
+6 -12
View File
@@ -30,25 +30,19 @@ impl<H: CefEventHandler> ImplClient for ClientImpl<H> {
fn on_process_message_received(
&self,
browser: Option<&mut cef::Browser>,
frame: Option<&mut cef::Frame>,
source_process: cef::ProcessId,
_browser: Option<&mut cef::Browser>,
_frame: Option<&mut cef::Frame>,
_source_process: cef::ProcessId,
message: Option<&mut cef::ProcessMessage>,
) -> ::std::os::raw::c_int {
let Some(message) = message else {
tracing::event!(tracing::Level::ERROR, "No message in RenderProcessHandlerImpl::on_process_message_received");
tracing::error!("No message in RenderProcessHandlerImpl::on_process_message_received");
return 1;
};
let pointer: *mut cef::sys::_cef_string_utf16_t = message.name().into();
let message = unsafe {
let str = (*pointer).str_;
let len = (*pointer).length;
let slice = std::slice::from_raw_parts(str, len as usize);
String::from_utf16(slice).unwrap()
};
let _ = self.event_handler.send_message_to_editior(message);
let string_message = super::utility::pointer_to_string(pointer);
let _ = self.event_handler.send_message_to_editor(string_message);
0
}
}
@@ -24,12 +24,7 @@ impl ImplV8Handler for NonBrowserV8HandlerImpl {
let string = arguments.unwrap().first().unwrap().as_ref().unwrap().string_value();
let pointer: *mut cef::sys::_cef_string_utf16_t = string.into();
let message = unsafe {
let str = (*pointer).str_;
let len = (*pointer).length;
let slice = std::slice::from_raw_parts(str, len);
String::from_utf16(slice).unwrap()
};
let message = super::utility::pointer_to_string(pointer);
let Some(mut process_message) = process_message_create(Some(&CefString::from(message.as_str()))) else {
tracing::event!(tracing::Level::ERROR, "Failed to create process message");
+8
View File
@@ -0,0 +1,8 @@
pub fn pointer_to_string(pointer: *mut cef::sys::_cef_string_utf16_t) -> String {
unsafe {
let str = (*pointer).str_;
let len = (*pointer).length;
let slice = std::slice::from_raw_parts(str, len as usize);
String::from_utf16(slice).unwrap()
}
}