1
1
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:
Timmy Xiao 2024-01-11 12:34:49 -05:00 committed by Wez Furlong
parent cfbc9d716c
commit fb35683e0a
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
7 changed files with 190 additions and 190 deletions

2
Cargo.lock generated
View File

@ -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]]

View File

@ -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}

View 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 {}

View File

@ -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

View File

@ -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);
}
}
}
}

View File

@ -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);

View File

@ -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 {