feature: support ignoring all keypresses (#1719)

* refactor

* add no key setting

* do it here instead of in main loop
This commit is contained in:
Clement Tsang 2025-08-29 21:30:50 -04:00 committed by GitHub
parent 43e1b34899
commit d799c656aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 34 additions and 9 deletions

View File

@ -25,6 +25,7 @@ That said, these are more guidelines rather than hardset rules, though the proje
### Features
- [#1793](https://github.com/ClementTsang/bottom/pull/1793): Add support for threads in Linux.
- [#1719](https://github.com/ClementTsang/bottom/pull/1719): Support ignoring all keypresses.
### Bug Fixes

View File

@ -51,6 +51,7 @@ pub struct AppConfigFields {
pub use_old_network_legend: bool,
pub table_gap: u16,
pub disable_click: bool,
pub disable_keys: bool,
pub enable_gpu: bool,
pub enable_cache_memory: bool,
pub show_table_scroll_position: bool,

View File

@ -325,6 +325,9 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott
# Disable mouse clicks
#disable_click = false
# Disable keyboard shortcuts
#disable_keys = false
# Show memory values in the processes widget as values by default
#process_memory_as_value = false

View File

@ -145,7 +145,10 @@ fn panic_hook(panic_info: &PanicHookInfo<'_>) {
/// Create a thread to poll for user inputs and forward them to the main thread.
fn create_input_thread(
sender: Sender<BottomEvent>, cancellation_token: Arc<CancellationToken>,
app_config_fields: &AppConfigFields,
) -> JoinHandle<()> {
let keys_disabled = app_config_fields.disable_keys;
thread::spawn(move || {
let mut mouse_timer = Instant::now();
@ -177,7 +180,9 @@ fn create_input_thread(
break;
}
}
Event::Key(key) if key.kind == KeyEventKind::Press => {
Event::Key(key)
if !keys_disabled && key.kind == KeyEventKind::Press =>
{
// For now, we only care about key down events. This may change in
// the future.
if sender.send(BottomEvent::KeyInput(key)).is_err() {
@ -325,7 +330,11 @@ pub fn start_bottom(enable_error_hook: &mut bool) -> anyhow::Result<()> {
);
// Set up the input handling loop thread.
let _input_thread = create_input_thread(sender.clone(), cancellation_token.clone());
let _input_thread = create_input_thread(
sender.clone(),
cancellation_token.clone(),
&app.app_config_fields,
);
// Set up the cleaning loop thread.
let _cleaning_thread = {

View File

@ -306,6 +306,7 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
use_old_network_legend: is_flag_enabled!(use_old_network_legend, args.network, config),
table_gap: u16::from(!(is_flag_enabled!(hide_table_gap, args.general, config))),
disable_click: is_flag_enabled!(disable_click, args.general, config),
disable_keys: is_flag_enabled!(disable_keys, args.general, config),
enable_gpu: get_enable_gpu(args, config),
enable_cache_memory: get_enable_cache_memory(args, config),
show_table_scroll_position: is_flag_enabled!(
@ -1038,7 +1039,7 @@ mod test {
app::App,
args::BottomArgs,
options::{
config::flags::FlagConfig, get_default_time_value, get_retention, get_update_rate,
config::flags::GeneralConfig, get_default_time_value, get_retention, get_update_rate,
try_parse_ms,
},
};
@ -1117,7 +1118,7 @@ mod test {
let args = BottomArgs::parse_from(["btm"]);
let mut config = Config::default();
let flags = FlagConfig {
let flags = GeneralConfig {
time_delta: Some("2 min".to_string().into()),
default_time_value: Some("300s".to_string().into()),
rate: Some("1s".to_string().into()),
@ -1147,7 +1148,7 @@ mod test {
let args = BottomArgs::parse_from(["btm"]);
let mut config = Config::default();
let flags = FlagConfig {
let flags = GeneralConfig {
time_delta: Some("120000".to_string().into()),
default_time_value: Some("300000".to_string().into()),
rate: Some("1000".to_string().into()),
@ -1177,7 +1178,7 @@ mod test {
let args = BottomArgs::parse_from(["btm"]);
let mut config = Config::default();
let flags = FlagConfig {
let flags = GeneralConfig {
time_delta: Some(120000.into()),
default_time_value: Some(300000.into()),
rate: Some(1000.into()),

View File

@ -207,6 +207,15 @@ pub struct GeneralArgs {
)]
pub disable_click: bool,
#[arg(
long,
action = ArgAction::SetTrue,
help = "Disables keypresses.",
long_help = "Disables keypresses from interacting with bottom. Note this includes keyboard shortcuts to quit bottom.",
alias = "disable-keys"
)]
pub disable_keys: bool,
// TODO: Change this to accept a string with the type of marker.
#[arg(
short = 'm',

View File

@ -9,7 +9,7 @@ pub mod style;
pub mod temperature;
use disk::DiskConfig;
use flags::FlagConfig;
use flags::GeneralConfig;
use network::NetworkConfig;
use serde::{Deserialize, Serialize};
use style::StyleConfig;
@ -23,7 +23,7 @@ use self::{cpu::CpuConfig, layout::Row, process::ProcessesConfig};
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields), derive(PartialEq, Eq))]
pub struct Config {
pub(crate) flags: Option<FlagConfig>,
pub(crate) flags: Option<GeneralConfig>,
pub(crate) styles: Option<StyleConfig>,
pub(crate) row: Option<Vec<Row>>,
pub(crate) processes: Option<ProcessesConfig>,

View File

@ -6,7 +6,7 @@ use super::StringOrNum;
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields), derive(PartialEq, Eq))]
pub(crate) struct FlagConfig {
pub(crate) struct GeneralConfig {
pub(crate) hide_avg_cpu: Option<bool>,
pub(crate) dot_marker: Option<bool>,
pub(crate) temperature_type: Option<String>,
@ -30,6 +30,7 @@ pub(crate) struct FlagConfig {
pub(crate) hide_table_gap: Option<bool>,
pub(crate) battery: Option<bool>,
pub(crate) disable_click: Option<bool>,
pub(crate) disable_keys: Option<bool>,
pub(crate) no_write: Option<bool>,
pub(crate) network_legend: Option<String>,
pub(crate) memory_legend: Option<String>,