1use std::borrow::Cow;
2use std::collections::{HashMap, HashSet};
3use std::fmt;
4use std::sync::mpsc::{self, Receiver, Sender};
5use std::sync::{Arc, Mutex, MutexGuard, PoisonError, RwLock, Weak};
6use std::thread::{self, JoinHandle};
7use std::time::{Duration, Instant};
8
9use crate::backend::{
10 Backend, Command, Input, InputKinds, LOCKED, LockSlot, Sign, Signal, UNLOCKED, Usage,
11};
12use crate::capability::{Action, Axis, Button, Direction, Execution, Quirk, Snapshot};
13use crate::click::{Click, ClickTiming, Holds, Timing};
14use crate::error::{Error, Result};
15use crate::event::{
16 DropSource, Event, EventKinds, Events, Listeners, QUEUE_CAPACITY, Queue, Stamp,
17};
18use crate::key::{Key, MediaKey};
19
20const SHUTDOWN_DEADLINE: Duration = Duration::from_secs(1);
22const MERGE: Duration = Duration::from_secs(1);
24
25pub struct Device {
28 core: Arc<Core>,
29 link: Mutex<Option<(JoinHandle<()>, Receiver<()>)>>,
30 closed: Mutex<bool>,
32}
33
34struct Core {
35 backend: Box<dyn Backend>,
36 snapshot: RwLock<Arc<Snapshot>>,
37 output: Mutex<Output>,
38 receivers: Mutex<Receivers>,
39 click_timing: ClickTiming,
40 holds: Mutex<Holds>,
41 opened: Instant,
42 signals: Sender<Signal>,
43 port: String,
44 refused: Mutex<Refusals>,
46}
47
48#[derive(Default)]
51struct Refusals {
52 last: HashMap<Action, (Instant, u64)>,
53 sent: u64,
54}
55
56impl Refusals {
57 fn note(&mut self, action: Action, at: Instant) {
58 self.sent += 1;
59 self.last.insert(action, (at, self.sent));
60 }
61}
62
63struct Output {
65 held: HashSet<Usage>,
66 unsure: HashSet<Usage>,
70 locked: HashMap<LockSlot, i16>,
73 link_up: bool,
74 closing: bool,
76 session: u64,
79}
80
81struct Receivers {
82 next_id: u64,
83 entries: Vec<Entry>,
84}
85
86struct Entry {
88 id: u64,
89 kinds: EventKinds,
90 queue: Weak<Queue>,
91}
92
93impl Receivers {
94 fn union(&self) -> EventKinds {
96 self.entries
97 .iter()
98 .fold(EventKinds::NONE, |all, entry| all | entry.kinds)
99 }
100}
101
102pub(crate) struct Start {
103 pub(crate) backend: Box<dyn Backend>,
104 pub(crate) snapshot: Snapshot,
105 pub(crate) signals: Sender<Signal>,
106 pub(crate) incoming: Receiver<Signal>,
107 pub(crate) click_timing: ClickTiming,
108 pub(crate) holds: Holds,
109 pub(crate) port: String,
110}
111
112impl Device {
113 pub(crate) fn start(start: Start) -> Result<Self> {
114 let core = Arc::new(Core {
115 snapshot: RwLock::new(prepare(start.snapshot, start.click_timing, &start.port)),
116 backend: start.backend,
117 output: Mutex::new(Output {
118 held: HashSet::new(),
119 locked: HashMap::new(),
120 unsure: HashSet::new(),
121 link_up: true,
122 closing: false,
123 session: 0,
124 }),
125 receivers: Mutex::new(Receivers {
126 next_id: 0,
127 entries: Vec::new(),
128 }),
129 click_timing: start.click_timing,
130 holds: Mutex::new(start.holds),
131 opened: Instant::now(),
132 signals: start.signals,
133 port: start.port.clone(),
134 refused: Mutex::new(Refusals::default()),
135 });
136 let link = spawn_link(Arc::downgrade(&core), start.incoming)?;
137 Ok(Self {
138 core,
139 link: Mutex::new(Some(link)),
140 closed: Mutex::new(false),
141 })
142 }
143
144 pub fn snapshot(&self) -> Arc<Snapshot> {
147 self.core.snapshot()
148 }
149
150 pub fn move_by(&self, dx: i16, dy: i16) -> Result<()> {
152 self.core
153 .run(Action::Move, Timing::Any, Command::Move(dx, dy))
154 }
155
156 pub fn move_now(&self, dx: i16, dy: i16) -> Result<()> {
158 self.core
159 .run(Action::MoveNow, Timing::Any, Command::MoveNow(dx, dy))
160 }
161
162 pub fn press(&self, button: Button) -> Result<()> {
163 self.core
164 .run(Action::Press, Timing::Any, Command::Press(button))
165 }
166
167 pub fn release(&self, button: Button) -> Result<()> {
168 self.core
169 .run(Action::Release, Timing::Any, Command::Release(button))
170 }
171
172 pub fn click(&self, button: Button) -> Result<()> {
174 self.click_with(button, Click::default())
175 }
176
177 pub fn click_with(&self, button: Button, click: Click) -> Result<()> {
178 self.core.tap(Usage::Button(button), click)
179 }
180
181 pub fn press_key(&self, key: Key) -> Result<()> {
183 self.core
184 .run(Action::KeyPress, Timing::Any, Command::KeyPress(key))
185 }
186
187 pub fn release_key(&self, key: Key) -> Result<()> {
188 self.core
189 .run(Action::KeyRelease, Timing::Any, Command::KeyRelease(key))
190 }
191
192 pub fn tap_key(&self, key: Key) -> Result<()> {
194 self.tap_key_with(key, Click::default())
195 }
196
197 pub fn tap_key_with(&self, key: Key, tap: Click) -> Result<()> {
198 self.core.tap(Usage::Key(key), tap)
199 }
200
201 pub fn press_media(&self, key: MediaKey) -> Result<()> {
203 self.core
204 .run(Action::MediaPress, Timing::Any, Command::MediaPress(key))
205 }
206
207 pub fn release_media(&self, key: MediaKey) -> Result<()> {
208 self.core.run(
209 Action::MediaRelease,
210 Timing::Any,
211 Command::MediaRelease(key),
212 )
213 }
214
215 pub fn tap_media(&self, key: MediaKey) -> Result<()> {
216 self.tap_media_with(key, Click::default())
217 }
218
219 pub fn tap_media_with(&self, key: MediaKey, tap: Click) -> Result<()> {
220 self.core.tap(Usage::Media(key), tap)
221 }
222
223 pub fn lock_button(&self, button: Button) -> Result<()> {
226 self.core
227 .lock(Action::LockButton, &[LockSlot::Button(button)], LOCKED)
228 }
229
230 pub fn unlock_button(&self, button: Button) -> Result<()> {
231 self.core
232 .lock(Action::LockButton, &[LockSlot::Button(button)], UNLOCKED)
233 }
234
235 pub fn lock_key(&self, key: Key) -> Result<()> {
237 self.core
238 .lock(Action::LockKey, &[LockSlot::Key(key)], LOCKED)
239 }
240
241 pub fn unlock_key(&self, key: Key) -> Result<()> {
242 self.core
243 .lock(Action::LockKey, &[LockSlot::Key(key)], UNLOCKED)
244 }
245
246 pub fn lock_axis(&self, axis: Axis, direction: Direction) -> Result<()> {
249 self.core
250 .lock(Action::LockAxis, &slots(axis, direction), LOCKED)
251 }
252
253 pub fn unlock_axis(&self, axis: Axis, direction: Direction) -> Result<()> {
255 self.core
256 .lock(Action::LockAxis, &slots(axis, direction), UNLOCKED)
257 }
258
259 pub fn scale_axis(&self, axis: Axis, direction: Direction, percent: i16) -> Result<()> {
262 self.core
263 .lock(Action::ScaleAxis, &slots(axis, direction), percent)
264 }
265
266 pub fn wheel(&self, notches: i16) -> Result<()> {
267 self.core
268 .run(Action::Wheel, Timing::Any, Command::Wheel(notches))
269 }
270
271 pub fn pan(&self, notches: i16) -> Result<()> {
273 self.core
274 .run(Action::Pan, Timing::Any, Command::Pan(notches))
275 }
276
277 pub fn discard_pending_moves(&self) -> Result<()> {
280 self.core.run(
281 Action::DiscardPendingMoves,
282 Timing::Any,
283 Command::DiscardPendingMoves,
284 )
285 }
286
287 pub fn events(&self) -> Events {
291 self.receiver(EventKinds::ALL, false)
292 }
293
294 pub fn events_of(&self, kinds: EventKinds) -> Events {
300 self.receiver(kinds, !kinds.contains(EventKinds::ALL))
302 }
303
304 fn receiver(&self, kinds: EventKinds, report_unsupported: bool) -> Events {
305 let listeners: Weak<dyn Listeners> = Arc::downgrade(&self.core) as Weak<Core>;
306 let (queue, id) = self.core.add_receiver(kinds, report_unsupported);
307 Events::new(queue, listeners, id)
308 }
309
310 #[cfg(feature = "medius")]
325 pub fn medius(&self) -> Option<medius::Device> {
326 if lock(&self.core.output).closing {
327 return None;
328 }
329 self.core
330 .backend
331 .as_any()
332 .downcast_ref::<crate::family::medius::MediusBackend>()
333 .and_then(crate::family::medius::MediusBackend::device)
334 }
335
336 pub fn close(&self) -> Result<()> {
342 let mut closed = lock(&self.closed);
343 if *closed {
344 return Err(Error::Closed);
345 }
346 *closed = true;
347 self.shutdown()
348 }
349
350 fn shutdown(&self) -> Result<()> {
351 let released = self.core.release_everything();
352 let stopped = self.core.backend.close(SHUTDOWN_DEADLINE);
353 let _ = self.core.signals.send(Signal::Stop);
354 if let Some((handle, done)) = lock(&self.link).take() {
355 if done.recv_timeout(SHUTDOWN_DEADLINE).is_ok() {
357 let _ = handle.join();
358 }
359 }
360 self.core.close_receivers();
361 released.and(stopped)
362 }
363}
364
365impl Drop for Device {
366 fn drop(&mut self) {
367 let mut closed = lock(&self.closed);
368 if !*closed {
369 *closed = true;
370 let _ = self.shutdown();
371 }
372 }
373}
374
375impl fmt::Debug for Device {
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377 f.debug_struct("Device")
378 .field("info", &self.snapshot().info)
379 .finish_non_exhaustive()
380 }
381}
382
383fn prepare(snapshot: Snapshot, click_timing: ClickTiming, port: &str) -> Arc<Snapshot> {
384 let Snapshot {
385 mut info,
386 capabilities,
387 } = snapshot;
388 info.port = port.to_owned();
390 Arc::new(Snapshot::new(
391 info,
392 capabilities.with_host_taps(click_timing),
393 ))
394}
395
396fn keeps_locked(snapshot: &Snapshot) -> bool {
397 [Action::LockButton, Action::LockAxis, Action::LockKey]
398 .into_iter()
399 .any(|lock| {
400 snapshot
401 .capabilities
402 .get(lock)
403 .quirks
404 .contains(&Quirk::KeepsLocked)
405 })
406}
407
408fn whole_axis_only(snapshot: &Snapshot) -> bool {
409 snapshot
410 .capabilities
411 .get(Action::LockAxis)
412 .quirks
413 .contains(&Quirk::WholeAxisOnly)
414}
415
416fn other_way(slot: LockSlot) -> Option<LockSlot> {
418 match slot {
419 LockSlot::Axis(axis, Sign::Positive) => Some(LockSlot::Axis(axis, Sign::Negative)),
420 LockSlot::Axis(axis, Sign::Negative) => Some(LockSlot::Axis(axis, Sign::Positive)),
421 _ => None,
422 }
423}
424
425fn slots(axis: Axis, direction: Direction) -> Vec<LockSlot> {
427 let signs: &[Sign] = match direction {
428 Direction::Both => &[Sign::Positive, Sign::Negative],
429 Direction::Positive => &[Sign::Positive],
430 Direction::Negative => &[Sign::Negative],
431 };
432 signs
433 .iter()
434 .map(|&sign| LockSlot::Axis(axis, sign))
435 .collect()
436}
437
438fn keeps_held(snapshot: &Snapshot) -> bool {
440 [Action::Press, Action::KeyPress, Action::MediaPress]
441 .into_iter()
442 .any(|press| {
443 snapshot
444 .capabilities
445 .get(press)
446 .quirks
447 .contains(&Quirk::KeepsHeld)
448 })
449}
450
451fn max_keys_held(snapshot: &Snapshot) -> Option<u8> {
452 snapshot
453 .capabilities
454 .get(Action::KeyPress)
455 .quirks
456 .iter()
457 .find_map(|quirk| match quirk {
458 Quirk::MaxKeysHeld(max) => Some(*max),
459 _ => None,
460 })
461}
462
463fn tap_actions(usage: Usage) -> (Action, Action, Action) {
465 match usage {
466 Usage::Button(_) => (Action::Click, Action::Press, Action::Release),
467 Usage::Key(_) => (Action::KeyTap, Action::KeyPress, Action::KeyRelease),
468 Usage::Media(_) => (Action::MediaTap, Action::MediaPress, Action::MediaRelease),
469 }
470}
471
472fn lock<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
473 mutex.lock().unwrap_or_else(PoisonError::into_inner)
474}
475
476fn stream_kinds(snapshot: &Snapshot) -> InputKinds {
477 let capabilities = &snapshot.capabilities;
478 InputKinds {
479 buttons: capabilities.get(Action::ButtonEvents).is_supported(),
480 motion: capabilities.get(Action::MotionEvents).is_supported(),
481 keys: capabilities.get(Action::KeyEvents).is_supported(),
482 media: capabilities.get(Action::MediaEvents).is_supported(),
483 }
484}
485
486impl Core {
487 fn snapshot(&self) -> Arc<Snapshot> {
488 self.snapshot
489 .read()
490 .unwrap_or_else(PoisonError::into_inner)
491 .clone()
492 }
493
494 fn unsupported(
495 snapshot: &Snapshot,
496 action: Action,
497 reason: impl Into<Cow<'static, str>>,
498 ) -> Error {
499 Error::Unsupported {
500 action,
501 family: snapshot.info.family,
502 reason: reason.into(),
503 }
504 }
505
506 fn gate(snapshot: &Snapshot, action: Action, timing: Timing, command: Command) -> Result<()> {
509 let capability = snapshot.capabilities.get(action);
510 match &capability.execution {
511 Execution::Unsupported { reason } => {
512 return Err(Self::unsupported(snapshot, action, reason.clone()));
513 }
514 Execution::Host if timing == Timing::NativeOnly => {
515 return Err(Self::unsupported(
516 snapshot,
517 action,
518 "the box can't do it by itself and you asked for native timing only",
519 ));
520 }
521 _ => {}
522 }
523 match command {
524 Command::Press(button) | Command::Release(button) | Command::Click { button, .. }
525 if !snapshot.capabilities.buttons().contains(&button) =>
526 {
527 Err(Error::InvalidArgument {
528 action,
529 detail: format!("the box has no {button} button").into(),
530 })
531 }
532 Command::KeyPress(key) | Command::KeyRelease(key) | Command::KeyTap { key, .. }
533 if !key.is_valid() =>
534 {
535 Err(Error::InvalidArgument {
536 action,
537 detail: format!("{key} isn't a key, keys go from 0x04 to 0xE7").into(),
538 })
539 }
540 Command::MediaPress(key)
541 | Command::MediaRelease(key)
542 | Command::MediaTap { key, .. }
543 if key.0 == 0 =>
544 {
545 Err(Error::InvalidArgument {
546 action,
547 detail: "media key 0 isn't a key".into(),
548 })
549 }
550 Command::Click {
551 hold: Some(hold), ..
552 }
553 | Command::KeyTap {
554 hold: Some(hold), ..
555 }
556 | Command::MediaTap {
557 hold: Some(hold), ..
558 } => {
559 for quirk in &capability.quirks {
560 match quirk {
561 Quirk::MaxHold(max) if hold > *max => {
562 return Err(Error::InvalidArgument {
563 action,
564 detail: format!("the box holds it down for at most {max:?}").into(),
565 });
566 }
567 _ => {}
568 }
569 }
570 Ok(())
571 }
572 Command::Wheel(notches) => {
573 for quirk in &capability.quirks {
574 if let Quirk::NotchesPerCommand(max) = quirk
575 && notches.unsigned_abs() > *max
576 {
577 return Err(Self::unsupported(
578 snapshot,
579 action,
580 match max {
581 1 => {
582 "it takes one wheel notch per command, send them one at a time"
583 .into()
584 }
585 _ => format!(
586 "it takes at most {max} wheel notches per command, so split it up"
587 ),
588 },
589 ));
590 }
591 }
592 Ok(())
593 }
594 Command::Lock { slot, keep } => {
595 let detail = match slot {
596 LockSlot::Button(button)
597 if !snapshot.capabilities.buttons().contains(&button) =>
598 {
599 Some(format!("the box has no {button} button"))
600 }
601 LockSlot::Key(key) if !key.is_valid() => {
602 Some(format!("{key} isn't a key, keys go from 0x04 to 0xE7"))
603 }
604 LockSlot::Axis(axis, _) if !snapshot.capabilities.axes().contains(&axis) => {
605 Some(format!("the box can't lock the {axis} axis"))
606 }
607 LockSlot::Button(_) | LockSlot::Key(_) | LockSlot::Axis(..)
608 if !(-255..=255).contains(&keep) =>
609 {
610 Some(format!(
611 "{keep} is out of range, a scale goes from -255 to 255"
612 ))
613 }
614 LockSlot::Button(_) | LockSlot::Key(_) | LockSlot::Axis(..) => None,
615 };
616 match detail {
617 Some(detail) => Err(Error::InvalidArgument {
618 action,
619 detail: detail.into(),
620 }),
621 None => Ok(()),
622 }
623 }
624 Command::Move(..)
625 | Command::MoveNow(..)
626 | Command::Press(_)
627 | Command::Release(_)
628 | Command::Click { hold: None, .. }
629 | Command::Pan(_)
630 | Command::DiscardPendingMoves
631 | Command::KeyPress(_)
632 | Command::KeyRelease(_)
633 | Command::KeyTap { hold: None, .. }
634 | Command::MediaPress(_)
635 | Command::MediaRelease(_)
636 | Command::MediaTap { hold: None, .. } => Ok(()),
637 }
638 }
639
640 fn check_rollover(
642 output: &Output,
643 snapshot: &Snapshot,
644 action: Action,
645 command: Command,
646 ) -> Result<()> {
647 let (Command::KeyPress(key) | Command::KeyTap { key, .. }) = command else {
648 return Ok(());
649 };
650 let Some(max) = max_keys_held(snapshot) else {
651 return Ok(());
652 };
653 if key.is_modifier() || output.held.contains(&Usage::Key(key)) {
654 return Ok(());
655 }
656 let held = output
657 .held
658 .iter()
659 .filter(|usage| matches!(usage, Usage::Key(held) if !held.is_modifier()))
660 .count();
661 if held >= usize::from(max) {
662 return Err(Self::unsupported(
663 snapshot,
664 action,
665 format!("this box holds at most {max} keys at once, let one go first"),
666 ));
667 }
668 Ok(())
669 }
670
671 fn open_output(&self) -> Result<(MutexGuard<'_, Output>, Arc<Snapshot>)> {
672 let output = lock(&self.output);
673 if output.closing {
674 return Err(Error::Closed);
675 }
676 if !output.link_up {
677 return Err(Error::Disconnected);
678 }
679 let snapshot = self.snapshot();
680 Ok((output, snapshot))
681 }
682
683 fn send_locked(
684 &self,
685 output: &mut Output,
686 snapshot: &Snapshot,
687 action: Action,
688 timing: Timing,
689 command: Command,
690 ) -> Result<()> {
691 let held = command.holds();
692 let releasing_held = matches!(held, Some((usage, false)) if output.held.contains(&usage));
695 if !releasing_held {
696 Self::gate(snapshot, action, timing, command)?;
697 }
698 Self::check_rollover(output, snapshot, action, command)?;
699 let sent = self.backend.send(command);
700 match (held, &sent) {
701 (Some((usage, true)), Ok(())) => {
704 output.held.insert(usage);
705 output.unsure.remove(&usage);
706 }
707 (Some((usage, true)), Err(Error::Disconnected)) => {
708 output.held.insert(usage);
709 output.unsure.insert(usage);
710 }
711 (Some((usage, false)), Ok(())) => {
712 output.held.remove(&usage);
713 output.unsure.remove(&usage);
714 }
715 _ => {}
716 }
717 sent
718 }
719
720 fn run(&self, action: Action, timing: Timing, command: Command) -> Result<()> {
721 let (mut output, snapshot) = self.open_output()?;
722 self.send_locked(&mut output, &snapshot, action, timing, command)
723 }
724
725 fn lock(&self, action: Action, slots: &[LockSlot], keep: i16) -> Result<()> {
728 let (mut output, snapshot) = self.open_output()?;
729 if let [slot] = *slots
732 && let Some(other) = other_way(slot)
733 && whole_axis_only(&snapshot)
734 && !(keep == UNLOCKED
735 && output.locked.contains_key(&slot)
736 && !output.locked.contains_key(&other))
737 {
738 return Err(Self::unsupported(
739 &snapshot,
740 action,
741 "it only locks a whole axis, so use Direction::Both",
742 ));
743 }
744 for &slot in slots {
745 let unlocking_held = keep == UNLOCKED && output.locked.contains_key(&slot);
746 if !unlocking_held {
747 Self::gate(&snapshot, action, Timing::Any, Command::Lock { slot, keep })?;
748 }
749 }
750 let mut first = Ok(());
751 for &slot in slots {
752 let sent = self.backend.send(Command::Lock { slot, keep });
753 if keep == UNLOCKED {
754 if sent.is_ok() {
755 output.locked.remove(&slot);
756 }
757 } else if matches!(sent, Ok(()) | Err(Error::Disconnected)) {
758 output.locked.insert(slot, keep);
761 }
762 if first.is_ok() {
763 first = sent;
764 }
765 }
766 first
767 }
768
769 fn tap(&self, usage: Usage, tap: Click) -> Result<()> {
772 let (action, press, release) = tap_actions(usage);
773 let (mut output, snapshot) = self.open_output()?;
774 let capability = snapshot.capabilities.get(action);
775 let fixed = tap.hold.is_some() && capability.quirks.contains(&Quirk::FixedClickTiming);
778 if capability.execution != Execution::Host && !fixed {
779 return self.send_locked(
780 &mut output,
781 &snapshot,
782 action,
783 tap.timing,
784 usage.tap(tap.hold),
785 );
786 }
787 if tap.timing == Timing::NativeOnly {
788 let reason = if fixed {
789 "the box's own click can't take a hold and you asked for native timing only"
790 } else {
791 "the box can't time it by itself and you asked for native timing only"
792 };
793 return Err(Self::unsupported(&snapshot, action, reason));
794 }
795 let hold = match tap.hold {
796 Some(hold) => hold,
797 None => lock(&self.holds).pick(self.click_timing).ok_or_else(|| {
798 Self::unsupported(
799 &snapshot,
800 action,
801 "the box can't time it by itself and ClickTiming is off, so give it a hold",
802 )
803 })?,
804 };
805 Self::gate(&snapshot, action, tap.timing, usage.tap(None))?;
807 Self::check_rollover(&output, &snapshot, action, usage.press())?;
808 self.send_locked(&mut output, &snapshot, press, Timing::Any, usage.press())?;
809 let session = output.session;
810 drop(output);
811 thread::sleep(hold);
812 let (mut output, snapshot) = match self.open_output() {
813 Ok(open) => open,
814 Err(error) => {
815 lock(&self.output).unsure.insert(usage);
816 return Err(error);
817 }
818 };
819 if output.session != session && !keeps_held(&snapshot) {
820 return Err(Error::Interrupted { action });
823 }
824 let released = self.send_locked(
825 &mut output,
826 &snapshot,
827 release,
828 Timing::Any,
829 usage.release(),
830 );
831 if released.is_err() {
832 output.unsure.insert(usage);
833 }
834 released
835 }
836
837 fn add_receiver(&self, kinds: EventKinds, report_unsupported: bool) -> (Arc<Queue>, u64) {
838 let output = lock(&self.output);
839 let queue = Arc::new(Queue::new(QUEUE_CAPACITY));
840 let (id, seen) = {
841 let refused = lock(&self.refused);
843 let mut receivers = lock(&self.receivers);
844 let id = receivers.next_id;
845 receivers.next_id += 1;
846 if output.closing {
847 queue.close();
848 return (queue, id);
849 }
850 receivers.entries.push(Entry {
851 id,
852 kinds,
853 queue: Arc::downgrade(&queue),
854 });
855 (id, refused.last.clone())
856 };
857 let snapshot = self.snapshot();
858 if report_unsupported {
859 let streamable = EventKinds::from_input(stream_kinds(&snapshot));
860 for (_, action) in (kinds & !streamable).each() {
861 queue.push(Event::Rejected { action, count: 1 });
862 }
863 }
864 let refused = self.apply_streams(&output, &snapshot);
865 drop(output);
866 for action in refused {
870 let event = Event::Rejected { action, count: 1 };
871 let mut merge = lock(&self.refused);
872 let last = merge.last.get(&action).copied();
873 let heard = last.map(|(_, n)| n) != seen.get(&action).map(|(_, n)| *n);
875 if !heard && EventKinds::of(&event).is_some_and(|kind| !(kinds & kind).is_empty()) {
876 queue.push(event.clone());
877 }
878 let now = Instant::now();
879 match last {
880 Some((at, n)) if now.duration_since(at) < MERGE => {
881 merge.last.insert(action, (now, n));
883 }
884 _ => {
885 merge.note(action, now);
886 self.deliver(&event, Some(id));
887 }
888 }
889 }
890 (queue, id)
891 }
892
893 fn publish(&self, event: Event) {
895 if let Event::Rejected { action, .. } = &event
899 && EventKinds::of_action(*action).is_some()
900 {
901 let now = Instant::now();
902 let mut merge = lock(&self.refused);
904 if merge
905 .last
906 .get(action)
907 .is_some_and(|(at, _)| now.duration_since(*at) < MERGE)
908 {
909 return;
910 }
911 merge.note(*action, now);
912 self.deliver(&event, None);
913 return;
914 }
915 self.deliver(&event, None);
916 }
917
918 fn deliver(&self, event: &Event, skip: Option<u64>) {
919 let kind = EventKinds::of(event);
920 let mut receivers = lock(&self.receivers);
921 receivers
922 .entries
923 .retain(|entry| match entry.queue.upgrade() {
924 Some(queue) => {
925 if Some(entry.id) != skip
926 && kind.is_none_or(|kind| !(entry.kinds & kind).is_empty())
927 {
928 queue.push(event.clone());
929 }
930 true
931 }
932 None => false,
933 });
934 }
935
936 fn publish_refused(&self, actions: Vec<Action>) {
937 for action in actions {
938 self.publish(Event::Rejected { action, count: 1 });
939 }
940 }
941
942 fn publish_to(&self, kinds: EventKinds, event: Event) {
944 let receivers = lock(&self.receivers);
945 for entry in &receivers.entries {
946 if !(entry.kinds & kinds).is_empty()
947 && let Some(queue) = entry.queue.upgrade()
948 {
949 queue.push(event.clone());
950 }
951 }
952 }
953
954 fn close_receivers(&self) {
955 for entry in lock(&self.receivers).entries.drain(..) {
956 if let Some(queue) = entry.queue.upgrade() {
957 queue.close();
958 }
959 }
960 }
961
962 fn apply_streams(&self, output: &Output, snapshot: &Snapshot) -> Vec<Action> {
967 if output.closing || !output.link_up {
968 return Vec::new();
969 }
970 let union = lock(&self.receivers).union();
971 let wanted = union & EventKinds::from_input(stream_kinds(snapshot));
972 match self.backend.set_streams(wanted.to_input()) {
973 Err(failure) if !matches!(failure.error, Error::Disconnected) => {
974 (EventKinds::from_input(failure.failed) & wanted)
975 .each()
976 .map(|(_, action)| action)
977 .collect()
978 }
979 _ => Vec::new(),
980 }
981 }
982
983 fn release_held(&self, output: &mut Output, snapshot: &Snapshot) -> bool {
987 let usages = if keeps_held(snapshot) {
988 &output.unsure
989 } else {
990 &output.held
991 };
992 let usages: Vec<Usage> = usages.iter().copied().collect();
993 let mut all_released = true;
994 for usage in usages {
995 if self.backend.send(usage.release()).is_ok() {
996 output.held.remove(&usage);
997 output.unsure.remove(&usage);
998 } else {
999 all_released = false;
1000 }
1001 }
1002 all_released
1003 }
1004
1005 fn release_everything(&self) -> Result<()> {
1006 let mut output = lock(&self.output);
1007 output.closing = true;
1008 output.link_up = false;
1009 output.unsure.clear();
1010 let held: Vec<Usage> = output.held.drain().collect();
1011 let released = if held.is_empty() {
1012 Ok(())
1013 } else {
1014 self.backend.release_all(&held)
1015 };
1016 let locked: Vec<LockSlot> = output.locked.drain().map(|(slot, _)| slot).collect();
1017 let unlocked = if locked.is_empty() {
1018 Ok(())
1019 } else {
1020 self.backend.unlock_all(&locked)
1021 };
1022 released.and(unlocked)
1023 }
1024
1025 fn relock(&self, output: &Output, snapshot: &Snapshot) {
1028 if keeps_locked(snapshot) {
1029 return;
1030 }
1031 for (&slot, &keep) in &output.locked {
1032 if whole_axis_only(snapshot)
1035 && let Some(other) = other_way(slot)
1036 && output.locked.get(&other) != Some(&keep)
1037 {
1038 continue;
1039 }
1040 let command = Command::Lock { slot, keep };
1041 if Self::gate(snapshot, command.action(), Timing::Any, command).is_ok() {
1042 let _ = self.backend.send(command);
1043 }
1044 }
1045 }
1046
1047 fn handle(&self, signal: Signal) {
1048 match signal {
1049 Signal::Input {
1050 input,
1051 arrived,
1052 box_time,
1053 read,
1054 } => {
1055 let mut at = Stamp::new(arrived, arrived.saturating_duration_since(self.opened));
1056 at.box_time = box_time;
1057 if let Some(read) = read {
1058 at.received = read.at;
1059 at.received_since_open = read.at.saturating_duration_since(self.opened);
1060 at.received_qpc = read.qpc;
1061 }
1062 self.publish(match input {
1063 Input::Button { button, pressed } => Event::Button {
1064 button,
1065 pressed,
1066 at,
1067 },
1068 Input::Motion { dx, dy, wheel, pan } => Event::Motion {
1069 dx,
1070 dy,
1071 wheel,
1072 pan,
1073 at,
1074 },
1075 Input::Key { key, pressed } => Event::Key { key, pressed, at },
1076 Input::Media { key, pressed } => Event::Media { key, pressed, at },
1077 });
1078 }
1079 Signal::Dropped(count, source, kind) => match kind {
1080 Some(kind) => self.publish_to(
1081 EventKinds::from_input(kind.kinds()),
1082 Event::Dropped { count, source },
1083 ),
1084 None => self.publish(Event::Dropped { count, source }),
1085 },
1086 Signal::StreamLost(kind) => {
1087 let output = lock(&self.output);
1088 if output.closing {
1089 return;
1090 }
1091 let lost = EventKinds::from_input(kind.kinds());
1092 self.publish_to(
1095 lost,
1096 Event::Dropped {
1097 count: 1,
1098 source: DropSource::Device,
1099 },
1100 );
1101 if output.link_up && lock(&self.receivers).union().contains(lost) {
1104 let restarted = self.backend.restart_stream(kind);
1105 drop(output);
1106 if let Err(error) = restarted
1107 && !matches!(error, Error::Disconnected)
1108 {
1109 for (_, action) in lost.each() {
1110 self.publish(Event::Rejected { action, count: 1 });
1111 }
1112 }
1113 }
1114 }
1115 Signal::Refused(action) => self.publish(Event::Rejected { action, count: 1 }),
1116 Signal::Disconnected => {
1117 let mut output = lock(&self.output);
1118 if output.closing {
1119 return;
1120 }
1121 let was_up = output.link_up;
1123 output.link_up = false;
1124 output.session += 1;
1125 drop(output);
1126 if was_up {
1127 self.publish(Event::Disconnected);
1128 }
1129 }
1130 Signal::Reconnected(snapshot) => {
1131 let mut output = lock(&self.output);
1132 if output.closing {
1133 return;
1134 }
1135 output.session += 1;
1136 let snapshot = prepare(*snapshot, self.click_timing, &self.port);
1137 *self
1138 .snapshot
1139 .write()
1140 .unwrap_or_else(PoisonError::into_inner) = snapshot.clone();
1141 if !self.release_held(&mut output, &snapshot) {
1142 let was_up = output.link_up;
1145 output.link_up = false;
1146 drop(output);
1147 if was_up {
1148 self.publish(Event::Disconnected);
1149 }
1150 return;
1151 }
1152 self.relock(&output, &snapshot);
1153 output.link_up = true;
1154 let refused = self.apply_streams(&output, &snapshot);
1155 drop(output);
1156 self.publish(Event::Reconnected);
1157 self.publish_refused(refused);
1158 }
1159 Signal::Changed(snapshot) => {
1160 let output = lock(&self.output);
1161 if output.closing {
1162 return;
1163 }
1164 let snapshot = prepare(*snapshot, self.click_timing, &self.port);
1165 let changed = {
1166 let mut current = self
1167 .snapshot
1168 .write()
1169 .unwrap_or_else(PoisonError::into_inner);
1170 let changed = *current != snapshot;
1172 *current = snapshot.clone();
1173 changed
1174 };
1175 let refused = self.apply_streams(&output, &snapshot);
1177 drop(output);
1178 if changed {
1179 self.publish(Event::Changed);
1180 }
1181 self.publish_refused(refused);
1182 }
1183 Signal::SessionReset => {
1184 let mut output = lock(&self.output);
1185 if output.closing {
1186 return;
1187 }
1188 output.session += 1;
1189 let snapshot = self.snapshot();
1190 self.release_held(&mut output, &snapshot);
1191 self.relock(&output, &snapshot);
1192 let refused = self.apply_streams(&output, &snapshot);
1193 drop(output);
1194 self.publish(Event::SessionReset);
1195 self.publish_refused(refused);
1196 }
1197 #[cfg(test)]
1198 Signal::Barrier(done) => {
1199 let _ = done.send(());
1200 }
1201 #[cfg(feature = "mock")]
1202 Signal::Examples(events) => {
1203 for event in events {
1204 self.publish(event);
1205 }
1206 }
1207 Signal::Stop => {}
1208 }
1209 }
1210}
1211
1212impl Listeners for Core {
1213 fn receiver_dropped(&self, id: u64) {
1214 let output = lock(&self.output);
1215 lock(&self.receivers).entries.retain(|entry| entry.id != id);
1216 let refused = self.apply_streams(&output, &self.snapshot());
1217 drop(output);
1218 self.publish_refused(refused);
1219 }
1220}
1221
1222fn spawn_link(
1223 core: Weak<Core>,
1224 incoming: Receiver<Signal>,
1225) -> Result<(JoinHandle<()>, Receiver<()>)> {
1226 let (done, finished) = mpsc::channel();
1227 let handle = thread::Builder::new()
1228 .name("anybox-link".into())
1229 .spawn(move || {
1230 while let Ok(signal) = incoming.recv() {
1231 if matches!(signal, Signal::Stop) {
1232 break;
1233 }
1234 match core.upgrade() {
1235 Some(core) => core.handle(signal),
1236 None => break,
1237 }
1238 }
1239 let _ = done.send(());
1240 })?;
1241 Ok((handle, finished))
1242}
1243
1244#[cfg(feature = "mock")]
1245impl Device {
1246 pub fn mock_example_events(&self) {
1249 let now = Instant::now();
1250 let at = Stamp::new(now, now.saturating_duration_since(self.core.opened));
1251 let _ = self
1252 .core
1253 .signals
1254 .send(Signal::Examples(Event::examples(at)));
1255 }
1256}
1257
1258#[cfg(test)]
1259impl Device {
1260 pub(crate) fn start_closing(&self) {
1262 let _ = self.core.release_everything();
1263 }
1264
1265 pub(crate) fn backend_for_tests(&self) -> &dyn std::any::Any {
1266 self.core.backend.as_any()
1267 }
1268
1269 pub(crate) fn held(&self) -> HashSet<Usage> {
1270 lock(&self.core.output).held.clone()
1271 }
1272
1273 pub(crate) fn settle(&self) {
1275 let (done, wait) = mpsc::channel();
1276 let _ = self.core.signals.send(Signal::Barrier(done));
1277 let _ = wait.recv_timeout(Duration::from_secs(5));
1278 }
1279}
1280
1281#[cfg(test)]
1282mod tests;