diff --git a/packages/oneclient_app/src/hooks/active_cluster.rs b/packages/oneclient_app/src/hooks/active_cluster.rs index 54627eb8..df24a08d 100644 --- a/packages/oneclient_app/src/hooks/active_cluster.rs +++ b/packages/oneclient_app/src/hooks/active_cluster.rs @@ -31,6 +31,19 @@ pub fn use_splash() -> SplashState { consume_root_context::() } +/// The settings value the window was built from, carried in from startup because +/// the settings channel is still on its defaults during the first frames +#[derive(Clone, Copy)] +pub struct StartMaximizedState(pub bool); + +pub fn use_provide_start_maximized(state: StartMaximizedState) { + use_provide_root_context(move || state); +} + +pub fn use_start_maximized() -> bool { + consume_root_context::().0 +} + #[derive(Clone)] pub struct BrowserCompatState(pub State); diff --git a/packages/oneclient_app/src/hooks/mod.rs b/packages/oneclient_app/src/hooks/mod.rs index d3feb7e3..2a119519 100644 --- a/packages/oneclient_app/src/hooks/mod.rs +++ b/packages/oneclient_app/src/hooks/mod.rs @@ -15,10 +15,11 @@ pub use view_state::{PersistedView, use_view_state}; pub use active_cluster::{ ActiveClusterState, BrowserCompatState, BrowserStateStore, BrowserUiState, LinkConfirmState, - OnboardingSelectionState, SplashState, use_active_cluster_id, use_browser_compat, - use_browser_state_store, use_link_confirm, use_onboarding_selection, use_provide_active_cluster, - use_provide_browser_compat, use_provide_browser_state, use_provide_link_confirm, - use_provide_onboarding_selection, use_provide_splash, use_splash, + OnboardingSelectionState, SplashState, StartMaximizedState, use_active_cluster_id, + use_browser_compat, use_browser_state_store, use_link_confirm, use_onboarding_selection, + use_provide_active_cluster, use_provide_browser_compat, use_provide_browser_state, + use_provide_link_confirm, use_provide_onboarding_selection, use_provide_splash, + use_provide_start_maximized, use_splash, use_start_maximized, }; pub use actions::{Actions, NotificationBuilder, PumpSignal}; diff --git a/packages/oneclient_app/src/layout/root_layout.rs b/packages/oneclient_app/src/layout/root_layout.rs index 07b43576..92bc474c 100644 --- a/packages/oneclient_app/src/layout/root_layout.rs +++ b/packages/oneclient_app/src/layout/root_layout.rs @@ -7,6 +7,8 @@ use crate::components::{ UpdatePromptOverlay, }; use crate::hooks::{SplashState, use_provide_overlay_claims, use_provide_splash}; +#[cfg(not(target_os = "macos"))] +use crate::hooks::use_start_maximized; use crate::layout::{HomeArtPrefetch, PendingLaunchDriver}; use crate::motion::AnimationClockDriver; use crate::routes::Route; @@ -32,7 +34,10 @@ impl Component for RootLayout { #[cfg(not(target_os = "macos"))] let corner = { let root_size = Platform::get().root_size; - let mut maximized = use_state(|| false); + // Seeded because the query below only answers after the window is visible + // which would round the corners of the first frames of a maximized launch + let start_maximized = use_start_maximized(); + let mut maximized = use_state(move || start_maximized); let size = *root_size.read(); let dep = (size.width as i32, size.height as i32); use_side_effect_with_deps(&dep, move |_| { diff --git a/packages/oneclient_app/src/main.rs b/packages/oneclient_app/src/main.rs index 91e175a8..ceb56952 100644 --- a/packages/oneclient_app/src/main.rs +++ b/packages/oneclient_app/src/main.rs @@ -9,14 +9,16 @@ use freya::radio::use_init_radio_station; use oneclient_app::ipc::{self, Claim}; use oneclient_app::state::{AppChannel, AppState, LauncherInit}; use oneclient_app::{ - Actions, ConfirmLinkOverlay, EventPump, LinkConfirmState, cli, constants, events, platform, - router, theme, use_provide_actions, use_provide_link_confirm, + Actions, ConfirmLinkOverlay, EventPump, LinkConfirmState, StartMaximizedState, cli, constants, + events, platform, router, theme, use_provide_actions, use_provide_link_confirm, + use_provide_start_maximized, }; use std::cell::Cell; use tokio::runtime::Builder; struct OneClientApp { needs_location: bool, + start_maximized: bool, boot_launch: Cell>, ipc: Cell>, } @@ -90,6 +92,8 @@ impl App for OneClientApp { let link_confirm = use_state(|| None::); use_provide_link_confirm(LinkConfirmState(link_confirm)); + use_provide_start_maximized(StartMaximizedState(self.start_maximized)); + rect() .width(Size::fill()) .height(Size::fill()) @@ -182,8 +186,11 @@ fn main() { #[cfg(target_os = "macos")] oneclient_app::platform::macos::loop_memory_collector(); + let start_maximized = settings.start_maximized; + let window_config = WindowConfig::new_app(OneClientApp { needs_location, + start_maximized, boot_launch: Cell::new(cli.launch), ipc: Cell::new(ipc), }) @@ -210,7 +217,7 @@ fn main() { #[cfg(target_os = "macos")] let window_config = window_config .with_decorations(true) - .with_window_attributes(|attrs, _| { + .with_window_attributes(move |attrs, _| { use freya::winit::platform::macos::WindowAttributesExtMacOS; attrs .with_title_hidden(true) @@ -218,10 +225,13 @@ fn main() { .with_titlebar_buttons_hidden(true) .with_fullsize_content_view(true) .with_has_shadow(true) + .with_maximized(start_maximized) }); #[cfg(not(target_os = "macos"))] - let window_config = window_config.with_decorations(false); + let window_config = window_config + .with_decorations(false) + .with_window_attributes(move |attrs, _| attrs.with_maximized(start_maximized)); let mut launch_config = LaunchConfig::new() .with_window(window_config) diff --git a/packages/oneclient_app/src/view/app/settings/launcher.rs b/packages/oneclient_app/src/view/app/settings/launcher.rs index 7bd60bca..84e4d34c 100644 --- a/packages/oneclient_app/src/view/app/settings/launcher.rs +++ b/packages/oneclient_app/src/view/app/settings/launcher.rs @@ -33,12 +33,18 @@ impl Component for SettingsLauncher { move || v }); + let start_maximized = use_state({ + let v = settings.start_maximized; + move || v + }); + let mut first = use_state(|| true); { let settings = settings.clone(); use_side_effect(move || { let discord = *discord_rpc.read(); let crash = *crash_reporting.read(); + let maximized = *start_maximized.read(); if *first.peek() { first.set(false); return; @@ -46,6 +52,7 @@ impl Component for SettingsLauncher { let mut next = settings.clone(); next.discord_enabled = discord; next.crash_reporting = crash; + next.start_maximized = maximized; dispatch.set_settings(next); }); } @@ -78,6 +85,12 @@ impl Component for SettingsLauncher { "Send anonymous crash and error reports to help fix bugs. Applies on restart.", toggle(crash_reporting), )) + .child(settings_row( + IconType::Maximize01, + "Start Maximized", + "Open the launcher window maximized. Applies on restart.", + toggle(start_maximized), + )) .child(settings_row( IconType::File02, "Terms & Privacy", diff --git a/packages/oneclient_core/src/settings/launcher.rs b/packages/oneclient_core/src/settings/launcher.rs index c334f152..92f16c6c 100644 --- a/packages/oneclient_core/src/settings/launcher.rs +++ b/packages/oneclient_core/src/settings/launcher.rs @@ -48,6 +48,7 @@ pub struct LauncherSettings { pub global_game_settings: GameSettingsProfile, pub allow_parallel_running_clusters: bool, pub dynamic_background_enabled: bool, + pub start_maximized: bool, pub animations_enabled: bool, pub view_states: BTreeMap, pub seen_onboarding: bool, @@ -88,6 +89,7 @@ impl Default for LauncherSettings { global_game_settings: GameSettingsProfile::default_global_profile(), allow_parallel_running_clusters: false, dynamic_background_enabled: true, + start_maximized: false, animations_enabled: true, view_states: BTreeMap::new(), seen_onboarding: false,