From 87cf48019e0206fe646f413897c4567b8f2e4540 Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:06:53 +0200 Subject: [PATCH] feat: Window corner radius is now dynamic on Windows and Linux, whereas on macOS native window attributes are used --- .../oneclient_app/src/layout/root_layout.rs | 34 ++++++++++++++- packages/oneclient_app/src/main.rs | 43 +++++++++++++------ 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/packages/oneclient_app/src/layout/root_layout.rs b/packages/oneclient_app/src/layout/root_layout.rs index b9c5c1ef..765de88f 100644 --- a/packages/oneclient_app/src/layout/root_layout.rs +++ b/packages/oneclient_app/src/layout/root_layout.rs @@ -19,13 +19,45 @@ impl Component for RootLayout { let home_ready = use_state(|| false); use_provide_splash(SplashState { active, home_ready }); + // macOS draws the corners natively (rounded window + shadow via the + // window attributes), so Freya must not round on top of it. + #[cfg(target_os = "macos")] + let corner = 0.; + + // Other platforms are borderless: Freya rounds, squared when maximized so + // there's no gap to the screen edge. No reactive maximized signal exists, + // so mirror it — root_size changes on every maximize/restore/resize, which + // re-runs the effect to re-query. + #[cfg(not(target_os = "macos"))] + let corner = { + let root_size = Platform::get().root_size; + let mut maximized = use_state(|| false); + let size = *root_size.read(); + let dep = (size.width as i32, size.height as i32); + use_side_effect_with_deps(&dep, move |_| { + spawn(async move { + let is_max = Platform::get() + .post_callback(|id, ctx| { + ctx.windows.get(&id).map(|w| w.window().is_maximized()) + }) + .await; + if let Ok(Some(is_max)) = is_max { + if *maximized.peek() != is_max { + maximized.set(is_max); + } + } + }); + }); + if *maximized.read() { 0. } else { 12. } + }; + rect() .width(Size::fill()) .height(Size::fill()) .background(colors::page()) .color(colors::fg_primary()) .font_family(theme::DEFAULT_FONT) - .corner_radius(CornerRadius::new_all(12.)) + .corner_radius(CornerRadius::new_all(corner)) .overflow(Overflow::Clip) .child( rect() diff --git a/packages/oneclient_app/src/main.rs b/packages/oneclient_app/src/main.rs index dd269c01..e5aeee62 100644 --- a/packages/oneclient_app/src/main.rs +++ b/packages/oneclient_app/src/main.rs @@ -59,20 +59,37 @@ fn main() { #[cfg(target_os = "macos")] oneclient_app::platform::macos::loop_memory_collector(); + let window_config = WindowConfig::new_app(OneClientApp { bridge }) + .with_title(constants::WINDOW_TITLE) + .with_app_id(constants::WINDOW_APP_ID) + .with_icon(LaunchConfig::window_icon(include_bytes!( + "../icons/128x128.png" + ))) + .with_size(1200., 800.) + .with_min_size(800., 600.) + .with_transparency(true) + .with_background(Color::TRANSPARENT); + + // macOS: keep the native frame (rounded corners + drop shadow) but hide the + // titlebar and extend content into it. Other platforms stay borderless. + #[cfg(target_os = "macos")] + let window_config = window_config + .with_decorations(true) + .with_window_attributes(|attrs, _| { + use freya::winit::platform::macos::WindowAttributesExtMacOS; + attrs + .with_titlebar_hidden(true) + .with_title_hidden(true) + .with_titlebar_transparent(true) + .with_titlebar_buttons_hidden(true) + .with_fullsize_content_view(true) + }); + + #[cfg(not(target_os = "macos"))] + let window_config = window_config.with_decorations(false); + let mut launch_config = LaunchConfig::new() - .with_window( - WindowConfig::new_app(OneClientApp { bridge }) - .with_title(constants::WINDOW_TITLE) - .with_app_id(constants::WINDOW_APP_ID) - .with_icon(LaunchConfig::window_icon(include_bytes!( - "../icons/128x128.png" - ))) - .with_size(1200., 800.) - .with_min_size(800., 600.) - .with_decorations(false) - .with_transparency(true) - .with_background(Color::TRANSPARENT), - ) + .with_window(window_config) .with_gpu_resource_cache_limit( std::env::var("ONECLIENT_GPU_CACHE_MB") .ok()