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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "calloop"
|
name = "calloop"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
|
@ -399,6 +405,7 @@ dependencies = [
|
||||||
"ron",
|
"ron",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
"serde",
|
"serde",
|
||||||
|
"shlex",
|
||||||
"tokio",
|
"tokio",
|
||||||
"xdg",
|
"xdg",
|
||||||
]
|
]
|
||||||
|
|
@ -1864,6 +1871,18 @@ dependencies = [
|
||||||
"adler",
|
"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]]
|
[[package]]
|
||||||
name = "mutate_once"
|
name = "mutate_once"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -2641,6 +2660,21 @@ dependencies = [
|
||||||
"digest",
|
"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]]
|
[[package]]
|
||||||
name = "simplecss"
|
name = "simplecss"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
|
@ -2926,8 +2960,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"bytes",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.42.0",
|
"windows-sys 0.42.0",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,11 @@ xdg = "2.4"
|
||||||
pretty_env_logger = "0.4"
|
pretty_env_logger = "0.4"
|
||||||
calloop = "0.10"
|
calloop = "0.10"
|
||||||
nix = "0.26"
|
nix = "0.26"
|
||||||
|
shlex = "1.1.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
log = "0.4"
|
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 = "*"
|
itertools = "*"
|
||||||
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", no-default-features = true}
|
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", no-default-features = true}
|
||||||
freedesktop-desktop-entry = "0.5.0"
|
freedesktop-desktop-entry = "0.5.0"
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ struct Toplevel {
|
||||||
toplevels: Vec<(ZcosmicToplevelHandleV1, ToplevelInfo)>,
|
toplevels: Vec<(ZcosmicToplevelHandleV1, ToplevelInfo)>,
|
||||||
app_id: String,
|
app_id: String,
|
||||||
icon_path: PathBuf,
|
icon_path: PathBuf,
|
||||||
|
exec: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
|
@ -67,14 +68,15 @@ enum Message {
|
||||||
Favorite(String),
|
Favorite(String),
|
||||||
UnFavorite(String),
|
UnFavorite(String),
|
||||||
TogglePopup(usize),
|
TogglePopup(usize),
|
||||||
Activate(Option<ZcosmicToplevelHandleV1>),
|
Activate(ZcosmicToplevelHandleV1),
|
||||||
|
Exec(String),
|
||||||
Quit(ZcosmicToplevelHandleV1),
|
Quit(ZcosmicToplevelHandleV1),
|
||||||
Errored(String),
|
Errored(String),
|
||||||
Ignore,
|
Ignore,
|
||||||
NewSeat(WlSeat),
|
NewSeat(WlSeat),
|
||||||
RemovedSeat(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())
|
let mut ret = freedesktop_desktop_entry::Iter::new(freedesktop_desktop_entry::default_paths())
|
||||||
.filter_map(|path| {
|
.filter_map(|path| {
|
||||||
std::fs::read_to_string(&path).ok().and_then(|input| {
|
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_size(128)
|
||||||
.with_cache()
|
.with_cache()
|
||||||
.find()
|
.find()
|
||||||
.map(|buf| (id, buf))
|
.map(|buf| (id, buf, de.exec().unwrap_or_default().to_string()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +98,7 @@ fn icon_for_app_ids(mut app_ids: Vec<String>) -> Vec<(String, PathBuf)> {
|
||||||
ret.append(
|
ret.append(
|
||||||
&mut app_ids
|
&mut app_ids
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|id| (id, Default::default()))
|
.map(|id| (id, Default::default(), Default::default()))
|
||||||
.collect_vec(),
|
.collect_vec(),
|
||||||
);
|
);
|
||||||
ret
|
ret
|
||||||
|
|
@ -112,12 +114,13 @@ impl Application for CosmicAppList {
|
||||||
let config = config::AppListConfig::load().unwrap_or_default();
|
let config = config::AppListConfig::load().unwrap_or_default();
|
||||||
(
|
(
|
||||||
CosmicAppList {
|
CosmicAppList {
|
||||||
toplevel_list: icon_for_app_ids(config.favorites.clone())
|
toplevel_list: icon_exec_for_app_ids(config.favorites.clone())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| Toplevel {
|
.map(|e| Toplevel {
|
||||||
toplevels: Default::default(),
|
toplevels: Default::default(),
|
||||||
app_id: e.0,
|
app_id: e.0,
|
||||||
icon_path: e.1,
|
icon_path: e.1,
|
||||||
|
exec: e.2,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
config,
|
config,
|
||||||
|
|
@ -161,7 +164,7 @@ impl Application for CosmicAppList {
|
||||||
let _ = self.config.remove_favorite(id);
|
let _ = self.config.remove_favorite(id);
|
||||||
}
|
}
|
||||||
Message::Activate(handle) => {
|
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()));
|
let _ = tx.send(ToplevelRequest::Activate(handle, seat.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -181,13 +184,14 @@ impl Application for CosmicAppList {
|
||||||
{
|
{
|
||||||
self.toplevel_list[i].toplevels.push((handle, info));
|
self.toplevel_list[i].toplevels.push((handle, info));
|
||||||
} else {
|
} else {
|
||||||
let (app_id, icon_name) =
|
let (app_id, icon_path, exec) =
|
||||||
icon_for_app_ids(vec![info.app_id.clone()]).remove(0);
|
icon_exec_for_app_ids(vec![info.app_id.clone()]).remove(0);
|
||||||
|
|
||||||
self.toplevel_list.push(Toplevel {
|
self.toplevel_list.push(Toplevel {
|
||||||
toplevels: vec![(handle, info)],
|
toplevels: vec![(handle, info)],
|
||||||
app_id,
|
app_id,
|
||||||
icon_path: icon_name,
|
icon_path,
|
||||||
|
exec
|
||||||
});
|
});
|
||||||
// TODO better way of setting window size?
|
// TODO better way of setting window size?
|
||||||
let pixel_size = self.applet_helper.suggested_icon_size();
|
let pixel_size = self.applet_helper.suggested_icon_size();
|
||||||
|
|
@ -298,6 +302,20 @@ impl Application for CosmicAppList {
|
||||||
Message::RemovedSeat(_) => {
|
Message::RemovedSeat(_) => {
|
||||||
self.seat.take();
|
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()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
@ -315,6 +333,7 @@ impl Application for CosmicAppList {
|
||||||
toplevels,
|
toplevels,
|
||||||
app_id,
|
app_id,
|
||||||
icon_path,
|
icon_path,
|
||||||
|
exec,
|
||||||
},
|
},
|
||||||
)| {
|
)| {
|
||||||
let icon = if icon_path.extension() == Some(&OsStr::new("svg")) {
|
let icon = if icon_path.extension() == Some(&OsStr::new("svg")) {
|
||||||
|
|
@ -371,7 +390,7 @@ impl Application for CosmicAppList {
|
||||||
// TODO tooltip on hover
|
// TODO tooltip on hover
|
||||||
let icon_button = cosmic::widget::button(Button::Text)
|
let icon_button = cosmic::widget::button(Button::Text)
|
||||||
.custom(vec![icon_wrapper])
|
.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)
|
.padding(8)
|
||||||
.into();
|
.into();
|
||||||
if self.config.favorites.contains(&app_id) {
|
if self.config.favorites.contains(&app_id) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue