Skip to content

Commit 53321eb

Browse files
committed
feat: allow handle virtual keyboard input by WM
1 parent a92540d commit 53321eb

File tree

3 files changed

+86
-8
lines changed

3 files changed

+86
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ wayland_frontend = ["wayland-server", "wayland-protocols", "wayland-protocols-wl
110110
x11rb_event_source = ["x11rb"]
111111
xwayland = ["encoding_rs", "wayland_frontend", "x11rb/composite", "x11rb/xfixes", "x11rb/randr", "x11rb_event_source", "scopeguard"]
112112
test_all_features = ["default", "use_system_lib", "renderer_glow", "renderer_test"]
113+
virtual_keyboard_not_use_default_handler = [ ]
113114

114115
[[example]]
115116
name = "minimal"

src/wayland/virtual_keyboard/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ use wayland_protocols_misc::zwp_virtual_keyboard_v1::server::{
5757
};
5858
use wayland_server::{backend::GlobalId, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New};
5959

60-
use crate::input::{Seat, SeatHandler};
61-
6260
use self::virtual_keyboard_handle::VirtualKeyboardHandle;
61+
use crate::backend::input::{KeyState, Keycode};
62+
use crate::input::keyboard::KeyboardHandle;
63+
use crate::input::{Seat, SeatHandler};
6364

6465
const MANAGER_VERSION: u32 = 1;
6566

@@ -91,6 +92,18 @@ where
9192
display.create_global::<D, ZwpVirtualKeyboardManagerV1, _>(MANAGER_VERSION, data)
9293
}
9394

95+
/// Handle keyboard event
96+
pub trait VirtualKeyboardHandler: SeatHandler {
97+
/// Handle KeyboardEvent as usual
98+
fn on_keyboard_event(
99+
&mut self,
100+
keycode: Keycode,
101+
state: KeyState,
102+
time: u32,
103+
keyboard: KeyboardHandle<Self>,
104+
);
105+
}
106+
94107
impl VirtualKeyboardManagerState {
95108
/// Initialize a virtual keyboard manager global.
96109
pub fn new<D, F>(display: &DisplayHandle, filter: F) -> Self

src/wayland/virtual_keyboard/virtual_keyboard_handle.rs

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,22 @@ use wayland_protocols_misc::zwp_virtual_keyboard_v1::server::zwp_virtual_keyboar
1010
self, ZwpVirtualKeyboardV1,
1111
};
1212
use wayland_server::{
13-
backend::ClientId,
14-
protocol::wl_keyboard::{KeyState, KeymapFormat},
15-
Client, DataInit, Dispatch, DisplayHandle, Resource,
13+
backend::ClientId, protocol::wl_keyboard::KeymapFormat, Client, DataInit, Dispatch, DisplayHandle,
14+
Resource,
1615
};
1716
use xkbcommon::xkb;
1817

1918
use crate::input::keyboard::{KeyboardTarget, KeymapFile, ModifiersState};
19+
use crate::wayland::input_method::InputMethodSeat;
2020
use crate::{
2121
input::{Seat, SeatHandler},
2222
utils::SERIAL_COUNTER,
2323
wayland::seat::{keyboard::for_each_focused_kbds, WaylandFocus},
2424
};
2525

26-
use super::VirtualKeyboardManagerState;
26+
use crate::backend::input::KeyState;
27+
28+
use super::{VirtualKeyboardHandler, VirtualKeyboardManagerState};
2729

2830
#[derive(Debug, Default)]
2931
pub(crate) struct VirtualKeyboard {
@@ -75,11 +77,12 @@ impl<D> Dispatch<ZwpVirtualKeyboardV1, VirtualKeyboardUserData<D>, D> for Virtua
7577
where
7678
D: Dispatch<ZwpVirtualKeyboardV1, VirtualKeyboardUserData<D>>,
7779
D: SeatHandler + 'static,
80+
D: VirtualKeyboardHandler,
7881
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
7982
{
8083
fn request(
8184
user_data: &mut D,
82-
_client: &Client,
85+
client: &Client,
8386
virtual_keyboard: &ZwpVirtualKeyboardV1,
8487
request: zwp_virtual_keyboard_v1::Request,
8588
data: &VirtualKeyboardUserData<D>,
@@ -90,6 +93,67 @@ where
9093
zwp_virtual_keyboard_v1::Request::Keymap { format, fd, size } => {
9194
update_keymap(data, format, fd, size as usize);
9295
}
96+
#[cfg(feature = "virtual_keyboard_not_use_default_handler")]
97+
zwp_virtual_keyboard_v1::Request::Key { time, key, state } => {
98+
// Ensure keymap was initialized.
99+
let mut virtual_data = data.handle.inner.lock().unwrap();
100+
let vk_state = match virtual_data.state.as_mut() {
101+
Some(vk_state) => vk_state,
102+
None => {
103+
virtual_keyboard.post_error(NoKeymap, "`key` sent before keymap.");
104+
return;
105+
}
106+
};
107+
// Ensure virtual keyboard's keymap is active.
108+
let keyboard_handle = data.seat.get_keyboard().unwrap();
109+
110+
let ime_keyboard_grabbed = data
111+
.seat
112+
.input_method()
113+
.inner
114+
.lock()
115+
.unwrap()
116+
.keyboard_grab
117+
.inner
118+
.lock()
119+
.unwrap()
120+
.grab
121+
.clone();
122+
if ime_keyboard_grabbed.is_some()
123+
&& ime_keyboard_grabbed.unwrap().client().unwrap() == *client
124+
{
125+
use wayland_server::protocol::wl_keyboard::KeyState;
126+
let mut internal = keyboard_handle.arc.internal.lock().unwrap();
127+
let focus = internal.focus.as_mut().map(|(focus, _)| focus);
128+
keyboard_handle.send_keymap(user_data, &focus, &vk_state.keymap, vk_state.mods);
129+
if let Some(wl_surface) = focus.and_then(|f| f.wl_surface()) {
130+
for_each_focused_kbds(&data.seat, &wl_surface, |kbd| {
131+
// This should be wl_keyboard::KeyState, but the protocol does not state
132+
// the parameter is an enum.
133+
let key_state = if state == 1 {
134+
KeyState::Pressed
135+
} else {
136+
KeyState::Released
137+
};
138+
139+
kbd.key(SERIAL_COUNTER.next_serial().0, time, key, key_state);
140+
});
141+
}
142+
} else {
143+
{
144+
let mut internal = keyboard_handle.arc.internal.lock().unwrap();
145+
let focus = internal.focus.as_mut().map(|(focus, _)| focus);
146+
keyboard_handle.send_keymap(user_data, &focus, &vk_state.keymap, vk_state.mods);
147+
}
148+
let key_state = if state == 1 {
149+
KeyState::Pressed
150+
} else {
151+
KeyState::Released
152+
};
153+
user_data.on_keyboard_event((key + 8).into(), key_state, time, keyboard_handle);
154+
}
155+
}
156+
#[cfg(not(feature = "virtual_keyboard_not_use_default_handler"))]
93157
zwp_virtual_keyboard_v1::Request::Key { time, key, state } => {
94158
// Ensure keymap was initialized.
95159
let mut virtual_data = data.handle.inner.lock().unwrap();
@@ -106,7 +170,7 @@ where
106170
let mut internal = keyboard_handle.arc.internal.lock().unwrap();
107171
let focus = internal.focus.as_mut().map(|(focus, _)| focus);
108172
keyboard_handle.send_keymap(user_data, &focus, &vk_state.keymap, vk_state.mods);
109-
173+
use wayland_server::protocol::wl_keyboard::KeyState;
110174
if let Some(wl_surface) = focus.and_then(|f| f.wl_surface()) {
111175
for_each_focused_kbds(&data.seat, &wl_surface, |kbd| {
112176
// This should be wl_keyboard::KeyState, but the protocol does not state

0 commit comments

Comments
 (0)