Skip to content

Commit 31166ce

Browse files
author
dcz
committed
im: Add keyboard bind/unbind/consume requests
1 parent 872efa4 commit 31166ce

File tree

1 file changed

+100
-4
lines changed

1 file changed

+100
-4
lines changed

src/seat/input_method_v3.rs

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use std::ops::Deref;
1313
use std::sync::{Arc, Mutex, MutexGuard, Weak};
1414

1515
use wayland_client::globals::{BindError, GlobalList};
16+
use wayland_client::protocol::wl_keyboard::WlKeyboard;
1617
use wayland_client::protocol::wl_seat::WlSeat;
17-
use wayland_client::protocol::wl_surface;
18+
use wayland_client::protocol::wl_surface::WlSurface;
1819
use wayland_client::WEnum;
1920
use wayland_client::{Connection, Dispatch, Proxy, QueueHandle};
2021
use wayland_protocols::wp::text_input::zv3::client::zwp_text_input_v3::{
@@ -24,12 +25,15 @@ use wayland_protocols::wp::text_input::zv3::client::zwp_text_input_v3::{
2425
use wl_input_method::input_method::v1::client as protocol;
2526

2627
pub use protocol::xx_input_method_v1::XxInputMethodV1;
28+
pub use protocol::xx_input_method_keyboard_v1::XxInputMethodKeyboardV1;
2729
pub use protocol::xx_input_popup_positioner_v1::XxInputPopupPositionerV1;
2830
pub use protocol::xx_input_popup_surface_v2::XxInputPopupSurfaceV2;
2931

3032
use protocol::{
33+
xx_input_method_v1,
34+
xx_input_method_keyboard_v1,
3135
xx_input_method_manager_v2::{self, XxInputMethodManagerV2},
32-
xx_input_method_v1, xx_input_popup_positioner_v1, xx_input_popup_surface_v2,
36+
xx_input_popup_positioner_v1, xx_input_popup_surface_v2,
3337
};
3438

3539
pub use xx_input_popup_positioner_v1::{Anchor, Gravity};
@@ -59,7 +63,7 @@ impl InputMethodManager {
5963
where
6064
D: Dispatch<XxInputMethodManagerV2, GlobalData> + 'static,
6165
{
62-
let manager = globals.bind(qh, 2..=2, GlobalData)?;
66+
let manager = globals.bind(qh, 3..=3, GlobalData)?;
6367
Ok(Self { manager })
6468
}
6569

@@ -238,6 +242,25 @@ impl InputMethod {
238242
surface,
239243
}
240244
}
245+
246+
/// May cause a protocol error if there's a bound keyboard already.
247+
pub fn keyboard_bind<D>(
248+
&self,
249+
qh: &QueueHandle<D>,
250+
keyboard: &WlKeyboard,
251+
surface: &WlSurface,
252+
) -> Keyboard
253+
where
254+
D: Dispatch<XxInputMethodKeyboardV1, KeyboardData> + 'static,
255+
{
256+
let data = self.input_method.data::<InputMethodData>().unwrap();
257+
Keyboard(self.input_method.keyboard_bind(
258+
keyboard,
259+
surface,
260+
qh,
261+
KeyboardData { im: Arc::downgrade(&data.inner) },
262+
))
263+
}
241264
}
242265

243266
#[derive(Debug)]
@@ -281,6 +304,9 @@ pub struct InputMethodEventState {
281304
pub content_hint: ContentHint,
282305
pub text_change_cause: ChangeCause,
283306
pub active: Active,
307+
/// A hash map of keyboards which reported a version.
308+
/// A missing entry is equal to version 0, meaning inactive.
309+
pub keyboards: HashMap<XxInputMethodKeyboardV1, KeyboardVersion>,
284310
pub popups: HashMap<XxInputPopupSurfaceV2, PopupState>,
285311
}
286312

@@ -292,6 +318,7 @@ impl Default for InputMethodEventState {
292318
content_purpose: ContentPurpose::Normal,
293319
text_change_cause: ChangeCause::InputMethod,
294320
active: Active::default(),
321+
keyboards: Default::default(),
295322
popups: Default::default(),
296323
}
297324
}
@@ -406,7 +433,7 @@ pub struct Popup {
406433
}
407434

408435
impl Popup {
409-
pub fn wl_surface(&self) -> &wl_surface::WlSurface {
436+
pub fn wl_surface(&self) -> &WlSurface {
410437
self.surface.wl_surface()
411438
}
412439

@@ -536,6 +563,62 @@ impl PopupDataInner {
536563
}
537564
}
538565

566+
#[derive(Debug)]
567+
pub struct Keyboard(XxInputMethodKeyboardV1);
568+
569+
impl Keyboard {
570+
/// May cause a protocol error if there's no bound keyboard.
571+
pub fn unbind(&self) {
572+
self.0.unbind();
573+
}
574+
575+
/// May cause a protocol error on invalid serial.
576+
pub fn filter(
577+
&self,
578+
serial: u32,
579+
action: xx_input_method_keyboard_v1::FilterAction,
580+
) {
581+
self.0.filter(serial, action);
582+
}
583+
}
584+
585+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
586+
pub struct KeyboardVersion(pub u32);
587+
588+
impl<D> Dispatch<XxInputMethodKeyboardV1, KeyboardData, D> for Keyboard
589+
where
590+
D: Dispatch<XxInputMethodKeyboardV1, KeyboardData> + InputMethodHandler,
591+
{
592+
fn event(
593+
_data: &mut D,
594+
keyboard: &XxInputMethodKeyboardV1,
595+
event: xx_input_method_keyboard_v1::Event,
596+
data: &KeyboardData,
597+
_conn: &Connection,
598+
_qh: &QueueHandle<D>,
599+
) {
600+
if let Some(im) = data.im.upgrade() {
601+
use xx_input_method_keyboard_v1::Event;
602+
match event {
603+
Event::NotifyVersion { version } => {
604+
let mut im = im.lock().unwrap();
605+
im.pending_state.keyboards
606+
.entry(keyboard.clone())
607+
.or_insert(KeyboardVersion(version));
608+
},
609+
_ => unreachable!(),
610+
}
611+
} else {
612+
warn!("received event for a keyboard whose input method already disappeared");
613+
};
614+
}
615+
}
616+
617+
#[derive(Debug)]
618+
pub struct KeyboardData {
619+
im: Weak<Mutex<InputMethodDataInner>>,
620+
}
621+
539622
#[macro_export]
540623
macro_rules! delegate_input_method_v3 {
541624
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
@@ -551,6 +634,9 @@ macro_rules! delegate_input_method_v3 {
551634
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
552635
$crate::reexports::protocols_experimental::input_method::v1::client::xx_input_popup_positioner_v1::XxInputPopupPositionerV1: $crate::seat::input_method_v3::PositionerData
553636
] => $crate::seat::input_method_v3::PopupPositioner);
637+
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
638+
$crate::reexports::protocols_experimental::input_method::v1::client::xx_input_method_keyboard_v1::XxInputMethodKeyboardV1: $crate::seat::input_method_v3::KeyboardData
639+
] => $crate::seat::input_method_v3::Keyboard);
554640
};
555641
}
556642

@@ -734,12 +820,22 @@ mod test {
734820
>,
735821
{
736822
}
823+
824+
fn assert_is_keyboard_delegate<T>()
825+
where
826+
T: wayland_client::Dispatch<
827+
protocol::xx_input_method_keyboard_v1::XxInputMethodKeyboardV1,
828+
KeyboardData,
829+
>,
830+
{
831+
}
737832

738833
#[test]
739834
fn test_valid_assignment() {
740835
assert_is_manager_delegate::<Handler>();
741836
assert_is_delegate::<Handler>();
742837
assert_is_popup_delegate::<Handler>();
743838
assert_is_positioner_delegate::<Handler>();
839+
assert_is_keyboard_delegate::<Handler>();
744840
}
745841
}

0 commit comments

Comments
 (0)