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}