reload system layout instead of re-using from startup

This commit is contained in:
galister
2025-12-15 20:32:13 +09:00
parent a0c9275b44
commit 19b7541049
4 changed files with 52 additions and 54 deletions

View File

@@ -6,22 +6,23 @@ use std::{
}; };
use crate::{ use crate::{
KEYMAP_CHANGE,
backend::input::{HoverResult, PointerHit}, backend::input::{HoverResult, PointerHit},
gui::panel::GuiPanel, gui::panel::GuiPanel,
overlays::keyboard::{builder::create_keyboard_panel, layout::AltModifier}, overlays::keyboard::{builder::create_keyboard_panel, layout::AltModifier},
state::AppState, state::AppState,
subsystem::hid::{ subsystem::hid::{
ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey, WheelDelta, XkbKeymap, get_keymap_wl, get_keymap_x11, KeyModifier, VirtualKey, WheelDelta, XkbKeymap, ALT, CTRL,
META, SHIFT, SUPER,
}, },
windowing::{ windowing::{
backend::{FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender}, backend::{FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender},
window::OverlayWindowConfig, window::OverlayWindowConfig,
}, },
KEYMAP_CHANGE,
}; };
use anyhow::Context; use anyhow::Context;
use glam::{Affine3A, Quat, Vec3, vec3}; use glam::{vec3, Affine3A, Quat, Vec3};
use slotmap::{SlotMap, new_key_type}; use slotmap::{new_key_type, SlotMap};
use wgui::{ use wgui::{
drawing, drawing,
event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex}, event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex},
@@ -35,10 +36,7 @@ pub const KEYBOARD_NAME: &str = "kbd";
const AUTO_RELEASE_MODS: [KeyModifier; 5] = [SHIFT, CTRL, ALT, SUPER, META]; const AUTO_RELEASE_MODS: [KeyModifier; 5] = [SHIFT, CTRL, ALT, SUPER, META];
const SYSTEM_LAYOUT_ALIASES: [&str; 5] = ["mozc", "pinyin", "hangul", "sayura", "unikey"]; const SYSTEM_LAYOUT_ALIASES: [&str; 5] = ["mozc", "pinyin", "hangul", "sayura", "unikey"];
pub fn create_keyboard( pub fn create_keyboard(app: &mut AppState, wayland: bool) -> anyhow::Result<OverlayWindowConfig> {
app: &mut AppState,
keymap: Option<XkbKeymap>,
) -> anyhow::Result<OverlayWindowConfig> {
let layout = layout::Layout::load_from_disk(); let layout = layout::Layout::load_from_disk();
let default_state = KeyboardState { let default_state = KeyboardState {
modifiers: 0, modifiers: 0,
@@ -53,15 +51,7 @@ pub fn create_keyboard(
processes: vec![], processes: vec![],
}; };
if let Some(keymap) = keymap.as_ref() { let auto_labels = layout.auto_labels.unwrap_or(true);
app.hid_provider.keymap_changed(keymap);
}
let effective_keymap = if layout.auto_labels.unwrap_or(true) {
keymap.as_ref()
} else {
None
};
let width = layout.row_size * 0.05 * app.session.config.keyboard_scale; let width = layout.row_size * 0.05 * app.session.config.keyboard_scale;
@@ -69,16 +59,25 @@ pub fn create_keyboard(
layout_panels: SlotMap::default(), layout_panels: SlotMap::default(),
layout_ids: HashMap::default(), layout_ids: HashMap::default(),
active_layout: KeyboardPanelKey::default(), active_layout: KeyboardPanelKey::default(),
default_layout: KeyboardPanelKey::default(),
default_state, default_state,
default_keymap: None,
wlx_layout: layout, wlx_layout: layout,
wayland,
}; };
backend.active_layout = backend.add_new_keymap(effective_keymap, app)?; let mut maybe_keymap = backend
backend.default_layout = backend.active_layout; .get_system_keymap()
.inspect_err(|e| log::warn!("{e:?}"))
.ok();
backend.default_keymap = keymap; if let Some(keymap) = maybe_keymap.as_ref() {
app.hid_provider.keymap_changed(keymap);
}
if !auto_labels {
maybe_keymap = None;
}
backend.active_layout = backend.add_new_keymap(maybe_keymap.as_ref(), app)?;
Ok(OverlayWindowConfig { Ok(OverlayWindowConfig {
name: KEYBOARD_NAME.into(), name: KEYBOARD_NAME.into(),
@@ -106,10 +105,9 @@ struct KeyboardBackend {
layout_panels: SlotMap<KeyboardPanelKey, GuiPanel<KeyboardState>>, layout_panels: SlotMap<KeyboardPanelKey, GuiPanel<KeyboardState>>,
layout_ids: HashMap<String, KeyboardPanelKey>, layout_ids: HashMap<String, KeyboardPanelKey>,
active_layout: KeyboardPanelKey, active_layout: KeyboardPanelKey,
default_layout: KeyboardPanelKey,
default_state: KeyboardState, default_state: KeyboardState,
default_keymap: Option<XkbKeymap>,
wlx_layout: layout::Layout, wlx_layout: layout::Layout,
wayland: bool,
} }
impl KeyboardBackend { impl KeyboardBackend {
@@ -168,6 +166,20 @@ impl KeyboardBackend {
.state = state_from; .state = state_from;
} }
fn get_system_keymap(&mut self) -> anyhow::Result<XkbKeymap> {
#[cfg(feature = "wayland")]
if self.wayland {
return get_keymap_wl();
}
#[cfg(feature = "x11")]
if !self.wayland {
return get_keymap_x11();
}
unreachable!();
}
fn switch_to_fcitx_keymap(&mut self, app: &mut AppState) -> anyhow::Result<bool> { fn switch_to_fcitx_keymap(&mut self, app: &mut AppState) -> anyhow::Result<bool> {
let fcitx_layout = app let fcitx_layout = app
.dbus .dbus
@@ -182,16 +194,10 @@ impl KeyboardBackend {
app.hid_provider.keymap_changed(&keymap); app.hid_provider.keymap_changed(&keymap);
self.switch_keymap(&keymap, app) self.switch_keymap(&keymap, app)
} else if SYSTEM_LAYOUT_ALIASES.contains(&fcitx_layout.as_str()) { } else if SYSTEM_LAYOUT_ALIASES.contains(&fcitx_layout.as_str()) {
if let Some(keymap) = self.default_keymap.as_ref() {
app.hid_provider.keymap_changed(&keymap);
}
log::debug!("{fcitx_layout} is an IME, switching to system layout."); log::debug!("{fcitx_layout} is an IME, switching to system layout.");
if self.active_layout == self.default_layout { let keymap = self.get_system_keymap()?;
Ok(false) app.hid_provider.keymap_changed(&keymap);
} else { self.switch_keymap(&keymap, app)
self.internal_switch_keymap(self.default_layout);
Ok(true)
}
} else { } else {
anyhow::bail!("Unknown layout or IME: {fcitx_layout}"); anyhow::bail!("Unknown layout or IME: {fcitx_layout}");
} }

View File

@@ -1,6 +1,6 @@
use std::{f32::consts::PI, sync::Arc}; use std::{f32::consts::PI, sync::Arc};
use glam::{Affine3A, Quat, Vec3, vec3}; use glam::{vec3, Affine3A, Quat, Vec3};
use wlx_capture::frame::Transform; use wlx_capture::frame::Transform;
use wlx_common::windowing::{OverlayWindowState, Positioning}; use wlx_common::windowing::{OverlayWindowState, Positioning};
@@ -63,35 +63,27 @@ pub struct ScreenCreateData {
pub screens: Vec<(ScreenMeta, OverlayWindowConfig)>, pub screens: Vec<(ScreenMeta, OverlayWindowConfig)>,
} }
pub fn create_screens(app: &mut AppState) -> anyhow::Result<(ScreenCreateData, Option<XkbKeymap>)> { pub fn create_screens(app: &mut AppState) -> anyhow::Result<(ScreenCreateData, bool)> {
app.screens.clear(); app.screens.clear();
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
{ {
if let Some(mut wl) = wlx_capture::wayland::WlxClient::new() { if let Some(mut wl) = wlx_capture::wayland::WlxClient::new() {
log::info!("Wayland detected."); log::info!("Wayland detected.");
let keymap = crate::subsystem::hid::get_keymap_wl() return Ok((wl::create_screens_wayland(&mut wl, app), true));
.map_err(|f| log::warn!("Could not load keyboard layout: {f}"))
.ok();
return Ok((wl::create_screens_wayland(&mut wl, app), keymap));
} }
log::info!("Wayland not detected, assuming X11."); log::info!("Wayland not detected, assuming X11.");
} }
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
{ {
let keymap = crate::subsystem::hid::get_keymap_x11()
.map_err(|f| log::warn!("Could not load keyboard layout: {f}"))
.ok();
#[cfg(feature = "pipewire")] #[cfg(feature = "pipewire")]
match x11::create_screens_x11pw(app) { match x11::create_screens_x11pw(app) {
Ok(data) => return Ok((data, keymap)), Ok(data) => return Ok((data, false)),
Err(e) => log::info!("Will not use X11 PipeWire capture: {e:?}"), Err(e) => log::info!("Will not use X11 PipeWire capture: {e:?}"),
} }
Ok((x11::create_screens_xshm(app)?, keymap)) Ok((x11::create_screens_xshm(app)?, false))
} }
#[cfg(not(feature = "x11"))] #[cfg(not(feature = "x11"))]
anyhow::bail!("No backends left to try.") anyhow::bail!("No backends left to try.")

View File

@@ -1,5 +1,5 @@
use glam::Vec2; use glam::Vec2;
use idmap::{IdMap, idmap}; use idmap::{idmap, IdMap};
use idmap_derive::IntegerId; use idmap_derive::IntegerId;
use input_linux::{ use input_linux::{
AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis, AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis,

View File

@@ -12,7 +12,6 @@ use wlx_common::{
}; };
use crate::{ use crate::{
FRAME_COUNTER,
backend::task::OverlayTask, backend::task::OverlayTask,
overlays::{ overlays::{
anchor::create_anchor, edit::EditWrapperManager, keyboard::create_keyboard, anchor::create_anchor, edit::EditWrapperManager, keyboard::create_keyboard,
@@ -20,12 +19,13 @@ use crate::{
}, },
state::AppState, state::AppState,
windowing::{ windowing::{
OverlayID, OverlaySelector,
backend::{OverlayEventData, OverlayMeta}, backend::{OverlayEventData, OverlayMeta},
set::OverlayWindowSet, set::OverlayWindowSet,
snap_upright, snap_upright,
window::{OverlayCategory, OverlayWindowData}, window::{OverlayCategory, OverlayWindowData},
OverlayID, OverlaySelector,
}, },
FRAME_COUNTER,
}; };
pub const MAX_OVERLAY_SETS: usize = 7; pub const MAX_OVERLAY_SETS: usize = 7;
@@ -50,8 +50,6 @@ where
T: Default, T: Default,
{ {
pub fn new(app: &mut AppState, headless: bool) -> anyhow::Result<Self> { pub fn new(app: &mut AppState, headless: bool) -> anyhow::Result<Self> {
let mut maybe_keymap = None;
let mut me = Self { let mut me = Self {
wrappers: EditWrapperManager::default(), wrappers: EditWrapperManager::default(),
overlays: HopSlotMap::with_key(), overlays: HopSlotMap::with_key(),
@@ -64,6 +62,8 @@ where
dropped_overlays: VecDeque::with_capacity(8), dropped_overlays: VecDeque::with_capacity(8),
}; };
let mut wayland = false;
if headless { if headless {
log::info!("Running in headless mode; keyboard will be en-US"); log::info!("Running in headless mode; keyboard will be en-US");
} else { } else {
@@ -71,7 +71,7 @@ where
// this is the default and would be overwritten by // this is the default and would be overwritten by
// OverlayWindowManager::restore_layout down below // OverlayWindowManager::restore_layout down below
match create_screens(app) { match create_screens(app) {
Ok((data, keymap)) => { Ok((data, is_wayland)) => {
let last_idx = data.screens.len() - 1; let last_idx = data.screens.len() - 1;
for (idx, (meta, mut config)) in data.screens.into_iter().enumerate() { for (idx, (meta, mut config)) in data.screens.into_iter().enumerate() {
config.show_on_spawn = true; config.show_on_spawn = true;
@@ -84,13 +84,13 @@ where
app.screens.push(meta); app.screens.push(meta);
} }
maybe_keymap = keymap; wayland = is_wayland;
} }
Err(e) => log::error!("Unable to initialize screens: {e:?}"), Err(e) => log::error!("Unable to initialize screens: {e:?}"),
} }
} }
let mut keyboard = OverlayWindowData::from_config(create_keyboard(app, maybe_keymap)?); let mut keyboard = OverlayWindowData::from_config(create_keyboard(app, wayland)?);
keyboard.config.show_on_spawn = true; keyboard.config.show_on_spawn = true;
let keyboard_id = me.add(keyboard, app); let keyboard_id = me.add(keyboard, app);