wayland: keyboard: add input method v1 support
Unfortunately, it is still not possible to emit keys in KDE Plasma.
This commit is contained in:
parent
5ac0295e3a
commit
cefc4ddc79
3 changed files with 112 additions and 27 deletions
|
|
@ -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::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_manager_v1;
|
||||||
use crate::wayland::fractional_scale_v1::wp_fractional_scale_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_manager_v2;
|
||||||
use crate::wayland::input_method_unstable_v2::zwp_input_method_v2;
|
use crate::wayland::input_method_unstable_v2::zwp_input_method_v2;
|
||||||
use crate::wayland::viewporter::wp_viewporter;
|
use crate::wayland::viewporter::wp_viewporter;
|
||||||
|
|
@ -29,6 +31,7 @@ use wayland_client::Dispatch;
|
||||||
use wayland_client::Proxy;
|
use wayland_client::Proxy;
|
||||||
use wayland_client::QueueHandle;
|
use wayland_client::QueueHandle;
|
||||||
use wayland_client::WEnum;
|
use wayland_client::WEnum;
|
||||||
|
use wayland_client::globals::BindError;
|
||||||
use wayland_client::globals::GlobalList;
|
use wayland_client::globals::GlobalList;
|
||||||
use wayland_client::globals::GlobalListContents;
|
use wayland_client::globals::GlobalListContents;
|
||||||
use wayland_client::protocol::wl_buffer;
|
use wayland_client::protocol::wl_buffer;
|
||||||
|
|
@ -69,6 +72,9 @@ impl Dispatcher {
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let _: Result<zwp_input_method_v1::ZwpInputMethodV1, BindError>
|
||||||
|
= globals.bind(&queue, 1..=1, ());
|
||||||
|
|
||||||
let frac_scale_man = match globals.bind(&queue, 1..=1, ()) {
|
let frac_scale_man = match globals.bind(&queue, 1..=1, ()) {
|
||||||
Ok(g) => Some(g),
|
Ok(g) => Some(g),
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
|
|
@ -422,6 +428,27 @@ impl Dispatch<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, ()> for Dispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Dispatch<zwp_input_method_context_v1::ZwpInputMethodContextV1, ()> 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<Dispatcher>)
|
||||||
|
{
|
||||||
|
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<zwp_input_method_manager_v2::ZwpInputMethodManagerV2, ()> for Dispatcher {
|
impl Dispatch<zwp_input_method_manager_v2::ZwpInputMethodManagerV2, ()> for Dispatcher {
|
||||||
fn event(_ctx: &mut Dispatcher,
|
fn event(_ctx: &mut Dispatcher,
|
||||||
_im_man: &zwp_input_method_manager_v2::ZwpInputMethodManagerV2,
|
_im_man: &zwp_input_method_manager_v2::ZwpInputMethodManagerV2,
|
||||||
|
|
@ -434,6 +461,35 @@ impl Dispatch<zwp_input_method_manager_v2::ZwpInputMethodManagerV2, ()> for Disp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Dispatch<zwp_input_method_v1::ZwpInputMethodV1, ()> for Dispatcher {
|
||||||
|
fn event(ctx: &mut Dispatcher,
|
||||||
|
_im: &zwp_input_method_v1::ZwpInputMethodV1,
|
||||||
|
evt: zwp_input_method_v1::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_qh: &QueueHandle<Dispatcher>)
|
||||||
|
{
|
||||||
|
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<zwp_input_method_v2::ZwpInputMethodV2, ()> for Dispatcher {
|
impl Dispatch<zwp_input_method_v2::ZwpInputMethodV2, ()> for Dispatcher {
|
||||||
fn event(ctx: &mut Dispatcher,
|
fn event(ctx: &mut Dispatcher,
|
||||||
_im: &zwp_input_method_v2::ZwpInputMethodV2,
|
_im: &zwp_input_method_v2::ZwpInputMethodV2,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
use crate::core::Keyboard;
|
use crate::core::Keyboard;
|
||||||
use crate::core::Layout;
|
use crate::core::Layout;
|
||||||
use crate::core::Part;
|
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_manager_v2::ZwpInputMethodManagerV2;
|
||||||
use crate::wayland::input_method_unstable_v2::zwp_input_method_v2::ZwpInputMethodV2;
|
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;
|
use crate::wayland::virtual_keyboard_unstable_v1::zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1;
|
||||||
|
|
@ -29,6 +30,7 @@ pub struct VirtualKeyboard {
|
||||||
keymap_id: u8,
|
keymap_id: u8,
|
||||||
|
|
||||||
im: Option<ZwpInputMethodV2>,
|
im: Option<ZwpInputMethodV2>,
|
||||||
|
im_ctx: Option<ZwpInputMethodContextV1>,
|
||||||
im_serial: u32,
|
im_serial: u32,
|
||||||
|
|
||||||
keycodes: HashMap<Keysym, u8>,
|
keycodes: HashMap<Keysym, u8>,
|
||||||
|
|
@ -46,7 +48,7 @@ impl VirtualKeyboard {
|
||||||
-> VirtualKeyboard
|
-> VirtualKeyboard
|
||||||
{
|
{
|
||||||
let vk = vk_man.as_ref().map(|m| m.create_virtual_keyboard(seat, queue, ()));
|
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 path = format!("/tmp/ufkbd-keymap-pid{}-1", process::id());
|
||||||
let keymap = File::create(path).unwrap();
|
let keymap = File::create(path).unwrap();
|
||||||
|
|
@ -57,6 +59,7 @@ impl VirtualKeyboard {
|
||||||
keymap_id: 1,
|
keymap_id: 1,
|
||||||
|
|
||||||
im,
|
im,
|
||||||
|
im_ctx: None,
|
||||||
im_serial: 0,
|
im_serial: 0,
|
||||||
|
|
||||||
keycodes: HashMap::with_capacity(248),
|
keycodes: HashMap::with_capacity(248),
|
||||||
|
|
@ -93,25 +96,33 @@ impl VirtualKeyboard {
|
||||||
{
|
{
|
||||||
self.im_serial += 1;
|
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<ZwpInputMethodContextV1>)
|
||||||
|
{
|
||||||
|
self.im_ctx = imc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Keyboard for VirtualKeyboard {
|
impl Keyboard for VirtualKeyboard {
|
||||||
fn key_supported(&self, sym: Keysym) -> bool
|
fn key_supported(&self, sym: Keysym) -> bool
|
||||||
{
|
{
|
||||||
if self.vk.is_none() {
|
if self.vk.is_some() {
|
||||||
return false;
|
match sym.name() {
|
||||||
}
|
Some(n) => n.starts_with("XK_"),
|
||||||
|
None => false,
|
||||||
match sym.name() {
|
}
|
||||||
Some(n) => n.starts_with("XK_"),
|
} else {
|
||||||
None => false,
|
self.im_ctx.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn press(&mut self, sym: Keysym)
|
fn press(&mut self, sym: Keysym)
|
||||||
{
|
{
|
||||||
let vk = self.vk.as_ref().unwrap();
|
|
||||||
|
|
||||||
if sym == Keysym::NoSymbol || sym == Keysym::XF86_Fn {
|
if sym == Keysym::NoSymbol || sym == Keysym::XF86_Fn {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -119,28 +130,33 @@ impl Keyboard for VirtualKeyboard {
|
||||||
match sym {
|
match sym {
|
||||||
Keysym::Shift_L => {
|
Keysym::Shift_L => {
|
||||||
self.mod_state |= 0x1;
|
self.mod_state |= 0x1;
|
||||||
vk.modifiers(self.mod_state, 0, 0, 0);
|
|
||||||
},
|
},
|
||||||
Keysym::Control_L => {
|
Keysym::Control_L => {
|
||||||
self.mod_state |= 0x4;
|
self.mod_state |= 0x4;
|
||||||
vk.modifiers(self.mod_state, 0, 0, 0);
|
|
||||||
},
|
},
|
||||||
Keysym::Alt_L => {
|
Keysym::Alt_L => {
|
||||||
self.mod_state |= 0x8;
|
self.mod_state |= 0x8;
|
||||||
vk.modifiers(self.mod_state, 0, 0, 0);
|
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let keycode = *self.keycodes.get(&sym).unwrap();
|
if let Some(vk) = &self.vk {
|
||||||
self.pressed[keycode as usize] = sym;
|
if sym == Keysym::Shift_L
|
||||||
vk.key(0, keycode as u32, 1);
|
|| 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)
|
fn release(&mut self, sym: Keysym)
|
||||||
{
|
{
|
||||||
let vk = self.vk.as_ref().unwrap();
|
|
||||||
|
|
||||||
if sym == Keysym::NoSymbol || sym == Keysym::XF86_Fn {
|
if sym == Keysym::NoSymbol || sym == Keysym::XF86_Fn {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -148,29 +164,41 @@ impl Keyboard for VirtualKeyboard {
|
||||||
match sym {
|
match sym {
|
||||||
Keysym::Shift_L => {
|
Keysym::Shift_L => {
|
||||||
self.mod_state &= !0x1;
|
self.mod_state &= !0x1;
|
||||||
vk.modifiers(self.mod_state, 0, 0, 0);
|
|
||||||
},
|
},
|
||||||
Keysym::Control_L => {
|
Keysym::Control_L => {
|
||||||
self.mod_state &= !0x4;
|
self.mod_state &= !0x4;
|
||||||
vk.modifiers(self.mod_state, 0, 0, 0);
|
|
||||||
},
|
},
|
||||||
Keysym::Alt_L => {
|
Keysym::Alt_L => {
|
||||||
self.mod_state &= !0x8;
|
self.mod_state &= !0x8;
|
||||||
vk.modifiers(self.mod_state, 0, 0, 0);
|
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let keycode = *self.keycodes.get(&sym).unwrap();
|
if let Some(vk) = &self.vk {
|
||||||
self.pressed[keycode as usize] = Keysym::NoSymbol;
|
if sym == Keysym::Shift_L
|
||||||
vk.key(0, keycode as u32, 0);
|
|| 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)
|
fn text(&mut self, text: &str)
|
||||||
{
|
{
|
||||||
let im = self.im.as_ref().unwrap();
|
if let Some(im) = &self.im {
|
||||||
im.commit_string(text.to_string());
|
im.commit_string(text.to_string());
|
||||||
im.commit(self.im_serial);
|
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)
|
fn change_layout(&mut self, layout: &Layout)
|
||||||
|
|
|
||||||
|
|
@ -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_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::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::text_input::zv3::client as text_input_unstable_v3;
|
||||||
pub use wayland_protocols::wp::viewporter::client as viewporter;
|
pub use wayland_protocols::wp::viewporter::client as viewporter;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue