Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 30 additions & 16 deletions desktop/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::thread;
use std::time::Duration;
use std::time::Instant;
use winit::application::ApplicationHandler;
use winit::dpi::PhysicalSize;
use winit::event::WindowEvent;
use winit::event_loop::ActiveEventLoop;
use winit::event_loop::ControlFlow;
Expand All @@ -25,8 +26,9 @@ use crate::wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, seri
pub(crate) struct App {
cef_context: Box<dyn cef::CefContext>,
window: Option<Window>,
window_scale: f64,
cef_schedule: Option<Instant>,
cef_window_size_sender: Sender<cef::WindowSize>,
cef_view_info_sender: Sender<cef::ViewInfoUpdate>,
graphics_state: Option<GraphicsState>,
wgpu_context: WgpuContext,
app_event_receiver: Receiver<AppEvent>,
Expand All @@ -44,7 +46,7 @@ pub(crate) struct App {
impl App {
pub(crate) fn new(
cef_context: Box<dyn cef::CefContext>,
window_size_sender: Sender<cef::WindowSize>,
cef_view_info_sender: Sender<cef::ViewInfoUpdate>,
wgpu_context: WgpuContext,
app_event_receiver: Receiver<AppEvent>,
app_event_scheduler: AppEventScheduler,
Expand All @@ -66,9 +68,10 @@ impl App {
Self {
cef_context,
window: None,
window_scale: 1.0,
cef_schedule: Some(Instant::now()),
graphics_state: None,
cef_window_size_sender: window_size_sender,
cef_view_info_sender,
wgpu_context,
app_event_receiver,
app_event_scheduler,
Expand Down Expand Up @@ -147,19 +150,19 @@ impl App {
}
});
}
DesktopFrontendMessage::UpdateViewportBounds { x, y, width, height } => {
DesktopFrontendMessage::UpdateViewportPhysicalBounds { x, y, width, height } => {
if let Some(graphics_state) = &mut self.graphics_state
&& let Some(window) = &self.window
{
let window_size = window.surface_size();

let viewport_offset_x = x / window_size.width as f32;
let viewport_offset_y = y / window_size.height as f32;
graphics_state.set_viewport_offset([viewport_offset_x, viewport_offset_y]);
let viewport_offset_x = x / window_size.width as f64;
let viewport_offset_y = y / window_size.height as f64;
graphics_state.set_viewport_offset([viewport_offset_x as f32, viewport_offset_y as f32]);

let viewport_scale_x = if width != 0.0 { window_size.width as f32 / width } else { 1.0 };
let viewport_scale_y = if height != 0.0 { window_size.height as f32 / height } else { 1.0 };
graphics_state.set_viewport_scale([viewport_scale_x, viewport_scale_y]);
let viewport_scale_x = if width != 0.0 { window_size.width as f64 / width } else { 1.0 };
let viewport_scale_y = if height != 0.0 { window_size.height as f64 / height } else { 1.0 };
graphics_state.set_viewport_scale([viewport_scale_x as f32, viewport_scale_y as f32]);
}
}
DesktopFrontendMessage::UpdateOverlays(scene) => {
Expand Down Expand Up @@ -352,14 +355,17 @@ impl App {
impl ApplicationHandler for App {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window = Window::new(event_loop, self.app_event_scheduler.clone());

self.window_scale = window.scale_factor();
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(self.window_scale));
self.cef_context.notify_view_info_changed();

self.window = Some(window);

let graphics_state = GraphicsState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone());

self.graphics_state = Some(graphics_state);

tracing::info!("Winit window created and ready");

self.desktop_wrapper.init(self.wgpu_context.clone());

#[cfg(target_os = "windows")]
Expand All @@ -378,20 +384,28 @@ impl ApplicationHandler for App {
}

fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, _window_id: WindowId, event: WindowEvent) {
self.cef_context.handle_window_event(&event);
self.cef_context.handle_window_event(&event, self.window_scale);

match event {
WindowEvent::CloseRequested => {
self.app_event_scheduler.schedule(AppEvent::CloseWindow);
}
WindowEvent::SurfaceResized(size) => {
let _ = self.cef_window_size_sender.send(size.into());
self.cef_context.notify_of_resize();
WindowEvent::SurfaceResized(PhysicalSize { width, height }) => {
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size {
width: width as usize,
height: height as usize,
});
self.cef_context.notify_view_info_changed();
if let Some(window) = &self.window {
let maximized = window.is_maximized();
self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateMaximized { maximized }));
}
}
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
self.window_scale = scale_factor;
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(self.window_scale));
self.cef_context.notify_view_info_changed();
}
WindowEvent::RedrawRequested => {
let Some(ref mut graphics_state) = self.graphics_state else { return };
// Only rerender once we have a new UI texture to display
Expand Down
94 changes: 64 additions & 30 deletions desktop/src/cef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use texture_import::SharedTextureHandle;
pub(crate) use context::{CefContext, CefContextBuilder, InitError};

pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static {
fn window_size(&self) -> WindowSize;
fn view_info(&self) -> ViewInfo;
fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>);
#[cfg(feature = "accelerated_paint")]
fn draw_gpu(&self, shared_texture: SharedTextureHandle);
Expand All @@ -53,21 +53,58 @@ pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static {
}

#[derive(Clone, Copy)]
pub(crate) struct WindowSize {
pub(crate) width: usize,
pub(crate) height: usize,
pub(crate) struct ViewInfo {
width: usize,
height: usize,
scale: f64,
}
impl WindowSize {
pub(crate) fn new(width: usize, height: usize) -> Self {
Self { width, height }
impl ViewInfo {
pub(crate) fn new() -> Self {
Self { width: 1, height: 1, scale: 1.0 }
}
pub(crate) fn apply_update(&mut self, update: ViewInfoUpdate) {
match update {
ViewInfoUpdate::Size { width, height } if width > 0 && height > 0 => {
self.width = width;
self.height = height;
}
ViewInfoUpdate::Scale(scale) if scale > 0.0 => {
self.scale = scale;
}
_ => {}
}
}
pub(crate) fn scale(&self) -> f64 {
self.scale
}
pub(crate) fn zoom(&self) -> f64 {
self.scale.ln() / 1.2f64.ln()
}
pub(crate) fn logical_width(&self) -> usize {
(self.width as f64 / self.scale).round() as usize
}
pub(crate) fn logical_height(&self) -> usize {
(self.height as f64 / self.scale).round() as usize
}

pub(crate) fn physical_width(&self) -> usize {
self.width
}
pub(crate) fn physical_height(&self) -> usize {
self.height
}
}
impl From<winit::dpi::PhysicalSize<u32>> for WindowSize {
fn from(size: winit::dpi::PhysicalSize<u32>) -> Self {
Self::new(size.width as usize, size.height as usize)
impl Default for ViewInfo {
fn default() -> Self {
Self::new()
}
}

pub(crate) enum ViewInfoUpdate {
Size { width: usize, height: usize },
Scale(f64),
}

#[derive(Clone)]
pub(crate) struct Resource {
pub(crate) reader: ResourceReader,
Expand All @@ -93,30 +130,30 @@ impl Read for ResourceReader {
pub(crate) struct CefHandler {
wgpu_context: WgpuContext,
app_event_scheduler: AppEventScheduler,
window_size_receiver: Arc<Mutex<WindowSizeReceiver>>,
view_info_receiver: Arc<Mutex<ViewInfoReceiver>>,
}

impl CefHandler {
pub(crate) fn new(wgpu_context: WgpuContext, app_event_scheduler: AppEventScheduler, window_size_receiver: Receiver<WindowSize>) -> Self {
pub(crate) fn new(wgpu_context: WgpuContext, app_event_scheduler: AppEventScheduler, view_info_receiver: Receiver<ViewInfoUpdate>) -> Self {
Self {
wgpu_context,
app_event_scheduler,
window_size_receiver: Arc::new(Mutex::new(WindowSizeReceiver::new(window_size_receiver))),
view_info_receiver: Arc::new(Mutex::new(ViewInfoReceiver::new(view_info_receiver))),
}
}
}

impl CefEventHandler for CefHandler {
fn window_size(&self) -> WindowSize {
let Ok(mut guard) = self.window_size_receiver.lock() else {
tracing::error!("Failed to lock window_size_receiver");
return WindowSize::new(1, 1);
fn view_info(&self) -> ViewInfo {
let Ok(mut guard) = self.view_info_receiver.lock() else {
tracing::error!("Failed to lock view_info_receiver");
return ViewInfo::new();
};
let WindowSizeReceiver { receiver, window_size } = &mut *guard;
for new_window_size in receiver.try_iter() {
*window_size = new_window_size;
let ViewInfoReceiver { receiver, view_info } = &mut *guard;
for update in receiver.try_iter() {
view_info.apply_update(update);
}
*window_size
*view_info
}
fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>) {
let width = frame_buffer.width() as u32;
Expand Down Expand Up @@ -246,15 +283,12 @@ impl CefEventHandler for CefHandler {
}
}

struct WindowSizeReceiver {
window_size: WindowSize,
receiver: Receiver<WindowSize>,
struct ViewInfoReceiver {
view_info: ViewInfo,
receiver: Receiver<ViewInfoUpdate>,
}
impl WindowSizeReceiver {
fn new(window_size_receiver: Receiver<WindowSize>) -> Self {
Self {
window_size: WindowSize { width: 1, height: 1 },
receiver: window_size_receiver,
}
impl ViewInfoReceiver {
fn new(receiver: Receiver<ViewInfoUpdate>) -> Self {
Self { view_info: ViewInfo::new(), receiver }
}
}
4 changes: 2 additions & 2 deletions desktop/src/cef/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ pub(crate) use builder::{CefContextBuilder, InitError};
pub(crate) trait CefContext {
fn work(&mut self);

fn handle_window_event(&mut self, event: &winit::event::WindowEvent);
fn handle_window_event(&mut self, event: &winit::event::WindowEvent, scale: f64);

fn notify_of_resize(&self);
fn notify_view_info_changed(&self);

fn send_web_message(&self, message: Vec<u8>);
}
1 change: 1 addition & 0 deletions desktop/src/cef/context/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ fn create_browser<H: CefEventHandler>(event_handler: H, instance_dir: PathBuf, d

if let Some(browser) = browser {
Ok(SingleThreadedCefContext {
event_handler,
browser,
input_state: InputState::default(),
instance_dir,
Expand Down
9 changes: 5 additions & 4 deletions desktop/src/cef/context/multithreaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use cef::{Task, ThreadId, post_task};
use std::cell::RefCell;
use winit::event::WindowEvent;

use crate::cef::CefEventHandler;
use crate::cef::internal::task::ClosureTask;

use super::CefContext;
Expand All @@ -19,22 +20,22 @@ impl CefContext for MultiThreadedCefContextProxy {
// CEF handles its own message loop in multi-threaded mode
}

fn handle_window_event(&mut self, event: &WindowEvent) {
fn handle_window_event(&mut self, event: &WindowEvent, scale: f64) {
let event_clone = event.clone();
run_on_ui_thread(move || {
CONTEXT.with(|b| {
if let Some(context) = b.borrow_mut().as_mut() {
context.handle_window_event(&event_clone);
context.handle_window_event(&event_clone, scale);
}
});
});
}

fn notify_of_resize(&self) {
fn notify_view_info_changed(&self) {
run_on_ui_thread(move || {
CONTEXT.with(|b| {
if let Some(context) = b.borrow_mut().as_mut() {
context.notify_of_resize();
context.notify_view_info_changed();
}
});
});
Expand Down
15 changes: 9 additions & 6 deletions desktop/src/cef/context/singlethreaded.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use cef::{Browser, ImplBrowser, ImplBrowserHost};
use cef::{Browser, ImplBrowser};
use winit::event::WindowEvent;

use crate::cef::input;
use crate::cef::input::InputState;
use crate::cef::internal::NotifyViewInfoChanged;
use crate::cef::ipc::{MessageType, SendMessage};
use crate::cef::{CefEventHandler, input};

use super::CefContext;

pub(super) struct SingleThreadedCefContext {
pub(super) event_handler: Box<dyn CefEventHandler>,
pub(super) browser: Browser,
pub(super) input_state: InputState,
pub(super) instance_dir: std::path::PathBuf,
Expand All @@ -18,12 +20,13 @@ impl CefContext for SingleThreadedCefContext {
cef::do_message_loop_work();
}

fn handle_window_event(&mut self, event: &WindowEvent) {
input::handle_window_event(&self.browser, &mut self.input_state, event)
fn handle_window_event(&mut self, event: &WindowEvent, scale: f64) {
input::handle_window_event(&self.browser, &mut self.input_state, event, scale)
}

fn notify_of_resize(&self) {
self.browser.host().unwrap().was_resized();
fn notify_view_info_changed(&self) {
let view_info = self.event_handler.view_info();
self.browser.host().unwrap().notify_view_info_changed(&view_info);
}

fn send_web_message(&self, message: Vec<u8>) {
Expand Down
Loading
Loading