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
// Take a look at the license at the top of the repository in the LICENSE file.

use std::{mem::transmute, ptr};

use glib::{
    signal::{connect_raw, SignalHandlerId},
    translate::*,
};

use crate::{prelude::*, Overlay, Widget};

impl Overlay {
    /// Emitted to determine the position and size of any overlay
    /// child widgets.
    ///
    /// A handler for this signal should fill @allocation with
    /// the desired position and size for @widget, relative to
    /// the 'main' child of @overlay.
    ///
    /// The default handler for this signal uses the @widget's
    /// halign and valign properties to determine the position
    /// and gives the widget its natural size (except that an
    /// alignment of [`Align::Fill`][crate::Align::Fill] will cause the overlay to
    /// be full-width/height). If the main child is a
    /// [`ScrolledWindow`][crate::ScrolledWindow], the overlays are placed relative
    /// to its contents.
    /// ## `widget`
    /// the child widget to position
    ///
    /// # Returns
    ///
    /// [`true`] if the @allocation has been filled
    ///
    /// ## `allocation`
    /// return
    ///   location for the allocation
    pub fn connect_get_child_position<F>(&self, f: F) -> SignalHandlerId
    where
        F: Fn(&Self, &Widget) -> Option<gdk::Rectangle> + 'static,
    {
        unsafe {
            let f: Box<F> = Box::new(f);
            connect_raw(
                self.as_ptr() as *mut _,
                b"get-child-position\0".as_ptr() as *mut _,
                Some(transmute(get_child_position_trampoline::<F> as usize)),
                Box::into_raw(f),
            )
        }
    }
}

unsafe extern "C" fn get_child_position_trampoline<
    F: Fn(&Overlay, &Widget) -> Option<gdk::Rectangle> + 'static,
>(
    this: *mut ffi::GtkOverlay,
    widget: *mut ffi::GtkWidget,
    allocation: *mut gdk::ffi::GdkRectangle,
    f: glib::ffi::gpointer,
) -> glib::ffi::gboolean {
    let f: &F = &*(f as *const F);
    match f(
        Overlay::from_glib_borrow(this).unsafe_cast_ref(),
        &from_glib_borrow(widget),
    ) {
        Some(rect) => {
            ptr::write(allocation, ptr::read(rect.to_glib_none().0));
            true
        }
        None => false,
    }
    .into_glib()
}