Merge pull request #705 from khyperia/keymap-from-names
config: Add keymap_from_names for RMLVO keymaps
This commit is contained in:
commit
7042efa4c7
10 changed files with 283 additions and 6 deletions
|
|
@ -19,7 +19,7 @@ use {
|
||||||
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
||||||
},
|
},
|
||||||
keyboard::{
|
keyboard::{
|
||||||
Keymap,
|
Group, Keymap,
|
||||||
mods::{Modifiers, RELEASE},
|
mods::{Modifiers, RELEASE},
|
||||||
syms::KeySym,
|
syms::KeySym,
|
||||||
},
|
},
|
||||||
|
|
@ -1385,6 +1385,23 @@ impl ConfigClient {
|
||||||
keymap
|
keymap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn keymap_from_names(
|
||||||
|
&self,
|
||||||
|
rules: Option<&str>,
|
||||||
|
model: Option<&str>,
|
||||||
|
groups: Option<&[Group<'_>]>,
|
||||||
|
options: Option<&[&str]>,
|
||||||
|
) -> Keymap {
|
||||||
|
let res = self.send_with_response(&ClientMessage::KeymapFromNames {
|
||||||
|
rules,
|
||||||
|
model,
|
||||||
|
groups: groups.map(|v| v.to_vec()),
|
||||||
|
options: options.map(|v| v.to_vec()),
|
||||||
|
});
|
||||||
|
get_response!(res, Keymap(0), KeymapFromNames { keymap });
|
||||||
|
keymap
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_ei_socket_enabled(&self, enabled: bool) {
|
pub fn set_ei_socket_enabled(&self, enabled: bool) {
|
||||||
self.send(&ClientMessage::SetEiSocketEnabled { enabled })
|
self.send(&ClientMessage::SetEiSocketEnabled { enabled })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use {
|
||||||
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
|
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
|
||||||
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
||||||
},
|
},
|
||||||
keyboard::{Keymap, mods::Modifiers, syms::KeySym},
|
keyboard::{Group, Keymap, mods::Modifiers, syms::KeySym},
|
||||||
logging::LogLevel,
|
logging::LogLevel,
|
||||||
theme::{BarPosition, Color, colors::Colorable, sized::Resizable},
|
theme::{BarPosition, Color, colors::Colorable, sized::Resizable},
|
||||||
timer::Timer,
|
timer::Timer,
|
||||||
|
|
@ -820,6 +820,12 @@ pub enum ClientMessage<'a> {
|
||||||
connector: Connector,
|
connector: Connector,
|
||||||
use_native_gamut: bool,
|
use_native_gamut: bool,
|
||||||
},
|
},
|
||||||
|
KeymapFromNames {
|
||||||
|
rules: Option<&'a str>,
|
||||||
|
model: Option<&'a str>,
|
||||||
|
groups: Option<Vec<Group<'a>>>,
|
||||||
|
options: Option<Vec<&'a str>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
@ -1067,6 +1073,9 @@ pub enum Response {
|
||||||
GetBarPosition {
|
GetBarPosition {
|
||||||
position: BarPosition,
|
position: BarPosition,
|
||||||
},
|
},
|
||||||
|
KeymapFromNames {
|
||||||
|
keymap: Keymap,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,15 @@ impl Keymap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An RMLVO group consisting of a layout and a variant.
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct Group<'a> {
|
||||||
|
/// The layout of the group.
|
||||||
|
pub layout: &'a str,
|
||||||
|
/// The variant of the group. Can be an empty string.
|
||||||
|
pub variant: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a keymap.
|
/// Parses a keymap.
|
||||||
///
|
///
|
||||||
/// The returned keymap can later be used to set the keymap of a seat. If the keymap cannot
|
/// The returned keymap can later be used to set the keymap of a seat. If the keymap cannot
|
||||||
|
|
@ -109,3 +118,39 @@ impl Keymap {
|
||||||
pub fn parse_keymap(keymap: &str) -> Keymap {
|
pub fn parse_keymap(keymap: &str) -> Keymap {
|
||||||
get!(Keymap::INVALID).parse_keymap(keymap)
|
get!(Keymap::INVALID).parse_keymap(keymap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a keymap from RMLVO names.
|
||||||
|
///
|
||||||
|
/// If a parameter is not given, a value from the environment or a default is used:
|
||||||
|
///
|
||||||
|
/// | name | default |
|
||||||
|
/// | ---------------------- | ---------------------- |
|
||||||
|
/// | `XKB_DEFAULT_RULES` | `evdev` |
|
||||||
|
/// | `XKB_DEFAULT_MODEL` | `pc105` |
|
||||||
|
/// | `XKB_DEFAULT_LAYOUT` | `us` |
|
||||||
|
/// | `XKB_DEFAULT_VARIANTS` | |
|
||||||
|
/// | `XKB_DEFAULT_OPTIONS` | |
|
||||||
|
///
|
||||||
|
/// `XKB_DEFAULT_LAYOUT` and `XKB_DEFAULT_VARIANTS` are parsed into the `groups` parameter like this example:
|
||||||
|
/// ```
|
||||||
|
/// XKB_DEFAULT_LAYOUT = "us,il,ru,de,jp"
|
||||||
|
/// XKB_DEFAULT_VARIANTS = ",,phonetic,neo"
|
||||||
|
/// ```
|
||||||
|
/// produces:
|
||||||
|
/// ```
|
||||||
|
/// [
|
||||||
|
/// Group { layout: "us", variant: "" },
|
||||||
|
/// Group { layout: "il", variant: "" },
|
||||||
|
/// Group { layout: "ru", variant: "phonetic" },
|
||||||
|
/// Group { layout: "de", variant: "neo" },
|
||||||
|
/// Group { layout: "jp", variant: "" },
|
||||||
|
/// ]
|
||||||
|
/// ```
|
||||||
|
pub fn keymap_from_names(
|
||||||
|
rules: Option<&str>,
|
||||||
|
model: Option<&str>,
|
||||||
|
groups: Option<&[Group<'_>]>,
|
||||||
|
options: Option<&[&str]>,
|
||||||
|
) -> Keymap {
|
||||||
|
get!(Keymap::INVALID).keymap_from_names(rules, model, groups, options)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ use {
|
||||||
CLICK_METHOD_BUTTON_AREAS, CLICK_METHOD_CLICKFINGER, CLICK_METHOD_NONE, ClickMethod,
|
CLICK_METHOD_BUTTON_AREAS, CLICK_METHOD_CLICKFINGER, CLICK_METHOD_NONE, ClickMethod,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
keyboard::{Keymap, mods::Modifiers, syms::KeySym},
|
keyboard::{Group, Keymap, mods::Modifiers, syms::KeySym},
|
||||||
logging::LogLevel,
|
logging::LogLevel,
|
||||||
theme::{BarPosition, colors::Colorable, sized::Resizable},
|
theme::{BarPosition, colors::Colorable, sized::Resizable},
|
||||||
timer::Timer as JayTimer,
|
timer::Timer as JayTimer,
|
||||||
|
|
@ -316,6 +316,39 @@ impl ConfigProxyHandler {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_keymap_from_names(
|
||||||
|
&self,
|
||||||
|
rules: Option<&str>,
|
||||||
|
model: Option<&str>,
|
||||||
|
groups: Option<Vec<Group<'_>>>,
|
||||||
|
options: Option<Vec<&str>>,
|
||||||
|
) -> Result<(), CphError> {
|
||||||
|
let kbvm_groups = groups.map(|groups| {
|
||||||
|
groups
|
||||||
|
.iter()
|
||||||
|
.map(|g| kbvm::xkb::rmlvo::Group {
|
||||||
|
layout: g.layout,
|
||||||
|
variant: g.variant,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
let (keymap, res) = match self.state.kb_ctx.keymap_from_names(
|
||||||
|
rules,
|
||||||
|
model,
|
||||||
|
kbvm_groups.as_deref(),
|
||||||
|
options.as_deref(),
|
||||||
|
) {
|
||||||
|
Ok(keymap) => {
|
||||||
|
let id = Keymap(self.id());
|
||||||
|
self.keymaps.set(id, keymap);
|
||||||
|
(id, Ok(()))
|
||||||
|
}
|
||||||
|
Err(e) => (Keymap::INVALID, Err(CphError::ParseKeymapError(e))),
|
||||||
|
};
|
||||||
|
self.respond(Response::KeymapFromNames { keymap });
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_get_connectors(
|
fn handle_get_connectors(
|
||||||
&self,
|
&self,
|
||||||
dev: Option<DrmDevice>,
|
dev: Option<DrmDevice>,
|
||||||
|
|
@ -3332,6 +3365,14 @@ impl ConfigProxyHandler {
|
||||||
} => self
|
} => self
|
||||||
.handle_connector_set_use_native_gamut(connector, use_native_gamut)
|
.handle_connector_set_use_native_gamut(connector, use_native_gamut)
|
||||||
.wrn("connector_set_use_native_gamut")?,
|
.wrn("connector_set_use_native_gamut")?,
|
||||||
|
ClientMessage::KeymapFromNames {
|
||||||
|
rules,
|
||||||
|
model,
|
||||||
|
groups,
|
||||||
|
options,
|
||||||
|
} => self
|
||||||
|
.handle_keymap_from_names(rules, model, groups, options)
|
||||||
|
.wrn("keymap_from_names")?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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! {
|
||||||
|
|
|
||||||
21
src/kbvm.rs
21
src/kbvm.rs
|
|
@ -92,6 +92,25 @@ impl KbvmContext {
|
||||||
.ctx
|
.ctx
|
||||||
.keymap_from_bytes(WriteToLog, None, keymap)
|
.keymap_from_bytes(WriteToLog, None, keymap)
|
||||||
.map_err(KbvmError::CouldNotParseKeymap)?;
|
.map_err(KbvmError::CouldNotParseKeymap)?;
|
||||||
|
let id = KbvmMapId(*blake3::hash(keymap).as_bytes());
|
||||||
|
self.create_keymap(id, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn keymap_from_names(
|
||||||
|
&self,
|
||||||
|
rules: Option<&str>,
|
||||||
|
model: Option<&str>,
|
||||||
|
groups: Option<&[xkb::rmlvo::Group<'_>]>,
|
||||||
|
options: Option<&[&str]>,
|
||||||
|
) -> Result<Rc<KbvmMap>, KbvmError> {
|
||||||
|
let map = self
|
||||||
|
.ctx
|
||||||
|
.keymap_from_names(WriteToLog, rules, model, groups, options);
|
||||||
|
let id = KbvmMapId(*blake3::hash(map.format().to_string().as_bytes()).as_bytes());
|
||||||
|
self.create_keymap(id, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_keymap(&self, id: KbvmMapId, map: Keymap) -> Result<Rc<KbvmMap>, KbvmError> {
|
||||||
let mut has_indicators = false;
|
let mut has_indicators = false;
|
||||||
let mut num_lock = None;
|
let mut num_lock = None;
|
||||||
let mut caps_lock = None;
|
let mut caps_lock = None;
|
||||||
|
|
@ -111,7 +130,7 @@ impl KbvmContext {
|
||||||
}
|
}
|
||||||
let builder = map.to_builder();
|
let builder = map.to_builder();
|
||||||
Ok(Rc::new(KbvmMap {
|
Ok(Rc::new(KbvmMap {
|
||||||
id: KbvmMapId(*blake3::hash(keymap).as_bytes()),
|
id,
|
||||||
state_machine: builder.build_state_machine(),
|
state_machine: builder.build_state_machine(),
|
||||||
map: create_keymap_memfd(&map, false).map_err(KbvmError::KeymapMemfd)?,
|
map: create_keymap_memfd(&map, false).map_err(KbvmError::KeymapMemfd)?,
|
||||||
xwayland_map: create_keymap_memfd(&map, true).map_err(KbvmError::KeymapMemfd)?,
|
xwayland_map: create_keymap_memfd(&map, true).map_err(KbvmError::KeymapMemfd)?,
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue