Skip to content
Merged
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
4 changes: 2 additions & 2 deletions desktop/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,8 @@ impl App {
}
}
AppEvent::CursorChange(cursor) => {
if let Some(window) = &self.window {
window.set_cursor(cursor);
if let Some(window) = &mut self.window {
window.set_cursor(event_loop, cursor);
}
}
AppEvent::CloseWindow => {
Expand Down
19 changes: 11 additions & 8 deletions desktop/src/cef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@
//!
//! The system gracefully falls back to CPU textures when hardware acceleration is unavailable.

use crate::event::{AppEvent, AppEventScheduler};
use crate::render::FrameBufferRef;
use crate::wrapper::{WgpuContext, deserialize_editor_message};
use std::fs::File;
use std::io::{Cursor, Read};
use std::io;
use std::io::Read;
use std::path::PathBuf;
use std::sync::mpsc::Receiver;
use std::sync::{Arc, Mutex};
use std::time::Instant;

use crate::event::{AppEvent, AppEventScheduler};
use crate::render::FrameBufferRef;
use crate::window::Cursor;
use crate::wrapper::{WgpuContext, deserialize_editor_message};

mod consts;
mod context;
mod dirs;
Expand All @@ -42,7 +45,7 @@ pub(crate) trait CefEventHandler: Send + Sync + 'static {
#[cfg(feature = "accelerated_paint")]
fn draw_gpu(&self, shared_texture: SharedTextureHandle);
fn load_resource(&self, path: PathBuf) -> Option<Resource>;
fn cursor_change(&self, cursor: winit::cursor::Cursor);
fn cursor_change(&self, cursor: Cursor);
/// Schedule the main event loop to run the CEF event loop after the timeout.
/// See [`_cef_browser_process_handler_t::on_schedule_message_pump_work`] for more documentation.
fn schedule_cef_message_loop_work(&self, scheduled_time: Instant);
Expand Down Expand Up @@ -105,7 +108,7 @@ pub(crate) struct Resource {
#[expect(dead_code)]
#[derive(Clone)]
pub(crate) enum ResourceReader {
Embedded(Cursor<&'static [u8]>),
Embedded(io::Cursor<&'static [u8]>),
File(Arc<File>),
}
impl Read for ResourceReader {
Expand Down Expand Up @@ -227,7 +230,7 @@ impl CefEventHandler for CefHandler {
&& let Some(file) = resources.get_file(&path)
{
return Some(Resource {
reader: ResourceReader::Embedded(Cursor::new(file.contents())),
reader: ResourceReader::Embedded(io::Cursor::new(file.contents())),
mimetype,
});
}
Expand All @@ -252,7 +255,7 @@ impl CefEventHandler for CefHandler {
None
}

fn cursor_change(&self, cursor: winit::cursor::Cursor) {
fn cursor_change(&self, cursor: Cursor) {
self.app_event_scheduler.schedule(AppEvent::CursorChange(cursor));
}

Expand Down
19 changes: 16 additions & 3 deletions desktop/src/cef/internal/display_handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use cef::rc::{Rc, RcImpl};
use cef::sys::{_cef_display_handler_t, cef_base_ref_counted_t, cef_cursor_type_t::*, cef_log_severity_t::*};
use cef::{CefString, ImplDisplayHandler, WrapDisplayHandler};
use cef::{CefString, ImplDisplayHandler, Point, Size, WrapDisplayHandler};
use winit::cursor::CursorIcon;

use crate::cef::CefEventHandler;
Expand All @@ -25,7 +25,21 @@ type CefCursorHandle = cef::CursorHandle;
type CefCursorHandle = *mut u8;

impl<H: CefEventHandler> ImplDisplayHandler for DisplayHandlerImpl<H> {
fn on_cursor_change(&self, _browser: Option<&mut cef::Browser>, _cursor: CefCursorHandle, cursor_type: cef::CursorType, _custom_cursor_info: Option<&cef::CursorInfo>) -> std::ffi::c_int {
fn on_cursor_change(&self, _browser: Option<&mut cef::Browser>, _cursor: CefCursorHandle, cursor_type: cef::CursorType, custom_cursor_info: Option<&cef::CursorInfo>) -> std::ffi::c_int {
if let Some(custom_cursor_info) = custom_cursor_info {
let Size { width, height } = custom_cursor_info.size;
let Point { x: hotspot_x, y: hotspot_y } = custom_cursor_info.hotspot;
let buffer_size = (width * height * 4) as usize;
let buffer_ptr = custom_cursor_info.buffer as *const u8;

if !buffer_ptr.is_null() && buffer_ptr.align_offset(std::mem::align_of::<u8>()) == 0 {
let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) }.to_vec();
let cursor = winit::cursor::CustomCursorSource::from_rgba(buffer, width as u16, height as u16, hotspot_x as u16, hotspot_y as u16).unwrap();
self.event_handler.cursor_change(cursor.into());
return 1; // We handled the cursor change.
}
}

let cursor = match cursor_type.into() {
CT_POINTER => CursorIcon::Default,
CT_CROSS => CursorIcon::Crosshair,
Expand Down Expand Up @@ -72,7 +86,6 @@ impl<H: CefEventHandler> ImplDisplayHandler for DisplayHandlerImpl<H> {
CT_GRABBING => CursorIcon::Grabbing,
CT_MIDDLE_PANNING_VERTICAL => CursorIcon::AllScroll,
CT_MIDDLE_PANNING_HORIZONTAL => CursorIcon::AllScroll,
CT_CUSTOM => CursorIcon::Default,
CT_DND_NONE => CursorIcon::Default,
CT_DND_MOVE => CursorIcon::Move,
CT_DND_COPY => CursorIcon::Copy,
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::wrapper::messages::DesktopWrapperMessage;

pub(crate) enum AppEvent {
UiUpdate(wgpu::Texture),
CursorChange(winit::cursor::Cursor),
CursorChange(crate::window::Cursor),
ScheduleBrowserWork(std::time::Instant),
WebCommunicationInitialized,
DesktopWrapperMessage(DesktopWrapperMessage),
Expand Down
38 changes: 37 additions & 1 deletion desktop/src/window.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use std::collections::HashMap;
use std::sync::Arc;
use winit::cursor::{CursorIcon, CustomCursor, CustomCursorSource};
use winit::event_loop::ActiveEventLoop;
use winit::window::{Window as WinitWindow, WindowAttributes};

Expand Down Expand Up @@ -35,6 +37,7 @@ pub(crate) struct Window {
winit_window: Arc<dyn winit::window::Window>,
#[allow(dead_code)]
native_handle: native::NativeWindowImpl,
custom_cursors: HashMap<CustomCursorSource, CustomCursor>,
}

impl Window {
Expand All @@ -57,6 +60,7 @@ impl Window {
Self {
winit_window: winit_window.into(),
native_handle,
custom_cursors: HashMap::new(),
}
}

Expand Down Expand Up @@ -108,11 +112,43 @@ impl Window {
self.native_handle.show_all();
}

pub(crate) fn set_cursor(&self, cursor: winit::cursor::Cursor) {
pub(crate) fn set_cursor(&mut self, event_loop: &dyn ActiveEventLoop, cursor: Cursor) {
let cursor = match cursor {
Cursor::Icon(cursor_icon) => cursor_icon.into(),
Cursor::Custom(custom_cursor_source) => {
let custom_cursor = match self.custom_cursors.get(&custom_cursor_source).cloned() {
Some(cursor) => cursor,
None => {
let Ok(custom_cursor) = event_loop.create_custom_cursor(custom_cursor_source.clone()) else {
tracing::error!("Failed to create custom cursor");
return;
};
self.custom_cursors.insert(custom_cursor_source, custom_cursor.clone());
custom_cursor
}
};
custom_cursor.into()
}
};
self.winit_window.set_cursor(cursor);
}

pub(crate) fn update_menu(&self, entries: Vec<MenuItem>) {
self.native_handle.update_menu(entries);
}
}

pub(crate) enum Cursor {
Icon(CursorIcon),
Custom(CustomCursorSource),
}
impl From<CursorIcon> for Cursor {
fn from(icon: CursorIcon) -> Self {
Cursor::Icon(icon)
}
}
impl From<CustomCursorSource> for Cursor {
fn from(custom: CustomCursorSource) -> Self {
Cursor::Custom(custom)
}
}
2 changes: 1 addition & 1 deletion frontend/package-installer.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ if (isInstallNeeded()) {
console.log("Finished installing npm packages.");
} catch (_) {
// eslint-disable-next-line no-console
console.error("Failed to install npm packages. Please run `npm install` from the `/frontend` directory.");
console.error("Failed to install npm packages. Please delete the `node_modules` folder and run `npm install` from the `/frontend` directory.");
process.exit(1);
}
} else {
Expand Down