Skip to content

Commit 1024f38

Browse files
committed
feat: allow handle virtual keyboard input by WM
1 parent 22cb70d commit 1024f38

File tree

4 files changed

+162
-36
lines changed

4 files changed

+162
-36
lines changed

anvil/src/input_handler.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ use crate::udev::UdevData;
77
#[cfg(feature = "udev")]
88
use smithay::backend::renderer::DebugFlags;
99

10+
#[cfg(any(feature = "winit", feature = "x11", feature = "udev"))]
11+
use smithay::backend::input::AbsolutePositionEvent;
12+
use smithay::input::keyboard::KeyboardHandle;
13+
use smithay::input::keyboard::Keycode;
14+
use smithay::utils::SERIAL_COUNTER;
15+
use smithay::wayland::virtual_keyboard::VirtualKeyboardHandler;
1016
use smithay::{
1117
backend::input::{
1218
self, Axis, AxisSource, Event, InputBackend, InputEvent, KeyState, KeyboardKeyEvent,
@@ -30,9 +36,6 @@ use smithay::{
3036
},
3137
};
3238

33-
#[cfg(any(feature = "winit", feature = "x11", feature = "udev"))]
34-
use smithay::backend::input::AbsolutePositionEvent;
35-
3639
#[cfg(any(feature = "winit", feature = "x11"))]
3740
use smithay::output::Output;
3841
use tracing::{debug, error, info};
@@ -1327,3 +1330,26 @@ fn process_keyboard_shortcut(modifiers: ModifiersState, keysym: Keysym) -> Optio
13271330
None
13281331
}
13291332
}
1333+
1334+
impl<BackendData: Backend> VirtualKeyboardHandler for AnvilState<BackendData> {
1335+
fn on_keyboard_event(
1336+
&mut self,
1337+
keycode: Keycode,
1338+
state: KeyState,
1339+
time: u32,
1340+
keyboard: KeyboardHandle<Self>,
1341+
) {
1342+
let serial = SERIAL_COUNTER.next_serial();
1343+
keyboard.input(self, keycode, state, serial, time, |_, _, _| {
1344+
FilterResult::Forward::<bool>
1345+
});
1346+
}
1347+
pub fn on_keyboard_modifiers(
1348+
&mut self,
1349+
depressed_mods: ModMask,
1350+
latched_mods: ModMask,
1351+
locked_mods: ModMask,
1352+
keyboard: KeyboardHandle<Self>,
1353+
) {
1354+
}
1355+
}

src/input/keyboard/keymap_file.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ impl KeymapFile {
8585
Ok(())
8686
}
8787

88+
#[cfg(feature = "wayland_frontend")]
89+
/// Send keymap string for processing
90+
pub fn keymap_string(&self) -> String {
91+
self.keymap.clone()
92+
}
93+
8894
/// Send the keymap contained within to a WlKeyboard
8995
pub fn send(
9096
&self,

src/wayland/virtual_keyboard/mod.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
//! # use smithay::wayland::compositor::{CompositorHandler, CompositorState, CompositorClientState};
1414
//! use smithay::wayland::virtual_keyboard::VirtualKeyboardManagerState;
1515
//! use smithay::reexports::wayland_server::{Display, protocol::wl_surface::WlSurface};
16+
//! use smithay::input::keyboard::KeyboardHandle;
17+
//! use smithay::backend::input::{KeyState, Keycode};
18+
//! use smithay::wayland::virtual_keyboard::VirtualKeyboardHandler;
1619
//! # use smithay::reexports::wayland_server::Client;
20+
//! use xkbcommon::xkb::ModMask;
1721
//!
1822
//! # struct State { seat_state: SeatState<Self> };
1923
//!
@@ -47,6 +51,22 @@
4751
//! # fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState { unimplemented!() }
4852
//! # fn commit(&mut self, surface: &WlSurface) {}
4953
//! # }
54+
//! impl VirtualKeyboardHandler for State {
55+
//! fn on_keyboard_event(
56+
//! &mut self,
57+
//! keycode: Keycode,
58+
//! state: KeyState,
59+
//! time: u32,
60+
//! keyboard: KeyboardHandle<Self>,
61+
//! ) { }
62+
//! fn on_keyboard_modifiers(
63+
//! &mut self,
64+
//! depressed_mods: ModMask,
65+
//! latched_mods: ModMask,
66+
//! locked_mods: ModMask,
67+
//! keyboard: KeyboardHandle<Self>,
68+
//! ) { }
69+
//! }
5070
//! # delegate_compositor!(State);
5171
//! ```
5272
//!
@@ -57,9 +77,11 @@ use wayland_protocols_misc::zwp_virtual_keyboard_v1::server::{
5777
};
5878
use wayland_server::{backend::GlobalId, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New};
5979

60-
use crate::input::{Seat, SeatHandler};
61-
6280
use self::virtual_keyboard_handle::VirtualKeyboardHandle;
81+
use crate::backend::input::{KeyState, Keycode};
82+
use crate::input::keyboard::KeyboardHandle;
83+
use crate::input::{Seat, SeatHandler};
84+
use xkbcommon::xkb::ModMask;
6385

6486
const MANAGER_VERSION: u32 = 1;
6587

@@ -91,6 +113,27 @@ where
91113
display.create_global::<D, ZwpVirtualKeyboardManagerV1, _>(MANAGER_VERSION, data)
92114
}
93115

116+
/// Handle keyboard event
117+
pub trait VirtualKeyboardHandler: SeatHandler {
118+
/// Handle KeyboardEvent as usual
119+
fn on_keyboard_event(
120+
&mut self,
121+
keycode: Keycode,
122+
state: KeyState,
123+
time: u32,
124+
keyboard: KeyboardHandle<Self>,
125+
);
126+
127+
/// Handle modifiers event as usual
128+
fn on_keyboard_modifiers(
129+
&mut self,
130+
depressed_mods: ModMask,
131+
latched_mods: ModMask,
132+
locked_mods: ModMask,
133+
keyboard: KeyboardHandle<Self>,
134+
);
135+
}
136+
94137
impl VirtualKeyboardManagerState {
95138
/// Initialize a virtual keyboard manager global.
96139
pub fn new<D, F>(display: &DisplayHandle, filter: F) -> Self

src/wayland/virtual_keyboard/virtual_keyboard_handle.rs

Lines changed: 82 additions & 31 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,21 +77,35 @@ 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>,
8689
_dh: &DisplayHandle,
8790
_data_init: &mut DataInit<'_, D>,
8891
) {
92+
let ime_keyboard_grabbed = data
93+
.seat
94+
.input_method()
95+
.inner
96+
.lock()
97+
.unwrap()
98+
.keyboard_grab
99+
.inner
100+
.lock()
101+
.unwrap()
102+
.grab
103+
.clone();
89104
match request {
90105
zwp_virtual_keyboard_v1::Request::Keymap { format, fd, size } => {
91106
update_keymap(data, format, fd, size as usize);
92107
}
108+
93109
zwp_virtual_keyboard_v1::Request::Key { time, key, state } => {
94110
// Ensure keymap was initialized.
95111
let mut virtual_data = data.handle.inner.lock().unwrap();
@@ -100,25 +116,47 @@ where
100116
return;
101117
}
102118
};
103-
104119
// Ensure virtual keyboard's keymap is active.
105120
let keyboard_handle = data.seat.get_keyboard().unwrap();
106-
let mut internal = keyboard_handle.arc.internal.lock().unwrap();
107-
let focus = internal.focus.as_mut().map(|(focus, _)| focus);
108-
keyboard_handle.send_keymap(user_data, &focus, &vk_state.keymap, vk_state.mods);
109-
110-
if let Some(wl_surface) = focus.and_then(|f| f.wl_surface()) {
111-
for_each_focused_kbds(&data.seat, &wl_surface, |kbd| {
112-
// This should be wl_keyboard::KeyState, but the protocol does not state
113-
// the parameter is an enum.
114-
let key_state = if state == 1 {
115-
KeyState::Pressed
116-
} else {
117-
KeyState::Released
118-
};
119-
120-
kbd.key(SERIAL_COUNTER.next_serial().0, time, key, key_state);
121-
});
121+
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+
keyboard_handle
130+
.set_keymap_from_string(user_data, vk_state.keymap.keymap_string())
131+
.unwrap();
132+
if let Some(wl_surface) = focus.and_then(|f| f.wl_surface()) {
133+
for_each_focused_kbds(&data.seat, &wl_surface, |kbd| {
134+
// This should be wl_keyboard::KeyState, but the protocol does not state
135+
// the parameter is an enum.
136+
let key_state = if state == 1 {
137+
KeyState::Pressed
138+
} else {
139+
KeyState::Released
140+
};
141+
142+
kbd.key(SERIAL_COUNTER.next_serial().0, time, key, key_state);
143+
});
144+
}
145+
} else {
146+
{
147+
let mut internal = keyboard_handle.arc.internal.lock().unwrap();
148+
let focus = internal.focus.as_mut().map(|(focus, _)| focus);
149+
keyboard_handle.send_keymap(user_data, &focus, &vk_state.keymap, vk_state.mods);
150+
keyboard_handle
151+
.set_keymap_from_string(user_data, vk_state.keymap.keymap_string())
152+
.unwrap();
153+
}
154+
let key_state = if state == 1 {
155+
KeyState::Pressed
156+
} else {
157+
KeyState::Released
158+
};
159+
user_data.on_keyboard_event((key + 8).into(), key_state, time, keyboard_handle);
122160
}
123161
}
124162
zwp_virtual_keyboard_v1::Request::Modifiers {
@@ -145,17 +183,30 @@ where
145183

146184
// Ensure virtual keyboard's keymap is active.
147185
let keyboard_handle = data.seat.get_keyboard().unwrap();
148-
let mut internal = keyboard_handle.arc.internal.lock().unwrap();
149-
let focus = internal.focus.as_mut().map(|(focus, _)| focus);
150-
let keymap_changed =
151-
keyboard_handle.send_keymap(user_data, &focus, &state.keymap, state.mods);
152-
153-
// Report modifiers change to all keyboards.
154-
if !keymap_changed {
155-
if let Some(focus) = focus {
156-
focus.modifiers(&data.seat, user_data, state.mods, SERIAL_COUNTER.next_serial());
186+
{
187+
let mut internal = keyboard_handle.arc.internal.lock().unwrap();
188+
let focus = internal.focus.as_mut().map(|(focus, _)| focus);
189+
let keymap_changed =
190+
keyboard_handle.send_keymap(user_data, &focus, &state.keymap, state.mods);
191+
keyboard_handle
192+
.set_keymap_from_string(user_data, state.keymap.keymap_string())
193+
.unwrap();
194+
if !keymap_changed {
195+
if let Some(focus) = focus {
196+
focus.modifiers(&data.seat, user_data, state.mods, SERIAL_COUNTER.next_serial());
197+
}
157198
}
158199
}
200+
if !ime_keyboard_grabbed.is_some()
201+
|| !(ime_keyboard_grabbed.unwrap().client().unwrap() == *client)
202+
{
203+
user_data.on_keyboard_modifiers(
204+
mods_depressed,
205+
mods_latched,
206+
mods_locked,
207+
keyboard_handle,
208+
);
209+
}
159210
}
160211
zwp_virtual_keyboard_v1::Request::Destroy => {
161212
// Nothing to do

0 commit comments

Comments
 (0)