Refactor slightly

This commit is contained in:
Kenny Levinsen
2023-01-13 21:53:07 +01:00
parent b2a9475e4c
commit 3a40bb18c5
9 changed files with 513 additions and 493 deletions
+33
View File
@@ -4,6 +4,10 @@ use crate::draw;
use fontconfig::Fontconfig as FontConfig;
use rusttype::Font;
use std::{
cell::RefCell,
mem,
rc::Rc,
thread,
collections::HashMap,
fs::File,
hash,
@@ -11,6 +15,7 @@ use std::{
path::{Path, PathBuf},
};
/// FontRef is used to store Fonts on widgets.
pub type FontRef<'a> = &'a rusttype::Font<'a>;
@@ -126,3 +131,31 @@ impl FontMap {
.expect("no font at specified size")
}
}
pub enum MaybeFontMap {
Waiting(thread::JoinHandle<FontMap>),
Ready(Rc<RefCell<FontMap>>),
Invalid,
}
impl MaybeFontMap {
pub fn unwrap(&self) -> Rc<RefCell<FontMap>> {
match self {
MaybeFontMap::Ready(f) => f.clone(),
_ => panic!("fontmap not yet ready"),
}
}
pub fn resolve(&mut self) {
if matches!(self, MaybeFontMap::Waiting(_)) {
let s = mem::replace(self, MaybeFontMap::Invalid);
match s {
MaybeFontMap::Waiting(handle) => {
*self = MaybeFontMap::Ready(Rc::new(RefCell::new(handle.join().unwrap())));
}
_ => unreachable!(),
}
}
}
}
+13 -435
View File
@@ -5,19 +5,9 @@ mod fonts;
mod keyboard;
mod utils;
mod widgets;
mod state;
use wayland_client::{
protocol::{
wl_buffer, wl_compositor, wl_keyboard, wl_registry, wl_seat, wl_shm, wl_shm_pool,
wl_surface,
},
Connection, Dispatch, QueueHandle, WEnum, WaylandSource,
};
use wayland_protocols::xdg::{
activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1},
shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base},
};
use wayland_client::{Connection, QueueHandle, WaylandSource,};
use calloop::{
timer::{TimeoutAction, Timer},
@@ -27,84 +17,14 @@ use chrono::{Duration, Local, Timelike};
use buffer::{BufferManager, BufferView};
use color::Color;
use fonts::FontMap;
use fonts::{MaybeFontMap, FontMap};
use keyboard::Keyboard;
use widgets::{
Backlight, Battery, Clock, Date, Geometry, HorizontalLayout, IndexedLayout, Interface, Layout,
Line, Margin, VerticalLayout, Widget, WidgetUpdater,
Backlight, Battery, Clock, Date, Geometry, Interface, Line, WidgetUpdater,
};
use state::State;
use std::{cell::RefCell, env, mem, process::exit, rc::Rc, thread};
enum MaybeFontMap {
Waiting(thread::JoinHandle<FontMap>),
Ready(Rc<RefCell<FontMap>>),
Invalid,
}
impl MaybeFontMap {
fn unwrap(&self) -> Rc<RefCell<FontMap>> {
match self {
MaybeFontMap::Ready(f) => f.clone(),
_ => panic!("fontmap not yet ready"),
}
}
fn resolve(&mut self) {
if matches!(self, MaybeFontMap::Waiting(_)) {
let s = mem::replace(self, MaybeFontMap::Invalid);
match s {
MaybeFontMap::Waiting(handle) => {
*self = MaybeFontMap::Ready(Rc::new(RefCell::new(handle.join().unwrap())));
}
_ => unreachable!(),
}
}
}
}
struct State {
running: bool,
dirty: bool,
activated: bool,
base_surface: Option<wl_surface::WlSurface>,
wm_base: Option<xdg_wm_base::XdgWmBase>,
xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>,
wl_shm: Option<wl_shm::WlShm>,
xdg_activation: Option<xdg_activation_v1::XdgActivationV1>,
configured: bool,
dimensions: (i32, i32),
bufmgr: BufferManager,
widgets: Vec<Box<dyn Widget>>,
keyboard: Keyboard,
fonts: MaybeFontMap,
}
impl State {
fn add_buffer(&mut self, qh: &QueueHandle<Self>) {
self.bufmgr.add_buffer(
self.wl_shm.as_ref().expect("missing wl_shm"),
self.dimensions,
qh,
);
}
fn activate(&mut self, qh: &QueueHandle<Self>) {
let key = match env::var("XDG_ACTIVATION_TOKEN") {
Ok(token) => token,
Err(_) => return,
};
match (&self.base_surface, &self.xdg_activation) {
(Some(surface), Some(activation)) => {
activation.activate(key, surface);
let activation_token = activation.get_activation_token(qh, ());
activation_token.commit();
env::remove_var("XDG_ACTIVATION_TOKEN");
}
_ => (),
}
}
}
use std::thread;
impl WidgetUpdater for State {
fn geometry_update(
@@ -121,8 +41,8 @@ fn main() {
let font_thread = thread::spawn(move || {
let mut fm = FontMap::new();
// Hard-coding font paths make things a lot faster
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 96.);
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 40.);
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 128.);
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 48.);
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 24.);
fm.queue_font_path(
"monospace",
@@ -146,12 +66,12 @@ fn main() {
let (ping_sender, ping_source) = calloop::ping::make_ping().unwrap();
let clock = Box::new(Clock::new());
let date = Box::new(Date::new());
let clock = Box::new(Clock::new("sans", 128.));
let date = Box::new(Date::new("sans", 48.));
let line = Box::new(Line::new());
let launcher = Box::new(Interface::new());
let battery = Box::new(Battery::new(ping_sender));
let backlight = Box::new(Backlight::new("intel_backlight"));
let launcher = Box::new(Interface::new("monospace", 32.));
let battery = Box::new(Battery::new(ping_sender, "sans", 24.));
let backlight = Box::new(Backlight::new("intel_backlight", "sans", 24.));
let mut event_loop: EventLoop<State> =
EventLoop::try_new().expect("Failed to initialize the event loop!");
@@ -288,345 +208,3 @@ fn main() {
}
}
impl Dispatch<wl_registry::WlRegistry, ()> for State {
fn event(
state: &mut Self,
registry: &wl_registry::WlRegistry,
event: wl_registry::Event,
_: &(),
_: &Connection,
qh: &QueueHandle<Self>,
) {
if let wl_registry::Event::Global {
name, interface, ..
} = event
{
match &interface[..] {
"wl_compositor" => {
let compositor =
registry.bind::<wl_compositor::WlCompositor, _, _>(name, 4, qh, ());
let surface = compositor.create_surface(qh, ());
state.base_surface = Some(surface);
state.activate(qh);
if state.wm_base.is_some() && state.xdg_surface.is_none() {
state.init_xdg_surface(qh);
}
}
"wl_shm" => {
state.wl_shm = Some(registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ()));
}
"wl_seat" => {
registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ());
}
"xdg_wm_base" => {
let wm_base = registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ());
state.wm_base = Some(wm_base);
if state.base_surface.is_some() && state.xdg_surface.is_none() {
state.init_xdg_surface(qh);
}
}
"xdg_activation_v1" => {
state.xdg_activation = Some(
registry.bind::<xdg_activation_v1::XdgActivationV1, _, _>(name, 1, qh, ()),
);
state.activate(qh);
}
_ => {}
}
}
}
}
impl Dispatch<wl_compositor::WlCompositor, ()> for State {
fn event(
_: &mut Self,
_: &wl_compositor::WlCompositor,
_: wl_compositor::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_surface::WlSurface, ()> for State {
fn event(
_: &mut Self,
_: &wl_surface::WlSurface,
_: wl_surface::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_shm::WlShm, ()> for State {
fn event(
_: &mut Self,
_: &wl_shm::WlShm,
_: wl_shm::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_shm_pool::WlShmPool, ()> for State {
fn event(
_: &mut Self,
_: &wl_shm_pool::WlShmPool,
_: wl_shm_pool::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_buffer::WlBuffer, ()> for State {
fn event(
state: &mut Self,
buffer: &wl_buffer::WlBuffer,
_: wl_buffer::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
for buf in state.bufmgr.buffers.iter_mut() {
if &buf.buffer == buffer {
buf.release();
}
}
}
}
impl State {
fn init_xdg_surface(&mut self, qh: &QueueHandle<State>) {
let wm_base = self.wm_base.as_ref().unwrap();
let base_surface = self.base_surface.as_ref().unwrap();
let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ());
let toplevel = xdg_surface.get_toplevel(qh, ());
toplevel.set_title("wldash".into());
base_surface.commit();
self.xdg_surface = Some((xdg_surface, toplevel));
}
}
impl Dispatch<xdg_wm_base::XdgWmBase, ()> for State {
fn event(
_: &mut Self,
wm_base: &xdg_wm_base::XdgWmBase,
event: xdg_wm_base::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
if let xdg_wm_base::Event::Ping { serial } = event {
wm_base.pong(serial);
}
}
}
impl Dispatch<xdg_surface::XdgSurface, ()> for State {
fn event(
state: &mut Self,
xdg_surface: &xdg_surface::XdgSurface,
event: xdg_surface::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
if let xdg_surface::Event::Configure { serial, .. } = event {
xdg_surface.ack_configure(serial);
state.configured = true;
state.dirty = true;
}
}
}
impl Dispatch<xdg_toplevel::XdgToplevel, ()> for State {
fn event(
state: &mut Self,
_: &xdg_toplevel::XdgToplevel,
event: xdg_toplevel::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
match event {
xdg_toplevel::Event::Configure {
width,
height,
states,
..
} => {
if (width, height) == (0, 0) {
return;
}
let activated = states
.iter()
.find(|&st| *st as u32 == xdg_toplevel::State::Activated as u32)
.is_some();
if activated {
state.activated = true;
} else if state.activated && !activated {
exit(0);
}
if state.dimensions != (width, height) {
state.bufmgr.clear_buffers();
state.dimensions = (width, height);
let mut layout = VerticalLayout {
widgets: vec![
Box::new(HorizontalLayout {
widgets: vec![
Box::new(IndexedLayout { widget_idx: 0 }),
Box::new(Margin {
widget: Box::new(IndexedLayout { widget_idx: 1 }),
margin: (16, 8, 0, 0),
}),
Box::new(VerticalLayout {
widgets: vec![
Box::new(Margin {
widget: Box::new(IndexedLayout { widget_idx: 2 }),
margin: (16, 8, 8, 0),
}),
Box::new(Margin {
widget: Box::new(IndexedLayout { widget_idx: 3 }),
margin: (16, 8, 8, 0),
}),
],
}),
],
}),
Box::new(IndexedLayout { widget_idx: 4 }),
Box::new(IndexedLayout { widget_idx: 5 }),
],
};
state.fonts.resolve();
let fonts = state.fonts.unwrap();
layout.geometry_update(
&mut fonts.borrow_mut(),
&Geometry {
x: 0,
y: 0,
width: width as u32,
height: height as u32,
},
state,
);
}
}
xdg_toplevel::Event::Close => {
state.running = false;
}
_ => (),
}
}
}
impl Dispatch<wl_seat::WlSeat, ()> for State {
fn event(
_: &mut Self,
seat: &wl_seat::WlSeat,
event: wl_seat::Event,
_: &(),
_: &Connection,
qh: &QueueHandle<Self>,
) {
if let wl_seat::Event::Capabilities {
capabilities: WEnum::Value(capabilities),
} = event
{
if capabilities.contains(wl_seat::Capability::Keyboard) {
seat.get_keyboard(qh, ());
}
}
}
}
impl Dispatch<wl_keyboard::WlKeyboard, ()> for State {
fn event(
state: &mut Self,
_: &wl_keyboard::WlKeyboard,
event: wl_keyboard::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
match event {
wl_keyboard::Event::Key {
serial,
time,
key,
state: kbstate,
} => {
if key == 1 {
state.running = false;
return;
}
let k = state.keyboard.key(serial, time, key, kbstate);
for widget in state.widgets.iter_mut() {
widget.keyboard_input(&k);
}
state.dirty = true;
}
wl_keyboard::Event::Modifiers {
mods_depressed,
mods_latched,
mods_locked,
group,
..
} => {
state
.keyboard
.modifiers(mods_depressed, mods_latched, mods_locked, group);
}
wl_keyboard::Event::Keymap { format, fd, size } => {
state.keyboard.keymap(format, fd, size);
}
_ => (),
}
}
}
impl Dispatch<xdg_activation_v1::XdgActivationV1, ()> for State {
fn event(
_: &mut Self,
_: &xdg_activation_v1::XdgActivationV1,
_: xdg_activation_v1::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ()> for State {
fn event(
state: &mut Self,
_: &xdg_activation_token_v1::XdgActivationTokenV1,
event: xdg_activation_token_v1::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
match event {
xdg_activation_token_v1::Event::Done { token } => {
for widget in state.widgets.iter_mut() {
widget.token_update(&token);
}
}
_ => (),
}
}
}
+412
View File
@@ -0,0 +1,412 @@
use std::{
env,
process::exit,
};
use wayland_client::{
protocol::{
wl_buffer, wl_compositor, wl_keyboard, wl_registry, wl_seat, wl_shm, wl_shm_pool,
wl_surface,
},
Connection, Dispatch, QueueHandle, WEnum,
};
use wayland_protocols::xdg::{
activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1},
shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base},
};
use crate::{
buffer::BufferManager,
fonts::MaybeFontMap,
keyboard::Keyboard,
widgets::{
Geometry, HorizontalLayout, IndexedLayout, Layout, Margin, VerticalLayout, Widget,
},
};
pub struct State {
pub running: bool,
pub dirty: bool,
pub activated: bool,
pub base_surface: Option<wl_surface::WlSurface>,
pub wm_base: Option<xdg_wm_base::XdgWmBase>,
pub xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>,
pub wl_shm: Option<wl_shm::WlShm>,
pub xdg_activation: Option<xdg_activation_v1::XdgActivationV1>,
pub configured: bool,
pub dimensions: (i32, i32),
pub bufmgr: BufferManager,
pub widgets: Vec<Box<dyn Widget>>,
pub keyboard: Keyboard,
pub fonts: MaybeFontMap,
}
impl State {
pub fn add_buffer(&mut self, qh: &QueueHandle<Self>) {
self.bufmgr.add_buffer(
self.wl_shm.as_ref().expect("missing wl_shm"),
self.dimensions,
qh,
);
}
pub fn activate(&mut self, qh: &QueueHandle<Self>) {
let key = match env::var("XDG_ACTIVATION_TOKEN") {
Ok(token) => token,
Err(_) => return,
};
match (&self.base_surface, &self.xdg_activation) {
(Some(surface), Some(activation)) => {
activation.activate(key, surface);
let activation_token = activation.get_activation_token(qh, ());
activation_token.commit();
env::remove_var("XDG_ACTIVATION_TOKEN");
}
_ => (),
}
}
}
impl Dispatch<wl_registry::WlRegistry, ()> for State {
fn event(
state: &mut Self,
registry: &wl_registry::WlRegistry,
event: wl_registry::Event,
_: &(),
_: &Connection,
qh: &QueueHandle<Self>,
) {
if let wl_registry::Event::Global {
name, interface, ..
} = event
{
match &interface[..] {
"wl_compositor" => {
let compositor =
registry.bind::<wl_compositor::WlCompositor, _, _>(name, 4, qh, ());
let surface = compositor.create_surface(qh, ());
state.base_surface = Some(surface);
state.activate(qh);
if state.wm_base.is_some() && state.xdg_surface.is_none() {
state.init_xdg_surface(qh);
}
}
"wl_shm" => {
state.wl_shm = Some(registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ()));
}
"wl_seat" => {
registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ());
}
"xdg_wm_base" => {
let wm_base = registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ());
state.wm_base = Some(wm_base);
if state.base_surface.is_some() && state.xdg_surface.is_none() {
state.init_xdg_surface(qh);
}
}
"xdg_activation_v1" => {
state.xdg_activation = Some(
registry.bind::<xdg_activation_v1::XdgActivationV1, _, _>(name, 1, qh, ()),
);
state.activate(qh);
}
_ => {}
}
}
}
}
impl Dispatch<wl_compositor::WlCompositor, ()> for State {
fn event(
_: &mut Self,
_: &wl_compositor::WlCompositor,
_: wl_compositor::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_surface::WlSurface, ()> for State {
fn event(
_: &mut Self,
_: &wl_surface::WlSurface,
_: wl_surface::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_shm::WlShm, ()> for State {
fn event(
_: &mut Self,
_: &wl_shm::WlShm,
_: wl_shm::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_shm_pool::WlShmPool, ()> for State {
fn event(
_: &mut Self,
_: &wl_shm_pool::WlShmPool,
_: wl_shm_pool::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<wl_buffer::WlBuffer, ()> for State {
fn event(
state: &mut Self,
buffer: &wl_buffer::WlBuffer,
_: wl_buffer::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
for buf in state.bufmgr.buffers.iter_mut() {
if &buf.buffer == buffer {
buf.release();
}
}
}
}
impl State {
fn init_xdg_surface(&mut self, qh: &QueueHandle<State>) {
let wm_base = self.wm_base.as_ref().unwrap();
let base_surface = self.base_surface.as_ref().unwrap();
let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ());
let toplevel = xdg_surface.get_toplevel(qh, ());
toplevel.set_title("wldash".into());
base_surface.commit();
self.xdg_surface = Some((xdg_surface, toplevel));
}
}
impl Dispatch<xdg_wm_base::XdgWmBase, ()> for State {
fn event(
_: &mut Self,
wm_base: &xdg_wm_base::XdgWmBase,
event: xdg_wm_base::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
if let xdg_wm_base::Event::Ping { serial } = event {
wm_base.pong(serial);
}
}
}
impl Dispatch<xdg_surface::XdgSurface, ()> for State {
fn event(
state: &mut Self,
xdg_surface: &xdg_surface::XdgSurface,
event: xdg_surface::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
if let xdg_surface::Event::Configure { serial, .. } = event {
xdg_surface.ack_configure(serial);
state.configured = true;
state.dirty = true;
}
}
}
impl Dispatch<xdg_toplevel::XdgToplevel, ()> for State {
fn event(
state: &mut Self,
_: &xdg_toplevel::XdgToplevel,
event: xdg_toplevel::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
match event {
xdg_toplevel::Event::Configure {
width,
height,
states,
..
} => {
if (width, height) == (0, 0) {
return;
}
let activated = states
.iter()
.find(|&st| *st as u32 == xdg_toplevel::State::Activated as u32)
.is_some();
if activated {
state.activated = true;
} else if state.activated && !activated {
exit(0);
}
if state.dimensions != (width, height) {
state.bufmgr.clear_buffers();
state.dimensions = (width, height);
let mut layout = VerticalLayout {
widgets: vec![
Box::new(HorizontalLayout {
widgets: vec![
Box::new(IndexedLayout { widget_idx: 0 }),
Box::new(Margin {
widget: Box::new(IndexedLayout { widget_idx: 1 }),
margin: (16, 8, 0, 0),
}),
Box::new(VerticalLayout {
widgets: vec![
Box::new(Margin {
widget: Box::new(IndexedLayout { widget_idx: 2 }),
margin: (16, 8, 8, 0),
}),
Box::new(Margin {
widget: Box::new(IndexedLayout { widget_idx: 3 }),
margin: (16, 8, 8, 0),
}),
],
}),
],
}),
Box::new(IndexedLayout { widget_idx: 4 }),
Box::new(IndexedLayout { widget_idx: 5 }),
],
};
state.fonts.resolve();
let fonts = state.fonts.unwrap();
layout.geometry_update(
&mut fonts.borrow_mut(),
&Geometry {
x: 0,
y: 0,
width: width as u32,
height: height as u32,
},
state,
);
}
}
xdg_toplevel::Event::Close => {
state.running = false;
}
_ => (),
}
}
}
impl Dispatch<wl_seat::WlSeat, ()> for State {
fn event(
_: &mut Self,
seat: &wl_seat::WlSeat,
event: wl_seat::Event,
_: &(),
_: &Connection,
qh: &QueueHandle<Self>,
) {
if let wl_seat::Event::Capabilities {
capabilities: WEnum::Value(capabilities),
} = event
{
if capabilities.contains(wl_seat::Capability::Keyboard) {
seat.get_keyboard(qh, ());
}
}
}
}
impl Dispatch<wl_keyboard::WlKeyboard, ()> for State {
fn event(
state: &mut Self,
_: &wl_keyboard::WlKeyboard,
event: wl_keyboard::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
match event {
wl_keyboard::Event::Key {
serial,
time,
key,
state: kbstate,
} => {
if key == 1 {
state.running = false;
return;
}
let k = state.keyboard.key(serial, time, key, kbstate);
for widget in state.widgets.iter_mut() {
widget.keyboard_input(&k);
}
state.dirty = true;
}
wl_keyboard::Event::Modifiers {
mods_depressed,
mods_latched,
mods_locked,
group,
..
} => {
state
.keyboard
.modifiers(mods_depressed, mods_latched, mods_locked, group);
}
wl_keyboard::Event::Keymap { format, fd, size } => {
state.keyboard.keymap(format, fd, size);
}
_ => (),
}
}
}
impl Dispatch<xdg_activation_v1::XdgActivationV1, ()> for State {
fn event(
_: &mut Self,
_: &xdg_activation_v1::XdgActivationV1,
_: xdg_activation_v1::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ()> for State {
fn event(
state: &mut Self,
_: &xdg_activation_token_v1::XdgActivationTokenV1,
event: xdg_activation_token_v1::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
match event {
xdg_activation_token_v1::Event::Done { token } => {
for widget in state.widgets.iter_mut() {
widget.token_update(&token);
}
}
_ => (),
}
}
}
+2 -2
View File
@@ -29,7 +29,7 @@ impl Backlight {
self.max = read_file_as_u64(self.device_path.join("max_brightness").as_path()).unwrap();
}
pub fn new(path: &str) -> BarWidget {
pub fn new(path: &str, font: &'static str, size: f32) -> BarWidget {
let mut dev = Backlight {
device_path: Path::new("/sys/class/backlight").to_path_buf().join(path),
cur: 0,
@@ -38,7 +38,7 @@ impl Backlight {
};
dev.update();
BarWidget::new(Box::new(dev))
BarWidget::new(Box::new(dev), font, size)
}
}
+7 -8
View File
@@ -8,9 +8,6 @@ use crate::{
widgets::{Geometry, Widget},
};
const BAR_FONT: &str = "sans";
const BAR_SIZE: f32 = 24.;
pub trait BarWidgetImpl {
fn get_dirty(&self) -> bool;
fn set_dirty(&mut self, dirty: bool);
@@ -20,15 +17,17 @@ pub trait BarWidgetImpl {
}
pub struct BarWidget {
font: &'static str,
size: f32,
geometry: Geometry,
inner_widget: Box<dyn BarWidgetImpl>,
}
impl BarWidget {
pub fn new(inner_widget: Box<dyn BarWidgetImpl>) -> BarWidget {
pub fn new(inner_widget: Box<dyn BarWidgetImpl>, font: &'static str, size: f32) -> BarWidget {
BarWidget {
geometry: Default::default(),
inner_widget,
inner_widget, font, size,
}
}
}
@@ -47,13 +46,13 @@ impl Widget for BarWidget {
}
fn draw(&mut self, fonts: &mut FontMap, view: &mut BufferView) -> Geometry {
let font = fonts.get_font(BAR_FONT, BAR_SIZE);
let font = fonts.get_font(self.font, self.size);
let fg = Color::new(1., 1., 1., 1.);
let bg = Color::new(0., 0., 0., 1.);
font.auto_draw_text(view, &bg, &fg, self.inner_widget.name())
.unwrap();
let size = BAR_SIZE.ceil() as u32;
let size = self.size.ceil() as u32;
let bar_offset = 4 * size;
let val = self.inner_widget.value();
@@ -86,7 +85,7 @@ impl Widget for BarWidget {
x: x,
y: geometry.y,
width: w,
height: BAR_SIZE.ceil() as u32,
height: self.size.ceil() as u32,
};
self.geometry
}
+2 -2
View File
@@ -111,7 +111,7 @@ pub struct Battery {
}
impl Battery {
pub fn new(ping: Ping) -> BarWidget {
pub fn new(ping: Ping, font: &'static str, size: f32) -> BarWidget {
let battery = Battery {
inner: Arc::new(Mutex::new(InnerBattery {
value: 0.,
@@ -120,7 +120,7 @@ impl Battery {
dirty: false,
};
start_monitor(battery.inner.clone(), ping);
BarWidget::new(Box::new(battery))
BarWidget::new(Box::new(battery), font, size)
}
}
+7 -7
View File
@@ -9,10 +9,9 @@ use crate::{
use chrono::{Local, Timelike};
const CLOCK_FONT: &str = "sans";
const CLOCK_SIZE: f32 = 96.;
pub struct Clock {
font: &'static str,
size: f32,
dirty: bool,
geometry: Geometry,
digit_width: u32,
@@ -20,8 +19,9 @@ pub struct Clock {
}
impl<'a> Clock {
pub fn new() -> Clock {
pub fn new(font: &'static str, size: f32) -> Clock {
Clock {
font, size,
dirty: true,
geometry: Default::default(),
digit_width: 0,
@@ -49,7 +49,7 @@ impl<'a> Widget for Clock {
let digit = self.digit_width;
let colon = self.colon_width;
let font = fonts.get_font(CLOCK_FONT, CLOCK_SIZE);
let font = fonts.get_font(self.font, self.size);
font.draw_text_fixed_width(
view,
&bg,
@@ -62,14 +62,14 @@ impl<'a> Widget for Clock {
}
fn geometry_update(&mut self, fonts: &mut FontMap, geometry: &Geometry) -> Geometry {
let font = fonts.get_font(CLOCK_FONT, CLOCK_SIZE);
let font = fonts.get_font(self.font, self.size);
self.digit_width = font.auto_widest("0123456789").unwrap();
self.colon_width = font.auto_widest(":").unwrap();
self.geometry = Geometry {
x: geometry.x,
y: geometry.y,
width: self.digit_width * 4 + self.colon_width,
height: CLOCK_SIZE.ceil() as u32,
height: self.size.ceil() as u32,
};
self.geometry
}
+8 -7
View File
@@ -9,17 +9,17 @@ use crate::{
use chrono::{Datelike, Local};
const DATE_FONT: &str = "sans";
const DATE_SIZE: f32 = 40.;
pub struct Date {
font: &'static str,
size: f32,
dirty: bool,
geometry: Geometry,
}
impl Date {
pub fn new() -> Date {
pub fn new(font: &'static str, size: f32) -> Date {
Date {
font, size,
dirty: true,
geometry: Default::default(),
}
@@ -43,7 +43,7 @@ impl<'a> Widget for Date {
let fg = Color::new(1., 1., 1., 1.);
let bg = Color::new(0., 0., 0., 1.);
let mut date_line = view.offset((0, 8)).unwrap();
let font = fonts.get_font(DATE_FONT, DATE_SIZE);
let font = fonts.get_font(self.font, self.size);
font.auto_draw_text(
&mut date_line,
&bg,
@@ -61,11 +61,12 @@ impl<'a> Widget for Date {
}
fn geometry_update(&mut self, _fonts: &mut FontMap, geometry: &Geometry) -> Geometry {
let width = (3. + 2. + 2. + 2. + 4.) * self.size / 2.;
self.geometry = Geometry {
x: geometry.x,
y: geometry.y,
width: 256,
height: DATE_SIZE.ceil() as u32,
width: width.ceil() as u32,
height: self.size.ceil() as u32,
};
self.geometry
}
+29 -32
View File
@@ -1,7 +1,11 @@
use std::cmp::{min, Ordering};
use std::collections::HashMap;
use std::default::Default;
use std::process::{exit, Command};
use std::{
cmp::{min, max, Ordering},
collections::HashMap,
default::Default,
process::{exit, Command},
sync::{Arc, Mutex},
thread,
};
use crate::{
buffer::BufferView,
@@ -17,12 +21,6 @@ use fuzzy_matcher::FuzzyMatcher;
use unicode_segmentation::UnicodeSegmentation;
use wayland_client::{protocol::wl_keyboard, WEnum};
use std::sync::{Arc, Mutex};
use std::thread;
const LAUNCHER_FONT: &str = "monospace";
const LAUNCHER_SIZE: f32 = 32.;
struct Matcher {
matches: HashMap<Desktop, i64>,
}
@@ -284,7 +282,7 @@ impl InterfaceWidget for Launcher {
let fg = Color::new(1., 1., 1., 1.);
let bg = Color::new(0., 0., 0., 1.);
let line_height = LAUNCHER_SIZE.ceil() as u32;
let line_height = intf.size.ceil() as u32;
// Draw line
let mut prompt_offset = intf.geometry.height - line_height;
@@ -292,9 +290,8 @@ impl InterfaceWidget for Launcher {
let mut prompt_border = prompt_line.limit((intf.geometry.width, 1)).unwrap();
prompt_border.memset(&fg);
// Draw prompt
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
font.auto_draw_text_with_cursor(
let font = fonts.get_font(intf.font, intf.size);
let mut x_max = font.auto_draw_text_with_cursor(
&mut prompt_line,
&bg,
&fg,
@@ -303,7 +300,6 @@ impl InterfaceWidget for Launcher {
)
.unwrap();
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
font.auto_draw_text(&mut prompt_line, &bg, &fg, ">")
.unwrap();
@@ -332,11 +328,11 @@ impl InterfaceWidget for Launcher {
colors.push(Color::new(0.75, 0.75, 0.75, 1.0));
}
}
font.auto_draw_text_individual_colors(&mut line, &bg, &colors, &m.name)
.unwrap();
x_max = max(x_max, font.auto_draw_text_individual_colors(&mut line, &bg, &colors, &m.name)
.unwrap());
} else {
font.auto_draw_text(&mut line, &bg, &dimfg, &m.name)
.unwrap();
x_max = max(x_max, font.auto_draw_text(&mut line, &bg, &dimfg, &m.name)
.unwrap());
}
}
@@ -347,7 +343,7 @@ impl InterfaceWidget for Launcher {
Geometry {
x: intf.geometry.x,
y: intf.geometry.y + intf.geometry.height - content_height,
width: intf.geometry.width,
width: x_max.0+1,
height: content_height,
}
}
@@ -380,7 +376,7 @@ impl InterfaceWidget for Shell {
let fg = Color::new(1., 1., 1., 1.);
let bg = Color::new(0., 0., 0., 1.);
let line_height = LAUNCHER_SIZE.ceil() as u32;
let line_height = intf.size.ceil() as u32;
// Draw line
let prompt_offset = intf.geometry.height - line_height;
@@ -389,8 +385,8 @@ impl InterfaceWidget for Shell {
prompt_border.memset(&fg);
// Draw prompt
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
font.auto_draw_text_with_cursor(
let font = fonts.get_font(intf.font, intf.size);
let x_max = font.auto_draw_text_with_cursor(
&mut prompt_line,
&bg,
&fg,
@@ -398,14 +394,13 @@ impl InterfaceWidget for Shell {
intf.prompt.cursor + 3,
)
.unwrap();
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
font.auto_draw_text(&mut prompt_line, &bg, &Color::new(1., 0.75, 0.5, 1.), "!")
.unwrap();
Geometry {
x: intf.geometry.x,
y: intf.geometry.y + intf.geometry.height - line_height,
width: intf.geometry.width,
width: x_max.0 + 1,
height: line_height,
}
}
@@ -443,16 +438,16 @@ impl InterfaceWidget for Calc {
let fg = Color::new(1., 1., 1., 1.);
let bg = Color::new(0., 0., 0., 1.);
let line_height = LAUNCHER_SIZE.ceil() as u32;
let line_height = intf.size.ceil() as u32;
// Draw line
let mut prompt_offset = intf.geometry.height - (LAUNCHER_SIZE.ceil() as u32);
let mut prompt_offset = intf.geometry.height - (line_height);
let mut prompt_line = view.offset((0, prompt_offset)).unwrap();
let mut prompt_border = prompt_line.limit((intf.geometry.width, 1)).unwrap();
prompt_border.memset(&fg);
// Draw prompt
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
let font = fonts.get_font(intf.font, intf.size);
let res_off = font
.auto_draw_text_with_cursor(
&mut prompt_line,
@@ -463,7 +458,6 @@ impl InterfaceWidget for Calc {
)
.unwrap();
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
font.auto_draw_text(&mut prompt_line, &bg, &Color::new(1., 0.75, 0.5, 1.), "=")
.unwrap();
@@ -476,10 +470,10 @@ impl InterfaceWidget for Calc {
for m in self.old.iter().rev() {
let dimfg = Color::new(0.5, 0.5, 0.5, 1.0);
if prompt_offset < LAUNCHER_SIZE.ceil() as u32 {
if prompt_offset < line_height {
break;
}
prompt_offset -= LAUNCHER_SIZE.ceil() as u32;
prompt_offset -= line_height;
let mut result_line = view.offset((0, prompt_offset)).unwrap();
font.auto_draw_text(&mut result_line, &bg, &dimfg, &m)
.unwrap();
@@ -499,6 +493,8 @@ impl InterfaceWidget for Calc {
}
struct InnerInterface {
font: &'static str,
size: f32,
dirty: bool,
geometry: Geometry,
selection: usize,
@@ -513,7 +509,7 @@ pub struct Interface {
}
impl Interface {
pub fn new() -> Interface {
pub fn new(font: &'static str, size: f32) -> Interface {
Interface {
launcher: Launcher::new(),
shell: Shell {},
@@ -522,6 +518,7 @@ impl Interface {
result: None,
},
inner: InnerInterface {
font, size,
dirty: false,
geometry: Default::default(),
selection: 0,