feat: add input sources applet
This commit is contained in:
parent
1abc466f49
commit
a1ad3c5f87
16 changed files with 508 additions and 36 deletions
110
Cargo.lock
generated
110
Cargo.lock
generated
|
|
@ -442,9 +442,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
|
|
@ -643,9 +643,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.96"
|
||||
version = "1.0.97"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
|
||||
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
|
|
@ -962,6 +962,26 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmic-applet-input-sources"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cosmic-comp-config",
|
||||
"cosmic-time",
|
||||
"i18n-embed",
|
||||
"i18n-embed-fl",
|
||||
"libcosmic",
|
||||
"libpulse-binding",
|
||||
"once_cell",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-log",
|
||||
"tracing-subscriber",
|
||||
"xkb-data",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmic-applet-minimize"
|
||||
version = "0.1.1"
|
||||
|
|
@ -1071,6 +1091,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tracing-log",
|
||||
"tracing-subscriber",
|
||||
"xkb-data",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1116,6 +1137,7 @@ dependencies = [
|
|||
"cosmic-applet-audio",
|
||||
"cosmic-applet-battery",
|
||||
"cosmic-applet-bluetooth",
|
||||
"cosmic-applet-input-sources",
|
||||
"cosmic-applet-minimize",
|
||||
"cosmic-applet-network",
|
||||
"cosmic-applet-notifications",
|
||||
|
|
@ -1227,7 +1249,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-panel-config"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/cosmic-panel#d1d656d6b2a4faaee34d72ed86bc0073dcd4da89"
|
||||
source = "git+https://github.com/pop-os/cosmic-panel#683a204ef81bd17c2b35264521e5145df3518ee5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cosmic-config",
|
||||
|
|
@ -1272,7 +1294,7 @@ dependencies = [
|
|||
"rangemap",
|
||||
"rustc-hash",
|
||||
"rustybuzz",
|
||||
"self_cell 1.0.3",
|
||||
"self_cell 1.0.4",
|
||||
"swash",
|
||||
"sys-locale",
|
||||
"ttf-parser",
|
||||
|
|
@ -2011,9 +2033,9 @@ checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
|
|||
|
||||
[[package]]
|
||||
name = "fluent"
|
||||
version = "0.16.0"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7"
|
||||
checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a"
|
||||
dependencies = [
|
||||
"fluent-bundle",
|
||||
"unic-langid",
|
||||
|
|
@ -2021,9 +2043,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fluent-bundle"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd"
|
||||
checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493"
|
||||
dependencies = [
|
||||
"fluent-langneg",
|
||||
"fluent-syntax",
|
||||
|
|
@ -2046,9 +2068,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fluent-syntax"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78"
|
||||
checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
|
@ -2351,9 +2373,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.14"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
|
@ -3046,9 +3068,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "intl-memoizer"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f"
|
||||
checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda"
|
||||
dependencies = [
|
||||
"type-map",
|
||||
"unic-langid",
|
||||
|
|
@ -3720,9 +3742,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.44"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
|
|
@ -3743,9 +3765,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.18"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
|
|
@ -4617,14 +4639,14 @@ version = "0.10.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
|
||||
dependencies = [
|
||||
"self_cell 1.0.3",
|
||||
"self_cell 1.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba"
|
||||
checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
|
|
@ -4635,6 +4657,18 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-xml-rs"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.200"
|
||||
|
|
@ -4798,7 +4832,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "smithay-clipboard"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/pop-os/smithay-clipboard?tag=pop-dnd-4#eefa50c3df5135d98df7f4192e2e9b07eeafe56b"
|
||||
source = "git+https://github.com/pop-os/smithay-clipboard?tag=pop-dnd-4#9b995a33a88c496a90259dd207367a998c95ac98"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"raw-window-handle 0.6.1",
|
||||
|
|
@ -5295,7 +5329,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow 0.6.7",
|
||||
"winnow 0.6.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5367,9 +5401,9 @@ checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
|
|||
|
||||
[[package]]
|
||||
name = "type-map"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46"
|
||||
checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f"
|
||||
dependencies = [
|
||||
"rustc-hash",
|
||||
]
|
||||
|
|
@ -6167,9 +6201,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.7"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578"
|
||||
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
@ -6226,6 +6260,16 @@ dependencies = [
|
|||
"wayland-protocols-wlr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xkb-data"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "294a599fc9e6a43c9f44f5d6c560b89fd751be413717442b31c17fa367d3c764"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde-xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xkbcommon"
|
||||
version = "0.7.0"
|
||||
|
|
@ -6358,18 +6402,18 @@ checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697"
|
|||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.32"
|
||||
version = "0.7.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||
checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.32"
|
||||
version = "0.7.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ members = [
|
|||
"cosmic-applet-time",
|
||||
"cosmic-applet-workspaces",
|
||||
"cosmic-panel-button",
|
||||
"cosmic-applet-input-sources",
|
||||
]
|
||||
|
||||
resolver = "2"
|
||||
|
|
|
|||
20
cosmic-applet-input-sources/Cargo.toml
Normal file
20
cosmic-applet-input-sources/Cargo.toml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "cosmic-applet-input-sources"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cosmic-time.workspace = true
|
||||
cosmic-comp-config = { git = "https://github.com/pop-os/cosmic-comp.git", rev = "5eb5af4" }
|
||||
i18n-embed-fl.workspace = true
|
||||
i18n-embed.workspace = true
|
||||
libcosmic.workspace = true
|
||||
libpulse-binding = "2.28.1"
|
||||
rust-embed.workspace = true
|
||||
tokio = { version = "1.36.0", features=["full"] }
|
||||
tracing-log.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
tracing.workspace = true
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
once_cell = "1.19.0"
|
||||
xkb-data = "0.1.0"
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
[Desktop Entry]
|
||||
Name=Cosmic Applet Input Sources
|
||||
Comment=Applet for Cosmic Panel
|
||||
Type=Application
|
||||
Exec=cosmic-applet-input-sources
|
||||
Terminal=false
|
||||
Categories=Cosmic;Iced;
|
||||
Keywords=Cosmic;Iced;
|
||||
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
|
||||
Icon=com.system76.CosmicAppletInputSources
|
||||
StartupNotify=true
|
||||
NoDisplay=true
|
||||
X-CosmicApplet=true
|
||||
4
cosmic-applet-input-sources/i18n.toml
Normal file
4
cosmic-applet-input-sources/i18n.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
fallback_language = "en"
|
||||
|
||||
[fluent]
|
||||
assets_dir = "i18n"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
show-keyboard-layout = Show Keyboard Layout...
|
||||
keyboard-settings = Keyboard Settings...
|
||||
15
cosmic-applet-input-sources/src/config.rs
Normal file
15
cosmic-applet-input-sources/src/config.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use cosmic::cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry};
|
||||
use cosmic_comp_config::XkbConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub const CONFIG_VERSION: u64 = 1;
|
||||
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct Config {}
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, PartialEq, Serialize, Default)]
|
||||
pub struct CosmicCompConfig {
|
||||
pub xkb_config: XkbConfig,
|
||||
}
|
||||
53
cosmic-applet-input-sources/src/lib.rs
Normal file
53
cosmic-applet-input-sources/src/lib.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use crate::window::Window;
|
||||
use config::{Config, CONFIG_VERSION};
|
||||
use cosmic::cosmic_config;
|
||||
use cosmic::cosmic_config::CosmicConfigEntry;
|
||||
mod config;
|
||||
use cosmic_comp_config::CosmicCompConfig;
|
||||
use window::Flags;
|
||||
mod localize;
|
||||
mod window;
|
||||
pub fn run() -> cosmic::iced::Result {
|
||||
localize::localize();
|
||||
let (config_handler, config) = match cosmic_config::Config::new(window::ID, CONFIG_VERSION) {
|
||||
Ok(config_handler) => {
|
||||
let config = match Config::get_entry(&config_handler) {
|
||||
Ok(ok) => ok,
|
||||
Err((errs, config)) => {
|
||||
eprintln!("errors loading config: {:?}", errs);
|
||||
config
|
||||
}
|
||||
};
|
||||
(Some(config_handler), config)
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("failed to create config handler: {}", err);
|
||||
(None, Config::default())
|
||||
}
|
||||
};
|
||||
let (comp_config_handler, comp_config) =
|
||||
match cosmic_config::Config::new("com.system76.CosmicComp", CosmicCompConfig::VERSION) {
|
||||
Ok(config_handler) => {
|
||||
let config = match CosmicCompConfig::get_entry(&config_handler) {
|
||||
Ok(ok) => ok,
|
||||
Err((errs, config)) => {
|
||||
eprintln!("errors loading config: {:?}", errs);
|
||||
config
|
||||
}
|
||||
};
|
||||
(Some(config_handler), config)
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("failed to create config handler: {}", err);
|
||||
(None, CosmicCompConfig::default())
|
||||
}
|
||||
};
|
||||
|
||||
let flags = Flags {
|
||||
comp_config,
|
||||
comp_config_handler,
|
||||
config_handler: config_handler,
|
||||
config: config,
|
||||
};
|
||||
cosmic::applet::run::<Window>(true, flags)
|
||||
}
|
||||
36
cosmic-applet-input-sources/src/localize.rs
Normal file
36
cosmic-applet-input-sources/src/localize.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use i18n_embed::{
|
||||
fluent::{fluent_language_loader, FluentLanguageLoader},
|
||||
DefaultLocalizer, LanguageLoader, Localizer,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use rust_embed::RustEmbed;
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "i18n/"]
|
||||
struct Localizations;
|
||||
pub static LANGUAGE_LOADER: Lazy<FluentLanguageLoader> = Lazy::new(|| {
|
||||
let loader: FluentLanguageLoader = fluent_language_loader!();
|
||||
loader
|
||||
.load_fallback_language(&Localizations)
|
||||
.expect("Error while loading fallback language");
|
||||
loader
|
||||
});
|
||||
#[macro_export]
|
||||
macro_rules! fl {
|
||||
($message_id:literal) => {{
|
||||
i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id)
|
||||
}};
|
||||
($message_id:literal, $($args:expr),*) => {{
|
||||
i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id, $($args), *)
|
||||
}};
|
||||
}
|
||||
// Get the `Localizer` to be used for localizing this library.
|
||||
pub fn localizer() -> Box<dyn Localizer> {
|
||||
Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations))
|
||||
}
|
||||
pub fn localize() {
|
||||
let localizer = localizer();
|
||||
let requested_languages = i18n_embed::DesktopLanguageRequester::requested_languages();
|
||||
if let Err(error) = localizer.select(&requested_languages) {
|
||||
eprintln!("Error while loading language for App List {}", error);
|
||||
}
|
||||
}
|
||||
3
cosmic-applet-input-sources/src/main.rs
Normal file
3
cosmic-applet-input-sources/src/main.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn main() -> cosmic::iced::Result {
|
||||
cosmic_applet_input_sources::run()
|
||||
}
|
||||
277
cosmic-applet-input-sources/src/window.rs
Normal file
277
cosmic-applet-input-sources/src/window.rs
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
use crate::config::{Config, CONFIG_VERSION};
|
||||
#[allow(unused_imports)]
|
||||
use crate::fl;
|
||||
use cosmic::app::Core;
|
||||
use cosmic::applet::{self};
|
||||
use cosmic::cosmic_config::{self, ConfigSet};
|
||||
use cosmic::iced::wayland::popup::{destroy_popup, get_popup};
|
||||
use cosmic::iced::window::Id;
|
||||
#[allow(unused_imports)]
|
||||
use cosmic::iced::{alignment, Alignment, Length};
|
||||
use cosmic::iced::{Command, Limits};
|
||||
use cosmic::iced_futures::Subscription;
|
||||
use cosmic::iced_runtime::core::window;
|
||||
use cosmic::iced_style::application;
|
||||
use cosmic::prelude::*;
|
||||
use cosmic::widget;
|
||||
use cosmic_comp_config::CosmicCompConfig;
|
||||
use xkb_data::KeyboardLayouts;
|
||||
pub const ID: &str = "com.system76.CosmicAppletInputSources";
|
||||
|
||||
pub struct Window {
|
||||
core: Core,
|
||||
popup: Option<Id>,
|
||||
config: Config,
|
||||
#[allow(dead_code)]
|
||||
config_handler: Option<cosmic_config::Config>,
|
||||
comp_config: CosmicCompConfig,
|
||||
comp_config_handler: Option<cosmic_config::Config>,
|
||||
layouts: KeyboardLayouts,
|
||||
active_layouts: Vec<ActiveLayout>,
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
Config(Config),
|
||||
TogglePopup,
|
||||
PopupClosed(Id),
|
||||
CompConfig(CosmicCompConfig),
|
||||
SetActiveLayout(ActiveLayout),
|
||||
KeyboardSettings,
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Flags {
|
||||
pub config_handler: Option<cosmic_config::Config>,
|
||||
pub config: Config,
|
||||
pub comp_config: CosmicCompConfig,
|
||||
pub comp_config_handler: Option<cosmic_config::Config>,
|
||||
}
|
||||
impl cosmic::Application for Window {
|
||||
type Executor = cosmic::SingleThreadExecutor;
|
||||
type Flags = Flags;
|
||||
type Message = Message;
|
||||
const APP_ID: &'static str = ID;
|
||||
fn core(&self) -> &Core {
|
||||
&self.core
|
||||
}
|
||||
fn core_mut(&mut self) -> &mut Core {
|
||||
&mut self.core
|
||||
}
|
||||
fn init(
|
||||
core: Core,
|
||||
flags: Self::Flags,
|
||||
) -> (Self, Command<cosmic::app::Message<Self::Message>>) {
|
||||
let layouts = xkb_data::keyboard_layouts().unwrap();
|
||||
let window = Window {
|
||||
comp_config_handler: flags.comp_config_handler,
|
||||
layouts,
|
||||
core,
|
||||
config: flags.config,
|
||||
config_handler: flags.config_handler,
|
||||
popup: None,
|
||||
comp_config: flags.comp_config,
|
||||
active_layouts: Vec::new(),
|
||||
};
|
||||
(window, Command::none())
|
||||
}
|
||||
fn on_close_requested(&self, id: window::Id) -> Option<Message> {
|
||||
Some(Message::PopupClosed(id))
|
||||
}
|
||||
fn update(&mut self, message: Self::Message) -> Command<cosmic::app::Message<Self::Message>> {
|
||||
match message {
|
||||
Message::Config(config) => self.config = config,
|
||||
Message::TogglePopup => {
|
||||
return if let Some(p) = self.popup.take() {
|
||||
destroy_popup(p)
|
||||
} else {
|
||||
let new_id = Id::unique();
|
||||
self.popup.replace(new_id);
|
||||
let mut popup_settings =
|
||||
self.core
|
||||
.applet
|
||||
.get_popup_settings(Id::MAIN, new_id, None, None, None);
|
||||
popup_settings.positioner.size_limits = Limits::NONE
|
||||
.max_width(372.0)
|
||||
.min_width(300.0)
|
||||
.min_height(200.0)
|
||||
.max_height(1080.0);
|
||||
get_popup(popup_settings)
|
||||
}
|
||||
}
|
||||
Message::PopupClosed(id) => {
|
||||
if self.popup.as_ref() == Some(&id) {
|
||||
self.popup = None;
|
||||
}
|
||||
}
|
||||
Message::CompConfig(config) => {
|
||||
self.comp_config = config;
|
||||
self.active_layouts = self.update_xkb();
|
||||
}
|
||||
Message::KeyboardSettings => {
|
||||
let mut cmd = std::process::Command::new("cosmic-settings");
|
||||
cmd.arg("keyboard");
|
||||
cosmic::process::spawn(cmd);
|
||||
}
|
||||
Message::SetActiveLayout(active_layout) => {
|
||||
let Some(i) = self
|
||||
.active_layouts
|
||||
.iter()
|
||||
.position(|layout| layout == &active_layout)
|
||||
else {
|
||||
return Command::none();
|
||||
};
|
||||
|
||||
self.active_layouts.swap(0, i);
|
||||
let mut new_layout = String::new();
|
||||
let mut new_variant = String::new();
|
||||
|
||||
for layout in &self.active_layouts {
|
||||
new_layout.push_str(&layout.layout);
|
||||
new_layout.push(',');
|
||||
new_variant.push_str(&layout.variant);
|
||||
new_variant.push(',');
|
||||
}
|
||||
let _excess_comma = new_layout.pop();
|
||||
let _excess_comma = new_variant.pop();
|
||||
|
||||
self.comp_config.xkb_config.layout = new_layout;
|
||||
self.comp_config.xkb_config.variant = new_variant;
|
||||
if let Some(comp_config_handler) = &self.comp_config_handler {
|
||||
if let Err(err) =
|
||||
comp_config_handler.set("xkb_config", &self.comp_config.xkb_config)
|
||||
{
|
||||
eprint!("Failed to set config 'xkb_config' {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
fn view(&self) -> Element<Self::Message> {
|
||||
let suggested = self.core.applet.suggested_padding();
|
||||
widget::button(
|
||||
widget::text(
|
||||
self.active_layouts
|
||||
.first()
|
||||
.map_or(String::new(), |l| l.layout.clone()),
|
||||
)
|
||||
.size(14),
|
||||
)
|
||||
.style(cosmic::theme::Button::AppletIcon)
|
||||
.padding([suggested / 2, suggested])
|
||||
.on_press(Message::TogglePopup)
|
||||
.into()
|
||||
}
|
||||
fn view_window(&self, _id: Id) -> Element<Self::Message> {
|
||||
let mut content_list =
|
||||
widget::column::with_capacity(4 + self.active_layouts.len()).padding([8, 0]);
|
||||
for layout in &self.active_layouts {
|
||||
let group = widget::column::with_capacity(2)
|
||||
.push(widget::text(layout.description.clone()).size(16))
|
||||
.push(widget::text(layout.layout.clone()).size(14));
|
||||
content_list = content_list.push(
|
||||
applet::menu_button(group).on_press(Message::SetActiveLayout(layout.clone())),
|
||||
);
|
||||
}
|
||||
content_list = content_list.extend(
|
||||
[
|
||||
applet::padded_control(widget::divider::horizontal::default()).apply(Element::from),
|
||||
applet::menu_button(widget::text(fl!("show-keyboard-layout"))).into(),
|
||||
applet::padded_control(widget::divider::horizontal::default()).into(),
|
||||
applet::menu_button(widget::text(fl!("keyboard-settings")))
|
||||
.on_press(Message::KeyboardSettings)
|
||||
.into(),
|
||||
]
|
||||
.into_iter(),
|
||||
);
|
||||
|
||||
self.core.applet.popup_container(content_list).into()
|
||||
}
|
||||
fn subscription(&self) -> Subscription<Self::Message> {
|
||||
struct ConfigSubscription;
|
||||
let config = cosmic_config::config_subscription(
|
||||
std::any::TypeId::of::<ConfigSubscription>(),
|
||||
Self::APP_ID.into(),
|
||||
CONFIG_VERSION,
|
||||
)
|
||||
.map(|update| {
|
||||
if !update.errors.is_empty() {
|
||||
eprintln!(
|
||||
"errors loading config {:?}: {:?}",
|
||||
update.keys, update.errors
|
||||
);
|
||||
}
|
||||
Message::Config(update.config)
|
||||
});
|
||||
let xbg_config = self
|
||||
.core
|
||||
.watch_config("com.system76.CosmicComp")
|
||||
.map(|update| {
|
||||
if !update.errors.is_empty() {
|
||||
eprintln!(
|
||||
"errors loading config {:?}: {:?}",
|
||||
update.keys, update.errors
|
||||
);
|
||||
}
|
||||
Message::CompConfig(update.config)
|
||||
});
|
||||
Subscription::batch(vec![config, xbg_config])
|
||||
}
|
||||
|
||||
fn style(&self) -> Option<<Theme as application::StyleSheet>::Style> {
|
||||
Some(cosmic::applet::style())
|
||||
}
|
||||
}
|
||||
impl Window {
|
||||
fn update_xkb(&self) -> Vec<ActiveLayout> {
|
||||
let mut active_layouts = Vec::new();
|
||||
let xkb = &self.comp_config.xkb_config;
|
||||
|
||||
let layouts = xkb.layout.split_terminator(',');
|
||||
|
||||
let variants = xkb
|
||||
.variant
|
||||
.split_terminator(',')
|
||||
.chain(std::iter::repeat(""));
|
||||
|
||||
for (layout, variant) in layouts.zip(variants) {
|
||||
println!("{} : {}", layout, variant);
|
||||
for xkb_layout in self.layouts.layouts() {
|
||||
if layout != xkb_layout.name() {
|
||||
continue;
|
||||
}
|
||||
if variant.is_empty() {
|
||||
let active_layout = ActiveLayout {
|
||||
description: xkb_layout.description().to_owned(),
|
||||
layout: layout.to_owned(),
|
||||
variant: variant.to_owned(),
|
||||
};
|
||||
active_layouts.push(active_layout);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(xkb_variants) = xkb_layout.variants() else {
|
||||
continue;
|
||||
};
|
||||
for xkb_variant in xkb_variants {
|
||||
if variant != xkb_variant.name() {
|
||||
continue;
|
||||
}
|
||||
let active_layout = ActiveLayout {
|
||||
description: xkb_variant.description().to_owned(),
|
||||
layout: layout.to_owned(),
|
||||
variant: variant.to_owned(),
|
||||
};
|
||||
active_layouts.push(active_layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
active_layouts
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ActiveLayout {
|
||||
layout: String,
|
||||
description: String,
|
||||
variant: String,
|
||||
}
|
||||
|
|
@ -21,3 +21,4 @@ tokio = { version = "1.36.0", features = ["sync", "rt"] }
|
|||
tracing-log.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
tracing.workspace = true
|
||||
xkb-data = "0.1.0"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ cosmic-applet-status-area = { path = "../cosmic-applet-status-area" }
|
|||
cosmic-applet-tiling = { path = "../cosmic-applet-tiling" }
|
||||
cosmic-applet-time = { path = "../cosmic-applet-time" }
|
||||
cosmic-applet-workspaces = { path = "../cosmic-applet-workspaces" }
|
||||
cosmic-applet-input-sources = { path = "../cosmic-applet-input-sources"}
|
||||
libcosmic.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
tracing-log.workspace = true
|
||||
tracing-log.workspace = true
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ fn main() -> cosmic::iced::Result {
|
|||
"cosmic-applet-tiling" => cosmic_applet_tiling::run(),
|
||||
"cosmic-applet-time" => cosmic_applet_time::run(),
|
||||
"cosmic-applet-workspaces" => cosmic_applet_workspaces::run(),
|
||||
"cosmic-applet-input-sources" => cosmic_applet_input_sources::run(),
|
||||
_ => return Ok(()),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
debian/links
vendored
3
debian/links
vendored
|
|
@ -9,4 +9,5 @@
|
|||
/usr/bin/cosmic-applets /usr/bin/cosmic-applet-status-area
|
||||
/usr/bin/cosmic-applets /usr/bin/cosmic-applet-tiling
|
||||
/usr/bin/cosmic-applets /usr/bin/cosmic-applet-time
|
||||
/usr/bin/cosmic-applets /usr/bin/cosmic-applet-workspaces
|
||||
/usr/bin/cosmic-applets /usr/bin/cosmic-applet-workspaces
|
||||
/usr/bin/cosmic-applets /usr/bin/cosmic-applet-input-sources
|
||||
|
|
|
|||
2
justfile
2
justfile
|
|
@ -51,7 +51,7 @@ _install_applet id name: (_install_icons name) \
|
|||
_install_button id name: (_install_icons name) (_install_desktop name + '/data/' + id + '.desktop')
|
||||
|
||||
# Installs files into the system
|
||||
install: (_install_bin 'cosmic-applets') (_install_applet 'com.system76.CosmicAppList' 'cosmic-app-list') (_install_default_schema 'cosmic-app-list') (_install_applet 'com.system76.CosmicAppletAudio' 'cosmic-applet-audio') (_install_applet 'com.system76.CosmicAppletBattery' 'cosmic-applet-battery') (_install_applet 'com.system76.CosmicAppletBluetooth' 'cosmic-applet-bluetooth') (_install_applet 'com.system76.CosmicAppletMinimize' 'cosmic-applet-minimize') (_install_applet 'com.system76.CosmicAppletNetwork' 'cosmic-applet-network') (_install_applet 'com.system76.CosmicAppletNotifications' 'cosmic-applet-notifications') (_install_applet 'com.system76.CosmicAppletPower' 'cosmic-applet-power') (_install_applet 'com.system76.CosmicAppletStatusArea' 'cosmic-applet-status-area') (_install_applet 'com.system76.CosmicAppletTiling' 'cosmic-applet-tiling') (_install_applet 'com.system76.CosmicAppletTime' 'cosmic-applet-time') (_install_applet 'com.system76.CosmicAppletWorkspaces' 'cosmic-applet-workspaces') (_install_bin 'cosmic-panel-button') (_install_button 'com.system76.CosmicPanelAppButton' 'cosmic-panel-app-button') (_install_button 'com.system76.CosmicPanelLauncherButton' 'cosmic-panel-launcher-button') (_install_button 'com.system76.CosmicPanelWorkspacesButton' 'cosmic-panel-workspaces-button')
|
||||
install: (_install_bin 'cosmic-applets') (_install_applet 'com.system76.CosmicAppList' 'cosmic-app-list') (_install_default_schema 'cosmic-app-list') (_install_applet 'com.system76.CosmicAppletAudio' 'cosmic-applet-audio') (_install_applet 'com.system76.CosmicAppletInputSources' 'cosmic-applet-input-sources') (_install_applet 'com.system76.CosmicAppletBattery' 'cosmic-applet-battery') (_install_applet 'com.system76.CosmicAppletBluetooth' 'cosmic-applet-bluetooth') (_install_applet 'com.system76.CosmicAppletMinimize' 'cosmic-applet-minimize') (_install_applet 'com.system76.CosmicAppletNetwork' 'cosmic-applet-network') (_install_applet 'com.system76.CosmicAppletNotifications' 'cosmic-applet-notifications') (_install_applet 'com.system76.CosmicAppletPower' 'cosmic-applet-power') (_install_applet 'com.system76.CosmicAppletStatusArea' 'cosmic-applet-status-area') (_install_applet 'com.system76.CosmicAppletTiling' 'cosmic-applet-tiling') (_install_applet 'com.system76.CosmicAppletTime' 'cosmic-applet-time') (_install_applet 'com.system76.CosmicAppletWorkspaces' 'cosmic-applet-workspaces') (_install_bin 'cosmic-panel-button') (_install_button 'com.system76.CosmicPanelAppButton' 'cosmic-panel-app-button') (_install_button 'com.system76.CosmicPanelLauncherButton' 'cosmic-panel-launcher-button') (_install_button 'com.system76.CosmicPanelWorkspacesButton' 'cosmic-panel-workspaces-button')
|
||||
|
||||
# Vendor Cargo dependencies locally
|
||||
vendor:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue