winit-core: move cursor
This commit is contained in:
parent
cbb29ab526
commit
446482367b
8 changed files with 77 additions and 38 deletions
|
|
@ -301,7 +301,7 @@ pub mod application;
|
|||
pub mod changelog;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
mod cursor;
|
||||
use winit_core::cursor;
|
||||
pub mod event;
|
||||
pub mod event_loop;
|
||||
pub use winit_core::{icon, keyboard, monitor};
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ impl CustomCursor {
|
|||
}
|
||||
|
||||
pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Result<Retained<NSCursor>, RequestError> {
|
||||
let width = cursor.width;
|
||||
let height = cursor.height;
|
||||
let width = cursor.width();
|
||||
let height = cursor.height();
|
||||
|
||||
let bitmap = unsafe {
|
||||
NSBitmapImageRep::initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(
|
||||
|
|
@ -60,15 +60,16 @@ pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Result<Retained<NSCurso
|
|||
32,
|
||||
)
|
||||
}.ok_or_else(|| os_error!("parent view should be installed in a window"))?;
|
||||
let bitmap_data = unsafe { slice::from_raw_parts_mut(bitmap.bitmapData(), cursor.rgba.len()) };
|
||||
bitmap_data.copy_from_slice(&cursor.rgba);
|
||||
let bitmap_data =
|
||||
unsafe { slice::from_raw_parts_mut(bitmap.bitmapData(), cursor.buffer().len()) };
|
||||
bitmap_data.copy_from_slice(cursor.buffer());
|
||||
|
||||
let image = unsafe {
|
||||
NSImage::initWithSize(NSImage::alloc(), NSSize::new(width.into(), height.into()))
|
||||
};
|
||||
unsafe { image.addRepresentation(&bitmap) };
|
||||
|
||||
let hotspot = NSPoint::new(cursor.hotspot_x as f64, cursor.hotspot_y as f64);
|
||||
let hotspot = NSPoint::new(cursor.hotspot_x() as f64, cursor.hotspot_y() as f64);
|
||||
|
||||
Ok(NSCursor::initWithImage_hotSpot(NSCursor::alloc(), &image, hotspot))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@ impl CustomCursor {
|
|||
let image = &image.0;
|
||||
let (buffer, canvas) = pool
|
||||
.create_buffer(
|
||||
image.width as i32,
|
||||
image.height as i32,
|
||||
4 * (image.width as i32),
|
||||
image.width() as i32,
|
||||
image.height() as i32,
|
||||
4 * (image.width() as i32),
|
||||
Format::Argb8888,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
for (canvas_chunk, rgba) in canvas.chunks_exact_mut(4).zip(image.rgba.chunks_exact(4)) {
|
||||
for (canvas_chunk, rgba) in canvas.chunks_exact_mut(4).zip(image.buffer().chunks_exact(4)) {
|
||||
// Alpha in buffer is premultiplied.
|
||||
let alpha = rgba[3] as f32 / 255.;
|
||||
let r = (rgba[0] as f32 * alpha) as u32;
|
||||
|
|
@ -59,10 +59,10 @@ impl CustomCursor {
|
|||
|
||||
CustomCursor {
|
||||
buffer,
|
||||
w: image.width as i32,
|
||||
h: image.height as i32,
|
||||
hotspot_x: image.hotspot_x as i32,
|
||||
hotspot_y: image.hotspot_y as i32,
|
||||
w: image.width() as i32,
|
||||
h: image.height() as i32,
|
||||
hotspot_x: image.hotspot_x() as i32,
|
||||
hotspot_y: image.hotspot_y() as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ impl CustomCursor {
|
|||
};
|
||||
|
||||
// Reverse RGBA order to BGRA.
|
||||
cursor.rgba.chunks_mut(4).for_each(|chunk| {
|
||||
cursor.buffer_mut().chunks_mut(4).for_each(|chunk| {
|
||||
let chunk: &mut [u8; 4] = chunk.try_into().unwrap();
|
||||
chunk[0..3].reverse();
|
||||
|
||||
|
|
@ -222,11 +222,11 @@ impl CustomCursor {
|
|||
let cursor = event_loop
|
||||
.xconn
|
||||
.create_cursor_from_image(
|
||||
cursor.width,
|
||||
cursor.height,
|
||||
cursor.hotspot_x,
|
||||
cursor.hotspot_y,
|
||||
&cursor.rgba,
|
||||
cursor.width(),
|
||||
cursor.height(),
|
||||
cursor.hotspot_x(),
|
||||
cursor.hotspot_y(),
|
||||
cursor.buffer(),
|
||||
)
|
||||
.map_err(|err| os_error!(err))?;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@ use super::backend::Style;
|
|||
use super::main_thread::{MainThreadMarker, MainThreadSafe};
|
||||
use super::r#async::{AbortHandle, Abortable, DropAbortHandle, Notified, Notifier};
|
||||
use super::ActiveEventLoop;
|
||||
use crate::cursor::{
|
||||
Cursor, CursorAnimation, CursorImage, CustomCursorProvider, CustomCursorSource,
|
||||
};
|
||||
use crate::cursor::{Cursor, CursorImage, CustomCursorProvider, CustomCursorSource};
|
||||
use crate::platform::web::CustomCursorError;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -48,7 +46,8 @@ impl CustomCursor {
|
|||
from_url(UrlType::Plain(url), hotspot_x, hotspot_y),
|
||||
false,
|
||||
),
|
||||
CustomCursorSource::Animation(CursorAnimation { duration, cursors }) => {
|
||||
CustomCursorSource::Animation(animation) => {
|
||||
let (duration, cursors) = animation.into_raw();
|
||||
Self::build_spawn(
|
||||
event_loop,
|
||||
from_animation(event_loop.runner.main_thread(), duration, cursors.into_iter()),
|
||||
|
|
@ -512,17 +511,17 @@ fn from_rgba(
|
|||
fn new(array: Uint8ClampedArray, sw: u32) -> Result<ImageDataExt, JsValue>;
|
||||
}
|
||||
|
||||
let array = Uint8Array::new_with_length(image.rgba.len() as u32);
|
||||
array.copy_from(&image.rgba);
|
||||
let array = Uint8Array::new_with_length(image.buffer().len() as u32);
|
||||
array.copy_from(image.buffer());
|
||||
let array = Uint8ClampedArray::new(&array);
|
||||
ImageDataExt::new(array, image.width as u32)
|
||||
ImageDataExt::new(array, image.width() as u32)
|
||||
.map(JsValue::from)
|
||||
.map(ImageData::unchecked_from_js)
|
||||
};
|
||||
#[cfg(not(target_feature = "atomics"))]
|
||||
let result = ImageData::new_with_u8_clamped_array(
|
||||
wasm_bindgen::Clamped(&image.rgba),
|
||||
image.width as u32,
|
||||
wasm_bindgen::Clamped(image.buffer()),
|
||||
image.width() as u32,
|
||||
);
|
||||
let image_data = result.expect("found wrong image size");
|
||||
|
||||
|
|
@ -538,7 +537,10 @@ fn from_rgba(
|
|||
.expect("unexpected exception in `createImageBitmap()`"),
|
||||
);
|
||||
|
||||
let CursorImage { width, height, hotspot_x, hotspot_y, .. } = *image;
|
||||
let width = image.width();
|
||||
let height = image.height();
|
||||
let hotspot_x = image.hotspot_x();
|
||||
let hotspot_y = image.hotspot_y();
|
||||
async move {
|
||||
let bitmap: ImageBitmap =
|
||||
bitmap.await.expect("found invalid state in `ImageData`").unchecked_into();
|
||||
|
|
|
|||
|
|
@ -184,11 +184,11 @@ impl CustomCursorProvider for WinCursor {
|
|||
|
||||
impl WinCursor {
|
||||
pub(crate) fn new(image: &CursorImage) -> Result<Self, RequestError> {
|
||||
let mut bgra = image.rgba.clone();
|
||||
let mut bgra = Vec::from(image.buffer());
|
||||
bgra.chunks_exact_mut(4).for_each(|chunk| chunk.swap(0, 2));
|
||||
|
||||
let w = image.width as i32;
|
||||
let h = image.height as i32;
|
||||
let w = image.width() as i32;
|
||||
let h = image.height() as i32;
|
||||
|
||||
unsafe {
|
||||
let hdc_screen = GetDC(ptr::null_mut());
|
||||
|
|
@ -215,8 +215,8 @@ impl WinCursor {
|
|||
|
||||
let icon_info = ICONINFO {
|
||||
fIcon: 0,
|
||||
xHotspot: image.hotspot_x as u32,
|
||||
yHotspot: image.hotspot_y as u32,
|
||||
xHotspot: image.hotspot_x() as u32,
|
||||
yHotspot: image.hotspot_y() as u32,
|
||||
hbmMask: hbm_mask,
|
||||
hbmColor: hbm_color,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use std::time::Duration;
|
|||
|
||||
use cursor_icon::CursorIcon;
|
||||
|
||||
use crate::utils::{impl_dyn_casting, AsAny};
|
||||
use crate::as_any::{impl_dyn_casting, AsAny};
|
||||
|
||||
/// The maximum width and height for a cursor when using [`CustomCursorSource::from_rgba`].
|
||||
pub const MAX_CURSOR_SIZE: u16 = 2048;
|
||||
|
|
@ -75,7 +75,7 @@ impl From<CustomCursor> for Cursor {
|
|||
/// # }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CustomCursor(pub(crate) Arc<dyn CustomCursorProvider>);
|
||||
pub struct CustomCursor(pub Arc<dyn CustomCursorProvider>);
|
||||
|
||||
pub trait CustomCursorProvider: AsAny + fmt::Debug + Send + Sync {
|
||||
/// Whether a cursor was backed by animation.
|
||||
|
|
@ -235,7 +235,6 @@ impl fmt::Display for BadAnimation {
|
|||
impl Error for BadAnimation {}
|
||||
|
||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||
#[allow(dead_code)]
|
||||
pub struct CursorImage {
|
||||
pub(crate) rgba: Vec<u8>,
|
||||
pub(crate) width: u16,
|
||||
|
|
@ -277,6 +276,30 @@ impl CursorImage {
|
|||
|
||||
Ok(CursorImage { rgba, width, height, hotspot_x, hotspot_y })
|
||||
}
|
||||
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
self.rgba.as_slice()
|
||||
}
|
||||
|
||||
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
||||
self.rgba.as_mut_slice()
|
||||
}
|
||||
|
||||
pub fn width(&self) -> u16 {
|
||||
self.width
|
||||
}
|
||||
|
||||
pub fn height(&self) -> u16 {
|
||||
self.height
|
||||
}
|
||||
|
||||
pub fn hotspot_x(&self) -> u16 {
|
||||
self.hotspot_x
|
||||
}
|
||||
|
||||
pub fn hotspot_y(&self) -> u16 {
|
||||
self.hotspot_y
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
|
@ -297,4 +320,16 @@ impl CursorAnimation {
|
|||
|
||||
Ok(Self { duration, cursors })
|
||||
}
|
||||
|
||||
pub fn duration(&self) -> Duration {
|
||||
self.duration
|
||||
}
|
||||
|
||||
pub fn cursors(&self) -> &[CustomCursor] {
|
||||
self.cursors.as_slice()
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> (Duration, Vec<CustomCursor>) {
|
||||
(self.duration, self.cursors)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#[macro_use]
|
||||
pub mod as_any;
|
||||
pub mod cursor;
|
||||
pub mod icon;
|
||||
pub mod keyboard;
|
||||
pub mod monitor;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue