window_positioning.rs

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