1use glib::translate::*;
6use glib_sys::gpointer;
7use gtk_sys;
8use libc::c_uint;
9use std::boxed::Box as Box_;
10use Clipboard;
11use SelectionData;
12use TargetEntry;
13
14impl Clipboard {
15 pub fn set_with_data<F: Fn(&Clipboard, &SelectionData, u32) + 'static>(
16 &self,
17 targets: &[TargetEntry],
18 f: F,
19 ) -> bool {
20 unsafe extern "C" fn trampoline<F: Fn(&Clipboard, &SelectionData, u32) + 'static>(
21 clipboard: *mut gtk_sys::GtkClipboard,
22 selection_data: *mut gtk_sys::GtkSelectionData,
23 info: c_uint,
24 user_data: gpointer,
25 ) {
26 let f: &F = &*(user_data as *const F);
27 f(
28 &from_glib_borrow(clipboard),
29 &from_glib_borrow(selection_data),
30 info,
31 );
32 }
33 unsafe extern "C" fn cleanup<F: Fn(&Clipboard, &SelectionData, u32) + 'static>(
34 _clipboard: *mut gtk_sys::GtkClipboard,
35 user_data: gpointer,
36 ) {
37 Box_::<F>::from_raw(user_data as *mut _);
38 }
39 let stashed_targets: Vec<_> = targets.iter().map(|e| e.to_glib_none()).collect();
40 let mut t = Vec::with_capacity(stashed_targets.len());
41 for stash in &stashed_targets {
42 unsafe {
43 t.push(gtk_sys::GtkTargetEntry {
44 target: (*stash.0).target,
45 flags: (*stash.0).flags,
46 info: (*stash.0).info,
47 });
48 }
49 }
50 let t_ptr: *mut gtk_sys::GtkTargetEntry = t.as_mut_ptr();
51 let f: Box_<F> = Box_::new(f);
52 let user_data = Box_::into_raw(f) as *mut _;
53 let success: bool = unsafe {
54 from_glib(gtk_sys::gtk_clipboard_set_with_data(
55 self.to_glib_none().0,
56 t_ptr,
57 t.len() as c_uint,
58 Some(trampoline::<F>),
59 Some(cleanup::<F>),
60 user_data,
61 ))
62 };
63 if !success {
64 unsafe {
66 Box_::<F>::from_raw(user_data as *mut _);
67 }
68 }
69 success
70 }
71}