209 lines
6.1 KiB
Rust
209 lines
6.1 KiB
Rust
|
|
//! Seat handling and managing.
|
||
|
|
|
||
|
|
use std::cell::RefCell;
|
||
|
|
use std::rc::Rc;
|
||
|
|
|
||
|
|
use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1;
|
||
|
|
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1;
|
||
|
|
use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3;
|
||
|
|
|
||
|
|
use sctk::reexports::client::protocol::wl_seat::WlSeat;
|
||
|
|
use sctk::reexports::client::Attached;
|
||
|
|
|
||
|
|
use sctk::environment::Environment;
|
||
|
|
use sctk::reexports::calloop::LoopHandle;
|
||
|
|
use sctk::seat::pointer::ThemeManager;
|
||
|
|
use sctk::seat::{SeatData, SeatListener};
|
||
|
|
|
||
|
|
use super::env::WinitEnv;
|
||
|
|
use super::event_loop::WinitState;
|
||
|
|
use crate::event::ModifiersState;
|
||
|
|
|
||
|
|
mod keyboard;
|
||
|
|
pub mod pointer;
|
||
|
|
pub mod text_input;
|
||
|
|
mod touch;
|
||
|
|
|
||
|
|
use keyboard::Keyboard;
|
||
|
|
use pointer::Pointers;
|
||
|
|
use text_input::TextInput;
|
||
|
|
use touch::Touch;
|
||
|
|
|
||
|
|
pub struct SeatManager {
|
||
|
|
/// Listener for seats.
|
||
|
|
_seat_listener: SeatListener,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl SeatManager {
|
||
|
|
pub fn new(
|
||
|
|
env: &Environment<WinitEnv>,
|
||
|
|
loop_handle: LoopHandle<WinitState>,
|
||
|
|
theme_manager: ThemeManager,
|
||
|
|
) -> Self {
|
||
|
|
let relative_pointer_manager = env.get_global::<ZwpRelativePointerManagerV1>();
|
||
|
|
let pointer_constraints = env.get_global::<ZwpPointerConstraintsV1>();
|
||
|
|
let text_input_manager = env.get_global::<ZwpTextInputManagerV3>();
|
||
|
|
|
||
|
|
let mut inner = SeatManagerInner::new(
|
||
|
|
theme_manager,
|
||
|
|
relative_pointer_manager,
|
||
|
|
pointer_constraints,
|
||
|
|
text_input_manager,
|
||
|
|
loop_handle,
|
||
|
|
);
|
||
|
|
|
||
|
|
// Handle existing seats.
|
||
|
|
for seat in env.get_all_seats() {
|
||
|
|
let seat_data = match sctk::seat::clone_seat_data(&seat) {
|
||
|
|
Some(seat_data) => seat_data,
|
||
|
|
None => continue,
|
||
|
|
};
|
||
|
|
|
||
|
|
inner.process_seat_update(&seat, &seat_data);
|
||
|
|
}
|
||
|
|
|
||
|
|
let seat_listener = env.listen_for_seats(move |seat, seat_data, _| {
|
||
|
|
inner.process_seat_update(&seat, &seat_data);
|
||
|
|
});
|
||
|
|
|
||
|
|
Self {
|
||
|
|
_seat_listener: seat_listener,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Inner state of the seat manager.
|
||
|
|
struct SeatManagerInner {
|
||
|
|
/// Currently observed seats.
|
||
|
|
seats: Vec<SeatInfo>,
|
||
|
|
|
||
|
|
/// Loop handle.
|
||
|
|
loop_handle: LoopHandle<WinitState>,
|
||
|
|
|
||
|
|
/// Relative pointer manager.
|
||
|
|
relative_pointer_manager: Option<Attached<ZwpRelativePointerManagerV1>>,
|
||
|
|
|
||
|
|
/// Pointer constraints.
|
||
|
|
pointer_constraints: Option<Attached<ZwpPointerConstraintsV1>>,
|
||
|
|
|
||
|
|
/// Text input manager.
|
||
|
|
text_input_manager: Option<Attached<ZwpTextInputManagerV3>>,
|
||
|
|
|
||
|
|
/// A theme manager.
|
||
|
|
theme_manager: ThemeManager,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl SeatManagerInner {
|
||
|
|
fn new(
|
||
|
|
theme_manager: ThemeManager,
|
||
|
|
relative_pointer_manager: Option<Attached<ZwpRelativePointerManagerV1>>,
|
||
|
|
pointer_constraints: Option<Attached<ZwpPointerConstraintsV1>>,
|
||
|
|
text_input_manager: Option<Attached<ZwpTextInputManagerV3>>,
|
||
|
|
loop_handle: LoopHandle<WinitState>,
|
||
|
|
) -> Self {
|
||
|
|
Self {
|
||
|
|
seats: Vec::new(),
|
||
|
|
loop_handle,
|
||
|
|
relative_pointer_manager,
|
||
|
|
pointer_constraints,
|
||
|
|
text_input_manager,
|
||
|
|
theme_manager,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Handle seats update from the `SeatListener`.
|
||
|
|
pub fn process_seat_update(&mut self, seat: &Attached<WlSeat>, seat_data: &SeatData) {
|
||
|
|
let detached_seat = seat.detach();
|
||
|
|
|
||
|
|
let position = self.seats.iter().position(|si| si.seat == detached_seat);
|
||
|
|
let index = position.unwrap_or_else(|| {
|
||
|
|
self.seats.push(SeatInfo::new(detached_seat));
|
||
|
|
self.seats.len() - 1
|
||
|
|
});
|
||
|
|
|
||
|
|
let seat_info = &mut self.seats[index];
|
||
|
|
|
||
|
|
// Pointer handling.
|
||
|
|
if seat_data.has_pointer && !seat_data.defunct {
|
||
|
|
if seat_info.pointer.is_none() {
|
||
|
|
seat_info.pointer = Some(Pointers::new(
|
||
|
|
&seat,
|
||
|
|
&self.theme_manager,
|
||
|
|
&self.relative_pointer_manager,
|
||
|
|
&self.pointer_constraints,
|
||
|
|
seat_info.modifiers_state.clone(),
|
||
|
|
));
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
seat_info.pointer = None;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Handle keyboard.
|
||
|
|
if seat_data.has_keyboard && !seat_data.defunct {
|
||
|
|
if seat_info.keyboard.is_none() {
|
||
|
|
seat_info.keyboard = Keyboard::new(
|
||
|
|
&seat,
|
||
|
|
self.loop_handle.clone(),
|
||
|
|
seat_info.modifiers_state.clone(),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
seat_info.keyboard = None;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Handle touch.
|
||
|
|
if seat_data.has_touch && !seat_data.defunct {
|
||
|
|
if seat_info.touch.is_none() {
|
||
|
|
seat_info.touch = Some(Touch::new(&seat));
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
seat_info.touch = None;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Handle text input.
|
||
|
|
if let Some(text_input_manager) = self.text_input_manager.as_ref() {
|
||
|
|
if seat_data.defunct {
|
||
|
|
seat_info.text_input = None;
|
||
|
|
} else if seat_info.text_input.is_none() {
|
||
|
|
seat_info.text_input = Some(TextInput::new(&seat, &text_input_manager));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Resources associtated with a given seat.
|
||
|
|
struct SeatInfo {
|
||
|
|
/// Seat to which this `SeatInfo` belongs.
|
||
|
|
seat: WlSeat,
|
||
|
|
|
||
|
|
/// A keyboard handle with its repeat rate handling.
|
||
|
|
keyboard: Option<Keyboard>,
|
||
|
|
|
||
|
|
/// All pointers we're using on a seat.
|
||
|
|
pointer: Option<Pointers>,
|
||
|
|
|
||
|
|
/// Touch handling.
|
||
|
|
touch: Option<Touch>,
|
||
|
|
|
||
|
|
/// Text input handling aka IME.
|
||
|
|
text_input: Option<TextInput>,
|
||
|
|
|
||
|
|
/// The current state of modifiers observed in keyboard handler.
|
||
|
|
///
|
||
|
|
/// We keep modifiers state on a seat, since it's being used by pointer events as well.
|
||
|
|
modifiers_state: Rc<RefCell<ModifiersState>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl SeatInfo {
|
||
|
|
pub fn new(seat: WlSeat) -> Self {
|
||
|
|
Self {
|
||
|
|
seat,
|
||
|
|
keyboard: None,
|
||
|
|
pointer: None,
|
||
|
|
touch: None,
|
||
|
|
text_input: None,
|
||
|
|
modifiers_state: Rc::new(RefCell::new(ModifiersState::default())),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|