feat: avoid tooltip creation if there is an existing popup

This commit is contained in:
Ashley Wulber 2025-02-27 14:54:03 -05:00
parent 40748c3037
commit 8b5d5ee45c
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
4 changed files with 78 additions and 66 deletions

View file

@ -210,7 +210,10 @@ impl cosmic::Application for Window {
}, },
); );
self.core.applet.applet_tooltip(btn, "test").into() self.core
.applet
.applet_tooltip(btn, "test", self.popup.is_some())
.into()
} }
fn view_window(&self, _id: Id) -> Element<Self::Message> { fn view_window(&self, _id: Id) -> Element<Self::Message> {

View file

@ -132,11 +132,11 @@ where
match surface_message { match surface_message {
SurfaceMessage::AppSubsurface(settings, view) => { SurfaceMessage::AppSubsurface(settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings) let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok() .ok()
.and_then(|s| s.downcast::<Box<dyn Fn(&mut T) -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync>>().ok()) else { .and_then(|s| s.downcast::<Box<dyn Fn(&mut T) -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync>>().ok()) else {
tracing::error!("Invalid settings for subsurface"); tracing::error!("Invalid settings for subsurface");
return Task::none(); return Task::none();
}; };
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<
@ -165,11 +165,11 @@ where
} }
SurfaceMessage::Subsurface(settings, view) => { SurfaceMessage::Subsurface(settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings) let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok() .ok()
.and_then(|s| s.downcast::<Box<dyn Fn() -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync>>().ok()) else { .and_then(|s| s.downcast::<Box<dyn Fn() -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync>>().ok()) else {
tracing::error!("Invalid settings for subsurface"); tracing::error!("Invalid settings for subsurface");
return Task::none(); return Task::none();
}; };
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<
@ -197,11 +197,11 @@ where
} }
SurfaceMessage::AppPopup(settings, view) => { SurfaceMessage::AppPopup(settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings) let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok() .ok()
.and_then(|s| s.downcast::<Box<dyn Fn(&mut T) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send + Sync>>().ok()) else { .and_then(|s| s.downcast::<Box<dyn Fn(&mut T) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send + Sync>>().ok()) else {
tracing::error!("Invalid settings for popup"); tracing::error!("Invalid settings for popup");
return Task::none(); return Task::none();
}; };
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<
@ -245,11 +245,11 @@ where
} }
SurfaceMessage::Popup(settings, view) => { SurfaceMessage::Popup(settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings) let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok() .ok()
.and_then(|s| s.downcast::<Box<dyn Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send + Sync>>().ok()) else { .and_then(|s| s.downcast::<Box<dyn Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send + Sync>>().ok()) else {
tracing::error!("Invalid settings for popup"); tracing::error!("Invalid settings for popup");
return Task::none(); return Task::none();
}; };
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<
@ -274,6 +274,7 @@ where
iced_winit::commands::popup::get_popup(settings()) iced_winit::commands::popup::get_popup(settings())
} }
} }
SurfaceMessage::Ignore => iced::Task::none(),
} }
#[cfg(not(feature = "wayland"))] #[cfg(not(feature = "wayland"))]
iced::Task::none() iced::Task::none()

View file

@ -238,8 +238,9 @@ impl Context {
&self, &self,
content: impl Into<Element<'a, Message>>, content: impl Into<Element<'a, Message>>,
tooltip: impl Into<Cow<'static, str>>, tooltip: impl Into<Cow<'static, str>>,
has_popup: bool,
) -> crate::widget::wayland::tooltip::widget::Tooltip<'a, Message> { ) -> crate::widget::wayland::tooltip::widget::Tooltip<'a, Message> {
let window_id = TOOLTIP_WINDOW_ID.clone(); let window_id = *TOOLTIP_WINDOW_ID;
let subsurface_id = TOOLTIP_ID.clone(); let subsurface_id = TOOLTIP_ID.clone();
let anchor = self.anchor; let anchor = self.anchor;
let tooltip = tooltip.into(); let tooltip = tooltip.into();
@ -254,50 +255,53 @@ impl Context {
PanelAnchor::Top => (Anchor::Bottom, Gravity::Bottom), PanelAnchor::Top => (Anchor::Bottom, Gravity::Bottom),
PanelAnchor::Bottom => (Anchor::Top, Gravity::Top), PanelAnchor::Bottom => (Anchor::Top, Gravity::Top),
}; };
if has_popup {
crate::app::message::simple_popup::< SurfaceMessage::Ignore.into()
Message, } else {
Option< crate::app::message::simple_popup::<
Box< Message,
dyn Fn() -> crate::Element<'static, crate::app::Message<Message>> Option<
+ Send Box<
+ Sync dyn Fn() -> crate::Element<'static, crate::app::Message<Message>>
+ 'static, + Send
+ Sync
+ 'static,
>,
>, >,
>, >(
>( move || SctkPopupSettings {
move || SctkPopupSettings { parent: window::Id::RESERVED,
parent: window::Id::RESERVED, id: window_id,
id: window_id, grab: false,
grab: false, input_zone: Some(Rectangle::default()),
input_zone: Some(Rectangle::default()), positioner: SctkPositioner {
positioner: SctkPositioner { size: None,
size: None, size_limits: Limits::NONE.min_width(1.).min_height(1.),
size_limits: Limits::NONE.min_width(1.).min_height(1.), anchor_rect: Rectangle {
anchor_rect: Rectangle { x: bounds.x.round() as i32,
x: bounds.x.round() as i32, y: bounds.y.round() as i32,
y: bounds.y.round() as i32, width: bounds.width.round() as i32,
width: bounds.width.round() as i32, height: bounds.height.round() as i32,
height: bounds.height.round() as i32, },
anchor: popup_anchor,
gravity,
constraint_adjustment: 15,
offset: (0, 0),
reactive: true,
}, },
anchor: popup_anchor, parent_size: None,
gravity, close_with_children: true,
constraint_adjustment: 15,
offset: (0, 0),
reactive: true,
}, },
parent_size: None, Some(Box::new(move || {
close_with_children: true, Element::<'static, crate::app::Message<Message>>::from(autosize::autosize(
}, layer_container(crate::widget::text(tooltip.clone()))
Some(Box::new(move || { .layer(crate::cosmic_theme::Layer::Background)
Element::<'static, crate::app::Message<Message>>::from(autosize::autosize( .padding(4.),
layer_container(crate::widget::text(tooltip.clone())) subsurface_id.clone(),
.layer(crate::cosmic_theme::Layer::Background) ))
.padding(4.), })),
subsurface_id.clone(), )
)) }
})),
)
}; };
crate::widget::wayland::tooltip::widget::Tooltip::new( crate::widget::wayland::tooltip::widget::Tooltip::new(
content, content,

View file

@ -50,14 +50,17 @@ pub enum SurfaceMessage {
/// Requested Full Size for expanded menu bar /// Requested Full Size for expanded menu bar
size: Size, size: Size,
}, },
Ignore,
} }
impl std::fmt::Debug for SurfaceMessage { impl std::fmt::Debug for SurfaceMessage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::AppSubsurface(arg0, arg1) => { Self::AppSubsurface(arg0, arg1) => f
f.debug_tuple("Subsurface").field(arg0).field(arg1).finish() .debug_tuple("AppSubsurface")
} .field(arg0)
.field(arg1)
.finish(),
Self::Subsurface(arg0, arg1) => { Self::Subsurface(arg0, arg1) => {
f.debug_tuple("Subsurface").field(arg0).field(arg1).finish() f.debug_tuple("Subsurface").field(arg0).field(arg1).finish()
} }
@ -79,6 +82,7 @@ impl std::fmt::Debug for SurfaceMessage {
.field("limits", limits) .field("limits", limits)
.field("size", size) .field("size", size)
.finish(), .finish(),
Self::Ignore => write!(f, "Ignore"),
} }
} }
} }