mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 22:01:47 +03:00
wayland: attempt to handle seat changes that impact the keyboard
A couple of times today while debugging things on wayland, I lost keyboard input to wezterm. I don't know if that is strictly a wezterm bug, or just a general wayland bug (not long after, the whole mutter session hung, and somehow wedged all processes with my uid). So, this is a quick stab in that direction.
This commit is contained in:
parent
b4ded64e14
commit
41cb9d3f38
@ -16,6 +16,7 @@ use std::time::{Duration, Instant};
|
|||||||
use toolkit::environment::Environment;
|
use toolkit::environment::Environment;
|
||||||
use toolkit::reexports::calloop::{EventLoop, EventSource, Interest, Mode, Poll, Readiness, Token};
|
use toolkit::reexports::calloop::{EventLoop, EventSource, Interest, Mode, Poll, Readiness, Token};
|
||||||
use toolkit::reexports::client::Display;
|
use toolkit::reexports::client::Display;
|
||||||
|
use toolkit::seat::SeatListener;
|
||||||
use toolkit::WaylandSource;
|
use toolkit::WaylandSource;
|
||||||
|
|
||||||
toolkit::default_environment!(MyEnvironment, desktop);
|
toolkit::default_environment!(MyEnvironment, desktop);
|
||||||
@ -37,6 +38,7 @@ pub struct WaylandConnection {
|
|||||||
pub(crate) gl_connection: RefCell<Option<Rc<crate::egl::GlConnection>>>,
|
pub(crate) gl_connection: RefCell<Option<Rc<crate::egl::GlConnection>>>,
|
||||||
pub(crate) pointer: PointerDispatcher,
|
pub(crate) pointer: PointerDispatcher,
|
||||||
pub(crate) keyboard: KeyboardDispatcher,
|
pub(crate) keyboard: KeyboardDispatcher,
|
||||||
|
seat_listener: SeatListener,
|
||||||
pub(crate) environment: RefCell<Environment<MyEnvironment>>,
|
pub(crate) environment: RefCell<Environment<MyEnvironment>>,
|
||||||
event_q: RefCell<EventLoop<()>>,
|
event_q: RefCell<EventLoop<()>>,
|
||||||
pub(crate) display: RefCell<Display>,
|
pub(crate) display: RefCell<Display>,
|
||||||
@ -52,14 +54,17 @@ impl WaylandConnection {
|
|||||||
let mut pointer = None;
|
let mut pointer = None;
|
||||||
|
|
||||||
for seat in environment.get_all_seats() {
|
for seat in environment.get_all_seats() {
|
||||||
if let Some((has_kbd, has_ptr)) = toolkit::seat::with_seat_data(&seat, |seat_data| {
|
if let Some((has_kbd, has_ptr, name)) =
|
||||||
(
|
toolkit::seat::with_seat_data(&seat, |seat_data| {
|
||||||
seat_data.has_keyboard && !seat_data.defunct,
|
(
|
||||||
seat_data.has_pointer && !seat_data.defunct,
|
seat_data.has_keyboard && !seat_data.defunct,
|
||||||
)
|
seat_data.has_pointer && !seat_data.defunct,
|
||||||
}) {
|
seat_data.name.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
{
|
||||||
if has_kbd {
|
if has_kbd {
|
||||||
keyboard.register(event_loop.handle(), &seat)?;
|
keyboard.register(event_loop.handle(), &seat, &name)?;
|
||||||
}
|
}
|
||||||
if has_ptr {
|
if has_ptr {
|
||||||
pointer.replace(PointerDispatcher::register(
|
pointer.replace(PointerDispatcher::register(
|
||||||
@ -72,6 +77,36 @@ impl WaylandConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let seat_listener;
|
||||||
|
{
|
||||||
|
let loop_handle = event_loop.handle();
|
||||||
|
let keyboard = keyboard.clone();
|
||||||
|
seat_listener = environment.listen_for_seats(move |seat, seat_data, _| {
|
||||||
|
if seat_data.has_keyboard {
|
||||||
|
if seat_data.defunct {
|
||||||
|
keyboard.deregister(loop_handle.clone(), &seat_data.name);
|
||||||
|
} else {
|
||||||
|
if let Err(err) =
|
||||||
|
keyboard.register(loop_handle.clone(), &seat, &seat_data.name)
|
||||||
|
{
|
||||||
|
log::error!("{:#}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if seat_data.has_pointer {
|
||||||
|
// TODO: ideally do something similar to the keyboard state,
|
||||||
|
// but the pointer state has a lot of other stuff floating
|
||||||
|
// around it so it's not so clear cut right now.
|
||||||
|
log::error!(
|
||||||
|
"seat {} changed; it has a pointer that is
|
||||||
|
defunct={} and we don't know what to do about it",
|
||||||
|
seat_data.name,
|
||||||
|
seat_data.defunct
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
WaylandSource::new(event_q)
|
WaylandSource::new(event_q)
|
||||||
.quick_insert(event_loop.handle())
|
.quick_insert(event_loop.handle())
|
||||||
.map_err(|e| anyhow!("failed to setup WaylandSource: {:?}", e))?;
|
.map_err(|e| anyhow!("failed to setup WaylandSource: {:?}", e))?;
|
||||||
@ -86,6 +121,7 @@ impl WaylandConnection {
|
|||||||
windows: RefCell::new(HashMap::new()),
|
windows: RefCell::new(HashMap::new()),
|
||||||
keyboard,
|
keyboard,
|
||||||
pointer: pointer.unwrap(),
|
pointer: pointer.unwrap(),
|
||||||
|
seat_listener,
|
||||||
gl_connection: RefCell::new(None),
|
gl_connection: RefCell::new(None),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@ use anyhow::anyhow;
|
|||||||
use smithay_client_toolkit as toolkit;
|
use smithay_client_toolkit as toolkit;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use toolkit::reexports::calloop::LoopHandle;
|
use toolkit::reexports::calloop::{LoopHandle, Source};
|
||||||
use toolkit::seat::keyboard::{
|
use toolkit::seat::keyboard::{
|
||||||
map_keyboard_repeat, Event as KbEvent, KeyState, ModifiersState, RepeatKind,
|
map_keyboard_repeat, Event as KbEvent, KeyState, ModifiersState, RepeatKind, RepeatSource,
|
||||||
};
|
};
|
||||||
|
use wayland_client::protocol::wl_keyboard::WlKeyboard;
|
||||||
use wayland_client::protocol::wl_seat::WlSeat;
|
use wayland_client::protocol::wl_seat::WlSeat;
|
||||||
use wayland_client::protocol::wl_surface::WlSurface;
|
use wayland_client::protocol::wl_surface::WlSurface;
|
||||||
use wayland_client::Attached;
|
use wayland_client::Attached;
|
||||||
@ -16,6 +17,7 @@ use wezterm_input_types::*;
|
|||||||
struct Inner {
|
struct Inner {
|
||||||
active_surface_id: u32,
|
active_surface_id: u32,
|
||||||
surface_to_window_id: HashMap<u32, usize>,
|
surface_to_window_id: HashMap<u32, usize>,
|
||||||
|
by_name: HashMap<String, (WlKeyboard, Source<RepeatSource>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inner {
|
impl Inner {
|
||||||
@ -64,9 +66,10 @@ impl KeyboardDispatcher {
|
|||||||
&self,
|
&self,
|
||||||
loop_handle: LoopHandle<()>,
|
loop_handle: LoopHandle<()>,
|
||||||
seat: &Attached<WlSeat>,
|
seat: &Attached<WlSeat>,
|
||||||
|
name: &str,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let inner = Arc::clone(&self.inner);
|
let inner = Arc::clone(&self.inner);
|
||||||
let (_kbd, _source) = map_keyboard_repeat(
|
let pair = map_keyboard_repeat(
|
||||||
loop_handle,
|
loop_handle,
|
||||||
&seat,
|
&seat,
|
||||||
None,
|
None,
|
||||||
@ -90,9 +93,22 @@ impl KeyboardDispatcher {
|
|||||||
)
|
)
|
||||||
.map_err(|e| anyhow!("Failed to configure keyboard callback: {:?}", e))?;
|
.map_err(|e| anyhow!("Failed to configure keyboard callback: {:?}", e))?;
|
||||||
|
|
||||||
|
self.inner
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.by_name
|
||||||
|
.insert(name.to_string(), pair);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deregister(&self, loop_handle: LoopHandle<()>, name: &str) {
|
||||||
|
if let Some((kbd, source)) = self.inner.lock().unwrap().by_name.remove(name) {
|
||||||
|
kbd.release();
|
||||||
|
loop_handle.remove(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_window(&self, window_id: usize, surface: &WlSurface) {
|
pub fn add_window(&self, window_id: usize, surface: &WlSurface) {
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
inner
|
inner
|
||||||
|
Loading…
Reference in New Issue
Block a user