gtk4/
overlay.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem::transmute, ptr};
4
5use glib::{
6    signal::{connect_raw, SignalHandlerId},
7    translate::*,
8};
9
10use crate::{ffi, prelude::*, Overlay, Widget};
11
12impl Overlay {
13    /// Emitted to determine the position and size of any overlay
14    /// child widgets.
15    ///
16    /// A handler for this signal should fill @allocation with
17    /// the desired position and size for @widget, relative to
18    /// the 'main' child of @overlay.
19    ///
20    /// The default handler for this signal uses the @widget's
21    /// halign and valign properties to determine the position
22    /// and gives the widget its natural size (except that an
23    /// alignment of [`Align::Fill`][crate::Align::Fill] will cause the overlay to
24    /// be full-width/height). If the main child is a
25    /// [`ScrolledWindow`][crate::ScrolledWindow], the overlays are placed relative
26    /// to its contents.
27    /// ## `widget`
28    /// the child widget to position
29    ///
30    /// # Returns
31    ///
32    /// [`true`] if the @allocation has been filled
33    ///
34    /// ## `allocation`
35    /// return
36    ///   location for the allocation
37    pub fn connect_get_child_position<F>(&self, f: F) -> SignalHandlerId
38    where
39        F: Fn(&Self, &Widget) -> Option<gdk::Rectangle> + 'static,
40    {
41        unsafe {
42            let f: Box<F> = Box::new(f);
43            connect_raw(
44                self.as_ptr() as *mut _,
45                b"get-child-position\0".as_ptr() as *mut _,
46                Some(transmute::<usize, unsafe extern "C" fn()>(
47                    get_child_position_trampoline::<F> as usize,
48                )),
49                Box::into_raw(f),
50            )
51        }
52    }
53}
54
55unsafe extern "C" fn get_child_position_trampoline<
56    F: Fn(&Overlay, &Widget) -> Option<gdk::Rectangle> + 'static,
57>(
58    this: *mut ffi::GtkOverlay,
59    widget: *mut ffi::GtkWidget,
60    allocation: *mut gdk::ffi::GdkRectangle,
61    f: glib::ffi::gpointer,
62) -> glib::ffi::gboolean {
63    let f: &F = &*(f as *const F);
64    match f(
65        Overlay::from_glib_borrow(this).unsafe_cast_ref(),
66        &from_glib_borrow(widget),
67    ) {
68        Some(rect) => {
69            ptr::write(allocation, ptr::read(rect.to_glib_none().0));
70            true
71        }
72        None => false,
73    }
74    .into_glib()
75}