Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 53 additions & 57 deletions cosmic-app-list/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::State;
use futures::future::pending;
use iced::{Alignment, Background, Length};
use itertools::Itertools;

Check warning on line 56 in cosmic-app-list/src/app.rs

View workflow job for this annotation

GitHub Actions / linting

unused import: `itertools::Itertools`

warning: unused import: `itertools::Itertools` --> cosmic-app-list/src/app.rs:56:5 | 56 | use itertools::Itertools; | ^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
use std::{borrow::Cow, collections::HashMap, path::PathBuf, rc::Rc, str::FromStr, time::Duration};
use switcheroo_control::Gpu;
use tokio::time::sleep;
Expand Down Expand Up @@ -150,17 +150,17 @@
}

impl DockItem {
fn as_icon(
&self,
applet: &Context,
rectangle_tracker: Option<&RectangleTracker<DockItemId>>,
interaction_enabled: bool,
dnd_source_enabled: bool,
gpus: Option<&[Gpu]>,
is_focused: bool,
dot_border_radius: [f32; 4],
window_id: window::Id,
) -> Element<'_, Message> {

Check warning on line 163 in cosmic-app-list/src/app.rs

View workflow job for this annotation

GitHub Actions / linting

this function has too many arguments (9/7)

warning: this function has too many arguments (9/7) --> cosmic-app-list/src/app.rs:153:5 | 153 | / fn as_icon( 154 | | &self, 155 | | applet: &Context, 156 | | rectangle_tracker: Option<&RectangleTracker<DockItemId>>, ... | 162 | | window_id: window::Id, 163 | | ) -> Element<'_, Message> { | |_____________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments = note: `#[warn(clippy::too_many_arguments)]` on by default
let Self {
toplevels,
desktop_info,
Expand All @@ -177,31 +177,24 @@
.width(app_icon.icon_size.into())
.height(app_icon.icon_size.into());

let dots = if toplevels.is_empty() {
(0..1)
.map(|_| {
container(vertical_space().height(Length::Fixed(0.0)))
.padding(app_icon.dot_radius)
.into()
})
.collect_vec()
} else {
(0..1)
.map(|_| {
container(if toplevels.len() == 1 {
vertical_space().height(Length::Fixed(0.0))
} else {
match applet.anchor {
PanelAnchor::Left | PanelAnchor::Right => {
vertical_space().height(app_icon.bar_size)
}
PanelAnchor::Top | PanelAnchor::Bottom => {
horizontal_space().width(app_icon.bar_size)
}
}
})
.padding(app_icon.dot_radius)
.class(theme::style::Container::Custom(Box::new(move |theme| {
let dot_constructor = || {
let space = if toplevels.len() <= 1 {
vertical_space().height(Length::Fixed(0.0))
} else {
match applet.anchor {
PanelAnchor::Left | PanelAnchor::Right => {
vertical_space().height(app_icon.bar_size)
}
PanelAnchor::Top | PanelAnchor::Bottom => {
horizontal_space().width(app_icon.bar_size)
}
}
};
let mut container = container(space).padding(app_icon.dot_radius);

if !toplevels.is_empty() {
container =
container.class(theme::style::Container::Custom(Box::new(move |theme| {
Comment on lines -180 to +197
Copy link
Contributor Author

@Cheong-Lau Cheong-Lau Oct 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored this section completely, so I'd like a more thorough check of this part in particular.

I moved the logic of making the Elements into its own closure (better variable names are very welcome!), which should make the same Elements as before, just separate to the collection part and hopefully clearer. Then just make an iterator with std::iter::repeat_with, which avoids the whole mess of mapping and collecting an iterator.

container::Style {
text_color: Some(Color::TRANSPARENT),
background: if is_focused {
Expand All @@ -218,34 +211,35 @@
icon_color: Some(Color::TRANSPARENT),
}
})))
.into()
})
.collect_vec()
}
container.into()
};

let dots = std::iter::repeat_with(dot_constructor).take(2);

let icon_wrapper: Element<_> = match applet.anchor {
PanelAnchor::Left => row(vec![
PanelAnchor::Left => row([
column(dots).into(),
horizontal_space().width(Length::Fixed(1.0)).into(),
cosmic_icon.clone().into(),
])
.align_y(Alignment::Center)
.into(),
PanelAnchor::Right => row(vec![
PanelAnchor::Right => row([
cosmic_icon.clone().into(),
horizontal_space().width(Length::Fixed(1.0)).into(),
column(dots).into(),
])
.align_y(Alignment::Center)
.into(),
PanelAnchor::Top => column(vec![
PanelAnchor::Top => column([
row(dots).into(),
vertical_space().height(Length::Fixed(1.0)).into(),
cosmic_icon.clone().into(),
])
.align_x(Alignment::Center)
.into(),
PanelAnchor::Bottom => column(vec![
PanelAnchor::Bottom => column([
cosmic_icon.clone().into(),
vertical_space().height(Length::Fixed(1.0)).into(),
row(dots).into(),
Expand Down Expand Up @@ -382,7 +376,7 @@
DndMotion(f64, f64),
DndDropFinished,
DndData(Option<DndPathBuf>),
StartListeningForDnd,

Check warning on line 379 in cosmic-app-list/src/app.rs

View workflow job for this annotation

GitHub Actions / linting

variants `StartListeningForDnd` and `StopListeningForDnd` are never constructed

warning: variants `StartListeningForDnd` and `StopListeningForDnd` are never constructed --> cosmic-app-list/src/app.rs:379:5 | 355 | enum Message { | ------- variants in this enum ... 379 | StartListeningForDnd, | ^^^^^^^^^^^^^^^^^^^^ 380 | StopListeningForDnd, | ^^^^^^^^^^^^^^^^^^^ | = note: `Message` has derived impls for the traits `Clone` and `Debug`, but these are intentionally ignored during dead code analysis = note: `#[warn(dead_code)]` on by default
StopListeningForDnd,
IncrementSubscriptionCtr,
ConfigUpdated(AppListConfig),
Expand Down Expand Up @@ -470,7 +464,7 @@
img.img.clone(),
)))
} else {
Image::new(Handle::from_rgba(1, 1, vec![0, 0, 0, 255])).into()
Image::new(Handle::from_rgba(1, 1, [0u8, 0u8, 0u8, 255u8].as_slice())).into()
})
.class(Container::Custom(Box::new(move |theme| {
container::Style {
Expand Down Expand Up @@ -590,7 +584,7 @@
app_ids.iter().map(|fav| {
let unicase_fav = fde::unicase::Ascii::new(fav.as_str());
fde::find_app_by_id(desktop_entries, unicase_fav).map_or_else(
|| fde::DesktopEntry::from_appid(fav.clone()).clone(),
|| fde::DesktopEntry::from_appid(fav.clone()),
ToOwned::to_owned,
)
})
Expand All @@ -612,7 +606,7 @@
.map(|(pinned_ctr, (e, original_id))| DockItem {
id: pinned_ctr as u32,
toplevels: Vec::new(),
desktop_info: e.clone(),
desktop_info: e,
original_app_id: original_id.clone(),
})
.collect();
Expand Down Expand Up @@ -673,7 +667,7 @@
} else {
self.overflow_active_popup = None;
self.overflow_favorites_popup = None;
return Task::batch(vec![destroy_popup(popup_id), destroy_popup(parent)]);
return Task::batch([destroy_popup(popup_id), destroy_popup(parent)]);
}
}
if let Some(toplevel_group) = self
Expand Down Expand Up @@ -733,7 +727,7 @@
} else {
self.overflow_active_popup = None;
self.overflow_favorites_popup = None;
return Task::batch(vec![destroy_popup(popup_id), destroy_popup(parent)]);
return Task::batch([destroy_popup(popup_id), destroy_popup(parent)]);
}
}
if let Some(toplevel_group) = self
Expand Down Expand Up @@ -900,7 +894,7 @@
}
}
Message::DragFinished => {
if let Some((_, mut toplevel_group, _, pinned_pos)) = self.dnd_source.take() {

Check warning on line 897 in cosmic-app-list/src/app.rs

View workflow job for this annotation

GitHub Actions / linting

unused variable: `pinned_pos`

warning: unused variable: `pinned_pos` --> cosmic-app-list/src/app.rs:897:56 | 897 | if let Some((_, mut toplevel_group, _, pinned_pos)) = self.dnd_source.take() { | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_pinned_pos` | = note: `#[warn(unused_variables)]` on by default
if self.dnd_offer.take().is_some() {
if let Some((_, toplevel_group, _, pinned_pos)) = self.dnd_source.as_ref() {
let mut pos = 0;
Expand Down Expand Up @@ -972,7 +966,7 @@
}
}
Message::DndLeave => {
let mut cnt = 0;

Check warning on line 969 in cosmic-app-list/src/app.rs

View workflow job for this annotation

GitHub Actions / linting

variable does not need to be mutable

warning: variable does not need to be mutable --> cosmic-app-list/src/app.rs:969:21 | 969 | let mut cnt = 0; | ----^^^ | | | help: remove this `mut` | = note: `#[warn(unused_mut)]` on by default

Check warning on line 969 in cosmic-app-list/src/app.rs

View workflow job for this annotation

GitHub Actions / linting

unused variable: `cnt`

warning: unused variable: `cnt` --> cosmic-app-list/src/app.rs:969:25 | 969 | let mut cnt = 0; | ^^^ help: if this is intentional, prefix it with an underscore: `_cnt`
if let Some((_, toplevel_group, _, pinned_pos)) = self.dnd_source.as_ref() {
let mut pos = 0;
self.pinned_list.retain_mut(|pinned| {
Expand Down Expand Up @@ -1490,7 +1484,10 @@
} else {
0
};
let favorites: Vec<_> = (&mut self.pinned_list.iter().rev())
let favorites: Vec<_> = self
.pinned_list
.iter()
.rev()
.filter(|f| {
if favorite_to_remove > 0 && f.toplevels.is_empty() {
favorite_to_remove -= 1;
Expand Down Expand Up @@ -1812,11 +1809,7 @@
Message::Exec(exec.to_string(), None, desktop_info.terminal()),
));
} else if let Some(gpus) = self.gpus.as_ref() {
let default_idx = if desktop_info.prefers_non_default_gpu() {
gpus.iter().position(|gpu| !gpu.default).unwrap_or(0)
} else {
gpus.iter().position(|gpu| gpu.default).unwrap_or(0)
};
let default_idx = preferred_gpu_idx(desktop_info, gpus.iter());
for (i, gpu) in gpus.iter().enumerate() {
content = content.push(
menu_button(text::body(format!(
Expand Down Expand Up @@ -2101,7 +2094,10 @@
0
};
let mut favorites_extra = Vec::with_capacity(favorite_to_remove);
let mut favorites: Vec<_> = (&mut self.pinned_list.iter().rev())
let mut favorites: Vec<_> = self
.pinned_list
.iter()
.rev()
.filter(|f| {
if favorite_to_remove > 0 && f.toplevels.is_empty() {
favorite_to_remove -= 1;
Expand Down Expand Up @@ -2190,7 +2186,7 @@
}

fn subscription(&self) -> Subscription<Message> {
Subscription::batch(vec![
Subscription::batch([
wayland_subscription().map(Message::Wayland),
listen_with(|e, _, id| match e {
cosmic::iced_runtime::core::Event::PlatformSpecific(
Expand Down Expand Up @@ -2299,9 +2295,9 @@
if self.active_workspaces.is_empty() {
return Vec::new();
}
let current_output = self.core.applet.output_name.clone();
let current_output = self.core.applet.output_name.as_ref();
let mut focused_toplevels: Vec<ExtForeignToplevelHandleV1> = Vec::new();
let active_workspaces = self.active_workspaces.clone();
let active_workspaces = &self.active_workspaces;
for toplevel_list in self.active_list.iter().chain(self.pinned_list.iter()) {
for (t_info, _) in &toplevel_list.toplevels {
if t_info.state.contains(&State::Activated)
Expand Down Expand Up @@ -2378,13 +2374,7 @@
fn launch_on_preferred_gpu(desktop_info: &DesktopEntry, gpus: Option<&[Gpu]>) -> Option<Message> {
let exec = desktop_info.exec()?;

let gpu_idx = gpus.map(|gpus| {
if desktop_info.prefers_non_default_gpu() {
gpus.iter().position(|gpu| !gpu.default).unwrap_or(0)
} else {
gpus.iter().position(|gpu| gpu.default).unwrap_or(0)
}
});
let gpu_idx = gpus.map(|gpus| preferred_gpu_idx(desktop_info, gpus.iter()));

Some(Message::Exec(
exec.to_string(),
Expand All @@ -2393,6 +2383,14 @@
))
}

fn preferred_gpu_idx<'a, I>(desktop_info: &DesktopEntry, mut gpus: I) -> usize
where
I: Iterator<Item = &'a Gpu>,
{
gpus.position(|gpu| gpu.default ^ desktop_info.prefers_non_default_gpu())
.unwrap_or(0)
}

#[derive(Debug, Default, Clone)]
pub struct DndPathBuf(PathBuf);

Expand Down Expand Up @@ -2428,8 +2426,6 @@
}

fn as_bytes(&self, _mime_type: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
Some(Cow::Owned(
self.0.clone().to_str()?.to_string().into_bytes(),
))
Some(Cow::Owned(self.0.to_str()?.as_bytes().to_vec()))
}
}
18 changes: 6 additions & 12 deletions cosmic-app-list/src/wayland_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,7 @@ impl OutputHandler for AppData {
if let Some(info) = self.output_state.info(&output) {
let _ = self
.tx
.unbounded_send(WaylandUpdate::Output(OutputUpdate::Add(
output.clone(),
info.clone(),
)));
.unbounded_send(WaylandUpdate::Output(OutputUpdate::Add(output, info)));
}
}

Expand All @@ -103,10 +100,7 @@ impl OutputHandler for AppData {
if let Some(info) = self.output_state.info(&output) {
let _ = self
.tx
.unbounded_send(WaylandUpdate::Output(OutputUpdate::Update(
output.clone(),
info.clone(),
)));
.unbounded_send(WaylandUpdate::Output(OutputUpdate::Update(output, info)));
}
}

Expand All @@ -118,7 +112,7 @@ impl OutputHandler for AppData {
) {
let _ = self
.tx
.unbounded_send(WaylandUpdate::Output(OutputUpdate::Remove(output.clone())));
.unbounded_send(WaylandUpdate::Output(OutputUpdate::Remove(output)));
}
}

Expand All @@ -136,12 +130,12 @@ impl WorkspaceHandler for AppData {
.iter()
.filter_map(|handle| self.workspace_state.workspace_info(handle))
.find(|w| w.state.contains(WorkspaceUpdateState::Active))
.map(|workspace| workspace.handle.clone())
})
.map(|workspace| workspace.handle.clone())
.collect::<Vec<_>>();
let _ = self
.tx
.unbounded_send(WaylandUpdate::Workspace(active_workspaces.clone()));
.unbounded_send(WaylandUpdate::Workspace(active_workspaces));
}
}

Expand Down Expand Up @@ -699,7 +693,6 @@ pub(crate) fn wayland_handler(
exit: false,
tx,
conn,
queue_handle: qh.clone(),
output_state: OutputState::new(&globals, &qh),
workspace_state: WorkspaceState::new(&registry_state, &qh),
toplevel_info_state: ToplevelInfoState::new(&registry_state, &qh),
Expand All @@ -709,6 +702,7 @@ pub(crate) fn wayland_handler(
seat_state: SeatState::new(&globals, &qh),
shm_state: Shm::bind(&globals, &qh).unwrap(),
activation_state: ActivationState::bind::<AppData>(&globals, &qh).ok(),
queue_handle: qh,
};

loop {
Expand Down
10 changes: 6 additions & 4 deletions cosmic-app-list/src/wayland_subscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ pub struct WaylandImage {

impl WaylandImage {
pub fn new(img: image::RgbaImage) -> Self {
let width = img.width();
let height = img.height();

Self {
// TODO avoid copy?
img: Bytes::copy_from_slice(img.as_bytes()),
width: img.width(),
height: img.height(),
img: Bytes::from_owner(img.into_vec()),
width,
height,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion cosmic-applet-a11y/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ impl cosmic::Application for CosmicA11yApplet {
}

fn subscription(&self) -> Subscription<Message> {
Subscription::batch(vec![
Subscription::batch([
accessibility::subscription().map(Message::DBusUpdate),
backend::wayland::a11y_subscription().map(Message::WaylandUpdate),
self.timeline
Expand Down
Loading
Loading