1use crate::{ContentFormats, ContentProvider, Display, Texture, ffi};
6use glib::{
7 object::ObjectType as _,
8 prelude::*,
9 signal::{SignalHandlerId, connect_raw},
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 unsafe {
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 }
178 let callback = read_text_async_trampoline::<P>;
179 unsafe {
180 ffi::gdk_clipboard_read_text_async(
181 self.to_glib_none().0,
182 cancellable.map(|p| p.as_ref()).to_glib_none().0,
183 Some(callback),
184 Box_::into_raw(user_data) as *mut _,
185 );
186 }
187 }
188
189 pub fn read_text_future(
190 &self,
191 ) -> Pin<
192 Box_<
193 dyn std::future::Future<Output = Result<Option<glib::GString>, glib::Error>> + 'static,
194 >,
195 > {
196 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
197 obj.read_text_async(Some(cancellable), move |res| {
198 send.resolve(res);
199 });
200 }))
201 }
202
203 #[doc(alias = "gdk_clipboard_read_texture_async")]
213 pub fn read_texture_async<P: FnOnce(Result<Option<Texture>, glib::Error>) + 'static>(
214 &self,
215 cancellable: Option<&impl IsA<gio::Cancellable>>,
216 callback: P,
217 ) {
218 let main_context = glib::MainContext::ref_thread_default();
219 let is_main_context_owner = main_context.is_owner();
220 let has_acquired_main_context = (!is_main_context_owner)
221 .then(|| main_context.acquire().ok())
222 .flatten();
223 assert!(
224 is_main_context_owner || has_acquired_main_context.is_some(),
225 "Async operations only allowed if the thread is owning the MainContext"
226 );
227
228 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
229 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
230 unsafe extern "C" fn read_texture_async_trampoline<
231 P: FnOnce(Result<Option<Texture>, glib::Error>) + 'static,
232 >(
233 _source_object: *mut glib::gobject_ffi::GObject,
234 res: *mut gio::ffi::GAsyncResult,
235 user_data: glib::ffi::gpointer,
236 ) {
237 unsafe {
238 let mut error = std::ptr::null_mut();
239 let ret = ffi::gdk_clipboard_read_texture_finish(
240 _source_object as *mut _,
241 res,
242 &mut error,
243 );
244 let result = if error.is_null() {
245 Ok(from_glib_full(ret))
246 } else {
247 Err(from_glib_full(error))
248 };
249 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
250 Box_::from_raw(user_data as *mut _);
251 let callback: P = callback.into_inner();
252 callback(result);
253 }
254 }
255 let callback = read_texture_async_trampoline::<P>;
256 unsafe {
257 ffi::gdk_clipboard_read_texture_async(
258 self.to_glib_none().0,
259 cancellable.map(|p| p.as_ref()).to_glib_none().0,
260 Some(callback),
261 Box_::into_raw(user_data) as *mut _,
262 );
263 }
264 }
265
266 pub fn read_texture_future(
267 &self,
268 ) -> Pin<Box_<dyn std::future::Future<Output = Result<Option<Texture>, glib::Error>> + 'static>>
269 {
270 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
271 obj.read_texture_async(Some(cancellable), move |res| {
272 send.resolve(res);
273 });
274 }))
275 }
276
277 #[doc(alias = "gdk_clipboard_read_value_async")]
292 pub fn read_value_async<P: FnOnce(Result<glib::Value, glib::Error>) + 'static>(
293 &self,
294 type_: glib::types::Type,
295 io_priority: glib::Priority,
296 cancellable: Option<&impl IsA<gio::Cancellable>>,
297 callback: P,
298 ) {
299 let main_context = glib::MainContext::ref_thread_default();
300 let is_main_context_owner = main_context.is_owner();
301 let has_acquired_main_context = (!is_main_context_owner)
302 .then(|| main_context.acquire().ok())
303 .flatten();
304 assert!(
305 is_main_context_owner || has_acquired_main_context.is_some(),
306 "Async operations only allowed if the thread is owning the MainContext"
307 );
308
309 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
310 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
311 unsafe extern "C" fn read_value_async_trampoline<
312 P: FnOnce(Result<glib::Value, glib::Error>) + 'static,
313 >(
314 _source_object: *mut glib::gobject_ffi::GObject,
315 res: *mut gio::ffi::GAsyncResult,
316 user_data: glib::ffi::gpointer,
317 ) {
318 unsafe {
319 let mut error = std::ptr::null_mut();
320 let ret =
321 ffi::gdk_clipboard_read_value_finish(_source_object as *mut _, res, &mut error);
322 let result = if error.is_null() {
323 Ok(from_glib_none(ret))
324 } else {
325 Err(from_glib_full(error))
326 };
327 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
328 Box_::from_raw(user_data as *mut _);
329 let callback: P = callback.into_inner();
330 callback(result);
331 }
332 }
333 let callback = read_value_async_trampoline::<P>;
334 unsafe {
335 ffi::gdk_clipboard_read_value_async(
336 self.to_glib_none().0,
337 type_.into_glib(),
338 io_priority.into_glib(),
339 cancellable.map(|p| p.as_ref()).to_glib_none().0,
340 Some(callback),
341 Box_::into_raw(user_data) as *mut _,
342 );
343 }
344 }
345
346 pub fn read_value_future(
347 &self,
348 type_: glib::types::Type,
349 io_priority: glib::Priority,
350 ) -> Pin<Box_<dyn std::future::Future<Output = Result<glib::Value, glib::Error>> + 'static>>
351 {
352 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
353 obj.read_value_async(type_, io_priority, Some(cancellable), move |res| {
354 send.resolve(res);
355 });
356 }))
357 }
358
359 #[doc(alias = "gdk_clipboard_set_content")]
379 pub fn set_content(
380 &self,
381 provider: Option<&impl IsA<ContentProvider>>,
382 ) -> Result<(), glib::error::BoolError> {
383 unsafe {
384 glib::result_from_gboolean!(
385 ffi::gdk_clipboard_set_content(
386 self.to_glib_none().0,
387 provider.map(|p| p.as_ref()).to_glib_none().0
388 ),
389 "Can't set new clipboard content"
390 )
391 }
392 }
393
394 #[doc(alias = "gdk_clipboard_set_text")]
398 pub fn set_text(&self, text: &str) {
399 unsafe {
400 ffi::gdk_clipboard_set_text(self.to_glib_none().0, text.to_glib_none().0);
401 }
402 }
403
404 #[doc(alias = "gdk_clipboard_set_texture")]
408 pub fn set_texture(&self, texture: &impl IsA<Texture>) {
409 unsafe {
410 ffi::gdk_clipboard_set_texture(
411 self.to_glib_none().0,
412 texture.as_ref().to_glib_none().0,
413 );
414 }
415 }
416
417 #[doc(alias = "gdk_clipboard_store_async")]
436 pub fn store_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
437 &self,
438 io_priority: glib::Priority,
439 cancellable: Option<&impl IsA<gio::Cancellable>>,
440 callback: P,
441 ) {
442 let main_context = glib::MainContext::ref_thread_default();
443 let is_main_context_owner = main_context.is_owner();
444 let has_acquired_main_context = (!is_main_context_owner)
445 .then(|| main_context.acquire().ok())
446 .flatten();
447 assert!(
448 is_main_context_owner || has_acquired_main_context.is_some(),
449 "Async operations only allowed if the thread is owning the MainContext"
450 );
451
452 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
453 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
454 unsafe extern "C" fn store_async_trampoline<
455 P: FnOnce(Result<(), glib::Error>) + 'static,
456 >(
457 _source_object: *mut glib::gobject_ffi::GObject,
458 res: *mut gio::ffi::GAsyncResult,
459 user_data: glib::ffi::gpointer,
460 ) {
461 unsafe {
462 let mut error = std::ptr::null_mut();
463 ffi::gdk_clipboard_store_finish(_source_object as *mut _, res, &mut error);
464 let result = if error.is_null() {
465 Ok(())
466 } else {
467 Err(from_glib_full(error))
468 };
469 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
470 Box_::from_raw(user_data as *mut _);
471 let callback: P = callback.into_inner();
472 callback(result);
473 }
474 }
475 let callback = store_async_trampoline::<P>;
476 unsafe {
477 ffi::gdk_clipboard_store_async(
478 self.to_glib_none().0,
479 io_priority.into_glib(),
480 cancellable.map(|p| p.as_ref()).to_glib_none().0,
481 Some(callback),
482 Box_::into_raw(user_data) as *mut _,
483 );
484 }
485 }
486
487 pub fn store_future(
488 &self,
489 io_priority: glib::Priority,
490 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
491 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
492 obj.store_async(io_priority, Some(cancellable), move |res| {
493 send.resolve(res);
494 });
495 }))
496 }
497
498 #[doc(alias = "changed")]
500 pub fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
501 unsafe extern "C" fn changed_trampoline<F: Fn(&Clipboard) + 'static>(
502 this: *mut ffi::GdkClipboard,
503 f: glib::ffi::gpointer,
504 ) {
505 unsafe {
506 let f: &F = &*(f as *const F);
507 f(&from_glib_borrow(this))
508 }
509 }
510 unsafe {
511 let f: Box_<F> = Box_::new(f);
512 connect_raw(
513 self.as_ptr() as *mut _,
514 c"changed".as_ptr() as *const _,
515 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
516 changed_trampoline::<F> as *const (),
517 )),
518 Box_::into_raw(f),
519 )
520 }
521 }
522
523 #[doc(alias = "content")]
524 pub fn connect_content_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
525 unsafe extern "C" fn notify_content_trampoline<F: Fn(&Clipboard) + 'static>(
526 this: *mut ffi::GdkClipboard,
527 _param_spec: glib::ffi::gpointer,
528 f: glib::ffi::gpointer,
529 ) {
530 unsafe {
531 let f: &F = &*(f as *const F);
532 f(&from_glib_borrow(this))
533 }
534 }
535 unsafe {
536 let f: Box_<F> = Box_::new(f);
537 connect_raw(
538 self.as_ptr() as *mut _,
539 c"notify::content".as_ptr() as *const _,
540 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
541 notify_content_trampoline::<F> as *const (),
542 )),
543 Box_::into_raw(f),
544 )
545 }
546 }
547
548 #[doc(alias = "formats")]
549 pub fn connect_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
550 unsafe extern "C" fn notify_formats_trampoline<F: Fn(&Clipboard) + 'static>(
551 this: *mut ffi::GdkClipboard,
552 _param_spec: glib::ffi::gpointer,
553 f: glib::ffi::gpointer,
554 ) {
555 unsafe {
556 let f: &F = &*(f as *const F);
557 f(&from_glib_borrow(this))
558 }
559 }
560 unsafe {
561 let f: Box_<F> = Box_::new(f);
562 connect_raw(
563 self.as_ptr() as *mut _,
564 c"notify::formats".as_ptr() as *const _,
565 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
566 notify_formats_trampoline::<F> as *const (),
567 )),
568 Box_::into_raw(f),
569 )
570 }
571 }
572
573 #[doc(alias = "local")]
574 pub fn connect_local_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
575 unsafe extern "C" fn notify_local_trampoline<F: Fn(&Clipboard) + 'static>(
576 this: *mut ffi::GdkClipboard,
577 _param_spec: glib::ffi::gpointer,
578 f: glib::ffi::gpointer,
579 ) {
580 unsafe {
581 let f: &F = &*(f as *const F);
582 f(&from_glib_borrow(this))
583 }
584 }
585 unsafe {
586 let f: Box_<F> = Box_::new(f);
587 connect_raw(
588 self.as_ptr() as *mut _,
589 c"notify::local".as_ptr() as *const _,
590 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
591 notify_local_trampoline::<F> as *const (),
592 )),
593 Box_::into_raw(f),
594 )
595 }
596 }
597}