Make the new login button stuff more automatic
By default it'll look at your environment to try to figure out which display manager is used in order to start a new session. We first try the org.freedesktop.DisplayManager dbus interface, and if that fails, inspect XDG_SESSION_DESKTOP to try to figure out which display manager is running. The user can also still specify the correct display manager, or a custom command.
This commit is contained in:
@ -8,3 +8,4 @@ anyhow = "1"
|
||||
bscreensaver-util = { path = "../util" }
|
||||
glib = "0.15"
|
||||
gtk = { version = "0.15", features = ["v3_20"] }
|
||||
log = "0.4"
|
||||
|
@ -1,17 +1,20 @@
|
||||
use gtk::{glib, prelude::*};
|
||||
use glib::clone;
|
||||
use log::warn;
|
||||
use std::{env, process::exit, time::Duration};
|
||||
|
||||
use bscreensaver_util::settings::Configuration;
|
||||
use bscreensaver_util::{init_logging, settings::Configuration, desktop::NewLoginCommand};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Widgets {
|
||||
lock_timeout: gtk::SpinButton,
|
||||
blank_before_locking: gtk::SpinButton,
|
||||
new_login_command: gtk::Entry,
|
||||
new_login_command_combo: gtk::ComboBoxText,
|
||||
custom_new_login_command_entry: gtk::Entry,
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
init_logging("BSCREENSAVER_SETTINGS");
|
||||
let config = Configuration::load()?;
|
||||
|
||||
let app = gtk::Application::builder()
|
||||
@ -122,27 +125,83 @@ fn show_ui(app: >k::Application, config: &Configuration) {
|
||||
label_sg.add_widget(&label);
|
||||
hbox.pack_start(&label, false, false, 0);
|
||||
|
||||
let new_login_command_entry = gtk::Entry::builder()
|
||||
.text(config.new_login_command.as_ref().unwrap_or(&"".to_string()))
|
||||
.width_chars(30)
|
||||
.activates_default(true)
|
||||
let vbox = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Vertical)
|
||||
.spacing(8)
|
||||
.build();
|
||||
hbox.pack_start(&new_login_command_entry, false, false, 0);
|
||||
hbox.pack_start(&vbox, true, true, 0);
|
||||
|
||||
let new_login_command_combo = gtk::ComboBoxText::builder()
|
||||
.build();
|
||||
new_login_command_combo.append_text(NewLoginCommand::Auto.as_str());
|
||||
new_login_command_combo.append_text(NewLoginCommand::DisplayManagerDBus.as_str());
|
||||
new_login_command_combo.append_text(NewLoginCommand::Gdm.as_str());
|
||||
new_login_command_combo.append_text(NewLoginCommand::Kdm.as_str());
|
||||
new_login_command_combo.append_text(NewLoginCommand::LightDm.as_str());
|
||||
new_login_command_combo.append_text(NewLoginCommand::Lxdm.as_str());
|
||||
new_login_command_combo.append_text(NewLoginCommand::Custom("".to_string()).as_str());
|
||||
new_login_command_combo.append_text(NewLoginCommand::Disabled.as_str());
|
||||
vbox.pack_start(&new_login_command_combo, false, false, 0);
|
||||
|
||||
let (custom_new_login_command_hbox, custom_new_login_command_entry, custom_new_login_command_button) = {
|
||||
let hbox = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Horizontal)
|
||||
.spacing(8)
|
||||
.sensitive(false)
|
||||
.build();
|
||||
topvbox.pack_start(&hbox, false, false, 0);
|
||||
|
||||
let spacer = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Horizontal)
|
||||
.spacing(0)
|
||||
.build();
|
||||
label_sg.add_widget(&spacer);
|
||||
hbox.pack_start(&spacer, false, false, 0);
|
||||
|
||||
let label = gtk::Label::builder()
|
||||
.label("Custom Command:")
|
||||
.tooltip_text("Custom command to run when the 'New Login' button is clicked in the unlock dialog")
|
||||
.xalign(0.0)
|
||||
.build();
|
||||
hbox.pack_start(&label, false, false, 0);
|
||||
|
||||
let entry = gtk::Entry::builder()
|
||||
.width_chars(30)
|
||||
.activates_default(true)
|
||||
.build();
|
||||
hbox.pack_start(&entry, false, false, 0);
|
||||
|
||||
let button = gtk::Button::from_icon_name(Some("folder-open"), gtk::IconSize::Button);
|
||||
hbox.pack_start(&button, false, false, 0);
|
||||
|
||||
(hbox, entry, button)
|
||||
};
|
||||
|
||||
match &config.new_login_command {
|
||||
NewLoginCommand::Custom(cmd) => {
|
||||
custom_new_login_command_entry.set_text(cmd.as_str());
|
||||
custom_new_login_command_hbox.set_sensitive(true);
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
new_login_command_combo.set_active(Some(config.new_login_command.ord()));
|
||||
new_login_command_combo.connect_changed(clone!(@strong custom_new_login_command_hbox => move |combo| {
|
||||
let sensitive = combo.active().unwrap_or(0) == NewLoginCommand::Custom("".to_string()).ord();
|
||||
custom_new_login_command_hbox.set_sensitive(sensitive);
|
||||
}));
|
||||
|
||||
let widgets = Widgets {
|
||||
lock_timeout: lock_timeout_spinbutton.clone(),
|
||||
blank_before_locking: blank_before_locking_spinbutton.clone(),
|
||||
new_login_command: new_login_command_entry.clone(),
|
||||
new_login_command_combo: new_login_command_combo.clone(),
|
||||
custom_new_login_command_entry: custom_new_login_command_entry.clone(),
|
||||
};
|
||||
mainwin.connect_delete_event(clone!(@strong config, @strong widgets, @strong app, @strong mainwin => move |_,_| {
|
||||
Inhibit(!confirm_cancel(&config, &widgets, &mainwin))
|
||||
}));
|
||||
|
||||
let button = gtk::Button::from_icon_name(Some("folder-open"), gtk::IconSize::Button);
|
||||
button.connect_clicked(clone!(@strong mainwin, @strong widgets => move |_| {
|
||||
custom_new_login_command_button.connect_clicked(clone!(@strong mainwin, @strong widgets => move |_| {
|
||||
run_file_chooser(&mainwin, &widgets);
|
||||
}));
|
||||
hbox.pack_start(&button, false, false, 0);
|
||||
|
||||
let button_box = gtk::ButtonBox::builder()
|
||||
.spacing(8)
|
||||
@ -177,7 +236,7 @@ fn show_ui(app: >k::Application, config: &Configuration) {
|
||||
|
||||
fn run_file_chooser(mainwin: >k::ApplicationWindow, widgets: &Widgets) {
|
||||
let file_chooser = gtk::FileChooserNative::new(
|
||||
Some("New Login Command"),
|
||||
Some("Custom New Login Command"),
|
||||
Some(mainwin),
|
||||
gtk::FileChooserAction::Open,
|
||||
Some("Select"),
|
||||
@ -187,7 +246,7 @@ fn run_file_chooser(mainwin: >k::ApplicationWindow, widgets: &Widgets) {
|
||||
file_chooser.hide();
|
||||
if response == gtk::ResponseType::Accept {
|
||||
if let Some(filename) = file_chooser.filename() {
|
||||
widgets.new_login_command.set_text(&filename.to_string_lossy());
|
||||
widgets.custom_new_login_command_entry.set_text(&filename.to_string_lossy());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -243,7 +302,19 @@ fn build_new_configuration(old_config: &Configuration, widgets: &Widgets) -> (Co
|
||||
let mut new_config = old_config.clone();
|
||||
new_config.lock_timeout = Duration::from_secs(widgets.lock_timeout.adjustment().value() as u64 * 60);
|
||||
new_config.blank_before_locking = Duration::from_secs(widgets.blank_before_locking.adjustment().value() as u64 * 60);
|
||||
new_config.new_login_command = Some(widgets.new_login_command.text()).filter(|s| !s.is_empty()).map(|s| s.to_string());
|
||||
|
||||
new_config.new_login_command = match NewLoginCommand::try_from(widgets.new_login_command_combo.active().unwrap_or(0) as u32) {
|
||||
Ok(NewLoginCommand::Custom(_)) => Some(widgets.custom_new_login_command_entry.text())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| NewLoginCommand::Custom(s.to_string()))
|
||||
.unwrap_or(NewLoginCommand::Auto),
|
||||
Ok(nlc) => nlc,
|
||||
Err(_) => {
|
||||
warn!("BUG: couldn't figure out new login command type from combo box");
|
||||
NewLoginCommand::Auto
|
||||
},
|
||||
};
|
||||
|
||||
let changed = old_config != &new_config;
|
||||
(new_config, changed)
|
||||
}
|
||||
|
Reference in New Issue
Block a user