gtk/
clipboard.rs

1// Copyright 2018, The Gtk-rs Project Developers.
2// See the COPYRIGHT file at the top-level directory of this distribution.
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5use 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            // Cleanup function is not called in case of a failure.
65            unsafe {
66                Box_::<F>::from_raw(user_data as *mut _);
67            }
68        }
69        success
70    }
71}