From d95808c2d9f8cf100ce5739ec639239c11ed3ce1 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Fri, 15 Jul 2022 14:21:20 +0200 Subject: [PATCH] input: Always add keyboard/pointer to seat --- src/backend/mod.rs | 18 +++++++++-- src/input/mod.rs | 79 ++++++++++++++++++++++------------------------ 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 6a7b62ff..1aa7e6c4 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::state::{Data, State}; -use anyhow::Result; +use anyhow::{Context, Result}; use smithay::reexports::{calloop::EventLoop, wayland_server::DisplayHandle}; pub mod render; @@ -17,7 +17,7 @@ pub fn init_backend_auto( event_loop: &mut EventLoop<'static, Data>, state: &mut State, ) -> Result<()> { - match std::env::var("COSMIC_BACKEND") { + let res = match std::env::var("COSMIC_BACKEND") { Ok(x) if x == "x11" => x11::init_backend(dh, event_loop, state), Ok(x) if x == "winit" => winit::init_backend(dh, event_loop, state), Ok(x) if x == "kms" => kms::init_backend(dh, event_loop, state), @@ -38,5 +38,19 @@ pub fn init_backend_auto( kms::init_backend(dh, event_loop, state) } } + }; + if res.is_ok() { + for seat in &state.common.seats { + let output = state + .common + .shell + .outputs() + .next() + .with_context(|| "Backend initialized without output")? + .clone(); + seat.user_data() + .insert_if_missing(|| crate::input::ActiveOutput(std::cell::RefCell::new(output))); + } } + res } diff --git a/src/input/mod.rs b/src/input/mod.rs index d073f77d..fc10051c 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -99,13 +99,46 @@ impl Devices { } pub fn add_seat(dh: &DisplayHandle, name: String) -> Seat { - let seat = Seat::::new(dh, name, None); + let mut seat = Seat::::new(dh, name, None); let userdata = seat.user_data(); userdata.insert_if_missing(SeatId::default); userdata.insert_if_missing(Devices::default); userdata.insert_if_missing(SupressedKeys::default); userdata.insert_if_missing(SeatMoveGrabState::default); userdata.insert_if_missing(|| RefCell::new(CursorImageStatus::Default)); + + // A lot of clients bind keyboard and pointer unconditionally once on launch.. + // Initial clients might race the compositor on adding periheral and + // end up in a state, where they are not able to receive input. + // Additionally a lot of clients don't handle keyboards/pointer objects being + // removed very well either and we don't want to crash applications, because the + // user is replugging their keyboard or mouse. + // + // So instead of doing the right thing (and initialize these capabilities as matching + // devices appear), we have to surrender to reality and just always expose a keyboard and pointer. + let dh_clone = dh.clone(); + let _ = seat.add_keyboard( + XkbConfig::default(), + 200, + 25, + move |seat, focus| { + if let Some(client) = + focus.and_then(|s| dh_clone.get_client(s.id()).ok()) + { + set_data_device_focus(&dh_clone, seat, Some(client)); + } + }, + ); + + let owned_seat = seat.clone(); + seat.add_pointer(move |status| { + *owned_seat + .user_data() + .get::>() + .unwrap() + .borrow_mut() = status; + }); + seat } @@ -124,40 +157,7 @@ impl State { let devices = userdata.get::().unwrap(); for cap in devices.add_device(&device) { match cap { - DeviceCapability::Keyboard => { - let dh_clone = dh.clone(); - let _ = seat.add_keyboard( - XkbConfig::default(), - 200, - 25, - move |seat, focus| { - if let Some(client) = - focus.and_then(|s| dh_clone.get_client(s.id()).ok()) - { - set_data_device_focus(&dh_clone, seat, Some(client)) - } - }, - ); - } - DeviceCapability::Pointer => { - let output = self - .common - .shell - .outputs() - .next() - .expect("Backend initialized without output") - .clone(); - seat.user_data() - .insert_if_missing(|| ActiveOutput(RefCell::new(output))); - let owned_seat = seat.clone(); - seat.add_pointer(move |status| { - *owned_seat - .user_data() - .get::>() - .unwrap() - .borrow_mut() = status; - }); - } + // TODO: Handle touch, tablet _ => {} } } @@ -174,13 +174,8 @@ impl State { if devices.has_device(&device) { for cap in devices.remove_device(&device) { match cap { - DeviceCapability::Keyboard => { - seat.remove_keyboard(); - } - DeviceCapability::Pointer => { - seat.remove_pointer(); - } - _ => {} + // TODO: Handle touch, tablet + _ => {}, } } break;