diff --git a/src/wayland/dispatcher.rs b/src/wayland/dispatcher.rs index cebe8c2..9f836e8 100644 --- a/src/wayland/dispatcher.rs +++ b/src/wayland/dispatcher.rs @@ -15,6 +15,8 @@ use crate::wayland::wlr_layer_shell_unstable_v1::zwlr_layer_shell_v1; use crate::wayland::wlr_layer_shell_unstable_v1::zwlr_layer_surface_v1; use crate::wayland::fractional_scale_v1::wp_fractional_scale_manager_v1; use crate::wayland::fractional_scale_v1::wp_fractional_scale_v1; +use crate::wayland::input_method_unstable_v1::zwp_input_method_context_v1; +use crate::wayland::input_method_unstable_v1::zwp_input_method_v1; use crate::wayland::input_method_unstable_v2::zwp_input_method_manager_v2; use crate::wayland::input_method_unstable_v2::zwp_input_method_v2; use crate::wayland::viewporter::wp_viewporter; @@ -29,6 +31,7 @@ use wayland_client::Dispatch; use wayland_client::Proxy; use wayland_client::QueueHandle; use wayland_client::WEnum; +use wayland_client::globals::BindError; use wayland_client::globals::GlobalList; use wayland_client::globals::GlobalListContents; use wayland_client::protocol::wl_buffer; @@ -69,6 +72,9 @@ impl Dispatcher { Err(_) => None, }; + let _: Result + = globals.bind(&queue, 1..=1, ()); + let frac_scale_man = match globals.bind(&queue, 1..=1, ()) { Ok(g) => Some(g), Err(_) => None, @@ -422,6 +428,27 @@ impl Dispatch for Dispatcher { } } +impl Dispatch for Dispatcher { + fn event(ctx: &mut Dispatcher, + _imc: &zwp_input_method_context_v1::ZwpInputMethodContextV1, + evt: zwp_input_method_context_v1::Event, + _data: &(), + _conn: &Connection, + _qh: &QueueHandle) + { + match evt { + zwp_input_method_context_v1::Event::SurroundingText { .. } => (), + zwp_input_method_context_v1::Event::Reset => (), + zwp_input_method_context_v1::Event::ContentType { .. } => (), + zwp_input_method_context_v1::Event::CommitState { serial } => { + ctx.seat.keyboard_mut().set_serial(serial); + }, + zwp_input_method_context_v1::Event::PreferredLanguage { .. } => (), + _ => eprintln!("warn: unknown zwp_input_method_context_v1 event emitted"), + } + } +} + impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _im_man: &zwp_input_method_manager_v2::ZwpInputMethodManagerV2, @@ -434,6 +461,35 @@ impl Dispatch for Disp } } +impl Dispatch for Dispatcher { + fn event(ctx: &mut Dispatcher, + _im: &zwp_input_method_v1::ZwpInputMethodV1, + evt: zwp_input_method_v1::Event, + _data: &(), + _conn: &Connection, + _qh: &QueueHandle) + { + match evt { + zwp_input_method_v1::Event::Activate { id } => { + ctx.seat.set_text_supported(true); + ctx.seat.keyboard_mut().set_input_method_context(Some(id)); + ctx.show(); + }, + zwp_input_method_v1::Event::Deactivate { .. } => { + ctx.seat.set_text_supported(false); + ctx.seat.keyboard_mut().set_input_method_context(None); + ctx.hide(); + }, + _ => eprintln!("warn: unknown zwp_input_method_v1 event emitted"), + } + } + + wayland_client::event_created_child!(Dispatcher, zwp_input_method_v1::ZwpInputMethodV1, [ + zwp_input_method_v1::EVT_ACTIVATE_OPCODE + => (zwp_input_method_context_v1::ZwpInputMethodContextV1, ()), + ]); +} + impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _im: &zwp_input_method_v2::ZwpInputMethodV2, diff --git a/src/wayland/keyboard.rs b/src/wayland/keyboard.rs index 37bc6c8..228c4b4 100644 --- a/src/wayland/keyboard.rs +++ b/src/wayland/keyboard.rs @@ -6,6 +6,7 @@ use crate::core::Keyboard; use crate::core::Layout; use crate::core::Part; +use crate::wayland::input_method_unstable_v1::zwp_input_method_context_v1::ZwpInputMethodContextV1; use crate::wayland::input_method_unstable_v2::zwp_input_method_manager_v2::ZwpInputMethodManagerV2; use crate::wayland::input_method_unstable_v2::zwp_input_method_v2::ZwpInputMethodV2; use crate::wayland::virtual_keyboard_unstable_v1::zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1; @@ -29,6 +30,7 @@ pub struct VirtualKeyboard { keymap_id: u8, im: Option, + im_ctx: Option, im_serial: u32, keycodes: HashMap, @@ -46,7 +48,7 @@ impl VirtualKeyboard { -> VirtualKeyboard { let vk = vk_man.as_ref().map(|m| m.create_virtual_keyboard(seat, queue, ())); - let im = im_man.as_ref().map(|m| m.get_input_method(&seat, &queue, ())); + let im = im_man.as_ref().map(|m| m.get_input_method(seat, queue, ())); let path = format!("/tmp/ufkbd-keymap-pid{}-1", process::id()); let keymap = File::create(path).unwrap(); @@ -57,6 +59,7 @@ impl VirtualKeyboard { keymap_id: 1, im, + im_ctx: None, im_serial: 0, keycodes: HashMap::with_capacity(248), @@ -93,25 +96,33 @@ impl VirtualKeyboard { { self.im_serial += 1; } + + pub fn set_serial(&mut self, serial: u32) + { + self.im_serial = serial; + } + + pub fn set_input_method_context(&mut self, imc: Option) + { + self.im_ctx = imc; + } } impl Keyboard for VirtualKeyboard { fn key_supported(&self, sym: Keysym) -> bool { - if self.vk.is_none() { - return false; - } - - match sym.name() { - Some(n) => n.starts_with("XK_"), - None => false, + if self.vk.is_some() { + match sym.name() { + Some(n) => n.starts_with("XK_"), + None => false, + } + } else { + self.im_ctx.is_some() } } fn press(&mut self, sym: Keysym) { - let vk = self.vk.as_ref().unwrap(); - if sym == Keysym::NoSymbol || sym == Keysym::XF86_Fn { return; } @@ -119,28 +130,33 @@ impl Keyboard for VirtualKeyboard { match sym { Keysym::Shift_L => { self.mod_state |= 0x1; - vk.modifiers(self.mod_state, 0, 0, 0); }, Keysym::Control_L => { self.mod_state |= 0x4; - vk.modifiers(self.mod_state, 0, 0, 0); }, Keysym::Alt_L => { self.mod_state |= 0x8; - vk.modifiers(self.mod_state, 0, 0, 0); }, _ => (), } - let keycode = *self.keycodes.get(&sym).unwrap(); - self.pressed[keycode as usize] = sym; - vk.key(0, keycode as u32, 1); + if let Some(vk) = &self.vk { + if sym == Keysym::Shift_L + || sym == Keysym::Control_L + || sym == Keysym::Alt_L { + vk.modifiers(self.mod_state, 0, 0, 0); + } + + let keycode = *self.keycodes.get(&sym).unwrap(); + self.pressed[keycode as usize] = sym; + vk.key(0, keycode as u32, 1); + } else if let Some(imc) = &self.im_ctx { + imc.keysym(self.im_serial, 0, sym.raw(), 0, self.mod_state); + } } fn release(&mut self, sym: Keysym) { - let vk = self.vk.as_ref().unwrap(); - if sym == Keysym::NoSymbol || sym == Keysym::XF86_Fn { return; } @@ -148,29 +164,41 @@ impl Keyboard for VirtualKeyboard { match sym { Keysym::Shift_L => { self.mod_state &= !0x1; - vk.modifiers(self.mod_state, 0, 0, 0); }, Keysym::Control_L => { self.mod_state &= !0x4; - vk.modifiers(self.mod_state, 0, 0, 0); }, Keysym::Alt_L => { self.mod_state &= !0x8; - vk.modifiers(self.mod_state, 0, 0, 0); }, _ => (), } - let keycode = *self.keycodes.get(&sym).unwrap(); - self.pressed[keycode as usize] = Keysym::NoSymbol; - vk.key(0, keycode as u32, 0); + if let Some(vk) = &self.vk { + if sym == Keysym::Shift_L + || sym == Keysym::Control_L + || sym == Keysym::Alt_L { + vk.modifiers(self.mod_state, 0, 0, 0); + } + + let keycode = *self.keycodes.get(&sym).unwrap(); + self.pressed[keycode as usize] = Keysym::NoSymbol; + vk.key(0, keycode as u32, 0); + } else if let Some(imc) = &self.im_ctx { + imc.keysym(self.im_serial, 0, sym.raw(), 0, self.mod_state); + } } fn text(&mut self, text: &str) { - let im = self.im.as_ref().unwrap(); - im.commit_string(text.to_string()); - im.commit(self.im_serial); + if let Some(im) = &self.im { + im.commit_string(text.to_string()); + im.commit(self.im_serial); + } else if let Some(imc) = &self.im_ctx { + imc.commit_string(self.im_serial, text.to_string()); + } else { + panic!("Text should not be emitted without an input method protocol"); + } } fn change_layout(&mut self, layout: &Layout) diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index cb0424b..4025812 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -18,6 +18,7 @@ pub use self::surface::Surface; pub use wayland_protocols_wlr::layer_shell::v1::client as wlr_layer_shell_unstable_v1; pub use wayland_protocols::wp::fractional_scale::v1::client as fractional_scale_v1; +pub use wayland_protocols::wp::input_method::zv1::client as input_method_unstable_v1; pub use wayland_protocols::wp::text_input::zv3::client as text_input_unstable_v3; pub use wayland_protocols::wp::viewporter::client as viewporter;