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