widget: Add wait support
Widgets can now specify that they wish to wait on an fd or for a target time to be reached. This can be used to save a few worker threads.
This commit is contained in:
Generated
+10
@@ -586,6 +586,14 @@ dependencies = [
|
|||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "timerfd"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.11.2"
|
version = "1.11.2"
|
||||||
@@ -723,6 +731,7 @@ dependencies = [
|
|||||||
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"timerfd 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wayland-client 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wayland-client 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wayland-protocols 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wayland-protocols 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -818,6 +827,7 @@ dependencies = [
|
|||||||
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||||
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
|
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
|
||||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||||
|
"checksum timerfd 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9a7822e546fa39d0b5ae14a93a33903975b62af6597288aea77f0580a6abbe"
|
||||||
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||||
"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
|
"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
|
||||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ lazy_static = "1.4"
|
|||||||
rcalc_lib = { version = "0.9" }
|
rcalc_lib = { version = "0.9" }
|
||||||
rust-ini = "0.13"
|
rust-ini = "0.13"
|
||||||
shlex = "0.1"
|
shlex = "0.1"
|
||||||
|
timerfd = "1.0.0"
|
||||||
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = { version = "1.0", optional = true }
|
serde_json = { version = "1.0", optional = true }
|
||||||
|
|||||||
+1
-1
@@ -91,7 +91,7 @@ impl Widget {
|
|||||||
.map(|x| x.unwrap())
|
.map(|x| x.unwrap())
|
||||||
.collect(),
|
.collect(),
|
||||||
)),
|
)),
|
||||||
Widget::Clock { font_size } => Some(widgets::clock::Clock::new(font_size, tx.clone())),
|
Widget::Clock { font_size } => Some(widgets::clock::Clock::new(font_size)),
|
||||||
Widget::Date { font_size } => Some(widgets::date::Date::new(font_size)),
|
Widget::Date { font_size } => Some(widgets::date::Date::new(font_size)),
|
||||||
Widget::Calendar {
|
Widget::Calendar {
|
||||||
font_size,
|
font_size,
|
||||||
|
|||||||
+39
-7
@@ -5,8 +5,10 @@ use std::os::unix::io::AsRawFd;
|
|||||||
use std::os::unix::net::{UnixListener, UnixStream};
|
use std::os::unix::net::{UnixListener, UnixStream};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
|
use timerfd::{TimerFd, TimerState, SetTimeFlags};
|
||||||
use nix::poll::{poll, PollFd, PollFlags};
|
use nix::poll::{poll, PollFd, PollFlags};
|
||||||
use os_pipe::pipe;
|
use os_pipe::pipe;
|
||||||
|
use chrono::{Local, Duration};
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod buffer;
|
mod buffer;
|
||||||
@@ -24,6 +26,7 @@ use app::{App, OutputMode};
|
|||||||
use cmd::Cmd;
|
use cmd::Cmd;
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use configfmt::ConfigFmt;
|
use configfmt::ConfigFmt;
|
||||||
|
use widget::WaitContext;
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
Start,
|
Start,
|
||||||
@@ -222,14 +225,19 @@ fn main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut fds = [
|
let mut timer = TimerFd::new().unwrap();
|
||||||
PollFd::new(app.event_queue().get_connection_fd(), PollFlags::POLLIN),
|
let ev_fd = PollFd::new(app.event_queue().get_connection_fd(), PollFlags::POLLIN);
|
||||||
PollFd::new(rx_pipe.as_raw_fd(), PollFlags::POLLIN),
|
let rx_fd = PollFd::new(rx_pipe.as_raw_fd(), PollFlags::POLLIN);
|
||||||
];
|
let tm_fd = PollFd::new(timer.as_raw_fd(), PollFlags::POLLIN);
|
||||||
|
|
||||||
app.cmd_queue().lock().unwrap().push_back(Cmd::Draw);
|
app.cmd_queue().lock().unwrap().push_back(Cmd::Draw);
|
||||||
|
|
||||||
let mut visible = !daemon;
|
let mut visible = !daemon;
|
||||||
|
let mut wait_ctx = WaitContext{
|
||||||
|
fds: Vec::new(),
|
||||||
|
target_time: None,
|
||||||
|
};
|
||||||
|
|
||||||
let q = app.cmd_queue();
|
let q = app.cmd_queue();
|
||||||
loop {
|
loop {
|
||||||
let cmd = q.lock().unwrap().pop_front();
|
let cmd = q.lock().unwrap().pop_front();
|
||||||
@@ -287,9 +295,27 @@ fn main() {
|
|||||||
None => {
|
None => {
|
||||||
app.flush_display();
|
app.flush_display();
|
||||||
|
|
||||||
poll(&mut fds, -1).unwrap();
|
wait_ctx.fds.clear();
|
||||||
|
wait_ctx.fds.push(ev_fd);
|
||||||
|
wait_ctx.fds.push(rx_fd);
|
||||||
|
wait_ctx.target_time = None;
|
||||||
|
|
||||||
if fds[0].revents().unwrap().contains(PollFlags::POLLIN) {
|
app.get_widget().wait(&mut wait_ctx);
|
||||||
|
|
||||||
|
if let Some(target_time) = wait_ctx.target_time {
|
||||||
|
let n = Local::now();
|
||||||
|
let sleep = if target_time > n {
|
||||||
|
target_time - n
|
||||||
|
} else {
|
||||||
|
Duration::seconds(0)
|
||||||
|
};
|
||||||
|
timer.set_state(TimerState::Oneshot(sleep.to_std().unwrap()), SetTimeFlags::Default);
|
||||||
|
wait_ctx.fds.push(tm_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
poll(&mut wait_ctx.fds, -1).unwrap();
|
||||||
|
|
||||||
|
if wait_ctx.fds[0].revents().unwrap().contains(PollFlags::POLLIN) {
|
||||||
if let Some(guard) = app.event_queue().prepare_read() {
|
if let Some(guard) = app.event_queue().prepare_read() {
|
||||||
if let Err(e) = guard.read_events() {
|
if let Err(e) = guard.read_events() {
|
||||||
if e.kind() != ::std::io::ErrorKind::WouldBlock {
|
if e.kind() != ::std::io::ErrorKind::WouldBlock {
|
||||||
@@ -306,10 +332,16 @@ fn main() {
|
|||||||
.expect("Failed to dispatch all messages.");
|
.expect("Failed to dispatch all messages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if fds[1].revents().unwrap().contains(PollFlags::POLLIN) {
|
if wait_ctx.fds[1].revents().unwrap().contains(PollFlags::POLLIN) {
|
||||||
let mut v = [0x00];
|
let mut v = [0x00];
|
||||||
rx_pipe.read_exact(&mut v).unwrap();
|
rx_pipe.read_exact(&mut v).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if wait_ctx.target_time.is_some() &&
|
||||||
|
wait_ctx.fds[wait_ctx.fds.len()-1].revents().unwrap().contains(PollFlags::POLLIN) {
|
||||||
|
timer.read();
|
||||||
|
q.lock().unwrap().push_back(Cmd::Draw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use nix::poll::{PollFd};
|
||||||
use crate::buffer::Buffer;
|
use crate::buffer::Buffer;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
@@ -29,7 +30,25 @@ impl DrawReport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WaitContext {
|
||||||
|
pub fds: Vec<PollFd>,
|
||||||
|
pub target_time: Option<DateTime<Local>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WaitContext {
|
||||||
|
pub fn set_time(&mut self, new_time: DateTime<Local>) {
|
||||||
|
if let Some(ot) = self.target_time {
|
||||||
|
if new_time < ot {
|
||||||
|
self.target_time = Some(new_time);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.target_time = Some(new_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Widget {
|
pub trait Widget {
|
||||||
|
fn wait(&self, ctx: &mut WaitContext);
|
||||||
fn enter(&mut self);
|
fn enter(&mut self);
|
||||||
fn leave(&mut self);
|
fn leave(&mut self);
|
||||||
fn size(&self) -> (u32, u32);
|
fn size(&self) -> (u32, u32);
|
||||||
@@ -62,6 +81,11 @@ impl VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for VerticalLayout {
|
impl Widget for VerticalLayout {
|
||||||
|
fn wait(&self, ctx: &mut WaitContext) {
|
||||||
|
for child in &self.children {
|
||||||
|
child.wait(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
fn enter(&mut self) {
|
fn enter(&mut self) {
|
||||||
for child in &mut self.children {
|
for child in &mut self.children {
|
||||||
child.enter();
|
child.enter();
|
||||||
@@ -168,6 +192,11 @@ impl HorizontalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for HorizontalLayout {
|
impl Widget for HorizontalLayout {
|
||||||
|
fn wait(&self, ctx: &mut WaitContext) {
|
||||||
|
for child in &self.children {
|
||||||
|
child.wait(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
fn enter(&mut self) {
|
fn enter(&mut self) {
|
||||||
for child in &mut self.children {
|
for child in &mut self.children {
|
||||||
child.enter();
|
child.enter();
|
||||||
@@ -280,6 +309,9 @@ impl Margin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Margin {
|
impl Widget for Margin {
|
||||||
|
fn wait(&self, ctx: &mut WaitContext) {
|
||||||
|
self.child.wait(ctx)
|
||||||
|
}
|
||||||
fn enter(&mut self) {
|
fn enter(&mut self) {
|
||||||
self.child.enter()
|
self.child.enter()
|
||||||
}
|
}
|
||||||
@@ -354,6 +386,9 @@ impl Fixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Fixed {
|
impl Widget for Fixed {
|
||||||
|
fn wait(&self, ctx: &mut WaitContext) {
|
||||||
|
self.child.wait(ctx)
|
||||||
|
}
|
||||||
fn enter(&mut self) {
|
fn enter(&mut self) {
|
||||||
self.child.enter()
|
self.child.enter()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
|
use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ impl BarWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for BarWidget {
|
impl Widget for BarWidget {
|
||||||
|
fn wait(&self, _: &mut WaitContext) {}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {}
|
fn leave(&mut self) {}
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::buffer::Buffer;
|
use crate::buffer::Buffer;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{Font, DEJAVUSANS_MONO, ROBOTO_REGULAR};
|
use crate::draw::{Font, DEJAVUSANS_MONO, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
||||||
|
|
||||||
use chrono::{Date, Datelike, Local};
|
use chrono::{Date, Datelike, Local};
|
||||||
|
|
||||||
@@ -177,6 +177,7 @@ impl Calendar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Calendar {
|
impl Widget for Calendar {
|
||||||
|
fn wait(&self, _: &mut WaitContext) {}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {}
|
fn leave(&mut self) {}
|
||||||
|
|
||||||
|
|||||||
+10
-21
@@ -1,9 +1,6 @@
|
|||||||
use crate::cmd::Cmd;
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{Font, ROBOTO_REGULAR};
|
use crate::draw::{Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
||||||
|
|
||||||
use std::sync::mpsc::Sender;
|
|
||||||
|
|
||||||
use chrono::{DateTime, Datelike, Duration, Local, Timelike};
|
use chrono::{DateTime, Datelike, Duration, Local, Timelike};
|
||||||
|
|
||||||
@@ -14,23 +11,7 @@ pub struct Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Clock {
|
impl Clock {
|
||||||
pub fn new(size: f32, ch: Sender<Cmd>) -> Box<Clock> {
|
pub fn new(size: f32) -> Box<Clock> {
|
||||||
let _ = std::thread::Builder::new()
|
|
||||||
.name("clock_ticker".to_string())
|
|
||||||
.spawn(move || loop {
|
|
||||||
let n = Local::now();
|
|
||||||
let target = (n + Duration::seconds(60))
|
|
||||||
.with_second(0)
|
|
||||||
.unwrap()
|
|
||||||
.with_nanosecond(0)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let d = target - n;
|
|
||||||
|
|
||||||
std::thread::sleep(d.to_std().unwrap());
|
|
||||||
ch.send(Cmd::Draw).unwrap();
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut clock_cache = Font::new(&ROBOTO_REGULAR, size);
|
let mut clock_cache = Font::new(&ROBOTO_REGULAR, size);
|
||||||
clock_cache.add_str_to_cache("0123456789:");
|
clock_cache.add_str_to_cache("0123456789:");
|
||||||
|
|
||||||
@@ -45,6 +26,14 @@ impl Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Clock {
|
impl Widget for Clock {
|
||||||
|
fn wait(&self, ctx: &mut WaitContext) {
|
||||||
|
let target = (self.cur_time + Duration::seconds(60))
|
||||||
|
.with_second(0)
|
||||||
|
.unwrap()
|
||||||
|
.with_nanosecond(0)
|
||||||
|
.unwrap();
|
||||||
|
ctx.set_time(target);
|
||||||
|
}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {}
|
fn leave(&mut self) {}
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{Font, ROBOTO_REGULAR};
|
use crate::draw::{Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
||||||
|
|
||||||
use chrono::{DateTime, Datelike, Local};
|
use chrono::{DateTime, Datelike, Local};
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ impl Date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Date {
|
impl Widget for Date {
|
||||||
|
fn wait(&self, _: &mut WaitContext) {}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {}
|
fn leave(&mut self) {}
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::cmd::Cmd;
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::desktop::{load_desktop_files, Desktop};
|
use crate::desktop::{load_desktop_files, Desktop};
|
||||||
use crate::draw::{Font, ROBOTO_REGULAR};
|
use crate::draw::{Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@@ -192,6 +192,7 @@ fn wlcopy(s: &str) -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Launcher {
|
impl Widget for Launcher {
|
||||||
|
fn wait(&self, _: &mut WaitContext) {}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {
|
fn leave(&mut self) {
|
||||||
self.input = "".to_string();
|
self.input = "".to_string();
|
||||||
|
|||||||
Reference in New Issue
Block a user