At the risk of falling for "premature optimisation is the root of all
evil", this is an attempt to prevent unnecessary drawing events and make
things as battery-friendly as possible.
With this patch, the timer (each second by default) does not request a
new draw event unless the time or the status icons have changed.
---
src/draw.rs | 10 ++++++++--
src/main.rs | 25 ++++++++++++++++++++++++-
src/wayland_protocol.rs | 5 +++++
3 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/src/draw.rs b/src/draw.rs
index 429296c..b600968 100644
--- a/src/draw.rs
+++ b/src/draw.rs
@@ -3,6 +3,7 @@ use chrono;
use memfd::{self, Memfd};
use memmap2::MmapMut;
use pangocairo;
+use std::hash::{DefaultHasher, Hash, Hasher};
use std::os::fd::AsFd;
use wayland_client::protocol::wl_shm;
@@ -56,9 +57,14 @@ impl State {
context.move_to((init_w as f64 / 2.0) - (layout_w as f64 / 2.0), 50.0);
pangocairo::functions::show_layout(&context, &layout);
+ // hash the statusline so we can check if it changes later
+ let mut h = DefaultHasher::new();
+ status.hash(&mut h);
+ self.statushash = Some(h.finish());
+
//draw time
- let time = chrono::Local::now();
- let timestring = time.format("%H:%M").to_string();
+ self.time = Some(chrono::Local::now());
+ let timestring = self.time.as_ref().unwrap().format("%H:%M").to_string();
let layout = pangocairo::functions::create_layout(&context);
layout.set_font_description(Some(&self.fontdesc_time));
layout.set_text(×tring);
diff --git a/src/main.rs b/src/main.rs
index 61733a0..a23e254 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
+use std::hash::{DefaultHasher, Hash, Hasher};
use std::io::{BufRead, BufReader};
use std::process::{Command, Stdio};
use std::sync::{Arc, Mutex};
@@ -6,6 +7,7 @@ use std::{env, thread, time};
mod draw;
mod poller;
mod wayland_protocol;
+use chrono::Timelike;
use poller::Poller;
use wayland_protocol::init_wayland;
use wayland_protocol::TouchDown;
@@ -145,7 +147,28 @@ fn main() {
if timer_ready {
poller.read_timer();
- way_state.redraw = true;
+ let time = chrono::Local::now();
+ let time_changed = way_state.time.is_none()
+ || way_state.time.as_ref().unwrap().minute() != time.minute();
+ let status_changed = {
+ let status = way_state.status.lock().expect("unlock must work");
+ let mut h = DefaultHasher::new();
+ status.hash(&mut h);
+ let statushash = h.finish();
+ way_state.statushash.is_none()
+ || *way_state.statushash.as_ref().unwrap() != statushash
+ };
+ if way_state.debug {
+ if time_changed {
+ eprintln!("time changed");
+ }
+ if status_changed {
+ eprintln!("status changed");
+ }
+ }
+ if time_changed || status_changed {
+ way_state.redraw = true;
+ }
}
if let Some(last_down) = way_state.last_down.as_ref() {
diff --git a/src/wayland_protocol.rs b/src/wayland_protocol.rs
index 233a0a7..689b730 100644
--- a/src/wayland_protocol.rs
+++ b/src/wayland_protocol.rs
@@ -31,6 +31,7 @@ use wayland_client::protocol::wl_shm;
use wayland_client::protocol::wl_shm_pool;
use crate::touch_pass::TouchState;
+use chrono::{DateTime, Local};
#[derive(Copy, Clone)]
pub struct TouchDown {
@@ -69,6 +70,8 @@ pub struct State {
pub wl_shm: Option<wl_shm::WlShm>,
pub touch_state: Option<TouchState>,
pub status: Arc<Mutex<String>>,
+ pub statushash: Option<u64>, //hash of last status
+ pub time: Option<DateTime<Local>>,
}
impl State {
@@ -332,6 +335,8 @@ pub fn init_wayland(
wl_shm: None,
touch_state: None,
status,
+ statushash: None,
+ time: None,
};
// To actually receive the events, we invoke the `sync_roundtrip` method. This method
--
2.47.1