app_list: Use libcosmic desktop helpers
This commit is contained in:
parent
2a47cde1b4
commit
d7a8db6a07
6 changed files with 112 additions and 248 deletions
48
Cargo.lock
generated
48
Cargo.lock
generated
|
|
@ -792,8 +792,6 @@ dependencies = [
|
|||
"anyhow",
|
||||
"cosmic-client-toolkit",
|
||||
"cosmic-protocols",
|
||||
"freedesktop-desktop-entry",
|
||||
"freedesktop-icons",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"i18n-embed 0.13.9",
|
||||
|
|
@ -808,7 +806,6 @@ dependencies = [
|
|||
"rust-embed 6.8.1",
|
||||
"rust-embed-utils 7.8.1",
|
||||
"serde",
|
||||
"shlex",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-log",
|
||||
|
|
@ -1036,7 +1033,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-config"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"atomicwrites",
|
||||
"cosmic-config-derive",
|
||||
|
|
@ -1044,17 +1041,19 @@ dependencies = [
|
|||
"dirs 5.0.1",
|
||||
"futures-util",
|
||||
"iced_futures",
|
||||
"known-folders",
|
||||
"notify",
|
||||
"once_cell",
|
||||
"ron",
|
||||
"serde",
|
||||
"xdg",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmic-config-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
|
|
@ -1164,7 +1163,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-theme"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"almost",
|
||||
"cosmic-config",
|
||||
|
|
@ -2689,7 +2688,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"iced_accessibility",
|
||||
"iced_core",
|
||||
|
|
@ -2704,7 +2703,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_accessibility"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"accesskit",
|
||||
"accesskit_unix",
|
||||
|
|
@ -2713,7 +2712,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_core"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"iced_accessibility",
|
||||
|
|
@ -2731,7 +2730,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_futures"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"iced_core",
|
||||
|
|
@ -2744,7 +2743,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_graphics"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bytemuck",
|
||||
|
|
@ -2767,7 +2766,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_renderer"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"iced_graphics",
|
||||
"iced_tiny_skia",
|
||||
|
|
@ -2780,7 +2779,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_runtime"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"iced_accessibility",
|
||||
"iced_core",
|
||||
|
|
@ -2792,7 +2791,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_sctk"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"enum-repr",
|
||||
"float-cmp",
|
||||
|
|
@ -2816,7 +2815,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_style"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"iced_core",
|
||||
"once_cell",
|
||||
|
|
@ -2826,7 +2825,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_tiny_skia"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"cosmic-text",
|
||||
|
|
@ -2844,7 +2843,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_wgpu"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bytemuck",
|
||||
|
|
@ -2864,7 +2863,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_widget"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"iced_renderer",
|
||||
"iced_runtime",
|
||||
|
|
@ -3070,6 +3069,15 @@ version = "3.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
||||
|
||||
[[package]]
|
||||
name = "known-folders"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4397c789f2709d23cfcb703b316e0766a8d4b17db2d47b0ab096ef6047cae1d8"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.0.8"
|
||||
|
|
@ -3120,7 +3128,7 @@ checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
|||
[[package]]
|
||||
name = "libcosmic"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic#912e8b0a4478e67ad4b3ce46e327c70dbe9887d8"
|
||||
source = "git+https://github.com/pop-os/libcosmic#bf0508816b7e7098cfcc6eb16ee288207ef0cc31"
|
||||
dependencies = [
|
||||
"apply",
|
||||
"ashpd",
|
||||
|
|
@ -3132,6 +3140,7 @@ dependencies = [
|
|||
"css-color",
|
||||
"derive_setters",
|
||||
"fraction",
|
||||
"freedesktop-desktop-entry",
|
||||
"freedesktop-icons",
|
||||
"iced",
|
||||
"iced_core",
|
||||
|
|
@ -3147,6 +3156,7 @@ dependencies = [
|
|||
"palette",
|
||||
"rfd",
|
||||
"ron",
|
||||
"shlex",
|
||||
"slotmap",
|
||||
"taffy",
|
||||
"thiserror",
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ libcosmic = { git = "https://github.com/pop-os/libcosmic", default-features = fa
|
|||
"applet-token",
|
||||
"tokio",
|
||||
"wayland",
|
||||
"process",
|
||||
"desktop",
|
||||
"dbus-config"
|
||||
] }
|
||||
zbus = { version = "3.14", default-features = false, features = ["tokio"] }
|
||||
|
|
|
|||
|
|
@ -18,14 +18,11 @@ tracing-subscriber.workspace = true
|
|||
tracing-log.workspace = true
|
||||
tracing.workspace = true
|
||||
nix = "0.26"
|
||||
shlex = "1.3.0"
|
||||
anyhow = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
log = "0.4"
|
||||
tokio = { version = "1.17.0", features = ["sync", "rt", "rt-multi-thread", "macros", "process"] }
|
||||
itertools = "*"
|
||||
freedesktop-desktop-entry = "0.5.0"
|
||||
freedesktop-icons = "0.2.4"
|
||||
i18n-embed = { version = "0.13", features = ["fluent-system", "desktop-requester"] }
|
||||
i18n-embed-fl = "0.6"
|
||||
rust-embed = "6.3"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use cctk::toplevel_info::ToplevelInfo;
|
|||
use cctk::wayland_client::protocol::wl_data_device_manager::DndAction;
|
||||
use cctk::wayland_client::protocol::wl_seat::WlSeat;
|
||||
use cosmic::cosmic_config::{self, Config, CosmicConfigEntry};
|
||||
use cosmic::desktop::{load_applications_for_app_ids, DesktopEntryData};
|
||||
use cosmic::iced;
|
||||
use cosmic::iced::event::listen_with;
|
||||
use cosmic::iced::wayland::actions::data_device::DataFromMimeType;
|
||||
|
|
@ -24,7 +25,6 @@ use cosmic::iced::widget::vertical_space;
|
|||
use cosmic::iced::widget::{column, dnd_source, mouse_area, row, Column, Row};
|
||||
use cosmic::iced::Color;
|
||||
use cosmic::iced::{window, Subscription};
|
||||
use cosmic::iced_core::window::Icon;
|
||||
use cosmic::iced_runtime::core::alignment::Horizontal;
|
||||
use cosmic::iced_runtime::core::event;
|
||||
use cosmic::iced_sctk::commands::data_device::accept_mime_type;
|
||||
|
|
@ -44,7 +44,6 @@ use cosmic::{
|
|||
};
|
||||
use cosmic::{Element, Theme};
|
||||
use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1;
|
||||
use freedesktop_desktop_entry::DesktopEntry;
|
||||
use futures::future::pending;
|
||||
use iced::widget::container;
|
||||
use iced::Alignment;
|
||||
|
|
@ -52,9 +51,7 @@ use iced::Background;
|
|||
use iced::Length;
|
||||
use itertools::Itertools;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
|
@ -71,14 +68,14 @@ pub fn run() -> cosmic::iced::Result {
|
|||
struct DockItem {
|
||||
id: u32,
|
||||
toplevels: Vec<(ZcosmicToplevelHandleV1, ToplevelInfo)>,
|
||||
desktop_info: DesktopInfo,
|
||||
desktop_info: DesktopEntryData,
|
||||
}
|
||||
|
||||
impl DataFromMimeType for DockItem {
|
||||
fn from_mime_type(&self, mime_type: &str) -> Option<Vec<u8>> {
|
||||
if mime_type == MIME_TYPE {
|
||||
if mime_type == MIME_TYPE && self.desktop_info.path.is_some() {
|
||||
Some(
|
||||
Url::from_file_path(self.desktop_info.path.clone())
|
||||
Url::from_file_path(self.desktop_info.path.as_deref().unwrap())
|
||||
.ok()?
|
||||
.to_string()
|
||||
.as_bytes()
|
||||
|
|
@ -94,7 +91,7 @@ impl DockItem {
|
|||
fn new(
|
||||
id: u32,
|
||||
toplevels: Vec<(ZcosmicToplevelHandleV1, ToplevelInfo)>,
|
||||
desktop_info: DesktopInfo,
|
||||
desktop_info: DesktopEntryData,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
|
|
@ -167,11 +164,11 @@ impl DockItem {
|
|||
dnd_source(
|
||||
mouse_area(
|
||||
icon_button
|
||||
.on_press(
|
||||
.on_press_maybe(
|
||||
toplevels
|
||||
.first()
|
||||
.map(|t| Message::Activate(t.0.clone()))
|
||||
.unwrap_or_else(|| Message::Exec(desktop_info.exec.clone())),
|
||||
.or_else(|| desktop_info.exec.clone().map(Message::Exec)),
|
||||
)
|
||||
.width(Length::Shrink)
|
||||
.height(Length::Shrink),
|
||||
|
|
@ -202,7 +199,7 @@ struct DndOffer {
|
|||
#[derive(Clone, Default)]
|
||||
struct CosmicAppList {
|
||||
core: cosmic::app::Core,
|
||||
popup: Option<(window::Id, DockItem)>,
|
||||
popup: Option<(window::Id, u32)>,
|
||||
subscription_ctr: u32,
|
||||
item_ctr: u32,
|
||||
active_list: Vec<DockItem>,
|
||||
|
|
@ -246,109 +243,6 @@ enum Message {
|
|||
ConfigUpdated(AppListConfig),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) enum IconSource {
|
||||
Name(String),
|
||||
Path(PathBuf),
|
||||
}
|
||||
|
||||
impl IconSource {
|
||||
fn from_unknown(icon: &str) -> Self {
|
||||
let icon_path = Path::new(icon);
|
||||
if icon_path.is_absolute() && icon_path.exists() {
|
||||
Self::Path(icon_path.into())
|
||||
} else {
|
||||
Self::Name(icon.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn as_cosmic_icon(&self) -> cosmic::widget::icon::Icon {
|
||||
match self {
|
||||
Self::Name(name) => cosmic::widget::icon::from_name(name.as_str())
|
||||
.size(128)
|
||||
.fallback(Some(cosmic::widget::icon::IconFallback::Names(vec![
|
||||
"application-default".into(),
|
||||
"application-x-executable".into(),
|
||||
])))
|
||||
.into(),
|
||||
Self::Path(path) => cosmic::widget::icon(cosmic::widget::icon::from_path(path.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for IconSource {
|
||||
fn default() -> Self {
|
||||
Self::Name("application-default".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct DesktopInfo {
|
||||
id: String,
|
||||
wm_class: Option<String>,
|
||||
icon: IconSource,
|
||||
exec: String,
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
fn desktop_info_for_app_ids(mut app_ids: Vec<String>) -> Vec<DesktopInfo> {
|
||||
let app_ids_clone = app_ids.clone();
|
||||
let mut ret = freedesktop_desktop_entry::Iter::new(freedesktop_desktop_entry::default_paths())
|
||||
.filter_map(|path| {
|
||||
std::fs::read_to_string(&path).ok().and_then(|input| {
|
||||
DesktopEntry::decode(&path, &input).ok().and_then(|de| {
|
||||
if let Some(i) = app_ids.iter().position(|s| {
|
||||
s == de.appid || s.eq(&de.startup_wm_class().unwrap_or_default())
|
||||
}) {
|
||||
// check if absolute path exists and otherwise treat it as a name
|
||||
let icon = de.icon().unwrap_or(de.appid);
|
||||
let icon_path = Path::new(icon);
|
||||
let icon = if icon_path.is_absolute() && icon_path.exists() {
|
||||
IconSource::Path(icon_path.into())
|
||||
} else {
|
||||
IconSource::Name(icon.into())
|
||||
};
|
||||
app_ids.remove(i);
|
||||
|
||||
Some(DesktopInfo {
|
||||
id: de.appid.to_string(),
|
||||
wm_class: de.startup_wm_class().map(ToString::to_string),
|
||||
icon,
|
||||
exec: de.exec().unwrap_or_default().to_string(),
|
||||
name: de.name(None).unwrap_or_default().to_string(),
|
||||
path: path.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect_vec();
|
||||
ret.append(
|
||||
&mut app_ids
|
||||
.into_iter()
|
||||
.map(|id| DesktopInfo {
|
||||
id,
|
||||
icon: IconSource::default(),
|
||||
..Default::default()
|
||||
})
|
||||
.collect_vec(),
|
||||
);
|
||||
ret.sort_by(|a, b| {
|
||||
app_ids_clone
|
||||
.iter()
|
||||
.position(|id| id == &a.id || Some(id) == a.wm_class.as_ref())
|
||||
.cmp(
|
||||
&app_ids_clone
|
||||
.iter()
|
||||
.position(|id| id == &b.id || Some(id) == b.wm_class.as_ref()),
|
||||
)
|
||||
});
|
||||
ret
|
||||
}
|
||||
|
||||
fn index_in_list(
|
||||
mut list_len: usize,
|
||||
item_size: f32,
|
||||
|
|
@ -404,15 +298,19 @@ impl cosmic::Application for CosmicAppList {
|
|||
.unwrap_or_default();
|
||||
let mut self_ = Self {
|
||||
core,
|
||||
favorite_list: desktop_info_for_app_ids(config.favorites.clone())
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(favorite_ctr, e)| DockItem {
|
||||
id: favorite_ctr as u32,
|
||||
toplevels: Default::default(),
|
||||
desktop_info: e,
|
||||
})
|
||||
.collect(),
|
||||
favorite_list: load_applications_for_app_ids(
|
||||
None,
|
||||
config.favorites.iter().map(|s| &**s),
|
||||
true,
|
||||
)
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(favorite_ctr, e)| DockItem {
|
||||
id: favorite_ctr as u32,
|
||||
toplevels: Default::default(),
|
||||
desktop_info: e,
|
||||
})
|
||||
.collect(),
|
||||
config,
|
||||
..Default::default()
|
||||
};
|
||||
|
|
@ -450,7 +348,7 @@ impl cosmic::Application for CosmicAppList {
|
|||
};
|
||||
|
||||
let new_id = window::Id::unique();
|
||||
self.popup = Some((new_id, toplevel_group.clone()));
|
||||
self.popup = Some((new_id, toplevel_group.id.clone()));
|
||||
|
||||
let mut popup_settings = self.core.applet.get_popup_settings(
|
||||
window::Id::MAIN,
|
||||
|
|
@ -511,12 +409,12 @@ impl cosmic::Application for CosmicAppList {
|
|||
}
|
||||
}
|
||||
Message::Activate(handle) => {
|
||||
if let Some(p) = self.popup.take() {
|
||||
return destroy_popup(p.0);
|
||||
}
|
||||
if let Some(tx) = self.wayland_sender.as_ref() {
|
||||
let _ = tx.send(WaylandRequest::Toplevel(ToplevelRequest::Activate(handle)));
|
||||
}
|
||||
if let Some(p) = self.popup.take() {
|
||||
return destroy_popup(p.0);
|
||||
}
|
||||
}
|
||||
Message::Quit(id) => {
|
||||
if let Some(toplevel_group) = self
|
||||
|
|
@ -649,18 +547,7 @@ impl cosmic::Application for CosmicAppList {
|
|||
}
|
||||
Message::DndData(file_path) => {
|
||||
if let Some(DndOffer { dock_item, .. }) = self.dnd_offer.as_mut() {
|
||||
if let Some(di) = std::fs::read_to_string(&file_path).ok().and_then(|input| {
|
||||
DesktopEntry::decode(&file_path, &input)
|
||||
.ok()
|
||||
.map(|de| DesktopInfo {
|
||||
id: de.id().to_string(),
|
||||
wm_class: de.startup_wm_class().map(ToString::to_string),
|
||||
icon: IconSource::from_unknown(de.icon().unwrap_or(de.appid)),
|
||||
exec: de.exec().unwrap_or_default().to_string(),
|
||||
name: de.name(None).unwrap_or_default().to_string(),
|
||||
path: file_path.clone(),
|
||||
})
|
||||
}) {
|
||||
if let Some(di) = cosmic::desktop::load_desktop_file(None, &file_path) {
|
||||
self.item_ctr += 1;
|
||||
*dock_item = Some(DockItem::new(self.item_ctr, Vec::new(), di));
|
||||
}
|
||||
|
|
@ -758,17 +645,14 @@ impl cosmic::Application for CosmicAppList {
|
|||
info.app_id = format!("Unknown Application {}", self.item_ctr);
|
||||
}
|
||||
self.item_ctr += 1;
|
||||
let desktop_info =
|
||||
desktop_info_for_app_ids(vec![info.app_id.clone()])
|
||||
.pop()
|
||||
.unwrap_or_else(|| DesktopInfo {
|
||||
id: info.app_id.clone(),
|
||||
wm_class: None,
|
||||
icon: IconSource::default(),
|
||||
exec: String::new(),
|
||||
name: info.app_id.clone(),
|
||||
path: PathBuf::new(),
|
||||
});
|
||||
let desktop_info = load_applications_for_app_ids(
|
||||
None,
|
||||
std::iter::once(&*info.app_id),
|
||||
true,
|
||||
)
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap();
|
||||
self.active_list.push(DockItem {
|
||||
id: self.item_ctr,
|
||||
toplevels: vec![(handle, info)],
|
||||
|
|
@ -806,23 +690,13 @@ impl cosmic::Application for CosmicAppList {
|
|||
}
|
||||
},
|
||||
WaylandUpdate::ActivationToken { token, exec } => {
|
||||
let mut exec = shlex::Shlex::new(&exec);
|
||||
let mut cmd = match exec.next() {
|
||||
Some(cmd) if !cmd.contains('=') => std::process::Command::new(cmd),
|
||||
_ => return Command::none(),
|
||||
};
|
||||
for arg in exec {
|
||||
// TODO handle "%" args here if necessary?
|
||||
if !arg.starts_with('%') {
|
||||
cmd.arg(arg);
|
||||
}
|
||||
}
|
||||
let mut envs = Vec::new();
|
||||
if let Some(token) = token {
|
||||
cmd.env("XDG_ACTIVATION_TOKEN", &token);
|
||||
cmd.env("DESKTOP_STARTUP_ID", &token);
|
||||
envs.push(("XDG_ACTIVATION_TOKEN", token.clone()));
|
||||
envs.push(("DESKTOP_STARTUP_ID", token));
|
||||
}
|
||||
tokio::task::spawn_blocking(|| {
|
||||
crate::process::spawn(cmd);
|
||||
cosmic::desktop::spawn_desktop_exec(exec, envs);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -872,25 +746,29 @@ impl cosmic::Application for CosmicAppList {
|
|||
}
|
||||
|
||||
// pull back configured items into the favorites list
|
||||
self.favorite_list = desktop_info_for_app_ids(self.config.favorites.clone())
|
||||
.into_iter()
|
||||
.map(|new_dock_item| {
|
||||
if let Some(p) = self
|
||||
.active_list
|
||||
.iter()
|
||||
.position(|dock_item| dock_item.desktop_info.id == new_dock_item.id)
|
||||
{
|
||||
self.active_list.remove(p)
|
||||
} else {
|
||||
self.item_ctr += 1;
|
||||
DockItem {
|
||||
id: self.item_ctr,
|
||||
toplevels: Default::default(),
|
||||
desktop_info: new_dock_item,
|
||||
}
|
||||
self.favorite_list = load_applications_for_app_ids(
|
||||
None,
|
||||
self.config.favorites.iter().map(|s| &**s),
|
||||
true,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|new_dock_item| {
|
||||
if let Some(p) = self
|
||||
.active_list
|
||||
.iter()
|
||||
.position(|dock_item| dock_item.desktop_info.id == new_dock_item.id)
|
||||
{
|
||||
self.active_list.remove(p)
|
||||
} else {
|
||||
self.item_ctr += 1;
|
||||
DockItem {
|
||||
id: self.item_ctr,
|
||||
toplevels: Default::default(),
|
||||
desktop_info: new_dock_item,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
Message::CloseRequested(id) => {
|
||||
if Some(id) == self.popup.as_ref().map(|p| p.0) {
|
||||
|
|
@ -1051,15 +929,20 @@ impl cosmic::Application for CosmicAppList {
|
|||
.as_cosmic_icon()
|
||||
.size(self.core.applet.suggested_size().0)
|
||||
.into()
|
||||
} else if let Some((
|
||||
_popup_id,
|
||||
DockItem {
|
||||
} else if let Some((_popup_id, id)) = self.popup.as_ref().filter(|p| id == p.0) {
|
||||
let Some(DockItem {
|
||||
toplevels,
|
||||
desktop_info,
|
||||
..
|
||||
},
|
||||
)) = self.popup.as_ref().filter(|p| id == p.0)
|
||||
{
|
||||
}) = self
|
||||
.favorite_list
|
||||
.iter()
|
||||
.chain(self.active_list.iter())
|
||||
.find(|i| i.id == *id)
|
||||
else {
|
||||
return iced::widget::text("").into();
|
||||
};
|
||||
|
||||
let is_favorite = self.config.favorites.contains(&desktop_info.id)
|
||||
|| desktop_info
|
||||
.wm_class
|
||||
|
|
@ -1068,13 +951,20 @@ impl cosmic::Application for CosmicAppList {
|
|||
|
||||
let mut content = column![
|
||||
iced::widget::text(&desktop_info.name).horizontal_alignment(Horizontal::Center),
|
||||
cosmic::widget::button(iced::widget::text(fl!("new-window")))
|
||||
.style(Button::Text)
|
||||
.on_press(Message::Exec(desktop_info.exec.clone())),
|
||||
]
|
||||
.padding(8)
|
||||
.spacing(4)
|
||||
.align_items(Alignment::Center);
|
||||
|
||||
if let Some(exec) = desktop_info.exec.clone() {
|
||||
content = content.push(
|
||||
cosmic::widget::button(iced::widget::text(fl!("new-window")))
|
||||
.style(Button::Text)
|
||||
.on_press(Message::Exec(exec)),
|
||||
);
|
||||
content = content.push(divider::horizontal::default());
|
||||
}
|
||||
|
||||
if !toplevels.is_empty() {
|
||||
let mut list_col = column![];
|
||||
for (handle, info) in toplevels {
|
||||
|
|
@ -1089,10 +979,9 @@ impl cosmic::Application for CosmicAppList {
|
|||
.on_press(Message::Activate(handle.clone())),
|
||||
);
|
||||
}
|
||||
content = content.push(divider::horizontal::default());
|
||||
content = content.push(list_col);
|
||||
content = content.push(divider::horizontal::default());
|
||||
}
|
||||
content = content.push(divider::horizontal::default());
|
||||
content = content.push(if is_favorite {
|
||||
cosmic::widget::button(iced::widget::text(fl!("unfavorite")))
|
||||
.style(Button::Text)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
mod app;
|
||||
mod config;
|
||||
mod localize;
|
||||
mod process;
|
||||
mod wayland_handler;
|
||||
mod wayland_subscription;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
use std::process::{exit, Command, Stdio};
|
||||
|
||||
use nix::sys::wait::waitpid;
|
||||
use nix::unistd::{fork, ForkResult};
|
||||
|
||||
/// Performs a double fork with setsid to spawn and detach a command.
|
||||
pub fn spawn(mut command: Command) {
|
||||
command
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null());
|
||||
|
||||
unsafe {
|
||||
match fork() {
|
||||
Ok(ForkResult::Parent { child }) => {
|
||||
let _res = waitpid(Some(child), None);
|
||||
}
|
||||
|
||||
Ok(ForkResult::Child) => {
|
||||
let _res = nix::unistd::setsid();
|
||||
let _res = command.spawn();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Err(why) => {
|
||||
println!("failed to fork and spawn command: {}", why.desc());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue