1
0
Fork 0
forked from wry/wry

cli: allow setting keymaps from RMLVO names

This commit is contained in:
Julian Orth 2025-12-29 20:55:46 +01:00
parent 0dfa6bc74b
commit eedec24e88
5 changed files with 148 additions and 2 deletions

View file

@ -77,6 +77,8 @@ pub enum SeatCommand {
SetRepeatRate(SetRepeatRateArgs), SetRepeatRate(SetRepeatRateArgs),
/// Set the keymap. /// Set the keymap.
SetKeymap(SetKeymapArgs), SetKeymap(SetKeymapArgs),
/// Set the keymap from RMLVO names.
SetKeymapFromNames(SetKeymapFromNamesArgs),
/// Retrieve the keymap. /// Retrieve the keymap.
Keymap, Keymap,
/// Configure whether this seat uses the hardware cursor. /// Configure whether this seat uses the hardware cursor.
@ -145,6 +147,8 @@ pub enum DeviceCommand {
SetTransformMatrix(SetTransformMatrixArgs), SetTransformMatrix(SetTransformMatrixArgs),
/// Set the keymap of this device. /// Set the keymap of this device.
SetKeymap(SetKeymapArgs), SetKeymap(SetKeymapArgs),
/// Set the keymap of this device from RMLVO names.
SetKeymapFromNames(SetKeymapFromNamesArgs),
/// Retrieve the keymap of this device. /// Retrieve the keymap of this device.
Keymap, Keymap,
/// Attach the device to a seat. /// Attach the device to a seat.
@ -293,6 +297,25 @@ pub struct SetKeymapArgs {
pub file: Option<String>, pub file: Option<String>,
} }
#[derive(Args, Debug, Clone)]
pub struct SetKeymapFromNamesArgs {
/// The rules file.
#[clap(short, long)]
pub rules: Option<String>,
/// The model name.
#[clap(short, long)]
pub model: Option<String>,
/// The comma-separated list of layouts.
#[clap(short, long)]
pub layout: Option<String>,
/// The comma-separated list of layout variants.
#[clap(short, long)]
pub variant: Option<String>,
/// The comma-separated list of options.
#[clap(short, long)]
pub options: Option<String>,
}
#[derive(Args, Debug, Clone)] #[derive(Args, Debug, Clone)]
pub struct UseHardwareCursorArgs { pub struct UseHardwareCursorArgs {
/// Whether the seat uses the hardware cursor. /// Whether the seat uses the hardware cursor.
@ -503,6 +526,20 @@ impl Input {
}); });
} }
}, },
SeatCommand::SetKeymapFromNames(a) => {
self.handle_error(input, |e| {
eprintln!("Could not set keymap: {}", e);
});
tc.send(jay_input::SetKeymapFromNames {
self_id: input,
seat: &args.seat,
rules: a.rules.as_deref(),
model: a.model.as_deref(),
layout: a.layout.as_deref(),
variant: a.variant.as_deref(),
options: a.options.as_deref(),
});
}
} }
tc.round_trip().await; tc.round_trip().await;
} }
@ -725,6 +762,20 @@ impl Input {
enabled: a.middle_button_emulation as _, enabled: a.middle_button_emulation as _,
}); });
} }
DeviceCommand::SetKeymapFromNames(a) => {
self.handle_error(input, |e| {
eprintln!("Could not set keymap: {}", e);
});
tc.send(jay_input::SetDeviceKeymapFromNames {
self_id: input,
id: args.device,
rules: a.rules.as_deref(),
model: a.model.as_deref(),
layout: a.layout.as_deref(),
variant: a.variant.as_deref(),
options: a.options.as_deref(),
});
}
} }
tc.round_trip().await; tc.round_trip().await;
} }

View file

@ -79,7 +79,7 @@ impl Global for JayCompositorGlobal {
} }
fn version(&self) -> u32 { fn version(&self) -> u32 {
23 24
} }
fn required_caps(&self) -> ClientCaps { fn required_caps(&self) -> ClientCaps {

View file

@ -16,6 +16,7 @@ use {
utils::errorfmt::ErrorFmt, utils::errorfmt::ErrorFmt,
wire::{JayInputId, jay_input::*}, wire::{JayInputId, jay_input::*},
}, },
kbvm::xkb::rmlvo::Group,
std::rc::Rc, std::rc::Rc,
thiserror::Error, thiserror::Error,
uapi::OwnedFd, uapi::OwnedFd,
@ -212,6 +213,44 @@ impl JayInput {
Ok(()) Ok(())
}) })
} }
fn set_keymap_from_names_impl<F>(
&self,
rules: Option<&str>,
model: Option<&str>,
layout: Option<&str>,
variant: Option<&str>,
options: Option<&str>,
f: F,
) -> Result<(), JayInputError>
where
F: FnOnce(&Rc<KbvmMap>) -> Result<(), JayInputError>,
{
self.or_error(|| {
let mut groups = None::<Vec<_>>;
if layout.is_some() || variant.is_some() {
groups = Some(
Group::from_layouts_and_variants(
layout.unwrap_or_default(),
variant.unwrap_or_default(),
)
.collect(),
);
}
let mut options_vec = None::<Vec<_>>;
if let Some(options) = options {
options_vec = Some(options.split(",").collect());
}
let keymap = self.client.state.kb_ctx.keymap_from_names(
rules,
model,
groups.as_deref(),
options_vec.as_deref(),
)?;
f(&keymap)?;
Ok(())
})
}
} }
impl JayInputRequestHandler for JayInput { impl JayInputRequestHandler for JayInput {
@ -539,6 +578,44 @@ impl JayInputRequestHandler for JayInput {
Ok(()) Ok(())
}) })
} }
fn set_keymap_from_names(
&self,
req: SetKeymapFromNames<'_>,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
self.set_keymap_from_names_impl(
req.rules,
req.model,
req.layout,
req.variant,
req.options,
|map| {
let seat = self.seat(req.seat)?;
seat.set_seat_keymap(&map);
Ok(())
},
)
}
fn set_device_keymap_from_names(
&self,
req: SetDeviceKeymapFromNames<'_>,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
self.set_keymap_from_names_impl(
req.rules,
req.model,
req.layout,
req.variant,
req.options,
|map| {
let dev = self.device(req.id)?;
dev.set_keymap(Some(map.clone()));
Ok(())
},
)
}
} }
object_base! { object_base! {

View file

@ -335,7 +335,7 @@ impl ToolClient {
self_id: s.registry, self_id: s.registry,
name: s.jay_compositor.0, name: s.jay_compositor.0,
interface: JayCompositor.name(), interface: JayCompositor.name(),
version: s.jay_compositor.1.min(23), version: s.jay_compositor.1.min(24),
id: id.into(), id: id.into(),
}); });
self.jay_compositor.set(Some(id)); self.jay_compositor.set(Some(id));

View file

@ -143,6 +143,24 @@ request reload_simple_im (since = 22) {
seat: str, seat: str,
} }
request set_keymap_from_names (since = 24) {
seat: str,
rules: optstr,
model: optstr,
layout: optstr,
variant: optstr,
options: optstr,
}
request set_device_keymap_from_names (since = 24) {
id: u32,
rules: optstr,
model: optstr,
layout: optstr,
variant: optstr,
options: optstr,
}
# events # events
event seat { event seat {