1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// DO NOT EDIT

use crate::Atom;
use crate::Device;
use crate::DragAction;
use crate::DragCancelReason;
use crate::DragProtocol;
use crate::Window;
use glib::object::ObjectType as ObjectType_;
use glib::signal::connect_raw;
use glib::signal::SignalHandlerId;
use glib::translate::*;
use std::boxed::Box as Box_;
use std::fmt;
use std::mem::transmute;

glib::wrapper! {
    ///
    #[doc(alias = "GdkDragContext")]
    pub struct DragContext(Object<ffi::GdkDragContext>);

    match fn {
        type_ => || ffi::gdk_drag_context_get_type(),
    }
}

impl DragContext {
    /// Determines the bitmask of actions proposed by the source if
    /// [`suggested_action()`][Self::suggested_action()] returns [`DragAction::ASK`][crate::DragAction::ASK].
    ///
    /// # Returns
    ///
    /// the [`DragAction`][crate::DragAction] flags
    #[doc(alias = "gdk_drag_context_get_actions")]
    #[doc(alias = "get_actions")]
    pub fn actions(&self) -> DragAction {
        unsafe { from_glib(ffi::gdk_drag_context_get_actions(self.to_glib_none().0)) }
    }

    /// Returns the destination window for the DND operation.
    ///
    /// # Returns
    ///
    /// a [`Window`][crate::Window]
    #[doc(alias = "gdk_drag_context_get_dest_window")]
    #[doc(alias = "get_dest_window")]
    pub fn dest_window(&self) -> Window {
        unsafe { from_glib_none(ffi::gdk_drag_context_get_dest_window(self.to_glib_none().0)) }
    }

    /// Returns the [`Device`][crate::Device] associated to the drag context.
    ///
    /// # Returns
    ///
    /// The [`Device`][crate::Device] associated to `self`.
    #[doc(alias = "gdk_drag_context_get_device")]
    #[doc(alias = "get_device")]
    pub fn device(&self) -> Device {
        unsafe { from_glib_none(ffi::gdk_drag_context_get_device(self.to_glib_none().0)) }
    }

    /// Returns the window on which the drag icon should be rendered
    /// during the drag operation. Note that the window may not be
    /// available until the drag operation has begun. GDK will move
    /// the window in accordance with the ongoing drag operation.
    /// The window is owned by `self` and will be destroyed when
    /// the drag operation is over.
    ///
    /// # Returns
    ///
    /// the drag window, or [`None`]
    #[doc(alias = "gdk_drag_context_get_drag_window")]
    #[doc(alias = "get_drag_window")]
    pub fn drag_window(&self) -> Option<Window> {
        unsafe { from_glib_none(ffi::gdk_drag_context_get_drag_window(self.to_glib_none().0)) }
    }

    /// Returns the drag protocol that is used by this context.
    ///
    /// # Returns
    ///
    /// the drag protocol
    #[doc(alias = "gdk_drag_context_get_protocol")]
    #[doc(alias = "get_protocol")]
    pub fn protocol(&self) -> DragProtocol {
        unsafe { from_glib(ffi::gdk_drag_context_get_protocol(self.to_glib_none().0)) }
    }

    /// Determines the action chosen by the drag destination.
    ///
    /// # Returns
    ///
    /// a [`DragAction`][crate::DragAction] value
    #[doc(alias = "gdk_drag_context_get_selected_action")]
    #[doc(alias = "get_selected_action")]
    pub fn selected_action(&self) -> DragAction {
        unsafe {
            from_glib(ffi::gdk_drag_context_get_selected_action(
                self.to_glib_none().0,
            ))
        }
    }

    /// Returns the [`Window`][crate::Window] where the DND operation started.
    ///
    /// # Returns
    ///
    /// a [`Window`][crate::Window]
    #[doc(alias = "gdk_drag_context_get_source_window")]
    #[doc(alias = "get_source_window")]
    pub fn source_window(&self) -> Window {
        unsafe {
            from_glib_none(ffi::gdk_drag_context_get_source_window(
                self.to_glib_none().0,
            ))
        }
    }

    /// Determines the suggested drag action of the context.
    ///
    /// # Returns
    ///
    /// a [`DragAction`][crate::DragAction] value
    #[doc(alias = "gdk_drag_context_get_suggested_action")]
    #[doc(alias = "get_suggested_action")]
    pub fn suggested_action(&self) -> DragAction {
        unsafe {
            from_glib(ffi::gdk_drag_context_get_suggested_action(
                self.to_glib_none().0,
            ))
        }
    }

    /// Retrieves the list of targets of the context.
    ///
    /// # Returns
    ///
    /// a `GList` of targets
    #[doc(alias = "gdk_drag_context_list_targets")]
    pub fn list_targets(&self) -> Vec<Atom> {
        unsafe {
            FromGlibPtrContainer::from_glib_none(ffi::gdk_drag_context_list_targets(
                self.to_glib_none().0,
            ))
        }
    }

    /// Requests the drag and drop operation to be managed by `self`.
    /// When a drag and drop operation becomes managed, the [`DragContext`][crate::DragContext]
    /// will internally handle all input and source-side [`EventDND`][crate::EventDND] events
    /// as required by the windowing system.
    ///
    /// Once the drag and drop operation is managed, the drag context will
    /// emit the following signals:
    /// - The `signal::DragContext::action-changed` signal whenever the final action
    ///  to be performed by the drag and drop operation changes.
    /// - The `signal::DragContext::drop-performed` signal after the user performs
    ///  the drag and drop gesture (typically by releasing the mouse button).
    /// - The `signal::DragContext::dnd-finished` signal after the drag and drop
    ///  operation concludes (after all `GdkSelection` transfers happen).
    /// - The `signal::DragContext::cancel` signal if the drag and drop operation is
    ///  finished but doesn't happen over an accepting destination, or is
    ///  cancelled through other means.
    /// ## `ipc_window`
    /// Window to use for IPC messaging/events
    /// ## `actions`
    /// the actions supported by the drag source
    ///
    /// # Returns
    ///
    /// [`true`] if the drag and drop operation is managed.
    #[doc(alias = "gdk_drag_context_manage_dnd")]
    pub fn manage_dnd(&self, ipc_window: &Window, actions: DragAction) -> bool {
        unsafe {
            from_glib(ffi::gdk_drag_context_manage_dnd(
                self.to_glib_none().0,
                ipc_window.to_glib_none().0,
                actions.into_glib(),
            ))
        }
    }

    /// Associates a [`Device`][crate::Device] to `self`, so all Drag and Drop events
    /// for `self` are emitted as if they came from this device.
    /// ## `device`
    /// a [`Device`][crate::Device]
    #[doc(alias = "gdk_drag_context_set_device")]
    pub fn set_device(&self, device: &Device) {
        unsafe {
            ffi::gdk_drag_context_set_device(self.to_glib_none().0, device.to_glib_none().0);
        }
    }

    /// Sets the position of the drag window that will be kept
    /// under the cursor hotspot. Initially, the hotspot is at the
    /// top left corner of the drag window.
    /// ## `hot_x`
    /// x coordinate of the drag window hotspot
    /// ## `hot_y`
    /// y coordinate of the drag window hotspot
    #[doc(alias = "gdk_drag_context_set_hotspot")]
    pub fn set_hotspot(&self, hot_x: i32, hot_y: i32) {
        unsafe {
            ffi::gdk_drag_context_set_hotspot(self.to_glib_none().0, hot_x, hot_y);
        }
    }

    /// A new action is being chosen for the drag and drop operation.
    ///
    /// This signal will only be emitted if the [`DragContext`][crate::DragContext] manages
    /// the drag and drop operation. See [`manage_dnd()`][Self::manage_dnd()]
    /// for more information.
    /// ## `action`
    /// The action currently chosen
    #[doc(alias = "action-changed")]
    pub fn connect_action_changed<F: Fn(&Self, DragAction) + 'static>(
        &self,
        f: F,
    ) -> SignalHandlerId {
        unsafe extern "C" fn action_changed_trampoline<
            F: Fn(&DragContext, DragAction) + 'static,
        >(
            this: *mut ffi::GdkDragContext,
            action: ffi::GdkDragAction,
            f: glib::ffi::gpointer,
        ) {
            let f: &F = &*(f as *const F);
            f(&from_glib_borrow(this), from_glib(action))
        }
        unsafe {
            let f: Box_<F> = Box_::new(f);
            connect_raw(
                self.as_ptr() as *mut _,
                b"action-changed\0".as_ptr() as *const _,
                Some(transmute::<_, unsafe extern "C" fn()>(
                    action_changed_trampoline::<F> as *const (),
                )),
                Box_::into_raw(f),
            )
        }
    }

    /// The drag and drop operation was cancelled.
    ///
    /// This signal will only be emitted if the [`DragContext`][crate::DragContext] manages
    /// the drag and drop operation. See [`manage_dnd()`][Self::manage_dnd()]
    /// for more information.
    /// ## `reason`
    /// The reason the context was cancelled
    #[doc(alias = "cancel")]
    pub fn connect_cancel<F: Fn(&Self, DragCancelReason) + 'static>(
        &self,
        f: F,
    ) -> SignalHandlerId {
        unsafe extern "C" fn cancel_trampoline<F: Fn(&DragContext, DragCancelReason) + 'static>(
            this: *mut ffi::GdkDragContext,
            reason: ffi::GdkDragCancelReason,
            f: glib::ffi::gpointer,
        ) {
            let f: &F = &*(f as *const F);
            f(&from_glib_borrow(this), from_glib(reason))
        }
        unsafe {
            let f: Box_<F> = Box_::new(f);
            connect_raw(
                self.as_ptr() as *mut _,
                b"cancel\0".as_ptr() as *const _,
                Some(transmute::<_, unsafe extern "C" fn()>(
                    cancel_trampoline::<F> as *const (),
                )),
                Box_::into_raw(f),
            )
        }
    }

    /// The drag and drop operation was finished, the drag destination
    /// finished reading all data. The drag source can now free all
    /// miscellaneous data.
    ///
    /// This signal will only be emitted if the [`DragContext`][crate::DragContext] manages
    /// the drag and drop operation. See [`manage_dnd()`][Self::manage_dnd()]
    /// for more information.
    #[doc(alias = "dnd-finished")]
    pub fn connect_dnd_finished<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
        unsafe extern "C" fn dnd_finished_trampoline<F: Fn(&DragContext) + 'static>(
            this: *mut ffi::GdkDragContext,
            f: glib::ffi::gpointer,
        ) {
            let f: &F = &*(f as *const F);
            f(&from_glib_borrow(this))
        }
        unsafe {
            let f: Box_<F> = Box_::new(f);
            connect_raw(
                self.as_ptr() as *mut _,
                b"dnd-finished\0".as_ptr() as *const _,
                Some(transmute::<_, unsafe extern "C" fn()>(
                    dnd_finished_trampoline::<F> as *const (),
                )),
                Box_::into_raw(f),
            )
        }
    }

    /// The drag and drop operation was performed on an accepting client.
    ///
    /// This signal will only be emitted if the [`DragContext`][crate::DragContext] manages
    /// the drag and drop operation. See [`manage_dnd()`][Self::manage_dnd()]
    /// for more information.
    /// ## `time`
    /// the time at which the drop happened.
    #[doc(alias = "drop-performed")]
    pub fn connect_drop_performed<F: Fn(&Self, i32) + 'static>(&self, f: F) -> SignalHandlerId {
        unsafe extern "C" fn drop_performed_trampoline<F: Fn(&DragContext, i32) + 'static>(
            this: *mut ffi::GdkDragContext,
            time: libc::c_int,
            f: glib::ffi::gpointer,
        ) {
            let f: &F = &*(f as *const F);
            f(&from_glib_borrow(this), time)
        }
        unsafe {
            let f: Box_<F> = Box_::new(f);
            connect_raw(
                self.as_ptr() as *mut _,
                b"drop-performed\0".as_ptr() as *const _,
                Some(transmute::<_, unsafe extern "C" fn()>(
                    drop_performed_trampoline::<F> as *const (),
                )),
                Box_::into_raw(f),
            )
        }
    }
}

impl fmt::Display for DragContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("DragContext")
    }
}