From 832b381421d71a65016f8abc09862b2eeff75fc2 Mon Sep 17 00:00:00 2001 From: "Brian J. Tarricone" Date: Tue, 3 May 2022 23:47:06 -0700 Subject: [PATCH] Implement dialog timeout & timeout bar --- Makefile | 6 ++++ dialog-gtk3/src/main.rs | 73 +++++++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 2395d4f..553e23a 100644 --- a/Makefile +++ b/Makefile @@ -45,3 +45,9 @@ run: build-dev BSCREENSAVER_DIALOG_GTK3_LOG=$(DEV_LOG_LEVEL) \ HELPER_DIR=target/debug \ cargo run --bin bscreensaver + +run-dialog: + RUST_BACKTRACE=1 \ + BSCREENSAVER_DIALOG_GTK3_LOG=$(DEV_LOG_LEVEL) \ + BSCREENSAVER_DIALOG_STANDALONE=1 \ + cargo run --bin bscreensaver-dialog-gtk3 diff --git a/dialog-gtk3/src/main.rs b/dialog-gtk3/src/main.rs index 935fc49..e660c3c 100644 --- a/dialog-gtk3/src/main.rs +++ b/dialog-gtk3/src/main.rs @@ -4,10 +4,13 @@ use gethostname::gethostname; use glib::GString; use gtk::{prelude::*, Button, Entry, Label, Plug, Window}; use log::{debug, error}; -use std::{io::{self, Write}, process::exit, thread}; +use std::{io::{self, Write}, process::exit, rc::Rc, thread, time::Duration}; use bscreensaver_util::init_logging; +const DIALOG_UPDATE_INTERVAL: Duration = Duration::from_millis(100); +const DIALOG_TIMEOUT: Duration = Duration::from_secs(60); + fn main() -> anyhow::Result<()> { init_logging("BSCREENSAVER_DIALOG_GTK3_LOG"); @@ -183,14 +186,14 @@ fn main() -> anyhow::Result<()> { label_sg.add_widget(&label); hbox.pack_start(&label, false, true, 8); - let password_box = Entry::builder() + let password_box = Rc::new(Entry::builder() .visibility(false) .input_purpose(gtk::InputPurpose::Password) .activates_default(true) .width_chars(25) - .build(); - entry_sg.add_widget(&password_box); - hbox.pack_start(&password_box, true, true, 8); + .build()); + entry_sg.add_widget(&*password_box); + hbox.pack_start(&*password_box, true, true, 8); password_box.connect_key_press_event(|_, ev| { if ev.keyval().name() == Some(GString::from("Escape")) { exit(1); @@ -208,25 +211,59 @@ fn main() -> anyhow::Result<()> { let button = Button::builder() .label("Unlock") .build(); - button.connect_clicked(move |button| { - button.set_sensitive(false); - password_box.set_sensitive(false); + { + let password_box = Rc::clone(&password_box); + button.connect_clicked(move |button| { + button.set_sensitive(false); + password_box.set_sensitive(false); - let username = username.clone(); - let password = password_box.text().to_string(); - - thread::spawn(move || { - if authenticate(&username, &password) { - exit(0); - } else { - exit(-1); - } + let username = username.clone(); + let password = password_box.text().to_string(); + + thread::spawn(move || { + if authenticate(&username, &password) { + exit(0); + } else { + exit(-1); + } + }); }); - }); + } hbox.pack_end(&button, false, true, 8); button.set_can_default(true); button.set_has_default(true); + let timer = Rc::new(gtk::ProgressBar::builder() + .orientation(gtk::Orientation::Horizontal) + .fraction(1.0) + .show_text(false) + .can_focus(false) + .margin(2) + .build()); + top_vbox.pack_end(&*timer, false, false, 0); + + { + let timer = Rc::clone(&timer); + let delta = (DIALOG_UPDATE_INTERVAL.as_millis() as f64) / (DIALOG_TIMEOUT.as_millis() as f64); + gtk::glib::source::timeout_add_local(DIALOG_UPDATE_INTERVAL, move || { + let new_fraction = timer.fraction() - delta; + if new_fraction <= 0.0 { + exit(1); + } + timer.set_fraction(new_fraction); + Continue(true) + }); + } + + { + let timer = Rc::clone(&timer); + password_box.connect_key_press_event(move |_, _| { + let new_fraction = timer.fraction() + 0.05; + timer.set_fraction(if new_fraction >= 1.0 { 1.0 } else { new_fraction }); + Inhibit(false) + }); + } + dialog.show_all(); gtk::main();