refactor(keyboard): use context drawers for special character keys
This commit is contained in:
parent
29f0489c8a
commit
2b88275af8
4 changed files with 143 additions and 144 deletions
|
|
@ -60,6 +60,7 @@ impl SettingsApp {
|
||||||
PageCommands::DesktopPanel => self.pages.page_id::<desktop::options::Page>(),
|
PageCommands::DesktopPanel => self.pages.page_id::<desktop::options::Page>(),
|
||||||
PageCommands::Displays => self.pages.page_id::<display::Page>(),
|
PageCommands::Displays => self.pages.page_id::<display::Page>(),
|
||||||
PageCommands::Firmware => self.pages.page_id::<system::firmware::Page>(),
|
PageCommands::Firmware => self.pages.page_id::<system::firmware::Page>(),
|
||||||
|
PageCommands::Keyboard => self.pages.page_id::<input::keyboard::Page>(),
|
||||||
PageCommands::Mouse => self.pages.page_id::<input::mouse::Page>(),
|
PageCommands::Mouse => self.pages.page_id::<input::mouse::Page>(),
|
||||||
PageCommands::Network => None,
|
PageCommands::Network => None,
|
||||||
PageCommands::Notifications => self.pages.page_id::<desktop::notifications::Page>(),
|
PageCommands::Notifications => self.pages.page_id::<desktop::notifications::Page>(),
|
||||||
|
|
@ -316,6 +317,12 @@ impl cosmic::Application for SettingsApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate::pages::Message::Keyboard(message) => {
|
||||||
|
if let Some(page) = self.pages.page_mut::<input::keyboard::Page>() {
|
||||||
|
return page.update(message).map(cosmic::app::Message::App);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crate::pages::Message::Input(message) => {
|
crate::pages::Message::Input(message) => {
|
||||||
if let Some(page) = self.pages.page_mut::<input::Page>() {
|
if let Some(page) = self.pages.page_mut::<input::Page>() {
|
||||||
return page.update(message).map(cosmic::app::Message::App);
|
return page.update(message).map(cosmic::app::Message::App);
|
||||||
|
|
@ -498,17 +505,17 @@ impl cosmic::Application for SettingsApp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(Some(page)) = (id == *keyboard::ADD_INPUT_SOURCE_DIALOGUE_ID)
|
// if let Some(Some(page)) = (id == *keyboard::ADD_INPUT_SOURCE_DIALOGUE_ID)
|
||||||
.then(|| self.pages.page::<input::Page>())
|
// .then(|| self.pages.page::<input::Page>())
|
||||||
{
|
// {
|
||||||
return page.add_input_source_view();
|
// return page.add_input_source_view();
|
||||||
}
|
// }
|
||||||
|
|
||||||
if let Some(Some(page)) = (id == *keyboard::SPECIAL_CHARACTER_DIALOGUE_ID)
|
// if let Some(Some(page)) = (id == *keyboard::SPECIAL_CHARACTER_DIALOGUE_ID)
|
||||||
.then(|| self.pages.page::<input::Page>())
|
// .then(|| self.pages.page::<input::Page>())
|
||||||
{
|
// {
|
||||||
return page.special_character_key_view();
|
// return page.special_character_key_view();
|
||||||
}
|
// }
|
||||||
|
|
||||||
if let Some(page) = self.pages.page::<desktop::wallpaper::Page>() {
|
if let Some(page) = self.pages.page::<desktop::wallpaper::Page>() {
|
||||||
if id == page.color_dialog {
|
if id == page.color_dialog {
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,20 @@
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
|
cosmic_config::{self, ConfigSet},
|
||||||
iced::{
|
iced::{
|
||||||
self,
|
self,
|
||||||
widget::{self, horizontal_space},
|
widget::{self, horizontal_space},
|
||||||
window, Length,
|
Length,
|
||||||
},
|
},
|
||||||
iced_core::Border,
|
iced_core::Border,
|
||||||
iced_style, theme,
|
iced_style, theme,
|
||||||
widget::{button, container, icon, radio, settings},
|
widget::{button, container, icon, radio, settings},
|
||||||
Apply,
|
Apply, Command, Element,
|
||||||
};
|
};
|
||||||
|
use cosmic_comp_config::XkbConfig;
|
||||||
use cosmic_settings_page::{self as page, section, Section};
|
use cosmic_settings_page::{self as page, section, Section};
|
||||||
use once_cell::sync::Lazy;
|
use itertools::Itertools;
|
||||||
use slotmap::SlotMap;
|
use slotmap::SlotMap;
|
||||||
|
|
||||||
use super::Message;
|
|
||||||
|
|
||||||
pub static ADD_INPUT_SOURCE_DIALOGUE_ID: Lazy<window::Id> = Lazy::new(window::Id::unique);
|
|
||||||
pub static SPECIAL_CHARACTER_DIALOGUE_ID: Lazy<window::Id> = Lazy::new(window::Id::unique);
|
|
||||||
|
|
||||||
static COMPOSE_OPTIONS: &[(&str, &str)] = &[
|
static COMPOSE_OPTIONS: &[(&str, &str)] = &[
|
||||||
// ("Left Alt", "compose:lalt"), XXX?
|
// ("Left Alt", "compose:lalt"), XXX?
|
||||||
("Right Alt", "compose:ralt"),
|
("Right Alt", "compose:ralt"),
|
||||||
|
|
@ -42,6 +39,39 @@ static ALTERNATE_CHARACTER_OPTIONS: &[(&str, &str)] = &[
|
||||||
// ("Print Screen", "lv3"), XXX
|
// ("Print Screen", "lv3"), XXX
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Message {
|
||||||
|
ExpandInputSourcePopover(Option<String>),
|
||||||
|
OpenSpecialCharacterContext(SpecialKey),
|
||||||
|
SpecialCharacterSelect(Option<&'static str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Page {
|
||||||
|
config: cosmic_config::Config,
|
||||||
|
context: Option<Context>,
|
||||||
|
expanded_source_popover: Option<String>,
|
||||||
|
sources: Vec<InputSource>,
|
||||||
|
xkb: XkbConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Page {
|
||||||
|
fn default() -> Self {
|
||||||
|
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
context: None,
|
||||||
|
expanded_source_popover: None,
|
||||||
|
sources: default_input_sources(),
|
||||||
|
xkb: super::get_config(&config, "xkb_config"),
|
||||||
|
config,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Context {
|
||||||
|
SpecialCharacter(SpecialKey),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum SpecialKey {
|
pub enum SpecialKey {
|
||||||
AlternateCharacters,
|
AlternateCharacters,
|
||||||
|
|
@ -144,54 +174,6 @@ pub struct InputSource {
|
||||||
label: String,
|
label: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Page {
|
|
||||||
pub fn add_input_source_view(&self) -> cosmic::Element<'static, crate::app::Message> {
|
|
||||||
widget::column![].into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn special_character_key_view(&self) -> cosmic::Element<'_, crate::app::Message> {
|
|
||||||
let Some(special_key) = self.special_character_dialog else {
|
|
||||||
return widget::text("").into();
|
|
||||||
};
|
|
||||||
|
|
||||||
let options = match special_key {
|
|
||||||
SpecialKey::Compose => COMPOSE_OPTIONS,
|
|
||||||
SpecialKey::AlternateCharacters => ALTERNATE_CHARACTER_OPTIONS,
|
|
||||||
};
|
|
||||||
let prefix = special_key.prefix();
|
|
||||||
let current = self
|
|
||||||
.xkb
|
|
||||||
.options
|
|
||||||
.iter()
|
|
||||||
.flat_map(|x| x.split(','))
|
|
||||||
.find(|x| x.starts_with(prefix));
|
|
||||||
|
|
||||||
// TODO description, layout default
|
|
||||||
|
|
||||||
let mut list = cosmic::widget::list_column();
|
|
||||||
list = list.add(special_char_radio_row("None", None, current));
|
|
||||||
for (desc, id) in options {
|
|
||||||
list = list.add(special_char_radio_row(desc, Some(id), current));
|
|
||||||
}
|
|
||||||
widget::column![
|
|
||||||
cosmic::widget::header_bar()
|
|
||||||
.title(special_key.title())
|
|
||||||
.on_close(Message::CloseSpecialCharacterDialog),
|
|
||||||
cosmic::widget::container(
|
|
||||||
cosmic::widget::scrollable(cosmic::widget::container(list).padding(24))
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill)
|
|
||||||
)
|
|
||||||
.style(theme::Container::Background)
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill)
|
|
||||||
]
|
|
||||||
.apply(cosmic::Element::from)
|
|
||||||
.map(crate::pages::Message::Input)
|
|
||||||
.map(crate::app::Message::PageMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn special_char_radio_row<'a>(
|
fn special_char_radio_row<'a>(
|
||||||
desc: &'a str,
|
desc: &'a str,
|
||||||
value: Option<&'static str>,
|
value: Option<&'static str>,
|
||||||
|
|
@ -204,9 +186,6 @@ fn special_char_radio_row<'a>(
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Page;
|
|
||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
pub fn default_input_sources() -> Vec<InputSource> {
|
pub fn default_input_sources() -> Vec<InputSource> {
|
||||||
vec![InputSource {
|
vec![InputSource {
|
||||||
|
|
@ -232,6 +211,85 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
.title(fl!("keyboard"))
|
.title(fl!("keyboard"))
|
||||||
.description(fl!("keyboard", "desc"))
|
.description(fl!("keyboard", "desc"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
|
||||||
|
match self.context {
|
||||||
|
Some(Context::SpecialCharacter(special_key)) => self
|
||||||
|
.special_character_key_view(special_key)
|
||||||
|
.map(crate::pages::Message::Keyboard)
|
||||||
|
.apply(Some),
|
||||||
|
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Page {
|
||||||
|
pub fn update(&mut self, message: Message) -> Command<crate::app::Message> {
|
||||||
|
match message {
|
||||||
|
Message::ExpandInputSourcePopover(value) => {
|
||||||
|
self.expanded_source_popover = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::OpenSpecialCharacterContext(key) => {
|
||||||
|
self.context = Some(Context::SpecialCharacter(key));
|
||||||
|
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
|
||||||
|
key.title().into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::SpecialCharacterSelect(id) => {
|
||||||
|
if let Some(Context::SpecialCharacter(special_key)) = self.context {
|
||||||
|
let options = self.xkb.options.as_deref().unwrap_or("");
|
||||||
|
let prefix = special_key.prefix();
|
||||||
|
let new_options = options
|
||||||
|
.split(',')
|
||||||
|
.filter(|x| !x.starts_with(prefix))
|
||||||
|
.chain(id)
|
||||||
|
.join(",");
|
||||||
|
|
||||||
|
self.xkb.options = Some(new_options).filter(|x| !x.is_empty());
|
||||||
|
|
||||||
|
if let Err(err) = self.config.set("xkb_config", &self.xkb) {
|
||||||
|
tracing::error!(?err, "Failed to set config 'xkb_config'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Command::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_input_source_view(&self) -> cosmic::Element<'static, crate::app::Message> {
|
||||||
|
widget::column![].into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn special_character_key_view(&self, special_key: SpecialKey) -> cosmic::Element<'_, Message> {
|
||||||
|
let options = match special_key {
|
||||||
|
SpecialKey::Compose => COMPOSE_OPTIONS,
|
||||||
|
SpecialKey::AlternateCharacters => ALTERNATE_CHARACTER_OPTIONS,
|
||||||
|
};
|
||||||
|
let prefix = special_key.prefix();
|
||||||
|
let current = self
|
||||||
|
.xkb
|
||||||
|
.options
|
||||||
|
.iter()
|
||||||
|
.flat_map(|x| x.split(','))
|
||||||
|
.find(|x| x.starts_with(prefix));
|
||||||
|
|
||||||
|
// TODO description, layout default
|
||||||
|
|
||||||
|
let mut list = cosmic::widget::list_column();
|
||||||
|
list = list.add(special_char_radio_row("None", None, current));
|
||||||
|
for (desc, id) in options {
|
||||||
|
list = list.add(special_char_radio_row(desc, Some(id), current));
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmic::widget::scrollable(cosmic::widget::container(list).padding(24))
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl page::AutoBind<crate::pages::Message> for Page {
|
impl page::AutoBind<crate::pages::Message> for Page {
|
||||||
|
|
@ -244,20 +302,18 @@ fn input_sources() -> Section<crate::pages::Message> {
|
||||||
// TODO desc
|
// TODO desc
|
||||||
Section::default()
|
Section::default()
|
||||||
.title(fl!("keyboard-sources"))
|
.title(fl!("keyboard-sources"))
|
||||||
.view::<Page>(|binder, _page, section| {
|
.view::<Page>(|_binder, page, section| {
|
||||||
let input = binder.page::<super::Page>().expect("input page not found");
|
|
||||||
|
|
||||||
// TODO Need something more custom, with drag and drop
|
// TODO Need something more custom, with drag and drop
|
||||||
let mut section = settings::view_section(§ion.title);
|
let mut section = settings::view_section(§ion.title);
|
||||||
|
|
||||||
let expanded_source = input.expanded_source_popover.as_deref();
|
let expanded_source = page.expanded_source_popover.as_deref();
|
||||||
for source in &input.sources {
|
for source in &page.sources {
|
||||||
section = section.add(input_source(source, expanded_source));
|
section = section.add(input_source(source, expanded_source));
|
||||||
}
|
}
|
||||||
|
|
||||||
section
|
section
|
||||||
.apply(cosmic::Element::from)
|
.apply(cosmic::Element::from)
|
||||||
.map(crate::pages::Message::Input)
|
.map(crate::pages::Message::Keyboard)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,18 +327,17 @@ fn special_character_entry() -> Section<crate::pages::Message> {
|
||||||
.view::<Page>(|_binder, _page, section| {
|
.view::<Page>(|_binder, _page, section| {
|
||||||
let descriptions = §ion.descriptions;
|
let descriptions = §ion.descriptions;
|
||||||
|
|
||||||
// TODO dialogs
|
|
||||||
settings::view_section(§ion.title)
|
settings::view_section(§ion.title)
|
||||||
.add(go_next_item(
|
.add(go_next_item(
|
||||||
&*descriptions[0],
|
&*descriptions[0],
|
||||||
Message::OpenSpecialCharacterDialog(SpecialKey::AlternateCharacters),
|
Message::OpenSpecialCharacterContext(SpecialKey::AlternateCharacters),
|
||||||
))
|
))
|
||||||
.add(go_next_item(
|
.add(go_next_item(
|
||||||
&*descriptions[1],
|
&*descriptions[1],
|
||||||
Message::OpenSpecialCharacterDialog(SpecialKey::Compose),
|
Message::OpenSpecialCharacterContext(SpecialKey::Compose),
|
||||||
))
|
))
|
||||||
.apply(cosmic::Element::from)
|
.apply(cosmic::Element::from)
|
||||||
.map(crate::pages::Message::Input)
|
.map(crate::pages::Message::Keyboard)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,8 @@ crate::cache_dynamic_lazy! {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
CloseSpecialCharacterDialog,
|
|
||||||
// seperate close message, to make sure another isn't closed?
|
// seperate close message, to make sure another isn't closed?
|
||||||
DisableWhileTyping(bool, bool),
|
DisableWhileTyping(bool, bool),
|
||||||
ExpandInputSourcePopover(Option<String>),
|
|
||||||
OpenSpecialCharacterDialog(keyboard::SpecialKey),
|
|
||||||
PrimaryButtonSelected(cosmic::widget::segmented_button::Entity, bool),
|
PrimaryButtonSelected(cosmic::widget::segmented_button::Entity, bool),
|
||||||
SetAcceleration(bool, bool),
|
SetAcceleration(bool, bool),
|
||||||
SetMouseSpeed(f64, bool),
|
SetMouseSpeed(f64, bool),
|
||||||
|
|
@ -45,7 +42,6 @@ pub enum Message {
|
||||||
SetSecondaryClickBehavior(Option<ClickMethod>, bool),
|
SetSecondaryClickBehavior(Option<ClickMethod>, bool),
|
||||||
SetScrollFactor(f64, bool),
|
SetScrollFactor(f64, bool),
|
||||||
SetScrollMethod(Option<ScrollMethod>, bool),
|
SetScrollMethod(Option<ScrollMethod>, bool),
|
||||||
SpecialCharacterSelect(Option<&'static str>),
|
|
||||||
TapToClick(bool),
|
TapToClick(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,12 +56,6 @@ pub struct Page {
|
||||||
|
|
||||||
// Touchpad
|
// Touchpad
|
||||||
touchpad_primary_button: cosmic::widget::segmented_button::SingleSelectModel,
|
touchpad_primary_button: cosmic::widget::segmented_button::SingleSelectModel,
|
||||||
|
|
||||||
// Keyboard
|
|
||||||
expanded_source_popover: Option<String>,
|
|
||||||
sources: Vec<keyboard::InputSource>,
|
|
||||||
special_character_dialog: Option<keyboard::SpecialKey>,
|
|
||||||
xkb: XkbConfig,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_config<T: Default + serde::de::DeserializeOwned>(
|
fn get_config<T: Default + serde::de::DeserializeOwned>(
|
||||||
|
|
@ -83,7 +73,6 @@ impl Default for Page {
|
||||||
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
|
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
|
||||||
let input_default: InputConfig = get_config(&config, "input_default");
|
let input_default: InputConfig = get_config(&config, "input_default");
|
||||||
let input_touchpad: InputConfig = get_config(&config, "input_touchpad");
|
let input_touchpad: InputConfig = get_config(&config, "input_touchpad");
|
||||||
let xkb = get_config(&config, "xkb_config");
|
|
||||||
|
|
||||||
let mut primary_button = mouse::default_primary_button();
|
let mut primary_button = mouse::default_primary_button();
|
||||||
let idx = input_default.left_handed.unwrap_or(false) as u16;
|
let idx = input_default.left_handed.unwrap_or(false) as u16;
|
||||||
|
|
@ -103,12 +92,6 @@ impl Default for Page {
|
||||||
|
|
||||||
// Touchpad
|
// Touchpad
|
||||||
touchpad_primary_button,
|
touchpad_primary_button,
|
||||||
|
|
||||||
// Keyboard
|
|
||||||
expanded_source_popover: None,
|
|
||||||
sources: keyboard::default_input_sources(),
|
|
||||||
special_character_dialog: None,
|
|
||||||
xkb,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +143,7 @@ impl Page {
|
||||||
Message::SetSecondaryClickBehavior(click_method, touchpad) => {
|
Message::SetSecondaryClickBehavior(click_method, touchpad) => {
|
||||||
self.update_input(touchpad, |x| {
|
self.update_input(touchpad, |x| {
|
||||||
x.click_method = click_method;
|
x.click_method = click_method;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::SetScrollFactor(value, touchpad) => self.update_input(touchpad, |x| {
|
Message::SetScrollFactor(value, touchpad) => self.update_input(touchpad, |x| {
|
||||||
|
|
@ -193,53 +176,6 @@ impl Page {
|
||||||
self.update_input(touchpad, |x| x.left_handed = Some(left_handed));
|
self.update_input(touchpad, |x| x.left_handed = Some(left_handed));
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::ExpandInputSourcePopover(value) => {
|
|
||||||
self.expanded_source_popover = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Message::OpenSpecialCharacterDialog(special_key) => {
|
|
||||||
self.special_character_dialog = Some(special_key);
|
|
||||||
let window_settings = SctkWindowSettings {
|
|
||||||
window_id: *keyboard::SPECIAL_CHARACTER_DIALOGUE_ID,
|
|
||||||
app_id: Some("com.system76.CosmicSettings".to_string()),
|
|
||||||
title: Some(special_key.title()),
|
|
||||||
parent: Some(window::Id::MAIN),
|
|
||||||
autosize: false,
|
|
||||||
size_limits: layout::Limits::NONE
|
|
||||||
.min_width(300.0)
|
|
||||||
.max_width(800.0)
|
|
||||||
.min_height(200.0)
|
|
||||||
.max_height(1080.0),
|
|
||||||
size: (512, 420),
|
|
||||||
resizable: None,
|
|
||||||
client_decorations: true,
|
|
||||||
transparent: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
return commands::window::get_window(window_settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message::CloseSpecialCharacterDialog => {
|
|
||||||
self.special_character_dialog = None;
|
|
||||||
return commands::window::close_window(*keyboard::SPECIAL_CHARACTER_DIALOGUE_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message::SpecialCharacterSelect(id) => {
|
|
||||||
if let Some(special_key) = self.special_character_dialog {
|
|
||||||
let options = self.xkb.options.as_deref().unwrap_or("");
|
|
||||||
let prefix = special_key.prefix();
|
|
||||||
let new_options = options
|
|
||||||
.split(',')
|
|
||||||
.filter(|x| !x.starts_with(prefix))
|
|
||||||
.chain(id)
|
|
||||||
.join(",");
|
|
||||||
self.xkb.options = Some(new_options).filter(|x| !x.is_empty());
|
|
||||||
if let Err(err) = self.config.set("xkb_config", &self.xkb) {
|
|
||||||
error!(?err, "Failed to set config 'xkb_config'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Message::TapToClick(enabled) => {
|
Message::TapToClick(enabled) => {
|
||||||
self.update_input(true, |conf| {
|
self.update_input(true, |conf| {
|
||||||
conf.tap_config
|
conf.tap_config
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ pub enum Message {
|
||||||
Dock(desktop::dock::Message),
|
Dock(desktop::dock::Message),
|
||||||
DockApplet(desktop::dock::applets::Message),
|
DockApplet(desktop::dock::applets::Message),
|
||||||
External { id: String, message: Vec<u8> },
|
External { id: String, message: Vec<u8> },
|
||||||
|
Keyboard(input::keyboard::Message),
|
||||||
Input(input::Message),
|
Input(input::Message),
|
||||||
Page(Entity),
|
Page(Entity),
|
||||||
Panel(desktop::panel::Message),
|
Panel(desktop::panel::Message),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue