feat: execute apps without toplevel
This commit is contained in:
parent
6fef03ed2f
commit
a378b0eee0
3 changed files with 69 additions and 11 deletions
38
applets/cosmic-app-list/Cargo.lock
generated
38
applets/cosmic-app-list/Cargo.lock
generated
|
|
@ -231,6 +231,12 @@ version = "1.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
||||
|
||||
[[package]]
|
||||
name = "calloop"
|
||||
version = "0.10.4"
|
||||
|
|
@ -399,6 +405,7 @@ dependencies = [
|
|||
"ron",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"shlex",
|
||||
"tokio",
|
||||
"xdg",
|
||||
]
|
||||
|
|
@ -1864,6 +1871,18 @@ dependencies = [
|
|||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mutate_once"
|
||||
version = "0.1.1"
|
||||
|
|
@ -2641,6 +2660,21 @@ dependencies = [
|
|||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simplecss"
|
||||
version = "0.2.1"
|
||||
|
|
@ -2926,8 +2960,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ xdg = "2.4"
|
|||
pretty_env_logger = "0.4"
|
||||
calloop = "0.10"
|
||||
nix = "0.26"
|
||||
shlex = "1.1.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"] }
|
||||
tokio = { version = "1.17.0", features = ["sync", "rt", "rt-multi-thread", "macros", "process"] }
|
||||
itertools = "*"
|
||||
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", no-default-features = true}
|
||||
freedesktop-desktop-entry = "0.5.0"
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ struct Toplevel {
|
|||
toplevels: Vec<(ZcosmicToplevelHandleV1, ToplevelInfo)>,
|
||||
app_id: String,
|
||||
icon_path: PathBuf,
|
||||
exec: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
|
|
@ -67,14 +68,15 @@ enum Message {
|
|||
Favorite(String),
|
||||
UnFavorite(String),
|
||||
TogglePopup(usize),
|
||||
Activate(Option<ZcosmicToplevelHandleV1>),
|
||||
Activate(ZcosmicToplevelHandleV1),
|
||||
Exec(String),
|
||||
Quit(ZcosmicToplevelHandleV1),
|
||||
Errored(String),
|
||||
Ignore,
|
||||
NewSeat(WlSeat),
|
||||
RemovedSeat(WlSeat),
|
||||
}
|
||||
fn icon_for_app_ids(mut app_ids: Vec<String>) -> Vec<(String, PathBuf)> {
|
||||
fn icon_exec_for_app_ids(mut app_ids: Vec<String>) -> Vec<(String, PathBuf, String)> {
|
||||
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| {
|
||||
|
|
@ -85,7 +87,7 @@ fn icon_for_app_ids(mut app_ids: Vec<String>) -> Vec<(String, PathBuf)> {
|
|||
.with_size(128)
|
||||
.with_cache()
|
||||
.find()
|
||||
.map(|buf| (id, buf))
|
||||
.map(|buf| (id, buf, de.exec().unwrap_or_default().to_string()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -96,7 +98,7 @@ fn icon_for_app_ids(mut app_ids: Vec<String>) -> Vec<(String, PathBuf)> {
|
|||
ret.append(
|
||||
&mut app_ids
|
||||
.into_iter()
|
||||
.map(|id| (id, Default::default()))
|
||||
.map(|id| (id, Default::default(), Default::default()))
|
||||
.collect_vec(),
|
||||
);
|
||||
ret
|
||||
|
|
@ -112,12 +114,13 @@ impl Application for CosmicAppList {
|
|||
let config = config::AppListConfig::load().unwrap_or_default();
|
||||
(
|
||||
CosmicAppList {
|
||||
toplevel_list: icon_for_app_ids(config.favorites.clone())
|
||||
toplevel_list: icon_exec_for_app_ids(config.favorites.clone())
|
||||
.into_iter()
|
||||
.map(|e| Toplevel {
|
||||
toplevels: Default::default(),
|
||||
app_id: e.0,
|
||||
icon_path: e.1,
|
||||
exec: e.2,
|
||||
})
|
||||
.collect(),
|
||||
config,
|
||||
|
|
@ -161,7 +164,7 @@ impl Application for CosmicAppList {
|
|||
let _ = self.config.remove_favorite(id);
|
||||
}
|
||||
Message::Activate(handle) => {
|
||||
if let (Some(tx), Some(seat), Some(handle)) = (self.toplevel_sender.as_ref(), self.seat.as_ref(), handle) {
|
||||
if let (Some(tx), Some(seat)) = (self.toplevel_sender.as_ref(), self.seat.as_ref()) {
|
||||
let _ = tx.send(ToplevelRequest::Activate(handle, seat.clone()));
|
||||
}
|
||||
}
|
||||
|
|
@ -181,13 +184,14 @@ impl Application for CosmicAppList {
|
|||
{
|
||||
self.toplevel_list[i].toplevels.push((handle, info));
|
||||
} else {
|
||||
let (app_id, icon_name) =
|
||||
icon_for_app_ids(vec![info.app_id.clone()]).remove(0);
|
||||
let (app_id, icon_path, exec) =
|
||||
icon_exec_for_app_ids(vec![info.app_id.clone()]).remove(0);
|
||||
|
||||
self.toplevel_list.push(Toplevel {
|
||||
toplevels: vec![(handle, info)],
|
||||
app_id,
|
||||
icon_path: icon_name,
|
||||
icon_path,
|
||||
exec
|
||||
});
|
||||
// TODO better way of setting window size?
|
||||
let pixel_size = self.applet_helper.suggested_icon_size();
|
||||
|
|
@ -298,6 +302,20 @@ impl Application for CosmicAppList {
|
|||
Message::RemovedSeat(_) => {
|
||||
self.seat.take();
|
||||
},
|
||||
Message::Exec(exec_str) => {
|
||||
let mut exec = shlex::Shlex::new(&exec_str);
|
||||
let mut cmd = match exec.next() {
|
||||
Some(cmd) if !cmd.contains("=") => tokio::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 _ = cmd.spawn();
|
||||
},
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
|
|
@ -315,6 +333,7 @@ impl Application for CosmicAppList {
|
|||
toplevels,
|
||||
app_id,
|
||||
icon_path,
|
||||
exec,
|
||||
},
|
||||
)| {
|
||||
let icon = if icon_path.extension() == Some(&OsStr::new("svg")) {
|
||||
|
|
@ -371,7 +390,7 @@ impl Application for CosmicAppList {
|
|||
// TODO tooltip on hover
|
||||
let icon_button = cosmic::widget::button(Button::Text)
|
||||
.custom(vec![icon_wrapper])
|
||||
.on_press(Message::Activate(toplevels.first().map(|t| t.0.clone())))
|
||||
.on_press(toplevels.first().map(|t| Message::Activate(t.0.clone())).unwrap_or_else(|| Message::Exec(exec.clone())))
|
||||
.padding(8)
|
||||
.into();
|
||||
if self.config.favorites.contains(&app_id) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue