1use crate::{ffi, ContentFormats, Device, Display, Drag, DragAction, Surface};
6use glib::{
7 prelude::*,
8 signal::{connect_raw, SignalHandlerId},
9 translate::*,
10};
11use std::{boxed::Box as Box_, pin::Pin};
12
13glib::wrapper! {
14 #[doc(alias = "GdkDrop")]
15 pub struct Drop(Object<ffi::GdkDrop>);
16
17 match fn {
18 type_ => || ffi::gdk_drop_get_type(),
19 }
20}
21
22impl Drop {
23 #[doc(alias = "gdk_drop_finish")]
24 pub fn finish(&self, action: DragAction) {
25 unsafe {
26 ffi::gdk_drop_finish(self.to_glib_none().0, action.into_glib());
27 }
28 }
29
30 #[doc(alias = "gdk_drop_get_actions")]
31 #[doc(alias = "get_actions")]
32 pub fn actions(&self) -> DragAction {
33 unsafe { from_glib(ffi::gdk_drop_get_actions(self.to_glib_none().0)) }
34 }
35
36 #[doc(alias = "gdk_drop_get_device")]
37 #[doc(alias = "get_device")]
38 pub fn device(&self) -> Device {
39 unsafe { from_glib_none(ffi::gdk_drop_get_device(self.to_glib_none().0)) }
40 }
41
42 #[doc(alias = "gdk_drop_get_display")]
43 #[doc(alias = "get_display")]
44 pub fn display(&self) -> Display {
45 unsafe { from_glib_none(ffi::gdk_drop_get_display(self.to_glib_none().0)) }
46 }
47
48 #[doc(alias = "gdk_drop_get_drag")]
49 #[doc(alias = "get_drag")]
50 pub fn drag(&self) -> Option<Drag> {
51 unsafe { from_glib_none(ffi::gdk_drop_get_drag(self.to_glib_none().0)) }
52 }
53
54 #[doc(alias = "gdk_drop_get_formats")]
55 #[doc(alias = "get_formats")]
56 pub fn formats(&self) -> ContentFormats {
57 unsafe { from_glib_none(ffi::gdk_drop_get_formats(self.to_glib_none().0)) }
58 }
59
60 #[doc(alias = "gdk_drop_get_surface")]
61 #[doc(alias = "get_surface")]
62 pub fn surface(&self) -> Surface {
63 unsafe { from_glib_none(ffi::gdk_drop_get_surface(self.to_glib_none().0)) }
64 }
65
66 #[doc(alias = "gdk_drop_read_value_async")]
67 pub fn read_value_async<P: FnOnce(Result<glib::Value, glib::Error>) + 'static>(
68 &self,
69 type_: glib::types::Type,
70 io_priority: glib::Priority,
71 cancellable: Option<&impl IsA<gio::Cancellable>>,
72 callback: P,
73 ) {
74 let main_context = glib::MainContext::ref_thread_default();
75 let is_main_context_owner = main_context.is_owner();
76 let has_acquired_main_context = (!is_main_context_owner)
77 .then(|| main_context.acquire().ok())
78 .flatten();
79 assert!(
80 is_main_context_owner || has_acquired_main_context.is_some(),
81 "Async operations only allowed if the thread is owning the MainContext"
82 );
83
84 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
85 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
86 unsafe extern "C" fn read_value_async_trampoline<
87 P: FnOnce(Result<glib::Value, glib::Error>) + 'static,
88 >(
89 _source_object: *mut glib::gobject_ffi::GObject,
90 res: *mut gio::ffi::GAsyncResult,
91 user_data: glib::ffi::gpointer,
92 ) {
93 let mut error = std::ptr::null_mut();
94 let ret = ffi::gdk_drop_read_value_finish(_source_object as *mut _, res, &mut error);
95 let result = if error.is_null() {
96 Ok(from_glib_none(ret))
97 } else {
98 Err(from_glib_full(error))
99 };
100 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
101 Box_::from_raw(user_data as *mut _);
102 let callback: P = callback.into_inner();
103 callback(result);
104 }
105 let callback = read_value_async_trampoline::<P>;
106 unsafe {
107 ffi::gdk_drop_read_value_async(
108 self.to_glib_none().0,
109 type_.into_glib(),
110 io_priority.into_glib(),
111 cancellable.map(|p| p.as_ref()).to_glib_none().0,
112 Some(callback),
113 Box_::into_raw(user_data) as *mut _,
114 );
115 }
116 }
117
118 pub fn read_value_future(
119 &self,
120 type_: glib::types::Type,
121 io_priority: glib::Priority,
122 ) -> Pin<Box_<dyn std::future::Future<Output = Result<glib::Value, glib::Error>> + 'static>>
123 {
124 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
125 obj.read_value_async(type_, io_priority, Some(cancellable), move |res| {
126 send.resolve(res);
127 });
128 }))
129 }
130
131 #[doc(alias = "gdk_drop_status")]
132 pub fn status(&self, actions: DragAction, preferred: DragAction) {
133 unsafe {
134 ffi::gdk_drop_status(
135 self.to_glib_none().0,
136 actions.into_glib(),
137 preferred.into_glib(),
138 );
139 }
140 }
141
142 #[doc(alias = "display")]
143 pub fn connect_display_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
144 unsafe extern "C" fn notify_display_trampoline<F: Fn(&Drop) + 'static>(
145 this: *mut ffi::GdkDrop,
146 _param_spec: glib::ffi::gpointer,
147 f: glib::ffi::gpointer,
148 ) {
149 let f: &F = &*(f as *const F);
150 f(&from_glib_borrow(this))
151 }
152 unsafe {
153 let f: Box_<F> = Box_::new(f);
154 connect_raw(
155 self.as_ptr() as *mut _,
156 c"notify::display".as_ptr() as *const _,
157 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
158 notify_display_trampoline::<F> as *const (),
159 )),
160 Box_::into_raw(f),
161 )
162 }
163 }
164}