chore: latest iced
All checks were successful
build / test-debian (push) Successful in 2m29s
build / test-alpine (push) Successful in 5m35s

This commit is contained in:
user0-07161 2026-02-11 20:27:41 +01:00
parent 25c89a270e
commit 99028d0605
3 changed files with 1545 additions and 1008 deletions

2400
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -5,13 +5,14 @@ edition = "2024"
[dependencies]
anyhow = "1.0.98"
async-trait = "0.1.88"
async-trait = "0.1.89"
freedesktop-icons = "0.4.0"
futures = "0.3.31"
iced = { version = "0.13.1", features = [ "image", "tokio", "svg", "async-std" ] }
iced_layershell = "0.13.7"
iced = { version = "0.14.0", features = [ "image", "tokio", "svg" ] }
iced_layershell = "0.14.2"
once_cell = "1.21.3"
tokio = { version = "1.47.1", features = ["full"] }
tracing-subscriber = "0.3.22"
wayrs-client = { version = "1.3.1", features = [ "tokio" ] }
wayrs-protocols = { version = "0.14.11", features = [ "wlr-foreign-toplevel-management-unstable-v1" ] }
wayrs-utils = { version = "0.17.2", features = [ "seats" ] }

View file

@ -1,37 +1,60 @@
mod toplevels;
use iced::border::Radius;
use iced::widget::image::Handle;
use iced::widget::scrollable::Scroller;
use iced::widget::{Column, Image, button, column, container, row, scrollable, stack, svg, text};
use iced::{
Alignment, Background, Border, Color, Element, Event, Font, Shadow, Task, Theme, event, exit,
};
use iced_layershell::Application;
use iced_layershell::reexport::{Anchor, Layer};
use iced_layershell::settings::{LayerShellSettings, Settings, StartMode};
use iced_layershell::to_layer_message;
use freedesktop_icons::lookup;
use iced::{
Alignment, Background, Border, Color, Element, Font, Shadow, Task, Theme,
border::Radius,
exit,
theme::Style,
widget::{
self, Column, Image, button, column, container,
image::Handle,
row,
scrollable::{self, Scroller},
stack, svg, text,
},
};
use iced_layershell::{
application,
reexport::{Anchor, Layer},
settings::{LayerShellSettings, Settings, StartMode},
to_layer_message,
};
use once_cell::sync::Lazy;
use tokio::runtime::Runtime;
use tracing_subscriber;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::sync::Mutex;
use std::{collections::HashMap, ffi::OsStr, sync::Mutex};
use anyhow::Result;
use crate::toplevels::{Backend, Toplevel, WlrToplevelManagement, ZwlrForeignToplevelHandleV1};
mod toplevels;
static MANAGER: Lazy<Mutex<Option<WlrToplevelManagement>>> = Lazy::new(|| Mutex::new(None));
pub fn main() -> Result<(), iced_layershell::Error> {
pub fn main() -> Result<(), anyhow::Error> {
tracing_subscriber::fmt::init();
let bound_output_name = std::env::args().nth(1);
let start_mode = match bound_output_name {
Some(output) => StartMode::TargetScreen(output),
None => StartMode::Active,
};
Recents::run(Settings {
application(
|| {
let mut honeycomb_recents = HoneycombRecents::default();
let tokio_rt = Runtime::new().unwrap();
honeycomb_recents.toplevels = tokio_rt.block_on(list_toplevels()).unwrap();
honeycomb_recents
},
HoneycombRecents::namespace,
HoneycombRecents::update,
HoneycombRecents::view,
)
.settings(Settings {
layer_settings: LayerShellSettings {
size: Some((0, 0)),
exclusive_zone: 0,
@ -42,53 +65,48 @@ pub fn main() -> Result<(), iced_layershell::Error> {
},
..Default::default()
})
.style(HoneycombRecents::style)
.run()?;
Ok(())
}
struct Recents {
struct HoneycombRecents {
toplevels: HashMap<ZwlrForeignToplevelHandleV1, Toplevel>,
selected_toplevel: Option<ZwlrForeignToplevelHandleV1>,
recents_default: Handle,
recents_pressed: Handle,
}
#[to_layer_message]
#[derive(Clone, Debug)]
#[allow(dead_code)]
enum Message {
IcedEvent(Event),
ToplevelsListed(Option<HashMap<ZwlrForeignToplevelHandleV1, Toplevel>>),
ToplevelSelected(ZwlrForeignToplevelHandleV1),
}
impl Application for Recents {
type Message = Message;
type Flags = ();
type Theme = Theme;
type Executor = iced::executor::Default;
fn new(_flags: ()) -> (Self, Task<Message>) {
(
impl HoneycombRecents {
fn default() -> Self {
Self {
toplevels: HashMap::new(),
selected_toplevel: None,
},
Task::perform(list_toplevels(), Message::ToplevelsListed),
)
recents_default: Handle::from_bytes(
include_bytes!("res/recents_thumbnail_bg.png") as &[u8]
),
recents_pressed: Handle::from_bytes(
include_bytes!("res/recents_thumbnail_bg_press.png") as &[u8],
),
}
}
fn namespace(&self) -> String {
String::from("project honeycomb - recents")
}
fn subscription(&self) -> iced::Subscription<Self::Message> {
iced::Subscription::batch(vec![event::listen().map(Message::IcedEvent)])
fn namespace() -> String {
String::from("honeycomb recents")
}
fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::ToplevelsListed(Some(toplevels)) => {
self.toplevels = toplevels;
Task::none()
}
Message::ToplevelSelected(toplevel) => {
self.selected_toplevel = Some(toplevel);
let mut mgr = MANAGER.lock().unwrap();
@ -98,17 +116,13 @@ impl Application for Recents {
exit()
}
Message::IcedEvent(e) => {
println!("{e:#?}");
Task::none()
}
_ => Task::none(),
}
}
fn view(&self) -> Element<'_, Message> {
let mut column = Column::new();
for (toplevel, info) in self.toplevels.clone() {
let title = info
.title
@ -123,16 +137,14 @@ impl Application for Recents {
.collect::<Vec<String>>()
.join("\n");
let mut img = if Some(toplevel) != self.selected_toplevel {
stack!(Image::new(Handle::from_bytes(
include_bytes!("res/recents_thumbnail_bg.png") as &[u8]
)))
let image = if Some(toplevel) != self.selected_toplevel {
&self.recents_default
} else {
stack!(Image::new(Handle::from_bytes(include_bytes!(
"res/recents_thumbnail_bg_press.png"
) as &[u8])))
&self.recents_pressed
};
let mut img = stack!(Image::new(image.clone()).width(245).height(144));
if let Some(id) = info.app_id {
if let Some(icon) = lookup(&id).find() {
if icon.extension() == Some(OsStr::new("svg")) {
@ -157,14 +169,13 @@ impl Application for Recents {
));
}
scrollable(column.spacing(50))
widget::scrollable(column.spacing(50))
.style(transparent_scrollbar)
.into()
}
fn style(&self, _: &Self::Theme) -> iced_layershell::Appearance {
use iced_layershell::Appearance;
Appearance {
fn style(&self, _: &Theme) -> Style {
Style {
background_color: Color {
r: 0.0,
g: 0.0,
@ -178,8 +189,8 @@ impl Application for Recents {
async fn list_toplevels() -> Option<HashMap<ZwlrForeignToplevelHandleV1, Toplevel>> {
let mut mgr = MANAGER.lock().unwrap();
*mgr = futures::executor::block_on(WlrToplevelManagement::new()).ok();
match futures::executor::block_on(mgr.as_mut()?.get_info()).ok() {
*mgr = WlrToplevelManagement::new().await.ok();
match mgr.as_mut()?.get_info().await.ok() {
Some(info) => return Some(info.toplevels),
None => return None,
}
@ -195,8 +206,8 @@ fn transparent_scrollbar(_: &Theme, _: scrollable::Status) -> scrollable::Style
background: Some(Background::Color(Color::TRANSPARENT)),
border: empty_border.clone(),
scroller: Scroller {
color: Color::TRANSPARENT,
border: empty_border.clone(),
background: Background::Color(Color::TRANSPARENT),
},
};
@ -205,6 +216,12 @@ fn transparent_scrollbar(_: &Theme, _: scrollable::Status) -> scrollable::Style
vertical_rail: rail.clone(),
horizontal_rail: rail.clone(),
gap: Some(Background::Color(Color::TRANSPARENT)),
auto_scroll: scrollable::AutoScroll {
background: Background::Color(Color::TRANSPARENT),
border: empty_border.clone(),
shadow: Shadow::default(),
icon: Color::TRANSPARENT,
},
}
}
@ -214,5 +231,6 @@ pub fn transparent_button(_: &Theme, _: button::Status) -> button::Style {
text_color: Color::WHITE,
border: Border::default(),
shadow: Shadow::default(),
snap: false,
}
}