Make use of SIGWINCH.
This commit is contained in:
parent
074a22f2d9
commit
851c950625
3 changed files with 40 additions and 15 deletions
|
@ -1,5 +1,6 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
use termion::{color, cursor, style};
|
use termion::{color, cursor, style};
|
||||||
use termion::raw::RawTerminal;
|
use termion::raw::RawTerminal;
|
||||||
use crate::{Clock, Config, Layout, Position};
|
use crate::{Clock, Config, Layout, Position};
|
||||||
|
@ -239,7 +240,7 @@ impl AlarmRoster {
|
||||||
// Update layout information.
|
// Update layout information.
|
||||||
if layout.roster_width != width {
|
if layout.roster_width != width {
|
||||||
layout.roster_width = width;
|
layout.roster_width = width;
|
||||||
layout.force_recalc = true;
|
layout.force_recalc.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
|
@ -13,7 +15,7 @@ pub struct Position {
|
||||||
|
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
pub force_redraw: bool, // Redraw elements on screen.
|
pub force_redraw: bool, // Redraw elements on screen.
|
||||||
pub force_recalc: bool, // Recalculate position of elements.
|
pub force_recalc: Arc<AtomicBool>, // Recalculate position of elements.
|
||||||
pub plain: bool, // Plain style clock.
|
pub plain: bool, // Plain style clock.
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
pub height: u16,
|
pub height: u16,
|
||||||
|
@ -34,7 +36,8 @@ impl Layout {
|
||||||
pub fn new(config: &Config) -> Layout {
|
pub fn new(config: &Config) -> Layout {
|
||||||
Layout {
|
Layout {
|
||||||
force_redraw: true,
|
force_redraw: true,
|
||||||
force_recalc: false,
|
// May be set by signal handler (SIGWINCH).
|
||||||
|
force_recalc: Arc::new(AtomicBool::new(true)),
|
||||||
plain: config.plain,
|
plain: config.plain,
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
|
@ -53,15 +56,13 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, display_hours: bool) {
|
pub fn update(&mut self, display_hours: bool) {
|
||||||
|
if self.force_recalc.swap(false, Ordering::Relaxed) {
|
||||||
let (width, height) = termion::terminal_size()
|
let (width, height) = termion::terminal_size()
|
||||||
.expect("Could not read terminal size!");
|
.expect("Could not read terminal size!");
|
||||||
|
|
||||||
if self.force_recalc || self.width != width || self.height != height {
|
|
||||||
self.width = width;
|
self.width = width;
|
||||||
self.height = height;
|
self.height = height;
|
||||||
self.compute(display_hours);
|
self.compute(display_hours);
|
||||||
self.force_redraw = true;
|
self.force_redraw = true;
|
||||||
self.force_recalc = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
src/main.rs
37
src/main.rs
|
@ -37,6 +37,8 @@ const MENUBAR_SHORT: &str =
|
||||||
"[0-9] Add [d] Delete [SPACE] Pause [r] Reset [c] Clear [q] Quit";
|
"[0-9] Add [d] Delete [SPACE] Pause [r] Reset [c] Clear [q] Quit";
|
||||||
// Needed for signal_hook.
|
// Needed for signal_hook.
|
||||||
const SIGTSTP: usize = signal_hook::consts::SIGTSTP as usize;
|
const SIGTSTP: usize = signal_hook::consts::SIGTSTP as usize;
|
||||||
|
const SIGWINCH: usize = signal_hook::consts::SIGWINCH as usize;
|
||||||
|
const SIGCONT: usize = signal_hook::consts::SIGCONT as usize;
|
||||||
const SIGTERM: usize = signal_hook::consts::SIGTERM as usize;
|
const SIGTERM: usize = signal_hook::consts::SIGTERM as usize;
|
||||||
const SIGINT: usize = signal_hook::consts::SIGINT as usize;
|
const SIGINT: usize = signal_hook::consts::SIGINT as usize;
|
||||||
const SIGUSR1: usize = signal_hook::consts::SIGUSR1 as usize;
|
const SIGUSR1: usize = signal_hook::consts::SIGUSR1 as usize;
|
||||||
|
@ -71,8 +73,9 @@ fn main() {
|
||||||
// Register signal handlers.
|
// Register signal handlers.
|
||||||
let signal = Arc::new(AtomicUsize::new(0));
|
let signal = Arc::new(AtomicUsize::new(0));
|
||||||
register_signal_handlers(&signal);
|
register_signal_handlers(&signal);
|
||||||
|
flag::register(SIGWINCH as i32, Arc::clone(&layout.force_recalc)).unwrap();
|
||||||
|
|
||||||
// Clear screen and hide cursor.
|
// Clear window and hide cursor.
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
"{}{}",
|
"{}{}",
|
||||||
clear::All,
|
clear::All,
|
||||||
|
@ -91,6 +94,14 @@ fn main() {
|
||||||
// Suspend execution on SIGTSTP.
|
// Suspend execution on SIGTSTP.
|
||||||
SIGTSTP => {
|
SIGTSTP => {
|
||||||
suspend(&mut stdout);
|
suspend(&mut stdout);
|
||||||
|
// Clear SIGCONT and continue from here.
|
||||||
|
signal.compare_and_swap(SIGCONT, 0, Ordering::Relaxed);
|
||||||
|
continue_after_suspend(&mut stdout);
|
||||||
|
layout.force_redraw = true;
|
||||||
|
},
|
||||||
|
// Continuing after SIGSTOP.
|
||||||
|
SIGCONT => {
|
||||||
|
continue_after_suspend(&mut stdout);
|
||||||
layout.force_redraw = true;
|
layout.force_redraw = true;
|
||||||
},
|
},
|
||||||
// Exit main loop on SIGTERM and SIGINT.
|
// Exit main loop on SIGTERM and SIGINT.
|
||||||
|
@ -103,6 +114,8 @@ fn main() {
|
||||||
},
|
},
|
||||||
// (Un-)Pause clock on SIGUSR2.
|
// (Un-)Pause clock on SIGUSR2.
|
||||||
SIGUSR2 => clock.toggle(),
|
SIGUSR2 => clock.toggle(),
|
||||||
|
// Window size changed.
|
||||||
|
//SIGWINCH => layout.force_recalc = true,
|
||||||
// We didn't register anything else.
|
// We didn't register anything else.
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -141,6 +154,9 @@ fn main() {
|
||||||
// Suspend an ^Z.
|
// Suspend an ^Z.
|
||||||
Key::Ctrl('z') => {
|
Key::Ctrl('z') => {
|
||||||
suspend(&mut stdout);
|
suspend(&mut stdout);
|
||||||
|
// Clear SIGCONT and continue from here.
|
||||||
|
signal.compare_and_swap(SIGCONT, 0, Ordering::Relaxed);
|
||||||
|
continue_after_suspend(&mut stdout);
|
||||||
layout.force_redraw = true;
|
layout.force_redraw = true;
|
||||||
},
|
},
|
||||||
// Enter.
|
// Enter.
|
||||||
|
@ -197,7 +213,7 @@ fn main() {
|
||||||
clock.start.elapsed().as_secs() as u32
|
clock.start.elapsed().as_secs() as u32
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update screen content if necessary.
|
// Update window content if necessary.
|
||||||
if elapsed != clock.elapsed || layout.force_redraw {
|
if elapsed != clock.elapsed || layout.force_redraw {
|
||||||
// Update clock. Advance one day after 24 hours.
|
// Update clock. Advance one day after 24 hours.
|
||||||
if elapsed < 24 * 60 * 60 {
|
if elapsed < 24 * 60 * 60 {
|
||||||
|
@ -206,12 +222,14 @@ fn main() {
|
||||||
clock.next_day();
|
clock.next_day();
|
||||||
// "clock.elapsed" set by "clock.next_day()".
|
// "clock.elapsed" set by "clock.next_day()".
|
||||||
alarm_roster.reset_all();
|
alarm_roster.reset_all();
|
||||||
layout.force_recalc = true;
|
layout.force_recalc.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force recalculation of layout if we start displaying hours.
|
// Force recalculation of layout if we start displaying hours.
|
||||||
if clock.elapsed == 3600 { layout.force_recalc = true };
|
if clock.elapsed == 3600 {
|
||||||
// Update screen size information and calculate the clock position.
|
layout.force_recalc.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
// Update window size information and calculate the clock position.
|
||||||
layout.update(clock.elapsed >= 3600);
|
layout.update(clock.elapsed >= 3600);
|
||||||
|
|
||||||
// Check for exceeded alarms.
|
// Check for exceeded alarms.
|
||||||
|
@ -226,7 +244,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the screen and redraw menu bar, alarm roster and buffer if
|
// Clear the window and redraw menu bar, alarm roster and buffer if
|
||||||
// requested.
|
// requested.
|
||||||
if layout.force_redraw {
|
if layout.force_redraw {
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
|
@ -268,7 +286,7 @@ fn main() {
|
||||||
thread::sleep(time::Duration::from_millis(100));
|
thread::sleep(time::Duration::from_millis(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main loop exited. Clear screen and restore cursor.
|
// Main loop exited. Clear window and restore cursor.
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
clear::BeforeCursor,
|
clear::BeforeCursor,
|
||||||
|
@ -312,6 +330,7 @@ fn parse_args(config: &mut Config) {
|
||||||
|
|
||||||
fn register_signal_handlers(signal: &Arc<AtomicUsize>) {
|
fn register_signal_handlers(signal: &Arc<AtomicUsize>) {
|
||||||
flag::register_usize(SIGTSTP as i32, Arc::clone(&signal), SIGTSTP).unwrap();
|
flag::register_usize(SIGTSTP as i32, Arc::clone(&signal), SIGTSTP).unwrap();
|
||||||
|
flag::register_usize(SIGCONT as i32, Arc::clone(&signal), SIGCONT).unwrap();
|
||||||
flag::register_usize(SIGTERM as i32, Arc::clone(&signal), SIGTERM).unwrap();
|
flag::register_usize(SIGTERM as i32, Arc::clone(&signal), SIGTERM).unwrap();
|
||||||
flag::register_usize(SIGINT as i32, Arc::clone(&signal), SIGINT).unwrap();
|
flag::register_usize(SIGINT as i32, Arc::clone(&signal), SIGINT).unwrap();
|
||||||
flag::register_usize(SIGUSR1 as i32, Arc::clone(&signal), SIGUSR1).unwrap();
|
flag::register_usize(SIGUSR1 as i32, Arc::clone(&signal), SIGUSR1).unwrap();
|
||||||
|
@ -335,7 +354,10 @@ fn suspend<W: Write>(stdout: &mut RawTerminal<W>) {
|
||||||
if let Err(error) = signal_hook::low_level::emulate_default_handler(SIGTSTP as i32) {
|
if let Err(error) = signal_hook::low_level::emulate_default_handler(SIGTSTP as i32) {
|
||||||
eprintln!("Error raising SIGTSTP: {}", error);
|
eprintln!("Error raising SIGTSTP: {}", error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up terminal when continuing from SIGTSTP or SIGSTOP.
|
||||||
|
fn continue_after_suspend<W: Write>(stdout: &mut RawTerminal<W>) {
|
||||||
stdout.activate_raw_mode()
|
stdout.activate_raw_mode()
|
||||||
.unwrap_or_else(|error| {
|
.unwrap_or_else(|error| {
|
||||||
eprintln!("Failed to re-enter raw terminal mode after suspend: {}", error);
|
eprintln!("Failed to re-enter raw terminal mode after suspend: {}", error);
|
||||||
|
@ -349,6 +371,7 @@ fn suspend<W: Write>(stdout: &mut RawTerminal<W>) {
|
||||||
eprintln!("Error writing to stdout: {}", error);
|
eprintln!("Error writing to stdout: {}", error);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
});
|
});
|
||||||
|
stdout.flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw input buffer.
|
// Draw input buffer.
|
||||||
|
|
Loading…
Reference in a new issue