diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8089d545a1..a1fc6f11ec 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -19,4 +19,5 @@ iced_core.workspace = true iced_futures.workspace = true iced_futures.features = ["thread-pool"] +raw-window-handle.workspace = true thiserror.workspace = true diff --git a/runtime/src/window.rs b/runtime/src/window.rs index 2136d64dcf..ba92776d40 100644 --- a/runtime/src/window.rs +++ b/runtime/src/window.rs @@ -15,6 +15,8 @@ use crate::core::{Point, Size}; use crate::futures::event; use crate::futures::Subscription; +use raw_window_handle::RawWindowHandle; + /// Subscribes to the frames of the window of the running application. /// /// The resulting [`Subscription`] will produce items at a rate equal to the @@ -165,6 +167,17 @@ pub fn fetch_id( Command::single(command::Action::Window(Action::FetchId(id, Box::new(f)))) } +/// Fetches the raw window handle for the specified window. +pub fn fetch_handle( + id: Id, + f: impl FnOnce(RawWindowHandle) -> Message + 'static, +) -> Command { + Command::single(command::Action::Window(Action::FetchHandle( + id, + Box::new(f), + ))) +} + /// Changes the [`Icon`] of the window. pub fn change_icon(id: Id, icon: Icon) -> Command { Command::single(command::Action::Window(Action::ChangeIcon(id, icon))) diff --git a/runtime/src/window/action.rs b/runtime/src/window/action.rs index 8b5325692c..5b3edbab90 100644 --- a/runtime/src/window/action.rs +++ b/runtime/src/window/action.rs @@ -3,6 +3,8 @@ use crate::core::{Point, Size}; use crate::futures::MaybeSend; use crate::window::Screenshot; +use raw_window_handle::RawWindowHandle; + use std::fmt; /// An operation to be performed on some window. @@ -81,6 +83,8 @@ pub enum Action { ChangeLevel(Id, Level), /// Fetch the raw identifier unique to the window. FetchId(Id, Box T + 'static>), + /// Fetch the raw window handle. + FetchHandle(Id, Box T + 'static>), /// Change the window [`Icon`]. /// /// On Windows and X11, this is typically the small icon in the top-left @@ -140,6 +144,9 @@ impl Action { Self::FetchId(id, o) => { Action::FetchId(id, Box::new(move |s| f(o(s)))) } + Self::FetchHandle(id, o) => { + Action::FetchHandle(id, Box::new(move |s| f(o(s)))) + } Self::ChangeIcon(id, icon) => Action::ChangeIcon(id, icon), Self::Screenshot(id, tag) => Action::Screenshot( id, @@ -194,6 +201,9 @@ impl fmt::Debug for Action { write!(f, "Action::ChangeLevel({id:?}, {level:?})") } Self::FetchId(id, _) => write!(f, "Action::FetchId({id:?})"), + Self::FetchHandle(id, _) => { + write!(f, "Action::FetchHandle({id:?})") + } Self::ChangeIcon(id, _icon) => { write!(f, "Action::ChangeIcon({id:?})") } diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 87e600aeba..ce66cdd084 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -31,6 +31,7 @@ thiserror.workspace = true tracing.workspace = true window_clipboard.workspace = true winit.workspace = true +raw-window-handle.workspace = true sysinfo.workspace = true sysinfo.optional = true diff --git a/winit/src/application.rs b/winit/src/application.rs index 35a35872f2..037fef54f9 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -25,6 +25,8 @@ use futures::channel::mpsc; use std::mem::ManuallyDrop; +use raw_window_handle::HasRawWindowHandle; + /// An interactive, native cross-platform application. /// /// This trait is the main entrypoint of Iced. Once implemented, you can run @@ -807,6 +809,9 @@ pub fn run_command( .send_event(tag(window.id().into())) .expect("Send message to event loop"); } + window::Action::FetchHandle(_id, tag) => proxy + .send_event(tag(window.raw_window_handle())) + .expect("Send message to event loop"), window::Action::Screenshot(_id, tag) => { let bytes = compositor.screenshot( renderer, diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 1550b94b11..87afcd80ee 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -26,6 +26,8 @@ use std::collections::HashMap; use std::mem::ManuallyDrop; use std::time::Instant; +use raw_window_handle::HasRawWindowHandle; + /// An interactive, native, cross-platform, multi-windowed application. /// /// This trait is the main entrypoint of multi-window Iced. Once implemented, you can run @@ -1039,6 +1041,13 @@ fn run_command( .expect("Event loop doesn't exist."); } } + window::Action::FetchHandle(id, tag) => { + if let Some(window) = window_manager.get_mut(id) { + proxy + .send_event(tag(window.raw.raw_window_handle())) + .expect("Event loop doesn't exist."); + } + } window::Action::Screenshot(id, tag) => { if let Some(window) = window_manager.get_mut(id) { let bytes = compositor.screenshot(