mirror of
https://github.com/wez/wezterm.git
synced 2024-09-11 14:25:57 +03:00
Don't use xkbcommon feature in smithay so we can use modifiers
This commit is contained in:
parent
cfbc9d716c
commit
fb35683e0a
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -5037,7 +5037,6 @@ dependencies = [
|
||||
"log",
|
||||
"memmap2 0.5.10",
|
||||
"nix 0.26.4",
|
||||
"pkg-config",
|
||||
"thiserror",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
@ -5045,7 +5044,6 @@ dependencies = [
|
||||
"wayland-protocols",
|
||||
"wayland-protocols-wlr",
|
||||
"wayland-scanner",
|
||||
"xkbcommon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -81,7 +81,7 @@ xcb-imdkit = { version="0.3", git="https://github.com/wez/xcb-imdkit-rs.git", re
|
||||
zbus = "3.14"
|
||||
zvariant = "3.15"
|
||||
|
||||
smithay-client-toolkit = {version = "0.17.0", features=["xkbcommon"], default-features=false, optional=true}
|
||||
smithay-client-toolkit = {version = "0.17.0", default-features=false, optional=true}
|
||||
wayland-protocols = {version="0.30", optional=true}
|
||||
wayland-client = {version="0.30", optional=true}
|
||||
wayland-egl = {version="0.30", optional=true}
|
||||
|
107
window/src/os/wayland/keyboard.rs
Normal file
107
window/src/os/wayland/keyboard.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use std::borrow::BorrowMut;
|
||||
use std::io::Read;
|
||||
use std::os::fd::{AsRawFd, FromRawFd};
|
||||
use std::os::unix::fs::FileExt;
|
||||
|
||||
use wayland_client::protocol::wl_keyboard::{Event as WlKeyboardEvent, KeymapFormat, WlKeyboard};
|
||||
use wayland_client::{Dispatch, Proxy};
|
||||
|
||||
use crate::x11::KeyboardWithFallback;
|
||||
|
||||
use super::state::WaylandState;
|
||||
use super::SurfaceUserData;
|
||||
|
||||
// We can't use the xkbcommon feature because it is too abstract for us
|
||||
impl Dispatch<WlKeyboard, KeyboardData> for WaylandState {
|
||||
fn event(
|
||||
state: &mut WaylandState,
|
||||
_proxy: &WlKeyboard,
|
||||
event: <WlKeyboard as wayland_client::Proxy>::Event,
|
||||
_data: &KeyboardData,
|
||||
_conn: &wayland_client::Connection,
|
||||
_qhandle: &wayland_client::QueueHandle<WaylandState>,
|
||||
) {
|
||||
log::trace!("We reached an event here: {:?}???", event);
|
||||
match &event {
|
||||
WlKeyboardEvent::Enter {
|
||||
serial, surface, ..
|
||||
} => {
|
||||
*state.active_surface_id.borrow_mut() = Some(surface.id());
|
||||
*state.last_serial.borrow_mut() = *serial;
|
||||
if let Some(sud) = SurfaceUserData::try_from_wl(&surface) {
|
||||
let window_id = sud.window_id;
|
||||
state.keyboard_window_id.borrow_mut().replace(window_id);
|
||||
} else {
|
||||
log::warn!("{:?}, no known surface", event);
|
||||
}
|
||||
}
|
||||
WlKeyboardEvent::Leave { serial, .. } => {
|
||||
// TODO: I know nothing about the input handler currently
|
||||
*state.last_serial.borrow_mut() = *serial;
|
||||
}
|
||||
WlKeyboardEvent::Key { serial, .. } | WlKeyboardEvent::Modifiers { serial, .. } => {
|
||||
*state.last_serial.borrow_mut() = *serial;
|
||||
}
|
||||
WlKeyboardEvent::RepeatInfo { rate, delay } => {
|
||||
*state.key_repeat_rate.borrow_mut() = *rate;
|
||||
*state.key_repeat_delay.borrow_mut() = *delay;
|
||||
}
|
||||
WlKeyboardEvent::Keymap { format, fd, size } => {
|
||||
let mut file = unsafe { std::fs::File::from_raw_fd(fd.as_raw_fd()) };
|
||||
match format.into_result().unwrap() {
|
||||
KeymapFormat::XkbV1 => {
|
||||
let mut data = vec![0u8; *size as usize];
|
||||
// If we weren't passed a pipe, be sure to explicitly
|
||||
// read from the start of the file
|
||||
match file.read_exact_at(&mut data, 0) {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
// ideally: we check for:
|
||||
// err.kind() == std::io::ErrorKind::NotSeekable
|
||||
// but that is not yet in stable rust
|
||||
if err.raw_os_error() == Some(libc::ESPIPE) {
|
||||
// It's a pipe, which cannot be seeked, so we
|
||||
// just try reading from the current pipe position
|
||||
file.read(&mut data).expect("read from Keymap fd/pipe");
|
||||
} else {
|
||||
return Err(err).expect("read_exact_at from Keymap fd");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dance around CString panicing on the NUL terminator
|
||||
// in the xkbcommon crate
|
||||
while let Some(0) = data.last() {
|
||||
data.pop();
|
||||
}
|
||||
let s = String::from_utf8(data).expect("Failed to read string from data");
|
||||
match KeyboardWithFallback::new_from_string(s) {
|
||||
Ok(k) => {
|
||||
state.keyboard_mapper.replace(k);
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Error processing keymap change: {:#}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
let Some(&window_id) = state.keyboard_window_id.as_ref() else {
|
||||
return;
|
||||
};
|
||||
let Some(win) = state.window_by_id(window_id) else {
|
||||
return;
|
||||
};
|
||||
let mut inner = win.as_ref().borrow_mut();
|
||||
let mapper = state.keyboard_mapper.borrow_mut();
|
||||
let mapper = mapper.as_mut().expect("no keymap");
|
||||
inner.keyboard_event(mapper, event);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct KeyboardData {}
|
@ -11,8 +11,9 @@ pub use connection::*;
|
||||
// mod drag_and_drop;
|
||||
// mod frame;
|
||||
// mod pointer;
|
||||
mod state;
|
||||
mod keyboard;
|
||||
mod seat;
|
||||
mod state;
|
||||
|
||||
/// Returns the id of a wayland proxy object, suitable for using
|
||||
/// a key into hash maps
|
||||
|
@ -1,19 +1,10 @@
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::RefMut;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
|
||||
use smithay_client_toolkit::seat::keyboard::{KeyEvent, KeyboardHandler, Keymap};
|
||||
use smithay_client_toolkit::seat::{Capability, SeatHandler, SeatState};
|
||||
use wayland_client::protocol::wl_keyboard::WlKeyboard;
|
||||
use wayland_client::protocol::wl_seat::WlSeat;
|
||||
use wayland_client::protocol::wl_surface::WlSurface;
|
||||
use wayland_client::{Connection, Proxy, QueueHandle};
|
||||
use wayland_client::{Connection, QueueHandle};
|
||||
|
||||
use crate::x11::KeyboardWithFallback;
|
||||
use crate::wayland::keyboard::KeyboardData;
|
||||
|
||||
use super::state::WaylandState;
|
||||
use super::{KeyRepeatState, SurfaceUserData};
|
||||
|
||||
impl SeatHandler for WaylandState {
|
||||
fn seat_state(&mut self) -> &mut SeatState {
|
||||
@ -33,11 +24,8 @@ impl SeatHandler for WaylandState {
|
||||
) {
|
||||
if capability == Capability::Keyboard && self.keyboard.is_none() {
|
||||
log::trace!("Setting keyboard capability");
|
||||
let keyboard = self
|
||||
.seat
|
||||
.get_keyboard(qh, &seat, None)
|
||||
.expect("Failed to create keyboard");
|
||||
self.keyboard = Some(keyboard);
|
||||
let keyboard = seat.get_keyboard(qh, KeyboardData {});
|
||||
self.keyboard = Some(keyboard)
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,168 +43,3 @@ impl SeatHandler for WaylandState {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyboardHandler for WaylandState {
|
||||
fn enter(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_keyboard: &WlKeyboard,
|
||||
surface: &WlSurface,
|
||||
serial: u32,
|
||||
raw: &[u32],
|
||||
keysyms: &[u32],
|
||||
) {
|
||||
*self.active_surface_id.borrow_mut() = Some(surface.id());
|
||||
*self.last_serial.borrow_mut() = serial;
|
||||
if let Some(sud) = SurfaceUserData::try_from_wl(surface) {
|
||||
let window_id = sud.window_id;
|
||||
self.keyboard_window_id.borrow_mut().replace(window_id);
|
||||
// TODO: env with inner seems to IME stuff
|
||||
} else {
|
||||
log::warn!("{:?}, no known surface", "WlKeyboardEnter");
|
||||
}
|
||||
|
||||
let Some(&window_id) = self.keyboard_window_id.as_ref() else {
|
||||
return;
|
||||
};
|
||||
let Some(mut win) = self.window_by_id(window_id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
// TODO: not sure if this is correct; is it keycodes?
|
||||
log::trace!(
|
||||
"keyboard event: Enter with keysyms: {:?}, raw: {:?}",
|
||||
keysyms,
|
||||
raw
|
||||
);
|
||||
|
||||
let inner = win.borrow_mut();
|
||||
let mapper = self.keyboard_mapper.borrow_mut();
|
||||
let mapper = mapper.as_mut().expect("no keymap");
|
||||
|
||||
inner.as_ref().borrow_mut().emit_focus(mapper, true);
|
||||
}
|
||||
|
||||
fn leave(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_keyboard: &WlKeyboard,
|
||||
_surface: &WlSurface,
|
||||
serial: u32,
|
||||
) {
|
||||
// TODO: inner input
|
||||
*self.last_serial.borrow_mut() = serial;
|
||||
}
|
||||
|
||||
fn press_key(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_keyboard: &WlKeyboard,
|
||||
serial: u32,
|
||||
event: KeyEvent,
|
||||
) {
|
||||
*self.last_serial.borrow_mut() = serial;
|
||||
let Some(&window_id) = self.keyboard_window_id.as_ref() else {
|
||||
return;
|
||||
};
|
||||
let Some(win) = self.window_by_id(window_id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let inner = win.as_ref().borrow_mut();
|
||||
let (mut events, mut key_repeat) =
|
||||
RefMut::map_split(inner, |w| (&mut w.events, &mut w.key_repeat));
|
||||
|
||||
let mapper = self.keyboard_mapper.borrow_mut();
|
||||
let mapper = mapper.as_mut().expect("no keymap");
|
||||
|
||||
let key = event.raw_code;
|
||||
if let Some(event) = mapper.process_wayland_key(key, true, &mut events) {
|
||||
let rep = Arc::new(Mutex::new(KeyRepeatState {
|
||||
when: Instant::now(),
|
||||
event,
|
||||
}));
|
||||
|
||||
key_repeat.replace((key, Arc::clone(&rep)));
|
||||
|
||||
KeyRepeatState::schedule(rep, window_id);
|
||||
} else if let Some((cur_key, _)) = key_repeat.as_mut() {
|
||||
if *cur_key == key {
|
||||
key_repeat.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn release_key(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_keyboard: &WlKeyboard,
|
||||
serial: u32,
|
||||
event: KeyEvent,
|
||||
) {
|
||||
// TODO: copy paste of press_key except process is false
|
||||
*self.last_serial.borrow_mut() = serial;
|
||||
let Some(&window_id) = self.keyboard_window_id.as_ref() else {
|
||||
return;
|
||||
};
|
||||
let Some(win) = self.window_by_id(window_id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let inner = win.as_ref().borrow_mut();
|
||||
let (mut events, mut key_repeat) =
|
||||
RefMut::map_split(inner, |w| (&mut w.events, &mut w.key_repeat));
|
||||
|
||||
let mapper = self.keyboard_mapper.borrow_mut();
|
||||
let mapper = mapper.as_mut().expect("no keymap");
|
||||
|
||||
let key = event.raw_code;
|
||||
if let Some(event) = mapper.process_wayland_key(key, false, &mut events) {
|
||||
let rep = Arc::new(Mutex::new(KeyRepeatState {
|
||||
when: Instant::now(),
|
||||
event,
|
||||
}));
|
||||
|
||||
key_repeat.replace((key, Arc::clone(&rep)));
|
||||
|
||||
KeyRepeatState::schedule(rep, window_id);
|
||||
} else if let Some((cur_key, _)) = key_repeat.as_mut() {
|
||||
if *cur_key == key {
|
||||
key_repeat.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_modifiers(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_keyboard: &WlKeyboard,
|
||||
serial: u32,
|
||||
_modifiers: smithay_client_toolkit::seat::keyboard::Modifiers,
|
||||
) {
|
||||
*self.last_serial.borrow_mut() = serial;
|
||||
}
|
||||
|
||||
fn update_keymap(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_keyboard: &WlKeyboard,
|
||||
keymap: Keymap<'_>,
|
||||
) {
|
||||
let keymap_str = keymap.as_string();
|
||||
match KeyboardWithFallback::new_from_string(keymap_str) {
|
||||
Ok(k) => {
|
||||
self.keyboard_mapper.replace(k);
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Error processing keymap change: {:#}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ use smithay_client_toolkit::shell::xdg::XdgShell;
|
||||
use smithay_client_toolkit::shm::slot::SlotPool;
|
||||
use smithay_client_toolkit::shm::{Shm, ShmHandler};
|
||||
use smithay_client_toolkit::{
|
||||
delegate_compositor, delegate_keyboard, delegate_output, delegate_registry, delegate_seat,
|
||||
delegate_shm, delegate_xdg_shell, delegate_xdg_window, registry_handlers,
|
||||
delegate_compositor, delegate_output, delegate_registry, delegate_seat, delegate_shm,
|
||||
delegate_xdg_shell, delegate_xdg_window, registry_handlers,
|
||||
};
|
||||
use wayland_client::backend::ObjectId;
|
||||
use wayland_client::globals::GlobalList;
|
||||
@ -116,7 +116,6 @@ delegate_output!(WaylandState);
|
||||
delegate_compositor!(WaylandState);
|
||||
|
||||
delegate_seat!(WaylandState);
|
||||
delegate_keyboard!(WaylandState);
|
||||
|
||||
delegate_xdg_shell!(WaylandState);
|
||||
delegate_xdg_window!(WaylandState);
|
||||
|
@ -21,11 +21,12 @@ use smithay_client_toolkit::shell::xdg::window::{
|
||||
};
|
||||
use smithay_client_toolkit::shell::WaylandSurface;
|
||||
use wayland_client::protocol::wl_callback::WlCallback;
|
||||
use wayland_client::protocol::wl_keyboard::{Event as WlKeyboardEvent, KeyState};
|
||||
use wayland_client::protocol::wl_surface::WlSurface;
|
||||
use wayland_client::{Connection as WConnection, Proxy};
|
||||
use wayland_egl::{is_available as egl_is_available, WlEglSurface};
|
||||
use wezterm_font::FontConfiguration;
|
||||
use wezterm_input_types::{Modifiers, WindowDecorations};
|
||||
use wezterm_input_types::{KeyboardLedStatus, Modifiers, WindowDecorations};
|
||||
|
||||
use crate::wayland::WaylandConnection;
|
||||
use crate::x11::KeyboardWithFallback;
|
||||
@ -235,6 +236,7 @@ impl WaylandWindow {
|
||||
window_state: WindowState::default(),
|
||||
|
||||
modifiers: Modifiers::NONE,
|
||||
leds: KeyboardLedStatus::empty(),
|
||||
|
||||
key_repeat: None,
|
||||
pending_event,
|
||||
@ -374,7 +376,7 @@ pub struct WaylandWindowInner {
|
||||
// hscroll_remainder: f64,
|
||||
// vscroll_remainder: f64,
|
||||
modifiers: Modifiers,
|
||||
// leds: KeyboardLedStatus,
|
||||
leds: KeyboardLedStatus,
|
||||
pub(super) key_repeat: Option<(u32, Arc<Mutex<KeyRepeatState>>)>,
|
||||
pub(crate) pending_event: Arc<Mutex<PendingEvent>>,
|
||||
// pending_mouse: Arc<Mutex<PendingMouse>>,
|
||||
@ -714,6 +716,76 @@ impl WaylandWindowInner {
|
||||
self.events.dispatch(WindowEvent::FocusChanged(focused));
|
||||
self.text_cursor.take();
|
||||
}
|
||||
|
||||
pub(super) fn keyboard_event(
|
||||
&mut self,
|
||||
mapper: &mut KeyboardWithFallback,
|
||||
event: WlKeyboardEvent,
|
||||
) {
|
||||
match event {
|
||||
WlKeyboardEvent::Enter { keys, .. } => {
|
||||
let key_codes = keys
|
||||
.chunks_exact(4)
|
||||
.map(|c| u32::from_ne_bytes(c.try_into().unwrap()))
|
||||
.collect::<Vec<_>>();
|
||||
log::trace!("keyboard event: Enter with keys: {:?}", key_codes);
|
||||
self.emit_focus(mapper, true);
|
||||
}
|
||||
WlKeyboardEvent::Leave { .. } => {
|
||||
self.emit_focus(mapper, false);
|
||||
}
|
||||
WlKeyboardEvent::Key { key, state, .. } => {
|
||||
if let Some(event) = mapper.process_wayland_key(
|
||||
key,
|
||||
state.into_result().unwrap() == KeyState::Pressed,
|
||||
&mut self.events,
|
||||
) {
|
||||
let rep = Arc::new(Mutex::new(KeyRepeatState {
|
||||
when: Instant::now(),
|
||||
event,
|
||||
}));
|
||||
self.key_repeat.replace((key, Arc::clone(&rep)));
|
||||
let window_id = SurfaceUserData::from_wl(
|
||||
self.window
|
||||
.as_ref()
|
||||
.expect("window should exist")
|
||||
.wl_surface(),
|
||||
)
|
||||
.window_id;
|
||||
KeyRepeatState::schedule(rep, window_id);
|
||||
} else if let Some((cur_key, _)) = self.key_repeat.as_ref() {
|
||||
// important to check that it's the same key, because the release of the previously
|
||||
// repeated key can come right after the press of the newly held key
|
||||
if *cur_key == key {
|
||||
self.key_repeat.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
WlKeyboardEvent::Modifiers {
|
||||
mods_depressed,
|
||||
mods_latched,
|
||||
mods_locked,
|
||||
group,
|
||||
..
|
||||
} => {
|
||||
mapper.update_modifier_state(mods_depressed, mods_latched, mods_locked, group);
|
||||
|
||||
let mods = mapper.get_key_modifiers();
|
||||
let leds = mapper.get_led_status();
|
||||
|
||||
let changed = (mods != self.modifiers) || (leds != self.leds);
|
||||
|
||||
self.modifiers = mapper.get_key_modifiers();
|
||||
self.leds = mapper.get_led_status();
|
||||
|
||||
if changed {
|
||||
self.events
|
||||
.dispatch(WindowEvent::AdviseModifiersLedStatus(mods, leds));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WaylandState {
|
||||
|
Loading…
Reference in New Issue
Block a user