refactor(wayland): update to 0.30.0
This is pretty much a rewrite of the Wayland client code for `wayland-client` and `wayland-protocols` v0.30.0, and `smithay-client-toolkit` v0.17.0
This commit is contained in:
@@ -1,88 +1,166 @@
|
||||
use super::offer::DataControlOffer;
|
||||
use super::source::DataControlSource;
|
||||
use super::manager::DataControlDeviceManagerState;
|
||||
use super::offer::{
|
||||
DataControlOfferData, DataControlOfferDataExt, DataControlOfferHandler, SelectionOffer,
|
||||
};
|
||||
use crate::error::ERR_WAYLAND_DATA;
|
||||
use crate::lock;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use wayland_client::protocol::wl_seat::WlSeat;
|
||||
use wayland_client::{Attached, DispatchData, Main};
|
||||
use wayland_protocols::wlr::unstable::data_control::v1::client::{
|
||||
use tracing::warn;
|
||||
use wayland_client::{event_created_child, Connection, Dispatch, Proxy, QueueHandle};
|
||||
use wayland_protocols_wlr::data_control::v1::client::{
|
||||
zwlr_data_control_device_v1::{Event, ZwlrDataControlDeviceV1},
|
||||
zwlr_data_control_manager_v1::ZwlrDataControlManagerV1,
|
||||
zwlr_data_control_offer_v1::ZwlrDataControlOfferV1,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Inner {
|
||||
offer: Option<Arc<DataControlOffer>>,
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
fn new_offer(&mut self, offer: &Main<ZwlrDataControlOfferV1>) {
|
||||
self.offer.replace(Arc::new(DataControlOffer::new(offer)));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DataControlDeviceEvent(pub Arc<DataControlOffer>);
|
||||
|
||||
fn data_control_device_implem<F>(
|
||||
event: Event,
|
||||
inner: &mut Inner,
|
||||
implem: &mut F,
|
||||
ddata: DispatchData,
|
||||
) where
|
||||
F: FnMut(DataControlDeviceEvent, DispatchData),
|
||||
{
|
||||
match event {
|
||||
Event::DataOffer { id } => {
|
||||
inner.new_offer(&id);
|
||||
}
|
||||
Event::Selection { id: Some(offer) } => {
|
||||
let inner_offer = inner
|
||||
.offer
|
||||
.clone()
|
||||
.expect("Offer should exist at this stage");
|
||||
if offer == inner_offer.offer {
|
||||
implem(DataControlDeviceEvent(inner_offer), ddata);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DataControlDevice {
|
||||
device: ZwlrDataControlDeviceV1,
|
||||
_inner: Arc<Mutex<Inner>>,
|
||||
pub device: ZwlrDataControlDeviceV1,
|
||||
}
|
||||
|
||||
impl DataControlDevice {
|
||||
pub fn init_for_seat<F>(
|
||||
manager: &Attached<ZwlrDataControlManagerV1>,
|
||||
seat: &WlSeat,
|
||||
mut callback: F,
|
||||
) -> Self
|
||||
where
|
||||
F: FnMut(DataControlDeviceEvent, DispatchData) + 'static,
|
||||
{
|
||||
let inner = Arc::new(Mutex::new(Inner { offer: None }));
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DataControlDeviceInner {
|
||||
/// the active selection offer and its data
|
||||
selection_offer: Arc<Mutex<Option<ZwlrDataControlOfferV1>>>,
|
||||
/// the active undetermined offers and their data
|
||||
pub undetermined_offers: Arc<Mutex<Vec<ZwlrDataControlOfferV1>>>,
|
||||
}
|
||||
|
||||
let device = manager.get_data_device(seat);
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DataControlDeviceData {
|
||||
pub(super) inner: Arc<Mutex<DataControlDeviceInner>>,
|
||||
}
|
||||
|
||||
{
|
||||
let inner = inner.clone();
|
||||
device.quick_assign(move |_handle, event, ddata| {
|
||||
let mut inner = lock!(inner);
|
||||
data_control_device_implem(event, &mut inner, &mut callback, ddata);
|
||||
});
|
||||
}
|
||||
pub trait DataControlDeviceDataExt: Send + Sync {
|
||||
type DataControlOfferInner: DataControlOfferDataExt + Send + Sync + 'static;
|
||||
|
||||
Self {
|
||||
device: device.detach(),
|
||||
_inner: inner,
|
||||
}
|
||||
fn data_control_device_data(&self) -> &DataControlDeviceData;
|
||||
|
||||
fn selection_mime_types(&self) -> Vec<String> {
|
||||
let inner = self.data_control_device_data();
|
||||
lock!(lock!(inner.inner).selection_offer)
|
||||
.as_ref()
|
||||
.map(|offer| {
|
||||
let data = offer
|
||||
.data::<Self::DataControlOfferInner>()
|
||||
.expect(ERR_WAYLAND_DATA);
|
||||
data.mime_types()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn set_selection(&self, source: &Option<DataControlSource>) {
|
||||
self.device
|
||||
.set_selection(source.as_ref().map(|s| &s.source));
|
||||
/// Get the active selection offer if it exists.
|
||||
fn selection_offer(&self) -> Option<SelectionOffer> {
|
||||
let inner = self.data_control_device_data();
|
||||
lock!(lock!(inner.inner).selection_offer)
|
||||
.as_ref()
|
||||
.and_then(|offer| {
|
||||
let data = offer
|
||||
.data::<Self::DataControlOfferInner>()
|
||||
.expect(ERR_WAYLAND_DATA);
|
||||
data.as_selection_offer()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl DataControlDeviceDataExt for DataControlDevice {
|
||||
type DataControlOfferInner = DataControlOfferData;
|
||||
fn data_control_device_data(&self) -> &DataControlDeviceData {
|
||||
self.device.data().expect(ERR_WAYLAND_DATA)
|
||||
}
|
||||
}
|
||||
|
||||
impl DataControlDeviceDataExt for DataControlDeviceData {
|
||||
type DataControlOfferInner = DataControlOfferData;
|
||||
fn data_control_device_data(&self) -> &DataControlDeviceData {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler trait for `DataDevice` events.
|
||||
///
|
||||
/// The functions defined in this trait are called as `DataDevice` events are received from the compositor.
|
||||
pub trait DataControlDeviceHandler: Sized {
|
||||
/// Advertises a new selection.
|
||||
fn selection(
|
||||
&mut self,
|
||||
conn: &Connection,
|
||||
qh: &QueueHandle<Self>,
|
||||
data_device: DataControlDevice,
|
||||
);
|
||||
}
|
||||
|
||||
impl<D, U, V> Dispatch<ZwlrDataControlDeviceV1, U, D> for DataControlDeviceManagerState<V>
|
||||
where
|
||||
D: Dispatch<ZwlrDataControlDeviceV1, U>
|
||||
+ Dispatch<ZwlrDataControlOfferV1, V>
|
||||
+ DataControlDeviceHandler
|
||||
+ DataControlOfferHandler
|
||||
+ 'static,
|
||||
U: DataControlDeviceDataExt,
|
||||
V: DataControlOfferDataExt + Default + 'static + Send + Sync,
|
||||
{
|
||||
event_created_child!(D, ZwlrDataControlDeviceV1, [
|
||||
0 => (ZwlrDataControlOfferV1, V::default())
|
||||
]);
|
||||
|
||||
fn event(
|
||||
state: &mut D,
|
||||
data_device: &ZwlrDataControlDeviceV1,
|
||||
event: Event,
|
||||
data: &U,
|
||||
conn: &Connection,
|
||||
qh: &QueueHandle<D>,
|
||||
) {
|
||||
let data = data.data_control_device_data();
|
||||
let inner = lock!(data.inner);
|
||||
|
||||
match event {
|
||||
Event::DataOffer { id } => {
|
||||
// XXX Drop done here to prevent Mutex deadlocks.S
|
||||
|
||||
lock!(inner.undetermined_offers).push(id.clone());
|
||||
let data = id
|
||||
.data::<V>()
|
||||
.expect(ERR_WAYLAND_DATA)
|
||||
.data_control_offer_data();
|
||||
data.init_undetermined_offer(&id);
|
||||
|
||||
// Append the data offer to our list of offers.
|
||||
drop(inner);
|
||||
}
|
||||
Event::Selection { id } => {
|
||||
let mut selection_offer = lock!(inner.selection_offer);
|
||||
|
||||
if let Some(offer) = id {
|
||||
let mut undetermined = lock!(inner.undetermined_offers);
|
||||
if let Some(i) = undetermined.iter().position(|o| o == &offer) {
|
||||
undetermined.remove(i);
|
||||
}
|
||||
drop(undetermined);
|
||||
|
||||
let data = offer
|
||||
.data::<V>()
|
||||
.expect(ERR_WAYLAND_DATA)
|
||||
.data_control_offer_data();
|
||||
data.to_selection_offer();
|
||||
// XXX Drop done here to prevent Mutex deadlocks.
|
||||
*selection_offer = Some(offer.clone());
|
||||
drop(selection_offer);
|
||||
drop(inner);
|
||||
state.selection(
|
||||
conn,
|
||||
qh,
|
||||
DataControlDevice {
|
||||
device: data_device.clone(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
*selection_offer = None;
|
||||
}
|
||||
}
|
||||
Event::Finished => {
|
||||
warn!("Data control offer is no longer valid, but has not been dropped by client. This could cause clipboard issues.");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user