applet overlap

chore: mpris dep

fix: dock buttons

improv: battery and audio improvements

feat: overlapping padding

fix: input source text button

fix: apply panel spacing to app tray

chore: update libcosmic

fix: spacing and padding

fix(minimize): hide when empty
This commit is contained in:
Ashley Wulber 2025-10-06 16:35:20 -04:00 committed by Ashley Wulber
parent b026db6f7c
commit 836c0e378b
26 changed files with 627 additions and 576 deletions

762
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -72,7 +72,10 @@ lto = "thin"
[workspace.metadata.cargo-machete] [workspace.metadata.cargo-machete]
ignored = ["libcosmic"] ignored = ["libcosmic"]
# [patch."https://github.com/pop-os/libcosmic"] [patch."https://github.com/pop-os/libcosmic"]
cosmic-config = { git = "https://github.com/pop-os/libcosmic//", branch = "shrinkable-applets" }
libcosmic = { git = "https://github.com/pop-os/libcosmic//", branch = "shrinkable-applets" }
iced_futures = { git = "https://github.com/pop-os/libcosmic//", branch = "shrinkable-applets" }
# cosmic-config = { path = "../libcosmic/cosmic-config" } # cosmic-config = { path = "../libcosmic/cosmic-config" }
# libcosmic = { path = "../libcosmic" } # libcosmic = { path = "../libcosmic" }
# iced_futures = { path = "../libcosmic/iced/futures" } # iced_futures = { path = "../libcosmic/iced/futures" }

View file

@ -79,8 +79,13 @@ static DND_FAVORITES: u64 = u64::MAX;
impl AppletIconData { impl AppletIconData {
fn new(applet: &Context) -> Self { fn new(applet: &Context) -> Self {
let icon_size = applet.suggested_size(false).0; let icon_size = applet.suggested_size(false).0;
let padding = applet.suggested_padding(false); let (major_padding, cross_padding) = applet.suggested_padding(false);
let icon_spacing = 4.0; let (h_padding, v_padding) = if applet.is_horizontal() {
(major_padding as f32, cross_padding as f32)
} else {
(cross_padding as f32, major_padding as f32)
};
let icon_spacing = applet.spacing as f32;
let (dot_radius, bar_size) = match applet.size { let (dot_radius, bar_size) = match applet.size {
Size::Hardcoded(_) => (2.0, 8.0), Size::Hardcoded(_) => (2.0, 8.0),
@ -98,14 +103,31 @@ impl AppletIconData {
} }
} }
}; };
let padding = padding as f32;
let padding = match applet.anchor { let padding = match applet.anchor {
PanelAnchor::Top => [padding - (dot_radius * 2. + 1.), padding, padding, padding], PanelAnchor::Top => [
PanelAnchor::Bottom => [padding, padding, padding - (dot_radius * 2. + 1.), padding], v_padding - (dot_radius * 2. + 1.),
PanelAnchor::Left => [padding, padding, padding, padding - (dot_radius * 2. + 1.)], h_padding,
PanelAnchor::Right => [padding, padding - (dot_radius * 2. + 1.), padding, padding], v_padding,
h_padding,
],
PanelAnchor::Bottom => [
v_padding,
h_padding,
v_padding - (dot_radius * 2. + 1.),
h_padding,
],
PanelAnchor::Left => [
v_padding,
h_padding,
v_padding,
h_padding - (dot_radius * 2. + 1.),
],
PanelAnchor::Right => [
v_padding,
h_padding - (dot_radius * 2. + 1.),
v_padding,
h_padding,
],
}; };
AppletIconData { AppletIconData {
icon_size, icon_size,
@ -920,7 +942,7 @@ impl cosmic::Application for CosmicAppList {
} }
Message::DndEnter(x, y) => { Message::DndEnter(x, y) => {
let item_size = self.core.applet.suggested_size(false).0 let item_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).0;
let pos_in_list = match self.core.applet.anchor { let pos_in_list = match self.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => x as f32, PanelAnchor::Top | PanelAnchor::Bottom => x as f32,
PanelAnchor::Left | PanelAnchor::Right => y as f32, PanelAnchor::Left | PanelAnchor::Right => y as f32,
@ -942,7 +964,7 @@ impl cosmic::Application for CosmicAppList {
} }
Message::DndMotion(x, y) => { Message::DndMotion(x, y) => {
let item_size = self.core.applet.suggested_size(false).0 let item_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).0;
let pos_in_list = match self.core.applet.anchor { let pos_in_list = match self.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => x as f32, PanelAnchor::Top | PanelAnchor::Bottom => x as f32,
PanelAnchor::Left | PanelAnchor::Right => y as f32, PanelAnchor::Left | PanelAnchor::Right => y as f32,
@ -1350,7 +1372,7 @@ impl cosmic::Application for CosmicAppList {
}; };
} }
let applet_suggested_size = self.core.applet.suggested_size(false).0 let applet_suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).0;
let (_favorite_popup_cutoff, active_popup_cutoff) = let (_favorite_popup_cutoff, active_popup_cutoff) =
self.panel_overflow_lengths(); self.panel_overflow_lengths();
let popup_applet_count = let popup_applet_count =
@ -1407,7 +1429,7 @@ impl cosmic::Application for CosmicAppList {
}; };
} }
let applet_suggested_size = self.core.applet.suggested_size(false).0 let applet_suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).0;
let (favorite_popup_cutoff, _active_popup_cutoff) = let (favorite_popup_cutoff, _active_popup_cutoff) =
self.panel_overflow_lengths(); self.panel_overflow_lengths();
let popup_applet_count = let popup_applet_count =
@ -1573,7 +1595,7 @@ impl cosmic::Application for CosmicAppList {
icon::from_name("starred-symbolic.symbolic") icon::from_name("starred-symbolic.symbolic")
.size(self.core.applet.suggested_size(false).0), .size(self.core.applet.suggested_size(false).0),
) )
.padding(self.core.applet.suggested_padding(false)) .padding(self.core.applet.suggested_padding(false).1) // TODO
.into(), .into(),
); );
} }
@ -1643,13 +1665,13 @@ impl cosmic::Application for CosmicAppList {
let window_size = self.core.applet.suggested_bounds.as_ref(); let window_size = self.core.applet.suggested_bounds.as_ref();
let max_num = if self.core.applet.is_horizontal() { let max_num = if self.core.applet.is_horizontal() {
let suggested_width = self.core.applet.suggested_size(false).0 let suggested_width = self.core.applet.suggested_size(false).0
+ self.core.applet.suggested_padding(false) * 2; + self.core.applet.suggested_padding(false).0 * 2;
window_size window_size
.map(|w| w.width) .map(|w| w.width)
.map_or(u32::MAX, |b| (b / suggested_width as f32) as u32) as usize .map_or(u32::MAX, |b| (b / suggested_width as f32) as u32) as usize
} else { } else {
let suggested_height = self.core.applet.suggested_size(false).1 let suggested_height = self.core.applet.suggested_size(false).1
+ self.core.applet.suggested_padding(false) * 2; + self.core.applet.suggested_padding(false).0 * 2;
window_size window_size
.map(|w| w.height) .map(|w| w.height)
.map_or(u32::MAX, |b| (b / suggested_height as f32) as u32) as usize .map_or(u32::MAX, |b| (b / suggested_height as f32) as u32) as usize
@ -2247,7 +2269,7 @@ impl CosmicAppList {
let applet_icon = AppletIconData::new(&self.core.applet); let applet_icon = AppletIconData::new(&self.core.applet);
let button_total_size = self.core.applet.suggested_size(true).0 let button_total_size = self.core.applet.suggested_size(true).0
+ self.core.applet.suggested_padding(true) * 2 + self.core.applet.suggested_padding(true).0 * 2
+ applet_icon.icon_spacing as u16; + applet_icon.icon_spacing as u16;
let favorite_active_cnt = self let favorite_active_cnt = self

View file

@ -21,6 +21,7 @@ Icon=preferences-desktop-accessibility-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
# Indicates that the auto-hover click should go to the "end" of the hover popup # Indicates that the auto-hover click should go to the "end" of the hover popup
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -11,7 +11,8 @@ i18n-embed-fl.workspace = true
i18n-embed.workspace = true i18n-embed.workspace = true
libcosmic.workspace = true libcosmic.workspace = true
libpulse-binding = "2.30.1" libpulse-binding = "2.30.1"
mpris2-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings" } mpris2-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings", branch = "precise-capturing" }
# mpris2-zbus = { path = "../../dbus-settings-bindings/mpris2" }
rust-embed.workspace = true rust-embed.workspace = true
serde.workspace = true serde.workspace = true
tokio.workspace = true tokio.workspace = true

View file

@ -22,6 +22,7 @@ Icon=com.system76.CosmicAppletAudio-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
# Indicates that the auto-hover click should go to the "end" of the hover popup # Indicates that the auto-hover click should go to the "end" of the hover popup
X-CosmicHoverPopup=End X-CosmicHoverPopup=End
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -12,8 +12,9 @@ use config::{AudioAppletConfig, amplification_sink, amplification_source};
use cosmic::{ use cosmic::{
Element, Renderer, Task, Theme, app, Element, Renderer, Task, Theme, app,
applet::{ applet::{
column as applet_column,
cosmic_panel_config::PanelAnchor, cosmic_panel_config::PanelAnchor,
menu_button, menu_control_padding, padded_control, menu_button, menu_control_padding, padded_control, row as applet_row,
token::subscription::{TokenRequest, TokenUpdate, activation_token_subscription}, token::subscription::{TokenRequest, TokenUpdate, activation_token_subscription},
}, },
cctk::sctk::reexports::calloop, cctk::sctk::reexports::calloop,
@ -166,10 +167,16 @@ pub enum Message {
Surface(surface::Action), Surface(surface::Action),
} }
// TODO
// mouse area with on enter and a stack widget for all buttons
// most recently entered button is on top
// position is a multiple of button size
// on leave of applet, popup button is on top again
impl Audio { impl Audio {
fn playback_buttons(&self) -> Option<Element<'_, Message>> { fn playback_buttons(&self) -> Vec<Element<'_, Message>> {
let mut elements: Vec<Element<'_, Message>> = Vec::new();
if self.player_status.is_some() && self.config.show_media_controls_in_top_panel { if self.player_status.is_some() && self.config.show_media_controls_in_top_panel {
let mut elements = Vec::with_capacity(3);
if self if self
.player_status .player_status
.as_ref() .as_ref()
@ -205,18 +212,8 @@ impl Audio {
.into(), .into(),
) )
} }
Some(match self.core.applet.anchor {
PanelAnchor::Left | PanelAnchor::Right => Column::with_children(elements)
.align_x(Alignment::Center)
.into(),
PanelAnchor::Top | PanelAnchor::Bottom => Row::with_children(elements)
.align_y(Alignment::Center)
.into(),
})
} else {
None
} }
elements
} }
fn go_previous(&self, icon_size: u16) -> Option<Element<'_, Message>> { fn go_previous(&self, icon_size: u16) -> Option<Element<'_, Message>> {
@ -724,21 +721,37 @@ impl cosmic::Application for Audio {
self.core self.core
.applet .applet
.autosize_window(if let Some(Some(playback_buttons)) = playback_buttons { .autosize_window(
match self.core.applet.anchor { if let Some(playback_buttons) = playback_buttons
PanelAnchor::Left | PanelAnchor::Right => Element::from( && !playback_buttons.is_empty()
Column::with_children([playback_buttons, btn.into()]) {
.align_x(Alignment::Center), match self.core.applet.anchor {
), PanelAnchor::Left | PanelAnchor::Right => Element::from(
PanelAnchor::Top | PanelAnchor::Bottom => { applet_column::Column::with_children(playback_buttons)
Row::with_children([playback_buttons, btn.into()]) .push(btn)
.align_y(Alignment::Center) .align_x(Alignment::Center)
.into() // TODO configurable variable from the panel?
.spacing(
-(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)
.push(btn)
.align_y(Alignment::Center)
// TODO configurable variable from the panel?
.spacing(
-(self.core.applet.suggested_padding(true).0 as f32)
* self.core.applet.padding_overlap,
)
.into()
}
} }
} } else {
} else { btn.into()
btn.into() },
}) )
.into() .into()
} }

View file

@ -21,5 +21,6 @@ Icon=com.system76.CosmicAppletBattery-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-CosmicHoverPopup=Start X-CosmicHoverPopup=Start
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -484,7 +484,7 @@ impl cosmic::Application for CosmicBatteryApplet {
} }
fn view(&self) -> Element<'_, Message> { fn view(&self) -> Element<'_, Message> {
let btn = self let btn: Element<'_, Message> = self
.core .core
.applet .applet
.icon_button(&self.icon_name) .icon_button(&self.icon_name)
@ -508,17 +508,24 @@ impl cosmic::Application for CosmicBatteryApplet {
shadow: Shadow::default(), shadow: Shadow::default(),
icon_color: Some(Color::TRANSPARENT), icon_color: Some(Color::TRANSPARENT),
} }
}))) })));
.into(); let (dot_align_x, dot_align_y) = match self.core.applet.anchor {
PanelAnchor::Left => (Alignment::Start, Alignment::Center),
PanelAnchor::Right => (Alignment::End, Alignment::Center),
PanelAnchor::Top => (Alignment::Center, Alignment::Start),
PanelAnchor::Bottom => (Alignment::Center, Alignment::End),
};
match self.core.applet.anchor { cosmic::iced::widget::stack![
PanelAnchor::Left | PanelAnchor::Right => Column::with_children([btn, dot]) btn,
.align_x(Alignment::Center) container(dot)
.into(), .width(Length::Fill)
PanelAnchor::Top | PanelAnchor::Bottom => Row::with_children([btn, dot]) .height(Length::Fill)
.align_y(Alignment::Center) .align_y(dot_align_y)
.into(), .align_x(dot_align_x)
} .padding(2.0)
]
.into()
}; };
self.core.applet.autosize_window(content).into() self.core.applet.autosize_window(content).into()
@ -790,7 +797,7 @@ impl cosmic::Application for CosmicBatteryApplet {
if gpu.toggled if gpu.toggled
&& !self.core.applet.suggested_bounds.as_ref().is_some_and(|c| { && !self.core.applet.suggested_bounds.as_ref().is_some_and(|c| {
let suggested_size = self.core.applet.suggested_size(true); let suggested_size = self.core.applet.suggested_size(true);
let padding = self.core.applet.suggested_padding(true); let padding = self.core.applet.suggested_padding(true).1;
let w = suggested_size.0 + 2 * padding; let w = suggested_size.0 + 2 * padding;
let h = suggested_size.1 + 2 * padding; let h = suggested_size.1 + 2 * padding;
// 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

View file

@ -12,5 +12,6 @@ Icon=com.system76.CosmicAppletBluetooth-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -204,13 +204,6 @@ impl cosmic::Application for CosmicBluetoothApplet {
) => { ) => {
// my headphones seem to always request this // my headphones seem to always request this
// doesn't seem to be defined in the UX mockups // doesn't seem to be defined in the UX mockups
// dbg!(
// "request service authorization",
// d.name,
// bluer::id::Service::try_from(service)
// .map(|s| s.to_string())
// .unwrap_or_else(|_| "unknown".to_string())
// );
} }
}, },
}, },

View file

@ -21,5 +21,6 @@ Icon=com.system76.CosmicAppletInputSources-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -11,7 +11,7 @@ use cosmic::{
cosmic_config::{self, ConfigSet, CosmicConfigEntry}, cosmic_config::{self, ConfigSet, CosmicConfigEntry},
cosmic_theme::Spacing, cosmic_theme::Spacing,
iced::{ iced::{
Task, Rectangle, Task,
platform_specific::shell::commands::popup::{destroy_popup, get_popup}, platform_specific::shell::commands::popup::{destroy_popup, get_popup},
widget::{column, row}, widget::{column, row},
window::Id, window::Id,
@ -20,11 +20,17 @@ use cosmic::{
iced_runtime::{Appearance, core::window}, iced_runtime::{Appearance, core::window},
prelude::*, prelude::*,
surface, theme, surface, theme,
widget::{self, horizontal_space, vertical_space}, widget::{
self, autosize, horizontal_space,
rectangle_tracker::{RectangleTracker, RectangleUpdate, rectangle_tracker_subscription},
vertical_space,
},
}; };
use cosmic_comp_config::CosmicCompConfig; use cosmic_comp_config::CosmicCompConfig;
use std::sync::LazyLock;
use xkb_data::KeyboardLayout; use xkb_data::KeyboardLayout;
static AUTOSIZE_MAIN_ID: LazyLock<widget::Id> = LazyLock::new(|| widget::Id::new("autosize-main"));
pub const ID: &str = "com.system76.CosmicAppletInputSources"; pub const ID: &str = "com.system76.CosmicAppletInputSources";
pub fn run() -> cosmic::iced::Result { pub fn run() -> cosmic::iced::Result {
@ -77,6 +83,8 @@ pub struct Window {
comp_config_handler: Option<cosmic_config::Config>, comp_config_handler: Option<cosmic_config::Config>,
layouts: Vec<KeyboardLayout>, layouts: Vec<KeyboardLayout>,
active_layouts: Vec<ActiveLayout>, active_layouts: Vec<ActiveLayout>,
rectangle_tracker: Option<RectangleTracker<u32>>,
rectangle: Rectangle,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -87,6 +95,7 @@ pub enum Message {
SetActiveLayout(usize), SetActiveLayout(usize),
KeyboardSettings, KeyboardSettings,
Surface(surface::Action), Surface(surface::Action),
Rectangle(RectangleUpdate<u32>),
} }
#[derive(Debug)] #[derive(Debug)]
@ -119,6 +128,8 @@ impl cosmic::Application for Window {
popup: None, popup: None,
comp_config: flags.comp_config, comp_config: flags.comp_config,
active_layouts: Vec::new(), active_layouts: Vec::new(),
rectangle_tracker: None,
rectangle: Rectangle::default(),
}; };
(window, Task::none()) (window, Task::none())
} }
@ -194,6 +205,14 @@ impl cosmic::Application for Window {
cosmic::app::Action::Surface(a), cosmic::app::Action::Surface(a),
)); ));
} }
Message::Rectangle(u) => match u {
RectangleUpdate::Rectangle(r) => {
self.rectangle = r.1;
}
RectangleUpdate::Init(tracker) => {
self.rectangle_tracker = Some(tracker);
}
},
} }
Task::none() Task::none()
@ -205,31 +224,18 @@ impl cosmic::Application for Window {
.first() .first()
.map_or("", |l| l.layout.as_str()), .map_or("", |l| l.layout.as_str()),
); );
let button = self
cosmic::widget::button::custom( .core
row!( .applet
column!( .text_button(input_source_text, Message::TogglePopup);
input_source_text, autosize::autosize(
horizontal_space().width(Length::Fixed( if let Some(tracker) = self.rectangle_tracker.as_ref() {
(self.core.applet.suggested_size(true).0 Element::from(tracker.container(0, button).ignore_bounds(true))
+ 2 * self.core.applet.suggested_padding(true)) } else {
as f32 button.into()
)) },
) AUTOSIZE_MAIN_ID.clone(),
.width(Length::Shrink)
.height(Length::Shrink)
.align_x(Alignment::Center),
vertical_space().height(Length::Fixed(
(self.core.applet.suggested_size(true).1
+ 2 * self.core.applet.suggested_padding(true)) as f32
))
)
.align_y(Alignment::Center)
.width(Length::Shrink)
.height(Length::Shrink),
) )
.on_press_down(Message::TogglePopup)
.class(cosmic::theme::Button::AppletIcon)
.into() .into()
} }
@ -263,18 +269,21 @@ impl cosmic::Application for Window {
} }
fn subscription(&self) -> Subscription<Self::Message> { fn subscription(&self) -> Subscription<Self::Message> {
self.core Subscription::batch(vec![
.watch_config("com.system76.CosmicComp") rectangle_tracker_subscription(0).map(|e| Message::Rectangle(e.1)),
.map(|update| { self.core
if !update.errors.is_empty() { .watch_config("com.system76.CosmicComp")
tracing::error!( .map(|update| {
"errors loading config {:?}: {:?}", if !update.errors.is_empty() {
update.keys, tracing::error!(
update.errors "errors loading config {:?}: {:?}",
); update.keys,
} update.errors
Message::CompConfig(Box::new(update.config)) );
}) }
Message::CompConfig(Box::new(update.config))
}),
])
} }
fn style(&self) -> Option<Appearance> { fn style(&self) -> Option<Appearance> {

View file

@ -74,7 +74,7 @@ impl Minimize {
return index; return index;
}; };
let button_total_size = self.core.applet.suggested_size(true).0 let button_total_size = self.core.applet.suggested_size(true).0
+ self.core.applet.suggested_padding(true) * 2 + self.core.applet.suggested_padding(true).0 * 2
+ 4; + 4;
let btn_count = max_major_axis_len / button_total_size as u32; let btn_count = max_major_axis_len / button_total_size as u32;
if btn_count >= self.apps.len() as u32 { if btn_count >= self.apps.len() as u32 {
@ -143,8 +143,11 @@ impl cosmic::Application for Minimize {
}; };
app.update_desktop_entries(); app.update_desktop_entries();
let t = iced::window::minimize::<cosmic::Action<Message>>(
(app, Task::none()) app.core.main_window_id().unwrap(),
true,
);
(app, t)
} }
fn core(&self) -> &cosmic::app::Core { fn core(&self) -> &cosmic::app::Core {
@ -205,11 +208,22 @@ impl cosmic::Application for Minimize {
} }
self.apps = apps; self.apps = apps;
return iced::window::maximize(self.core.main_window_id().unwrap(), true);
} }
ToplevelUpdate::Remove(handle) => { ToplevelUpdate::Remove(handle) => {
let prev_was_empty = self.apps.is_empty();
self.apps self.apps
.retain(|a| a.toplevel_info.foreign_toplevel != handle); .retain(|a| a.toplevel_info.foreign_toplevel != handle);
self.apps.shrink_to_fit(); self.apps.shrink_to_fit();
let changed = prev_was_empty != self.apps.is_empty();
if self.apps.is_empty() && changed {
// hide the window
return iced::window::minimize(
self.core.main_window_id().unwrap(),
true,
);
}
} }
}, },
WaylandUpdate::Image(handle, img) => { WaylandUpdate::Image(handle, img) => {
@ -241,7 +255,7 @@ impl cosmic::Application for Minimize {
self.overflow_popup = Some(new_id); self.overflow_popup = Some(new_id);
let icon_size = self.core.applet.suggested_size(true).0 as u32 let icon_size = self.core.applet.suggested_size(true).0 as u32
+ 2 * self.core.applet.suggested_padding(true) as u32; + 2 * self.core.applet.suggested_padding(true).1 as u32;
let spacing = self.core.system_theme().cosmic().space_xxs() as u32; let spacing = self.core.system_theme().cosmic().space_xxs() as u32;
let major_axis_len = (icon_size + spacing) * (pos.saturating_sub(1) as u32); let major_axis_len = (icon_size + spacing) * (pos.saturating_sub(1) as u32);
let rectangle = match self.core.applet.anchor { let rectangle = match self.core.applet.anchor {
@ -293,9 +307,16 @@ impl cosmic::Application for Minimize {
} }
}); });
let (width, _) = self.core.applet.suggested_size(false); let (width, _) = self.core.applet.suggested_size(false);
let padding = self.core.applet.suggested_padding(false); let (major_padding, cross_padding) = self.core.applet.suggested_padding(false);
let padding = if matches!(
self.core.applet.anchor,
PanelAnchor::Top | PanelAnchor::Bottom
) {
(major_padding, cross_padding)
} else {
(cross_padding, major_padding)
};
let theme = self.core.system_theme().cosmic(); let theme = self.core.system_theme().cosmic();
let space_xxs = theme.space_xxs();
let icon_buttons = self.apps[..max_icon_count].iter().map(|app| { let icon_buttons = self.apps[..max_icon_count].iter().map(|app| {
self.core self.core
.applet .applet
@ -332,6 +353,7 @@ impl cosmic::Application for Minimize {
None None
}; };
let spacing = self.core.applet.spacing;
// TODO optional dividers on ends if detects app list neighbor // TODO optional dividers on ends if detects app list neighbor
// not sure the best way to tell if there is an adjacent app-list // not sure the best way to tell if there is an adjacent app-list
let icon_buttons = icon_buttons.chain(overflow_btn); let icon_buttons = icon_buttons.chain(overflow_btn);
@ -343,14 +365,14 @@ impl cosmic::Application for Minimize {
.align_y(cosmic::iced_core::Alignment::Center) .align_y(cosmic::iced_core::Alignment::Center)
.height(Length::Shrink) .height(Length::Shrink)
.width(Length::Shrink) .width(Length::Shrink)
.spacing(space_xxs) .spacing(spacing as f32)
.into() .into()
} else { } else {
Column::with_children(icon_buttons) Column::with_children(icon_buttons)
.align_x(cosmic::iced_core::Alignment::Center) .align_x(cosmic::iced_core::Alignment::Center)
.height(Length::Shrink) .height(Length::Shrink)
.width(Length::Shrink) .width(Length::Shrink)
.spacing(space_xxs) .spacing(spacing as f32)
.into() .into()
}; };
@ -388,7 +410,15 @@ impl cosmic::Application for Minimize {
} }
}); });
let (width, _) = self.core.applet.suggested_size(false); let (width, _) = self.core.applet.suggested_size(false);
let padding = self.core.applet.suggested_padding(false); let (major_padding, cross_padding) = self.core.applet.suggested_padding(false);
let padding = if matches!(
self.core.applet.anchor,
PanelAnchor::Top | PanelAnchor::Bottom
) {
(major_padding, cross_padding)
} else {
(cross_padding, major_padding)
};
let theme = self.core.system_theme().cosmic(); let theme = self.core.system_theme().cosmic();
let space_xxs = theme.space_xxs(); let space_xxs = theme.space_xxs();
let icon_buttons = self.apps[max_icon_count..].iter().map(|app| { let icon_buttons = self.apps[max_icon_count..].iter().map(|app| {
@ -429,15 +459,13 @@ impl cosmic::Application for Minimize {
Row::with_children(icon_buttons) Row::with_children(icon_buttons)
.align_y(cosmic::iced_core::Alignment::Center) .align_y(cosmic::iced_core::Alignment::Center)
.height(Length::Shrink) .height(Length::Shrink)
.width(Length::Shrink) .width(Length::Shrink),
.spacing(space_xxs),
) )
} else { } else {
Column::with_children(icon_buttons) Column::with_children(icon_buttons)
.align_x(cosmic::iced_core::Alignment::Center) .align_x(cosmic::iced_core::Alignment::Center)
.height(Length::Shrink) .height(Length::Shrink)
.width(Length::Shrink) .width(Length::Shrink)
.spacing(space_xxs)
.into() .into()
}, },
) )

View file

@ -20,7 +20,7 @@ use cctk::{
}, },
toplevel_info::{ToplevelInfoHandler, ToplevelInfoState}, toplevel_info::{ToplevelInfoHandler, ToplevelInfoState},
toplevel_management::{ToplevelManagerHandler, ToplevelManagerState}, toplevel_management::{ToplevelManagerHandler, ToplevelManagerState},
wayland_client::{self, WEnum, protocol::wl_seat::WlSeat}, wayland_client::{self, WEnum, delegate_noop, protocol::wl_seat::WlSeat},
}; };
use cosmic::{ use cosmic::{
cctk::{ cctk::{
@ -557,21 +557,10 @@ impl Dispatch<wl_shm_pool::WlShmPool, ()> for AppData {
} }
} }
impl Dispatch<wl_buffer::WlBuffer, ()> for AppData {
fn event(
_app_data: &mut Self,
_buffer: &wl_buffer::WlBuffer,
_event: wl_buffer::Event,
(): &(),
_: &Connection,
_qh: &QueueHandle<Self>,
) {
}
}
sctk::delegate_shm!(AppData); sctk::delegate_shm!(AppData);
sctk::delegate_seat!(AppData); sctk::delegate_seat!(AppData);
sctk::delegate_registry!(AppData); sctk::delegate_registry!(AppData);
cctk::delegate_toplevel_info!(AppData); cctk::delegate_toplevel_info!(AppData);
cctk::delegate_toplevel_manager!(AppData); cctk::delegate_toplevel_manager!(AppData);
cctk::delegate_screencopy!(AppData); cctk::delegate_screencopy!(AppData);
delegate_noop!(AppData: ignore wl_buffer::WlBuffer);

View file

@ -26,7 +26,7 @@ where
icon: &fde::IconSource, icon: &fde::IconSource,
size: f32, size: f32,
on_press: Msg, on_press: Msg,
padding: u16, padding: (u16, u16),
) -> Self { ) -> Self {
let border = 1.0; let border = 1.0;
Self { Self {
@ -63,8 +63,9 @@ where
.height(Length::Shrink) .height(Length::Shrink)
.width(Length::Shrink), .width(Length::Shrink),
) )
.center(Length::Fixed(size + padding as f32 * 2.0)) .center_x(Length::Fixed(size + padding.0 as f32 * 2.0))
.padding(padding), .center_y(Length::Fixed(size + padding.1 as f32 * 2.0))
.padding([padding.0 as f32, padding.1 as f32]),
) )
.on_press(on_press) .on_press(on_press)
.width(Length::Shrink) .width(Length::Shrink)

View file

@ -21,5 +21,6 @@ Icon=com.system76.CosmicAppletNetwork-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -20,6 +20,7 @@ Keywords=COSMIC;Iced;
Icon=com.system76.CosmicAppletNotifications-symbolic Icon=com.system76.CosmicAppletNotifications-symbolic
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-NotificationsApplet=true X-NotificationsApplet=true
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -20,5 +20,6 @@ Icon=com.system76.CosmicAppletPower-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto
X-OverflowPriority=10 X-OverflowPriority=10

View file

@ -56,7 +56,7 @@ impl App {
fn resize_window(&self) -> app::Task<Msg> { fn resize_window(&self) -> app::Task<Msg> {
let icon_size = self.core.applet.suggested_size(true).0 as u32 let icon_size = self.core.applet.suggested_size(true).0 as u32
+ self.core.applet.suggested_padding(true) as u32 * 2; + self.core.applet.suggested_padding(true).1 as u32 * 2;
let n = self.menus.len() as u32; let n = self.menus.len() as u32;
window::resize( window::resize(
self.core.main_window_id().unwrap(), self.core.main_window_id().unwrap(),
@ -73,8 +73,8 @@ impl App {
} }
})?; })?;
let button_total_size = let button_total_size = self.core.applet.suggested_size(true).0
self.core.applet.suggested_size(true).0 + self.core.applet.suggested_padding(true) * 2; + self.core.applet.suggested_padding(true).1 * 2;
let menu_count = self.menus.len(); let menu_count = self.menus.len();
@ -250,11 +250,11 @@ impl cosmic::Application for App {
PanelAnchor::Left | PanelAnchor::Right PanelAnchor::Left | PanelAnchor::Right
) { ) {
let suggested_size = self.core.applet.suggested_size(false).1 let suggested_size = self.core.applet.suggested_size(false).1
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32; popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32;
} else { } else {
let suggested_size = self.core.applet.suggested_size(false).0 let suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32; popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32;
} }
cmds.push(get_popup(popup_settings)); cmds.push(get_popup(popup_settings));
@ -332,11 +332,11 @@ impl cosmic::Application for App {
PanelAnchor::Left | PanelAnchor::Right PanelAnchor::Left | PanelAnchor::Right
) { ) {
let suggested_size = self.core.applet.suggested_size(false).1 let suggested_size = self.core.applet.suggested_size(false).1
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32; popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32;
} else { } else {
let suggested_size = self.core.applet.suggested_size(false).0 let suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32; popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32;
} }
cmds.push(get_popup(popup_settings)); cmds.push(get_popup(popup_settings));
@ -369,12 +369,12 @@ impl cosmic::Application for App {
PanelAnchor::Left | PanelAnchor::Right PanelAnchor::Left | PanelAnchor::Right
) { ) {
let suggested_size = self.core.applet.suggested_size(false).1 let suggested_size = self.core.applet.suggested_size(false).1
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y = popup_settings.positioner.anchor_rect.y =
overflow_index as i32 * suggested_size as i32; overflow_index as i32 * suggested_size as i32;
} else { } else {
let suggested_size = self.core.applet.suggested_size(false).0 let suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x = popup_settings.positioner.anchor_rect.x =
overflow_index as i32 * suggested_size as i32; overflow_index as i32 * suggested_size as i32;
} }
@ -418,11 +418,11 @@ impl cosmic::Application for App {
PanelAnchor::Left | PanelAnchor::Right PanelAnchor::Left | PanelAnchor::Right
) { ) {
let suggested_size = self.core.applet.suggested_size(false).1 let suggested_size = self.core.applet.suggested_size(false).1
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32; popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32;
} else { } else {
let suggested_size = self.core.applet.suggested_size(false).0 let suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false); + 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32; popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32;
} }
cmds.push(get_popup(popup_settings)); cmds.push(get_popup(popup_settings));

View file

@ -21,5 +21,6 @@ Icon=com.system76.CosmicAppletTiling-symbolic
StartupNotify=true StartupNotify=true
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-HostWaylandDisplay=true X-HostWaylandDisplay=true
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto

View file

@ -19,6 +19,7 @@ Keywords=COSMIC;Iced;
Icon=com.system76.CosmicAppletTime-symbolic Icon=com.system76.CosmicAppletTime-symbolic
NoDisplay=true NoDisplay=true
X-CosmicApplet=true X-CosmicApplet=true
X-CosmicShrinkable=true
X-HostWaylandDisplay=true X-HostWaylandDisplay=true
X-CosmicHoverPopup=Auto X-CosmicHoverPopup=Auto
# No shrink priority, as this applet is always visible when configured # No shrink priority, as this applet is always visible when configured

View file

@ -226,7 +226,8 @@ impl Window {
date_time_col, date_time_col,
horizontal_space().width(Length::Fixed( horizontal_space().width(Length::Fixed(
(self.core.applet.suggested_size(true).0 (self.core.applet.suggested_size(true).0
+ 2 * self.core.applet.suggested_padding(true)) as f32 + 2 * self.core.applet.suggested_padding(true).1)
as f32
)) ))
) )
.align_x(Alignment::Center), .align_x(Alignment::Center),
@ -282,7 +283,8 @@ impl Window {
self.core.applet.text(formatted_date), self.core.applet.text(formatted_date),
container(vertical_space().height(Length::Fixed( container(vertical_space().height(Length::Fixed(
(self.core.applet.suggested_size(true).1 (self.core.applet.suggested_size(true).1
+ 2 * self.core.applet.suggested_padding(true)) as f32 + 2 * self.core.applet.suggested_padding(true).1)
as f32
))) )))
) )
.align_y(Alignment::Center), .align_y(Alignment::Center),
@ -662,9 +664,9 @@ impl cosmic::Application for Window {
self.vertical_layout() self.vertical_layout()
}) })
.padding(if horizontal { .padding(if horizontal {
[0, self.core.applet.suggested_padding(true)] [0, self.core.applet.suggested_padding(true).0]
} else { } else {
[self.core.applet.suggested_padding(true), 0] [self.core.applet.suggested_padding(true).0, 0]
}) })
.on_press_down(Message::TogglePopup) .on_press_down(Message::TogglePopup)
.class(cosmic::theme::Button::AppletIcon); .class(cosmic::theme::Button::AppletIcon);

View file

@ -74,7 +74,7 @@ impl IcedWorkspacesApplet {
return index; return index;
}; };
let button_total_size = self.core.applet.suggested_size(true).0 let button_total_size = self.core.applet.suggested_size(true).0
+ self.core.applet.suggested_padding(true) * 2 + self.core.applet.suggested_padding(true).1 * 2
+ 4; + 4;
let btn_count = max_major_axis_len / button_total_size as u32; let btn_count = max_major_axis_len / button_total_size as u32;
if btn_count >= self.workspaces.len() as u32 { if btn_count >= self.workspaces.len() as u32 {
@ -219,8 +219,8 @@ impl cosmic::Application for IcedWorkspacesApplet {
self.core.applet.anchor, self.core.applet.anchor,
PanelAnchor::Top | PanelAnchor::Bottom PanelAnchor::Top | PanelAnchor::Bottom
); );
let suggested_total = let suggested_total = self.core.applet.suggested_size(true).0
self.core.applet.suggested_size(true).0 + self.core.applet.suggested_padding(true) * 2; + self.core.applet.suggested_padding(true).1 * 2;
let suggested_window_size = self.core.applet.suggested_window_size(); let suggested_window_size = self.core.applet.suggested_window_size();
let popup_index = self.popup_index().unwrap_or(self.workspaces.len()); let popup_index = self.popup_index().unwrap_or(self.workspaces.len());
@ -245,9 +245,9 @@ impl cosmic::Application for IcedWorkspacesApplet {
.align_y(Alignment::Center), .align_y(Alignment::Center),
) )
.padding(if horizontal { .padding(if horizontal {
[0, self.core.applet.suggested_padding(true)] [0, self.core.applet.suggested_padding(true).1]
} else { } else {
[self.core.applet.suggested_padding(true), 0] [self.core.applet.suggested_padding(true).1, 0]
}) })
.on_press( .on_press(
if w.state.contains(ext_workspace_handle_v1::State::Active) { if w.state.contains(ext_workspace_handle_v1::State::Active) {

View file

@ -41,6 +41,47 @@ enum Msg {
Surface(surface::Action), Surface(surface::Action),
} }
impl Button {
pub fn icon_button_from_handle<'a, Message: Clone + 'static>(
&self,
icon: cosmic::widget::icon::Handle,
) -> cosmic::widget::Button<'a, Message> {
let theme = cosmic::theme::active();
let theme = theme.cosmic();
let suggested = self.core.applet.suggested_size(icon.symbolic);
let (major_padding, applet_padding_minor_axis) =
self.core.applet.suggested_padding(icon.symbolic);
let (horizontal_padding, vertical_padding) = if self.core.applet.is_horizontal() {
(major_padding, applet_padding_minor_axis)
} else {
(applet_padding_minor_axis, major_padding)
};
let symbolic = icon.symbolic;
cosmic::widget::button::custom(
cosmic::widget::layer_container(
cosmic::widget::icon(icon)
.class(if symbolic {
cosmic::theme::Svg::Custom(std::rc::Rc::new(|theme| {
cosmic::iced_widget::svg::Style {
color: Some(theme.cosmic().background.on.into()),
}
}))
} else {
cosmic::theme::Svg::default()
})
.width(Length::Fixed(suggested.0 as f32))
.height(Length::Fixed(suggested.1 as f32)),
)
.center(Length::Fill),
)
.width(Length::Fixed((suggested.0 + 2 * horizontal_padding) as f32))
.height(Length::Fixed((suggested.1 + 2 * vertical_padding) as f32))
.class(cosmic::theme::Button::AppletIcon)
}
}
impl cosmic::Application for Button { impl cosmic::Application for Button {
type Message = Msg; type Message = Msg;
type Executor = cosmic::SingleThreadExecutor; type Executor = cosmic::SingleThreadExecutor;
@ -124,13 +165,11 @@ impl cosmic::Application for Button {
{ {
cosmic::Element::from( cosmic::Element::from(
self.core.applet.applet_tooltip::<Msg>( self.core.applet.applet_tooltip::<Msg>(
self.core self.icon_button_from_handle(
.applet cosmic::widget::icon::from_name(self.desktop.icon.clone().unwrap())
.icon_button_from_handle( .handle(),
cosmic::widget::icon::from_name(self.desktop.icon.clone().unwrap()) )
.handle(), .on_press_down(Msg::Press),
)
.on_press_down(Msg::Press),
self.desktop.name.clone(), self.desktop.name.clone(),
false, false,
Msg::Surface, Msg::Surface,
@ -142,13 +181,13 @@ impl cosmic::Application for Button {
self.core.applet.text(&self.desktop.name), self.core.applet.text(&self.desktop.name),
vertical_space().height(Length::Fixed( vertical_space().height(Length::Fixed(
(self.core.applet.suggested_size(true).1 (self.core.applet.suggested_size(true).1
+ 2 * self.core.applet.suggested_padding(true)) + 2 * self.core.applet.suggested_padding(true).1)
as f32 as f32
)) ))
) )
.align_y(iced::Alignment::Center); .align_y(iced::Alignment::Center);
cosmic::widget::button::custom(content) cosmic::widget::button::custom(content)
.padding([0, self.core.applet.suggested_padding(true)]) .padding([0, self.core.applet.suggested_padding(true).0])
.class(cosmic::theme::Button::AppletIcon) .class(cosmic::theme::Button::AppletIcon)
.on_press_down(Msg::Press) .on_press_down(Msg::Press)
.into() .into()

View file

@ -1,2 +1,2 @@
[toolchain] [toolchain]
channel = "1.85.1" channel = "1.90.0"