169 lines
5.8 KiB
Rust
169 lines
5.8 KiB
Rust
use smithay_client_toolkit::{
|
|
error::GlobalError,
|
|
globals::{GlobalData, ProvidesBoundGlobal},
|
|
reexports::{
|
|
client::{
|
|
globals::{BindError, GlobalList},
|
|
Connection, Dispatch, QueueHandle,
|
|
},
|
|
protocols::wp::{
|
|
input_method::zv1::client::{
|
|
zwp_input_method_context_v1::{self, ZwpInputMethodContextV1},
|
|
zwp_input_method_v1::{self, ZwpInputMethodV1},
|
|
},
|
|
text_input::zv1::client::zwp_text_input_v1::{ContentHint, ContentPurpose},
|
|
},
|
|
},
|
|
};
|
|
|
|
pub trait ImeContextV1Handler {
|
|
fn reset(&mut self);
|
|
fn preferred_language(&mut self, lang: &str);
|
|
fn content_type(&mut self, hint: ContentHint, purpose: ContentPurpose);
|
|
fn commit_state(&mut self, serial: u32);
|
|
/// button: e.g. BTN_LEFT / BTN_RIGHT
|
|
/// index = position in preedit
|
|
fn invoke_action(&mut self, button: u32, index: u32);
|
|
fn set_surrounding_text(&mut self, text: &str, cursor: u32, anchor: u32);
|
|
}
|
|
|
|
pub trait ImeV1Handler {
|
|
fn activate(&mut self, ctx: ImeContextV1);
|
|
fn deactivate(&mut self, ctx: ImeContextV1);
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ImeV1 {
|
|
wl_ime: ZwpInputMethodV1,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ImeContextV1 {
|
|
wl_ime_ctx: ZwpInputMethodContextV1,
|
|
}
|
|
|
|
impl From<ZwpInputMethodContextV1> for ImeContextV1 {
|
|
fn from(wl_ime: ZwpInputMethodContextV1) -> Self {
|
|
Self { wl_ime_ctx: wl_ime }
|
|
}
|
|
}
|
|
|
|
impl ImeV1 {
|
|
pub fn bind<State>(globals: &GlobalList, qh: &QueueHandle<State>) -> Result<Self, BindError>
|
|
where
|
|
State: Dispatch<ZwpInputMethodV1, GlobalData, State> + ImeContextV1Handler + 'static,
|
|
{
|
|
let wl_ime = globals.bind(qh, 1..=1, GlobalData)?;
|
|
// Compositors must advertise Argb8888 and Xrgb8888, so let's reserve space for those formats.
|
|
Ok(Self { wl_ime })
|
|
}
|
|
|
|
#[allow(unused)]
|
|
pub fn wl_ime(&self) -> &ZwpInputMethodV1 {
|
|
&self.wl_ime
|
|
}
|
|
}
|
|
|
|
impl ImeContextV1 {
|
|
#[allow(unused)]
|
|
pub fn wl_ime_ctx(&self) -> &ZwpInputMethodContextV1 {
|
|
&self.wl_ime_ctx
|
|
}
|
|
}
|
|
|
|
impl ProvidesBoundGlobal<ZwpInputMethodV1, 1> for ImeV1 {
|
|
fn bound_global(&self) -> Result<ZwpInputMethodV1, GlobalError> {
|
|
Ok(self.wl_ime.clone())
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! delegate_ime_v1 {
|
|
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
|
smithay_client_toolkit::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty:
|
|
[
|
|
smithay_client_toolkit::reexports::protocols::wp::input_method::zv1::client::zwp_input_method_v1::ZwpInputMethodV1: smithay_client_toolkit::globals::GlobalData
|
|
] => $crate::wayland::ime_v1::ImeV1
|
|
);
|
|
};
|
|
}
|
|
#[macro_export]
|
|
macro_rules! delegate_ime_context_v1 {
|
|
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
|
smithay_client_toolkit::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty:
|
|
[
|
|
smithay_client_toolkit::reexports::protocols::wp::input_method::zv1::client::zwp_input_method_context_v1::ZwpInputMethodContextV1: smithay_client_toolkit::globals::GlobalData// $crate::wayland::ime_v1::ImeContextV1Data
|
|
] => $crate::wayland::ime_v1::ImeContextV1
|
|
);
|
|
};
|
|
}
|
|
|
|
impl<D> Dispatch<ZwpInputMethodContextV1, GlobalData, D> for ImeContextV1
|
|
where
|
|
D: Dispatch<ZwpInputMethodContextV1, GlobalData> + ImeContextV1Handler,
|
|
{
|
|
fn event(
|
|
state: &mut D,
|
|
_proxy: &ZwpInputMethodContextV1,
|
|
event: zwp_input_method_context_v1::Event,
|
|
_: &GlobalData,
|
|
_: &Connection,
|
|
_: &QueueHandle<D>,
|
|
) {
|
|
log::debug!(target: "zwp_input_method_context_v1", "received {event:?}");
|
|
match event {
|
|
zwp_input_method_context_v1::Event::Reset => {
|
|
state.reset();
|
|
}
|
|
zwp_input_method_context_v1::Event::ContentType { hint, purpose } => {
|
|
let Some(hint) = ContentHint::from_bits(hint) else {
|
|
log::debug!(target: "zwp_input_method_context_v1", "unknown hint: {hint:?}");
|
|
return;
|
|
};
|
|
let Ok(purpose) = ContentPurpose::try_from(purpose) else {
|
|
log::debug!(target: "zwp_input_method_context_v1", "unknown purpose: {purpose:?}");
|
|
return;
|
|
};
|
|
state.content_type(hint, purpose);
|
|
}
|
|
zwp_input_method_context_v1::Event::CommitState { serial } => {
|
|
state.commit_state(serial);
|
|
}
|
|
zwp_input_method_context_v1::Event::InvokeAction { button, index } => {
|
|
state.invoke_action(button, index);
|
|
}
|
|
zwp_input_method_context_v1::Event::SurroundingText {
|
|
text,
|
|
cursor,
|
|
anchor,
|
|
} => {
|
|
state.set_surrounding_text(&text, cursor, anchor);
|
|
}
|
|
zwp_input_method_context_v1::Event::PreferredLanguage { language } => {
|
|
state.preferred_language(&language);
|
|
}
|
|
_ => log::debug!(target: "zwp_input_method_context_v1", "unknown event"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<D> Dispatch<ZwpInputMethodV1, GlobalData, D> for ImeV1
|
|
where
|
|
D: Dispatch<ZwpInputMethodV1, GlobalData> + ImeV1Handler,
|
|
{
|
|
fn event(
|
|
state: &mut D,
|
|
_proxy: &ZwpInputMethodV1,
|
|
event: zwp_input_method_v1::Event,
|
|
_data: &GlobalData,
|
|
_conn: &Connection,
|
|
_qh: &QueueHandle<D>,
|
|
) {
|
|
match event {
|
|
zwp_input_method_v1::Event::Activate { id } => state.activate(id.into()),
|
|
zwp_input_method_v1::Event::Deactivate { context } => state.deactivate(context.into()),
|
|
_ => log::debug!(target: "zwp_input_method_v1", "unknown event"),
|
|
}
|
|
}
|
|
}
|