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        ..Default::default()
 66    }
 67}
 68
 69fn main() {
 70    Application::new().run(|cx: &mut App| {
 71        // Create several new windows, positioned in the top right corner of each screen
 72        let size = Size {
 73            width: px(350.),
 74            height: px(75.),
 75        };
 76        let margin_offset = px(150.);
 77
 78        for screen in cx.displays() {
 79            let bounds = Bounds {
 80                origin: point(margin_offset, margin_offset),
 81                size,
 82            };
 83
 84            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
 85                cx.new(|_| WindowContent {
 86                    text: format!("Top Left {:?}", screen.id()).into(),
 87                    bg: gpui::red(),
 88                    bounds,
 89                })
 90            })
 91            .unwrap();
 92
 93            let bounds = Bounds {
 94                origin: screen.bounds().top_right()
 95                    - point(size.width + margin_offset, -margin_offset),
 96                size,
 97            };
 98
 99            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
100                cx.new(|_| WindowContent {
101                    text: format!("Top Right {:?}", screen.id()).into(),
102                    bg: gpui::red(),
103                    bounds,
104                })
105            })
106            .unwrap();
107
108            let bounds = Bounds {
109                origin: screen.bounds().bottom_left()
110                    - point(-margin_offset, size.height + margin_offset),
111                size,
112            };
113
114            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
115                cx.new(|_| WindowContent {
116                    text: format!("Bottom Left {:?}", screen.id()).into(),
117                    bg: gpui::blue(),
118                    bounds,
119                })
120            })
121            .unwrap();
122
123            let bounds = Bounds {
124                origin: screen.bounds().bottom_right()
125                    - point(size.width + margin_offset, size.height + margin_offset),
126                size,
127            };
128
129            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
130                cx.new(|_| WindowContent {
131                    text: format!("Bottom Right {:?}", screen.id()).into(),
132                    bg: gpui::blue(),
133                    bounds,
134                })
135            })
136            .unwrap();
137
138            let bounds = Bounds {
139                origin: point(screen.bounds().center().x - size.center().x, margin_offset),
140                size,
141            };
142
143            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
144                cx.new(|_| WindowContent {
145                    text: format!("Top Center {:?}", screen.id()).into(),
146                    bg: gpui::black(),
147                    bounds,
148                })
149            })
150            .unwrap();
151
152            let bounds = Bounds {
153                origin: point(margin_offset, screen.bounds().center().y - size.center().y),
154                size,
155            };
156
157            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
158                cx.new(|_| WindowContent {
159                    text: format!("Left Center {:?}", screen.id()).into(),
160                    bg: gpui::black(),
161                    bounds,
162                })
163            })
164            .unwrap();
165
166            let bounds = Bounds {
167                origin: point(
168                    screen.bounds().center().x - size.center().x,
169                    screen.bounds().center().y - size.center().y,
170                ),
171                size,
172            };
173
174            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
175                cx.new(|_| WindowContent {
176                    text: format!("Center {:?}", screen.id()).into(),
177                    bg: gpui::black(),
178                    bounds,
179                })
180            })
181            .unwrap();
182
183            let bounds = Bounds {
184                origin: point(
185                    screen.bounds().size.width - size.width - margin_offset,
186                    screen.bounds().center().y - size.center().y,
187                ),
188                size,
189            };
190
191            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
192                cx.new(|_| WindowContent {
193                    text: format!("Right Center {:?}", screen.id()).into(),
194                    bg: gpui::black(),
195                    bounds,
196                })
197            })
198            .unwrap();
199
200            let bounds = Bounds {
201                origin: point(
202                    screen.bounds().center().x - size.center().x,
203                    screen.bounds().size.height - size.height - margin_offset,
204                ),
205                size,
206            };
207
208            cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
209                cx.new(|_| WindowContent {
210                    text: format!("Bottom Center {:?}", screen.id()).into(),
211                    bg: gpui::black(),
212                    bounds,
213                })
214            })
215            .unwrap();
216        }
217    });
218}