1 | use std::sync::{Arc, Mutex}; |
2 | |
3 | use crate::reexports::client::{ |
4 | event_created_child, protocol::wl_seat::WlSeat, Connection, Dispatch, Proxy, QueueHandle, |
5 | }; |
6 | use crate::reexports::protocols::wp::primary_selection::zv1::client::{ |
7 | zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1, |
8 | zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1, |
9 | }; |
10 | |
11 | use super::{ |
12 | offer::{PrimarySelectionOffer, PrimarySelectionOfferData}, |
13 | PrimarySelectionManagerState, |
14 | }; |
15 | |
16 | pub trait PrimarySelectionDeviceHandler: Sized { |
17 | /// The new selection is received. |
18 | /// |
19 | /// The given primary selection device could be used to identify [`PrimarySelectionDevice`]. |
20 | fn selection( |
21 | &mut self, |
22 | conn: &Connection, |
23 | qh: &QueueHandle<Self>, |
24 | primary_selection_device: &ZwpPrimarySelectionDeviceV1, |
25 | ); |
26 | } |
27 | |
28 | #[derive (Debug)] |
29 | pub struct PrimarySelectionDevice { |
30 | pub(crate) device: ZwpPrimarySelectionDeviceV1, |
31 | } |
32 | |
33 | impl PrimarySelectionDevice { |
34 | /// Remove the currently active selection. |
35 | /// |
36 | /// The passed `serial` is the serial of the input event. |
37 | pub fn unset_selection(&self, serial: u32) { |
38 | self.device.set_selection(None, serial); |
39 | } |
40 | |
41 | /// Get the underlying data. |
42 | pub fn data(&self) -> &PrimarySelectionDeviceData { |
43 | self.device.data::<PrimarySelectionDeviceData>().unwrap() |
44 | } |
45 | |
46 | pub fn inner(&self) -> &ZwpPrimarySelectionDeviceV1 { |
47 | &self.device |
48 | } |
49 | } |
50 | |
51 | impl Drop for PrimarySelectionDevice { |
52 | fn drop(&mut self) { |
53 | self.device.destroy(); |
54 | } |
55 | } |
56 | |
57 | impl<State> Dispatch<ZwpPrimarySelectionDeviceV1, PrimarySelectionDeviceData, State> |
58 | for PrimarySelectionManagerState |
59 | where |
60 | State: Dispatch<ZwpPrimarySelectionDeviceV1, PrimarySelectionDeviceData> |
61 | + Dispatch<ZwpPrimarySelectionOfferV1, PrimarySelectionOfferData> |
62 | + PrimarySelectionDeviceHandler |
63 | + 'static, |
64 | { |
65 | event_created_child!(State, ZwpPrimarySelectionDeviceV1, [ |
66 | 0 => (ZwpPrimarySelectionOfferV1, PrimarySelectionOfferData::default()) |
67 | ]); |
68 | |
69 | fn event( |
70 | state: &mut State, |
71 | proxy: &ZwpPrimarySelectionDeviceV1, |
72 | event: <ZwpPrimarySelectionDeviceV1 as wayland_client::Proxy>::Event, |
73 | data: &PrimarySelectionDeviceData, |
74 | conn: &Connection, |
75 | qhandle: &QueueHandle<State>, |
76 | ) { |
77 | use wayland_protocols::wp::primary_selection::zv1::client::zwp_primary_selection_device_v1::Event; |
78 | let mut data = data.inner.lock().unwrap(); |
79 | match event { |
80 | Event::DataOffer { offer } => { |
81 | // Try to resist faulty compositors. |
82 | if let Some(pending_offer) = data.pending_offer.take() { |
83 | pending_offer.destroy(); |
84 | } |
85 | |
86 | data.pending_offer = Some(offer); |
87 | } |
88 | Event::Selection { id } => { |
89 | // We must drop the current offer regardless. |
90 | if let Some(offer) = data.offer.take() { |
91 | offer.destroy(); |
92 | } |
93 | |
94 | if id == data.pending_offer { |
95 | data.offer = data.pending_offer.take(); |
96 | } else { |
97 | // Remove the pending offer, assign the new delivered one. |
98 | if let Some(offer) = data.pending_offer.take() { |
99 | offer.destroy() |
100 | } |
101 | |
102 | data.offer = id; |
103 | } |
104 | |
105 | // Release the user data lock before calling into user. |
106 | drop(data); |
107 | |
108 | state.selection(conn, qhandle, proxy); |
109 | } |
110 | _ => unreachable!(), |
111 | } |
112 | } |
113 | } |
114 | |
115 | /// The user data associated with the [`ZwpPrimarySelectionDeviceV1`]. |
116 | #[derive (Debug)] |
117 | pub struct PrimarySelectionDeviceData { |
118 | /// The seat associated with this device. |
119 | seat: WlSeat, |
120 | /// The inner mutable storage. |
121 | inner: Arc<Mutex<PrimarySelectionDeviceDataInner>>, |
122 | } |
123 | |
124 | impl PrimarySelectionDeviceData { |
125 | pub(crate) fn new(seat: WlSeat) -> Self { |
126 | Self { seat, inner: Default::default() } |
127 | } |
128 | |
129 | /// The seat used to create this primary selection device. |
130 | pub fn seat(&self) -> &WlSeat { |
131 | &self.seat |
132 | } |
133 | |
134 | /// The active selection offer. |
135 | pub fn selection_offer(&self) -> Option<PrimarySelectionOffer> { |
136 | self.inner |
137 | .lock() |
138 | .unwrap() |
139 | .offer |
140 | .as_ref() |
141 | .map(|offer: &{unknown}| PrimarySelectionOffer { offer: offer.clone() }) |
142 | } |
143 | } |
144 | |
145 | #[derive (Debug, Default)] |
146 | struct PrimarySelectionDeviceDataInner { |
147 | /// The offer is valid until either `NULL` or new selection is received via the |
148 | /// `selection` event. |
149 | offer: Option<ZwpPrimarySelectionOfferV1>, |
150 | /// The offer we've got in `offer` event, but not finished it in `selection`. |
151 | pending_offer: Option<ZwpPrimarySelectionOfferV1>, |
152 | } |
153 | |