fix: explicit lifetimes for view closures
This commit is contained in:
parent
add66a6424
commit
354b4866ec
6 changed files with 127 additions and 93 deletions
|
|
@ -105,7 +105,9 @@ libc = { version = "0.2.155", optional = true }
|
||||||
license = { version = "3.5.1", optional = true }
|
license = { version = "3.5.1", optional = true }
|
||||||
mime = { version = "0.3.17", optional = true }
|
mime = { version = "0.3.17", optional = true }
|
||||||
palette = "0.7.3"
|
palette = "0.7.3"
|
||||||
rfd = { version = "0.14.0", default-features = false, features = ["xdg-portal"], optional = true }
|
rfd = { version = "0.14.0", default-features = false, features = [
|
||||||
|
"xdg-portal",
|
||||||
|
], optional = true }
|
||||||
rustix = { version = "0.38.34", features = [
|
rustix = { version = "0.38.34", features = [
|
||||||
"pipe",
|
"pipe",
|
||||||
"process",
|
"process",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use cosmic::app::Core;
|
use cosmic::app::Core;
|
||||||
|
use cosmic::iced::event::listen_with;
|
||||||
use cosmic::iced::window::Id;
|
use cosmic::iced::window::Id;
|
||||||
use cosmic::iced::{Length, Limits, Task};
|
use cosmic::iced::{self, Length, Limits, Task};
|
||||||
use cosmic::iced_runtime::core::window;
|
use cosmic::iced_runtime::core::window;
|
||||||
use cosmic::iced_runtime::platform_specific::wayland::popup::SctkPopupSettings;
|
use cosmic::iced_runtime::platform_specific::wayland::popup::SctkPopupSettings;
|
||||||
use cosmic::iced_runtime::platform_specific::wayland::subsurface;
|
use cosmic::iced_runtime::platform_specific::wayland::subsurface;
|
||||||
|
|
@ -114,7 +115,7 @@ impl cosmic::Application for Window {
|
||||||
self.example_row = toggled;
|
self.example_row = toggled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::Surface(surface_message) => {}
|
Message::Surface(_) => {}
|
||||||
Message::Selected(i) => {
|
Message::Selected(i) => {
|
||||||
self.selected = Some(i);
|
self.selected = Some(i);
|
||||||
return cosmic::task::message(cosmic::app::message::destroy_popup::<Window>(
|
return cosmic::task::message(cosmic::app::message::destroy_popup::<Window>(
|
||||||
|
|
@ -123,16 +124,14 @@ impl cosmic::Application for Window {
|
||||||
}
|
}
|
||||||
Message::OpenDropdown(sctk_popup_settings, view) => {
|
Message::OpenDropdown(sctk_popup_settings, view) => {
|
||||||
self.dropdown_id = sctk_popup_settings.id;
|
self.dropdown_id = sctk_popup_settings.id;
|
||||||
return cosmic::task::message(cosmic::app::message::app_popup::<
|
return cosmic::task::message(cosmic::app::message::app_popup::<Window>(
|
||||||
Window,
|
move |_: &mut Window| sctk_popup_settings.clone(),
|
||||||
>(
|
Some(Box::new(
|
||||||
move |_: &mut Window| sctk_popup_settings.clone(),
|
move |_: &Window| -> cosmic::Element<'_, cosmic::app::Message<Message>> {
|
||||||
Some(
|
view().map(cosmic::app::Message::App)
|
||||||
move |_: &Window| -> cosmic::Element<'static, cosmic::app::Message<Message>> {
|
},
|
||||||
view().map(cosmic::app::Message::App)
|
)),
|
||||||
},
|
));
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Message::PopupCloseRequested(id) => {
|
Message::PopupCloseRequested(id) => {
|
||||||
return cosmic::task::message(cosmic::app::message::destroy_popup::<Window>(id));
|
return cosmic::task::message(cosmic::app::message::destroy_popup::<Window>(id));
|
||||||
|
|
@ -169,57 +168,67 @@ impl cosmic::Application for Window {
|
||||||
popup_settings
|
popup_settings
|
||||||
},
|
},
|
||||||
Some(
|
Some(
|
||||||
move |state: &Window| -> cosmic::Element<
|
Box::new(
|
||||||
'static,
|
move |state: &Window| -> cosmic::Element<
|
||||||
cosmic::app::Message<Message>,
|
'_,
|
||||||
> {
|
cosmic::app::Message<Message>,
|
||||||
{
|
> {
|
||||||
let content_list = list_column().padding(5).spacing(0).add(
|
{
|
||||||
settings::item(
|
let content_list = list_column()
|
||||||
"Example row",
|
.padding(5)
|
||||||
cosmic::widget::container(
|
.spacing(0)
|
||||||
toggler(state.example_row).on_toggle(|value| {
|
.add(settings::item(
|
||||||
Message::ToggleExampleRow(value)
|
"Example row",
|
||||||
}),
|
cosmic::widget::container(
|
||||||
)
|
toggler(state.example_row).on_toggle(|value| {
|
||||||
.height(Length::Fixed(50.)),
|
Message::ToggleExampleRow(value)
|
||||||
),
|
}),
|
||||||
).add(dropdown(&["1", "asdf", "hello", "test"], state.selected, Message::Selected).with_popup(state.popup.unwrap_or(Id::NONE), Message::OpenDropdown).on_close_popup(Message::PopupCloseRequested)
|
)
|
||||||
);
|
.height(Length::Fixed(50.)),
|
||||||
Element::from(
|
))
|
||||||
state.core.applet.popup_container(content_list),
|
.add(
|
||||||
)
|
dropdown(
|
||||||
.map(cosmic::app::Message::App)
|
&["1", "asdf", "hello", "test"],
|
||||||
}
|
state.selected,
|
||||||
},
|
Message::Selected,
|
||||||
|
)
|
||||||
|
.with_popup(
|
||||||
|
state.popup.unwrap_or(Id::NONE),
|
||||||
|
Message::OpenDropdown,
|
||||||
|
)
|
||||||
|
.on_close_popup(Message::PopupCloseRequested),
|
||||||
|
);
|
||||||
|
Element::from(
|
||||||
|
state.core.applet.popup_container(content_list),
|
||||||
|
)
|
||||||
|
.map(cosmic::app::Message::App)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|_| {
|
|_| {
|
||||||
cosmic::app::message::subsurface(
|
cosmic::app::message::subsurface(
|
||||||
|app: &mut Window| {
|
|app: &mut Window| subsurface::SctkSubsurfaceSettings {
|
||||||
subsurface::SctkSubsurfaceSettings {
|
parent: window::Id::RESERVED,
|
||||||
parent: window::Id::RESERVED,
|
id: app.subsurface_id,
|
||||||
id: app.subsurface_id,
|
loc: iced_core::Point { x: -100., y: 0. },
|
||||||
loc: iced_core::Point { x: -100., y: 0. },
|
size: Some((10., 10.).into()),
|
||||||
size: Some((10., 10.).into()),
|
z: 1,
|
||||||
z: 1,
|
steal_keyboard_focus: true,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Some(|_: &Window| {
|
Some(Box::new(|_: &'_ Window| {
|
||||||
autosize::autosize(
|
Element::from(autosize::autosize(
|
||||||
layer_container(cosmic::widget::text("hello"))
|
layer_container(cosmic::widget::text("hello"))
|
||||||
.layer(cosmic::cosmic_theme::Layer::Background),
|
.layer(cosmic::cosmic_theme::Layer::Background),
|
||||||
SUBSURFACE_ID.clone(),
|
SUBSURFACE_ID.clone(),
|
||||||
)
|
))
|
||||||
.into()
|
})),
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
cosmic::app::message::destroy_subsurface::<Window>(
|
cosmic::app::message::destroy_subsurface::<Window>(self.subsurface_id),
|
||||||
self.subsurface_id
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
@ -231,4 +240,13 @@ impl cosmic::Application for Window {
|
||||||
fn style(&self) -> Option<cosmic::iced_runtime::Appearance> {
|
fn style(&self) -> Option<cosmic::iced_runtime::Appearance> {
|
||||||
Some(cosmic::applet::style())
|
Some(cosmic::applet::style())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn subscription(&self) -> cosmic::iced::Subscription<Self::Message> {
|
||||||
|
listen_with(|e, status, id| {
|
||||||
|
if matches!(e, iced::event::Event::Keyboard(_)) {
|
||||||
|
dbg!(e, id);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use apply::Apply;
|
||||||
use cosmic::app::{Core, Settings, Task};
|
use cosmic::app::{Core, Settings, Task};
|
||||||
use cosmic::dialog::file_chooser::{self, FileFilter};
|
use cosmic::dialog::file_chooser::{self, FileFilter};
|
||||||
use cosmic::iced_core::Length;
|
use cosmic::iced_core::Length;
|
||||||
|
use cosmic::surface_message::{SurfaceMessage, SurfaceMessageHandler};
|
||||||
use cosmic::widget::button;
|
use cosmic::widget::button;
|
||||||
use cosmic::{executor, iced, ApplicationExt, Element};
|
use cosmic::{executor, iced, ApplicationExt, Element};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -34,6 +35,22 @@ pub enum Message {
|
||||||
OpenError(Arc<file_chooser::Error>),
|
OpenError(Arc<file_chooser::Error>),
|
||||||
OpenFile,
|
OpenFile,
|
||||||
Selected(Url),
|
Selected(Url),
|
||||||
|
Surface(SurfaceMessage),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SurfaceMessageHandler for Message {
|
||||||
|
fn to_surface_message(self) -> cosmic::surface_message::MessageWrapper<Self> {
|
||||||
|
match self {
|
||||||
|
Message::Surface(m) => cosmic::surface_message::MessageWrapper::Surface(m),
|
||||||
|
m => cosmic::surface_message::MessageWrapper::Message(m),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SurfaceMessage> for Message {
|
||||||
|
fn from(value: SurfaceMessage) -> Self {
|
||||||
|
Message::Surface(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [`App`] stores application-specific state.
|
/// The [`App`] stores application-specific state.
|
||||||
|
|
@ -91,13 +108,11 @@ impl cosmic::Application for App {
|
||||||
Message::Cancelled => {
|
Message::Cancelled => {
|
||||||
eprintln!("open file dialog cancelled");
|
eprintln!("open file dialog cancelled");
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::FileRead(url, contents) => {
|
Message::FileRead(url, contents) => {
|
||||||
eprintln!("read file");
|
eprintln!("read file");
|
||||||
self.selected_file = Some(url);
|
self.selected_file = Some(url);
|
||||||
self.file_contents = contents;
|
self.file_contents = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::Selected(url) => {
|
Message::Selected(url) => {
|
||||||
eprintln!("selected file");
|
eprintln!("selected file");
|
||||||
|
|
||||||
|
|
@ -142,8 +157,6 @@ impl cosmic::Application for App {
|
||||||
Message::FileRead(url, contents)
|
Message::FileRead(url, contents)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new open dialog.
|
|
||||||
Message::OpenFile => {
|
Message::OpenFile => {
|
||||||
return cosmic::task::future(async move {
|
return cosmic::task::future(async move {
|
||||||
eprintln!("opening new dialog");
|
eprintln!("opening new dialog");
|
||||||
|
|
@ -169,13 +182,9 @@ impl cosmic::Application for App {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Displays an error in the application's warning bar.
|
|
||||||
Message::Error(why) => {
|
Message::Error(why) => {
|
||||||
self.error_status = Some(why);
|
self.error_status = Some(why);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Displays an error in the application's warning bar.
|
|
||||||
Message::OpenError(why) => {
|
Message::OpenError(why) => {
|
||||||
if let Some(why) = Arc::into_inner(why) {
|
if let Some(why) = Arc::into_inner(why) {
|
||||||
let mut source: &dyn std::error::Error = &why;
|
let mut source: &dyn std::error::Error = &why;
|
||||||
|
|
@ -190,10 +199,10 @@ impl cosmic::Application for App {
|
||||||
self.error_status = Some(string);
|
self.error_status = Some(string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::CloseError => {
|
Message::CloseError => {
|
||||||
self.error_status = None;
|
self.error_status = None;
|
||||||
}
|
}
|
||||||
|
Message::Surface(surface_message) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::none()
|
Task::none()
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,10 @@ pub enum Message {
|
||||||
pub struct Cosmic<App: Application> {
|
pub struct Cosmic<App: Application> {
|
||||||
pub app: App,
|
pub app: App,
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub surface_views:
|
pub surface_views: HashMap<
|
||||||
HashMap<window::Id, Box<dyn Fn(&App) -> Element<'static, super::Message<App::Message>>>>,
|
window::Id,
|
||||||
|
Box<dyn for<'a> Fn(&'a App) -> Element<'a, super::Message<App::Message>>>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Application> Cosmic<T>
|
impl<T: Application> Cosmic<T>
|
||||||
|
|
@ -138,7 +140,10 @@ where
|
||||||
|
|
||||||
if let Some(view) = view.and_then(|view| {
|
if let Some(view) = view.and_then(|view| {
|
||||||
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
|
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
|
||||||
dyn Fn(&T) -> Element<'static, super::Message<T::Message>>
|
dyn for<'a> Fn(
|
||||||
|
&'a T,
|
||||||
|
)
|
||||||
|
-> Element<'a, super::Message<T::Message>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
>>(
|
>>(
|
||||||
|
|
@ -170,7 +175,10 @@ where
|
||||||
|
|
||||||
if let Some(view) = view.and_then(|view| {
|
if let Some(view) = view.and_then(|view| {
|
||||||
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
|
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
|
||||||
dyn Fn(&T) -> Element<'static, super::Message<T::Message>>
|
dyn for<'a> Fn(
|
||||||
|
&'a T,
|
||||||
|
)
|
||||||
|
-> Element<'a, super::Message<T::Message>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
>>(
|
>>(
|
||||||
|
|
@ -840,7 +848,9 @@ impl<App: Application> Cosmic<App> {
|
||||||
pub fn get_subsurface(
|
pub fn get_subsurface(
|
||||||
&mut self,
|
&mut self,
|
||||||
settings: iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings,
|
settings: iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings,
|
||||||
view: Box<dyn Fn(&App) -> Element<'static, super::Message<App::Message>> + Send + Sync>,
|
view: Box<
|
||||||
|
dyn for<'a> Fn(&'a App) -> Element<'a, super::Message<App::Message>> + Send + Sync,
|
||||||
|
>,
|
||||||
) -> Task<super::Message<App::Message>> {
|
) -> Task<super::Message<App::Message>> {
|
||||||
use iced_winit::commands::subsurface::get_subsurface;
|
use iced_winit::commands::subsurface::get_subsurface;
|
||||||
|
|
||||||
|
|
@ -853,7 +863,9 @@ impl<App: Application> Cosmic<App> {
|
||||||
pub fn get_popup(
|
pub fn get_popup(
|
||||||
&mut self,
|
&mut self,
|
||||||
settings: iced_runtime::platform_specific::wayland::popup::SctkPopupSettings,
|
settings: iced_runtime::platform_specific::wayland::popup::SctkPopupSettings,
|
||||||
view: Box<dyn Fn(&App) -> Element<'static, super::Message<App::Message>> + Send + Sync>,
|
view: Box<
|
||||||
|
dyn for<'a> Fn(&'a App) -> Element<'a, super::Message<App::Message>> + Send + Sync,
|
||||||
|
>,
|
||||||
) -> Task<super::Message<App::Message>> {
|
) -> Task<super::Message<App::Message>> {
|
||||||
use iced_winit::commands::popup::get_popup;
|
use iced_winit::commands::popup::get_popup;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,10 +81,12 @@ pub mod message {
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
view: Option<
|
view: Option<
|
||||||
impl Fn(&App) -> crate::Element<'static, super::Message<App::Message>>
|
Box<
|
||||||
+ Send
|
dyn for<'a> Fn(&'a App) -> crate::Element<'a, super::Message<App::Message>>
|
||||||
+ Sync
|
+ Send
|
||||||
+ 'static,
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
>,
|
||||||
>,
|
>,
|
||||||
) -> App::Message
|
) -> App::Message
|
||||||
where
|
where
|
||||||
|
|
@ -104,13 +106,7 @@ pub mod message {
|
||||||
App::Message::from(SurfaceMessage::AppPopup(
|
App::Message::from(SurfaceMessage::AppPopup(
|
||||||
Arc::new(boxed),
|
Arc::new(boxed),
|
||||||
view.map(|view| {
|
view.map(|view| {
|
||||||
let boxed: Box<
|
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
|
||||||
dyn Fn(&App) -> crate::Element<'static, super::Message<App::Message>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
> = Box::new(view);
|
|
||||||
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
|
|
||||||
Arc::new(boxed)
|
Arc::new(boxed)
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
|
|
@ -118,7 +114,7 @@ pub mod message {
|
||||||
|
|
||||||
/// Used to create a popup message from within a widget.
|
/// Used to create a popup message from within a widget.
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub fn simple_popup<Message>(
|
pub fn simple_popup<Message, V>(
|
||||||
settings: impl Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
|
settings: impl Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
|
|
@ -129,6 +125,7 @@ pub mod message {
|
||||||
) -> Message
|
) -> Message
|
||||||
where
|
where
|
||||||
Message: SurfaceMessageHandler + From<SurfaceMessage> + 'static,
|
Message: SurfaceMessageHandler + From<SurfaceMessage> + 'static,
|
||||||
|
V:,
|
||||||
{
|
{
|
||||||
use std::{any::Any, sync::Arc};
|
use std::{any::Any, sync::Arc};
|
||||||
|
|
||||||
|
|
@ -173,19 +170,21 @@ pub mod message {
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub fn subsurface<App: super::Application>(
|
pub fn subsurface<App: super::Application>(
|
||||||
settings: impl Fn(&mut App) -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync + 'static,
|
settings: impl Fn(&mut App) -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync + 'static,
|
||||||
|
// XXX Boxed trait object is required for less cumbersome type inference, but we box it anyways.
|
||||||
view: Option<
|
view: Option<
|
||||||
impl Fn(&App) -> crate::Element<'static, super::Message<App::Message>>
|
Box<
|
||||||
+ Send
|
dyn for<'a> Fn(&'a App) -> crate::Element<'a, super::Message<App::Message>>
|
||||||
+ Sync
|
+ Send
|
||||||
+ 'static,
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
>,
|
||||||
>,
|
>,
|
||||||
) -> App::Message
|
) -> App::Message
|
||||||
where
|
where
|
||||||
App::Message: SurfaceMessageHandler + From<SurfaceMessage>,
|
App::Message: SurfaceMessageHandler + From<SurfaceMessage>,
|
||||||
{
|
{
|
||||||
|
use crate::surface_message::SurfaceMessage;
|
||||||
use std::{any::Any, sync::Arc};
|
use std::{any::Any, sync::Arc};
|
||||||
|
|
||||||
use crate::surface_message::{SurfaceMessage, SurfaceMessageHandler};
|
|
||||||
let boxed: Box<
|
let boxed: Box<
|
||||||
dyn Fn(
|
dyn Fn(
|
||||||
&mut App,
|
&mut App,
|
||||||
|
|
@ -200,13 +199,7 @@ pub mod message {
|
||||||
App::Message::from(SurfaceMessage::Subsurface(
|
App::Message::from(SurfaceMessage::Subsurface(
|
||||||
Arc::new(boxed),
|
Arc::new(boxed),
|
||||||
view.map(|view| {
|
view.map(|view| {
|
||||||
let boxed: Box<
|
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
|
||||||
dyn Fn(&App) -> crate::Element<'static, super::Message<App::Message>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
> = Box::new(view);
|
|
||||||
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
|
|
||||||
Arc::new(boxed)
|
Arc::new(boxed)
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//! Autosize Container, which will resize the window to its contents.
|
//! Responsive Container, which will notify of size changes.
|
||||||
|
|
||||||
use iced::{Limits, Size};
|
use iced::{Limits, Size};
|
||||||
use iced_core::event::{self, Event};
|
use iced_core::event::{self, Event};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue