Support Bevy 0.17 (#11)
* update: modify for 0.17 * update: enhance webview functionality and improve plugin implementation * update: refactor webview system and improve binding group usage * update: refactor command triggering for webview events and enhance Receive struct * update: refactor command triggering for webview dev tools * update: refactor render process handler and improve webview handling * update: refactor webview browser handling and improve IME caret management * clippy * fmt * update: improve README formatting and clarify version compatibility * update: support Bevy 0.17 and enhance permissions in settings * update: enhance CI configuration by adding Wayland and XKB dependencies * delete: settings.json * update: refactor shader imports and improve binding group definitions * update: refactor devtool command triggers for improved clarity * update: modify LibraryLoader initialization for improved path handling on macOS * fmt --------- Co-authored-by: not-elm <elmgameinfo@gmail.com>
This commit is contained in:
@@ -31,23 +31,22 @@ pub struct WebviewBrowser {
|
||||
pub client: Browser,
|
||||
pub host: BrowserHost,
|
||||
pub size: SharedViewSize,
|
||||
pub ime_caret: SharedImeCaret,
|
||||
}
|
||||
|
||||
pub struct Browsers {
|
||||
browsers: HashMap<Entity, WebviewBrowser>,
|
||||
sender: TextureSender,
|
||||
receiver: TextureReceiver,
|
||||
ime_caret: SharedImeCaret,
|
||||
}
|
||||
|
||||
impl Default for Browsers {
|
||||
fn default() -> Self {
|
||||
let (sender, receiver) = async_channel::unbounded::<RenderTexture>();
|
||||
let (sender, receiver) = async_channel::unbounded::<RenderTextureMessage>();
|
||||
Browsers {
|
||||
browsers: HashMap::default(),
|
||||
sender,
|
||||
receiver,
|
||||
ime_caret: Rc::new(Cell::new(0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,10 +67,11 @@ impl Browsers {
|
||||
) {
|
||||
let mut context = Self::request_context(requester);
|
||||
let size = Rc::new(Cell::new(webview_size));
|
||||
let ime_caret = Rc::new(Cell::new(0));
|
||||
let browser = browser_host_create_browser_sync(
|
||||
Some(&WindowInfo {
|
||||
windowless_rendering_enabled: true as _,
|
||||
external_begin_frame_enabled: true as _,
|
||||
external_begin_frame_enabled: false as _,
|
||||
#[cfg(target_os = "macos")]
|
||||
parent_view: match _window_handle {
|
||||
Some(RawWindowHandle::AppKit(handle)) => handle.ns_view.as_ptr(),
|
||||
@@ -86,6 +86,7 @@ impl Browsers {
|
||||
Some(&mut self.client_handler(
|
||||
webview,
|
||||
size.clone(),
|
||||
ime_caret.clone(),
|
||||
ipc_event_sender,
|
||||
brp_sender,
|
||||
system_cursor_icon_sender,
|
||||
@@ -99,15 +100,15 @@ impl Browsers {
|
||||
context.as_mut(),
|
||||
)
|
||||
.expect("Failed to create browser");
|
||||
let host = browser.host().expect("Failed to get browser host");
|
||||
let webview_browser = WebviewBrowser {
|
||||
host,
|
||||
client: browser,
|
||||
size,
|
||||
ime_caret,
|
||||
};
|
||||
|
||||
self.browsers.insert(
|
||||
webview,
|
||||
WebviewBrowser {
|
||||
host: browser.host().expect("Failed to get browser host"),
|
||||
client: browser,
|
||||
size,
|
||||
},
|
||||
);
|
||||
self.browsers.insert(webview, webview_browser);
|
||||
}
|
||||
|
||||
pub fn send_external_begin_frame(&mut self) {
|
||||
@@ -222,7 +223,7 @@ impl Browsers {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_receive_texture(&self) -> core::result::Result<RenderTexture, TryRecvError> {
|
||||
pub fn try_receive_texture(&self) -> core::result::Result<RenderTextureMessage, TryRecvError> {
|
||||
self.receiver.try_recv()
|
||||
}
|
||||
|
||||
@@ -326,12 +327,12 @@ impl Browsers {
|
||||
from: i as _,
|
||||
to: i as _,
|
||||
};
|
||||
let replacement_range = self.ime_caret_range();
|
||||
for browser in self
|
||||
.browsers
|
||||
.values()
|
||||
.filter(|b| b.client.focused_frame().is_some())
|
||||
{
|
||||
let replacement_range = Self::ime_caret_range_for(browser);
|
||||
browser.host.ime_set_composition(
|
||||
Some(&text.into()),
|
||||
underlines.len(),
|
||||
@@ -356,12 +357,12 @@ impl Browsers {
|
||||
}
|
||||
|
||||
pub fn set_ime_commit_text(&self, text: &str) {
|
||||
let replacement_range = self.ime_caret_range();
|
||||
for browser in self
|
||||
.browsers
|
||||
.values()
|
||||
.filter(|b| b.client.focused_frame().is_some())
|
||||
{
|
||||
let replacement_range = Self::ime_caret_range_for(browser);
|
||||
browser
|
||||
.host
|
||||
.ime_commit_text(Some(&text.into()), Some(&replacement_range), 0)
|
||||
@@ -387,6 +388,7 @@ impl Browsers {
|
||||
&self,
|
||||
webview: Entity,
|
||||
size: SharedViewSize,
|
||||
ime_caret: SharedImeCaret,
|
||||
ipc_event_sender: Sender<IpcEventRaw>,
|
||||
brp_sender: Sender<BrpMessage>,
|
||||
system_cursor_icon_sender: SystemCursorIconSenderInner,
|
||||
@@ -395,7 +397,7 @@ impl Browsers {
|
||||
webview,
|
||||
self.sender.clone(),
|
||||
size.clone(),
|
||||
self.ime_caret.clone(),
|
||||
ime_caret,
|
||||
))
|
||||
.with_display_handler(DisplayHandlerBuilder::build(system_cursor_icon_sender))
|
||||
.with_message_handler(JsEmitEventHandler::new(webview, ipc_event_sender))
|
||||
@@ -404,8 +406,8 @@ impl Browsers {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ime_caret_range(&self) -> Range {
|
||||
let caret = self.ime_caret.get();
|
||||
fn ime_caret_range_for(browser: &WebviewBrowser) -> Range {
|
||||
let caret = browser.ime_caret.get();
|
||||
Range {
|
||||
from: caret,
|
||||
to: caret,
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
use async_channel::{Receiver, Sender};
|
||||
use bevy::prelude::{Entity, Event};
|
||||
use bevy::prelude::*;
|
||||
use cef::rc::{Rc, RcImpl};
|
||||
use cef::{
|
||||
Browser, CefString, ImplRenderHandler, PaintElementType, Range, Rect, RenderHandler,
|
||||
WrapRenderHandler, sys,
|
||||
};
|
||||
use cef::*;
|
||||
use cef_dll_sys::cef_paint_element_type_t;
|
||||
use std::cell::Cell;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
pub type TextureSender = Sender<RenderTexture>;
|
||||
pub type TextureSender = Sender<RenderTextureMessage>;
|
||||
|
||||
pub type TextureReceiver = Receiver<RenderTexture>;
|
||||
pub type TextureReceiver = Receiver<RenderTextureMessage>;
|
||||
|
||||
/// The texture structure passed from [`CefRenderHandler::OnPaint`](https://cef-builds.spotifycdn.com/docs/106.1/classCefRenderHandler.html#a6547d5c9dd472e6b84706dc81d3f1741).
|
||||
#[derive(Debug, Clone, PartialEq, Event)]
|
||||
pub struct RenderTexture {
|
||||
#[derive(Debug, Clone, PartialEq, Message)]
|
||||
pub struct RenderTextureMessage {
|
||||
/// The entity of target rendering webview.
|
||||
pub webview: Entity,
|
||||
/// The type of the paint element.
|
||||
@@ -100,7 +97,7 @@ impl Clone for RenderHandlerBuilder {
|
||||
}
|
||||
|
||||
impl ImplRenderHandler for RenderHandlerBuilder {
|
||||
fn view_rect(&self, _browser: Option<&mut Browser>, rect: Option<&mut Rect>) {
|
||||
fn view_rect(&self, _browser: Option<&mut Browser>, rect: Option<&mut cef::Rect>) {
|
||||
if let Some(rect) = rect {
|
||||
let size = self.size.get();
|
||||
rect.width = size.x as _;
|
||||
@@ -108,6 +105,33 @@ impl ImplRenderHandler for RenderHandlerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
fn on_paint(
|
||||
&self,
|
||||
_browser: Option<&mut Browser>,
|
||||
type_: PaintElementType,
|
||||
_dirty_rects_count: usize,
|
||||
_dirty_rects: Option<&cef::Rect>,
|
||||
buffer: *const u8,
|
||||
width: c_int,
|
||||
height: c_int,
|
||||
) {
|
||||
let ty = match type_.as_ref() {
|
||||
cef_paint_element_type_t::PET_POPUP => RenderPaintElementType::Popup,
|
||||
_ => RenderPaintElementType::View,
|
||||
};
|
||||
let texture = RenderTextureMessage {
|
||||
webview: self.webview,
|
||||
ty,
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
buffer: unsafe {
|
||||
std::slice::from_raw_parts(buffer, (width * height * 4) as usize).to_vec()
|
||||
},
|
||||
};
|
||||
let _ = self.texture_sender.send_blocking(texture);
|
||||
}
|
||||
|
||||
fn on_text_selection_changed(
|
||||
&self,
|
||||
_browser: Option<&mut Browser>,
|
||||
@@ -119,33 +143,6 @@ impl ImplRenderHandler for RenderHandlerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
fn on_paint(
|
||||
&self,
|
||||
_browser: Option<&mut Browser>,
|
||||
type_: PaintElementType,
|
||||
_dirty_rects_count: usize,
|
||||
_dirty_rects: Option<&Rect>,
|
||||
buffer: *const u8,
|
||||
width: c_int,
|
||||
height: c_int,
|
||||
) {
|
||||
let ty = match type_.as_ref() {
|
||||
cef_paint_element_type_t::PET_POPUP => RenderPaintElementType::Popup,
|
||||
_ => RenderPaintElementType::View,
|
||||
};
|
||||
let texture = RenderTexture {
|
||||
webview: self.webview,
|
||||
ty,
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
buffer: unsafe {
|
||||
std::slice::from_raw_parts(buffer, (width * height * 4) as usize).to_vec()
|
||||
},
|
||||
};
|
||||
let _ = self.texture_sender.send_blocking(texture);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_raw(&self) -> *mut sys::_cef_render_handler_t {
|
||||
self.object.cast()
|
||||
|
||||
@@ -38,18 +38,18 @@ impl Rc for RenderProcessAppBuilder {
|
||||
}
|
||||
|
||||
impl ImplApp for RenderProcessAppBuilder {
|
||||
fn render_process_handler(&self) -> Option<RenderProcessHandler> {
|
||||
Some(RenderProcessHandler::new(
|
||||
RenderProcessHandlerBuilder::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 render_process_handler(&self) -> Option<RenderProcessHandler> {
|
||||
Some(RenderProcessHandler::new(
|
||||
RenderProcessHandlerBuilder::build(),
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_raw(&self) -> *mut _cef_app_t {
|
||||
self.object as *mut _cef_app_t
|
||||
|
||||
Reference in New Issue
Block a user