iced_winit/platform_specific/
mod.rs
1use std::collections::HashMap;
5
6use iced_graphics::Compositor;
7use iced_runtime::{
8 core::{window, Vector},
9 user_interface, Debug,
10};
11use winit::raw_window_handle::HasWindowHandle;
12
13#[cfg(all(feature = "wayland", target_os = "linux"))]
14pub mod wayland;
15
16#[cfg(all(feature = "wayland", target_os = "linux"))]
17pub use wayland::*;
18#[cfg(all(feature = "wayland", target_os = "linux"))]
19use wayland_backend::client::Backend;
20
21use crate::{program::WindowManager, Program};
22
23#[derive(Debug)]
24pub enum Event {
25 #[cfg(all(feature = "wayland", target_os = "linux"))]
26 Wayland(sctk_event::SctkEvent),
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub enum SurfaceIdWrapper {
31 LayerSurface(window::Id),
32 Window(window::Id),
33 Popup(window::Id),
34 SessionLock(window::Id),
35 Subsurface(window::Id),
36}
37impl SurfaceIdWrapper {
38 pub fn inner(&self) -> window::Id {
39 match self {
40 SurfaceIdWrapper::LayerSurface(id) => *id,
41 SurfaceIdWrapper::Window(id) => *id,
42 SurfaceIdWrapper::Popup(id) => *id,
43 SurfaceIdWrapper::SessionLock(id) => *id,
44 SurfaceIdWrapper::Subsurface(id) => *id,
45 }
46 }
47}
48
49#[derive(Debug, Default)]
50pub struct PlatformSpecific {
51 #[cfg(all(feature = "wayland", target_os = "linux"))]
52 wayland: WaylandSpecific,
53}
54
55impl PlatformSpecific {
56 pub(crate) fn send_action(
57 &mut self,
58 action: iced_runtime::platform_specific::Action,
59 ) {
60 match action {
61 #[cfg(all(feature = "wayland", target_os = "linux"))]
62 iced_runtime::platform_specific::Action::Wayland(a) => {
63 self.send_wayland(wayland::Action::Action(a));
64 }
65 }
66 }
67
68 pub(crate) fn clear_subsurface_list(&mut self) {
69 #[cfg(all(feature = "wayland", target_os = "linux"))]
70 {
71 self.wayland.clear_subsurface_list();
72 }
73 }
74
75 pub(crate) fn update_subsurfaces(
76 &mut self,
77 id: window::Id,
78 window: &dyn HasWindowHandle,
79 ) {
80 #[cfg(all(feature = "wayland", target_os = "linux"))]
81 {
82 use cctk::sctk::reexports::client::{
83 protocol::wl_surface::WlSurface, Proxy,
84 };
85 use wayland_backend::client::ObjectId;
86
87 let Some(conn) = self.wayland.conn() else {
88 log::error!("No Wayland conn");
89 return;
90 };
91
92 let Ok(raw) = window.window_handle() else {
93 log::error!("Invalid window handle {id:?}");
94 return;
95 };
96 let wl_surface = match raw.as_raw() {
97 raw_window_handle::RawWindowHandle::Wayland(
98 wayland_window_handle,
99 ) => {
100 let res = unsafe {
101 ObjectId::from_ptr(
102 WlSurface::interface(),
103 wayland_window_handle.surface.as_ptr().cast(),
104 )
105 };
106 let Ok(id) = res else {
107 log::error!(
108 "Could not create WlSurface Id from window"
109 );
110 return;
111 };
112 let Ok(surface) = WlSurface::from_id(&conn, id) else {
113 log::error!("Could not create WlSurface from Id");
114 return;
115 };
116 surface
117 }
118
119 _ => {
120 log::error!("Unexpected window handle type");
121 return;
122 }
123 };
124 self.wayland.update_subsurfaces(id, &wl_surface);
125 }
126 }
127
128 pub(crate) fn create_surface(
129 &mut self,
130 ) -> Option<Box<dyn HasWindowHandle + Send + Sync + 'static>> {
131 #[cfg(all(feature = "wayland", target_os = "linux"))]
132 {
133 return self.wayland.create_surface();
134 }
135 None
136 }
137
138 pub(crate) fn update_surface_shm(
139 &mut self,
140 surface: &dyn HasWindowHandle,
141 width: u32,
142 height: u32,
143 scale: f64,
144 data: &[u8],
145 offset: Vector,
146 ) {
147 #[cfg(all(feature = "wayland", target_os = "linux"))]
148 {
149 return self.wayland.update_surface_shm(
150 surface, width, height, scale, data, offset,
151 );
152 }
153 }
154}
155
156pub type UserInterfaces<'a, P> = HashMap<
157 window::Id,
158 user_interface::UserInterface<
159 'a,
160 <P as Program>::Message,
161 <P as Program>::Theme,
162 <P as Program>::Renderer,
163 >,
164 rustc_hash::FxBuildHasher,
165>;
166
167pub(crate) fn handle_event<'a, P, C>(
168 e: Event,
169 events: &mut Vec<(Option<window::Id>, iced_runtime::core::Event)>,
170 platform_specific: &mut PlatformSpecific,
171 program: &'a P,
172 compositor: &mut C,
173 window_manager: &mut WindowManager<P, C>,
174 debug: &mut Debug,
175 user_interfaces: &mut UserInterfaces<'a, P>,
176 clipboard: &mut crate::Clipboard,
177 #[cfg(feature = "a11y")] adapters: &mut std::collections::HashMap<
178 window::Id,
179 (u64, iced_accessibility::accesskit_winit::Adapter),
180 >,
181) where
182 P: 'static + Program,
183 C: Compositor<Renderer = P::Renderer>,
184{
185 match e {
186 #[cfg(all(feature = "wayland", target_os = "linux"))]
187 Event::Wayland(e) => {
188 platform_specific.wayland.handle_event(
189 e,
190 events,
191 program,
192 compositor,
193 window_manager,
194 debug,
195 user_interfaces,
196 clipboard,
197 #[cfg(feature = "a11y")]
198 adapters,
199 );
200 }
201 }
202}