From b76a1c9eedba6918e083293d18483e6cdfdbe7e6 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 29 Jul 2024 13:56:42 -0700 Subject: [PATCH 1/7] WIP Add `cosmic-keymap-unstable-v1` protocol --- Cargo.lock | 2 +- Cargo.toml | 3 +- src/state.rs | 2 + src/wayland/handlers/keymap.rs | 5 ++ src/wayland/handlers/mod.rs | 1 + src/wayland/protocols/keymap.rs | 100 ++++++++++++++++++++++++++++++++ src/wayland/protocols/mod.rs | 1 + 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/wayland/handlers/keymap.rs create mode 100644 src/wayland/protocols/keymap.rs diff --git a/Cargo.lock b/Cargo.lock index aebb3e94..246e38df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -899,7 +899,7 @@ dependencies = [ [[package]] name = "cosmic-protocols" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-protocols?branch=main#ec1616b90fa6b4568709cfe2c0627b1e8cc887e0" +source = "git+https://github.com/pop-os/cosmic-protocols?branch=keymap#17fb2f85904355abc7c7eecdd3f12763de7e39ca" dependencies = [ "bitflags 2.6.0", "wayland-backend", diff --git a/Cargo.toml b/Cargo.toml index 6aa22761..ed29f123 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,8 @@ bytemuck = "1.12" calloop = {version = "0.14.1", features = ["executor"]} cosmic-comp-config = {path = "cosmic-comp-config"} cosmic-config = {git = "https://github.com/pop-os/libcosmic/", features = ["calloop", "macro"]} -cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"]} +# cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"]} +cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "keymap", default-features = false, features = ["server"]} cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon" } edid-rs = {version = "0.1"} egui = {version = "0.29.0", optional = true} diff --git a/src/state.rs b/src/state.rs index 747754c0..2eab2327 100644 --- a/src/state.rs +++ b/src/state.rs @@ -15,6 +15,7 @@ use crate::{ atspi::AtspiState, drm::WlDrmState, image_source::ImageSourceState, + keymap::KeymapState, output_configuration::OutputConfigurationState, output_power::OutputPowerState, screencopy::ScreencopyState, @@ -522,6 +523,7 @@ impl State { VirtualKeyboardManagerState::new::(&dh, client_is_privileged); AlphaModifierState::new::(&dh); SinglePixelBufferState::new::(&dh); + KeymapState::new::(&dh, client_is_privileged); let idle_notifier_state = IdleNotifierState::::new(&dh, handle.clone()); let idle_inhibit_manager_state = IdleInhibitManagerState::new::(&dh); diff --git a/src/wayland/handlers/keymap.rs b/src/wayland/handlers/keymap.rs new file mode 100644 index 00000000..9b4a50c3 --- /dev/null +++ b/src/wayland/handlers/keymap.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-only +// +use crate::{state::State, wayland::protocols::keymap::delegate_keymap}; + +delegate_keymap!(State); diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index 52414103..1a288abc 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -17,6 +17,7 @@ pub mod idle_notify; pub mod image_source; pub mod input_method; pub mod keyboard_shortcuts_inhibit; +pub mod keymap; pub mod layer_shell; pub mod output; pub mod output_configuration; diff --git a/src/wayland/protocols/keymap.rs b/src/wayland/protocols/keymap.rs new file mode 100644 index 00000000..e96fd132 --- /dev/null +++ b/src/wayland/protocols/keymap.rs @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use cosmic_protocols::keymap::v1::server::zcosmic_keymap_manager_v1::{ + self, ZcosmicKeymapManagerV1, +}; +use smithay::{ + input::{ + keyboard::{KeyboardHandle, Layout}, + SeatHandler, + }, + reexports::wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New}, +}; +use wayland_backend::server::GlobalId; + +pub struct KeymapState { + pub global: GlobalId, +} + +impl KeymapState { + pub fn new(dh: &DisplayHandle, client_filter: F) -> Self + where + D: GlobalDispatch + 'static, + F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static, + { + let global = dh.create_global::( + 1, + KeymapGlobalData { + filter: Box::new(client_filter), + }, + ); + KeymapState { global } + } +} + +pub struct KeymapGlobalData { + filter: Box Fn(&'a Client) -> bool + Send + Sync>, +} + +impl GlobalDispatch for KeymapState +where + D: GlobalDispatch + + Dispatch + + 'static, +{ + fn bind( + _state: &mut D, + _handle: &DisplayHandle, + _client: &Client, + resource: New, + _global_data: &KeymapGlobalData, + data_init: &mut DataInit<'_, D>, + ) { + data_init.init(resource, ()); + } + + fn can_view(client: Client, global_data: &KeymapGlobalData) -> bool { + (global_data.filter)(&client) + } +} + +impl Dispatch for KeymapState +where + D: Dispatch + 'static, + D: SeatHandler, +{ + fn request( + state: &mut D, + _client: &Client, + _resource: &ZcosmicKeymapManagerV1, + request: zcosmic_keymap_manager_v1::Request, + _data: &(), + _dhandle: &DisplayHandle, + _data_init: &mut DataInit<'_, D>, + ) { + match request { + zcosmic_keymap_manager_v1::Request::SetGroup { keyboard, group } => { + if let Some(handle) = KeyboardHandle::::from_resource(&keyboard) { + handle.with_xkb_state(state, |mut context| { + context.set_layout(Layout(group)); + // TODO is `modifiers` sent? + }); + } + } + zcosmic_keymap_manager_v1::Request::Destroy => {} + _ => unreachable!(), + } + } +} + +macro_rules! delegate_keymap { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::keymap::v1::server::zcosmic_keymap_manager_v1::ZcosmicKeymapManagerV1: $crate::wayland::protocols::keymap::KeymapGlobalData + ] => $crate::wayland::protocols::keymap::KeymapState); + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::keymap::v1::server::zcosmic_keymap_manager_v1::ZcosmicKeymapManagerV1: () + ] => $crate::wayland::protocols::keymap::KeymapState); + }; +} +pub(crate) use delegate_keymap; diff --git a/src/wayland/protocols/mod.rs b/src/wayland/protocols/mod.rs index 3fe5285d..5e6923f7 100644 --- a/src/wayland/protocols/mod.rs +++ b/src/wayland/protocols/mod.rs @@ -3,6 +3,7 @@ pub mod atspi; pub mod drm; pub mod image_source; +pub mod keymap; pub mod output_configuration; pub mod output_power; pub mod overlap_notify; From daacf0ffd66fcd06cb1cc5bb5deede5d9e1f5a22 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 15 Nov 2024 16:45:57 -0800 Subject: [PATCH 2/7] WIP updated keymap protocol with extension object TODO: Send `group` --- Cargo.lock | 12 ++++---- src/wayland/protocols/keymap.rs | 53 ++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 246e38df..ae594f88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -899,7 +899,7 @@ dependencies = [ [[package]] name = "cosmic-protocols" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-protocols?branch=keymap#17fb2f85904355abc7c7eecdd3f12763de7e39ca" +source = "git+https://github.com/pop-os/cosmic-protocols?branch=keymap#9f0ccdb533ee48f5eec9dcf8a3486a9a13a17279" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -1064,7 +1064,7 @@ version = "0.19.0" source = "git+https://github.com/gfx-rs/wgpu?rev=20fda69#20fda698341efbdc870b8027d6d49f5bf3f36109" dependencies = [ "bitflags 2.6.0", - "libloading 0.8.5", + "libloading 0.7.4", "winapi", ] @@ -1199,7 +1199,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.5", + "libloading 0.7.4", ] [[package]] @@ -2162,7 +2162,7 @@ dependencies = [ "bitflags 2.6.0", "com", "libc", - "libloading 0.8.5", + "libloading 0.7.4", "thiserror", "widestring", "winapi", @@ -2828,7 +2828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -5879,7 +5879,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.5", + "libloading 0.7.4", "log", "metal", "naga", diff --git a/src/wayland/protocols/keymap.rs b/src/wayland/protocols/keymap.rs index e96fd132..bbc72aae 100644 --- a/src/wayland/protocols/keymap.rs +++ b/src/wayland/protocols/keymap.rs @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only -use cosmic_protocols::keymap::v1::server::zcosmic_keymap_manager_v1::{ +use cosmic_protocols::keymap::v1::server::{zcosmic_keymap_v1::{self, ZcosmicKeymapV1}, zcosmic_keymap_manager_v1::{ self, ZcosmicKeymapManagerV1, -}; +}}; use smithay::{ input::{ keyboard::{KeyboardHandle, Layout}, @@ -60,28 +60,62 @@ where impl Dispatch for KeymapState where - D: Dispatch + 'static, + D: Dispatch, + D: Dispatch>, + D: 'static, D: SeatHandler, { fn request( - state: &mut D, + _state: &mut D, _client: &Client, _resource: &ZcosmicKeymapManagerV1, request: zcosmic_keymap_manager_v1::Request, _data: &(), _dhandle: &DisplayHandle, + data_init: &mut DataInit<'_, D>, + ) { + match request { + zcosmic_keymap_manager_v1::Request::GetKeymap { keymap, keyboard } => { + let handle = KeyboardHandle::::from_resource(&keyboard); + data_init.init(keymap, KeymapUserData { + handle + }); + } + zcosmic_keymap_manager_v1::Request::Destroy => {} + _ => unreachable!(), + } + } +} + +#[doc(hidden)] +pub struct KeymapUserData { + handle: Option>, +} + +impl Dispatch, D> for KeymapState +where + D: Dispatch>, + D: 'static, + D: SeatHandler, +{ + fn request( + state: &mut D, + _client: &Client, + _resource: &ZcosmicKeymapV1, + request: zcosmic_keymap_v1::Request, + data: &KeymapUserData, + _dhandle: &DisplayHandle, _data_init: &mut DataInit<'_, D>, ) { match request { - zcosmic_keymap_manager_v1::Request::SetGroup { keyboard, group } => { - if let Some(handle) = KeyboardHandle::::from_resource(&keyboard) { + zcosmic_keymap_v1::Request::SetGroup { group } => { + if let Some(handle) = data.handle.as_ref() { handle.with_xkb_state(state, |mut context| { context.set_layout(Layout(group)); - // TODO is `modifiers` sent? }); } } - zcosmic_keymap_manager_v1::Request::Destroy => {} + zcosmic_keymap_v1::Request::Destroy => {} _ => unreachable!(), } } @@ -95,6 +129,9 @@ macro_rules! delegate_keymap { smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ cosmic_protocols::keymap::v1::server::zcosmic_keymap_manager_v1::ZcosmicKeymapManagerV1: () ] => $crate::wayland::protocols::keymap::KeymapState); + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::keymap::v1::server::zcosmic_keymap_v1::ZcosmicKeymapV1: $crate::wayland::protocols::keymap::KeymapUserData<$ty> + ] => $crate::wayland::protocols::keymap::KeymapState); }; } pub(crate) use delegate_keymap; From 4ad0bcec47888aa80dd823ccc1e6c51eb699b1c4 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 15 Nov 2024 17:24:15 -0800 Subject: [PATCH 3/7] WIP track list of keymaps --- src/state.rs | 4 +++- src/wayland/handlers/keymap.rs | 9 ++++++++- src/wayland/protocols/keymap.rs | 30 +++++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/state.rs b/src/state.rs index 2eab2327..961b0801 100644 --- a/src/state.rs +++ b/src/state.rs @@ -218,6 +218,7 @@ pub struct Common { pub viewporter_state: ViewporterState, pub kde_decoration_state: KdeDecorationState, pub xdg_decoration_state: XdgDecorationState, + pub keymap_state: KeymapState, // shell-related wayland state pub xdg_shell_state: XdgShellState, @@ -523,7 +524,7 @@ impl State { VirtualKeyboardManagerState::new::(&dh, client_is_privileged); AlphaModifierState::new::(&dh); SinglePixelBufferState::new::(&dh); - KeymapState::new::(&dh, client_is_privileged); + let keymap_state = KeymapState::new::(&dh, client_is_privileged); let idle_notifier_state = IdleNotifierState::::new(&dh, handle.clone()); let idle_inhibit_manager_state = IdleInhibitManagerState::new::(&dh); @@ -627,6 +628,7 @@ impl State { xwayland_state: None, xwayland_shell_state, pointer_focus_state: None, + keymap_state, atspi_state, atspi_ei: Default::default(), diff --git a/src/wayland/handlers/keymap.rs b/src/wayland/handlers/keymap.rs index 9b4a50c3..fd5d4004 100644 --- a/src/wayland/handlers/keymap.rs +++ b/src/wayland/handlers/keymap.rs @@ -1,5 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-only -// + use crate::{state::State, wayland::protocols::keymap::delegate_keymap}; +use crate::wayland::protocols::keymap::{KeymapHandler, KeymapState}; + +impl KeymapHandler for State { + fn keymap_state(&mut self) -> &mut KeymapState { + &mut self.common.keymap_state + } +} delegate_keymap!(State); diff --git a/src/wayland/protocols/keymap.rs b/src/wayland/protocols/keymap.rs index bbc72aae..668f78cf 100644 --- a/src/wayland/protocols/keymap.rs +++ b/src/wayland/protocols/keymap.rs @@ -8,12 +8,22 @@ use smithay::{ keyboard::{KeyboardHandle, Layout}, SeatHandler, }, - reexports::wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New}, + reexports::{ + wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New}, + } }; -use wayland_backend::server::GlobalId; +use wayland_backend::server::{ClientId, GlobalId}; + +pub trait KeymapHandler { + fn keymap_state(&mut self) -> &mut KeymapState; +} +// TODO: add a refrensh function that sends `group` +// track list of keymaps per keyboard +#[derive(Debug)] pub struct KeymapState { pub global: GlobalId, + keymaps: Vec, } impl KeymapState { @@ -28,7 +38,7 @@ impl KeymapState { filter: Box::new(client_filter), }, ); - KeymapState { global } + KeymapState { global, keymaps: Vec::new() } } } @@ -64,9 +74,10 @@ where D: Dispatch>, D: 'static, D: SeatHandler, + D: KeymapHandler, { fn request( - _state: &mut D, + state: &mut D, _client: &Client, _resource: &ZcosmicKeymapManagerV1, request: zcosmic_keymap_manager_v1::Request, @@ -77,9 +88,10 @@ where match request { zcosmic_keymap_manager_v1::Request::GetKeymap { keymap, keyboard } => { let handle = KeyboardHandle::::from_resource(&keyboard); - data_init.init(keymap, KeymapUserData { + let keymap = data_init.init(keymap, KeymapUserData { handle }); + state.keymap_state().keymaps.push(keymap); } zcosmic_keymap_manager_v1::Request::Destroy => {} _ => unreachable!(), @@ -97,6 +109,7 @@ where D: Dispatch>, D: 'static, D: SeatHandler, + D: KeymapHandler, { fn request( state: &mut D, @@ -119,6 +132,13 @@ where _ => unreachable!(), } } + + fn destroyed(state: &mut D, _client: ClientId, keymap: &ZcosmicKeymapV1, _data: &KeymapUserData) { + let keymaps = &mut state.keymap_state().keymaps; + if let Some(idx) = keymaps.iter().position(|x| x == keymap) { + keymaps.remove(idx); + } + } } macro_rules! delegate_keymap { From 2075a54d6dd0c3f8d470b3c05dcc5399c3fa9d0c Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 18 Nov 2024 09:29:02 -0800 Subject: [PATCH 4/7] group refresh --- src/wayland/protocols/keymap.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/wayland/protocols/keymap.rs b/src/wayland/protocols/keymap.rs index 668f78cf..5b920b93 100644 --- a/src/wayland/protocols/keymap.rs +++ b/src/wayland/protocols/keymap.rs @@ -24,6 +24,7 @@ pub trait KeymapHandler { pub struct KeymapState { pub global: GlobalId, keymaps: Vec, + group: Option, } impl KeymapState { @@ -38,7 +39,16 @@ impl KeymapState { filter: Box::new(client_filter), }, ); - KeymapState { global, keymaps: Vec::new() } + KeymapState { global, keymaps: Vec::new(), group: None } + } + + pub fn refresh(&mut self, group: u32) { + if self.group != Some(group) { + for keymap in &self.keymaps { + keymap.group(group); + } + self.group = Some(group); + } } } @@ -91,6 +101,9 @@ where let keymap = data_init.init(keymap, KeymapUserData { handle }); + if let Some(group) = state.keymap_state().group { + keymap.group(group); + } state.keymap_state().keymaps.push(keymap); } zcosmic_keymap_manager_v1::Request::Destroy => {} From 7f353e6db31c9ad23d94540d1f3b1dfeb39737cb Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 18 Nov 2024 09:43:09 -0800 Subject: [PATCH 5/7] WIP --- src/wayland/handlers/keymap.rs | 2 +- src/wayland/protocols/keymap.rs | 36 ++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/wayland/handlers/keymap.rs b/src/wayland/handlers/keymap.rs index fd5d4004..9e35c615 100644 --- a/src/wayland/handlers/keymap.rs +++ b/src/wayland/handlers/keymap.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::{state::State, wayland::protocols::keymap::delegate_keymap}; use crate::wayland::protocols::keymap::{KeymapHandler, KeymapState}; +use crate::{state::State, wayland::protocols::keymap::delegate_keymap}; impl KeymapHandler for State { fn keymap_state(&mut self) -> &mut KeymapState { diff --git a/src/wayland/protocols/keymap.rs b/src/wayland/protocols/keymap.rs index 5b920b93..328b6f81 100644 --- a/src/wayland/protocols/keymap.rs +++ b/src/wayland/protocols/keymap.rs @@ -1,16 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-only -use cosmic_protocols::keymap::v1::server::{zcosmic_keymap_v1::{self, ZcosmicKeymapV1}, zcosmic_keymap_manager_v1::{ - self, ZcosmicKeymapManagerV1, -}}; +use cosmic_protocols::keymap::v1::server::{ + zcosmic_keymap_manager_v1::{self, ZcosmicKeymapManagerV1}, + zcosmic_keymap_v1::{self, ZcosmicKeymapV1}, +}; use smithay::{ input::{ keyboard::{KeyboardHandle, Layout}, SeatHandler, }, - reexports::{ - wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New}, - } + reexports::wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New}, }; use wayland_backend::server::{ClientId, GlobalId}; @@ -25,6 +24,7 @@ pub struct KeymapState { pub global: GlobalId, keymaps: Vec, group: Option, + // TODO: per keyboard? } impl KeymapState { @@ -39,7 +39,11 @@ impl KeymapState { filter: Box::new(client_filter), }, ); - KeymapState { global, keymaps: Vec::new(), group: None } + KeymapState { + global, + keymaps: Vec::new(), + group: None, + } } pub fn refresh(&mut self, group: u32) { @@ -98,11 +102,14 @@ where match request { zcosmic_keymap_manager_v1::Request::GetKeymap { keymap, keyboard } => { let handle = KeyboardHandle::::from_resource(&keyboard); - let keymap = data_init.init(keymap, KeymapUserData { - handle + let active_layout = handle.as_ref().map(|handle| { + handle.with_xkb_state(state, |context| { + context.xkb().lock().unwrap().active_layout() + }) }); - if let Some(group) = state.keymap_state().group { - keymap.group(group); + let keymap = data_init.init(keymap, KeymapUserData { handle }); + if let Some(layout) = active_layout { + keymap.group(layout.0); } state.keymap_state().keymaps.push(keymap); } @@ -146,7 +153,12 @@ where } } - fn destroyed(state: &mut D, _client: ClientId, keymap: &ZcosmicKeymapV1, _data: &KeymapUserData) { + fn destroyed( + state: &mut D, + _client: ClientId, + keymap: &ZcosmicKeymapV1, + _data: &KeymapUserData, + ) { let keymaps = &mut state.keymap_state().keymaps; if let Some(idx) = keymaps.iter().position(|x| x == keymap) { keymaps.remove(idx); From 8c88777cacc13e1ff2e4f7db59d35c7d5278e9d9 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 18 Nov 2024 09:51:24 -0800 Subject: [PATCH 6/7] WIP --- src/wayland/protocols/keymap.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/wayland/protocols/keymap.rs b/src/wayland/protocols/keymap.rs index 328b6f81..6736e18e 100644 --- a/src/wayland/protocols/keymap.rs +++ b/src/wayland/protocols/keymap.rs @@ -9,7 +9,7 @@ use smithay::{ keyboard::{KeyboardHandle, Layout}, SeatHandler, }, - reexports::wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New}, + reexports::wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, Resource, New}, }; use wayland_backend::server::{ClientId, GlobalId}; @@ -17,14 +17,10 @@ pub trait KeymapHandler { fn keymap_state(&mut self) -> &mut KeymapState; } -// TODO: add a refrensh function that sends `group` -// track list of keymaps per keyboard #[derive(Debug)] pub struct KeymapState { pub global: GlobalId, - keymaps: Vec, - group: Option, - // TODO: per keyboard? + keymaps: Vec<(ZcosmicKeymapV1, Option)>, } impl KeymapState { @@ -42,16 +38,23 @@ impl KeymapState { KeymapState { global, keymaps: Vec::new(), - group: None, } } - pub fn refresh(&mut self, group: u32) { - if self.group != Some(group) { - for keymap in &self.keymaps { - keymap.group(group); + // requires D + pub fn refresh(&mut self, state: &mut D) { + for (keymap, last_layout) in &mut self.keymaps { + if let Some(data) = keymap.data::>() { + if let Some(handle) = &data.handle { + let active_layout = handle.with_xkb_state(state, |context| { + context.xkb().lock().unwrap().active_layout() + }); + if *last_layout != Some(active_layout) { + keymap.group(active_layout.0); + *last_layout = Some(active_layout); + } + } } - self.group = Some(group); } } } @@ -111,7 +114,7 @@ where if let Some(layout) = active_layout { keymap.group(layout.0); } - state.keymap_state().keymaps.push(keymap); + state.keymap_state().keymaps.push((keymap, active_layout)); } zcosmic_keymap_manager_v1::Request::Destroy => {} _ => unreachable!(), @@ -160,7 +163,7 @@ where _data: &KeymapUserData, ) { let keymaps = &mut state.keymap_state().keymaps; - if let Some(idx) = keymaps.iter().position(|x| x == keymap) { + if let Some(idx) = keymaps.iter().position(|(x, _)| x == keymap) { keymaps.remove(idx); } } From 30aebf1cc1b894e5d6bfc88c1ac067c1cc711161 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 18 Nov 2024 09:58:36 -0800 Subject: [PATCH 7/7] refresh --- src/main.rs | 6 +++++- src/wayland/protocols/keymap.rs | 15 +++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4c9c4860..99667679 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,9 @@ use state::State; use std::{env, ffi::OsString, os::unix::process::CommandExt, process, sync::Arc}; use tracing::{error, info, warn}; -use crate::wayland::handlers::compositor::client_compositor_state; +use crate::wayland::{ + handlers::compositor::client_compositor_state, protocols::keymap::KeymapState, +}; pub mod backend; pub mod config; @@ -133,6 +135,8 @@ fn main() -> Result<()> { state::Common::refresh_focus(state); state.common.update_x11_stacking_order(); + KeymapState::refresh(state); + { let shell = state.common.shell.read().unwrap(); if shell.animations_going() { diff --git a/src/wayland/protocols/keymap.rs b/src/wayland/protocols/keymap.rs index 6736e18e..36b2f360 100644 --- a/src/wayland/protocols/keymap.rs +++ b/src/wayland/protocols/keymap.rs @@ -9,8 +9,11 @@ use smithay::{ keyboard::{KeyboardHandle, Layout}, SeatHandler, }, - reexports::wayland_server::{Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, Resource, New}, + reexports::wayland_server::{ + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, + }, }; +use std::mem; use wayland_backend::server::{ClientId, GlobalId}; pub trait KeymapHandler { @@ -41,9 +44,12 @@ impl KeymapState { } } - // requires D - pub fn refresh(&mut self, state: &mut D) { - for (keymap, last_layout) in &mut self.keymaps { + pub fn refresh(state: &mut D) + where + D: SeatHandler + KeymapHandler + 'static, + { + let mut keymaps = mem::take(&mut state.keymap_state().keymaps); + for (keymap, last_layout) in &mut keymaps { if let Some(data) = keymap.data::>() { if let Some(handle) = &data.handle { let active_layout = handle.with_xkb_state(state, |context| { @@ -56,6 +62,7 @@ impl KeymapState { } } } + state.keymap_state().keymaps = keymaps; } }