wl-seat: split device and object handlers
This commit is contained in:
parent
054a3a919f
commit
ff04218023
4 changed files with 357 additions and 346 deletions
|
|
@ -1,9 +1,12 @@
|
|||
mod event_handling;
|
||||
mod device_handler;
|
||||
pub mod ext_transient_seat_manager_v1;
|
||||
pub mod ext_transient_seat_v1;
|
||||
mod gesture_owner;
|
||||
mod kb_owner;
|
||||
mod pointer_owner;
|
||||
mod position_hint;
|
||||
mod seat_object;
|
||||
pub mod tablet;
|
||||
pub mod text_input;
|
||||
mod touch_owner;
|
||||
|
|
@ -107,7 +110,6 @@ use {
|
|||
},
|
||||
wire_ei::EiSeatId,
|
||||
},
|
||||
CursorPositionType::Warp,
|
||||
ahash::AHashMap,
|
||||
jay_config::{
|
||||
input::FallbackOutputMode as ConfigFallbackOutputMode,
|
||||
|
|
@ -128,7 +130,12 @@ use {
|
|||
};
|
||||
pub use {
|
||||
event_handling::NodeSeatState,
|
||||
position_hint::{
|
||||
CursorPositionType, PositionHintRequest, handle_position_hint_requests,
|
||||
handle_warp_mouse_to_focus,
|
||||
},
|
||||
pointer_owner::{ToplevelSelector, WorkspaceSelector},
|
||||
seat_object::WlSeatError,
|
||||
};
|
||||
|
||||
pub const POINTER: u32 = 1;
|
||||
|
|
@ -1782,147 +1789,6 @@ pub struct WlSeat {
|
|||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
const READ_ONLY_KEYMAP_SINCE: Version = Version(7);
|
||||
|
||||
impl WlSeat {
|
||||
fn send_capabilities(self: &Rc<Self>) {
|
||||
self.client.event(Capabilities {
|
||||
self_id: self.id,
|
||||
capabilities: self.global.capabilities.get(),
|
||||
})
|
||||
}
|
||||
|
||||
fn send_name(self: &Rc<Self>, name: &str) {
|
||||
self.client.event(Name {
|
||||
self_id: self.id,
|
||||
name,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn keymap_fd(&self, state: &KeyboardState) -> Result<KeymapFd, WlKeyboardError> {
|
||||
let fd = match self.client.is_xwayland {
|
||||
true => &state.map.xwayland_map,
|
||||
_ => &state.map.map,
|
||||
};
|
||||
if self.version >= READ_ONLY_KEYMAP_SINCE {
|
||||
return Ok(fd.clone());
|
||||
}
|
||||
Ok(fd.create_unprotected_fd()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl WlSeatRequestHandler for WlSeat {
|
||||
type Error = WlSeatError;
|
||||
|
||||
fn get_pointer(&self, req: GetPointer, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let p = Rc::new(WlPointer::new(req.id, slf));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.pointers.set(req.id, p.clone());
|
||||
let surface = self
|
||||
.global
|
||||
.pointer_node()
|
||||
.and_then(|n| n.node_into_surface());
|
||||
if let Some(surface) = surface
|
||||
&& surface.client.id == self.client.id
|
||||
{
|
||||
let (x, y) = self.global.pointer_cursor.position();
|
||||
let (x_int, y_int) = surface
|
||||
.buffer_abs_pos
|
||||
.get()
|
||||
.translate(x.round_down(), y.round_down());
|
||||
p.send_enter(
|
||||
self.client.next_serial(),
|
||||
surface.id,
|
||||
x.apply_fract(x_int),
|
||||
y.apply_fract(y_int),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_keyboard(&self, req: GetKeyboard, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let p = Rc::new(WlKeyboard::new(req.id, slf));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.keyboards.set(req.id, p.clone());
|
||||
if let Some(surface) = self.global.keyboard_node.get().node_into_surface()
|
||||
&& surface.client.id == self.client.id
|
||||
{
|
||||
p.enter(
|
||||
self.client.next_serial(),
|
||||
surface.id,
|
||||
&self.global.seat_kb_state.get().borrow().kb_state,
|
||||
);
|
||||
}
|
||||
if self.version >= REPEAT_INFO_SINCE {
|
||||
let (rate, delay) = self.global.repeat_rate.get();
|
||||
p.send_repeat_info(rate, delay);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_touch(&self, req: GetTouch, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let p = Rc::new(WlTouch::new(req.id, slf));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.touches.set(req.id, p);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn release(&self, _req: Release, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
{
|
||||
let mut bindings = self.global.bindings.borrow_mut();
|
||||
if let Entry::Occupied(mut hm) = bindings.entry(self.client.id) {
|
||||
hm.get_mut().remove(&self.id);
|
||||
if hm.get().is_empty() {
|
||||
hm.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = WlSeat;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for WlSeat {
|
||||
fn break_loops(&self) {
|
||||
{
|
||||
let mut bindings = self.global.bindings.borrow_mut();
|
||||
if let Entry::Occupied(mut hm) = bindings.entry(self.client.id) {
|
||||
hm.get_mut().remove(&self.id);
|
||||
if hm.get().is_empty() {
|
||||
hm.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.pointers.clear();
|
||||
self.relative_pointers.clear();
|
||||
self.keyboards.clear();
|
||||
self.touches.clear();
|
||||
}
|
||||
}
|
||||
|
||||
dedicated_add_obj!(WlSeat, WlSeatId, seats);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WlSeatError {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error(transparent)]
|
||||
TransferError(#[from] TransferError),
|
||||
#[error(transparent)]
|
||||
WlKeyboardError(Box<WlKeyboardError>),
|
||||
#[error("Data source has a toplevel attached")]
|
||||
OfferHasDrag,
|
||||
}
|
||||
efrom!(WlSeatError, ClientError);
|
||||
efrom!(WlSeatError, WlKeyboardError);
|
||||
|
||||
pub fn collect_kb_foci2(node: Rc<dyn Node>, seats: &mut SmallVec<[Rc<WlSeatGlobal>; 3]>) {
|
||||
node.node_visit(&mut generic_node_visitor(|node| {
|
||||
|
|
@ -1935,207 +1801,3 @@ pub fn collect_kb_foci(node: Rc<dyn Node>) -> SmallVec<[Rc<WlSeatGlobal>; 3]> {
|
|||
collect_kb_foci2(node, &mut res);
|
||||
res
|
||||
}
|
||||
|
||||
impl DeviceHandlerData {
|
||||
pub fn set_seat(&self, _state: &State, seat: Option<Rc<WlSeatGlobal>>) {
|
||||
if let Some(new) = &seat {
|
||||
if let Some(old) = self.seat.get()
|
||||
&& old.id() == new.id()
|
||||
{
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if self.seat.is_none() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.destroy_physical_keyboard_state();
|
||||
let old = self.seat.set(seat.clone());
|
||||
if let Some(old) = old {
|
||||
if let Some(info) = &self.tablet_init {
|
||||
old.tablet_remove_tablet(info.id);
|
||||
}
|
||||
if let Some(info) = &self.tablet_pad_init {
|
||||
old.tablet_remove_tablet_pad(info.id);
|
||||
}
|
||||
if self.is_touch {
|
||||
old.num_touch_devices.fetch_sub(1);
|
||||
old.update_capabilities();
|
||||
}
|
||||
}
|
||||
if let Some(seat) = &seat {
|
||||
if let Some(info) = &self.tablet_init {
|
||||
seat.tablet_add_tablet(self.device.id(), info);
|
||||
}
|
||||
if let Some(info) = &self.tablet_pad_init {
|
||||
seat.tablet_add_tablet_pad(self.device.id(), info);
|
||||
}
|
||||
if self.is_touch {
|
||||
seat.num_touch_devices.fetch_add(1);
|
||||
seat.update_capabilities();
|
||||
}
|
||||
}
|
||||
self.attach_event_listeners();
|
||||
}
|
||||
|
||||
fn destroy_physical_keyboard_state(&self) {
|
||||
self.mods_listener.detach();
|
||||
if let Some(seat) = self.seat.get() {
|
||||
seat.destroy_physical_keyboard(self.keyboard_id);
|
||||
};
|
||||
}
|
||||
|
||||
fn attach_event_listeners(&self) {
|
||||
if self.is_kb
|
||||
&& let Some(seat) = self.seat.get()
|
||||
{
|
||||
seat.attach_modifiers_listener(
|
||||
self.keyboard_id,
|
||||
&self.mods_listener,
|
||||
self.keymap.get().as_ref(),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_keymap(&self, _state: &State, keymap: Option<Rc<KbvmMap>>) {
|
||||
self.destroy_physical_keyboard_state();
|
||||
self.keymap.set(keymap);
|
||||
self.attach_event_listeners();
|
||||
}
|
||||
|
||||
pub fn set_output(&self, _state: &State, output: Option<&WlOutputGlobal>) {
|
||||
match output {
|
||||
None => {
|
||||
log::info!("Removing output mapping of {}", self.device.name());
|
||||
self.output.take();
|
||||
}
|
||||
Some(o) => {
|
||||
log::info!("Mapping {} to {}", self.device.name(), o.connector.name);
|
||||
self.output.set(Some(o.opt.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_rect(&self, state: &State) -> Rect {
|
||||
if let Some(output) = self.output.get()
|
||||
&& let Some(output) = output.get()
|
||||
{
|
||||
return output.pos.get();
|
||||
}
|
||||
state.root.extents.get()
|
||||
}
|
||||
|
||||
pub fn set_accel_profile(&self, _state: &State, v: InputDeviceAccelProfile) {
|
||||
self.device.set_accel_profile(v);
|
||||
}
|
||||
|
||||
pub fn set_accel_speed(&self, _state: &State, v: f64) {
|
||||
self.device.set_accel_speed(v);
|
||||
}
|
||||
|
||||
pub fn set_tap_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_tap_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_drag_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_drag_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_drag_lock_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_drag_lock_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_left_handed(&self, _state: &State, v: bool) {
|
||||
self.device.set_left_handed(v);
|
||||
}
|
||||
|
||||
pub fn set_natural_scrolling_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_natural_scrolling_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_px_per_scroll_wheel(&self, _state: &State, v: f64) {
|
||||
self.px_per_scroll_wheel.set(v);
|
||||
}
|
||||
|
||||
pub fn set_transform_matrix(&self, _state: &State, v: TransformMatrix) {
|
||||
self.device.set_transform_matrix(v);
|
||||
}
|
||||
|
||||
pub fn set_calibration_matrix(&self, _state: &State, v: [[f32; 3]; 2]) {
|
||||
self.device.set_calibration_matrix(v);
|
||||
}
|
||||
|
||||
pub fn set_click_method(&self, _state: &State, v: InputDeviceClickMethod) {
|
||||
self.device.set_click_method(v);
|
||||
}
|
||||
|
||||
pub fn set_middle_button_emulation_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_middle_button_emulation_enabled(v);
|
||||
}
|
||||
}
|
||||
|
||||
impl LedsListener for DeviceHandlerData {
|
||||
fn leds(&self, leds: Leds) {
|
||||
self.device.set_enabled_leds(leds);
|
||||
}
|
||||
}
|
||||
|
||||
impl LedsListener for WlSeatGlobal {
|
||||
fn leds(&self, leds: Leds) {
|
||||
self.dispatch_seat_leds_listeners(leds)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PositionHintRequest {
|
||||
seat: Rc<WlSeatGlobal>,
|
||||
client_id: ClientId,
|
||||
old_pos: (Fixed, Fixed),
|
||||
new_pos: (Fixed, Fixed),
|
||||
}
|
||||
|
||||
pub async fn handle_position_hint_requests(state: Rc<State>) {
|
||||
loop {
|
||||
let req = state.position_hint_requests.pop().await;
|
||||
let (x, y) = (req.new_pos.0.round_down(), req.new_pos.1.round_down());
|
||||
if state.node_at(x, y).node.node_client_id() != Some(req.client_id) {
|
||||
continue;
|
||||
}
|
||||
let current_pos = req.seat.pointer_cursor.position();
|
||||
let (x, y) = (
|
||||
req.new_pos.0 + (current_pos.0 - req.old_pos.0),
|
||||
req.new_pos.1 + (current_pos.1 - req.old_pos.1),
|
||||
);
|
||||
req.seat.motion_event_abs(state.now_usec(), x, y, Warp);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_warp_mouse_to_focus(state: Rc<State>) {
|
||||
loop {
|
||||
state.pending_warp_mouse_to_focus.non_empty().await;
|
||||
state.eng.yield_now().await;
|
||||
while let Some(seat) = state.pending_warp_mouse_to_focus.try_pop() {
|
||||
seat.warp_mouse_to_focus_scheduled.set(false);
|
||||
let skip_target_check = seat.warp_mouse_to_focus_skip_target_check.take();
|
||||
let Some(tl) = seat.keyboard_node.get().node_toplevel() else {
|
||||
continue;
|
||||
};
|
||||
let (x, y) = tl.node_absolute_position().center();
|
||||
if !skip_target_check {
|
||||
let Some(target) = state.node_at(x, y).node.node_toplevel() else {
|
||||
continue;
|
||||
};
|
||||
if target.node_id() != tl.node_id() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (x, y) = (Fixed::from_int(x), Fixed::from_int(y));
|
||||
seat.motion_event_abs(state.now_usec(), x, y, Warp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum CursorPositionType {
|
||||
Motion,
|
||||
Warp,
|
||||
}
|
||||
|
|
|
|||
151
src/ifs/wl_seat/device_handler.rs
Normal file
151
src/ifs/wl_seat/device_handler.rs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
use super::*;
|
||||
|
||||
impl DeviceHandlerData {
|
||||
pub fn set_seat(&self, _state: &State, seat: Option<Rc<WlSeatGlobal>>) {
|
||||
if let Some(new) = &seat {
|
||||
if let Some(old) = self.seat.get()
|
||||
&& old.id() == new.id()
|
||||
{
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if self.seat.is_none() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.destroy_physical_keyboard_state();
|
||||
let old = self.seat.set(seat.clone());
|
||||
if let Some(old) = old {
|
||||
if let Some(info) = &self.tablet_init {
|
||||
old.tablet_remove_tablet(info.id);
|
||||
}
|
||||
if let Some(info) = &self.tablet_pad_init {
|
||||
old.tablet_remove_tablet_pad(info.id);
|
||||
}
|
||||
if self.is_touch {
|
||||
old.num_touch_devices.fetch_sub(1);
|
||||
old.update_capabilities();
|
||||
}
|
||||
}
|
||||
if let Some(seat) = &seat {
|
||||
if let Some(info) = &self.tablet_init {
|
||||
seat.tablet_add_tablet(self.device.id(), info);
|
||||
}
|
||||
if let Some(info) = &self.tablet_pad_init {
|
||||
seat.tablet_add_tablet_pad(self.device.id(), info);
|
||||
}
|
||||
if self.is_touch {
|
||||
seat.num_touch_devices.fetch_add(1);
|
||||
seat.update_capabilities();
|
||||
}
|
||||
}
|
||||
self.attach_event_listeners();
|
||||
}
|
||||
|
||||
fn destroy_physical_keyboard_state(&self) {
|
||||
self.mods_listener.detach();
|
||||
if let Some(seat) = self.seat.get() {
|
||||
seat.destroy_physical_keyboard(self.keyboard_id);
|
||||
};
|
||||
}
|
||||
|
||||
fn attach_event_listeners(&self) {
|
||||
if self.is_kb
|
||||
&& let Some(seat) = self.seat.get()
|
||||
{
|
||||
seat.attach_modifiers_listener(
|
||||
self.keyboard_id,
|
||||
&self.mods_listener,
|
||||
self.keymap.get().as_ref(),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_keymap(&self, _state: &State, keymap: Option<Rc<KbvmMap>>) {
|
||||
self.destroy_physical_keyboard_state();
|
||||
self.keymap.set(keymap);
|
||||
self.attach_event_listeners();
|
||||
}
|
||||
|
||||
pub fn set_output(&self, _state: &State, output: Option<&WlOutputGlobal>) {
|
||||
match output {
|
||||
None => {
|
||||
log::info!("Removing output mapping of {}", self.device.name());
|
||||
self.output.take();
|
||||
}
|
||||
Some(o) => {
|
||||
log::info!("Mapping {} to {}", self.device.name(), o.connector.name);
|
||||
self.output.set(Some(o.opt.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_rect(&self, state: &State) -> Rect {
|
||||
if let Some(output) = self.output.get()
|
||||
&& let Some(output) = output.get()
|
||||
{
|
||||
return output.pos.get();
|
||||
}
|
||||
state.root.extents.get()
|
||||
}
|
||||
|
||||
pub fn set_accel_profile(&self, _state: &State, v: InputDeviceAccelProfile) {
|
||||
self.device.set_accel_profile(v);
|
||||
}
|
||||
|
||||
pub fn set_accel_speed(&self, _state: &State, v: f64) {
|
||||
self.device.set_accel_speed(v);
|
||||
}
|
||||
|
||||
pub fn set_tap_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_tap_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_drag_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_drag_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_drag_lock_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_drag_lock_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_left_handed(&self, _state: &State, v: bool) {
|
||||
self.device.set_left_handed(v);
|
||||
}
|
||||
|
||||
pub fn set_natural_scrolling_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_natural_scrolling_enabled(v);
|
||||
}
|
||||
|
||||
pub fn set_px_per_scroll_wheel(&self, _state: &State, v: f64) {
|
||||
self.px_per_scroll_wheel.set(v);
|
||||
}
|
||||
|
||||
pub fn set_transform_matrix(&self, _state: &State, v: TransformMatrix) {
|
||||
self.device.set_transform_matrix(v);
|
||||
}
|
||||
|
||||
pub fn set_calibration_matrix(&self, _state: &State, v: [[f32; 3]; 2]) {
|
||||
self.device.set_calibration_matrix(v);
|
||||
}
|
||||
|
||||
pub fn set_click_method(&self, _state: &State, v: InputDeviceClickMethod) {
|
||||
self.device.set_click_method(v);
|
||||
}
|
||||
|
||||
pub fn set_middle_button_emulation_enabled(&self, _state: &State, v: bool) {
|
||||
self.device.set_middle_button_emulation_enabled(v);
|
||||
}
|
||||
}
|
||||
|
||||
impl LedsListener for DeviceHandlerData {
|
||||
fn leds(&self, leds: Leds) {
|
||||
self.device.set_enabled_leds(leds);
|
||||
}
|
||||
}
|
||||
|
||||
impl LedsListener for WlSeatGlobal {
|
||||
fn leds(&self, leds: Leds) {
|
||||
self.dispatch_seat_leds_listeners(leds)
|
||||
}
|
||||
}
|
||||
55
src/ifs/wl_seat/position_hint.rs
Normal file
55
src/ifs/wl_seat/position_hint.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use {super::*, CursorPositionType::Warp};
|
||||
|
||||
pub struct PositionHintRequest {
|
||||
pub(super) seat: Rc<WlSeatGlobal>,
|
||||
pub(super) client_id: ClientId,
|
||||
pub(super) old_pos: (Fixed, Fixed),
|
||||
pub(super) new_pos: (Fixed, Fixed),
|
||||
}
|
||||
|
||||
pub async fn handle_position_hint_requests(state: Rc<State>) {
|
||||
loop {
|
||||
let req = state.position_hint_requests.pop().await;
|
||||
let (x, y) = (req.new_pos.0.round_down(), req.new_pos.1.round_down());
|
||||
if state.node_at(x, y).node.node_client_id() != Some(req.client_id) {
|
||||
continue;
|
||||
}
|
||||
let current_pos = req.seat.pointer_cursor.position();
|
||||
let (x, y) = (
|
||||
req.new_pos.0 + (current_pos.0 - req.old_pos.0),
|
||||
req.new_pos.1 + (current_pos.1 - req.old_pos.1),
|
||||
);
|
||||
req.seat.motion_event_abs(state.now_usec(), x, y, Warp);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_warp_mouse_to_focus(state: Rc<State>) {
|
||||
loop {
|
||||
state.pending_warp_mouse_to_focus.non_empty().await;
|
||||
state.eng.yield_now().await;
|
||||
while let Some(seat) = state.pending_warp_mouse_to_focus.try_pop() {
|
||||
seat.warp_mouse_to_focus_scheduled.set(false);
|
||||
let skip_target_check = seat.warp_mouse_to_focus_skip_target_check.take();
|
||||
let Some(tl) = seat.keyboard_node.get().node_toplevel() else {
|
||||
continue;
|
||||
};
|
||||
let (x, y) = tl.node_absolute_position().center();
|
||||
if !skip_target_check {
|
||||
let Some(target) = state.node_at(x, y).node.node_toplevel() else {
|
||||
continue;
|
||||
};
|
||||
if target.node_id() != tl.node_id() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (x, y) = (Fixed::from_int(x), Fixed::from_int(y));
|
||||
seat.motion_event_abs(state.now_usec(), x, y, Warp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum CursorPositionType {
|
||||
Motion,
|
||||
Warp,
|
||||
}
|
||||
143
src/ifs/wl_seat/seat_object.rs
Normal file
143
src/ifs/wl_seat/seat_object.rs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
use super::*;
|
||||
|
||||
const READ_ONLY_KEYMAP_SINCE: Version = Version(7);
|
||||
|
||||
impl WlSeat {
|
||||
pub(super) fn send_capabilities(self: &Rc<Self>) {
|
||||
self.client.event(Capabilities {
|
||||
self_id: self.id,
|
||||
capabilities: self.global.capabilities.get(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn send_name(self: &Rc<Self>, name: &str) {
|
||||
self.client.event(Name {
|
||||
self_id: self.id,
|
||||
name,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn keymap_fd(&self, state: &KeyboardState) -> Result<KeymapFd, WlKeyboardError> {
|
||||
let fd = match self.client.is_xwayland {
|
||||
true => &state.map.xwayland_map,
|
||||
_ => &state.map.map,
|
||||
};
|
||||
if self.version >= READ_ONLY_KEYMAP_SINCE {
|
||||
return Ok(fd.clone());
|
||||
}
|
||||
Ok(fd.create_unprotected_fd()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl WlSeatRequestHandler for WlSeat {
|
||||
type Error = WlSeatError;
|
||||
|
||||
fn get_pointer(&self, req: GetPointer, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let p = Rc::new(WlPointer::new(req.id, slf));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.pointers.set(req.id, p.clone());
|
||||
let surface = self
|
||||
.global
|
||||
.pointer_node()
|
||||
.and_then(|n| n.node_into_surface());
|
||||
if let Some(surface) = surface
|
||||
&& surface.client.id == self.client.id
|
||||
{
|
||||
let (x, y) = self.global.pointer_cursor.position();
|
||||
let (x_int, y_int) = surface
|
||||
.buffer_abs_pos
|
||||
.get()
|
||||
.translate(x.round_down(), y.round_down());
|
||||
p.send_enter(
|
||||
self.client.next_serial(),
|
||||
surface.id,
|
||||
x.apply_fract(x_int),
|
||||
y.apply_fract(y_int),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_keyboard(&self, req: GetKeyboard, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let p = Rc::new(WlKeyboard::new(req.id, slf));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.keyboards.set(req.id, p.clone());
|
||||
if let Some(surface) = self.global.keyboard_node.get().node_into_surface()
|
||||
&& surface.client.id == self.client.id
|
||||
{
|
||||
p.enter(
|
||||
self.client.next_serial(),
|
||||
surface.id,
|
||||
&self.global.seat_kb_state.get().borrow().kb_state,
|
||||
);
|
||||
}
|
||||
if self.version >= REPEAT_INFO_SINCE {
|
||||
let (rate, delay) = self.global.repeat_rate.get();
|
||||
p.send_repeat_info(rate, delay);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_touch(&self, req: GetTouch, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let p = Rc::new(WlTouch::new(req.id, slf));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.touches.set(req.id, p);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn release(&self, _req: Release, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
{
|
||||
let mut bindings = self.global.bindings.borrow_mut();
|
||||
if let Entry::Occupied(mut hm) = bindings.entry(self.client.id) {
|
||||
hm.get_mut().remove(&self.id);
|
||||
if hm.get().is_empty() {
|
||||
hm.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = WlSeat;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for WlSeat {
|
||||
fn break_loops(&self) {
|
||||
{
|
||||
let mut bindings = self.global.bindings.borrow_mut();
|
||||
if let Entry::Occupied(mut hm) = bindings.entry(self.client.id) {
|
||||
hm.get_mut().remove(&self.id);
|
||||
if hm.get().is_empty() {
|
||||
hm.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.pointers.clear();
|
||||
self.relative_pointers.clear();
|
||||
self.keyboards.clear();
|
||||
self.touches.clear();
|
||||
}
|
||||
}
|
||||
|
||||
dedicated_add_obj!(WlSeat, WlSeatId, seats);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WlSeatError {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error(transparent)]
|
||||
TransferError(#[from] TransferError),
|
||||
#[error(transparent)]
|
||||
WlKeyboardError(Box<WlKeyboardError>),
|
||||
#[error("Data source has a toplevel attached")]
|
||||
OfferHasDrag,
|
||||
}
|
||||
efrom!(WlSeatError, ClientError);
|
||||
efrom!(WlSeatError, WlKeyboardError);
|
||||
Loading…
Add table
Add a link
Reference in a new issue