fix: give clipboard/primary TARGETS unique atoms

The clipboard and primary selections previously used the same atom to
store TARGETS when queried for them by `handle_target_list`. When a
program requests both selections simultaneously, problems such as one
selection using the target list of the other, then deleting it and
requiring the second target to get the selection targets again could
occur. This was observed when using `wl-clip-persist` and could result
in selection desyncs.

This change gives a unique atom to each primary and clipboard selection
targets so they no longer compete over the same property. It also adds
updates to the `copy_from_x11` intergration to test for this issue.
This commit is contained in:
En-En 2025-10-13 20:38:20 +00:00 committed by Supreeeme
parent 3cd3edffe1
commit 34bf07db05
3 changed files with 70 additions and 41 deletions

View file

@ -233,6 +233,7 @@ enum CurrentSelection<T: SelectionType> {
struct SelectionData<T: SelectionType> {
last_selection_timestamp: u32,
atom: x::Atom,
targets_atom: x::Atom,
current_selection: Option<CurrentSelection<T>>,
}
@ -269,10 +270,11 @@ trait SelectionDataImpl {
}
impl<T: SelectionType> SelectionData<T> {
fn new(atom: x::Atom) -> Self {
fn new(atom: x::Atom, targets_atom: x::Atom) -> Self {
Self {
last_selection_timestamp: x::CURRENT_TIME,
atom,
targets_atom,
current_selection: None,
}
}
@ -336,7 +338,7 @@ impl<T: SelectionType> SelectionDataImpl for SelectionData<T> {
requestor: wm_window,
selection: self.atom,
target: atoms.targets,
property: atoms.selection_reply,
property: self.targets_atom,
time: timestamp,
}) {
Ok(_) => {
@ -571,8 +573,8 @@ impl SelectionState {
.expect("Couldn't create window for selections");
Self {
target_window,
clipboard: SelectionData::new(atoms.clipboard),
primary: SelectionData::new(atoms.primary),
clipboard: SelectionData::new(atoms.clipboard, atoms.clipboard_targets),
primary: SelectionData::new(atoms.primary, atoms.primary_targets),
}
}
}