feat, chore: cleanup, make the back button work, latest iced
This commit is contained in:
parent
0e09558b1e
commit
0cd6c9e52f
4 changed files with 1520 additions and 1099 deletions
2416
Cargo.lock
generated
2416
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
10
Cargo.toml
10
Cargo.toml
|
|
@ -5,10 +5,10 @@ edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.98"
|
anyhow = "1.0.98"
|
||||||
iced = { version = "0.13.1", features = [ "image", "async-std" ] }
|
iced = { version = "0.14.0", default-features = false, features = ["tokio", "image", "wayland"] }
|
||||||
iced_layershell = "0.13.7"
|
iced_layershell = "0.14.2"
|
||||||
interprocess = "2.3.1"
|
interprocess = "2.3.1"
|
||||||
tempfile = "3.20.0"
|
tempfile = "3.25.0"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.44"
|
||||||
tracing-subscriber = "0.3.19"
|
tracing-subscriber = "0.3.22"
|
||||||
xkbcommon = "0.9.0"
|
xkbcommon = "0.9.0"
|
||||||
|
|
|
||||||
175
src/main.rs
175
src/main.rs
|
|
@ -1,22 +1,25 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
|
||||||
use iced::theme::Palette;
|
|
||||||
use iced::widget::image::{self, Handle};
|
|
||||||
use iced::widget::{Button, Text, button, horizontal_space, row, stack};
|
|
||||||
use iced::{
|
use iced::{
|
||||||
Background, Border, Color, Element, Event, Font, Shadow, Task as Command, Task, Theme, color,
|
Background, Border, Color, Element, Font, Shadow, Task as Command, Theme, color, font,
|
||||||
event, font, time,
|
theme::Palette,
|
||||||
|
time,
|
||||||
|
widget::{
|
||||||
|
Button, Text, button,
|
||||||
|
image::{self, Handle},
|
||||||
|
row,
|
||||||
|
space::horizontal as horizontal_space,
|
||||||
|
stack,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use iced_layershell::{
|
||||||
|
actions::{LayershellCustomAction, LayershellCustomActionWithId},
|
||||||
|
application,
|
||||||
|
reexport::{Anchor, KeyboardInteractivity, wl_keyboard::KeymapFormat},
|
||||||
|
settings::{LayerShellSettings, Settings, StartMode, VirtualKeyboardSettings},
|
||||||
};
|
};
|
||||||
use iced_layershell::Application;
|
|
||||||
use iced_layershell::actions::{LayershellCustomActions, LayershellCustomActionsWithId};
|
|
||||||
use iced_layershell::reexport::Anchor;
|
|
||||||
use iced_layershell::reexport::wl_keyboard::KeymapFormat;
|
|
||||||
use iced_layershell::settings::{LayerShellSettings, Settings, StartMode, VirtualKeyboardSettings};
|
|
||||||
use iced_layershell::to_layer_message;
|
|
||||||
|
|
||||||
use crate::ipc::Ipc;
|
use crate::{ipc::Ipc, xkb::get_keymap_as_file};
|
||||||
use crate::xkb::get_keymap_as_file;
|
|
||||||
|
|
||||||
mod ipc;
|
mod ipc;
|
||||||
mod xkb;
|
mod xkb;
|
||||||
|
|
@ -27,6 +30,7 @@ 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: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,12 +44,19 @@ pub fn main() -> Result<(), iced_layershell::Error> {
|
||||||
|
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
Bar::run(Settings {
|
application(
|
||||||
|
|| HoneycombBar::default(),
|
||||||
|
HoneycombBar::namespace,
|
||||||
|
HoneycombBar::update,
|
||||||
|
HoneycombBar::view,
|
||||||
|
)
|
||||||
|
.settings(Settings {
|
||||||
layer_settings: LayerShellSettings {
|
layer_settings: LayerShellSettings {
|
||||||
size: Some((0, 40)),
|
size: Some((0, 40)),
|
||||||
exclusive_zone: 40,
|
exclusive_zone: 40,
|
||||||
anchor: Anchor::Bottom | Anchor::Left | Anchor::Right,
|
anchor: Anchor::Bottom | Anchor::Left | Anchor::Right,
|
||||||
start_mode,
|
start_mode,
|
||||||
|
keyboard_interactivity: KeyboardInteractivity::None,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
virtual_keyboard_support: Some(VirtualKeyboardSettings {
|
virtual_keyboard_support: Some(VirtualKeyboardSettings {
|
||||||
|
|
@ -55,12 +66,28 @@ pub fn main() -> Result<(), iced_layershell::Error> {
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
.font(include_bytes!("res/fonts/HoneycombClock.ttf").as_slice())
|
||||||
|
.font(include_bytes!("res/fonts/HoneycombClock2.ttf").as_slice())
|
||||||
|
.subscription(HoneycombBar::subscription)
|
||||||
|
.theme(HoneycombBar::theme)
|
||||||
|
.run()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Bar {
|
struct HoneycombBar {
|
||||||
back_clicked: bool,
|
back_clicked: bool,
|
||||||
home_clicked: bool,
|
home_clicked: bool,
|
||||||
recent_clicked: bool,
|
recent_clicked: bool,
|
||||||
|
|
||||||
|
recent_default: Handle,
|
||||||
|
recent_pressed: Handle,
|
||||||
|
|
||||||
|
back_default: Handle,
|
||||||
|
back_pressed: Handle,
|
||||||
|
|
||||||
|
home_default: Handle,
|
||||||
|
home_pressed: Handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -70,11 +97,9 @@ enum NavButton {
|
||||||
Recent,
|
Recent,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[to_layer_message]
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
enum Message {
|
enum Message {
|
||||||
IcedEvent(Event),
|
|
||||||
ButtonClicked(NavButton),
|
ButtonClicked(NavButton),
|
||||||
Poll,
|
Poll,
|
||||||
FontLoaded(Result<(), font::Error>),
|
FontLoaded(Result<(), font::Error>),
|
||||||
|
|
@ -82,69 +107,67 @@ enum Message {
|
||||||
OpenRecents,
|
OpenRecents,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryInto<LayershellCustomActionsWithId> for Message {
|
// from github.com/waycrate/exwlshelleventloop/blob/master/iced_examples/iced_virtualkeyboard/src/main.rs
|
||||||
type Error = anyhow::Error;
|
impl TryInto<LayershellCustomActionWithId> for Message {
|
||||||
fn try_into(self) -> Result<LayershellCustomActionsWithId, Self::Error> {
|
type Error = Self;
|
||||||
|
fn try_into(self) -> Result<LayershellCustomActionWithId, Self::Error> {
|
||||||
match self {
|
match self {
|
||||||
Message::PressEsc => Ok(LayershellCustomActionsWithId(
|
Message::PressEsc => Ok(LayershellCustomActionWithId(
|
||||||
None,
|
None,
|
||||||
LayershellCustomActions::VirtualKeyboardPressed { time: 100, key: 27 },
|
LayershellCustomAction::VirtualKeyboardPressed {
|
||||||
|
time: 100,
|
||||||
|
key: xkb::get_esc_keycode(),
|
||||||
|
},
|
||||||
)),
|
)),
|
||||||
|
_ => Err(self),
|
||||||
_ => Err(anyhow!("unknown message")),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Bar {
|
impl HoneycombBar {
|
||||||
type Message = Message;
|
fn namespace() -> String {
|
||||||
type Flags = ();
|
String::from("honeycomb navigation")
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = iced::executor::Default;
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
back_clicked: false,
|
|
||||||
home_clicked: false,
|
|
||||||
recent_clicked: false,
|
|
||||||
},
|
|
||||||
Command::batch([
|
|
||||||
font::load(include_bytes!("res/fonts/HoneycombClock.ttf").as_slice())
|
|
||||||
.map(Message::FontLoaded),
|
|
||||||
font::load(include_bytes!("res/fonts/HoneycombClock2.ttf").as_slice())
|
|
||||||
.map(Message::FontLoaded),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn namespace(&self) -> String {
|
fn default() -> Self {
|
||||||
String::from("project honeycomb")
|
Self {
|
||||||
|
recent_default: Handle::from_bytes(include_bytes!("res/recent_default.png") as &[u8]),
|
||||||
|
recent_pressed: Handle::from_bytes(include_bytes!("res/recent_pressed.png") as &[u8]),
|
||||||
|
|
||||||
|
back_default: Handle::from_bytes(include_bytes!("res/back_default.png") as &[u8]),
|
||||||
|
back_pressed: Handle::from_bytes(include_bytes!("res/back_pressed.png") as &[u8]),
|
||||||
|
|
||||||
|
home_default: Handle::from_bytes(include_bytes!("res/home_default.png") as &[u8]),
|
||||||
|
home_pressed: Handle::from_bytes(include_bytes!("res/home_pressed.png") as &[u8]),
|
||||||
|
|
||||||
|
recent_clicked: false,
|
||||||
|
back_clicked: false,
|
||||||
|
home_clicked: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> iced::Subscription<Self::Message> {
|
fn subscription(&self) -> iced::Subscription<Message> {
|
||||||
iced::Subscription::batch(vec![
|
iced::Subscription::batch(vec![
|
||||||
event::listen().map(Message::IcedEvent),
|
time::every(Duration::from_millis(250)).map(|_| Message::Poll),
|
||||||
time::every(Duration::from_millis(300)).map(|_| Message::Poll),
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Task<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::ButtonClicked(button) => match button {
|
Message::ButtonClicked(button) => match button {
|
||||||
NavButton::Back => {
|
NavButton::Back => {
|
||||||
self.back_clicked = true;
|
self.back_clicked = true;
|
||||||
Task::done(Message::PressEsc)
|
Command::done(Message::PressEsc)
|
||||||
}
|
}
|
||||||
|
|
||||||
NavButton::Home => {
|
NavButton::Home => {
|
||||||
self.home_clicked = true;
|
self.home_clicked = true;
|
||||||
Task::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
NavButton::Recent => {
|
NavButton::Recent => {
|
||||||
self.recent_clicked = true;
|
self.recent_clicked = true;
|
||||||
Task::done(Message::OpenRecents)
|
Command::done(Message::OpenRecents)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -152,7 +175,7 @@ impl Application for Bar {
|
||||||
self.back_clicked = false;
|
self.back_clicked = false;
|
||||||
self.home_clicked = false;
|
self.home_clicked = false;
|
||||||
self.recent_clicked = false;
|
self.recent_clicked = false;
|
||||||
Task::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::FontLoaded(result) => {
|
Message::FontLoaded(result) => {
|
||||||
|
|
@ -165,43 +188,46 @@ impl Application for Bar {
|
||||||
println!("error while loading font");
|
println!("error while loading font");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Task::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::OpenRecents => {
|
Message::OpenRecents => {
|
||||||
Ipc::open_recents().unwrap();
|
Ipc::open_recents().unwrap();
|
||||||
Task::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Task::none(),
|
Message::PressEsc => Command::done(message),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<'_, Message> {
|
fn view(&self) -> Element<'_, Message> {
|
||||||
let back = if !self.back_clicked {
|
let back = if !self.back_clicked {
|
||||||
include_bytes!("res/back_default.png") as &[u8]
|
&self.back_default
|
||||||
} else {
|
} else {
|
||||||
include_bytes!("res/back_pressed.png") as &[u8]
|
&self.back_pressed
|
||||||
};
|
};
|
||||||
let back_button = Button::new(image::Image::new(Handle::from_bytes(back)))
|
|
||||||
|
let home = if !self.home_clicked {
|
||||||
|
&self.home_default
|
||||||
|
} else {
|
||||||
|
&self.home_pressed
|
||||||
|
};
|
||||||
|
|
||||||
|
let recent = if !self.recent_clicked {
|
||||||
|
&self.recent_default
|
||||||
|
} else {
|
||||||
|
&self.recent_pressed
|
||||||
|
};
|
||||||
|
|
||||||
|
let back_button = Button::new(image::Image::new(back.clone()))
|
||||||
.on_press(Message::ButtonClicked(NavButton::Back))
|
.on_press(Message::ButtonClicked(NavButton::Back))
|
||||||
.style(transparent_button);
|
.style(transparent_button);
|
||||||
|
|
||||||
let home = if !self.home_clicked {
|
let home_button = Button::new(image::Image::new(home.clone()))
|
||||||
include_bytes!("res/home_default.png") as &[u8]
|
|
||||||
} else {
|
|
||||||
include_bytes!("res/home_pressed.png") as &[u8]
|
|
||||||
};
|
|
||||||
let home_button = Button::new(image::Image::new(Handle::from_bytes(home)))
|
|
||||||
.on_press(Message::ButtonClicked(NavButton::Home))
|
.on_press(Message::ButtonClicked(NavButton::Home))
|
||||||
.style(transparent_button);
|
.style(transparent_button);
|
||||||
|
|
||||||
let recent = if !self.recent_clicked {
|
let recent_button = Button::new(image::Image::new(recent.clone()))
|
||||||
include_bytes!("res/recent_default.png") as &[u8]
|
|
||||||
} else {
|
|
||||||
include_bytes!("res/recent_pressed.png") as &[u8]
|
|
||||||
};
|
|
||||||
let recent_button = Button::new(image::Image::new(Handle::from_bytes(recent)))
|
|
||||||
.on_press(Message::ButtonClicked(NavButton::Recent))
|
.on_press(Message::ButtonClicked(NavButton::Recent))
|
||||||
.style(transparent_button);
|
.style(transparent_button);
|
||||||
|
|
||||||
|
|
@ -225,13 +251,14 @@ impl Application for Bar {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Self::Theme {
|
fn theme(&self) -> Theme {
|
||||||
let custom_palette = Palette {
|
let custom_palette = Palette {
|
||||||
background: Color::BLACK,
|
background: Color::BLACK,
|
||||||
primary: Color::BLACK,
|
primary: Color::BLACK,
|
||||||
text: Color::WHITE,
|
text: Color::WHITE,
|
||||||
success: Color::WHITE,
|
success: Color::WHITE,
|
||||||
danger: Color::WHITE,
|
danger: Color::WHITE,
|
||||||
|
warning: Color::WHITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
Theme::custom("honeycomb-default".to_owned(), custom_palette)
|
Theme::custom("honeycomb-default".to_owned(), custom_palette)
|
||||||
|
|
|
||||||
18
src/xkb.rs
18
src/xkb.rs
|
|
@ -2,8 +2,7 @@ use std::{ffi::CString, fs::File, io::Write, path::PathBuf};
|
||||||
|
|
||||||
use xkbcommon::xkb;
|
use xkbcommon::xkb;
|
||||||
|
|
||||||
// from https://github.com/ptazithos/wkeys/blob/main/wkeys/src/native/session.rs
|
fn get_keymap() -> xkb::Keymap {
|
||||||
pub fn get_keymap_as_file() -> (File, u32) {
|
|
||||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||||
|
|
||||||
let keymap = xkb::Keymap::new_from_names(
|
let keymap = xkb::Keymap::new_from_names(
|
||||||
|
|
@ -17,9 +16,14 @@ pub fn get_keymap_as_file() -> (File, u32) {
|
||||||
)
|
)
|
||||||
.expect("xkbcommon keymap panicked!");
|
.expect("xkbcommon keymap panicked!");
|
||||||
let xkb_state = xkb::State::new(&keymap);
|
let xkb_state = xkb::State::new(&keymap);
|
||||||
let keymap = xkb_state
|
|
||||||
.get_keymap()
|
xkb_state.get_keymap()
|
||||||
.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);
|
}
|
||||||
|
|
||||||
|
// from https://github.com/ptazithos/wkeys/blob/main/wkeys/src/native/session.rs
|
||||||
|
pub fn get_keymap_as_file() -> (File, u32) {
|
||||||
|
let keymap = get_keymap().get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);
|
||||||
|
println!("{keymap}");
|
||||||
let keymap = CString::new(keymap).expect("Keymap should not contain interior nul bytes");
|
let keymap = CString::new(keymap).expect("Keymap should not contain interior nul bytes");
|
||||||
let keymap = keymap.as_bytes_with_nul();
|
let keymap = keymap.as_bytes_with_nul();
|
||||||
let dir = std::env::var_os("XDG_RUNTIME_DIR")
|
let dir = std::env::var_os("XDG_RUNTIME_DIR")
|
||||||
|
|
@ -30,3 +34,7 @@ pub fn get_keymap_as_file() -> (File, u32) {
|
||||||
file.flush().unwrap();
|
file.flush().unwrap();
|
||||||
(file, keymap.len() as u32)
|
(file, keymap.len() as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_esc_keycode() -> u32 {
|
||||||
|
Into::<u32>::into(get_keymap().key_by_name("ESC").unwrap()) - 8 as u32
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue