1
0
Fork 0
forked from wry/wry

seat: implement input methods

This commit is contained in:
Julian Orth 2024-04-14 20:22:57 +02:00
parent 5e2cdef388
commit daf52299db
44 changed files with 2165 additions and 75 deletions

View file

@ -0,0 +1,119 @@
use {
crate::{
it::{
test_error::{TestError, TestResult},
test_ifs::{
test_input_method_keyboard_grab::TestInputMethodKeyboardGrab,
test_input_popup_surface::TestInputPopupSurface, test_surface::TestSurface,
},
test_object::TestObject,
test_transport::TestTransport,
test_utils::test_expected_event::TEEH,
testrun::ParseFull,
},
utils::{buffd::MsgParser, numcell::NumCell},
wire::{zwp_input_method_v2::*, ZwpInputMethodV2Id},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestInputMethod {
pub id: ZwpInputMethodV2Id,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
pub activate: TEEH<bool>,
pub done: TEEH<()>,
pub done_received: NumCell<u32>,
}
impl TestInputMethod {
pub fn commit_string(&self, s: &str) -> TestResult {
self.tran.send(CommitString {
self_id: self.id,
text: s,
})
}
pub fn commit(&self) -> TestResult {
self.tran.send(Commit {
self_id: self.id,
serial: self.done_received.get(),
})
}
#[allow(dead_code)]
pub fn grab(&self) -> TestResult<Rc<TestInputMethodKeyboardGrab>> {
let obj = Rc::new(TestInputMethodKeyboardGrab {
id: self.tran.id(),
tran: self.tran.clone(),
destroyed: Cell::new(false),
keymap: Rc::new(Default::default()),
key: Rc::new(Default::default()),
modifiers: Rc::new(Default::default()),
repeat_info: Rc::new(Default::default()),
});
self.tran.add_obj(obj.clone())?;
self.tran.send(GrabKeyboard {
self_id: self.id,
keyboard: obj.id,
})?;
Ok(obj)
}
pub fn get_popup(&self, surface: &TestSurface) -> TestResult<Rc<TestInputPopupSurface>> {
let obj = Rc::new(TestInputPopupSurface {
id: self.tran.id(),
tran: self.tran.clone(),
destroyed: Cell::new(false),
});
self.tran.add_obj(obj.clone())?;
self.tran.send(GetInputPopupSurface {
self_id: self.id,
id: obj.id,
surface: surface.id,
})?;
Ok(obj)
}
pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id })?;
}
Ok(())
}
fn handle_activate(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Activate::parse_full(parser)?;
self.activate.push(true);
Ok(())
}
fn handle_deactivate(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Deactivate::parse_full(parser)?;
self.activate.push(false);
Ok(())
}
fn handle_done(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Done::parse_full(parser)?;
self.done.push(());
self.done_received.fetch_add(1);
Ok(())
}
}
impl Drop for TestInputMethod {
fn drop(&mut self) {
let _ = self.destroy();
}
}
test_object! {
TestInputMethod, ZwpInputMethodV2;
ACTIVATE => handle_activate,
DEACTIVATE => handle_deactivate,
DONE => handle_done,
}
impl TestObject for TestInputMethod {}

View file

@ -0,0 +1,71 @@
use {
crate::{
it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
test_utils::test_expected_event::TEEH, testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{zwp_input_method_keyboard_grab_v2::*, ZwpInputMethodKeyboardGrabV2Id},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestInputMethodKeyboardGrab {
pub id: ZwpInputMethodKeyboardGrabV2Id,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
pub keymap: TEEH<Keymap>,
pub key: TEEH<Key>,
pub modifiers: TEEH<Modifiers>,
pub repeat_info: TEEH<RepeatInfo>,
}
impl TestInputMethodKeyboardGrab {
pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) {
self.tran.send(Release { self_id: self.id })?;
}
Ok(())
}
fn handle_keymap(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Keymap::parse_full(parser)?;
self.keymap.push(ev);
Ok(())
}
fn handle_key(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Key::parse_full(parser)?;
self.key.push(ev);
Ok(())
}
fn handle_modifiers(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Modifiers::parse_full(parser)?;
self.modifiers.push(ev);
Ok(())
}
fn handle_repeat_info(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = RepeatInfo::parse_full(parser)?;
self.repeat_info.push(ev);
Ok(())
}
}
impl Drop for TestInputMethodKeyboardGrab {
fn drop(&mut self) {
let _ = self.destroy();
}
}
test_object! {
TestInputMethodKeyboardGrab, ZwpInputMethodKeyboardGrabV2;
KEYMAP => handle_keymap,
KEY => handle_key,
MODIFIERS => handle_modifiers,
REPEAT_INFO => handle_repeat_info,
}
impl TestObject for TestInputMethodKeyboardGrab {}

View file

@ -0,0 +1,50 @@
use {
crate::{
it::{
test_error::TestResult,
test_ifs::{test_input_method::TestInputMethod, test_seat::TestSeat},
test_object::TestObject,
test_transport::TestTransport,
},
wire::{zwp_input_method_manager_v2::GetInputMethod, ZwpInputMethodManagerV2Id},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestInputMethodManager {
pub id: ZwpInputMethodManagerV2Id,
pub tran: Rc<TestTransport>,
}
impl TestInputMethodManager {
pub fn new(tran: &Rc<TestTransport>) -> Self {
Self {
id: tran.id(),
tran: tran.clone(),
}
}
pub fn get_input_method(&self, seat: &TestSeat) -> TestResult<Rc<TestInputMethod>> {
let obj = Rc::new(TestInputMethod {
id: self.tran.id(),
tran: self.tran.clone(),
destroyed: Cell::new(false),
activate: Rc::new(Default::default()),
done: Rc::new(Default::default()),
done_received: Default::default(),
});
self.tran.add_obj(obj.clone())?;
self.tran.send(GetInputMethod {
self_id: self.id,
seat: seat.id,
input_method: obj.id,
})?;
Ok(obj)
}
}
test_object! {
TestInputMethodManager, ZwpInputMethodManagerV2;
}
impl TestObject for TestInputMethodManager {}

View file

@ -0,0 +1,34 @@
use {
crate::{
it::{test_error::TestError, test_object::TestObject, test_transport::TestTransport},
wire::{zwp_input_popup_surface_v2::*, ZwpInputPopupSurfaceV2Id},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestInputPopupSurface {
pub id: ZwpInputPopupSurfaceV2Id,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
}
impl TestInputPopupSurface {
pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id })?;
}
Ok(())
}
}
impl Drop for TestInputPopupSurface {
fn drop(&mut self) {
let _ = self.destroy();
}
}
test_object! {
TestInputPopupSurface, ZwpInputPopupSurfaceV2;
}
impl TestObject for TestInputPopupSurface {}

View file

@ -11,9 +11,11 @@ use {
test_data_control_manager::TestDataControlManager,
test_data_device_manager::TestDataDeviceManager, test_dmabuf::TestDmabuf,
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
test_input_method_manager::TestInputMethodManager,
test_jay_compositor::TestJayCompositor, test_shm::TestShm,
test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
test_subcompositor::TestSubcompositor, test_syncobj_manager::TestSyncobjManager,
test_text_input_manager::TestTextInputManager,
test_toplevel_drag_manager::TestToplevelDragManager,
test_viewporter::TestViewporter,
test_virtual_keyboard_manager::TestVirtualKeyboardManager,
@ -54,6 +56,8 @@ pub struct TestRegistrySingletons {
pub xdg_toplevel_drag_manager_v1: u32,
pub wp_alpha_modifier_v1: u32,
pub zwp_virtual_keyboard_manager_v1: u32,
pub zwp_input_method_manager_v2: u32,
pub zwp_text_input_manager_v3: u32,
}
pub struct TestRegistry {
@ -79,6 +83,8 @@ pub struct TestRegistry {
pub drag_manager: CloneCell<Option<Rc<TestToplevelDragManager>>>,
pub alpha_modifier: CloneCell<Option<Rc<TestAlphaModifier>>>,
pub virtual_keyboard_manager: CloneCell<Option<Rc<TestVirtualKeyboardManager>>>,
pub input_method_manager: CloneCell<Option<Rc<TestInputMethodManager>>>,
pub text_input_manager: CloneCell<Option<Rc<TestTextInputManager>>>,
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
}
@ -148,6 +154,8 @@ impl TestRegistry {
xdg_toplevel_drag_manager_v1,
wp_alpha_modifier_v1,
zwp_virtual_keyboard_manager_v1,
zwp_input_method_manager_v2,
zwp_text_input_manager_v3,
};
self.singletons.set(Some(singletons.clone()));
Ok(singletons)
@ -249,6 +257,20 @@ impl TestRegistry {
1,
TestVirtualKeyboardManager
);
create_singleton!(
get_input_method_manager,
input_method_manager,
zwp_input_method_manager_v2,
1,
TestInputMethodManager
);
create_singleton!(
get_text_input_manager,
text_input_manager,
zwp_text_input_manager_v3,
1,
TestTextInputManager
);
pub fn bind<O: TestObject>(
&self,

View file

@ -0,0 +1,97 @@
use {
crate::{
it::{
test_error::{TestError, TestResult},
test_object::TestObject,
test_transport::TestTransport,
test_utils::test_expected_event::TEEH,
testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{zwp_text_input_v3::*, ZwpTextInputV3Id},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestTextInput {
pub id: ZwpTextInputV3Id,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
pub enter: TEEH<Enter>,
pub leave: TEEH<Leave>,
pub commit_string: TEEH<String>,
pub done: TEEH<Done>,
}
impl TestTextInput {
pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id })?;
}
Ok(())
}
pub fn enable(&self) -> TestResult {
self.tran.send(Enable { self_id: self.id })
}
pub fn disable(&self) -> TestResult {
self.tran.send(Disable { self_id: self.id })
}
pub fn set_cursor_rectangle(&self, x: i32, y: i32, width: i32, height: i32) -> TestResult {
self.tran.send(SetCursorRectangle {
self_id: self.id,
x,
y,
width,
height,
})
}
pub fn commit(&self) -> TestResult {
self.tran.send(Commit { self_id: self.id })
}
fn handle_enter(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Enter::parse_full(parser)?;
self.enter.push(ev);
Ok(())
}
fn handle_leave(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Leave::parse_full(parser)?;
self.leave.push(ev);
Ok(())
}
fn handle_commit_string(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = CommitString::parse_full(parser)?;
self.commit_string
.push(ev.text.unwrap_or_default().to_string());
Ok(())
}
fn handle_done(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Done::parse_full(parser)?;
self.done.push(ev);
Ok(())
}
}
impl Drop for TestTextInput {
fn drop(&mut self) {
let _ = self.destroy();
}
}
test_object! {
TestTextInput, ZwpTextInputV3;
ENTER => handle_enter,
LEAVE => handle_leave,
COMMIT_STRING => handle_commit_string,
DONE => handle_done,
}
impl TestObject for TestTextInput {}

View file

@ -0,0 +1,51 @@
use {
crate::{
it::{
test_error::TestResult,
test_ifs::{test_seat::TestSeat, test_text_input::TestTextInput},
test_object::TestObject,
test_transport::TestTransport,
},
wire::{zwp_text_input_manager_v3::*, ZwpTextInputManagerV3Id},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestTextInputManager {
pub id: ZwpTextInputManagerV3Id,
pub tran: Rc<TestTransport>,
}
impl TestTextInputManager {
pub fn new(tran: &Rc<TestTransport>) -> Self {
Self {
id: tran.id(),
tran: tran.clone(),
}
}
pub fn get_text_input(&self, seat: &TestSeat) -> TestResult<Rc<TestTextInput>> {
let obj = Rc::new(TestTextInput {
id: self.tran.id(),
tran: self.tran.clone(),
destroyed: Cell::new(false),
enter: Rc::new(Default::default()),
leave: Rc::new(Default::default()),
commit_string: Rc::new(Default::default()),
done: Rc::new(Default::default()),
});
self.tran.add_obj(obj.clone())?;
self.tran.send(GetTextInput {
self_id: self.id,
id: obj.id,
seat: seat.id,
})?;
Ok(obj)
}
}
test_object! {
TestTextInputManager, ZwpTextInputManagerV3;
}
impl TestObject for TestTextInputManager {}