diff --git a/wlx-overlay-s/src/overlays/keyboard/mod.rs b/wlx-overlay-s/src/overlays/keyboard/mod.rs index 2f23169..518876b 100644 --- a/wlx-overlay-s/src/overlays/keyboard/mod.rs +++ b/wlx-overlay-s/src/overlays/keyboard/mod.rs @@ -10,7 +10,8 @@ use crate::{ overlays::keyboard::{builder::create_keyboard_panel, layout::AltModifier}, state::AppState, subsystem::hid::{ - ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey, WheelDelta, XkbKeymap, + wayland::WlKeymapMonitor, KeyModifier, VirtualKey, WheelDelta, XkbKeymap, ALT, CTRL, META, + SHIFT, SUPER, }, windowing::{ backend::{FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender}, @@ -18,8 +19,8 @@ use crate::{ }, }; use dbus::message::MatchRule; -use glam::{Affine3A, Quat, Vec3, vec3}; -use slotmap::{SlotMap, new_key_type}; +use glam::{vec3, Affine3A, Quat, Vec3}; +use slotmap::{new_key_type, SlotMap}; use wgui::{ drawing, event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex}, @@ -62,10 +63,10 @@ pub fn create_keyboard( active_keymap: KeyboardPanelKey::default(), default_state, layout, + wkm: WlKeymapMonitor::new()?, }; backend.active_keymap = backend.add_new_keymap(keymap.as_ref(), app)?; - backend.watch_dbus(app); Ok(OverlayWindowConfig { name: KEYBOARD_NAME.into(), @@ -95,6 +96,7 @@ struct KeyboardBackend { active_keymap: KeyboardPanelKey, default_state: KeyboardState, layout: layout::Layout, + wkm: WlKeymapMonitor, } impl KeyboardBackend { @@ -114,43 +116,22 @@ impl KeyboardBackend { Ok(id) } - fn watch_dbus(&mut self, app: &mut AppState) { - let rules = [ - MatchRule::new() - .with_member("CurrentInputMethod") - .with_interface("org.fcitx.Fcitx.Controller1") - .with_path("/controller") - .with_sender("org.fcitx.Fcitx5"), - MatchRule::new_signal("org.kde.KeyboardLayouts", "layoutChanged").with_path("/Layouts"), - ]; - - for rule in rules { - let _ = app.dbus.add_match( - rule, - Box::new(move |(), _, msg| { - log::warn!("new keymap: {msg:?}"); - true - }), - ); - } - } - - fn switch_keymap(&mut self, keymap: &XkbKeymap, app: &mut AppState) -> anyhow::Result<()> { + fn switch_keymap(&mut self, keymap: &XkbKeymap, app: &mut AppState) -> anyhow::Result { let Some(layout_name) = keymap.inner.layouts().next() else { log::error!("XKB keymap without a layout!"); - return Ok(()); + return Ok(false); }; if let Some(new_key) = self.keymap_ids.get(layout_name) { if self.active_keymap.eq(new_key) { - return Ok(()); + return Ok(false); } self.internal_switch_keymap(*new_key); } else { let new_key = self.add_new_keymap(Some(keymap), app)?; self.internal_switch_keymap(new_key); } - Ok(()) + Ok(true) } fn internal_switch_keymap(&mut self, new_key: KeyboardPanelKey) { @@ -179,6 +160,14 @@ impl OverlayBackend for KeyboardBackend { self.panel().init(app) } fn should_render(&mut self, app: &mut AppState) -> anyhow::Result { + if let Some(keymap) = self.wkm.check() { + if self.switch_keymap(&keymap, app)? { + return Ok(match self.panel().should_render(app)? { + ShouldRender::Should | ShouldRender::Can => ShouldRender::Should, + ShouldRender::Unable => ShouldRender::Unable, + }); + } + } self.panel().should_render(app) } fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> { diff --git a/wlx-overlay-s/src/subsystem/hid/mod.rs b/wlx-overlay-s/src/subsystem/hid/mod.rs index f0a8e2b..bee74cf 100644 --- a/wlx-overlay-s/src/subsystem/hid/mod.rs +++ b/wlx-overlay-s/src/subsystem/hid/mod.rs @@ -1,5 +1,5 @@ use glam::Vec2; -use idmap::{IdMap, idmap}; +use idmap::{idmap, IdMap}; use idmap_derive::IntegerId; use input_linux::{ AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis, @@ -14,7 +14,7 @@ use strum::{EnumIter, EnumString, IntoEnumIterator}; use xkbcommon::xkb; #[cfg(feature = "wayland")] -mod wayland; +pub mod wayland; #[cfg(feature = "x11")] mod x11; diff --git a/wlx-overlay-s/src/subsystem/hid/wayland.rs b/wlx-overlay-s/src/subsystem/hid/wayland.rs index 1fe9624..b754a80 100644 --- a/wlx-overlay-s/src/subsystem/hid/wayland.rs +++ b/wlx-overlay-s/src/subsystem/hid/wayland.rs @@ -1,24 +1,81 @@ use anyhow::Context; +use wayland_client::{globals::GlobalList, EventQueue}; use wlx_capture::wayland::wayland_client::{ - Connection, Dispatch, Proxy, QueueHandle, - globals::{GlobalListContents, registry_queue_init}, + globals::{registry_queue_init, GlobalListContents}, protocol::{ wl_keyboard::{self, WlKeyboard}, wl_registry::WlRegistry, wl_seat::{self, Capability, WlSeat}, }, + Connection, Dispatch, Proxy, QueueHandle, }; use xkbcommon::xkb; use super::XkbKeymap; -struct WlKeymapHandler { +pub struct WlKeymapMonitor { + connection: Connection, + globals: GlobalList, + queue: EventQueue, + state: MonitorState, +} + +impl WlKeymapMonitor { + pub fn new() -> anyhow::Result { + let connection = Connection::connect_to_env()?; + let (globals, mut queue) = registry_queue_init::(&connection)?; + let qh = queue.handle(); + let seat: WlSeat = globals + .bind(&qh, 4..=9, ()) + .unwrap_or_else(|_| panic!("{}", WlSeat::interface().name)); + + let mut state = MonitorState { + seat, + keyboard: None, + keymap: None, + }; + + // this gets us the wl_seat + let _ = queue.blocking_dispatch(&mut state); + + // this gets us the wl_keyboard + let _ = queue.blocking_dispatch(&mut state); + + Ok(Self { + connection, + globals, + queue, + state, + }) + } + + pub fn check(&mut self) -> Option { + let Some(read_guard) = self.connection.prepare_read() else { + return None; + }; + read_guard + .read() + .context("could not read wayland events") + .inspect_err(|e| log::warn!("{e:?}")) + .ok()?; + + self.queue.dispatch_pending(&mut self.state).ok()?; + + self.take_keymap() + } + + pub fn take_keymap(&mut self) -> Option { + self.state.keymap.take() + } +} + +struct MonitorState { seat: WlSeat, keyboard: Option, keymap: Option, } -impl Drop for WlKeymapHandler { +impl Drop for MonitorState { fn drop(&mut self) { if let Some(keyboard) = &self.keyboard { keyboard.release(); @@ -29,13 +86,13 @@ impl Drop for WlKeymapHandler { pub fn get_keymap_wl() -> anyhow::Result { let connection = Connection::connect_to_env()?; - let (globals, mut queue) = registry_queue_init::(&connection)?; + let (globals, mut queue) = registry_queue_init::(&connection)?; let qh = queue.handle(); let seat: WlSeat = globals .bind(&qh, 4..=9, ()) .unwrap_or_else(|_| panic!("{}", WlSeat::interface().name)); - let mut me = WlKeymapHandler { + let mut me = MonitorState { seat, keyboard: None, keymap: None, @@ -50,7 +107,7 @@ pub fn get_keymap_wl() -> anyhow::Result { me.keymap.take().context("could not load keymap") } -impl Dispatch for WlKeymapHandler { +impl Dispatch for MonitorState { fn event( _state: &mut Self, _proxy: &WlRegistry, @@ -62,7 +119,7 @@ impl Dispatch for WlKeymapHandler { } } -impl Dispatch for WlKeymapHandler { +impl Dispatch for MonitorState { fn event( state: &mut Self, proxy: &WlSeat, @@ -88,7 +145,7 @@ impl Dispatch for WlKeymapHandler { } } -impl Dispatch for WlKeymapHandler { +impl Dispatch for MonitorState { fn event( state: &mut Self, _proxy: &WlKeyboard,