chore: latest iced
This commit is contained in:
parent
25c89a270e
commit
99028d0605
3 changed files with 1545 additions and 1008 deletions
2400
Cargo.lock
generated
2400
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -5,13 +5,14 @@ edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.98"
|
anyhow = "1.0.98"
|
||||||
async-trait = "0.1.88"
|
async-trait = "0.1.89"
|
||||||
freedesktop-icons = "0.4.0"
|
freedesktop-icons = "0.4.0"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
iced = { version = "0.13.1", features = [ "image", "tokio", "svg", "async-std" ] }
|
iced = { version = "0.14.0", features = [ "image", "tokio", "svg" ] }
|
||||||
iced_layershell = "0.13.7"
|
iced_layershell = "0.14.2"
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
tokio = { version = "1.47.1", features = ["full"] }
|
tokio = { version = "1.47.1", features = ["full"] }
|
||||||
|
tracing-subscriber = "0.3.22"
|
||||||
wayrs-client = { version = "1.3.1", features = [ "tokio" ] }
|
wayrs-client = { version = "1.3.1", features = [ "tokio" ] }
|
||||||
wayrs-protocols = { version = "0.14.11", features = [ "wlr-foreign-toplevel-management-unstable-v1" ] }
|
wayrs-protocols = { version = "0.14.11", features = [ "wlr-foreign-toplevel-management-unstable-v1" ] }
|
||||||
wayrs-utils = { version = "0.17.2", features = [ "seats" ] }
|
wayrs-utils = { version = "0.17.2", features = [ "seats" ] }
|
||||||
|
|
|
||||||
146
src/main.rs
146
src/main.rs
|
|
@ -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 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 once_cell::sync::Lazy;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use tracing_subscriber;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, ffi::OsStr, sync::Mutex};
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::toplevels::{Backend, Toplevel, WlrToplevelManagement, ZwlrForeignToplevelHandleV1};
|
use crate::toplevels::{Backend, Toplevel, WlrToplevelManagement, ZwlrForeignToplevelHandleV1};
|
||||||
|
|
||||||
|
mod toplevels;
|
||||||
|
|
||||||
static MANAGER: Lazy<Mutex<Option<WlrToplevelManagement>>> = Lazy::new(|| Mutex::new(None));
|
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 bound_output_name = std::env::args().nth(1);
|
||||||
let start_mode = match bound_output_name {
|
let start_mode = match bound_output_name {
|
||||||
Some(output) => StartMode::TargetScreen(output),
|
Some(output) => StartMode::TargetScreen(output),
|
||||||
None => StartMode::Active,
|
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 {
|
layer_settings: LayerShellSettings {
|
||||||
size: Some((0, 0)),
|
size: Some((0, 0)),
|
||||||
exclusive_zone: 0,
|
exclusive_zone: 0,
|
||||||
|
|
@ -42,53 +65,48 @@ pub fn main() -> Result<(), iced_layershell::Error> {
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
.style(HoneycombRecents::style)
|
||||||
|
.run()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Recents {
|
struct HoneycombRecents {
|
||||||
toplevels: HashMap<ZwlrForeignToplevelHandleV1, Toplevel>,
|
toplevels: HashMap<ZwlrForeignToplevelHandleV1, Toplevel>,
|
||||||
selected_toplevel: Option<ZwlrForeignToplevelHandleV1>,
|
selected_toplevel: Option<ZwlrForeignToplevelHandleV1>,
|
||||||
|
|
||||||
|
recents_default: Handle,
|
||||||
|
recents_pressed: Handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[to_layer_message]
|
#[to_layer_message]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
enum Message {
|
enum Message {
|
||||||
IcedEvent(Event),
|
|
||||||
ToplevelsListed(Option<HashMap<ZwlrForeignToplevelHandleV1, Toplevel>>),
|
|
||||||
ToplevelSelected(ZwlrForeignToplevelHandleV1),
|
ToplevelSelected(ZwlrForeignToplevelHandleV1),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Recents {
|
impl HoneycombRecents {
|
||||||
type Message = Message;
|
fn default() -> Self {
|
||||||
type Flags = ();
|
Self {
|
||||||
type Theme = Theme;
|
toplevels: HashMap::new(),
|
||||||
type Executor = iced::executor::Default;
|
selected_toplevel: None,
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Task<Message>) {
|
recents_default: Handle::from_bytes(
|
||||||
(
|
include_bytes!("res/recents_thumbnail_bg.png") as &[u8]
|
||||||
Self {
|
),
|
||||||
toplevels: HashMap::new(),
|
recents_pressed: Handle::from_bytes(
|
||||||
selected_toplevel: None,
|
include_bytes!("res/recents_thumbnail_bg_press.png") as &[u8],
|
||||||
},
|
),
|
||||||
Task::perform(list_toplevels(), Message::ToplevelsListed),
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn namespace(&self) -> String {
|
fn namespace() -> String {
|
||||||
String::from("project honeycomb - recents")
|
String::from("honeycomb recents")
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> iced::Subscription<Self::Message> {
|
|
||||||
iced::Subscription::batch(vec![event::listen().map(Message::IcedEvent)])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Task<Message> {
|
fn update(&mut self, message: Message) -> Task<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::ToplevelsListed(Some(toplevels)) => {
|
|
||||||
self.toplevels = toplevels;
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
|
|
||||||
Message::ToplevelSelected(toplevel) => {
|
Message::ToplevelSelected(toplevel) => {
|
||||||
self.selected_toplevel = Some(toplevel);
|
self.selected_toplevel = Some(toplevel);
|
||||||
let mut mgr = MANAGER.lock().unwrap();
|
let mut mgr = MANAGER.lock().unwrap();
|
||||||
|
|
@ -98,17 +116,13 @@ impl Application for Recents {
|
||||||
exit()
|
exit()
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::IcedEvent(e) => {
|
|
||||||
println!("{e:#?}");
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => Task::none(),
|
_ => Task::none(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<'_, Message> {
|
fn view(&self) -> Element<'_, Message> {
|
||||||
let mut column = Column::new();
|
let mut column = Column::new();
|
||||||
|
|
||||||
for (toplevel, info) in self.toplevels.clone() {
|
for (toplevel, info) in self.toplevels.clone() {
|
||||||
let title = info
|
let title = info
|
||||||
.title
|
.title
|
||||||
|
|
@ -123,16 +137,14 @@ impl Application for Recents {
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
let mut img = if Some(toplevel) != self.selected_toplevel {
|
let image = if Some(toplevel) != self.selected_toplevel {
|
||||||
stack!(Image::new(Handle::from_bytes(
|
&self.recents_default
|
||||||
include_bytes!("res/recents_thumbnail_bg.png") as &[u8]
|
|
||||||
)))
|
|
||||||
} else {
|
} else {
|
||||||
stack!(Image::new(Handle::from_bytes(include_bytes!(
|
&self.recents_pressed
|
||||||
"res/recents_thumbnail_bg_press.png"
|
|
||||||
) as &[u8])))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut img = stack!(Image::new(image.clone()).width(245).height(144));
|
||||||
|
|
||||||
if let Some(id) = info.app_id {
|
if let Some(id) = info.app_id {
|
||||||
if let Some(icon) = lookup(&id).find() {
|
if let Some(icon) = lookup(&id).find() {
|
||||||
if icon.extension() == Some(OsStr::new("svg")) {
|
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)
|
.style(transparent_scrollbar)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self, _: &Self::Theme) -> iced_layershell::Appearance {
|
fn style(&self, _: &Theme) -> Style {
|
||||||
use iced_layershell::Appearance;
|
Style {
|
||||||
Appearance {
|
|
||||||
background_color: Color {
|
background_color: Color {
|
||||||
r: 0.0,
|
r: 0.0,
|
||||||
g: 0.0,
|
g: 0.0,
|
||||||
|
|
@ -178,8 +189,8 @@ impl Application for Recents {
|
||||||
|
|
||||||
async fn list_toplevels() -> Option<HashMap<ZwlrForeignToplevelHandleV1, Toplevel>> {
|
async fn list_toplevels() -> Option<HashMap<ZwlrForeignToplevelHandleV1, Toplevel>> {
|
||||||
let mut mgr = MANAGER.lock().unwrap();
|
let mut mgr = MANAGER.lock().unwrap();
|
||||||
*mgr = futures::executor::block_on(WlrToplevelManagement::new()).ok();
|
*mgr = WlrToplevelManagement::new().await.ok();
|
||||||
match futures::executor::block_on(mgr.as_mut()?.get_info()).ok() {
|
match mgr.as_mut()?.get_info().await.ok() {
|
||||||
Some(info) => return Some(info.toplevels),
|
Some(info) => return Some(info.toplevels),
|
||||||
None => return None,
|
None => return None,
|
||||||
}
|
}
|
||||||
|
|
@ -195,8 +206,8 @@ fn transparent_scrollbar(_: &Theme, _: scrollable::Status) -> scrollable::Style
|
||||||
background: Some(Background::Color(Color::TRANSPARENT)),
|
background: Some(Background::Color(Color::TRANSPARENT)),
|
||||||
border: empty_border.clone(),
|
border: empty_border.clone(),
|
||||||
scroller: Scroller {
|
scroller: Scroller {
|
||||||
color: Color::TRANSPARENT,
|
|
||||||
border: empty_border.clone(),
|
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(),
|
vertical_rail: rail.clone(),
|
||||||
horizontal_rail: rail.clone(),
|
horizontal_rail: rail.clone(),
|
||||||
gap: Some(Background::Color(Color::TRANSPARENT)),
|
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,
|
text_color: Color::WHITE,
|
||||||
border: Border::default(),
|
border: Border::default(),
|
||||||
shadow: Shadow::default(),
|
shadow: Shadow::default(),
|
||||||
|
snap: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue