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