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
162 changes: 73 additions & 89 deletions cosmic-app-list/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,18 +176,18 @@
}

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,
filter: Option<&dyn Fn(&ToplevelInfo) -> bool>,
) -> Element<'_, Message> {

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

View workflow job for this annotation

GitHub Actions / linting

this function has too many arguments (10/7)

warning: this function has too many arguments (10/7) --> cosmic-app-list/src/app.rs:179:5 | 179 | / fn as_icon( 180 | | &self, 181 | | applet: &Context, 182 | | rectangle_tracker: Option<&RectangleTracker<DockItemId>>, ... | 189 | | filter: Option<&dyn Fn(&ToplevelInfo) -> bool>, 190 | | ) -> Element<'_, Message> { | |_____________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.93.0/index.html#too_many_arguments = note: `#[warn(clippy::too_many_arguments)]` on by default
let Self {
toplevels,
desktop_info,
Expand Down Expand Up @@ -310,15 +310,16 @@
icon_button.into()
};

let icon_origin = iced::Vector::new(app_icon.padding.left, app_icon.padding.top);
let path = desktop_info.path.clone();
let icon_button = if dnd_source_enabled && interaction_enabled {
DndSource::with_id(icon_button, cosmic::widget::Id::new("asdfasdfadfs"))
.window(window_id)
.drag_icon(move |_| {
.drag_icon(move |pointer_offset| {
(
cosmic_icon.clone().into(),
iced::core::widget::tree::State::None,
iced::Vector::ZERO,
icon_origin - pointer_offset,
)
})
.drag_threshold(16.)
Expand All @@ -336,6 +337,15 @@
icon_button.into()
}
}

fn as_dragged_item(&self, applet: &Context) -> Element<'_, Message> {
let app_icon = AppletIconData::new(applet);

container(horizontal_space())
.width(app_icon.icon_size as f32 + app_icon.padding.left + app_icon.padding.right)
.height(app_icon.icon_size as f32 + app_icon.padding.top + app_icon.padding.bottom)
.into()
}
}

#[derive(Debug, Clone, Default)]
Expand All @@ -361,6 +371,7 @@
desktop_entries: Vec<DesktopEntry>,
active_list: Vec<DockItem>,
pinned_list: Vec<DockItem>,
dragged_item: Option<DockItem>,
dnd_source: Option<(window::Id, DockItem, DndAction, Option<usize>)>,
config: AppListConfig,
wayland_sender: Option<Sender<WaylandRequest>>,
Expand All @@ -385,33 +396,33 @@
}

#[derive(Debug, Clone)]
enum Message {
Wayland(WaylandUpdate),
PinApp(u32),
UnpinApp(u32),
Popup(u32, window::Id),
Pressed(window::Id),
ToplevelListPopup(u32, window::Id),
ToplevelHoverChanged(ExtForeignToplevelHandleV1, bool),
GpuRequest(Option<Vec<Gpu>>),
CloseRequested(window::Id),
ClosePopup,
Activate(ExtForeignToplevelHandleV1),
Toggle(ExtForeignToplevelHandleV1),
Exec(String, Option<usize>, bool),
CloseToplevel(ExtForeignToplevelHandleV1),
Quit(String),
NewSeat(WlSeat),
RemovedSeat,
Rectangle(RectangleUpdate<DockItemId>),
StartDrag(u32),
DragFinished,
DndEnter(f64, f64),
DndLeave,
DndMotion(f64, f64),
DndDropFinished,
DndData(Option<DndPathBuf>),
StartListeningForDnd,

Check warning on line 425 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:425:5 | 399 | enum Message { | ------- variants in this enum ... 425 | StartListeningForDnd, | ^^^^^^^^^^^^^^^^^^^^ 426 | 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)]` (part of `#[warn(unused)]`) on by default
StopListeningForDnd,
IncrementSubscriptionCtr,
ConfigUpdated(AppListConfig),
Expand All @@ -421,40 +432,21 @@
}

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

View workflow job for this annotation

GitHub Actions / linting

large size difference between variants

warning: large size difference between variants --> cosmic-app-list/src/app.rs:399:1 | 399 | / enum Message { 400 | | Wayland(WaylandUpdate), | | ---------------------- the largest variant contains at least 400 bytes 401 | | PinApp(u32), 402 | | UnpinApp(u32), ... | 406 | | ToplevelHoverChanged(ExtForeignToplevelHandleV1, bool), | | ------------------------------------------------------ the second-largest variant contains at least 65 bytes ... | 431 | | Surface(surface::Action), 432 | | } | |_^ the entire enum is at least 400 bytes | = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.93.0/index.html#large_enum_variant = note: `#[warn(clippy::large_enum_variant)]` on by default help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | 400 - Wayland(WaylandUpdate), 400 + Wayland(Box<WaylandUpdate>), |

fn index_in_list(
mut list_len: usize,
list_len: usize,
item_size: f32,
divider_size: f32,
center_threshold: f32,
existing_preview: Option<usize>,
pos_in_list: f32,
) -> usize {
if existing_preview.is_some() {
list_len += 1;
}

let index = if (list_len == 0) || (pos_in_list < item_size / 2.0) {
0
} else {
let mut i = 1;
let mut pos = item_size / 2.0;
while i < list_len {
let next_pos = pos + item_size + divider_size;
if pos < pos_in_list && pos_in_list < next_pos {
break;
}
pos = next_pos;
i += 1;
}
i
};
let current_index = existing_preview.unwrap_or(0);
let current_center = current_index as f32 * item_size + item_size / 2.0;

if let Some(existing_preview) = existing_preview {
if index >= existing_preview {
index.saturating_sub(1)
} else {
index
}
if pos_in_list > current_center + item_size - center_threshold {
(current_index + 1).min(list_len)
} else if pos_in_list < current_center - item_size + center_threshold {
current_index.saturating_sub(1)
} else {
index
current_index
}
}

Expand Down Expand Up @@ -665,7 +657,7 @@
.output_list
.iter()
.find(|(_, info)| info.name.as_ref() == Some(&self.core.applet.output_name))
.map_or(true, |(active_output, _)| {
.is_none_or(|(active_output, _)| {
toplevel_info
.output
.iter()
Expand Down Expand Up @@ -1131,26 +1123,36 @@
})
{
let icon_id = window::Id::unique();
if let Some(pinned_pos) = pos {
let entry = self.pinned_list.remove(pinned_pos);
if !entry.toplevels.is_empty() {
self.dragged_item = Some(entry);
}
}
self.dnd_source =
Some((icon_id, toplevel_group.clone(), DndAction::empty(), pos));
self.dnd_offer = Some(DndOffer {
dock_item: Some(toplevel_group),
preview_index: pos.unwrap_or(self.pinned_list.len()),
});
}
}
Message::DragFinished => {
if let Some((_, mut toplevel_group, _, _pinned_pos)) = self.dnd_source.take() {
if self.dnd_offer.take().is_some() {
if let Some((_, toplevel_group, _, pinned_pos)) = self.dnd_source.as_ref() {
let mut pos = 0;
self.pinned_list.retain_mut(|pinned| {
let matched_id =
pinned.desktop_info.id() == toplevel_group.desktop_info.id();
let pinned_match =
pinned_pos.is_some_and(|pinned_pos| pinned_pos == pos);
let ret = !matched_id || pinned_match;

pos += 1;
ret
});
}
if self.dnd_offer.take().is_some()
&& let Some((_, toplevel_group, _, pinned_pos)) = self.dnd_source.as_ref()
{
let mut pos = 0;
self.pinned_list.retain_mut(|pinned| {
let matched_id =
pinned.desktop_info.id() == toplevel_group.desktop_info.id();
let pinned_match =
pinned_pos.is_some_and(|pinned_pos| pinned_pos == pos);
let ret = !matched_id || pinned_match;

pos += 1;
ret
});
}

if !self
Expand All @@ -1175,14 +1177,20 @@
};
let num_pinned = self.pinned_list.len();
let index = index_in_list(num_pinned, item_size as f32, 4.0, None, pos_in_list);
self.dnd_offer = Some(DndOffer {
preview_index: index,
..DndOffer::default()
});
if let Some(dnd_source) = self.dnd_source.as_ref() {
self.dnd_offer.as_mut().unwrap().dock_item = Some(dnd_source.1.clone());
let source_id = dnd_source.1.desktop_info.id().to_string();
self.pinned_list
.retain(|p| p.desktop_info.id() != source_id);

self.dnd_offer = Some(DndOffer {
preview_index: index,
dock_item: Some(dnd_source.1.clone()),
});
} else {
// TODO dnd
self.dnd_offer = Some(DndOffer {
preview_index: index,
..DndOffer::default()
});
return peek_dnd::<DndPathBuf>()
.map(Message::DndData)
.map(cosmic::Action::App);
Expand All @@ -1208,17 +1216,9 @@
}
}
Message::DndLeave => {
if let Some((_, toplevel_group, _, pinned_pos)) = self.dnd_source.as_ref() {
let mut pos = 0;
self.pinned_list.retain_mut(|pinned| {
let matched_id =
pinned.desktop_info.id() == toplevel_group.desktop_info.id();
let pinned_match = pinned_pos.is_some_and(|pinned_pos| pinned_pos == pos);
let ret = !matched_id || pinned_match;

pos += 1;
ret
});
if let Some(dragged_item) = self.dragged_item.take() {
self.active_list.push(dragged_item);
self.dragged_item = None;
}
self.dnd_offer = None;
}
Expand All @@ -1227,16 +1227,16 @@
tracing::error!("Couldn't peek at hovered path.");
return Task::none();
};
if let Some(DndOffer { dock_item, .. }) = self.dnd_offer.as_mut() {
if let Ok(de) = fde::DesktopEntry::from_path(file_path.0, Some(&self.locales)) {
self.item_ctr += 1;
*dock_item = Some(DockItem {
id: self.item_ctr,
toplevels: Vec::new(),
original_app_id: de.id().to_string(),
desktop_info: de,
});
}
if let Some(DndOffer { dock_item, .. }) = self.dnd_offer.as_mut()
&& let Ok(de) = fde::DesktopEntry::from_path(file_path.0, Some(&self.locales))
{
self.item_ctr += 1;
*dock_item = Some(DockItem {
id: self.item_ctr,
toplevels: Vec::new(),
original_app_id: de.id().to_string(),
desktop_info: de,
});
}
}
Message::DndDropFinished => {
Expand Down Expand Up @@ -1818,25 +1818,9 @@
.as_ref()
.and_then(|o| o.dock_item.as_ref().map(|item| (item, o.preview_index)))
{
let filtered_is_focused = item
.toplevels
.iter()
.filter(|(info, _)| self.is_on_current_monitor_and_workspace(info))
.any(|y| focused_item.contains(&y.0.foreign_toplevel));

favorites.insert(
index.min(favorites.len()),
item.as_icon(
&self.core.applet,
None,
false,
self.config.enable_drag_source,
self.gpus.as_deref(),
filtered_is_focused,
dot_radius,
self.core.main_window_id().unwrap(),
Some(&|info| self.is_on_current_monitor_and_workspace(info)),
),
item.as_dragged_item(&self.core.applet),
);
} else if self.is_listening_for_dnd && self.pinned_list.is_empty() {
// show star indicating pinned_list is drag target
Expand Down
10 changes: 5 additions & 5 deletions cosmic-app-list/src/wayland_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,11 +624,11 @@ pub(crate) fn wayland_handler(
}
WaylandRequest::Toplevel(req) => match req {
ToplevelRequest::Activate(handle) => {
if let Some(cosmic_toplevel) = state.cosmic_toplevel(&handle) {
if let Some(seat) = state.seat_state.seats().next() {
let manager = &state.toplevel_manager_state.manager;
manager.activate(&cosmic_toplevel, &seat);
}
if let Some(cosmic_toplevel) = state.cosmic_toplevel(&handle)
&& let Some(seat) = state.seat_state.seats().next()
{
let manager = &state.toplevel_manager_state.manager;
manager.activate(&cosmic_toplevel, &seat);
}
}
ToplevelRequest::Minimize(handle) => {
Expand Down
3 changes: 1 addition & 2 deletions cosmic-applet-a11y/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ use cosmic::{
};

use cosmic_settings_a11y_manager_subscription::{
self as cosmic_a11y_manager, AccessibilityEvent, AccessibilityRequest, ColorFilter,
AccessibilityEvent, AccessibilityRequest, ColorFilter,
};
use cosmic_settings_accessibility_subscription::{self as accessibility};
use std::sync::LazyLock;
use tokio::sync::mpsc::UnboundedSender;

pub fn run() -> cosmic::iced::Result {
Expand Down
5 changes: 2 additions & 3 deletions cosmic-applet-a11y/src/backend/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
// SPDX-License-Identifier: GPL-3.0-only

use anyhow;
use cctk::sctk::reexports::calloop::{self, channel::SyncSender};
use cctk::sctk::reexports::calloop::{self};
use cosmic::iced::{
self, Subscription,
futures::{self, SinkExt, StreamExt, channel::mpsc},
futures::{self, SinkExt},
stream,
};
use cosmic_protocols::a11y::v1::client::cosmic_a11y_manager_v1::Filter;
use cosmic_settings_a11y_manager_subscription::{
self as thread, AccessibilityEvent, AccessibilityRequest,
};
Expand Down
5 changes: 2 additions & 3 deletions cosmic-applet-audio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,9 @@ impl cosmic::Application for Audio {
self.config.show_media_controls_in_top_panel = enabled;
if let Ok(helper) =
cosmic::cosmic_config::Config::new(Self::APP_ID, AudioAppletConfig::VERSION)
&& let Err(err) = self.config.write_entry(&helper)
{
if let Err(err) = self.config.write_entry(&helper) {
tracing::error!(?err, "Error writing config");
}
tracing::error!(?err, "Error writing config");
}
}
Message::CloseRequested(id) => {
Expand Down
Loading
Loading