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}