1use crate::{ffi, ContentFormats, ContentProvider, Display, Texture};
6use glib::{
7 object::ObjectType as _,
8 prelude::*,
9 signal::{connect_raw, SignalHandlerId},
10 translate::*,
11};
12use std::{boxed::Box as Box_, pin::Pin};
13
14glib::wrapper! {
15 #[doc(alias = "GdkClipboard")]
67 pub struct Clipboard(Object<ffi::GdkClipboard>);
68
69 match fn {
70 type_ => || ffi::gdk_clipboard_get_type(),
71 }
72}
73
74impl Clipboard {
75 #[doc(alias = "gdk_clipboard_get_content")]
85 #[doc(alias = "get_content")]
86 pub fn content(&self) -> Option<ContentProvider> {
87 unsafe { from_glib_none(ffi::gdk_clipboard_get_content(self.to_glib_none().0)) }
88 }
89
90 #[doc(alias = "gdk_clipboard_get_display")]
96 #[doc(alias = "get_display")]
97 pub fn display(&self) -> Display {
98 unsafe { from_glib_none(ffi::gdk_clipboard_get_display(self.to_glib_none().0)) }
99 }
100
101 #[doc(alias = "gdk_clipboard_get_formats")]
107 #[doc(alias = "get_formats")]
108 pub fn formats(&self) -> ContentFormats {
109 unsafe { from_glib_none(ffi::gdk_clipboard_get_formats(self.to_glib_none().0)) }
110 }
111
112 #[doc(alias = "gdk_clipboard_is_local")]
124 #[doc(alias = "local")]
125 pub fn is_local(&self) -> bool {
126 unsafe { from_glib(ffi::gdk_clipboard_is_local(self.to_glib_none().0)) }
127 }
128
129 #[doc(alias = "gdk_clipboard_read_text_async")]
139 pub fn read_text_async<P: FnOnce(Result<Option<glib::GString>, glib::Error>) + 'static>(
140 &self,
141 cancellable: Option<&impl IsA<gio::Cancellable>>,
142 callback: P,
143 ) {
144 let main_context = glib::MainContext::ref_thread_default();
145 let is_main_context_owner = main_context.is_owner();
146 let has_acquired_main_context = (!is_main_context_owner)
147 .then(|| main_context.acquire().ok())
148 .flatten();
149 assert!(
150 is_main_context_owner || has_acquired_main_context.is_some(),
151 "Async operations only allowed if the thread is owning the MainContext"
152 );
153
154 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
155 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
156 unsafe extern "C" fn read_text_async_trampoline<
157 P: FnOnce(Result<Option<glib::GString>, glib::Error>) + 'static,
158 >(
159 _source_object: *mut glib::gobject_ffi::GObject,
160 res: *mut gio::ffi::GAsyncResult,
161 user_data: glib::ffi::gpointer,
162 ) {
163 let mut error = std::ptr::null_mut();
164 let ret =
165 ffi::gdk_clipboard_read_text_finish(_source_object as *mut _, res, &mut error);
166 let result = if error.is_null() {
167 Ok(from_glib_full(ret))
168 } else {
169 Err(from_glib_full(error))
170 };
171 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
172 Box_::from_raw(user_data as *mut _);
173 let callback: P = callback.into_inner();
174 callback(result);
175 }
176 let callback = read_text_async_trampoline::<P>;
177 unsafe {
178 ffi::gdk_clipboard_read_text_async(
179 self.to_glib_none().0,
180 cancellable.map(|p| p.as_ref()).to_glib_none().0,
181 Some(callback),
182 Box_::into_raw(user_data) as *mut _,
183 );
184 }
185 }
186
187 pub fn read_text_future(
188 &self,
189 ) -> Pin<
190 Box_<
191 dyn std::future::Future<Output = Result<Option<glib::GString>, glib::Error>> + 'static,
192 >,
193 > {
194 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
195 obj.read_text_async(Some(cancellable), move |res| {
196 send.resolve(res);
197 });
198 }))
199 }
200
201 #[doc(alias = "gdk_clipboard_read_texture_async")]
211 pub fn read_texture_async<P: FnOnce(Result<Option<Texture>, glib::Error>) + 'static>(
212 &self,
213 cancellable: Option<&impl IsA<gio::Cancellable>>,
214 callback: P,
215 ) {
216 let main_context = glib::MainContext::ref_thread_default();
217 let is_main_context_owner = main_context.is_owner();
218 let has_acquired_main_context = (!is_main_context_owner)
219 .then(|| main_context.acquire().ok())
220 .flatten();
221 assert!(
222 is_main_context_owner || has_acquired_main_context.is_some(),
223 "Async operations only allowed if the thread is owning the MainContext"
224 );
225
226 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
227 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
228 unsafe extern "C" fn read_texture_async_trampoline<
229 P: FnOnce(Result<Option<Texture>, glib::Error>) + 'static,
230 >(
231 _source_object: *mut glib::gobject_ffi::GObject,
232 res: *mut gio::ffi::GAsyncResult,
233 user_data: glib::ffi::gpointer,
234 ) {
235 let mut error = std::ptr::null_mut();
236 let ret =
237 ffi::gdk_clipboard_read_texture_finish(_source_object as *mut _, res, &mut error);
238 let result = if error.is_null() {
239 Ok(from_glib_full(ret))
240 } else {
241 Err(from_glib_full(error))
242 };
243 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
244 Box_::from_raw(user_data as *mut _);
245 let callback: P = callback.into_inner();
246 callback(result);
247 }
248 let callback = read_texture_async_trampoline::<P>;
249 unsafe {
250 ffi::gdk_clipboard_read_texture_async(
251 self.to_glib_none().0,
252 cancellable.map(|p| p.as_ref()).to_glib_none().0,
253 Some(callback),
254 Box_::into_raw(user_data) as *mut _,
255 );
256 }
257 }
258
259 pub fn read_texture_future(
260 &self,
261 ) -> Pin<Box_<dyn std::future::Future<Output = Result<Option<Texture>, glib::Error>> + 'static>>
262 {
263 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
264 obj.read_texture_async(Some(cancellable), move |res| {
265 send.resolve(res);
266 });
267 }))
268 }
269
270 #[doc(alias = "gdk_clipboard_read_value_async")]
285 pub fn read_value_async<P: FnOnce(Result<glib::Value, glib::Error>) + 'static>(
286 &self,
287 type_: glib::types::Type,
288 io_priority: glib::Priority,
289 cancellable: Option<&impl IsA<gio::Cancellable>>,
290 callback: P,
291 ) {
292 let main_context = glib::MainContext::ref_thread_default();
293 let is_main_context_owner = main_context.is_owner();
294 let has_acquired_main_context = (!is_main_context_owner)
295 .then(|| main_context.acquire().ok())
296 .flatten();
297 assert!(
298 is_main_context_owner || has_acquired_main_context.is_some(),
299 "Async operations only allowed if the thread is owning the MainContext"
300 );
301
302 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
303 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
304 unsafe extern "C" fn read_value_async_trampoline<
305 P: FnOnce(Result<glib::Value, glib::Error>) + 'static,
306 >(
307 _source_object: *mut glib::gobject_ffi::GObject,
308 res: *mut gio::ffi::GAsyncResult,
309 user_data: glib::ffi::gpointer,
310 ) {
311 let mut error = std::ptr::null_mut();
312 let ret =
313 ffi::gdk_clipboard_read_value_finish(_source_object as *mut _, res, &mut error);
314 let result = if error.is_null() {
315 Ok(from_glib_none(ret))
316 } else {
317 Err(from_glib_full(error))
318 };
319 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
320 Box_::from_raw(user_data as *mut _);
321 let callback: P = callback.into_inner();
322 callback(result);
323 }
324 let callback = read_value_async_trampoline::<P>;
325 unsafe {
326 ffi::gdk_clipboard_read_value_async(
327 self.to_glib_none().0,
328 type_.into_glib(),
329 io_priority.into_glib(),
330 cancellable.map(|p| p.as_ref()).to_glib_none().0,
331 Some(callback),
332 Box_::into_raw(user_data) as *mut _,
333 );
334 }
335 }
336
337 pub fn read_value_future(
338 &self,
339 type_: glib::types::Type,
340 io_priority: glib::Priority,
341 ) -> Pin<Box_<dyn std::future::Future<Output = Result<glib::Value, glib::Error>> + 'static>>
342 {
343 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
344 obj.read_value_async(type_, io_priority, Some(cancellable), move |res| {
345 send.resolve(res);
346 });
347 }))
348 }
349
350 #[doc(alias = "gdk_clipboard_set_content")]
370 pub fn set_content(
371 &self,
372 provider: Option<&impl IsA<ContentProvider>>,
373 ) -> Result<(), glib::error::BoolError> {
374 unsafe {
375 glib::result_from_gboolean!(
376 ffi::gdk_clipboard_set_content(
377 self.to_glib_none().0,
378 provider.map(|p| p.as_ref()).to_glib_none().0
379 ),
380 "Can't set new clipboard content"
381 )
382 }
383 }
384
385 #[doc(alias = "gdk_clipboard_set_text")]
389 pub fn set_text(&self, text: &str) {
390 unsafe {
391 ffi::gdk_clipboard_set_text(self.to_glib_none().0, text.to_glib_none().0);
392 }
393 }
394
395 #[doc(alias = "gdk_clipboard_set_texture")]
399 pub fn set_texture(&self, texture: &impl IsA<Texture>) {
400 unsafe {
401 ffi::gdk_clipboard_set_texture(
402 self.to_glib_none().0,
403 texture.as_ref().to_glib_none().0,
404 );
405 }
406 }
407
408 #[doc(alias = "gdk_clipboard_store_async")]
427 pub fn store_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
428 &self,
429 io_priority: glib::Priority,
430 cancellable: Option<&impl IsA<gio::Cancellable>>,
431 callback: P,
432 ) {
433 let main_context = glib::MainContext::ref_thread_default();
434 let is_main_context_owner = main_context.is_owner();
435 let has_acquired_main_context = (!is_main_context_owner)
436 .then(|| main_context.acquire().ok())
437 .flatten();
438 assert!(
439 is_main_context_owner || has_acquired_main_context.is_some(),
440 "Async operations only allowed if the thread is owning the MainContext"
441 );
442
443 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
444 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
445 unsafe extern "C" fn store_async_trampoline<
446 P: FnOnce(Result<(), glib::Error>) + 'static,
447 >(
448 _source_object: *mut glib::gobject_ffi::GObject,
449 res: *mut gio::ffi::GAsyncResult,
450 user_data: glib::ffi::gpointer,
451 ) {
452 let mut error = std::ptr::null_mut();
453 ffi::gdk_clipboard_store_finish(_source_object as *mut _, res, &mut error);
454 let result = if error.is_null() {
455 Ok(())
456 } else {
457 Err(from_glib_full(error))
458 };
459 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
460 Box_::from_raw(user_data as *mut _);
461 let callback: P = callback.into_inner();
462 callback(result);
463 }
464 let callback = store_async_trampoline::<P>;
465 unsafe {
466 ffi::gdk_clipboard_store_async(
467 self.to_glib_none().0,
468 io_priority.into_glib(),
469 cancellable.map(|p| p.as_ref()).to_glib_none().0,
470 Some(callback),
471 Box_::into_raw(user_data) as *mut _,
472 );
473 }
474 }
475
476 pub fn store_future(
477 &self,
478 io_priority: glib::Priority,
479 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
480 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
481 obj.store_async(io_priority, Some(cancellable), move |res| {
482 send.resolve(res);
483 });
484 }))
485 }
486
487 #[doc(alias = "changed")]
489 pub fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
490 unsafe extern "C" fn changed_trampoline<F: Fn(&Clipboard) + 'static>(
491 this: *mut ffi::GdkClipboard,
492 f: glib::ffi::gpointer,
493 ) {
494 let f: &F = &*(f as *const F);
495 f(&from_glib_borrow(this))
496 }
497 unsafe {
498 let f: Box_<F> = Box_::new(f);
499 connect_raw(
500 self.as_ptr() as *mut _,
501 c"changed".as_ptr() as *const _,
502 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
503 changed_trampoline::<F> as *const (),
504 )),
505 Box_::into_raw(f),
506 )
507 }
508 }
509
510 #[doc(alias = "content")]
511 pub fn connect_content_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
512 unsafe extern "C" fn notify_content_trampoline<F: Fn(&Clipboard) + 'static>(
513 this: *mut ffi::GdkClipboard,
514 _param_spec: glib::ffi::gpointer,
515 f: glib::ffi::gpointer,
516 ) {
517 let f: &F = &*(f as *const F);
518 f(&from_glib_borrow(this))
519 }
520 unsafe {
521 let f: Box_<F> = Box_::new(f);
522 connect_raw(
523 self.as_ptr() as *mut _,
524 c"notify::content".as_ptr() as *const _,
525 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
526 notify_content_trampoline::<F> as *const (),
527 )),
528 Box_::into_raw(f),
529 )
530 }
531 }
532
533 #[doc(alias = "formats")]
534 pub fn connect_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
535 unsafe extern "C" fn notify_formats_trampoline<F: Fn(&Clipboard) + 'static>(
536 this: *mut ffi::GdkClipboard,
537 _param_spec: glib::ffi::gpointer,
538 f: glib::ffi::gpointer,
539 ) {
540 let f: &F = &*(f as *const F);
541 f(&from_glib_borrow(this))
542 }
543 unsafe {
544 let f: Box_<F> = Box_::new(f);
545 connect_raw(
546 self.as_ptr() as *mut _,
547 c"notify::formats".as_ptr() as *const _,
548 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
549 notify_formats_trampoline::<F> as *const (),
550 )),
551 Box_::into_raw(f),
552 )
553 }
554 }
555
556 #[doc(alias = "local")]
557 pub fn connect_local_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
558 unsafe extern "C" fn notify_local_trampoline<F: Fn(&Clipboard) + 'static>(
559 this: *mut ffi::GdkClipboard,
560 _param_spec: glib::ffi::gpointer,
561 f: glib::ffi::gpointer,
562 ) {
563 let f: &F = &*(f as *const F);
564 f(&from_glib_borrow(this))
565 }
566 unsafe {
567 let f: Box_<F> = Box_::new(f);
568 connect_raw(
569 self.as_ptr() as *mut _,
570 c"notify::local".as_ptr() as *const _,
571 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
572 notify_local_trampoline::<F> as *const (),
573 )),
574 Box_::into_raw(f),
575 )
576 }
577 }
578}