mirror of
https://github.com/Noratrieb/colouncher.git
synced 2026-03-14 21:26:10 +01:00
cleanup
This commit is contained in:
parent
bee16cced1
commit
eaaa474eb5
2 changed files with 49 additions and 13 deletions
|
|
@ -1,8 +1,36 @@
|
||||||
use eyre::{Context, Result};
|
use eyre::{Context, Result};
|
||||||
use freedesktop_file_parser::{DesktopFile, EntryType};
|
use freedesktop_file_parser::{DesktopFile, EntryType};
|
||||||
use palette::{IntoColor, Oklab, Oklaba};
|
use palette::{IntoColor, Oklab, Oklaba, color_difference::EuclideanDistance};
|
||||||
use std::{collections::HashMap, ffi::OsStr, fs::DirEntry, path::Path};
|
use std::{collections::HashMap, ffi::OsStr, fs::DirEntry, path::Path};
|
||||||
|
|
||||||
|
pub struct DesktopEntries {
|
||||||
|
entries: Vec<DesktopEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DesktopEntry {
|
||||||
|
pub _id: String,
|
||||||
|
pub file: DesktopFile,
|
||||||
|
pub avg_icon_color: Oklab,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DesktopEntries {
|
||||||
|
pub fn count(&self) -> usize {
|
||||||
|
self.entries.len()
|
||||||
|
}
|
||||||
|
pub fn find_entry(&self, color: Oklab) -> Option<&DesktopEntry> {
|
||||||
|
self.entries.iter().min_by(|x, y| {
|
||||||
|
f32::total_cmp(
|
||||||
|
&diff_color(x.avg_icon_color, color),
|
||||||
|
&diff_color(y.avg_icon_color, color),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn diff_color(icon: Oklab, color: Oklab) -> f32 {
|
||||||
|
icon.distance_squared(color)
|
||||||
|
}
|
||||||
|
|
||||||
fn walkdir(path: &Path, f: &mut impl FnMut(&DirEntry) -> Result<()>) -> Result<()> {
|
fn walkdir(path: &Path, f: &mut impl FnMut(&DirEntry) -> Result<()>) -> Result<()> {
|
||||||
for entry in path.read_dir()? {
|
for entry in path.read_dir()? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
|
|
@ -14,7 +42,7 @@ fn walkdir(path: &Path, f: &mut impl FnMut(&DirEntry) -> Result<()>) -> Result<(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn find_desktop_files() -> Result<Vec<(DesktopFile, Oklab)>> {
|
pub(crate) fn find_desktop_files() -> Result<DesktopEntries> {
|
||||||
// https://specifications.freedesktop.org/desktop-entry/latest/file-naming.html
|
// https://specifications.freedesktop.org/desktop-entry/latest/file-naming.html
|
||||||
let paths = std::env::var("XDG_DATA_DIRS").unwrap_or("/usr/local/share/:/usr/share/".into());
|
let paths = std::env::var("XDG_DATA_DIRS").unwrap_or("/usr/local/share/:/usr/share/".into());
|
||||||
let paths = std::env::split_paths(&paths);
|
let paths = std::env::split_paths(&paths);
|
||||||
|
|
@ -55,7 +83,14 @@ pub(crate) fn find_desktop_files() -> Result<Vec<(DesktopFile, Oklab)>> {
|
||||||
.decode()
|
.decode()
|
||||||
.wrap_err_with(|| format!("decoding {}", icon.display()))?;
|
.wrap_err_with(|| format!("decoding {}", icon.display()))?;
|
||||||
let color = average_color(&icon);
|
let color = average_color(&icon);
|
||||||
results.insert(id, (file, color));
|
results.insert(
|
||||||
|
id.clone(),
|
||||||
|
DesktopEntry {
|
||||||
|
_id: id,
|
||||||
|
file,
|
||||||
|
avg_icon_color: color,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -63,7 +98,9 @@ pub(crate) fn find_desktop_files() -> Result<Vec<(DesktopFile, Oklab)>> {
|
||||||
.wrap_err_with(|| format!("{}", base.display()))?;
|
.wrap_err_with(|| format!("{}", base.display()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(results.into_values().collect())
|
Ok(DesktopEntries {
|
||||||
|
entries: results.into_values().collect(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn average_color(image: &image::DynamicImage) -> palette::Oklab {
|
fn average_color(image: &image::DynamicImage) -> palette::Oklab {
|
||||||
|
|
|
||||||
17
src/main.rs
17
src/main.rs
|
|
@ -6,9 +6,9 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use eyre::{Context, Result, bail};
|
use eyre::{Context, Result, bail};
|
||||||
use freedesktop_file_parser::{DesktopFile, EntryType};
|
use freedesktop_file_parser::EntryType;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use palette::{FromColor, IntoColor, Oklab, color_difference::EuclideanDistance};
|
use palette::{FromColor, IntoColor, Oklab};
|
||||||
use smithay_client_toolkit::{
|
use smithay_client_toolkit::{
|
||||||
compositor::{CompositorHandler, CompositorState},
|
compositor::{CompositorHandler, CompositorState},
|
||||||
output::{OutputHandler, OutputState},
|
output::{OutputHandler, OutputState},
|
||||||
|
|
@ -33,6 +33,8 @@ use wayland_client::{
|
||||||
protocol::{wl_buffer, wl_output::WlOutput, wl_pointer::WlPointer, wl_seat::WlSeat, wl_shm},
|
protocol::{wl_buffer, wl_output::WlOutput, wl_pointer::WlPointer, wl_seat::WlSeat, wl_shm},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::desktop::DesktopEntries;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
env_logger::builder()
|
env_logger::builder()
|
||||||
.filter(None, log::LevelFilter::Info)
|
.filter(None, log::LevelFilter::Info)
|
||||||
|
|
@ -42,7 +44,7 @@ fn main() -> Result<()> {
|
||||||
let desktop_files = desktop::find_desktop_files().wrap_err("loading .desktop files")?;
|
let desktop_files = desktop::find_desktop_files().wrap_err("loading .desktop files")?;
|
||||||
info!(
|
info!(
|
||||||
"Loaded {} desktop icons in {:?}",
|
"Loaded {} desktop icons in {:?}",
|
||||||
desktop_files.len(),
|
desktop_files.count(),
|
||||||
now.elapsed()
|
now.elapsed()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -89,7 +91,7 @@ struct App {
|
||||||
shm: Shm,
|
shm: Shm,
|
||||||
seat_state: SeatState,
|
seat_state: SeatState,
|
||||||
|
|
||||||
desktop_files: Vec<(DesktopFile, Oklab)>,
|
desktop_files: DesktopEntries,
|
||||||
pointers: HashMap<WlSeat, WlPointer>,
|
pointers: HashMap<WlSeat, WlPointer>,
|
||||||
layer_surfaces: Vec<OutputSurface>,
|
layer_surfaces: Vec<OutputSurface>,
|
||||||
}
|
}
|
||||||
|
|
@ -400,13 +402,10 @@ impl PointerHandler for App {
|
||||||
|
|
||||||
let oklab: Oklab = srgb.into_format::<f32>().into_color();
|
let oklab: Oklab = srgb.into_format::<f32>().into_color();
|
||||||
|
|
||||||
let best_match = self
|
let best_match = self.desktop_files.find_entry(oklab);
|
||||||
.desktop_files
|
|
||||||
.iter()
|
|
||||||
.min_by_key(|(_, icon_color)| (oklab.distance(*icon_color) * 1000000.0) as u32);
|
|
||||||
|
|
||||||
if let Some(best_match) = best_match
|
if let Some(best_match) = best_match
|
||||||
&& let EntryType::Application(app) = &best_match.0.entry.entry_type
|
&& let EntryType::Application(app) = &best_match.file.entry.entry_type
|
||||||
&& let Some(exec) = &app.exec
|
&& let Some(exec) = &app.exec
|
||||||
{
|
{
|
||||||
// lol terrible implementation that works well enough
|
// lol terrible implementation that works well enough
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue