#![allow(non_upper_case_globals, non_snake_case)]
use super::{libx11::*, X11Display};
const CurrentTime: libc::c_long = 0 as libc::c_long;
const SelectionRequest: libc::c_int = 30 as libc::c_int;
const SelectionNotify: libc::c_int = 31 as libc::c_int;
const AnyPropertyType: libc::c_long = 0 as libc::c_long;
type Time = libc::c_ulong;
pub unsafe fn get_clipboard(
display: &mut X11Display,
bufname: *const libc::c_char,
fmtname: *const libc::c_char,
) -> Option<String> {
let mut result = 0 as *mut libc::c_char;
let mut ressize: libc::c_ulong = 0;
let mut restail: libc::c_ulong = 0;
let mut resbits: libc::c_int = 0;
let bufid = (display.libx11.XInternAtom)(display.display, bufname, false as _);
let mut fmtid = (display.libx11.XInternAtom)(display.display, fmtname, false as _);
let propid = (display.libx11.XInternAtom)(
display.display,
b"XSEL_DATA\x00" as *const u8 as *const libc::c_char,
false as _,
);
let incrid = (display.libx11.XInternAtom)(
display.display,
b"INCR\x00" as *const u8 as *const libc::c_char,
false as _,
);
let mut event = _XEvent { type_0: 0 };
(display.libx11.XConvertSelection)(
display.display,
bufid,
fmtid,
propid,
display.window,
CurrentTime as Time,
);
loop {
(display.libx11.XNextEvent)(display.display, &mut event);
if !(event.type_0 != SelectionNotify || event.xselection.selection != bufid) {
break;
}
if event.type_0 == SelectionRequest {
respond_to_clipboard_request(display, &mut event as *mut _);
}
}
if event.xselection.property != 0 {
let read_size = (100 as u32 * std::mem::size_of::<Atom>() as u32) as libc::c_long;
let mut bytes: Vec<u8> = vec![];
let mut offset: libc::c_long = 0 as libc::c_long;
loop {
(display.libx11.XGetWindowProperty)(
display.display,
display.window,
propid,
offset,
read_size,
false as _,
AnyPropertyType as Atom,
&mut fmtid,
&mut resbits,
&mut ressize,
&mut restail,
&mut result as *mut *mut libc::c_char as *mut *mut libc::c_uchar,
);
if fmtid == incrid {
(display.libx11.XFree)(result as *mut libc::c_void);
panic!("Buffer is too large and INCR reading is not implemented yet.");
} else {
let slice = std::slice::from_raw_parts(result as *const _, ressize as _);
bytes.extend(slice);
(display.libx11.XFree)(result as *mut libc::c_void);
if restail == 0 {
return std::str::from_utf8(&bytes[..]).map(|s| s.to_owned()).ok();
} else {
offset += read_size;
}
}
}
}
return None;
}
static mut MESSAGE: Option<String> = None;
pub unsafe fn claim_clipboard_ownership(
display: &mut X11Display,
bufname: *const libc::c_char,
message: String,
) {
let selection = (display.libx11.XInternAtom)(
display.display,
bufname as *const u8 as *const libc::c_char,
0 as libc::c_int,
);
(display.libx11.XSetSelectionOwner)(
display.display,
selection,
display.window,
0 as libc::c_int as Time,
);
MESSAGE = Some(message);
}
pub(crate) unsafe fn respond_to_clipboard_request(display: &mut X11Display, event: *const XEvent) {
assert!((*event).type_0 == 30);
let empty_message = String::new();
let message = MESSAGE.as_ref().unwrap_or(&empty_message);
let UTF8 = (display.libx11.XInternAtom)(
display.display,
b"UTF8_STRING\x00" as *const u8 as *const libc::c_char,
1 as libc::c_int,
);
let xselectionrequest = (*event).xselectionrequest;
let mut ev = XSelectionEvent {
type_0: super::clipboard::SelectionNotify,
serial: 0,
send_event: 0,
display: xselectionrequest.display,
requestor: xselectionrequest.requestor,
selection: xselectionrequest.selection,
target: xselectionrequest.target,
property: xselectionrequest.property,
time: xselectionrequest.time,
};
if xselectionrequest.target == UTF8 {
(display.libx11.XChangeProperty)(
xselectionrequest.display,
xselectionrequest.requestor,
xselectionrequest.property,
UTF8,
8 as libc::c_int,
PropModeReplace,
message.as_bytes().as_ptr() as *const u8 as *const _,
message.as_bytes().len() as _,
);
(display.libx11.XSendEvent)(
display.display,
ev.requestor,
0 as libc::c_int,
0 as libc::c_int as libc::c_long,
&mut ev as *mut XSelectionEvent as *mut XEvent,
);
} else {
ev.property = 0 as Atom;
(display.libx11.XSendEvent)(
display.display,
ev.requestor,
0 as libc::c_int,
0 as libc::c_int as libc::c_long,
&mut ev as *mut XSelectionEvent as *mut XEvent,
);
}
}