mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-30 21:30:03 -04:00
@@ -3,6 +3,8 @@ use sctk::reexports::client::protocol::wl_shm::Format;
|
||||
use sctk::shm::slot::{Buffer, SlotPool};
|
||||
use winit_core::cursor::{CursorImage, CustomCursorProvider};
|
||||
|
||||
use crate::image_to_buffer;
|
||||
|
||||
// Wrap in our own type to not impl trait on global type.
|
||||
#[derive(Debug)]
|
||||
pub struct WaylandCustomCursor(pub(crate) CursorImage);
|
||||
@@ -36,25 +38,14 @@ pub struct CustomCursor {
|
||||
impl CustomCursor {
|
||||
pub(crate) fn new(pool: &mut SlotPool, image: &WaylandCustomCursor) -> Self {
|
||||
let image = &image.0;
|
||||
let (buffer, canvas) = pool
|
||||
.create_buffer(
|
||||
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.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;
|
||||
let g = (rgba[1] as f32 * alpha) as u32;
|
||||
let b = (rgba[2] as f32 * alpha) as u32;
|
||||
let color = ((rgba[3] as u32) << 24) + (r << 16) + (g << 8) + b;
|
||||
let array: &mut [u8; 4] = canvas_chunk.try_into().unwrap();
|
||||
*array = color.to_le_bytes();
|
||||
}
|
||||
let buffer = image_to_buffer(
|
||||
image.width() as i32,
|
||||
image.height() as i32,
|
||||
image.buffer(),
|
||||
Format::Argb8888,
|
||||
pool,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
CustomCursor {
|
||||
buffer,
|
||||
|
||||
@@ -5,3 +5,4 @@ pub mod kwin_blur;
|
||||
pub mod wp_fractional_scaling;
|
||||
pub mod wp_viewporter;
|
||||
pub mod xdg_activation;
|
||||
pub mod xdg_toplevel_icon_manager;
|
||||
|
||||
108
winit-wayland/src/types/xdg_toplevel_icon_manager.rs
Normal file
108
winit-wayland/src/types/xdg_toplevel_icon_manager.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
//! Handling of xdg toplevel icon manager, which is used for icon setting requests.
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
|
||||
use sctk::globals::GlobalData;
|
||||
use sctk::shm::slot::{Buffer, SlotPool};
|
||||
use wayland_client::globals::{BindError, GlobalList};
|
||||
use wayland_client::protocol::wl_shm::Format;
|
||||
use wayland_client::{delegate_dispatch, Connection, Dispatch, Proxy, QueueHandle};
|
||||
use wayland_protocols::xdg::toplevel_icon::v1::client::xdg_toplevel_icon_manager_v1::XdgToplevelIconManagerV1;
|
||||
use wayland_protocols::xdg::toplevel_icon::v1::client::xdg_toplevel_icon_v1::XdgToplevelIconV1;
|
||||
use winit_core::icon::{Icon, RgbaIcon};
|
||||
|
||||
use crate::image_to_buffer;
|
||||
use crate::state::WinitState;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct XdgToplevelIconManagerState {
|
||||
xdg_toplevel_icon_manager: XdgToplevelIconManagerV1,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum ToplevelIconError {
|
||||
/// The icon's unsupported
|
||||
Unsupported,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ToplevelIcon {
|
||||
buffer: Buffer,
|
||||
}
|
||||
|
||||
impl ToplevelIcon {
|
||||
pub fn new(icon: Icon, pool: &mut SlotPool) -> Result<Self, ToplevelIconError> {
|
||||
let icon = match icon.cast_ref::<RgbaIcon>() {
|
||||
Some(icon) => icon,
|
||||
None => return Err(ToplevelIconError::Unsupported),
|
||||
};
|
||||
|
||||
let buffer = image_to_buffer(
|
||||
icon.width() as i32,
|
||||
icon.height() as i32,
|
||||
icon.buffer(),
|
||||
Format::Argb8888,
|
||||
pool,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Ok(Self { buffer })
|
||||
}
|
||||
|
||||
pub fn add_buffer(&self, xdg_toplevel_icon: &XdgToplevelIconV1) {
|
||||
xdg_toplevel_icon.add_buffer(self.buffer.wl_buffer(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ToplevelIconError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ToplevelIconError::Unsupported => write!(f, "this icon is unsupported on Wayland"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl XdgToplevelIconManagerState {
|
||||
pub fn bind(
|
||||
globals: &GlobalList,
|
||||
queue_handle: &QueueHandle<WinitState>,
|
||||
) -> Result<Self, BindError> {
|
||||
let xdg_toplevel_icon_manager = globals.bind(queue_handle, 1..=1, GlobalData)?;
|
||||
Ok(Self { xdg_toplevel_icon_manager })
|
||||
}
|
||||
|
||||
pub fn global(&self) -> &XdgToplevelIconManagerV1 {
|
||||
&self.xdg_toplevel_icon_manager
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<XdgToplevelIconManagerV1, GlobalData, WinitState> for XdgToplevelIconManagerState {
|
||||
fn event(
|
||||
_state: &mut WinitState,
|
||||
_proxy: &XdgToplevelIconManagerV1,
|
||||
_event: <XdgToplevelIconManagerV1 as Proxy>::Event,
|
||||
_data: &GlobalData,
|
||||
_conn: &Connection,
|
||||
_qhandle: &QueueHandle<WinitState>,
|
||||
) {
|
||||
// No events.
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<XdgToplevelIconV1, GlobalData, WinitState> for XdgToplevelIconManagerState {
|
||||
fn event(
|
||||
_state: &mut WinitState,
|
||||
_proxy: &XdgToplevelIconV1,
|
||||
_event: <XdgToplevelIconV1 as Proxy>::Event,
|
||||
_data: &GlobalData,
|
||||
_conn: &Connection,
|
||||
_qhandle: &QueueHandle<WinitState>,
|
||||
) {
|
||||
// No events.
|
||||
}
|
||||
}
|
||||
|
||||
delegate_dispatch!(WinitState: [XdgToplevelIconManagerV1: GlobalData] => XdgToplevelIconManagerState);
|
||||
delegate_dispatch!(WinitState: [XdgToplevelIconV1: GlobalData] => XdgToplevelIconManagerState);
|
||||
Reference in New Issue
Block a user