config: allow configuring repeat rates via toml
This commit is contained in:
parent
b374947b45
commit
1a9b7146fd
9 changed files with 241 additions and 2 deletions
|
|
@ -117,6 +117,9 @@ pub enum Action {
|
||||||
workspace: Option<Workspace>,
|
workspace: Option<Workspace>,
|
||||||
output: OutputMatch,
|
output: OutputMatch,
|
||||||
},
|
},
|
||||||
|
SetRepeatRate {
|
||||||
|
rate: RepeatRate,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
|
@ -269,9 +272,16 @@ pub enum ConfigKeymap {
|
||||||
Defined { name: String, map: Keymap },
|
Defined { name: String, map: Keymap },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RepeatRate {
|
||||||
|
pub rate: i32,
|
||||||
|
pub delay: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub keymap: Option<ConfigKeymap>,
|
pub keymap: Option<ConfigKeymap>,
|
||||||
|
pub repeat_rate: Option<RepeatRate>,
|
||||||
pub shortcuts: Vec<(ModifiedKeySym, Action)>,
|
pub shortcuts: Vec<(ModifiedKeySym, Action)>,
|
||||||
pub on_graphics_initialized: Option<Action>,
|
pub on_graphics_initialized: Option<Action>,
|
||||||
pub on_idle: Option<Action>,
|
pub on_idle: Option<Action>,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ mod mode;
|
||||||
pub mod modified_keysym;
|
pub mod modified_keysym;
|
||||||
mod output;
|
mod output;
|
||||||
mod output_match;
|
mod output_match;
|
||||||
|
mod repeat_rate;
|
||||||
pub mod shortcuts;
|
pub mod shortcuts;
|
||||||
mod status;
|
mod status;
|
||||||
mod theme;
|
mod theme;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use {
|
||||||
log_level::{LogLevelParser, LogLevelParserError},
|
log_level::{LogLevelParser, LogLevelParserError},
|
||||||
output::{OutputParser, OutputParserError},
|
output::{OutputParser, OutputParserError},
|
||||||
output_match::{OutputMatchParser, OutputMatchParserError},
|
output_match::{OutputMatchParser, OutputMatchParserError},
|
||||||
|
repeat_rate::{RepeatRateParser, RepeatRateParserError},
|
||||||
status::{StatusParser, StatusParserError},
|
status::{StatusParser, StatusParserError},
|
||||||
theme::{ThemeParser, ThemeParserError},
|
theme::{ThemeParser, ThemeParserError},
|
||||||
StringParser, StringParserError,
|
StringParser, StringParserError,
|
||||||
|
|
@ -77,6 +78,8 @@ pub enum ActionParserError {
|
||||||
ConfigureIdle(#[source] IdleParserError),
|
ConfigureIdle(#[source] IdleParserError),
|
||||||
#[error("Could not parse a move-to-output action")]
|
#[error("Could not parse a move-to-output action")]
|
||||||
MoveToOutput(#[source] OutputMatchParserError),
|
MoveToOutput(#[source] OutputMatchParserError),
|
||||||
|
#[error("Could not parse a set-repeat-rate action")]
|
||||||
|
RepeatRate(#[source] RepeatRateParserError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ActionParser<'a>(pub &'a Context<'a>);
|
pub struct ActionParser<'a>(pub &'a Context<'a>);
|
||||||
|
|
@ -295,6 +298,14 @@ impl ActionParser<'_> {
|
||||||
output,
|
output,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_set_repeat_rate(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
|
let rate = ext
|
||||||
|
.extract(val("rate"))?
|
||||||
|
.parse_map(&mut RepeatRateParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::RepeatRate)?;
|
||||||
|
Ok(Action::SetRepeatRate { rate })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser for ActionParser<'a> {
|
impl<'a> Parser for ActionParser<'a> {
|
||||||
|
|
@ -345,6 +356,7 @@ impl<'a> Parser for ActionParser<'a> {
|
||||||
"set-render-device" => self.parse_set_render_device(&mut ext),
|
"set-render-device" => self.parse_set_render_device(&mut ext),
|
||||||
"configure-idle" => self.parse_configure_idle(&mut ext),
|
"configure-idle" => self.parse_configure_idle(&mut ext),
|
||||||
"move-to-output" => self.parse_move_to_output(&mut ext),
|
"move-to-output" => self.parse_move_to_output(&mut ext),
|
||||||
|
"set-repeat-rate" => self.parse_set_repeat_rate(&mut ext),
|
||||||
v => {
|
v => {
|
||||||
ext.ignore_unused();
|
ext.ignore_unused();
|
||||||
return Err(ActionParserError::UnknownType(v.to_string()).spanned(ty.span));
|
return Err(ActionParserError::UnknownType(v.to_string()).spanned(ty.span));
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ use {
|
||||||
keymap::KeymapParser,
|
keymap::KeymapParser,
|
||||||
log_level::LogLevelParser,
|
log_level::LogLevelParser,
|
||||||
output::OutputsParser,
|
output::OutputsParser,
|
||||||
|
repeat_rate::RepeatRateParser,
|
||||||
shortcuts::{ShortcutsParser, ShortcutsParserError},
|
shortcuts::{ShortcutsParser, ShortcutsParserError},
|
||||||
status::StatusParser,
|
status::StatusParser,
|
||||||
theme::ThemeParser,
|
theme::ThemeParser,
|
||||||
|
|
@ -95,7 +96,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
_,
|
_,
|
||||||
idle_val,
|
idle_val,
|
||||||
),
|
),
|
||||||
(explicit_sync,),
|
(explicit_sync, repeat_rate_val),
|
||||||
) = ext.extract((
|
) = ext.extract((
|
||||||
(
|
(
|
||||||
opt(val("keymap")),
|
opt(val("keymap")),
|
||||||
|
|
@ -121,7 +122,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
opt(val("$schema")),
|
opt(val("$schema")),
|
||||||
opt(val("idle")),
|
opt(val("idle")),
|
||||||
),
|
),
|
||||||
(recover(opt(bol("explicit-sync"))),),
|
(recover(opt(bol("explicit-sync"))), opt(val("repeat-rate"))),
|
||||||
))?;
|
))?;
|
||||||
let mut keymap = None;
|
let mut keymap = None;
|
||||||
if let Some(value) = keymap_val {
|
if let Some(value) = keymap_val {
|
||||||
|
|
@ -256,8 +257,18 @@ impl Parser for ConfigParser<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut repeat_rate = None;
|
||||||
|
if let Some(value) = repeat_rate_val {
|
||||||
|
match value.parse(&mut RepeatRateParser(self.0)) {
|
||||||
|
Ok(v) => repeat_rate = Some(v),
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Could not parse the repeat rate: {}", self.0.error(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
keymap,
|
keymap,
|
||||||
|
repeat_rate,
|
||||||
shortcuts,
|
shortcuts,
|
||||||
on_graphics_initialized,
|
on_graphics_initialized,
|
||||||
on_idle,
|
on_idle,
|
||||||
|
|
|
||||||
45
toml-config/src/config/parsers/repeat_rate.rs
Normal file
45
toml-config/src/config/parsers/repeat_rate.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
config::{
|
||||||
|
context::Context,
|
||||||
|
extractor::{s32, Extractor, ExtractorError},
|
||||||
|
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||||
|
RepeatRate,
|
||||||
|
},
|
||||||
|
toml::{
|
||||||
|
toml_span::{Span, Spanned},
|
||||||
|
toml_value::Value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
indexmap::IndexMap,
|
||||||
|
thiserror::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum RepeatRateParserError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Expected(#[from] UnexpectedDataType),
|
||||||
|
#[error(transparent)]
|
||||||
|
Extract(#[from] ExtractorError),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RepeatRateParser<'a>(pub &'a Context<'a>);
|
||||||
|
|
||||||
|
impl Parser for RepeatRateParser<'_> {
|
||||||
|
type Value = RepeatRate;
|
||||||
|
type Error = RepeatRateParserError;
|
||||||
|
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
||||||
|
|
||||||
|
fn parse_table(
|
||||||
|
&mut self,
|
||||||
|
span: Span,
|
||||||
|
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||||
|
) -> ParseResult<Self> {
|
||||||
|
let mut ext = Extractor::new(self.0, span, table);
|
||||||
|
let (rate, delay) = ext.extract((s32("rate"), s32("delay")))?;
|
||||||
|
Ok(RepeatRate {
|
||||||
|
rate: rate.value,
|
||||||
|
delay: delay.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -172,6 +172,9 @@ impl Action {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Action::SetRepeatRate { rate } => {
|
||||||
|
Box::new(move || s.set_repeat_rate(rate.rate, rate.delay))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -728,6 +731,11 @@ fn load_config(initial_load: bool, persistent: &Rc<PersistentState>) {
|
||||||
if let Some(keymap) = config.keymap {
|
if let Some(keymap) = config.keymap {
|
||||||
state.set_keymap(&keymap);
|
state.set_keymap(&keymap);
|
||||||
}
|
}
|
||||||
|
if let Some(repeat_rate) = config.repeat_rate {
|
||||||
|
persistent
|
||||||
|
.seat
|
||||||
|
.set_repeat_rate(repeat_rate.rate, repeat_rate.delay);
|
||||||
|
}
|
||||||
on_new_connector(move |c| {
|
on_new_connector(move |c| {
|
||||||
for connector in &config.connectors {
|
for connector in &config.connectors {
|
||||||
if connector.match_.matches(c) {
|
if connector.match_.matches(c) {
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,23 @@
|
||||||
"keymap"
|
"keymap"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": "Sets the keyboard repeat rate.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-x = { type = \"set-repeat-rate\", rate = { rate = 25, delay = 250 } }\n ```\n",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"const": "set-repeat-rate"
|
||||||
|
},
|
||||||
|
"rate": {
|
||||||
|
"description": "The rate.",
|
||||||
|
"$ref": "#/$defs/RepeatRate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"rate"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Sets the status command.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-j = { type = \"set-status\", status = { exec = \"i3status\" } }\n ```\n",
|
"description": "Sets the status command.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-j = { type = \"set-status\", status = { exec = \"i3status\" } }\n ```\n",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
@ -418,6 +435,10 @@
|
||||||
"description": "The keymap to use.\n\n- Example:\n\n ```toml\n keymap = \"\"\"\n xkb_keymap {\n xkb_keycodes { include \"evdev+aliases(qwerty)\" };\n xkb_types { include \"complete\" };\n xkb_compat { include \"complete\" };\n xkb_symbols { include \"pc+us+inet(evdev)\" };\n };\n \"\"\"\n ```\n",
|
"description": "The keymap to use.\n\n- Example:\n\n ```toml\n keymap = \"\"\"\n xkb_keymap {\n xkb_keycodes { include \"evdev+aliases(qwerty)\" };\n xkb_types { include \"complete\" };\n xkb_compat { include \"complete\" };\n xkb_symbols { include \"pc+us+inet(evdev)\" };\n };\n \"\"\"\n ```\n",
|
||||||
"$ref": "#/$defs/Keymap"
|
"$ref": "#/$defs/Keymap"
|
||||||
},
|
},
|
||||||
|
"repeat-rate": {
|
||||||
|
"description": "The keyboard repeat rate.\n\n- Example:\n \n ```toml\n repeat-rate = { rate = 25, delay = 250 }\n ```\n",
|
||||||
|
"$ref": "#/$defs/RepeatRate"
|
||||||
|
},
|
||||||
"shortcuts": {
|
"shortcuts": {
|
||||||
"description": "The compositor shortcuts.\n\nThe keys should be in the following format:\n\n```\n(MOD-)*KEYSYM\n```\n\n`MOD` should be one of `shift`, `lock`, `ctrl`, `mod1`, `mod2`, `mod3`, `mod4`,\n`mod5`, `caps`, `alt`, `num`, or `logo`.\n\n`KEYSYM` should be the name of a keysym. The authorative location for these names\nis [1] with the `XKB_KEY_` prefix removed.\n\nThe keysym should be the unmodified keysym. E.g. `shift-q` not `shift-Q`.\n\n[1]: https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n",
|
"description": "The compositor shortcuts.\n\nThe keys should be in the following format:\n\n```\n(MOD-)*KEYSYM\n```\n\n`MOD` should be one of `shift`, `lock`, `ctrl`, `mod1`, `mod2`, `mod3`, `mod4`,\n`mod5`, `caps`, `alt`, `num`, or `logo`.\n\n`KEYSYM` should be the name of a keysym. The authorative location for these names\nis [1] with the `XKB_KEY_` prefix removed.\n\nThe keysym should be the unmodified keysym. E.g. `shift-q` not `shift-Q`.\n\n[1]: https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
@ -985,6 +1006,24 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"RepeatRate": {
|
||||||
|
"description": "Describes a keyboard repeat rate.\n\n- Example:\n\n ```toml\n repeat-rate = { rate = 25, delay = 250 }\n ```\n",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"rate": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The number of times to repeat per second."
|
||||||
|
},
|
||||||
|
"delay": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The number of milliseconds after a key is pressed before repeating begins.\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"rate",
|
||||||
|
"delay"
|
||||||
|
]
|
||||||
|
},
|
||||||
"SimpleActionName": {
|
"SimpleActionName": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of a `simple` Action.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n",
|
"description": "The name of a `simple` Action.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n",
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,25 @@ This table is a tagged union. The variant is determined by the `type` field. It
|
||||||
|
|
||||||
The value of this field should be a [Keymap](#types-Keymap).
|
The value of this field should be a [Keymap](#types-Keymap).
|
||||||
|
|
||||||
|
- `set-repeat-rate`:
|
||||||
|
|
||||||
|
Sets the keyboard repeat rate.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
alt-x = { type = "set-repeat-rate", rate = { rate = 25, delay = 250 } }
|
||||||
|
```
|
||||||
|
|
||||||
|
The table has the following fields:
|
||||||
|
|
||||||
|
- `rate` (required):
|
||||||
|
|
||||||
|
The rate.
|
||||||
|
|
||||||
|
The value of this field should be a [RepeatRate](#types-RepeatRate).
|
||||||
|
|
||||||
- `set-status`:
|
- `set-status`:
|
||||||
|
|
||||||
Sets the status command.
|
Sets the status command.
|
||||||
|
|
@ -652,6 +671,18 @@ The table has the following fields:
|
||||||
|
|
||||||
The value of this field should be a [Keymap](#types-Keymap).
|
The value of this field should be a [Keymap](#types-Keymap).
|
||||||
|
|
||||||
|
- `repeat-rate` (optional):
|
||||||
|
|
||||||
|
The keyboard repeat rate.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
repeat-rate = { rate = 25, delay = 250 }
|
||||||
|
```
|
||||||
|
|
||||||
|
The value of this field should be a [RepeatRate](#types-RepeatRate).
|
||||||
|
|
||||||
- `shortcuts` (optional):
|
- `shortcuts` (optional):
|
||||||
|
|
||||||
The compositor shortcuts.
|
The compositor shortcuts.
|
||||||
|
|
@ -2038,6 +2069,38 @@ The table has the following fields:
|
||||||
The value of this field should be a string.
|
The value of this field should be a string.
|
||||||
|
|
||||||
|
|
||||||
|
<a name="types-RepeatRate"></a>
|
||||||
|
### `RepeatRate`
|
||||||
|
|
||||||
|
Describes a keyboard repeat rate.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
repeat-rate = { rate = 25, delay = 250 }
|
||||||
|
```
|
||||||
|
|
||||||
|
Values of this type should be tables.
|
||||||
|
|
||||||
|
The table has the following fields:
|
||||||
|
|
||||||
|
- `rate` (required):
|
||||||
|
|
||||||
|
The number of times to repeat per second.
|
||||||
|
|
||||||
|
The value of this field should be a number.
|
||||||
|
|
||||||
|
The numbers should be integers.
|
||||||
|
|
||||||
|
- `delay` (required):
|
||||||
|
|
||||||
|
The number of milliseconds after a key is pressed before repeating begins.
|
||||||
|
|
||||||
|
The value of this field should be a number.
|
||||||
|
|
||||||
|
The numbers should be integers.
|
||||||
|
|
||||||
|
|
||||||
<a name="types-SimpleActionName"></a>
|
<a name="types-SimpleActionName"></a>
|
||||||
### `SimpleActionName`
|
### `SimpleActionName`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,21 @@ Action:
|
||||||
description: The keymap.
|
description: The keymap.
|
||||||
required: true
|
required: true
|
||||||
ref: Keymap
|
ref: Keymap
|
||||||
|
set-repeat-rate:
|
||||||
|
description: |
|
||||||
|
Sets the keyboard repeat rate.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
alt-x = { type = "set-repeat-rate", rate = { rate = 25, delay = 250 } }
|
||||||
|
```
|
||||||
|
fields:
|
||||||
|
rate:
|
||||||
|
description: The rate.
|
||||||
|
required: true
|
||||||
|
ref: RepeatRate
|
||||||
set-status:
|
set-status:
|
||||||
description: |
|
description: |
|
||||||
Sets the status command.
|
Sets the status command.
|
||||||
|
|
@ -1649,6 +1664,17 @@ Config:
|
||||||
};
|
};
|
||||||
"""
|
"""
|
||||||
```
|
```
|
||||||
|
repeat-rate:
|
||||||
|
ref: RepeatRate
|
||||||
|
required: false
|
||||||
|
description: |
|
||||||
|
The keyboard repeat rate.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
repeat-rate = { rate = 25, delay = 250 }
|
||||||
|
```
|
||||||
shortcuts:
|
shortcuts:
|
||||||
kind: map
|
kind: map
|
||||||
values:
|
values:
|
||||||
|
|
@ -1983,3 +2009,27 @@ Idle:
|
||||||
integer_only: true
|
integer_only: true
|
||||||
minimum: 0
|
minimum: 0
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
|
|
||||||
|
RepeatRate:
|
||||||
|
kind: table
|
||||||
|
description: |
|
||||||
|
Describes a keyboard repeat rate.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
repeat-rate = { rate = 25, delay = 250 }
|
||||||
|
```
|
||||||
|
fields:
|
||||||
|
rate:
|
||||||
|
kind: number
|
||||||
|
integer_only: true
|
||||||
|
required: true
|
||||||
|
description: The number of times to repeat per second.
|
||||||
|
delay:
|
||||||
|
kind: number
|
||||||
|
integer_only: true
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
The number of milliseconds after a key is pressed before repeating begins.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue