Skip to content

Commit

Permalink
fix(perf): fill in desktop entry paths at the beginning of execution
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Brue <ryanbrue.dev@gmail.com>
  • Loading branch information
ryanabx committed Sep 17, 2024
1 parent 9fa3e3e commit a118f15
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 63 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ readme = "README.md"
freedesktop-desktop-entry = "0.6.2"
freedesktop-icons = "0.2.6"
iced = { git = "https://github.com/iced-rs/iced", branch = "master", features = [ "tiny-skia", "image", "svg", "fira-sans" ] }
# iced = { git = "https://github.com/ryanabx/iced", branch = "iced-rbshell", features = [ "wayland", "tiny-skia", "image", "svg", "fira-sans", "auto-detect-theme" ] }
# iced = { git = "https://github.com/ryanabx-contrib/iced", branch = "iced-rbshell", features = [ "wayland", "tiny-skia", "image", "svg", "fira-sans", "auto-detect-theme" ] }
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "c8d3a1c" }
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", default-features = false, features = [
"client",
Expand Down
43 changes: 21 additions & 22 deletions src/app_tray/compositor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ fn wayland_client_listener(tx: UnboundedSender<WaylandIncoming>, rx: Channel<Way
// Retrieve the WlDisplay Wayland object from the connection. This object is
// the starting point of any Wayland program, from which all other objects will
// be created.
let display = conn.display();
let _display = conn.display();

// Create an event queue for our event processing

Expand All @@ -486,25 +486,25 @@ fn wayland_client_listener(tx: UnboundedSender<WaylandIncoming>, rx: Channel<Way
log::trace!("WaylandRequest: {:?}", req);
match req {
WaylandRequest::Toplevel(req) => match req {
WaylandToplevelRequest::Activate(handle) => {
WaylandToplevelRequest::Activate(_handle) => {
// if let Some(seat) = state.seat_state.seats().next() {
// let manager = &state.toplevel_manager_state.manager;
// manager.activate(&handle, &seat);
// }
}
WaylandToplevelRequest::Minimize(handle) => {
WaylandToplevelRequest::Minimize(_handle) => {
// let manager = &state.toplevel_manager_state.manager;
// manager.set_minimized(&handle);
}
WaylandToplevelRequest::Quit(handle) => {
WaylandToplevelRequest::Quit(_handle) => {
// let manager = &state.toplevel_manager_state.manager;
// manager.close(&handle);
}
},
WaylandRequest::TokenRequest {
app_id,
exec,
gpu_idx,
app_id: _,
exec: _,
gpu_idx: _,
} => {
// if let Some(activation_state) = state.activation_state.as_ref() {
// let seat_and_serial = state.seat_state.seats().next().map(|seat| (seat, 0));
Expand Down Expand Up @@ -547,20 +547,20 @@ fn wayland_client_listener(tx: UnboundedSender<WaylandIncoming>, rx: Channel<Way
});

// now you can bind the globals you need for your app
let zwlr_toplevel_manager = match globals
.bind::<zwlr_foreign_toplevel_manager_v1::ZwlrForeignToplevelManagerV1, _, _>(
&qh,
3..=3,
(),
) {
Ok(manager) => Some(manager),
Err(e) => {
log::warn!("Wlroots toplevel manager could not be bound: {}", e);
None
}
};
let _zwlr_toplevel_manager =
match globals.bind::<zwlr_foreign_toplevel_manager_v1::ZwlrForeignToplevelManagerV1, _, _>(
&qh,
3..=3,
(),
) {
Ok(manager) => Some(manager),
Err(e) => {
log::warn!("Wlroots toplevel manager could not be bound: {}", e);
None
}
};

let zcosmic_toplevel_manager = match globals
let _zcosmic_toplevel_manager = match globals
.bind::<zcosmic_toplevel_info_v1::ZcosmicToplevelInfoV1, _, _>(&qh, 1..=1, ())
{
Ok(manager) => Some(manager),
Expand All @@ -570,7 +570,7 @@ fn wayland_client_listener(tx: UnboundedSender<WaylandIncoming>, rx: Channel<Way
}
};

let kde_window_manager = match globals
let _kde_window_manager = match globals
.bind::<org_kde_plasma_window_management::OrgKdePlasmaWindowManagement, _, _>(
&qh,
15..=16,
Expand Down Expand Up @@ -866,7 +866,6 @@ impl CompositorBackend {
None
}
},
_ => todo!("Not implemented"),
}
}

Expand Down
24 changes: 11 additions & 13 deletions src/app_tray/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ use cctk::wayland_client::protocol::wl_seat::WlSeat;
use compositor::{
CompositorBackend, CompositorToplevelInfo, ToplevelHandle, WaylandIncoming, WaylandOutgoing,
};
use freedesktop_desktop_entry::DesktopEntry;
use iced::{
widget::{column, Container},
window::Id,
Element, Length, Task, Theme,
};

use crate::{component_theme::button_style, config::AppTrayConfig};
use crate::{component_theme::button_style, config::AppTrayConfig, desktop_entry::EntryInfo};

pub mod compositor;

Expand Down Expand Up @@ -120,16 +119,13 @@ impl<'a> AppTray<'a> {
fn view_tray_item(
&self,
app_id: &str,
desktop_entry: Option<&DesktopEntry<'a>>,
entry: Option<&EntryInfo<'a>>,
app_info: HashMap<ToplevelHandle, CompositorToplevelInfo>,
active_window: Option<ToplevelHandle>,
) -> iced::widget::MouseArea<'a, AppTrayMessage> {
let is_active = active_window.is_some_and(|window| app_info.contains_key(&window));
let num_toplevels = app_info.len();
let icon_name = desktop_entry.and_then(|entry| entry.icon());
let icon_path = icon_name
.and_then(|icon| freedesktop_icons::lookup(icon).with_cache().find())
.or_else(get_default_icon);
let icon_path = entry.and_then(|e| e.icon_path.as_deref());
iced::widget::mouse_area(
match icon_path {
Some(path) => iced::widget::button(column![
Expand All @@ -145,12 +141,14 @@ impl<'a> AppTray<'a> {
.height(Length::Fill)
.padding(4)
.on_press_maybe(if num_toplevels == 0 {
desktop_entry.and_then(|entry| entry.exec()).map(|exec| {
AppTrayMessage::WaylandOut(WaylandOutgoing::Exec(
app_id.to_string(),
exec.to_string(),
))
})
entry
.and_then(|entry| entry.desktop_entry.exec())
.map(|exec| {
AppTrayMessage::WaylandOut(WaylandOutgoing::Exec(
app_id.to_string(),
exec.to_string(),
))
})
} else if num_toplevels == 1 {
Some(AppTrayMessage::WaylandOut(WaylandOutgoing::Toggle(
app_info.keys().next().unwrap().clone(),
Expand Down
78 changes: 70 additions & 8 deletions src/desktop_entry.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,69 @@
use std::collections::HashMap;
use std::{collections::HashMap, path::PathBuf};

use freedesktop_desktop_entry::{
default_paths, get_languages_from_env, DesktopEntry, Iter, Locale, PathSource,
};

#[derive(Clone, Debug)]
pub struct DesktopEntryCache<'a>(pub HashMap<String, DesktopEntry<'a>>);
pub struct DesktopEntryCache<'a>(pub HashMap<String, EntryInfo<'a>>);

#[derive(Clone, Debug)]
pub struct EntryInfo<'a> {
pub desktop_entry: DesktopEntry<'a>,
pub icon_path: Option<PathBuf>,
}

impl<'a> EntryInfo<'a> {
pub fn new(desktop_entry: DesktopEntry<'a>) -> Self {
let icon_path = desktop_entry.icon().and_then(|icon| {
freedesktop_icons::lookup(icon)
.force_svg()
.with_cache()
.find()
.or_else(|| {
freedesktop_icons::lookup(icon)
.with_size(512)
.with_cache()
.find()
})
.or_else(|| {
freedesktop_icons::lookup(icon)
.with_size(256)
.with_cache()
.find()
})
.or_else(|| {
freedesktop_icons::lookup(icon)
.with_size(128)
.with_cache()
.find()
})
.or_else(|| {
freedesktop_icons::lookup(icon)
.with_size(96)
.with_cache()
.find()
})
.or_else(|| {
freedesktop_icons::lookup(icon)
.with_size(64)
.with_cache()
.find()
})
.or_else(|| {
freedesktop_icons::lookup(icon)
.with_size(48)
.with_cache()
.find()
})
.or_else(|| freedesktop_icons::lookup(icon).with_cache().find())
});
Self {
desktop_entry,
icon_path,
}
}
}

impl<'a> Default for DesktopEntryCache<'a> {
fn default() -> Self {
Expand All @@ -22,29 +80,33 @@ impl<'a> DesktopEntryCache<'a> {
let path_src = PathSource::guess_from(&path);
if let Ok(entry) = DesktopEntry::from_path(path.clone(), &locales) {
log::debug!("{:?}::{}", path_src, &entry.appid);
return Some((entry.appid.to_string(), entry));
return Some((entry.appid.to_string(), EntryInfo::new(entry)));
}
None
})
.collect::<HashMap<String, _>>();
Self(entries)
}

pub fn fuzzy_match(&self, pattern: &str) -> Option<DesktopEntry<'a>> {
pub fn fuzzy_match(&self, pattern: &str) -> Option<EntryInfo<'a>> {
self.0
.get(pattern)
.or_else(|| {
self.0.values().find(|entry| {
// log::debug!("entry: {}", entry.appid);
entry.startup_wm_class().is_some_and(|wm_class| {
// log::trace!("Fuzzy matching wm class {} == {}", wm_class, pattern);
wm_class == pattern
})
entry
.desktop_entry
.startup_wm_class()
.is_some_and(|wm_class| {
// log::trace!("Fuzzy matching wm class {} == {}", wm_class, pattern);
wm_class == pattern
})
})
})
.or_else(|| {
self.0.values().find(|entry| {
entry
.desktop_entry
.name(&[Locale::default()])
.is_some_and(|name| name == pattern)
})
Expand Down
4 changes: 2 additions & 2 deletions src/panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use iced::{
border::Radius,
widget::{column, row, text},
window::{self, Settings},
Element, Length, Padding, Subscription, Task, Theme,
Element, Length, Padding, Size, Subscription, Task, Theme,
};

use crate::{
Expand All @@ -15,7 +15,6 @@ use crate::{
start_menu::{StartMenu, StartMenuMessage},
};

#[derive(Clone, Debug)]
pub struct Panel<'a> {
start_menu: StartMenu<'a>,
app_tray: AppTray<'a>,
Expand Down Expand Up @@ -60,6 +59,7 @@ impl<'a> Panel<'a> {
log::warn!("Start menu toggle!!");
let (_, task) = window::open(Settings {
position: window::Position::Centered,
size: Size::new(240.0, 480.0),
..Default::default()
});
task.map(move |i| Message::OpenPopup(i, PopupType::StartMenu))
Expand Down
41 changes: 24 additions & 17 deletions src/start_menu/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::rc::Rc;

use freedesktop_desktop_entry::{get_languages_from_env, DesktopEntry};
use freedesktop_desktop_entry::get_languages_from_env;
use iced::{
border::Radius,
widget::{
Expand All @@ -12,7 +12,9 @@ use iced::{
};

use crate::{
component_theme::button_style, components::app_icon, desktop_entry::DesktopEntryCache,
component_theme::button_style,
components::app_icon,
desktop_entry::{DesktopEntryCache, EntryInfo},
};

#[derive(Clone, Debug)]
Expand All @@ -21,9 +23,8 @@ pub enum StartMenuMessage {
Launch(String),
}

#[derive(Clone, Debug)]
pub struct StartMenu<'a> {
de_cache: Rc<DesktopEntryCache<'a>>,
pub de_cache: Rc<DesktopEntryCache<'a>>,
}

impl<'a> StartMenu<'a> {
Expand Down Expand Up @@ -92,24 +93,25 @@ impl<'a> StartMenu<'a> {
.width(Length::Fill)
.into()
}

pub fn populate_menu_items(&mut self) {}
}

fn view_menu_item<'a>(
desktop_entry: &DesktopEntry<'a>,
) -> Option<iced::Element<'a, StartMenuMessage>> {
if desktop_entry.no_display()
|| desktop_entry.name(&get_languages_from_env()).is_none()
|| desktop_entry.terminal()
|| desktop_entry.exec().is_none()
fn view_menu_item<'a>(entry: &EntryInfo<'a>) -> Option<iced::Element<'a, StartMenuMessage>> {
if entry.desktop_entry.no_display()
|| entry
.desktop_entry
.name(&get_languages_from_env())
.is_none()
|| entry.desktop_entry.terminal()
|| entry.desktop_entry.exec().is_none()
{
return None;
}
let icon_path = desktop_entry
.icon()
.and_then(|icon| freedesktop_icons::lookup(icon).with_cache().find());

Some(
iced::widget::button(row![
iced::widget::container(match icon_path {
iced::widget::container(match &entry.icon_path {
Some(path) => {
app_icon(&path)
}
Expand All @@ -120,10 +122,15 @@ fn view_menu_item<'a>(
})
.width(32)
.height(32),
text!("{}", desktop_entry.name(&get_languages_from_env()).unwrap()),
text!(
"{}",
entry.desktop_entry.name(&get_languages_from_env()).unwrap()
),
])
.style(|theme, status| button_style(theme, status, false, 0))
.on_press(StartMenuMessage::Launch(desktop_entry.appid.to_string()))
.on_press(StartMenuMessage::Launch(
entry.desktop_entry.appid.to_string(),
))
.width(Length::Fill)
.into(),
)
Expand Down

0 comments on commit a118f15

Please sign in to comment.