improv(audio): adjust popup size based on window size

This commit is contained in:
Ashley Wulber 2026-06-17 20:56:08 -04:00 committed by Michael Murphy
parent 95eda40878
commit 456d052535

View file

@ -19,13 +19,17 @@ use cosmic::{
cosmic_config::CosmicConfigEntry, cosmic_config::CosmicConfigEntry,
cosmic_theme::Spacing, cosmic_theme::Spacing,
iced::{ iced::{
self, Alignment, Length, Subscription, self, Alignment, Length, Rectangle, Subscription,
futures::StreamExt, futures::StreamExt,
widget::{self, column, row, slider}, widget::{self, column, row, slider},
window, window,
}, },
surface, theme, surface, theme,
widget::{Row, button, container, divider, icon, space, text, toggler}, widget::{
Row, button, container, divider, icon,
rectangle_tracker::{RectangleTracker, RectangleUpdate, rectangle_tracker_subscription},
space, text, toggler,
},
}; };
use cosmic_settings_audio_client::{self as audio_client, CosmicAudioProxy}; use cosmic_settings_audio_client::{self as audio_client, CosmicAudioProxy};
use futures::SinkExt; use futures::SinkExt;
@ -73,6 +77,8 @@ pub struct Audio {
player_status: Option<mpris_subscription::PlayerStatus>, player_status: Option<mpris_subscription::PlayerStatus>,
/// Used to request an activation token for opening cosmic-settings. /// Used to request an activation token for opening cosmic-settings.
token_tx: Option<calloop::channel::Sender<TokenRequest>>, token_tx: Option<calloop::channel::Sender<TokenRequest>>,
rectangle_tracker: Option<RectangleTracker<u32>>,
rectangle: Option<iced::Rectangle>,
} }
impl Audio { impl Audio {
@ -138,6 +144,7 @@ pub enum Message {
OpenSettings, OpenSettings,
Subscription(audio_client::Event), Subscription(audio_client::Event),
Surface(surface::Action), Surface(surface::Action),
Rectangle(RectangleUpdate<u32>),
} }
// TODO // TODO
@ -272,6 +279,14 @@ impl cosmic::Application for Audio {
fn update(&mut self, message: Message) -> app::Task<Message> { fn update(&mut self, message: Message) -> app::Task<Message> {
match message { match message {
Message::Rectangle(u) => match u {
RectangleUpdate::Rectangle(r) => {
self.rectangle = Some(r.1);
}
RectangleUpdate::Init(tracker) => {
self.rectangle_tracker.replace(tracker);
}
},
Message::Ignore => {} Message::Ignore => {}
Message::TogglePopup => { Message::TogglePopup => {
if let Some(p) = self.popup.take() { if let Some(p) = self.popup.take() {
@ -292,14 +307,21 @@ impl cosmic::Application for Audio {
(100, &[][..]) (100, &[][..])
}; };
let popup_settings = self.core.applet.get_popup_settings( let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(), self.core.main_window_id().unwrap(),
new_id, new_id,
None, None,
None, None,
None, None,
); );
if let Some(r) = self.rectangle {
popup_settings.positioner.anchor_rect = Rectangle {
x: r.x as i32,
y: r.y as i32,
width: r.width as i32,
height: r.height as i32,
};
}
return get_popup(popup_settings); return get_popup(popup_settings);
} }
} }
@ -548,6 +570,7 @@ impl cosmic::Application for Audio {
}, },
) )
}), }),
rectangle_tracker_subscription(0).map(|update| Message::Rectangle(update.1)),
]) ])
} }
@ -573,48 +596,59 @@ impl cosmic::Application for Audio {
Message::SetSinkVolume(new_volume as u32) Message::SetSinkVolume(new_volume as u32)
}); });
let mut has_playback_buttons = false;
let playback_buttons = (!self.core.applet.suggested_bounds.as_ref().is_some_and(|c| { let playback_buttons = (!self.core.applet.suggested_bounds.as_ref().is_some_and(|c| {
// if we have a configure for width and height, we're in a overflow popup // if we have a configure for width and height, we're in a overflow popup
c.width > 0. && c.height > 0. c.width > 0. && c.height > 0.
})) }))
.then(|| self.playback_buttons()); .then(|| self.playback_buttons());
self.core let mut ret = if let Some(playback_buttons) = playback_buttons
.applet && !playback_buttons.is_empty()
.autosize_window( {
if let Some(playback_buttons) = playback_buttons has_playback_buttons = true;
&& !playback_buttons.is_empty() Element::from(match self.core.applet.anchor {
{ PanelAnchor::Left | PanelAnchor::Right => Element::from(
match self.core.applet.anchor { applet_column::Column::with_children(playback_buttons)
PanelAnchor::Left | PanelAnchor::Right => Element::from( .push(btn)
applet_column::Column::with_children(playback_buttons) .align_x(Alignment::Center)
.push(btn) .height(Length::Shrink)
.align_x(Alignment::Center) // TODO configurable variable from the panel?
.height(Length::Shrink) .spacing(
// TODO configurable variable from the panel? -(self.core.applet.suggested_padding(true).0 as f32)
.spacing( * self.core.applet.padding_overlap,
-(self.core.applet.suggested_padding(true).0 as f32)
* self.core.applet.padding_overlap,
),
), ),
PanelAnchor::Top | PanelAnchor::Bottom => { ),
applet_row::Row::with_children(playback_buttons) PanelAnchor::Top | PanelAnchor::Bottom => {
.push(btn) applet_row::Row::with_children(playback_buttons)
.align_y(Alignment::Center) .push(btn)
.width(Length::Shrink) .align_y(Alignment::Center)
// TODO configurable variable from the panel? .width(Length::Shrink)
.spacing( // TODO configurable variable from the panel?
-(self.core.applet.suggested_padding(true).0 as f32) .spacing(
* self.core.applet.padding_overlap, -(self.core.applet.suggested_padding(true).0 as f32)
) * self.core.applet.padding_overlap,
.into() )
} .into()
} }
} else { })
btn.into() } else {
}, btn.into()
) };
.into()
if let Some(tracker) = self.rectangle_tracker.as_ref()
&& has_playback_buttons
{
ret = tracker.container(0, ret).into()
}
if !self.core.applet.suggested_bounds.as_ref().is_some_and(|c| {
// if we have a configure for width and height, we're in a overflow popup
c.width > 0. && c.height > 0.
}) {
ret = self.core.applet.autosize_window(ret).into();
}
ret
} }
fn view_window(&self, _id: window::Id) -> Element<'_, Message> { fn view_window(&self, _id: window::Id) -> Element<'_, Message> {