fixes: various fixes and cleanup

This commit is contained in:
Ashley Wulber 2026-02-19 17:01:13 -05:00
parent b4346ff3ca
commit c1edb81084
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
27 changed files with 676 additions and 1455 deletions

View file

@ -27,6 +27,7 @@ pub use program::runtime;
pub use runtime::futures;
use window_clipboard::mime::ClipboardStoreData;
pub use winit;
use winit::event::WindowEvent;
use winit::raw_window_handle::HasWindowHandle;
#[cfg(feature = "a11y")]
@ -76,6 +77,7 @@ use window::WindowManager;
use rustc_hash::FxHashMap;
use std::borrow::Cow;
use std::mem::ManuallyDrop;
use std::ops::ControlFlow;
use std::slice;
use std::sync::Arc;
@ -130,7 +132,13 @@ where
let task = if let Some(window_settings) = window_settings {
let mut task = Some(task);
let (_id, open) = runtime::window::open(window_settings);
let open = iced_runtime::task::oneshot(|channel| {
iced_runtime::Action::Window(iced_runtime::window::Action::Open(
window::Id::RESERVED,
window_settings,
channel,
))
});
open.then(move |_| task.take().unwrap_or_else(Task::none))
} else {
@ -532,52 +540,49 @@ where
.start_send(Event::StartDnd)
.expect("Send event");
}
#[cfg(feature = "a11y")]
Control::InitAdapter(id, window) => {
#[cfg(feature = "a11y")]
{
use crate::a11y::*;
use iced_accessibility::accesskit::{
ActivationHandler, Node, NodeId, Role,
Tree, TreeUpdate,
use crate::a11y::*;
use iced_accessibility::accesskit::{
ActivationHandler, Node, NodeId, Role,
Tree, TreeUpdate,
};
use iced_accessibility::accesskit_winit::Adapter;
let node_id =
iced_runtime::core::id::window_node_id();
let activation_handler =
WinitActivationHandler {
proxy: self.control_sender.clone(),
title: String::new(),
};
use iced_accessibility::accesskit_winit::Adapter;
let node_id =
iced_runtime::core::id::window_node_id(
);
let action_handler = WinitActionHandler {
id,
proxy: self.control_sender.clone(),
};
let activation_handler =
WinitActivationHandler {
proxy: self.control_sender.clone(),
title: String::new(),
};
let action_handler = WinitActionHandler {
id,
let deactivation_handler =
WinitDeactivationHandler {
proxy: self.control_sender.clone(),
};
let deactivation_handler =
WinitDeactivationHandler {
proxy: self.control_sender.clone(),
};
self.sender
.start_send(Event::A11yAdapter(
id,
(
node_id,
Adapter::with_direct_handlers(
event_loop,
window.as_ref(),
activation_handler,
action_handler,
deactivation_handler,
),
self.sender
.start_send(Event::A11yAdapter(
id,
(
node_id,
Adapter::with_direct_handlers(
event_loop,
window.as_ref(),
activation_handler,
action_handler,
deactivation_handler,
),
))
.expect("send event");
}
),
))
.expect("send event");
}
},
_ => {
@ -776,69 +781,32 @@ async fn run_instance<P>(
control_sender
.start_send(Control::InitAdapter(id, window.clone()))
.expect("Send control message");
if compositor.is_none() {
let (compositor_sender, compositor_receiver) =
oneshot::channel();
let create_compositor = {
let window = window.clone();
let display_handle = display_handle.clone();
let proxy = proxy.clone();
let default_fonts = default_fonts.clone();
async move {
let shell = Shell::new(proxy.clone());
let mut compositor =
<P::Renderer as compositor::Default>::Compositor::new(
graphics_settings,
display_handle,
window,
shell,
).await;
if let Ok(compositor) = &mut compositor {
for font in default_fonts {
compositor.load_font(font.clone());
}
}
compositor_sender
.send(compositor)
.ok()
.expect("Send compositor");
// HACK! Send a proxy event on completion to trigger
// a runtime re-poll
// TODO: Send compositor through proxy (?)
{
let (sender, _receiver) = oneshot::channel();
proxy.send_action(Action::Window(
runtime::window::Action::GetLatest(sender),
));
}
}
};
#[cfg(target_arch = "wasm32")]
wasm_bindgen_futures::spawn_local(create_compositor);
#[cfg(not(target_arch = "wasm32"))]
runtime.block_on(create_compositor);
match compositor_receiver
.await
.expect("Wait for compositor")
{
Ok(new_compositor) => {
compositor = Some(new_compositor);
}
Err(error) => {
let _ = control_sender
.start_send(Control::Crash(error.into()));
continue;
}
#[cfg(feature = "wayland")]
platform_specific_handler.send_wayland(
platform_specific::Action::TrackWindow(window.clone(), id),
);
match create_compositor::<P>(
window.clone(),
CreateCompositor {
proxy: &proxy,
runtime: &mut runtime,
display_handle: &display_handle,
graphics_settings: &graphics_settings,
default_fonts: &default_fonts,
},
)
.await
{
Ok(comp) => {
compositor = Some(comp);
}
Err(error) => {
control_sender
.start_send(Control::Crash(
Error::GraphicsCreationFailed(error),
))
.expect("Send control message");
continue;
}
}
@ -982,6 +950,22 @@ async fn run_instance<P>(
else {
continue;
};
// XX must force update to corner radius before the surface is committed.
#[cfg(feature = "wayland")]
if window.surface_version != window.state.surface_version()
|| window.logical_size() != window.state.logical_size()
{
platform_specific_handler.send_wayland(
platform_specific::Action::ResizeWindow(id),
);
window.redraw_requested = true;
control_sender
.start_send(Control::Winit(
window.raw.id(),
WindowEvent::RedrawRequested,
))
.expect("Send redraw event");
}
window.redraw_requested = false;
let physical_size = window.state.physical_size();
@ -1330,7 +1314,6 @@ async fn run_instance<P>(
true
}
});
let no_window_events = window_events.is_empty();
#[cfg(feature = "wayland")]
window_events.push(core::Event::PlatformSpecific(
@ -1376,6 +1359,14 @@ async fn run_instance<P>(
_ = window.raw.request_surface_size(s);
window.raw.set_min_surface_size(Some(s));
window.raw.set_max_surface_size(Some(s));
window.state.update(
&program,
window.raw.as_ref(),
&WindowEvent::SurfaceResized(
requested_physical_size,
),
);
window.state.synchronize(
&program,
id,
@ -1499,7 +1490,9 @@ async fn run_instance<P>(
.start_send(Control::ChangeFlow(ControlFlow::Wait));
}
}
Event::Exit => break,
Event::Exit => {
break;
}
Event::Dnd(e) => {
use winit::raw_window_handle::HasWindowHandle;
@ -1569,23 +1562,26 @@ async fn run_instance<P>(
a11y_enabled = enabled;
}
Event::PlatformSpecific(e) => {
if let Some(c) = compositor.as_mut() {
crate::platform_specific::handle_event(
e,
&mut events,
&mut platform_specific_handler,
&program,
c,
&mut window_manager,
&mut user_interfaces,
&mut clipboard,
#[cfg(feature = "a11y")]
&mut adapters,
);
} else {
// TODO should we break?
break;
}
crate::platform_specific::handle_event(
e,
&mut events,
&mut platform_specific_handler,
&program,
&mut compositor,
&mut window_manager,
&mut user_interfaces,
&mut clipboard,
#[cfg(feature = "a11y")]
&mut adapters,
CreateCompositor {
proxy: &proxy,
display_handle: &display_handle,
graphics_settings: &graphics_settings,
default_fonts: &default_fonts,
runtime: &mut runtime,
},
)
.await;
}
Event::StartDnd => {
let compositor = match compositor.as_mut() {
@ -1614,12 +1610,15 @@ async fn run_instance<P>(
Some(s)
}
core::clipboard::DndSource::Widget(w) => {
log::debug!(
log::trace!(
"start_dnd: searching for widget {:?}",
w
);
// search windows for widget with operation
let result = user_interfaces.iter_mut().find_map(
// if user intefaces is just 1 len, use the single id instead of wasting time searching
let result = if user_interfaces.len() ==1 {
user_interfaces.keys().next().cloned()
} else {
user_interfaces.iter_mut().find_map(
|(ui_id, ui)| {
let Some(ui_renderer) = window_manager
.get_mut(ui_id.clone())
@ -1666,7 +1665,11 @@ async fn run_instance<P>(
}
None
},
);
)
};
// search windows for widget with operation
if result.is_none() {
log::warn!(
"start_dnd: widget {:?} not found; drag will fail",
@ -1817,6 +1820,88 @@ async fn run_instance<P>(
let _ = ManuallyDrop::into_inner(user_interfaces);
}
struct CreateCompositor<'a, P: Program> {
proxy: &'a Proxy<<P as Program>::Message>,
display_handle: &'a winit::event_loop::OwnedDisplayHandle,
graphics_settings: &'a iced_graphics::Settings,
default_fonts: &'a [Cow<'static, [u8]>],
runtime: &'a mut Runtime<
<P as Program>::Executor,
Proxy<<P as Program>::Message>,
Action<<P as Program>::Message>,
>,
}
async fn create_compositor<'a, P>(
window: Arc<dyn winit::window::Window + 'static>,
CreateCompositor {
proxy,
display_handle,
graphics_settings,
default_fonts,
runtime,
}: CreateCompositor<'a, P>,
) -> Result<
<<P as Program>::Renderer as compositor::Default>::Compositor,
iced_graphics::Error,
>
where
P: Program,
{
let (compositor_sender, compositor_receiver) = oneshot::channel();
let create_compositor = {
let display_handle = display_handle.clone();
let proxy = proxy.clone();
let graphics_settings = (*graphics_settings).clone();
let window = window.clone();
let default_fonts = default_fonts.to_vec();
async move {
let shell = Shell::new(proxy.clone());
let mut compositor =
<P::Renderer as compositor::Default>::Compositor::new(
graphics_settings,
display_handle,
window,
shell,
)
.await;
if let Ok(compositor) = &mut compositor {
for font in default_fonts {
compositor.load_font(font.clone());
}
}
compositor_sender
.send(compositor)
.ok()
.expect("Send compositor");
// HACK! Send a proxy event on completion to trigger
// a runtime re-poll
// TODO: Send compositor through proxy (?)
{
let (sender, _receiver) = oneshot::channel();
proxy.send_action(Action::Window(
runtime::window::Action::GetLatest(sender),
));
}
}
};
#[cfg(target_arch = "wasm32")]
wasm_bindgen_futures::spawn_local(create_compositor);
#[cfg(not(target_arch = "wasm32"))]
runtime.block_on(create_compositor);
compositor_receiver.await.expect("Wait for compositor")
}
/// Builds a window's [`UserInterface`] for the [`Program`].
fn build_user_interface<'a, P: Program>(
program: &'a program::Instance<P>,
@ -1965,7 +2050,9 @@ where
let _ = ui_caches.remove(&id);
let _ = interfaces.remove(&id);
let proxy = clipboard.proxy();
#[cfg(feature = "wayland")]
platform_specific
.send_wayland(platform_specific::Action::RemoveWindow(id));
if let Some(window) = window_manager.remove(id) {
if clipboard.window_id() == Some(window.raw.id()) {
*clipboard = window_manager

View file

@ -1,7 +1,7 @@
//! Wayland specific shell
//!
use std::collections::HashMap;
use std::{borrow::Cow, collections::HashMap, sync::Arc};
#[cfg(all(feature = "wayland", target_os = "linux"))]
use cctk::sctk::reexports::client::Connection;
@ -20,7 +20,7 @@ pub use wayland::*;
#[cfg(all(feature = "wayland", target_os = "linux"))]
use wayland_backend::client::Backend;
use crate::{Program, WindowManager};
use crate::{CreateCompositor, Program, WindowManager};
pub type UserInterfaces<'a, P> = HashMap<
window::Id,
@ -176,12 +176,14 @@ impl PlatformSpecific {
}
}
pub(crate) fn handle_event<'a, P>(
pub(crate) async fn handle_event<'a, 'b, P>(
e: Event,
events: &mut Vec<(Option<window::Id>, iced_runtime::core::Event)>,
platform_specific: &mut PlatformSpecific,
program: &'a crate::program::Instance<P>,
compositor: &mut <<P as Program>::Renderer as compositor::Default>::Compositor,
compositor: &mut Option<
<<P as Program>::Renderer as compositor::Default>::Compositor,
>,
window_manager: &mut WindowManager<
P,
<<P as Program>::Renderer as compositor::Default>::Compositor,
@ -192,23 +194,28 @@ pub(crate) fn handle_event<'a, P>(
window::Id,
(u64, iced_accessibility::accesskit_winit::Adapter),
>,
create_compositor: CreateCompositor<'b, P>,
) where
P: Program,
{
match e {
#[cfg(all(feature = "wayland", target_os = "linux"))]
Event::Wayland(e) => {
platform_specific.wayland.handle_event(
e,
events,
program,
compositor,
window_manager,
user_interfaces,
clipboard,
#[cfg(feature = "a11y")]
adapters,
);
platform_specific
.wayland
.handle_event(
e,
events,
program,
compositor,
window_manager,
user_interfaces,
clipboard,
#[cfg(feature = "a11y")]
adapters,
create_compositor,
)
.await;
}
}
}

View file

@ -1232,7 +1232,6 @@ impl SctkState {
found |= p.data.id == settings.parent;
parent_mismatch |= found && p.data.id != settings.parent;
}
parent_mismatch |= !found;
if !self.destroyed.is_empty() || parent_mismatch {
if parent_mismatch {
let mut found = false;

View file

@ -893,3 +893,195 @@ pub fn keysym_location(keysym: u32) -> Location {
_ => Location::Standard,
}
}
pub fn key_to_keysym(
unmodified_key: Key,
location: Location,
) -> Option<xkeysym::Keysym> {
use xkbcommon_dl::keysyms;
let raw = match unmodified_key {
Key::Named(named) => Some(match (named, location) {
(Named::Escape, _) => keysyms::Escape,
(Named::Backspace, _) => keysyms::BackSpace,
(Named::Tab, _) => keysyms::Tab,
(Named::Enter, _) => keysyms::Return,
(Named::Compose, _) => keysyms::Multi_key,
(Named::KanjiMode, _) => keysyms::Kanji,
(Named::Eisu, _) => keysyms::Eisu_toggle,
(Named::NonConvert, _) => keysyms::Muhenkan,
(Named::Convert, _) => keysyms::Henkan_Mode,
(Named::Romaji, _) => keysyms::Romaji,
(Named::Hiragana, _) => keysyms::Hiragana,
(Named::Katakana, _) => keysyms::Katakana,
(Named::HiraganaKatakana, _) => keysyms::Hiragana_Katakana,
(Named::Zenkaku, _) => keysyms::Zenkaku,
(Named::Hankaku, _) => keysyms::Hankaku,
(Named::ZenkakuHankaku, _) => keysyms::Zenkaku_Hankaku,
(Named::KanaMode, _) => keysyms::Kana_Lock,
(Named::Alphanumeric, _) => keysyms::Eisu_toggle,
(Named::CodeInput, _) => keysyms::Codeinput,
(Named::AllCandidates, _) => keysyms::MultipleCandidate,
(Named::PreviousCandidate, _) => keysyms::PreviousCandidate,
(Named::SingleCandidate, _) => keysyms::SingleCandidate,
(Named::ArrowUp, _) => keysyms::Up,
(Named::ArrowDown, _) => keysyms::Down,
(Named::ArrowLeft, _) => keysyms::Left,
(Named::ArrowRight, _) => keysyms::Right,
(Named::PageUp, _) => keysyms::Page_Up,
(Named::PageDown, _) => keysyms::Page_Down,
(Named::Home, _) => keysyms::Home,
(Named::End, _) => keysyms::End,
(Named::Insert, _) => keysyms::Insert,
(Named::Delete, _) => keysyms::Delete,
(Named::Undo, _) => keysyms::Undo,
(Named::Redo, _) => keysyms::Redo,
(Named::ContextMenu, _) => keysyms::Menu,
(Named::Find, _) => keysyms::Find,
(Named::Cancel, _) => keysyms::Cancel,
(Named::Help, _) => keysyms::Help,
(Named::Pause, _) => keysyms::Break,
(Named::ModeChange, _) => keysyms::Mode_switch,
(Named::NumLock, _) => keysyms::Num_Lock,
(Named::CapsLock, _) => keysyms::Caps_Lock,
(Named::ScrollLock, _) => keysyms::Scroll_Lock,
(Named::PrintScreen, _) => keysyms::Print,
(Named::F1, _) => keysyms::F1,
(Named::F2, _) => keysyms::F2,
(Named::F3, _) => keysyms::F3,
(Named::F4, _) => keysyms::F4,
(Named::F5, _) => keysyms::F5,
(Named::F6, _) => keysyms::F6,
(Named::F7, _) => keysyms::F7,
(Named::F8, _) => keysyms::F8,
(Named::F9, _) => keysyms::F9,
(Named::F10, _) => keysyms::F10,
(Named::F11, _) => keysyms::F11,
(Named::F12, _) => keysyms::F12,
(Named::F13, _) => keysyms::F13,
(Named::F14, _) => keysyms::F14,
(Named::F15, _) => keysyms::F15,
(Named::F16, _) => keysyms::F16,
(Named::F17, _) => keysyms::F17,
(Named::F18, _) => keysyms::F18,
(Named::F19, _) => keysyms::F19,
(Named::F20, _) => keysyms::F20,
(Named::Shift, _) => keysyms::Shift_L,
(Named::Control, _) => keysyms::Control_L,
(Named::Alt, _) => keysyms::Alt_L,
(Named::Super, _) => keysyms::Super_L,
(Named::Hyper, _) => keysyms::Hyper_L,
(Named::Meta, _) => keysyms::Meta_L,
(Named::AltGraph, _) => keysyms::ISO_Level3_Shift,
(Named::GroupNext, _) => keysyms::ISO_Next_Group,
(Named::GroupPrevious, _) => keysyms::ISO_Prev_Group,
(Named::GroupFirst, _) => keysyms::ISO_First_Group,
(Named::GroupLast, _) => keysyms::ISO_Last_Group,
(Named::EraseEof, _) => keysyms::_3270_EraseEOF,
(Named::Attn, _) => keysyms::_3270_Attn,
(Named::Play, _) => keysyms::_3270_Play,
(Named::ExSel, _) => keysyms::_3270_ExSelect,
(Named::CrSel, _) => keysyms::_3270_CursorSelect,
(Named::Space, _) => keysyms::space,
// XF86 multimedia / internet / power keys (subset shown)
(Named::BrightnessUp, _) => keysyms::XF86_MonBrightnessUp,
(Named::BrightnessDown, _) => keysyms::XF86_MonBrightnessDown,
(Named::Standby, _) => keysyms::XF86_Standby,
(Named::AudioVolumeDown, _) => keysyms::XF86_AudioLowerVolume,
(Named::AudioVolumeUp, _) => keysyms::XF86_AudioRaiseVolume,
(Named::MediaPlay, _) => keysyms::XF86_AudioPlay,
(Named::MediaStop, _) => keysyms::XF86_AudioStop,
(Named::MediaTrackPrevious, _) => keysyms::XF86_AudioPrev,
(Named::MediaTrackNext, _) => keysyms::XF86_AudioNext,
(Named::BrowserHome, _) => keysyms::XF86_HomePage,
(Named::LaunchMail, _) => keysyms::XF86_Mail,
(Named::BrowserSearch, _) => keysyms::XF86_Search,
(Named::MediaRecord, _) => keysyms::XF86_AudioRecord,
(Named::LaunchApplication2, _) => keysyms::XF86_Calculator,
(Named::LaunchCalendar, _) => keysyms::XF86_Calendar,
(Named::Power, _) => keysyms::XF86_PowerDown,
(Named::BrowserBack, _) => keysyms::XF86_Back,
(Named::BrowserForward, _) => keysyms::XF86_Forward,
(Named::BrowserRefresh, _) => keysyms::XF86_Refresh,
(Named::WakeUp, _) => keysyms::XF86_WakeUp,
(Named::Eject, _) => keysyms::XF86_Eject,
(Named::LaunchScreenSaver, _) => keysyms::XF86_ScreenSaver,
(Named::LaunchWebBrowser, _) => keysyms::XF86_WWW,
(Named::BrowserFavorites, _) => keysyms::XF86_Favorites,
(Named::MediaPause, _) => keysyms::XF86_AudioPause,
(Named::LaunchApplication1, _) => keysyms::XF86_MyComputer,
(Named::Close, _) => keysyms::XF86_Close,
(Named::Copy, _) => keysyms::XF86_Copy,
(Named::Cut, _) => keysyms::XF86_Cut,
(Named::LaunchSpreadsheet, _) => keysyms::XF86_Excel,
(Named::LogOff, _) => keysyms::XF86_LogOff,
(Named::New, _) => keysyms::XF86_New,
(Named::Open, _) => keysyms::XF86_Open,
(Named::Paste, _) => keysyms::XF86_Paste,
(Named::LaunchPhone, _) => keysyms::XF86_Phone,
(Named::MailReply, _) => keysyms::XF86_Reply,
(Named::Save, _) => keysyms::XF86_Save,
(Named::MailSend, _) => keysyms::XF86_Send,
(Named::SpellCheck, _) => keysyms::XF86_Spell,
(Named::SplitScreenToggle, _) => keysyms::XF86_SplitScreen,
(Named::LaunchMediaPlayer, _) => keysyms::XF86_Video,
(Named::LaunchWordProcessor, _) => keysyms::XF86_Word,
(Named::ZoomIn, _) => keysyms::XF86_ZoomIn,
(Named::ZoomOut, _) => keysyms::XF86_ZoomOut,
(Named::LaunchWebCam, _) => keysyms::XF86_WebCam,
(Named::MailForward, _) => keysyms::XF86_MailForward,
(Named::LaunchMusicPlayer, _) => keysyms::XF86_Music,
(Named::MediaFastForward, _) => keysyms::XF86_AudioForward,
(Named::RandomToggle, _) => keysyms::XF86_AudioRandomPlay,
(Named::Subtitle, _) => keysyms::XF86_Subtitle,
(Named::MediaAudioTrack, _) => keysyms::XF86_AudioCycleTrack,
(Named::Hibernate, _) => keysyms::XF86_Hibernate,
(Named::AudioVolumeMute, _) => keysyms::XF86_AudioMute,
(Named::VideoModeNext, _) => keysyms::XF86_Next_VMode,
_ => return None,
}),
Key::Character(c) if c.chars().count() == 1 => {
Some(match (c.chars().next(), location) {
(Some('0'), Location::Numpad) => keysyms::KP_0,
(Some('1'), Location::Numpad) => keysyms::KP_1,
(Some('2'), Location::Numpad) => keysyms::KP_2,
(Some('3'), Location::Numpad) => keysyms::KP_3,
(Some('4'), Location::Numpad) => keysyms::KP_4,
(Some('5'), Location::Numpad) => keysyms::KP_5,
(Some('6'), Location::Numpad) => keysyms::KP_6,
(Some('7'), Location::Numpad) => keysyms::KP_7,
(Some('8'), Location::Numpad) => keysyms::KP_8,
(Some('9'), Location::Numpad) => keysyms::KP_9,
(Some('.'), Location::Numpad) => keysyms::KP_Decimal,
(Some('+'), Location::Numpad) => keysyms::KP_Add,
(Some('-'), Location::Numpad) => keysyms::KP_Subtract,
(Some('*'), Location::Numpad) => keysyms::KP_Multiply,
(Some('/'), Location::Numpad) => keysyms::KP_Divide,
(Some('='), Location::Numpad) => keysyms::KP_Equal,
(Some(c), _) => unsafe {
let keysym =
xkbcommon::xkb::ffi::xkb_utf32_to_keysym(c as u32);
if keysym == keysyms::NoSymbol {
return None;
}
keysym
},
_ => return None,
})
}
_ => None,
};
raw.map(|k| xkeysym::Keysym::new(k))
}

View file

@ -8,7 +8,7 @@ pub mod subsurface_widget;
pub mod winit_window;
use super::{PlatformSpecific, SurfaceIdWrapper};
use crate::{Control, Program, WindowManager};
use crate::{Control, CreateCompositor, Program, WindowManager};
use crate::platform_specific::UserInterfaces;
use cctk::sctk::reexports::calloop;
@ -150,12 +150,14 @@ impl WaylandSpecific {
self.conn.as_ref()
}
pub(crate) fn handle_event<'a, P>(
pub(crate) async fn handle_event<'a, 'b, P>(
&mut self,
e: SctkEvent,
events: &mut Vec<(Option<window::Id>, iced_runtime::core::Event)>,
program: &'a crate::program::Instance<P>,
compositor: &mut <<P as Program>::Renderer as compositor::Default>::Compositor,
compositor: &mut Option<
<<P as Program>::Renderer as compositor::Default>::Compositor,
>,
window_manager: &mut WindowManager<
P,
<<P as Program>::Renderer as compositor::Default>::Compositor,
@ -166,6 +168,7 @@ impl WaylandSpecific {
window::Id,
(u64, iced_accessibility::accesskit_winit::Adapter),
>,
create_compositor: CreateCompositor<'b, P>,
) where
P: Program,
{
@ -196,22 +199,25 @@ impl WaylandSpecific {
return Default::default();
};
sctk_event.process(
modifiers,
program,
compositor,
window_manager,
surface_ids,
sender,
event_sender,
proxy,
user_interfaces,
events,
clipboard,
subsurface_state,
#[cfg(feature = "a11y")]
adapters,
);
sctk_event
.process(
modifiers,
program,
compositor,
window_manager,
surface_ids,
sender,
event_sender,
proxy,
user_interfaces,
events,
clipboard,
subsurface_state,
#[cfg(feature = "a11y")]
adapters,
create_compositor,
)
.await;
}
};
}

View file

@ -1,5 +1,5 @@
use crate::{
Clipboard, Control, Program,
Clipboard, Control, CreateCompositor, Error, Program, create_compositor,
platform_specific::{
SurfaceIdWrapper, UserInterfaces,
wayland::{
@ -342,11 +342,13 @@ pub struct SurfaceCompositorUpdate {
}
impl SctkEvent {
pub(crate) fn process<'a, P>(
pub(crate) async fn process<'a, 'b, P>(
self,
modifiers: &mut Modifiers,
program: &'a crate::program::Instance<P>,
compositor: &mut <<P as Program>::Renderer as compositor::Default>::Compositor,
compositor: &mut Option<
<<P as Program>::Renderer as compositor::Default>::Compositor,
>,
window_manager: &mut crate::WindowManager<
P,
<<P as Program>::Renderer as compositor::Default>::Compositor,
@ -363,6 +365,7 @@ impl SctkEvent {
window::Id,
(u64, iced_accessibility::accesskit_winit::Adapter),
>,
create_compositor_data: CreateCompositor<'b, P>,
) where
P: Program,
{
@ -766,7 +769,25 @@ impl SctkEvent {
sctk_winit.clone(),
))
.expect("Send control message");
if compositor.is_none() {
match create_compositor(
sctk_winit.clone(),
create_compositor_data,
)
.await
{
Ok(c) => *compositor = Some(c),
Err(error) => {
control_sender
.start_send(Control::Crash(
Error::GraphicsCreationFailed(error),
))
.expect("Send control message");
return;
}
};
}
let compositor = compositor.as_mut().unwrap();
let window = window_manager.insert(
surface_id,
sctk_winit,
@ -976,6 +997,10 @@ impl SctkEvent {
},
);
}
let Some(compositor) = compositor.as_mut() else {
log::error!("compositor missing");
return;
};
let window = window_manager.insert(
surface_id,
@ -1190,6 +1215,25 @@ impl SctkEvent {
},
);
}
if compositor.is_none() {
match create_compositor(
sctk_winit.clone(),
create_compositor_data,
)
.await
{
Ok(c) => *compositor = Some(c),
Err(error) => {
control_sender
.start_send(Control::Crash(
Error::GraphicsCreationFailed(error),
))
.expect("Send control message");
return;
}
};
}
let compositor = compositor.as_mut().unwrap();
let window = window_manager.insert(
surface_id,
@ -1201,20 +1245,70 @@ impl SctkEvent {
);
_ = surface_ids.insert(object_id, wrapper.clone());
let logical_size = window.logical_size();
todo!()
// let _ = user_interfaces.insert(
// surface_id,
// crate::build_user_interface(
// program,
// user_interface::Cache::default(),
// &mut window.renderer,
// logical_size,
// surface_id,
// window.raw.clone(),
// window.prev_dnd_destination_rectangles_count,
// clipboard,
// ),
// );
let mut ui = crate::build_user_interface(
program,
user_interface::Cache::default(),
&mut window.renderer,
logical_size,
surface_id,
window.raw.clone(),
window.prev_dnd_destination_rectangles_count,
clipboard,
);
_ = ui.update(
&vec![iced_runtime::core::Event::PlatformSpecific(
iced_runtime::core::event::PlatformSpecific::Wayland(
iced_runtime::core::event::wayland::Event::RequestResize,
),
)],
window.state.cursor(),
&mut window.renderer,
clipboard,
&mut Vec::new(),
);
if let Some(requested_size) =
clipboard.requested_logical_size.lock().unwrap().take()
{
let requested_physical_size = winit::dpi::PhysicalSize::new(
(requested_size.width as f64
* window.state.scale_factor())
.ceil() as u32,
(requested_size.height as f64
* window.state.scale_factor())
.ceil() as u32,
);
let physical_size = window.state.physical_size();
if requested_physical_size.width != physical_size.width
|| requested_physical_size.height
!= physical_size.height
{
// 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;
let s =
winit::dpi::Size::Physical(requested_physical_size);
_ = window.raw.request_surface_size(s);
window.raw.set_min_surface_size(Some(s));
window.raw.set_max_surface_size(Some(s));
window.state.synchronize(
&program,
surface_id,
window.raw.as_ref(),
);
}
}
events.push((
Some(surface_id),
iced_runtime::core::Event::PlatformSpecific(
PlatformSpecific::Wayland(wayland::Event::Subsurface(
wayland::SubsurfaceEvent::Created,
)),
),
));
_ = user_interfaces.insert(surface_id, ui);
}
SctkEvent::SessionLockSurfaceConfigure {
surface,
@ -1434,6 +1528,10 @@ impl SctkEvent {
},
);
}
let Some(compositor) = compositor.as_mut() else {
log::error!("compositor missing");
return;
};
let window = window_manager.insert(
surface_id,

View file

@ -72,8 +72,10 @@ where
);
let renderer = compositor.create_renderer();
self.aliases.retain(|w, i| *w != window.id() && *i != id);
let _ = self.aliases.insert(window.id(), id);
self.entries.retain(|old, _| id != *old);
let _ = self.entries.insert(
id,
Window {