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:
Jake Stanger
2023-04-29 22:08:02 +01:00
parent 5c18ec8ba0
commit 7f46cb4976
23 changed files with 1779 additions and 1338 deletions

View File

@@ -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.");
}
_ => {}
}
}
}