server: verify selection offer is still valid when handling clipboard
Should fix #170, fix #183
This commit is contained in:
parent
2e7c318ac2
commit
cf1fae1eae
4 changed files with 49 additions and 14 deletions
|
|
@ -3,7 +3,8 @@ use hecs::{Entity, World};
|
|||
use smithay_client_toolkit::{
|
||||
activation::{ActivationHandler, RequestData, RequestDataExt},
|
||||
data_device_manager::{
|
||||
data_device::DataDeviceHandler, data_offer::DataOfferHandler,
|
||||
data_device::{DataDeviceData, DataDeviceHandler},
|
||||
data_offer::{DataOfferHandler, SelectionOffer},
|
||||
data_source::DataSourceHandler,
|
||||
},
|
||||
delegate_activation, delegate_data_device,
|
||||
|
|
@ -78,7 +79,7 @@ pub(super) struct MyWorld {
|
|||
pub new_globals: Vec<Global>,
|
||||
events: Vec<(Entity, ObjectEvent)>,
|
||||
queued_events: Vec<mpsc::Receiver<(Entity, ObjectEvent)>>,
|
||||
pub selection: Option<wayland_client::protocol::wl_data_device::WlDataDevice>,
|
||||
pub selection_offer: Option<SelectionOffer>,
|
||||
pub selection_requests: Vec<(
|
||||
String,
|
||||
smithay_client_toolkit::data_device_manager::WritePipe,
|
||||
|
|
@ -95,7 +96,7 @@ impl MyWorld {
|
|||
new_globals: Vec::new(),
|
||||
events: Vec::new(),
|
||||
queued_events: Vec::new(),
|
||||
selection: None,
|
||||
selection_offer: None,
|
||||
selection_requests: Vec::new(),
|
||||
selection_cancelled: false,
|
||||
pending_activations: Vec::new(),
|
||||
|
|
@ -385,7 +386,8 @@ impl DataDeviceHandler for MyWorld {
|
|||
_: &wayland_client::QueueHandle<Self>,
|
||||
data_device: &wayland_client::protocol::wl_data_device::WlDataDevice,
|
||||
) {
|
||||
self.selection = Some(data_device.clone());
|
||||
let data: &DataDeviceData = data_device.data().unwrap();
|
||||
self.selection_offer = data.selection_offer();
|
||||
}
|
||||
|
||||
fn drop_performed(
|
||||
|
|
|
|||
|
|
@ -1095,16 +1095,18 @@ impl<C: XConnection> ServerState<C> {
|
|||
}
|
||||
}
|
||||
|
||||
if clipboard.source.is_none() || self.world.selection_cancelled {
|
||||
if self.world.selection.take().is_some() {
|
||||
let device = clipboard.device.as_ref().unwrap();
|
||||
let offer = device.data().selection_offer().unwrap();
|
||||
let mime_types: Box<[String]> = offer.with_mime_types(|mimes| mimes.into());
|
||||
let foreign = ForeignSelection {
|
||||
mime_types,
|
||||
inner: offer,
|
||||
};
|
||||
clipboard.source = Some(CopyPasteData::Foreign(foreign));
|
||||
if clipboard.source.is_none() {
|
||||
if let Some(offer) = self.world.selection_offer.take() {
|
||||
if offer.inner().is_alive() {
|
||||
let mime_types: Box<[String]> = offer.with_mime_types(|mimes| mimes.into());
|
||||
let foreign = ForeignSelection {
|
||||
mime_types,
|
||||
inner: offer,
|
||||
};
|
||||
clipboard.source = Some(CopyPasteData::Foreign(foreign));
|
||||
} else {
|
||||
clipboard.source = None;
|
||||
}
|
||||
}
|
||||
self.world.selection_cancelled = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2427,6 +2427,23 @@ fn output_updated_before_x_connection() {
|
|||
assert_eq!(data.dims.x, 0);
|
||||
assert_eq!(data.dims.y, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quick_empty_data_offer() {
|
||||
let (mut f, comp) = TestFixture::new_with_compositor();
|
||||
TestObject::<WlKeyboard>::from_request(&comp.seat.obj, wl_seat::Request::GetKeyboard {});
|
||||
let win = unsafe { Window::new(1) };
|
||||
let (_surface, _id) = f.create_toplevel(&comp, win);
|
||||
f.testwl.create_data_offer(vec![testwl::PasteData {
|
||||
mime_type: "text".to_string(),
|
||||
data: b"abc".to_vec(),
|
||||
}]);
|
||||
f.testwl.empty_data_offer();
|
||||
f.run();
|
||||
|
||||
let selection = f.satellite.new_selection();
|
||||
assert!(selection.is_none());
|
||||
}
|
||||
/// See Pointer::handle_event for an explanation.
|
||||
#[test]
|
||||
fn popup_pointer_motion_workaround() {}
|
||||
|
|
|
|||
|
|
@ -695,6 +695,20 @@ impl Server {
|
|||
self.display.flush_clients().unwrap();
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn empty_data_offer(&mut self) {
|
||||
let Some(dev) = &self.state.data_device else {
|
||||
panic!("No data device created");
|
||||
};
|
||||
|
||||
if let Some(selection) = self.state.selection.take() {
|
||||
selection.cancelled();
|
||||
}
|
||||
|
||||
dev.selection(None);
|
||||
self.display.flush_clients().unwrap();
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn move_pointer_to(&mut self, surface: SurfaceId, x: f64, y: f64) {
|
||||
let pointer = self.state.pointer.as_ref().expect("No pointer created");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue