window_positioning.rs

  1use gpui::{
  2    App, Application, Bounds, Context, DisplayId, Hsla, Pixels, SharedString, Size, Window,
  3    WindowBackgroundAppearance, WindowBounds, WindowKind, WindowOptions, div, point, prelude::*,
  4    px, rgb,
  5};
  6
  7struct WindowContent {
  8    text: SharedString,
  9    bounds: Bounds<Pixels>,
 10    bg: Hsla,
 11}
 12
 13impl Render for WindowContent {
 14    fn render(&mut self, window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
 15        let window_bounds = window.bounds();
 16
 17        div()
 18            .flex()
 19            .flex_col()
 20            .bg(self.bg)
 21            .size_full()
 22            .items_center()
 23            .text_color(rgb(0xffffff))
 24            .child(self.text.clone())
 25            .child(
 26                div()
 27                    .flex()
 28                    .flex_col()
 29                    .text_sm()
 30                    .items_center()
 31                    .size_full()
 32                    .child(format!(
 33                        "origin: {}, {} size: {}, {}",
 34                        self.bounds.origin.x,
 35                        self.bounds.origin.y,
 36                        self.bounds.size.width,
 37                        self.bounds.size.height
 38                    ))
 39                    .child(format!(
 40                        "cx.bounds() origin: {}, {} size {}, {}",
 41                        window_bounds.origin.x,
 42                        window_bounds.origin.y,
 43                        window_bounds.size.width,
 44                        window_bounds.size.height
 45                    )),
 46            )
 47    }
 48}
 49
 50fn build_window_options(display_id: DisplayId, bounds: Bounds<Pixels>) -> WindowOptions {
 51    WindowOptions {
 52        // Set the bounds of the window in screen coordinates
 53        window_bounds: Some(WindowBounds::Windowed(bounds)),
 54        // Specify the display_id to ensure the window is created on the correct screen
 55        display_id: Some(display_id),
 56        titlebar: None,
 57        window_background: WindowBackgroundAppearance::Transparent,
 58        focus: false,
 59        show: true,
 60        kind: WindowKind::PopUp,
 61        is_movable: false,
 62        app_id: None,
 63        window_min_size: None,
 64        window_decorations: None,
 65        tabbing_identifier: None,
 66        ..Default::default()
 67    }
 68}
 69
 70fn main() {
 71    Application::new().run(|cx: &mut App| {
 72        // Create several new windows, positioned in the top right corner of each screen
 73        let size = Size {
 74            width: px(350.),
 75            height: px(75.),
 76        };
 77        let margin_offset = px(150.);
 78
 79        for screen in cx.displays() {
 80            let bounds = Bounds {
 81                origin: point(margin_offset, margin_offset),
 82                size,
 83            };
 84
 85            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
 86                cx.new(|_| WindowContent {
 87                    text: format!("Top Left {:?}", screen.id()).into(),
 88                    bg: gpui::red(),
 89                    bounds,
 90                })
 91            })
 92            .unwrap();
 93
 94            let bounds = Bounds {
 95                origin: screen.bounds().top_right()
 96                    - point(size.width + margin_offset, -margin_offset),
 97                size,
 98            };
 99
100            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
101                cx.new(|_| WindowContent {
102                    text: format!("Top Right {:?}", screen.id()).into(),
103                    bg: gpui::red(),
104                    bounds,
105                })
106            })
107            .unwrap();
108
109            let bounds = Bounds {
110                origin: screen.bounds().bottom_left()
111                    - point(-margin_offset, size.height + margin_offset),
112                size,
113            };
114
115            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
116                cx.new(|_| WindowContent {
117                    text: format!("Bottom Left {:?}", screen.id()).into(),
118                    bg: gpui::blue(),
119                    bounds,
120                })
121            })
122            .unwrap();
123
124            let bounds = Bounds {
125                origin: screen.bounds().bottom_right()
126                    - point(size.width + margin_offset, size.height + margin_offset),
127                size,
128            };
129
130            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
131                cx.new(|_| WindowContent {
132                    text: format!("Bottom Right {:?}", screen.id()).into(),
133                    bg: gpui::blue(),
134                    bounds,
135                })
136            })
137            .unwrap();
138
139            let bounds = Bounds {
140                origin: point(screen.bounds().center().x - size.center().x, margin_offset),
141                size,
142            };
143
144            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
145                cx.new(|_| WindowContent {
146                    text: format!("Top Center {:?}", screen.id()).into(),
147                    bg: gpui::black(),
148                    bounds,
149                })
150            })
151            .unwrap();
152
153            let bounds = Bounds {
154                origin: point(margin_offset, screen.bounds().center().y - size.center().y),
155                size,
156            };
157
158            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
159                cx.new(|_| WindowContent {
160                    text: format!("Left Center {:?}", screen.id()).into(),
161                    bg: gpui::black(),
162                    bounds,
163                })
164            })
165            .unwrap();
166
167            let bounds = Bounds {
168                origin: point(
169                    screen.bounds().center().x - size.center().x,
170                    screen.bounds().center().y - size.center().y,
171                ),
172                size,
173            };
174
175            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
176                cx.new(|_| WindowContent {
177                    text: format!("Center {:?}", screen.id()).into(),
178                    bg: gpui::black(),
179                    bounds,
180                })
181            })
182            .unwrap();
183
184            let bounds = Bounds {
185                origin: point(
186                    screen.bounds().size.width - size.width - margin_offset,
187                    screen.bounds().center().y - size.center().y,
188                ),
189                size,
190            };
191
192            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
193                cx.new(|_| WindowContent {
194                    text: format!("Right Center {:?}", screen.id()).into(),
195                    bg: gpui::black(),
196                    bounds,
197                })
198            })
199            .unwrap();
200
201            let bounds = Bounds {
202                origin: point(
203                    screen.bounds().center().x - size.center().x,
204                    screen.bounds().size.height - size.height - margin_offset,
205                ),
206                size,
207            };
208
209            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
210                cx.new(|_| WindowContent {
211                    text: format!("Bottom Center {:?}", screen.id()).into(),
212                    bg: gpui::black(),
213                    bounds,
214                })
215            })
216            .unwrap();
217        }
218    });
219}