xstate: always advertise utf8 mime type as UTF8_STRING from Wayland selection
Fixes #87
This commit is contained in:
parent
ba9c1a6a3e
commit
8f55e27f63
3 changed files with 92 additions and 3 deletions
|
|
@ -12,6 +12,7 @@ use xcb::x;
|
||||||
struct SelectionTargetId {
|
struct SelectionTargetId {
|
||||||
name: String,
|
name: String,
|
||||||
atom: x::Atom,
|
atom: x::Atom,
|
||||||
|
source: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PendingSelectionData {
|
struct PendingSelectionData {
|
||||||
|
|
@ -227,10 +228,18 @@ impl XState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_clipboard(&mut self, selection: ForeignSelection) {
|
pub(crate) fn set_clipboard(&mut self, selection: ForeignSelection) {
|
||||||
let mimes = selection
|
let mut utf8_xwl = false;
|
||||||
|
let mut utf8_wl = false;
|
||||||
|
let mut mimes: Vec<SelectionTargetId> = selection
|
||||||
.mime_types
|
.mime_types
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mime| {
|
.map(|mime| {
|
||||||
|
match mime.as_str() {
|
||||||
|
"UTF8_STRING" => utf8_xwl = true,
|
||||||
|
"text/plain;charset=utf-8" => utf8_wl = true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let atom = self
|
let atom = self
|
||||||
.connection
|
.connection
|
||||||
.wait_for_reply(self.connection.send_request(&x::InternAtom {
|
.wait_for_reply(self.connection.send_request(&x::InternAtom {
|
||||||
|
|
@ -242,10 +251,28 @@ impl XState {
|
||||||
SelectionTargetId {
|
SelectionTargetId {
|
||||||
name: mime.clone(),
|
name: mime.clone(),
|
||||||
atom: atom.atom(),
|
atom: atom.atom(),
|
||||||
|
source: None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
if utf8_wl && !utf8_xwl {
|
||||||
|
let name = "UTF8_STRING".to_string();
|
||||||
|
let atom = self
|
||||||
|
.connection
|
||||||
|
.wait_for_reply(self.connection.send_request(&x::InternAtom {
|
||||||
|
only_if_exists: false,
|
||||||
|
name: name.as_bytes(),
|
||||||
|
}))
|
||||||
|
.unwrap()
|
||||||
|
.atom();
|
||||||
|
mimes.push(SelectionTargetId {
|
||||||
|
name,
|
||||||
|
atom,
|
||||||
|
source: Some("text/plain;charset=utf-8".to_string()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self.selection_data.current_selection = Some(CurrentSelection::Wayland {
|
self.selection_data.current_selection = Some(CurrentSelection::Wayland {
|
||||||
mimes,
|
mimes,
|
||||||
inner: selection,
|
inner: selection,
|
||||||
|
|
@ -364,7 +391,12 @@ impl XState {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = inner.receive(target.name.clone(), server_state);
|
let mime_name = target
|
||||||
|
.source
|
||||||
|
.as_ref()
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| target.name.clone());
|
||||||
|
let data = inner.receive(mime_name, server_state);
|
||||||
match self.connection.send_and_check_request(&x::ChangeProperty {
|
match self.connection.send_and_check_request(&x::ChangeProperty {
|
||||||
mode: x::PropMode::Replace,
|
mode: x::PropMode::Replace,
|
||||||
window: e.requestor(),
|
window: e.requestor(),
|
||||||
|
|
@ -479,6 +511,7 @@ impl XState {
|
||||||
.map(|target_atom| SelectionTargetId {
|
.map(|target_atom| SelectionTargetId {
|
||||||
name: get_atom_name(&self.connection, target_atom),
|
name: get_atom_name(&self.connection, target_atom),
|
||||||
atom: target_atom,
|
atom: target_atom,
|
||||||
|
source: None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1306,3 +1306,59 @@ fn wayland_then_x11_clipboard_owner() {
|
||||||
assert_eq!(request.selection(), connection.atoms.clipboard);
|
assert_eq!(request.selection(), connection.atoms.clipboard);
|
||||||
assert_eq!(request.target(), connection.atoms.targets);
|
assert_eq!(request.target(), connection.atoms.targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fake_selection_targets() {
|
||||||
|
let mut f = Fixture::new();
|
||||||
|
let mut connection = Connection::new(&f.display);
|
||||||
|
let window = connection.new_window(connection.root, 0, 0, 20, 20, false);
|
||||||
|
connection.get_selection_owner_change_events(true, window);
|
||||||
|
|
||||||
|
let data = b"boingloings";
|
||||||
|
f.map_as_toplevel(&mut connection, window);
|
||||||
|
let offer = vec![testwl::PasteData {
|
||||||
|
mime_type: "text/plain;charset=utf-8".into(),
|
||||||
|
data: data.to_vec(),
|
||||||
|
}];
|
||||||
|
f.testwl.create_data_offer(offer.clone());
|
||||||
|
|
||||||
|
connection.await_selection_owner_change();
|
||||||
|
connection.verify_clipboard_owner(connection.wm_window);
|
||||||
|
connection.get_selection_owner_change_events(false, window);
|
||||||
|
|
||||||
|
let utf8_string = connection
|
||||||
|
.get_reply(&x::InternAtom {
|
||||||
|
only_if_exists: false,
|
||||||
|
name: b"UTF8_STRING",
|
||||||
|
})
|
||||||
|
.atom();
|
||||||
|
|
||||||
|
connection
|
||||||
|
.send_and_check_request(&x::ConvertSelection {
|
||||||
|
requestor: window,
|
||||||
|
selection: connection.atoms.clipboard,
|
||||||
|
target: utf8_string,
|
||||||
|
property: utf8_string,
|
||||||
|
time: x::CURRENT_TIME,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
f.wait_and_dispatch();
|
||||||
|
let notify = connection.await_selection_notify();
|
||||||
|
assert_eq!(notify.property(), utf8_string, "ConvertSelection failed");
|
||||||
|
|
||||||
|
let reply = connection.get_reply(&x::GetProperty {
|
||||||
|
delete: false,
|
||||||
|
window,
|
||||||
|
property: utf8_string,
|
||||||
|
r#type: utf8_string,
|
||||||
|
long_offset: 0,
|
||||||
|
long_length: data.len() as u32,
|
||||||
|
});
|
||||||
|
let paste_data: &[u8] = reply.value();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
std::str::from_utf8(paste_data).unwrap(),
|
||||||
|
std::str::from_utf8(data).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -875,7 +875,7 @@ impl Dispatch<WlDataOffer, Vec<PasteData>> for State {
|
||||||
let pos = data
|
let pos = data
|
||||||
.iter()
|
.iter()
|
||||||
.position(|data| data.mime_type == mime_type)
|
.position(|data| data.mime_type == mime_type)
|
||||||
.expect("Invalid mime type: {mime_type}");
|
.unwrap_or_else(|| panic!("Invalid mime type: {mime_type}"));
|
||||||
|
|
||||||
let mut stream = UnixStream::from(fd);
|
let mut stream = UnixStream::from(fd);
|
||||||
stream.write_all(&data[pos].data).unwrap();
|
stream.write_all(&data[pos].data).unwrap();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue