diff --git a/winit/src/a11y.rs b/winit/src/a11y.rs index 8f6cf27b..61fbe630 100644 --- a/winit/src/a11y.rs +++ b/winit/src/a11y.rs @@ -7,7 +7,7 @@ use iced_accessibility::accesskit::{ use iced_runtime::core; pub struct WinitActivationHandler { - pub(crate) proxy: mpsc::UnboundedSender, + pub proxy: mpsc::UnboundedSender, pub title: String, } @@ -33,7 +33,7 @@ impl ActivationHandler for WinitActivationHandler { pub struct WinitActionHandler { pub id: core::window::Id, - pub(crate) proxy: mpsc::UnboundedSender, + pub proxy: mpsc::UnboundedSender, } impl iced_accessibility::accesskit::ActionHandler for WinitActionHandler { @@ -48,7 +48,7 @@ impl iced_accessibility::accesskit::ActionHandler for WinitActionHandler { } pub struct WinitDeactivationHandler { - pub(crate) proxy: mpsc::UnboundedSender, + pub proxy: mpsc::UnboundedSender, } impl iced_accessibility::accesskit::DeactivationHandler diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index 5192cb61..0afb8e72 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -3,6 +3,8 @@ //! [`winit`]: https://github.com/rust-windowing/winit //! [`iced_runtime`]: https://github.com/iced-rs/iced/tree/0.14/runtime use crate::core::input_method; +use std::hash::Hash; +use std::hash::Hasher; use std::sync::Arc; use crate::core::keyboard; @@ -638,6 +640,10 @@ pub fn mouse_interaction( Interaction::AllScroll => winit_core::cursor::CursorIcon::AllScroll, Interaction::ZoomIn => winit_core::cursor::CursorIcon::ZoomIn, Interaction::ZoomOut => winit_core::cursor::CursorIcon::ZoomOut, + Interaction::Cell => winit_core::cursor::CursorIcon::Cell, + Interaction::Move => winit_core::cursor::CursorIcon::Move, + Interaction::Copy => winit_core::cursor::CursorIcon::Copy, + Interaction::Help => winit_core::cursor::CursorIcon::Help, Interaction::Hidden => { return None; } @@ -696,7 +702,7 @@ enum TouchInternal { /// /// [`winit`]: https://github.com/rust-windowing/winit /// [`iced`]: https://github.com/iced-rs/iced/tree/0.12 -fn touch_event( +pub fn touch_event( finger: FingerId, state: TouchInternal, _force: Option, @@ -1073,7 +1079,6 @@ pub fn physical_key( /// /// [`winit`]: https://github.com/rust-windowing/winit /// [`iced`]: https://github.com/iced-rs/iced/tree/0.12 -#[allow(deprecated)] // KeyCode::Super/Hyper/Turbo: legacy spec, no Meta variant in this enum pub fn key_code( key_code: winit::keyboard::KeyCode, ) -> Option { @@ -1278,7 +1283,6 @@ pub fn key_code( }) } -#[allow(deprecated)] // KeyCode::Super/Hyper/Turbo: legacy spec, no Meta variant in this enum pub fn winit_key_code( key_code: keyboard::key::Code, ) -> Option { @@ -1589,10 +1593,7 @@ pub fn resize_direction( } } -// Fields are passed through to winit via `IconProvider: AsAny` for potential -// downcast; they are not read directly here. #[derive(Debug)] -#[allow(dead_code)] pub struct RawImage(Vec, Size); impl IconProvider for RawImage {} impl From for winit_core::icon::Icon { diff --git a/winit/src/lib.rs b/winit/src/lib.rs index 3c5a5d29..5b5d1ce1 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -157,8 +157,7 @@ where let (boot_sender, boot_receiver) = oneshot::channel(); let (control_sender, control_receiver) = mpsc::unbounded(); - // Sender side currently not wired to a producer; receiver gets default. - let (_system_theme_sender, system_theme_receiver) = oneshot::channel(); + let (system_theme_sender, system_theme_receiver) = oneshot::channel(); let instance = Box::pin(run_instance::

( program, @@ -179,6 +178,9 @@ where struct BootConfig { sender: oneshot::Sender<()>, + fonts: Vec>, + graphics_settings: graphics::Settings, + is_wayland: bool, } struct Runner { instance: std::pin::Pin>, @@ -188,6 +190,7 @@ where sender: mpsc::UnboundedSender>, receiver: mpsc::UnboundedReceiver, error: Option, + system_theme: Option>, control_sender: mpsc::UnboundedSender, #[cfg(feature = "a11y")] @@ -204,12 +207,16 @@ where context, boot: Some(BootConfig { sender: boot_sender, + fonts: settings.fonts, + graphics_settings, + is_wayland, }), id: settings.id, sender: event_sender, receiver: control_receiver, control_sender: control_sender.clone(), error: None, + system_theme: Some(system_theme_sender), #[cfg(feature = "a11y")] adapters: Default::default(), @@ -312,7 +319,12 @@ where event_loop: &dyn winit::event_loop::ActiveEventLoop, ) { // create initial window - let Some(BootConfig { sender }) = self.boot.take() + let Some(BootConfig { + sender, + fonts: _, + graphics_settings: _, + is_wayland: _, + }) = self.boot.take() else { return; }; @@ -350,8 +362,6 @@ where where F: Future, { - // TODO(yoda): migrate try_next → try_recv (futures-channel API change). - #[allow(deprecated)] fn process_event( &mut self, event_loop: &dyn winit::event_loop::ActiveEventLoop, @@ -679,7 +689,6 @@ where } } -#[allow(hidden_glob_reexports)] // intentional: internal Event shadows winit::event::Event from `pub use winit` enum Event { WindowCreated { id: window::Id, @@ -787,6 +796,9 @@ async fn run_instance

( > = None; let mut dnd_surface_id: Option = None; + #[cfg(feature = "a11y")] + let mut a11y_enabled = false; + #[cfg(all(feature = "linux-theme-detection", target_os = "linux"))] let mut system_theme = { let to_mode = |color_scheme| match color_scheme { @@ -1379,6 +1391,7 @@ async fn run_instance

( } let mut uis_stale = false; + let mut resized = false; for (id, window) in window_manager.iter_mut() { if skip && !window.resize_enabled { continue; @@ -1431,6 +1444,7 @@ async fn run_instance

( // FIXME what to do when we are stuck in a configure event/resize request loop // We don't have control over how winit handles this. window.resize_enabled = true; + resized = true; needs_redraw = true; let s = winit::dpi::Size::Logical( requested_size.cast(), @@ -1645,8 +1659,8 @@ async fn run_instance

( events.push((Some(id), conversion::a11y(action_request))); } #[cfg(feature = "a11y")] - Event::AccessibilityEnabled(_enabled) => { - // a11y enable signal currently unused at this layer + Event::AccessibilityEnabled(enabled) => { + a11y_enabled = enabled; } Event::PlatformSpecific(e) => { crate::platform_specific::handle_event( diff --git a/winit/src/platform_specific/mod.rs b/winit/src/platform_specific/mod.rs index 357fb1ec..66eda20c 100644 --- a/winit/src/platform_specific/mod.rs +++ b/winit/src/platform_specific/mod.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; -use iced_graphics::compositor; +use iced_graphics::{Compositor, compositor}; use iced_runtime::{ core::{Vector, window}, user_interface, }; diff --git a/winit/src/platform_specific/wayland/event_loop/control_flow.rs b/winit/src/platform_specific/wayland/event_loop/control_flow.rs new file mode 100644 index 00000000..bc920ed4 --- /dev/null +++ b/winit/src/platform_specific/wayland/event_loop/control_flow.rs @@ -0,0 +1,56 @@ +/// Set by the user callback given to the [`EventLoop::run`] method. +/// +/// Indicates the desired behavior of the event loop after [`Event::RedrawEventsCleared`] is emitted. +/// +/// Defaults to [`Poll`]. +/// +/// ## Persistency +/// +/// Almost every change is persistent between multiple calls to the event loop closure within a +/// given run loop. The only exception to this is [`ExitWithCode`] which, once set, cannot be unset. +/// Changes are **not** persistent between multiple calls to `run_return` - issuing a new call will +/// reset the control flow to [`Poll`]. +/// +/// [`ExitWithCode`]: Self::ExitWithCode +/// [`Poll`]: Self::Poll +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ControlFlow { + /// When the current loop iteration finishes, immediately begin a new iteration regardless of + /// whether or not new events are available to process. + /// + /// ## Platform-specific + /// + /// - **Web:** Events are queued and usually sent when `requestAnimationFrame` fires but sometimes + /// the events in the queue may be sent before the next `requestAnimationFrame` callback, for + /// example when the scaling of the page has changed. This should be treated as an implementation + /// detail which should not be relied on. + Poll, + /// When the current loop iteration finishes, suspend the thread until another event arrives. + Wait, + /// When the current loop iteration finishes, suspend the thread until either another event + /// arrives or the given time is reached. + /// + /// Useful for implementing efficient timers. Applications which want to render at the display's + /// native refresh rate should instead use [`Poll`] and the VSync functionality of a graphics API + /// to reduce odds of missed frames. + /// + /// [`Poll`]: Self::Poll + WaitUntil(std::time::Instant), + /// Send a [`LoopDestroyed`] event and stop the event loop. This variant is *sticky* - once set, + /// `control_flow` cannot be changed from `ExitWithCode`, and any future attempts to do so will + /// result in the `control_flow` parameter being reset to `ExitWithCode`. + /// + /// The contained number will be used as exit code. The [`Exit`] constant is a shortcut for this + /// with exit code 0. + /// + /// ## Platform-specific + /// + /// - **Android / iOS / WASM:** The supplied exit code is unused. + /// - **Unix:** On most Unix-like platforms, only the 8 least significant bits will be used, + /// which can cause surprises with negative exit values (`-42` would end up as `214`). See + /// [`std::process::exit`]. + /// + /// [`LoopDestroyed`]: Event::LoopDestroyed + /// [`Exit`]: ControlFlow::Exit + ExitWithCode(i32), +} diff --git a/winit/src/platform_specific/wayland/event_loop/mod.rs b/winit/src/platform_specific/wayland/event_loop/mod.rs index d21edcea..87d00ec2 100644 --- a/winit/src/platform_specific/wayland/event_loop/mod.rs +++ b/winit/src/platform_specific/wayland/event_loop/mod.rs @@ -1,3 +1,5 @@ +pub mod control_flow; +pub mod proxy; pub mod state; use crate::{ @@ -26,7 +28,7 @@ use cctk::{ reexports::{ calloop::{self, EventLoop}, client::{ - Connection, Proxy, globals::registry_queue_init, + ConnectError, Connection, Proxy, globals::registry_queue_init, }, }, registry::RegistryState, @@ -62,8 +64,8 @@ pub struct SctkEventLoop { pub(crate) state: SctkState, } -#[allow(dead_code)] // payloads kept for Debug; not inspected programmatically pub enum Error { + Connect(ConnectError), Calloop(calloop::Error), Global(GlobalError), NoDisplayHandle, diff --git a/winit/src/platform_specific/wayland/event_loop/proxy.rs b/winit/src/platform_specific/wayland/event_loop/proxy.rs new file mode 100644 index 00000000..bdbc44a4 --- /dev/null +++ b/winit/src/platform_specific/wayland/event_loop/proxy.rs @@ -0,0 +1,66 @@ +use cctk::sctk::reexports::calloop; +use iced_futures::futures::{ + channel::mpsc, + task::{Context, Poll}, + Sink, +}; +use std::pin::Pin; + +/// An event loop proxy that implements `Sink`. +#[derive(Debug)] +pub struct Proxy { + raw: calloop::channel::Sender, +} + +impl Clone for Proxy { + fn clone(&self) -> Self { + Self { + raw: self.raw.clone(), + } + } +} + +impl Proxy { + /// Creates a new [`Proxy`] from an `EventLoopProxy`. + pub fn new(raw: calloop::channel::Sender) -> Self { + Self { raw } + } + /// send an event + pub fn send_event(&self, message: Message) { + let _ = self.raw.send(message); + } +} + +impl Sink for Proxy { + type Error = mpsc::SendError; + + fn poll_ready( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + + fn start_send( + self: Pin<&mut Self>, + message: Message, + ) -> Result<(), Self::Error> { + let _ = self.raw.send(message); + + Ok(()) + } + + fn poll_flush( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_close( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } +} diff --git a/winit/src/platform_specific/wayland/event_loop/state.rs b/winit/src/platform_specific/wayland/event_loop/state.rs index 8be7c639..3d93a015 100644 --- a/winit/src/platform_specific/wayland/event_loop/state.rs +++ b/winit/src/platform_specific/wayland/event_loop/state.rs @@ -33,7 +33,7 @@ use std::{ }; use wayland_backend::client::ObjectId; use winit::{ - dpi::LogicalSize, + dpi::{LogicalPosition, LogicalSize}, platform::wayland::WindowExtWayland, }; @@ -229,6 +229,9 @@ impl CommonSurface { #[derive(Debug, Clone)] pub struct Common { pub(crate) fractional_scale: Option, + pub(crate) has_focus: bool, + pub(crate) ime_pos: LogicalPosition, + pub(crate) ime_size: LogicalSize, pub(crate) size: LogicalSize, pub(crate) requested_size: (Option, Option), pub(crate) wp_viewport: Option, @@ -238,6 +241,9 @@ impl Default for Common { fn default() -> Self { Self { fractional_scale: Default::default(), + has_focus: Default::default(), + ime_pos: Default::default(), + ime_size: Default::default(), size: LogicalSize::new(1, 1), requested_size: (None, None), wp_viewport: None, @@ -330,6 +336,7 @@ pub struct SctkPopupData { pub(crate) parent: PopupParent, pub(crate) toplevel: WlSurface, pub(crate) positioner: Arc, + pub(crate) grab: bool, } #[derive(Debug)] @@ -870,6 +877,7 @@ impl SctkState { parent: parent.clone(), toplevel: toplevel.clone(), positioner: positioner.clone(), + grab: settings.grab, }, last_configure: None, _pending_requests: Default::default(), @@ -1511,6 +1519,7 @@ impl SctkState { SctkEvent::SubsurfaceEvent (crate::sctk_event::SubsurfaceEventVariant::Created{ parent_id, parent, + surface: subsurface, qh: self.queue_handle.clone(), common_surface, surface_id: subsurface_settings.id, diff --git a/winit/src/platform_specific/wayland/mod.rs b/winit/src/platform_specific/wayland/mod.rs index e613e3b4..321561da 100644 --- a/winit/src/platform_specific/wayland/mod.rs +++ b/winit/src/platform_specific/wayland/mod.rs @@ -16,9 +16,10 @@ use cctk::sctk::reexports::client::protocol::wl_surface::WlSurface; use cctk::sctk::seat::keyboard::Modifiers; use cursor_icon::CursorIcon; use iced_futures::futures::channel::mpsc; -use iced_graphics::compositor; +use iced_graphics::{Compositor, compositor}; use iced_runtime::core::{Vector, window}; -use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; +use raw_window_handle::{HasRawDisplayHandle, RawWindowHandle}; use sctk_event::SctkEvent; use std::{collections::HashMap, sync::Arc}; use subsurface_widget::{SubsurfaceInstance, SubsurfaceState}; @@ -105,7 +106,7 @@ impl PlatformSpecific { display: OwnedDisplayHandle, ) -> Self { self.wayland.winit_event_sender = Some(tx); - self.wayland.conn = match display.display_handle().map(|h| h.as_raw()) { + self.wayland.conn = match display.raw_display_handle() { Ok(raw_window_handle::RawDisplayHandle::Wayland( wayland_display_handle, )) => { diff --git a/winit/src/platform_specific/wayland/sctk_event.rs b/winit/src/platform_specific/wayland/sctk_event.rs index a11ebe66..8c2b24df 100755 --- a/winit/src/platform_specific/wayland/sctk_event.rs +++ b/winit/src/platform_specific/wayland/sctk_event.rs @@ -27,7 +27,7 @@ use iced_futures::{ }, futures::{SinkExt, channel::mpsc}, }; -use iced_graphics::compositor; +use iced_graphics::{Compositor, compositor}; use iced_runtime::{ core::{ Point, @@ -282,6 +282,7 @@ pub enum SubsurfaceEventVariant { Created { parent_id: window::Id, parent: WlSurface, + surface: WlSurface, qh: QueueHandle, common_surface: CommonSurface, surface_id: SurfaceId, @@ -1502,6 +1503,7 @@ impl SctkEvent { common, z, parent, + surface: _, qh, surface_id, display, diff --git a/winit/src/platform_specific/wayland/subsurface_widget.rs b/winit/src/platform_specific/wayland/subsurface_widget.rs index c09e2424..7f15854b 100644 --- a/winit/src/platform_specific/wayland/subsurface_widget.rs +++ b/winit/src/platform_specific/wayland/subsurface_widget.rs @@ -7,6 +7,7 @@ use crate::core::{ widget::{self, Widget}, }; use std::{ + borrow::BorrowMut, cell::RefCell, collections::HashMap, fmt::Debug, @@ -623,7 +624,7 @@ impl Drop for SubsurfaceState { } #[derive(Clone, Debug)] -pub struct SubsurfaceInstance { +pub(crate) struct SubsurfaceInstance { pub(crate) wl_surface: WlSurface, pub(crate) wl_subsurface: WlSubsurface, pub(crate) wp_viewport: WpViewport, diff --git a/winit/src/proxy.rs b/winit/src/proxy.rs index aabe15c3..e65de2aa 100644 --- a/winit/src/proxy.rs +++ b/winit/src/proxy.rs @@ -33,7 +33,7 @@ impl Proxy { const MAX_SIZE: usize = 100; /// Creates a new [`Proxy`] from an `EventLoopProxy`. - pub(crate) fn new( + pub fn new( raw: winit::event_loop::EventLoopProxy, event_sender: mpsc::UnboundedSender>, ) -> (Self, impl Future) { diff --git a/winit/src/window.rs b/winit/src/window.rs index ecb2107a..87d35a5a 100644 --- a/winit/src/window.rs +++ b/winit/src/window.rs @@ -14,7 +14,7 @@ use crate::core::text; use crate::core::theme::{self, Base}; use crate::core::time::Instant; use crate::core::{ - Color, InputMethod, Padding, Point, Rectangle, Size, Text, Vector, + Color, Element, InputMethod, Padding, Point, Rectangle, Size, Text, Vector, }; use crate::graphics::Compositor; use crate::program::{self, Program}; @@ -26,6 +26,10 @@ use winit::monitor::MonitorHandle; use std::collections::BTreeMap; use std::sync::Arc; +pub(crate) type ViewFn = Arc< + Box Option> + Send + Sync + 'static>, +>; + pub struct WindowManager where P: Program, @@ -321,10 +325,6 @@ where } } - // TODO(yoda): migrate to Window::request_ime_update(ImeRequest::*). - // Legacy set_ime_* still functional but deprecated; full migration - // requires ImeCapabilities + ImeRequestData reshape. - #[allow(deprecated)] fn enable_ime( &mut self, cursor: Rectangle, @@ -355,7 +355,6 @@ where } } - #[allow(deprecated)] // see TODO on enable_ime fn disable_ime(&mut self) { if self.ime_state.is_some() { self.raw.set_ime_allowed(false);