Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:35:11.362Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

window_shadow.rs

247 lines · 11.2 KB · rust
1#![cfg_attr(target_family = "wasm", no_main)]
2
3use gpui::{
4    App, Bounds, Context, CursorStyle, Decorations, HitboxBehavior, Hsla, MouseButton, Pixels,
5    Point, ResizeEdge, Size, Window, WindowBackgroundAppearance, WindowBounds, WindowDecorations,
6    WindowOptions, black, canvas, div, green, point, prelude::*, px, rgb, size, transparent_black,
7    white,
8};
9use gpui_platform::application;
10
11struct WindowShadow {}
12
13// Things to do:
14// 1. We need a way of calculating which edge or corner the mouse is on,
15//    and then dispatch on that
16// 2. We need to improve the shadow rendering significantly
17// 3. We need to implement the techniques in here in Zed
18
19impl Render for WindowShadow {
20    fn render(&mut self, window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
21        let decorations = window.window_decorations();
22        let rounding = px(10.0);
23        let shadow_size = px(10.0);
24        let border_size = px(1.0);
25        let grey = rgb(0x808080);
26        window.set_client_inset(shadow_size);
27
28        div()
29            .id("window-backdrop")
30            .bg(transparent_black())
31            .map(|div| match decorations {
32                Decorations::Server => div,
33                Decorations::Client { tiling, .. } => div
34                    .bg(gpui::transparent_black())
35                    .child(
36                        canvas(
37                            |_bounds, window, _cx| {
38                                window.insert_hitbox(
39                                    Bounds::new(
40                                        point(px(0.0), px(0.0)),
41                                        window.window_bounds().get_bounds().size,
42                                    ),
43                                    HitboxBehavior::Normal,
44                                )
45                            },
46                            move |_bounds, hitbox, window, _cx| {
47                                let mouse = window.mouse_position();
48                                let size = window.window_bounds().get_bounds().size;
49                                let Some(edge) = resize_edge(mouse, shadow_size, size) else {
50                                    return;
51                                };
52                                window.set_cursor_style(
53                                    match edge {
54                                        ResizeEdge::Top | ResizeEdge::Bottom => {
55                                            CursorStyle::ResizeUpDown
56                                        }
57                                        ResizeEdge::Left | ResizeEdge::Right => {
58                                            CursorStyle::ResizeLeftRight
59                                        }
60                                        ResizeEdge::TopLeft | ResizeEdge::BottomRight => {
61                                            CursorStyle::ResizeUpLeftDownRight
62                                        }
63                                        ResizeEdge::TopRight | ResizeEdge::BottomLeft => {
64                                            CursorStyle::ResizeUpRightDownLeft
65                                        }
66                                    },
67                                    &hitbox,
68                                );
69                            },
70                        )
71                        .size_full()
72                        .absolute(),
73                    )
74                    .when(!(tiling.top || tiling.right), |div| {
75                        div.rounded_tr(rounding)
76                    })
77                    .when(!(tiling.top || tiling.left), |div| div.rounded_tl(rounding))
78                    .when(!tiling.top, |div| div.pt(shadow_size))
79                    .when(!tiling.bottom, |div| div.pb(shadow_size))
80                    .when(!tiling.left, |div| div.pl(shadow_size))
81                    .when(!tiling.right, |div| div.pr(shadow_size))
82                    .on_mouse_move(|_e, window, _cx| window.refresh())
83                    .on_mouse_down(MouseButton::Left, move |e, window, _cx| {
84                        let size = window.window_bounds().get_bounds().size;
85                        let pos = e.position;
86
87                        match resize_edge(pos, shadow_size, size) {
88                            Some(edge) => window.start_window_resize(edge),
89                            None => window.start_window_move(),
90                        };
91                    }),
92            })
93            .size_full()
94            .child(
95                div()
96                    .cursor(CursorStyle::Arrow)
97                    .map(|div| match decorations {
98                        Decorations::Server => div,
99                        Decorations::Client { tiling } => div
100                            .border_color(grey)
101                            .when(!(tiling.top || tiling.right), |div| {
102                                div.rounded_tr(rounding)
103                            })
104                            .when(!(tiling.top || tiling.left), |div| div.rounded_tl(rounding))
105                            .when(!tiling.top, |div| div.border_t(border_size))
106                            .when(!tiling.bottom, |div| div.border_b(border_size))
107                            .when(!tiling.left, |div| div.border_l(border_size))
108                            .when(!tiling.right, |div| div.border_r(border_size))
109                            .when(!tiling.is_tiled(), |div| {
110                                div.shadow(vec![
111                                    gpui::BoxShadow::new(
112                                        px(0.),
113                                        px(0.),
114                                        Hsla {
115                                            h: 0.,
116                                            s: 0.,
117                                            l: 0.,
118                                            a: 0.4,
119                                        },
120                                    )
121                                    .blur_radius(shadow_size / 2.),
122                                ])
123                            }),
124                    })
125                    .on_mouse_move(|_e, _, cx| {
126                        cx.stop_propagation();
127                    })
128                    .bg(gpui::rgb(0xCCCCFF))
129                    .size_full()
130                    .flex()
131                    .flex_col()
132                    .justify_around()
133                    .child(
134                        div().w_full().flex().flex_row().justify_around().child(
135                            div()
136                                .flex()
137                                .bg(white())
138                                .size(px(300.0))
139                                .justify_center()
140                                .items_center()
141                                .shadow_lg()
142                                .border_1()
143                                .border_color(rgb(0x0000ff))
144                                .text_xl()
145                                .text_color(rgb(0xffffff))
146                                .child(
147                                    div()
148                                        .id("hello")
149                                        .w(px(200.0))
150                                        .h(px(100.0))
151                                        .bg(green())
152                                        .shadow(vec![
153                                            gpui::BoxShadow::new(
154                                                px(0.),
155                                                px(0.),
156                                                Hsla {
157                                                    h: 0.,
158                                                    s: 0.,
159                                                    l: 0.,
160                                                    a: 1.0,
161                                                },
162                                            )
163                                            .blur_radius(px(20.0)),
164                                        ])
165                                        .map(|div| match decorations {
166                                            Decorations::Server => div,
167                                            Decorations::Client { .. } => div
168                                                .on_mouse_down(
169                                                    MouseButton::Left,
170                                                    |_e, window, _| {
171                                                        window.start_window_move();
172                                                    },
173                                                )
174                                                .on_click(|e, window, _| {
175                                                    if e.is_right_click() {
176                                                        window.show_window_menu(e.position());
177                                                    }
178                                                })
179                                                .text_color(black())
180                                                .child("this is the custom titlebar"),
181                                        }),
182                                ),
183                        ),
184                    ),
185            )
186    }
187}
188
189fn resize_edge(pos: Point<Pixels>, shadow_size: Pixels, size: Size<Pixels>) -> Option<ResizeEdge> {
190    let edge = if pos.y < shadow_size && pos.x < shadow_size {
191        ResizeEdge::TopLeft
192    } else if pos.y < shadow_size && pos.x > size.width - shadow_size {
193        ResizeEdge::TopRight
194    } else if pos.y < shadow_size {
195        ResizeEdge::Top
196    } else if pos.y > size.height - shadow_size && pos.x < shadow_size {
197        ResizeEdge::BottomLeft
198    } else if pos.y > size.height - shadow_size && pos.x > size.width - shadow_size {
199        ResizeEdge::BottomRight
200    } else if pos.y > size.height - shadow_size {
201        ResizeEdge::Bottom
202    } else if pos.x < shadow_size {
203        ResizeEdge::Left
204    } else if pos.x > size.width - shadow_size {
205        ResizeEdge::Right
206    } else {
207        return None;
208    };
209    Some(edge)
210}
211
212fn run_example() {
213    application().run(|cx: &mut App| {
214        let bounds = Bounds::centered(None, size(px(600.0), px(600.0)), cx);
215        cx.open_window(
216            WindowOptions {
217                window_bounds: Some(WindowBounds::Windowed(bounds)),
218                window_background: WindowBackgroundAppearance::Opaque,
219                window_decorations: Some(WindowDecorations::Client),
220                ..Default::default()
221            },
222            |window, cx| {
223                cx.new(|cx| {
224                    cx.observe_window_appearance(window, |_, window, _| {
225                        window.refresh();
226                    })
227                    .detach();
228                    WindowShadow {}
229                })
230            },
231        )
232        .unwrap();
233    });
234}
235
236#[cfg(not(target_family = "wasm"))]
237fn main() {
238    run_example();
239}
240
241#[cfg(target_family = "wasm")]
242#[wasm_bindgen::prelude::wasm_bindgen(start)]
243pub fn start() {
244    gpui_platform::web_init();
245    run_example();
246}
247
Served at tenant.openagents/omega Member data and write actions are omitted.