smithay_client_toolkit/primary_selection/
device.rs1use std::sync::{Arc, Mutex};
2
3use crate::reexports::client::{
4 event_created_child, protocol::wl_seat::WlSeat, Connection, Dispatch, Proxy, QueueHandle,
5};
6use crate::reexports::protocols::wp::primary_selection::zv1::client::{
7 zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1,
8 zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1,
9};
10
11use crate::dispatch2::Dispatch2;
12
13use super::offer::{PrimarySelectionOffer, PrimarySelectionOfferData};
14
15pub trait PrimarySelectionDeviceHandler: Sized {
16 fn selection(
20 &mut self,
21 conn: &Connection,
22 qh: &QueueHandle<Self>,
23 primary_selection_device: &ZwpPrimarySelectionDeviceV1,
24 );
25}
26
27#[derive(Debug)]
28pub struct PrimarySelectionDevice {
29 pub(crate) device: ZwpPrimarySelectionDeviceV1,
30}
31
32impl PrimarySelectionDevice {
33 pub fn unset_selection(&self, serial: u32) {
37 self.device.set_selection(None, serial);
38 }
39
40 pub fn data(&self) -> &PrimarySelectionDeviceData {
42 self.device.data::<PrimarySelectionDeviceData>().unwrap()
43 }
44
45 pub fn inner(&self) -> &ZwpPrimarySelectionDeviceV1 {
46 &self.device
47 }
48}
49
50impl Drop for PrimarySelectionDevice {
51 fn drop(&mut self) {
52 self.device.destroy();
53 }
54}
55
56impl<State> Dispatch2<ZwpPrimarySelectionDeviceV1, State> for PrimarySelectionDeviceData
57where
58 State: Dispatch<ZwpPrimarySelectionOfferV1, PrimarySelectionOfferData>
59 + PrimarySelectionDeviceHandler
60 + 'static,
61{
62 event_created_child!(State, ZwpPrimarySelectionDeviceV1, [
63 0 => (ZwpPrimarySelectionOfferV1, PrimarySelectionOfferData::default())
64 ]);
65
66 fn event(
67 &self,
68 state: &mut State,
69 proxy: &ZwpPrimarySelectionDeviceV1,
70 event: <ZwpPrimarySelectionDeviceV1 as wayland_client::Proxy>::Event,
71 conn: &Connection,
72 qhandle: &QueueHandle<State>,
73 ) {
74 use wayland_protocols::wp::primary_selection::zv1::client::zwp_primary_selection_device_v1::Event;
75 let mut data = self.inner.lock().unwrap();
76 match event {
77 Event::DataOffer { offer } => {
78 if let Some(pending_offer) = data.pending_offer.take() {
80 pending_offer.destroy();
81 }
82
83 data.pending_offer = Some(offer);
84 }
85 Event::Selection { id } => {
86 if let Some(offer) = data.offer.take() {
88 offer.destroy();
89 }
90
91 if id == data.pending_offer {
92 data.offer = data.pending_offer.take();
93 } else {
94 if let Some(offer) = data.pending_offer.take() {
96 offer.destroy()
97 }
98
99 data.offer = id;
100 }
101
102 drop(data);
104
105 state.selection(conn, qhandle, proxy);
106 }
107 _ => unreachable!(),
108 }
109 }
110}
111
112#[derive(Debug)]
114pub struct PrimarySelectionDeviceData {
115 seat: WlSeat,
117 inner: Arc<Mutex<PrimarySelectionDeviceDataInner>>,
119}
120
121impl PrimarySelectionDeviceData {
122 pub(crate) fn new(seat: WlSeat) -> Self {
123 Self { seat, inner: Default::default() }
124 }
125
126 pub fn seat(&self) -> &WlSeat {
128 &self.seat
129 }
130
131 pub fn selection_offer(&self) -> Option<PrimarySelectionOffer> {
133 self.inner
134 .lock()
135 .unwrap()
136 .offer
137 .as_ref()
138 .map(|offer| PrimarySelectionOffer { offer: offer.clone() })
139 }
140}
141
142#[derive(Debug, Default)]
143struct PrimarySelectionDeviceDataInner {
144 offer: Option<ZwpPrimarySelectionOfferV1>,
147 pending_offer: Option<ZwpPrimarySelectionOfferV1>,
149}