Skip to main content

gdk/
geometry.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::Gravity;
4use glib::translate::*;
5use std::fmt;
6
7glib::wrapper! {
8    /// The [`Geometry`][crate::Geometry] struct gives the window manager information about
9    /// a window’s geometry constraints. Normally you would set these on
10    /// the GTK+ level using `gtk_window_set_geometry_hints()`. `GtkWindow`
11    /// then sets the hints on the [`Window`][crate::Window] it creates.
12    ///
13    /// [`Window::set_geometry_hints()`][crate::Window::set_geometry_hints()] expects the hints to be fully valid already
14    /// and simply passes them to the window manager; in contrast,
15    /// `gtk_window_set_geometry_hints()` performs some interpretation. For example,
16    /// `GtkWindow` will apply the hints to the geometry widget instead of the
17    /// toplevel window, if you set a geometry widget. Also, the
18    /// `min_width`/`min_height`/`max_width`/`max_height` fields may be set to -1, and
19    /// `GtkWindow` will substitute the size request of the window or geometry widget.
20    /// If the minimum size hint is not provided, `GtkWindow` will use its requisition
21    /// as the minimum size. If the minimum size is provided and a geometry widget is
22    /// set, `GtkWindow` will take the minimum size as the minimum size of the
23    /// geometry widget rather than the entire window. The base size is treated
24    /// similarly.
25    ///
26    /// The canonical use-case for `gtk_window_set_geometry_hints()` is to get a
27    /// terminal widget to resize properly. Here, the terminal text area should be
28    /// the geometry widget; `GtkWindow` will then automatically set the base size to
29    /// the size of other widgets in the terminal window, such as the menubar and
30    /// scrollbar. Then, the `width_inc` and `height_inc` fields should be set to the
31    /// size of one character in the terminal. Finally, the base size should be set
32    /// to the size of one character. The net effect is that the minimum size of the
33    /// terminal will have a 1x1 character terminal area, and only terminal sizes on
34    /// the “character grid” will be allowed.
35    ///
36    /// Here’s an example of how the terminal example would be implemented, assuming
37    /// a terminal area widget called “terminal” and a toplevel window “toplevel”:
38    ///
39    ///
40    ///
41    /// **⚠️ The following code is in C ⚠️**
42    ///
43    /// ```C
44    ///     GdkGeometry hints;
45    ///
46    ///     hints.base_width = terminal->char_width;
47    ///         hints.base_height = terminal->char_height;
48    ///         hints.min_width = terminal->char_width;
49    ///         hints.min_height = terminal->char_height;
50    ///         hints.width_inc = terminal->char_width;
51    ///         hints.height_inc = terminal->char_height;
52    ///
53    ///  gtk_window_set_geometry_hints (GTK_WINDOW (toplevel),
54    ///                                 GTK_WIDGET (terminal),
55    ///                                 &hints,
56    ///                                 GDK_HINT_RESIZE_INC |
57    ///                                 GDK_HINT_MIN_SIZE |
58    ///                                 GDK_HINT_BASE_SIZE);
59    /// ```
60    ///
61    /// The other useful fields are the `min_aspect` and `max_aspect` fields; these
62    /// contain a width/height ratio as a floating point number. If a geometry widget
63    /// is set, the aspect applies to the geometry widget rather than the entire
64    /// window. The most common use of these hints is probably to set `min_aspect` and
65    /// `max_aspect` to the same value, thus forcing the window to keep a constant
66    /// aspect ratio.
67    #[doc(alias = "GdkGeometry")]
68    pub struct Geometry(BoxedInline<ffi::GdkGeometry>);
69}
70
71impl Geometry {
72    #[allow(clippy::too_many_arguments)]
73    pub fn new(
74        min_width: i32,
75        min_height: i32,
76        max_width: i32,
77        max_height: i32,
78        base_width: i32,
79        base_height: i32,
80        width_inc: i32,
81        height_inc: i32,
82        min_aspect: f64,
83        max_aspect: f64,
84        win_gravity: Gravity,
85    ) -> Self {
86        assert_initialized_main_thread!();
87        unsafe {
88            Geometry::unsafe_from(ffi::GdkGeometry {
89                min_width,
90                min_height,
91                max_width,
92                max_height,
93                base_width,
94                base_height,
95                width_inc,
96                height_inc,
97                min_aspect,
98                max_aspect,
99                win_gravity: win_gravity.into_glib(),
100            })
101        }
102    }
103
104    pub fn min_width(&self) -> i32 {
105        self.inner.min_width
106    }
107    pub fn min_height(&self) -> i32 {
108        self.inner.min_height
109    }
110    pub fn max_width(&self) -> i32 {
111        self.inner.max_width
112    }
113    pub fn max_height(&self) -> i32 {
114        self.inner.max_height
115    }
116    pub fn base_width(&self) -> i32 {
117        self.inner.base_width
118    }
119    pub fn base_height(&self) -> i32 {
120        self.inner.base_height
121    }
122    pub fn width_inc(&self) -> i32 {
123        self.inner.width_inc
124    }
125    pub fn height_inc(&self) -> i32 {
126        self.inner.height_inc
127    }
128    pub fn min_aspect(&self) -> f64 {
129        self.inner.min_aspect
130    }
131    pub fn max_aspect(&self) -> f64 {
132        self.inner.max_aspect
133    }
134    pub fn win_gravity(&self) -> Gravity {
135        unsafe { from_glib(self.inner.win_gravity) }
136    }
137}
138
139impl fmt::Debug for Geometry {
140    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141        f.debug_struct("Geometry")
142            .field("min_width", &self.min_width())
143            .field("min_height", &self.min_height())
144            .field("max_width", &self.max_width())
145            .field("max_height", &self.max_height())
146            .field("base_width", &self.base_width())
147            .field("base_height", &self.base_height())
148            .field("width_inc", &self.width_inc())
149            .field("height_inc", &self.height_inc())
150            .field("min_aspect", &self.min_aspect())
151            .field("max_aspect", &self.max_aspect())
152            .field("win_gravity", &self.win_gravity())
153            .finish()
154    }
155}