iced_winit/platform_specific/
mod.rs1use 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 retain_subsurfaces<F: Fn(window::Id) -> bool>(
69 &mut self,
70 keep: F,
71 ) {
72 #[cfg(all(feature = "wayland", target_os = "linux"))]
73 {
74 self.wayland.retain_subsurfaces(keep);
75 }
76 }
77
78 pub(crate) fn clear_subsurface_list(&mut self) {
79 #[cfg(all(feature = "wayland", target_os = "linux"))]
80 {
81 self.wayland.clear_subsurface_list();
82 }
83 }
84
85 pub(crate) fn update_subsurfaces(
86 &mut self,
87 id: window::Id,
88 window: &dyn HasWindowHandle,
89 ) {
90 #[cfg(all(feature = "wayland", target_os = "linux"))]
91 {
92 use cctk::sctk::reexports::client::{
93 protocol::wl_surface::WlSurface, Proxy,
94 };
95 use wayland_backend::client::ObjectId;
96
97 let Some(conn) = self.wayland.conn() else {
98 log::info!("No Wayland conn");
99 return;
100 };
101
102 let Ok(raw) = window.window_handle() else {
103 log::error!("Invalid window handle {id:?}");
104 return;
105 };
106 let wl_surface = match raw.as_raw() {
107 raw_window_handle::RawWindowHandle::Wayland(
108 wayland_window_handle,
109 ) => {
110 let res = unsafe {
111 ObjectId::from_ptr(
112 WlSurface::interface(),
113 wayland_window_handle.surface.as_ptr().cast(),
114 )
115 };
116 let Ok(id) = res else {
117 log::error!(
118 "Could not create WlSurface Id from window"
119 );
120 return;
121 };
122 let Ok(surface) = WlSurface::from_id(&conn, id) else {
123 log::error!("Could not create WlSurface from Id");
124 return;
125 };
126 surface
127 }
128
129 _ => {
130 log::error!("Unexpected window handle type");
131 return;
132 }
133 };
134 self.wayland.update_subsurfaces(id, &wl_surface);
135 }
136 }
137
138 pub(crate) fn create_surface(
139 &mut self,
140 ) -> Option<Box<dyn HasWindowHandle + Send + Sync + 'static>> {
141 #[cfg(all(feature = "wayland", target_os = "linux"))]
142 {
143 return self.wayland.create_surface();
144 }
145 None
146 }
147
148 pub(crate) fn update_surface_shm(
149 &mut self,
150 surface: &dyn HasWindowHandle,
151 width: u32,
152 height: u32,
153 scale: f64,
154 data: &[u8],
155 offset: Vector,
156 ) {
157 #[cfg(all(feature = "wayland", target_os = "linux"))]
158 {
159 return self.wayland.update_surface_shm(
160 surface, width, height, scale, data, offset,
161 );
162 }
163 }
164}
165
166pub type UserInterfaces<'a, P> = HashMap<
167 window::Id,
168 user_interface::UserInterface<
169 'a,
170 <P as Program>::Message,
171 <P as Program>::Theme,
172 <P as Program>::Renderer,
173 >,
174 rustc_hash::FxBuildHasher,
175>;
176
177pub(crate) fn handle_event<'a, P, C>(
178 e: Event,
179 events: &mut Vec<(Option<window::Id>, iced_runtime::core::Event)>,
180 platform_specific: &mut PlatformSpecific,
181 program: &'a P,
182 compositor: &mut C,
183 window_manager: &mut WindowManager<P, C>,
184 debug: &mut Debug,
185 user_interfaces: &mut UserInterfaces<'a, P>,
186 clipboard: &mut crate::Clipboard,
187 #[cfg(feature = "a11y")] adapters: &mut std::collections::HashMap<
188 window::Id,
189 (u64, iced_accessibility::accesskit_winit::Adapter),
190 >,
191) where
192 P: 'static + Program,
193 C: Compositor<Renderer = P::Renderer>,
194{
195 match e {
196 #[cfg(all(feature = "wayland", target_os = "linux"))]
197 Event::Wayland(e) => {
198 platform_specific.wayland.handle_event(
199 e,
200 events,
201 program,
202 compositor,
203 window_manager,
204 debug,
205 user_interfaces,
206 clipboard,
207 #[cfg(feature = "a11y")]
208 adapters,
209 );
210 }
211 }
212}