1use crate::x::*;
6
7use crate::{_sapp_x11_display, _sapp_x11_window};
8
9const CurrentTime: libc::c_long = 0 as libc::c_long;
10pub(crate) const SelectionRequest: libc::c_int = 30 as libc::c_int;
11pub(crate) const SelectionNotify: libc::c_int = 31 as libc::c_int;
12const AnyPropertyType: libc::c_long = 0 as libc::c_long;
13
14type Time = libc::c_ulong;
15
16pub unsafe fn get_clipboard(
17 mut bufname: *const libc::c_char,
18 mut fmtname: *const libc::c_char,
19) -> Option<String> {
20 assert!(_sapp_x11_display as usize != 0 && _sapp_x11_window != 0);
21
22 let mut result = 0 as *mut libc::c_char;
23 let mut ressize: libc::c_ulong = 0;
24 let mut restail: libc::c_ulong = 0;
25 let mut resbits: libc::c_int = 0;
26 let mut bufid = XInternAtom(_sapp_x11_display, bufname, false as _);
27 let mut fmtid = XInternAtom(_sapp_x11_display, fmtname, false as _);
28 let mut propid = XInternAtom(
29 _sapp_x11_display,
30 b"XSEL_DATA\x00" as *const u8 as *const libc::c_char,
31 false as _,
32 );
33 let mut incrid = XInternAtom(
34 _sapp_x11_display,
35 b"INCR\x00" as *const u8 as *const libc::c_char,
36 false as _,
37 );
38 let mut event = _XEvent { type_0: 0 };
39
40 XConvertSelection(
45 _sapp_x11_display,
46 bufid,
47 fmtid,
48 propid,
49 _sapp_x11_window,
50 CurrentTime as Time,
51 );
52
53 loop {
59 XNextEvent(_sapp_x11_display, &mut event);
60 if !(event.type_0 != SelectionNotify || event.xselection.selection != bufid) {
61 break;
62 }
63 if event.type_0 == SelectionRequest {
64 respond_to_clipboard_request(&mut event as *mut _);
65 }
66 }
67 if event.xselection.property != 0 {
68 let read_size = (100 as u32 * std::mem::size_of::<Atom>() as u32) as libc::c_long;
69 let mut bytes: Vec<u8> = vec![];
70 let mut offset: libc::c_long = 0 as libc::c_long;
71 loop {
72 XGetWindowProperty(
73 _sapp_x11_display,
74 _sapp_x11_window,
75 propid,
76 offset,
77 read_size,
78 false as _,
79 AnyPropertyType as Atom,
80 &mut fmtid,
81 &mut resbits,
82 &mut ressize,
83 &mut restail,
84 &mut result as *mut *mut libc::c_char as *mut *mut libc::c_uchar,
85 );
86 if fmtid == incrid {
87 XFree(result as *mut libc::c_void);
88 panic!("Buffer is too large and INCR reading is not implemented yet.");
89 } else {
90 let slice = std::slice::from_raw_parts(result as *const _, ressize as _);
91 let str_result = bytes.extend(slice);
92
93 XFree(result as *mut libc::c_void);
94
95 if restail == 0 {
96 return std::str::from_utf8(&bytes[..]).map(|s| s.to_owned()).ok();
97 } else {
98 offset += read_size;
99 }
100 }
101 }
102 }
103
104 return None;
105}
106
107static mut MESSAGE: Option<String> = None;
109
110pub unsafe fn claim_clipboard_ownership(mut bufname: *const libc::c_char, message: String) {
113 assert!(_sapp_x11_display as usize != 0 && _sapp_x11_window != 0);
114
115 let mut selection = XInternAtom(
116 _sapp_x11_display,
117 bufname as *const u8 as *const libc::c_char,
118 0 as libc::c_int,
119 );
120
121 XSetSelectionOwner(
122 _sapp_x11_display,
123 selection,
124 _sapp_x11_window,
125 0 as libc::c_int as Time,
126 );
127
128 MESSAGE = Some(message);
129}
130
131pub(crate) unsafe fn respond_to_clipboard_request(event: *const XEvent) {
135 assert!((*event).type_0 == 30); let empty_message = String::new();
138 let message = MESSAGE.as_ref().unwrap_or(&empty_message);
139
140 let UTF8 = XInternAtom(
141 _sapp_x11_display,
142 b"UTF8_STRING\x00" as *const u8 as *const libc::c_char,
143 1 as libc::c_int,
144 );
145 let xselectionrequest = (*event).xselectionrequest;
146 let mut ev = XSelectionEvent {
147 type_0: crate::clipboard::SelectionNotify,
148 serial: 0,
149 send_event: 0,
150 display: xselectionrequest.display,
151 requestor: xselectionrequest.requestor,
152 selection: xselectionrequest.selection,
153 target: xselectionrequest.target,
154 property: xselectionrequest.property,
155 time: xselectionrequest.time,
156 };
157
158 if xselectionrequest.target == UTF8 {
160 XChangeProperty(
161 xselectionrequest.display,
162 xselectionrequest.requestor,
163 xselectionrequest.property,
164 UTF8,
165 8 as libc::c_int,
166 PropModeReplace,
167 message.as_bytes().as_ptr() as *const u8 as *const _,
168 message.as_bytes().len() as _,
169 );
170
171 XSendEvent(
172 _sapp_x11_display,
173 ev.requestor,
174 0 as libc::c_int,
175 0 as libc::c_int as libc::c_long,
176 &mut ev as *mut XSelectionEvent as *mut XEvent,
177 );
178 } else {
179 ev.property = 0 as Atom;
181
182 XSendEvent(
183 _sapp_x11_display,
184 ev.requestor,
185 0 as libc::c_int,
186 0 as libc::c_int as libc::c_long,
187 &mut ev as *mut XSelectionEvent as *mut XEvent,
188 );
189 }
190}