diff --git a/desktop/src/app.rs b/desktop/src/app.rs index e3a3970c85..bafec9c1d2 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -1,3 +1,4 @@ +use rand::Rng; use rfd::AsyncFileDialog; use std::fs; use std::path::PathBuf; @@ -16,7 +17,7 @@ use crate::event::{AppEvent, AppEventScheduler}; use crate::persist::PersistentData; use crate::render::{RenderError, RenderState}; use crate::window::Window; -use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, InputMessage, MouseKeys, MouseState, Platform}; +use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, InputMessage, MouseKeys, MouseState}; use crate::wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages}; pub(crate) struct App { @@ -78,6 +79,8 @@ impl App { let mut persistent_data = PersistentData::default(); persistent_data.load_from_disk(); + let desktop_wrapper = DesktopWrapper::new(rand::rng().random()); + Self { render_state: None, wgpu_context, @@ -91,7 +94,7 @@ impl App { ui_scale: 1., app_event_receiver, app_event_scheduler, - desktop_wrapper: DesktopWrapper::new(), + desktop_wrapper, last_ui_update: Instant::now(), cef_context, cef_schedule: Some(Instant::now()), @@ -478,14 +481,6 @@ impl ApplicationHandler for App { self.resize(); self.desktop_wrapper.init(self.wgpu_context.clone()); - - #[cfg(target_os = "windows")] - let platform = Platform::Windows; - #[cfg(target_os = "macos")] - let platform = Platform::Mac; - #[cfg(target_os = "linux")] - let platform = Platform::Linux; - self.dispatch_desktop_wrapper_message(DesktopWrapperMessage::UpdatePlatform(platform)); } fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { diff --git a/desktop/src/lib.rs b/desktop/src/lib.rs index 93ac5c58e8..a685b2b2fa 100644 --- a/desktop/src/lib.rs +++ b/desktop/src/lib.rs @@ -66,6 +66,7 @@ pub fn start() { } }; + // Must be called before event loop initialization or native window integrations will break App::init(); let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context()); @@ -78,9 +79,9 @@ pub fn start() { let cef_handler = cef::CefHandler::new(wgpu_context.clone(), app_event_scheduler.clone(), cef_view_info_receiver); let cef_context = match cef_context_builder.initialize(cef_handler, cli.disable_ui_acceleration) { - Ok(c) => { + Ok(context) => { tracing::info!("CEF initialized successfully"); - c + context } Err(cef::InitError::AlreadyRunning) => { tracing::error!("Another instance is already running, Exiting."); diff --git a/desktop/wrapper/src/handle_desktop_wrapper_message.rs b/desktop/wrapper/src/handle_desktop_wrapper_message.rs index a830931fff..5330e67977 100644 --- a/desktop/wrapper/src/handle_desktop_wrapper_message.rs +++ b/desktop/wrapper/src/handle_desktop_wrapper_message.rs @@ -1,11 +1,10 @@ use graphene_std::Color; use graphene_std::raster::Image; -use graphite_editor::messages::app_window::app_window_message_handler::AppWindowPlatform; use graphite_editor::messages::clipboard::utility_types::ClipboardContentRaw; use graphite_editor::messages::prelude::*; use super::DesktopWrapperMessageDispatcher; -use super::messages::{DesktopFrontendMessage, DesktopWrapperMessage, EditorMessage, OpenFileDialogContext, Platform, SaveFileDialogContext}; +use super::messages::{DesktopFrontendMessage, DesktopWrapperMessage, EditorMessage, OpenFileDialogContext, SaveFileDialogContext}; pub(super) fn handle_desktop_wrapper_message(dispatcher: &mut DesktopWrapperMessageDispatcher, message: DesktopWrapperMessage) { match message { @@ -111,15 +110,6 @@ pub(super) fn handle_desktop_wrapper_message(dispatcher: &mut DesktopWrapperMess dispatcher.queue_editor_message(message); } DesktopWrapperMessage::PollNodeGraphEvaluation => dispatcher.poll_node_graph_evaluation(), - DesktopWrapperMessage::UpdatePlatform(platform) => { - let platform = match platform { - Platform::Windows => AppWindowPlatform::Windows, - Platform::Mac => AppWindowPlatform::Mac, - Platform::Linux => AppWindowPlatform::Linux, - }; - let message = AppWindowMessage::UpdatePlatform { platform }; - dispatcher.queue_editor_message(message); - } DesktopWrapperMessage::UpdateMaximized { maximized } => { let message = FrontendMessage::UpdateMaximized { maximized }; dispatcher.queue_editor_message(message); diff --git a/desktop/wrapper/src/lib.rs b/desktop/wrapper/src/lib.rs index bdb9978e61..1080b83df6 100644 --- a/desktop/wrapper/src/lib.rs +++ b/desktop/wrapper/src/lib.rs @@ -1,5 +1,5 @@ use graph_craft::wasm_application_io::WasmApplicationIo; -use graphite_editor::application::Editor; +use graphite_editor::application::{Editor, Environment, Host, Platform}; use graphite_editor::messages::prelude::{FrontendMessage, Message}; // TODO: Remove usage of this reexport in desktop create and remove this line @@ -27,8 +27,18 @@ pub struct DesktopWrapper { } impl DesktopWrapper { - pub fn new() -> Self { - Self { editor: Editor::new() } + pub fn new(uuid_random_seed: u64) -> Self { + #[cfg(target_os = "windows")] + let host = Host::Windows; + #[cfg(target_os = "macos")] + let host = Host::Mac; + #[cfg(target_os = "linux")] + let host = Host::Linux; + let env = Environment { platform: Platform::Desktop, host }; + + Self { + editor: Editor::new(env, uuid_random_seed), + } } pub fn init(&self, wgpu_context: WgpuContext) { @@ -51,12 +61,6 @@ impl DesktopWrapper { } } -impl Default for DesktopWrapper { - fn default() -> Self { - Self::new() - } -} - pub enum NodeGraphExecutionResult { HasRun(Option), NotRun, diff --git a/desktop/wrapper/src/messages.rs b/desktop/wrapper/src/messages.rs index 08c31df36a..23a9247547 100644 --- a/desktop/wrapper/src/messages.rs +++ b/desktop/wrapper/src/messages.rs @@ -109,7 +109,6 @@ pub enum DesktopWrapperMessage { content: Vec, }, PollNodeGraphEvaluation, - UpdatePlatform(Platform), UpdateMaximized { maximized: bool, }, @@ -163,12 +162,6 @@ pub enum SaveFileDialogContext { File { content: Vec }, } -pub enum Platform { - Windows, - Mac, - Linux, -} - pub enum MenuItem { Action { id: String, diff --git a/editor/src/application.rs b/editor/src/application.rs index 34016c2fa2..cc54caa8e3 100644 --- a/editor/src/application.rs +++ b/editor/src/application.rs @@ -1,24 +1,31 @@ use crate::dispatcher::Dispatcher; use crate::messages::prelude::*; pub use graphene_std::uuid::*; +use std::sync::OnceLock; -// TODO: serialize with serde to save the current editor state pub struct Editor { pub dispatcher: Dispatcher, } impl Editor { - /// Construct the editor. - /// Remember to provide a random seed with `editor::set_uuid_seed(seed)` before any editors can be used. - pub fn new() -> Self { + pub fn new(environment: Environment, uuid_random_seed: u64) -> Self { + ENVIRONMENT.set(environment).expect("Editor shoud only be initialized once"); + graphene_std::uuid::set_uuid_seed(uuid_random_seed); + Self { dispatcher: Dispatcher::new() } } #[cfg(test)] pub(crate) fn new_local_executor() -> (Self, crate::node_graph_executor::NodeRuntime) { + let _ = ENVIRONMENT.set(*Editor::environment()); + graphene_std::uuid::set_uuid_seed(0); + let (runtime, executor) = crate::node_graph_executor::NodeGraphExecutor::new_with_local_runtime(); - let dispatcher = Dispatcher::with_executor(executor); - (Self { dispatcher }, runtime) + let editor = Self { + dispatcher: Dispatcher::with_executor(executor), + }; + + (editor, runtime) } pub fn handle_message>(&mut self, message: T) -> Vec { @@ -32,9 +39,53 @@ impl Editor { } } -impl Default for Editor { - fn default() -> Self { - Self::new() +static ENVIRONMENT: OnceLock = OnceLock::new(); +impl Editor { + #[cfg(not(test))] + pub fn environment() -> &'static Environment { + ENVIRONMENT.get().expect("Editor environment accessed before initialization") + } + + #[cfg(test)] + pub fn environment() -> &'static Environment { + &Environment { + platform: Platform::Desktop, + host: Host::Linux, + } + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Environment { + pub platform: Platform, + pub host: Host, +} +#[derive(Clone, Copy, Debug)] +pub enum Platform { + Desktop, + Web, +} +#[derive(Clone, Copy, Debug)] +pub enum Host { + Windows, + Mac, + Linux, +} +impl Environment { + pub fn is_desktop(&self) -> bool { + matches!(self.platform, Platform::Desktop) + } + pub fn is_web(&self) -> bool { + matches!(self.platform, Platform::Web) + } + pub fn is_windows(&self) -> bool { + matches!(self.host, Host::Windows) + } + pub fn is_mac(&self) -> bool { + matches!(self.host, Host::Mac) + } + pub fn is_linux(&self) -> bool { + matches!(self.host, Host::Linux) } } diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index cfffefefe2..296084c835 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -23,12 +23,11 @@ pub struct DispatcherMessageHandlers { debug_message_handler: DebugMessageHandler, defer_message_handler: DeferMessageHandler, dialog_message_handler: DialogMessageHandler, - globals_message_handler: GlobalsMessageHandler, input_preprocessor_message_handler: InputPreprocessorMessageHandler, key_mapping_message_handler: KeyMappingMessageHandler, layout_message_handler: LayoutMessageHandler, menu_bar_message_handler: MenuBarMessageHandler, - pub portfolio_message_handler: PortfolioMessageHandler, + pub(crate) portfolio_message_handler: PortfolioMessageHandler, preferences_message_handler: PreferencesMessageHandler, tool_message_handler: ToolMessageHandler, viewport_message_handler: ViewportMessageHandler, @@ -192,17 +191,11 @@ impl Dispatcher { self.responses.push(message); } } - Message::Globals(message) => { - self.message_handlers.globals_message_handler.process_message(message, &mut queue, ()); - } Message::InputPreprocessor(message) => { - let keyboard_platform = GLOBAL_PLATFORM.get().copied().unwrap_or_default().as_keyboard_platform_layout(); - self.message_handlers.input_preprocessor_message_handler.process_message( message, &mut queue, InputPreprocessorMessageContext { - keyboard_platform, viewport: &self.message_handlers.viewport_message_handler, }, ); diff --git a/editor/src/messages/app_window/app_window_message.rs b/editor/src/messages/app_window/app_window_message.rs index 0dcc39ae5d..c02b99b5fd 100644 --- a/editor/src/messages/app_window/app_window_message.rs +++ b/editor/src/messages/app_window/app_window_message.rs @@ -1,11 +1,8 @@ use crate::messages::prelude::*; -use super::app_window_message_handler::AppWindowPlatform; - #[impl_message(Message, AppWindow)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum AppWindowMessage { - UpdatePlatform { platform: AppWindowPlatform }, PointerLock, PointerLockMove { x: f64, y: f64 }, Close, diff --git a/editor/src/messages/app_window/app_window_message_handler.rs b/editor/src/messages/app_window/app_window_message_handler.rs index 66c4ef0bab..21b6e9b5e9 100644 --- a/editor/src/messages/app_window/app_window_message_handler.rs +++ b/editor/src/messages/app_window/app_window_message_handler.rs @@ -1,20 +1,15 @@ -use crate::messages::app_window::AppWindowMessage; +use crate::application::{Environment, Platform}; use crate::messages::prelude::*; +use crate::{application::Host, messages::app_window::AppWindowMessage}; use graphite_proc_macros::{ExtractField, message_handler_data}; #[derive(Debug, Clone, Default, ExtractField)] -pub struct AppWindowMessageHandler { - platform: AppWindowPlatform, -} +pub struct AppWindowMessageHandler {} #[message_handler_data] impl MessageHandler for AppWindowMessageHandler { fn process_message(&mut self, message: AppWindowMessage, responses: &mut std::collections::VecDeque, _: ()) { match message { - AppWindowMessage::UpdatePlatform { platform } => { - self.platform = platform; - responses.add(FrontendMessage::UpdatePlatform { platform: self.platform }); - } AppWindowMessage::PointerLock => { responses.add(FrontendMessage::WindowPointerLock); } @@ -66,3 +61,14 @@ pub enum AppWindowPlatform { Mac, Linux, } + +impl From<&Environment> for AppWindowPlatform { + fn from(environment: &Environment) -> Self { + match (environment.platform, environment.host) { + (Platform::Web, _) => AppWindowPlatform::Web, + (Platform::Desktop, Host::Linux) => AppWindowPlatform::Linux, + (Platform::Desktop, Host::Mac) => AppWindowPlatform::Mac, + (Platform::Desktop, Host::Windows) => AppWindowPlatform::Windows, + } + } +} diff --git a/editor/src/messages/globals/global_variables.rs b/editor/src/messages/globals/global_variables.rs deleted file mode 100644 index b3fb71da06..0000000000 --- a/editor/src/messages/globals/global_variables.rs +++ /dev/null @@ -1,4 +0,0 @@ -use crate::messages::portfolio::utility_types::Platform; -use std::sync::OnceLock; - -pub static GLOBAL_PLATFORM: OnceLock = OnceLock::new(); diff --git a/editor/src/messages/globals/globals_message.rs b/editor/src/messages/globals/globals_message.rs deleted file mode 100644 index 11a39e9cc1..0000000000 --- a/editor/src/messages/globals/globals_message.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::messages::portfolio::utility_types::Platform; -use crate::messages::prelude::*; - -#[impl_message(Message, Globals)] -#[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize)] -pub enum GlobalsMessage { - SetPlatform { platform: Platform }, -} diff --git a/editor/src/messages/globals/globals_message_handler.rs b/editor/src/messages/globals/globals_message_handler.rs deleted file mode 100644 index 8974bd16ce..0000000000 --- a/editor/src/messages/globals/globals_message_handler.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::messages::prelude::*; - -#[derive(Debug, Default, ExtractField)] -pub struct GlobalsMessageHandler {} - -#[message_handler_data] -impl MessageHandler for GlobalsMessageHandler { - fn process_message(&mut self, message: GlobalsMessage, _responses: &mut VecDeque, _: ()) { - match message { - GlobalsMessage::SetPlatform { platform } => { - if GLOBAL_PLATFORM.get() != Some(&platform) { - GLOBAL_PLATFORM.set(platform).expect("Failed to set GLOBAL_PLATFORM"); - } - } - } - } - - advertise_actions!(GlobalsMessageDiscriminant; - ); -} diff --git a/editor/src/messages/globals/mod.rs b/editor/src/messages/globals/mod.rs deleted file mode 100644 index 65cc989f6e..0000000000 --- a/editor/src/messages/globals/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod globals_message; -mod globals_message_handler; - -pub mod global_variables; - -#[doc(inline)] -pub use globals_message::{GlobalsMessage, GlobalsMessageDiscriminant}; -#[doc(inline)] -pub use globals_message_handler::GlobalsMessageHandler; diff --git a/editor/src/messages/input_mapper/input_mapper_message_handler.rs b/editor/src/messages/input_mapper/input_mapper_message_handler.rs index 058fb70c83..d38845c6d9 100644 --- a/editor/src/messages/input_mapper/input_mapper_message_handler.rs +++ b/editor/src/messages/input_mapper/input_mapper_message_handler.rs @@ -1,8 +1,8 @@ use super::utility_types::input_keyboard::KeysGroup; use super::utility_types::misc::Mapping; +use crate::application::Editor; use crate::messages::input_mapper::utility_types::input_keyboard::{self, Key}; use crate::messages::input_mapper::utility_types::misc::MappingEntry; -use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; #[derive(ExtractField)] @@ -48,11 +48,7 @@ impl InputMapperMessageHandler { let found_actions = all_mapping_entries.filter(|entry| entry.action.to_discriminant() == *action_to_find); // Get the `Key` for this platform's accelerator key - let keyboard_layout = || GLOBAL_PLATFORM.get().copied().unwrap_or_default().as_keyboard_platform_layout(); - let platform_accel_key = match keyboard_layout() { - KeyboardPlatformLayout::Standard => Key::Control, - KeyboardPlatformLayout::Mac => Key::Command, - }; + let platform_accel_key = if Editor::environment().is_mac() { Key::Command } else { Key::Control }; let entry_to_key = |entry: &MappingEntry| { // Get the modifier keys for the entry (and convert them to Key) diff --git a/editor/src/messages/input_mapper/input_mappings.rs b/editor/src/messages/input_mapper/input_mappings.rs index 6ad22cb71c..8daf93ca9f 100644 --- a/editor/src/messages/input_mapper/input_mappings.rs +++ b/editor/src/messages/input_mapper/input_mappings.rs @@ -1,3 +1,4 @@ +use crate::application::Editor; use crate::consts::{BIG_NUDGE_AMOUNT, BRUSH_SIZE_CHANGE_KEYBOARD, NUDGE_AMOUNT}; use crate::messages::input_mapper::key_mapping::MappingVariant; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeyStates}; @@ -8,7 +9,6 @@ use crate::messages::input_mapper::utility_types::misc::{KeyMappingEntries, Mapp use crate::messages::portfolio::document::node_graph::utility_types::Direction; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; use crate::messages::portfolio::document::utility_types::misc::GroupFolderType; -use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; use crate::messages::tool::tool_messages::brush_tool::BrushToolMessageOptionsUpdate; use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys; @@ -27,8 +27,7 @@ pub fn input_mappings(zoom_with_scroll: bool) -> Mapping { use InputMapperMessage::*; use Key::*; - // TODO: Fix this failing to load the correct data (and throwing a console warning) because it's occurring before the value has been supplied during initialization from the JS `initAfterFrontendReady` - let keyboard_platform = GLOBAL_PLATFORM.get().copied().unwrap_or_default().as_keyboard_platform_layout(); + let is_mac = Editor::environment().is_mac(); // NOTICE: // If a new mapping you added here isn't working (and perhaps another lower-precedence one is instead), make sure to advertise @@ -58,8 +57,8 @@ pub fn input_mappings(zoom_with_scroll: bool) -> Mapping { entry!(KeyDown(KeyZ); modifiers=[Accel, MouseLeft], action_dispatch=DocumentMessage::Noop), // // AppWindowMessage - entry!(KeyDown(F11); disabled=(keyboard_platform == KeyboardPlatformLayout::Mac), action_dispatch=AppWindowMessage::Fullscreen), - entry!(KeyDown(KeyF); modifiers=[Command, Control], disabled=(keyboard_platform != KeyboardPlatformLayout::Mac), action_dispatch=AppWindowMessage::Fullscreen), + entry!(KeyDown(F11); disabled=is_mac, action_dispatch=AppWindowMessage::Fullscreen), + entry!(KeyDown(KeyF); modifiers=[Command, Control], disabled=!is_mac, action_dispatch=AppWindowMessage::Fullscreen), entry!(KeyDown(KeyQ); modifiers=[Command], disabled=cfg!(not(target_os = "macos")), action_dispatch=AppWindowMessage::Close), // // ClipboardMessage @@ -429,8 +428,8 @@ pub fn input_mappings(zoom_with_scroll: bool) -> Mapping { entry!(WheelScroll; modifiers=[Shift], disabled=zoom_with_scroll, action_dispatch=NavigationMessage::CanvasPanMouseWheel { use_y_as_x: true }), entry!(WheelScroll; disabled=zoom_with_scroll, action_dispatch=NavigationMessage::CanvasPanMouseWheel { use_y_as_x: false }), // On Mac, the OS already converts Shift+scroll into horizontal scrolling so we have to reverse the behavior from normal to produce the same outcome - entry!(WheelScroll; modifiers=[Control], disabled=!zoom_with_scroll, action_dispatch=NavigationMessage::CanvasPanMouseWheel { use_y_as_x: keyboard_platform == KeyboardPlatformLayout::Mac }), - entry!(WheelScroll; modifiers=[Shift], disabled=!zoom_with_scroll, action_dispatch=NavigationMessage::CanvasPanMouseWheel { use_y_as_x: keyboard_platform != KeyboardPlatformLayout::Mac }), + entry!(WheelScroll; modifiers=[Control], disabled=!zoom_with_scroll, action_dispatch=NavigationMessage::CanvasPanMouseWheel { use_y_as_x: is_mac }), + entry!(WheelScroll; modifiers=[Shift], disabled=!zoom_with_scroll, action_dispatch=NavigationMessage::CanvasPanMouseWheel { use_y_as_x: !is_mac }), entry!(WheelScroll; disabled=!zoom_with_scroll, action_dispatch=NavigationMessage::CanvasZoomMouseWheel), entry!(KeyDown(PageUp); modifiers=[Shift], action_dispatch=NavigationMessage::CanvasPanByViewportFraction { delta: DVec2::new(1., 0.) }), entry!(KeyDown(PageDown); modifiers=[Shift], action_dispatch=NavigationMessage::CanvasPanByViewportFraction { delta: DVec2::new(-1., 0.) }), diff --git a/editor/src/messages/input_mapper/utility_types/input_keyboard.rs b/editor/src/messages/input_mapper/utility_types/input_keyboard.rs index e5b97c2bc3..e8c9bc533f 100644 --- a/editor/src/messages/input_mapper/utility_types/input_keyboard.rs +++ b/editor/src/messages/input_mapper/utility_types/input_keyboard.rs @@ -1,4 +1,4 @@ -use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; +use crate::application::Editor; use crate::messages::prelude::*; use bitflags::bitflags; use std::fmt::{self, Display, Formatter}; @@ -258,7 +258,7 @@ impl fmt::Display for Key { return write!(f, "{}", key_name.chars().skip(KEY_PREFIX.len()).collect::()); } - let keyboard_layout = || GLOBAL_PLATFORM.get().copied().unwrap_or_default().as_keyboard_platform_layout(); + let is_mac = Editor::environment().is_mac(); let name = match self { // Writing system keys @@ -275,21 +275,21 @@ impl fmt::Display for Key { Self::Slash => "/", // Functional keys - Self::Alt => match keyboard_layout() { - KeyboardPlatformLayout::Standard => "Alt", - KeyboardPlatformLayout::Mac => "⌥", + Self::Alt => match is_mac { + true => "⌥", + false => "Alt", }, - Self::Meta => match keyboard_layout() { - KeyboardPlatformLayout::Standard => "⊞", - KeyboardPlatformLayout::Mac => "⌘", + Self::Meta => match is_mac { + true => "⌘", + false => "⊞", }, - Self::Shift => match keyboard_layout() { - KeyboardPlatformLayout::Standard => "Shift", - KeyboardPlatformLayout::Mac => "⇧", + Self::Shift => match is_mac { + true => "⇧", + false => "Shift", }, - Self::Control => match keyboard_layout() { - KeyboardPlatformLayout::Standard => "Ctrl", - KeyboardPlatformLayout::Mac => "⌃", + Self::Control => match is_mac { + true => "⌃", + false => "Ctrl", }, Self::Backspace => "⌫", @@ -317,9 +317,9 @@ impl fmt::Display for Key { // Other keys that aren't part of the W3C spec Self::Command => "⌘", - Self::Accel => match keyboard_layout() { - KeyboardPlatformLayout::Standard => "Ctrl", - KeyboardPlatformLayout::Mac => "⌘", + Self::Accel => match is_mac { + true => "⌘", + false => "Ctrl", }, Self::MouseLeft => "Click", Self::MouseRight => "R.Click", @@ -356,10 +356,9 @@ impl fmt::Display for KeysGroup { .0 .iter() .map(|key| { - let keyboard_layout = GLOBAL_PLATFORM.get().copied().unwrap_or_default().as_keyboard_platform_layout(); let key_is_modifier = matches!(*key, Key::Control | Key::Command | Key::Alt | Key::Shift | Key::Meta | Key::Accel); - if keyboard_layout == KeyboardPlatformLayout::Mac && key_is_modifier { + if Editor::environment().is_mac() && key_is_modifier { key.to_string() } else { key.to_string() + JOINER_MARK diff --git a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs index 3464f0a07e..e9f5847b7b 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs @@ -1,13 +1,12 @@ +use crate::application::Editor; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeyStates, ModifierKeys}; use crate::messages::input_mapper::utility_types::input_mouse::{MouseButton, MouseKeys, MouseState}; use crate::messages::input_mapper::utility_types::misc::FrameTimeInfo; -use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; use std::time::Duration; #[derive(ExtractField)] pub struct InputPreprocessorMessageContext<'a> { - pub keyboard_platform: KeyboardPlatformLayout, pub viewport: &'a ViewportMessageHandler, } @@ -22,11 +21,11 @@ pub struct InputPreprocessorMessageHandler { #[message_handler_data] impl<'a> MessageHandler> for InputPreprocessorMessageHandler { fn process_message(&mut self, message: InputPreprocessorMessage, responses: &mut VecDeque, context: InputPreprocessorMessageContext<'a>) { - let InputPreprocessorMessageContext { keyboard_platform, viewport } = context; + let InputPreprocessorMessageContext { viewport } = context; match message { InputPreprocessorMessage::DoubleClick { editor_mouse_state, modifier_keys } => { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(viewport); self.mouse.position = mouse_state.position; @@ -43,7 +42,7 @@ impl<'a> MessageHandler { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); self.keyboard.set(key as usize); if !key_repeat { responses.add(InputMapperMessage::KeyDownNoRepeat(key)); @@ -51,7 +50,7 @@ impl<'a> MessageHandler { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); self.keyboard.unset(key as usize); if !key_repeat { responses.add(InputMapperMessage::KeyUpNoRepeat(key)); @@ -59,7 +58,7 @@ impl<'a> MessageHandler { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(viewport); self.mouse.position = mouse_state.position; @@ -67,7 +66,7 @@ impl<'a> MessageHandler { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(viewport); self.mouse.position = mouse_state.position; @@ -78,7 +77,7 @@ impl<'a> MessageHandler { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(viewport); self.mouse.position = mouse_state.position; @@ -86,7 +85,7 @@ impl<'a> MessageHandler { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(viewport); self.mouse.position = mouse_state.position; @@ -99,7 +98,7 @@ impl<'a> MessageHandler { - self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); + self.update_states_of_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(viewport); self.mouse.position = mouse_state.position; @@ -148,7 +147,7 @@ impl InputPreprocessorMessageHandler { self.mouse = new_state; } - fn update_states_of_modifier_keys(&mut self, pressed_modifier_keys: ModifierKeys, keyboard_platform: KeyboardPlatformLayout, responses: &mut VecDeque) { + fn update_states_of_modifier_keys(&mut self, pressed_modifier_keys: ModifierKeys, responses: &mut VecDeque) { let is_key_pressed = |key_to_check: ModifierKeys| pressed_modifier_keys.contains(key_to_check); // Update the state of the concrete modifier keys based on the source state @@ -157,16 +156,16 @@ impl InputPreprocessorMessageHandler { self.update_modifier_key(Key::Control, is_key_pressed(ModifierKeys::CONTROL), responses); // Update the state of either the concrete Meta or the Command keys based on which one is applicable for this platform - let meta_or_command = match keyboard_platform { - KeyboardPlatformLayout::Mac => Key::Command, - KeyboardPlatformLayout::Standard => Key::Meta, + let meta_or_command = match Editor::environment().is_mac() { + true => Key::Command, + false => Key::Meta, }; self.update_modifier_key(meta_or_command, is_key_pressed(ModifierKeys::META_OR_COMMAND), responses); // Update the state of the virtual Accel key (the primary accelerator key) based on the source state of the Control or Command key, whichever is relevant on this platform - let accel_virtual_key_state = match keyboard_platform { - KeyboardPlatformLayout::Mac => is_key_pressed(ModifierKeys::META_OR_COMMAND), - KeyboardPlatformLayout::Standard => is_key_pressed(ModifierKeys::CONTROL), + let accel_virtual_key_state = match Editor::environment().is_mac() { + true => is_key_pressed(ModifierKeys::META_OR_COMMAND), + false => is_key_pressed(ModifierKeys::CONTROL), }; self.update_modifier_key(Key::Accel, accel_virtual_key_state, responses); } @@ -188,7 +187,6 @@ impl InputPreprocessorMessageHandler { mod test { use crate::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys}; use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta}; - use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; #[test] @@ -206,7 +204,6 @@ mod test { let mut responses = VecDeque::new(); let context = InputPreprocessorMessageContext { - keyboard_platform: KeyboardPlatformLayout::Standard, viewport: &ViewportMessageHandler::default(), }; input_preprocessor.process_message(message, &mut responses, context); @@ -226,7 +223,6 @@ mod test { let mut responses = VecDeque::new(); let context = InputPreprocessorMessageContext { - keyboard_platform: KeyboardPlatformLayout::Standard, viewport: &ViewportMessageHandler::default(), }; input_preprocessor.process_message(message, &mut responses, context); @@ -246,7 +242,6 @@ mod test { let mut responses = VecDeque::new(); let context = InputPreprocessorMessageContext { - keyboard_platform: KeyboardPlatformLayout::Standard, viewport: &ViewportMessageHandler::default(), }; input_preprocessor.process_message(message, &mut responses, context); @@ -268,7 +263,6 @@ mod test { let mut responses = VecDeque::new(); let context = InputPreprocessorMessageContext { - keyboard_platform: KeyboardPlatformLayout::Standard, viewport: &ViewportMessageHandler::default(), }; input_preprocessor.process_message(message, &mut responses, context); @@ -289,7 +283,6 @@ mod test { let mut responses = VecDeque::new(); let context = InputPreprocessorMessageContext { - keyboard_platform: KeyboardPlatformLayout::Standard, viewport: &ViewportMessageHandler::default(), }; input_preprocessor.process_message(message, &mut responses, context); diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index 4b104495ee..5d4dd8bfea 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -22,8 +22,6 @@ pub enum Message { #[child] Frontend(FrontendMessage), #[child] - Globals(GlobalsMessage), - #[child] InputPreprocessor(InputPreprocessorMessage), #[child] KeyMapping(KeyMappingMessage), diff --git a/editor/src/messages/mod.rs b/editor/src/messages/mod.rs index 7edfea806e..7b3c39e7d1 100644 --- a/editor/src/messages/mod.rs +++ b/editor/src/messages/mod.rs @@ -8,7 +8,6 @@ pub mod debug; pub mod defer; pub mod dialog; pub mod frontend; -pub mod globals; pub mod input_mapper; pub mod input_preprocessor; pub mod layout; diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index 00e280b51c..3806a1e245 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -1,3 +1,4 @@ +use crate::application::Editor; use crate::consts::{ VIEWPORT_ROTATE_SNAP_INTERVAL, VIEWPORT_SCROLL_RATE, VIEWPORT_ZOOM_LEVELS, VIEWPORT_ZOOM_MIN_FRACTION_COVER, VIEWPORT_ZOOM_MOUSE_RATE, VIEWPORT_ZOOM_SCALE_MAX, VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR, @@ -8,7 +9,6 @@ use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition; use crate::messages::portfolio::document::navigation::utility_types::NavigationOperation; use crate::messages::portfolio::document::utility_types::misc::PTZ; use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface; -use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; use glam::{DAffine2, DVec2}; @@ -176,9 +176,7 @@ impl MessageHandler> for Navigat } NavigationMessage::CanvasPanMouseWheel { use_y_as_x } => { // On Mac, the OS already converts Shift+scroll into horizontal scrolling - let keyboard_platform = GLOBAL_PLATFORM.get().copied().unwrap_or_default().as_keyboard_platform_layout(); - - let delta = if use_y_as_x && keyboard_platform == KeyboardPlatformLayout::Standard { + let delta = if use_y_as_x && !Editor::environment().is_mac() { (ipp.mouse.scroll_delta.y, 0.).into() } else { ipp.mouse.scroll_delta.as_dvec2() diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 83e4e35af1..6e8ba98842 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -1,7 +1,7 @@ use super::document::utility_types::document_metadata::LayerNodeIdentifier; use super::document::utility_types::network_interface; use super::utility_types::{PanelType, PersistentData}; -use crate::application::generate_uuid; +use crate::application::{Editor, generate_uuid}; use crate::consts::{DEFAULT_DOCUMENT_NAME, DEFAULT_STROKE_WIDTH, FILE_EXTENSION}; use crate::messages::animation::TimingInformation; use crate::messages::clipboard::utility_types::ClipboardContent; @@ -101,9 +101,17 @@ impl MessageHandler> for Portfolio // Messages PortfolioMessage::Init => { + // Initialize the frontend with environment information + responses.add(FrontendMessage::UpdatePlatform { + platform: Editor::environment().into(), + }); + // Tell frontend to load persistent preferences responses.add(FrontendMessage::TriggerLoadPreferences); + // Before loading any documents, initially prepare the welcome screen buttons layout + responses.add(PortfolioMessage::RequestWelcomeScreenButtonsLayout); + // Tell frontend to load the current document responses.add(FrontendMessage::TriggerLoadFirstAutoSaveDocument); @@ -128,15 +136,13 @@ impl MessageHandler> for Portfolio shortcut: action_shortcut_manual!(Key::Shift, Key::MouseLeft), }); - // Before loading any documents, initially prepare the welcome screen buttons layout - responses.add(PortfolioMessage::RequestWelcomeScreenButtonsLayout); - // Request status bar info layout responses.add(PortfolioMessage::RequestStatusBarInfoLayout); // Tell frontend to finish loading persistent documents responses.add(FrontendMessage::TriggerLoadRestAutoSaveDocuments); + // Tell frontend to load documented passed in as launch arguments responses.add(FrontendMessage::TriggerOpenLaunchDocuments); } PortfolioMessage::DocumentPassMessage { document_id, message } => { diff --git a/editor/src/messages/portfolio/utility_types.rs b/editor/src/messages/portfolio/utility_types.rs index 54a526ecdc..a43fced4c1 100644 --- a/editor/src/messages/portfolio/utility_types.rs +++ b/editor/src/messages/portfolio/utility_types.rs @@ -82,37 +82,6 @@ impl FontCatalogStyle { } } -#[derive(PartialEq, Eq, Clone, Copy, Default, Debug, serde::Serialize, serde::Deserialize)] -pub enum Platform { - #[default] - Unknown, - Windows, - Mac, - Linux, -} - -impl Platform { - pub fn as_keyboard_platform_layout(&self) -> KeyboardPlatformLayout { - match self { - Platform::Mac => KeyboardPlatformLayout::Mac, - Platform::Windows | Platform::Linux => KeyboardPlatformLayout::Standard, - Platform::Unknown => { - warn!("The platform has not been set, remember to send `GlobalsMessage::SetPlatform` during editor initialization."); - KeyboardPlatformLayout::Standard - } - } - } -} - -#[derive(PartialEq, Eq, Clone, Copy, Default, Debug, serde::Serialize, serde::Deserialize)] -pub enum KeyboardPlatformLayout { - /// Standard keyboard mapping used by Windows and Linux - #[default] - Standard, - /// Keyboard mapping used by Macs where Command is sometimes used in favor of Control - Mac, -} - #[derive(PartialEq, Eq, Clone, Copy, Debug, Default, serde::Serialize, serde::Deserialize)] pub enum PanelType { #[default] diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index f64cbf0ee9..d331697cc0 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -15,7 +15,6 @@ pub use crate::messages::dialog::new_document_dialog::{NewDocumentDialogMessage, pub use crate::messages::dialog::preferences_dialog::{PreferencesDialogMessage, PreferencesDialogMessageContext, PreferencesDialogMessageDiscriminant, PreferencesDialogMessageHandler}; pub use crate::messages::dialog::{DialogMessage, DialogMessageContext, DialogMessageDiscriminant, DialogMessageHandler}; pub use crate::messages::frontend::{FrontendMessage, FrontendMessageDiscriminant}; -pub use crate::messages::globals::{GlobalsMessage, GlobalsMessageDiscriminant, GlobalsMessageHandler}; pub use crate::messages::input_mapper::key_mapping::{KeyMappingMessage, KeyMappingMessageContext, KeyMappingMessageDiscriminant, KeyMappingMessageHandler}; pub use crate::messages::input_mapper::{InputMapperMessage, InputMapperMessageContext, InputMapperMessageDiscriminant, InputMapperMessageHandler}; pub use crate::messages::input_preprocessor::{InputPreprocessorMessage, InputPreprocessorMessageContext, InputPreprocessorMessageDiscriminant, InputPreprocessorMessageHandler}; @@ -51,7 +50,6 @@ pub use crate::messages::tool::tool_messages::spline_tool::{SplineToolMessage, S pub use crate::messages::tool::tool_messages::text_tool::{TextToolMessage, TextToolMessageDiscriminant}; // Helper/miscellaneous -pub use crate::messages::globals::global_variables::*; pub use crate::messages::portfolio::document::utility_types::misc::DocumentId; pub use graphite_proc_macros::*; pub use std::collections::{HashMap, HashSet, VecDeque}; diff --git a/editor/src/test_utils.rs b/editor/src/test_utils.rs index 63291d1f1c..8c963e0b57 100644 --- a/editor/src/test_utils.rs +++ b/editor/src/test_utils.rs @@ -1,9 +1,7 @@ use crate::application::Editor; -use crate::application::set_uuid_seed; use crate::messages::input_mapper::utility_types::input_keyboard::ModifierKeys; use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta, ViewportPosition}; use crate::messages::portfolio::document::node_graph::document_node_definitions::DefinitionIdentifier; -use crate::messages::portfolio::utility_types::Platform; use crate::messages::prelude::*; use crate::messages::tool::tool_messages::tool_prelude::Key; use crate::messages::tool::utility_types::ToolType; @@ -25,15 +23,11 @@ pub struct EditorTestUtils { impl EditorTestUtils { pub fn create() -> Self { let _ = env_logger::builder().is_test(true).try_init(); - set_uuid_seed(0); let (mut editor, runtime) = Editor::new_local_executor(); - // We have to set this directly instead of using `GlobalsMessage::SetPlatform` because race conditions with multiple tests can cause that message handler to set it more than once, which is a failure. - // It isn't sufficient to guard the message dispatch here with a check if the once_cell is empty, because that isn't atomic and the time between checking and handling the dispatch can let multiple through. - let _ = GLOBAL_PLATFORM.set(Platform::Windows).is_ok(); - editor.handle_message(PortfolioMessage::Init); + Self { editor, runtime } } diff --git a/frontend/src/components/Editor.svelte b/frontend/src/components/Editor.svelte index 584201eb51..1e220a1e37 100644 --- a/frontend/src/components/Editor.svelte +++ b/frontend/src/components/Editor.svelte @@ -16,7 +16,6 @@ import { createNodeGraphState } from "@graphite/state-providers/node-graph"; import { createPortfolioState } from "@graphite/state-providers/portfolio"; import { createTooltipState } from "@graphite/state-providers/tooltip"; - import { operatingSystem } from "@graphite/utility-functions/platform"; import MainWindow from "@graphite/components/window/MainWindow.svelte"; @@ -51,7 +50,7 @@ onMount(() => { // Initialize certain setup tasks required by the editor backend to be ready for the user now that the frontend is ready - editor.handle.initAfterFrontendReady(operatingSystem()); + editor.handle.initAfterFrontendReady(); }); onDestroy(() => { diff --git a/frontend/src/editor.ts b/frontend/src/editor.ts index fcbbba3eee..1661b78920 100644 --- a/frontend/src/editor.ts +++ b/frontend/src/editor.ts @@ -1,8 +1,12 @@ // import { panicProxy } from "@graphite/utility-functions/panic-proxy"; -import init, { setRandomSeed, wasmMemory, EditorHandle, receiveNativeMessage } from "@graphite/../wasm/pkg/graphite_wasm"; + +import { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm"; +import init, { wasmMemory, receiveNativeMessage } from "@graphite/../wasm/pkg/graphite_wasm"; import { type JsMessageType } from "@graphite/messages"; import { createSubscriptionRouter, type SubscriptionRouter } from "@graphite/subscription-router"; +import { operatingSystem } from "@graphite/utility-functions/platform"; +// TODO: Remove `raw`, split out `subscriptions`, and unwrap the remaining `handle` so `EditorHandle` can replace `Editor` and then it can also be renamed to `Editor` to fully remove `EditorHandle`. export type Editor = { raw: WebAssembly.Memory; handle: EditorHandle; @@ -14,10 +18,10 @@ let wasmImport: WebAssembly.Memory | undefined; // Should be called asynchronously before `createEditor()`. export async function initWasm() { - // Skip if the WASM module is already initialized + // Skip if the Wasm module is already initialized if (wasmImport !== undefined) return; - // Import the WASM module JS bindings and wrap them in the panic proxy + // Import the Wasm module JS bindings and wrap them in the panic proxy const wasm = await init(); for (const [name, f] of Object.entries(wasm)) { if (name.startsWith("__node_registry")) f(); @@ -28,28 +32,27 @@ export async function initWasm() { (window as any).imageCanvases = {}; // eslint-disable-next-line @typescript-eslint/no-explicit-any (window as any).receiveNativeMessage = receiveNativeMessage; - - // Provide a random starter seed which must occur after initializing the WASM module, since WASM can't generate its own random numbers - const randomSeedFloat = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); - const randomSeed = BigInt(randomSeedFloat); - setRandomSeed(randomSeed); } // Should be called after running `initWasm()` and its promise resolving. export function createEditor(): Editor { - // Raw: object containing several callable functions from `editor_api.rs` defined directly on the WASM module, not the `EditorHandle` struct (generated by wasm-bindgen) - if (!wasmImport) throw new Error("Editor WASM backend was not initialized at application startup"); + // Raw: object containing several callable functions from `editor_api.rs` defined directly on the Wasm module, not the `EditorHandle` struct (generated by wasm-bindgen) + if (!wasmImport) throw new Error("Editor Wasm backend was not initialized at application startup"); const raw: WebAssembly.Memory = wasmImport; + // Provide a random starter seed which must occur after initializing the Wasm module, since Wasm can't generate its own random numbers + const randomSeedFloat = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); + const randomSeed = BigInt(randomSeedFloat); + // Handle: object containing many functions from `editor_api.rs` that are part of the `EditorHandle` struct (generated by wasm-bindgen) - const handle: EditorHandle = new EditorHandle((messageType: JsMessageType, messageData: Record) => { - // This callback is called by WASM when a FrontendMessage is received from the WASM wrapper `EditorHandle` + const handle = EditorHandle.create(operatingSystem(), randomSeed, (messageType: JsMessageType, messageData: Record) => { + // This callback is called by Wasm when a FrontendMessage is received from the Wasm wrapper `EditorHandle` // We pass along the first two arguments then add our own `raw` and `handle` context for the last two arguments subscriptions.handleJsMessage(messageType, messageData, raw, handle); }); - // Subscriptions: allows subscribing to messages in JS that are sent from the WASM backend - const subscriptions: SubscriptionRouter = createSubscriptionRouter(); + // Subscriptions: allows subscribing to messages in JS that are sent from the Wasm backend + const subscriptions = createSubscriptionRouter(); // Check if the URL hash fragment has any demo artwork to be loaded (async () => { diff --git a/frontend/src/io-managers/panic.ts b/frontend/src/io-managers/panic.ts index 3a6343289e..312af59fc9 100644 --- a/frontend/src/io-managers/panic.ts +++ b/frontend/src/io-managers/panic.ts @@ -40,7 +40,7 @@ export function githubUrl(panicDetails: string): string { Provide any further information or context that you think would be helpful in fixing the issue. Screenshots or video can be linked or attached to this issue. **Browser and OS** - ${browserVersion()}, ${operatingSystem().replace("Unknown", "YOUR OPERATING SYSTEM")} + ${browserVersion()}, ${operatingSystem()} **Stack Trace** Copied from the crash dialog in the Graphite editor: diff --git a/frontend/src/utility-functions/platform.ts b/frontend/src/utility-functions/platform.ts index 6a7b7365c1..e50e027068 100644 --- a/frontend/src/utility-functions/platform.ts +++ b/frontend/src/utility-functions/platform.ts @@ -25,18 +25,17 @@ export function browserVersion(): string { return `${match[0]} ${match[1]}`; } -export type OperatingSystem = "Windows" | "Mac" | "Linux" | "Unknown"; +export type OperatingSystem = "Windows" | "Mac" | "Linux"; export function operatingSystem(): OperatingSystem { const osTable: Record = { Windows: "Windows", Mac: "Mac", Linux: "Linux", - Unknown: "Unknown", }; const userAgentOS = Object.keys(osTable).find((key) => window.navigator.userAgent.includes(key)); - return osTable[userAgentOS || "Unknown"]; + return osTable[userAgentOS || "Windows"]; } export function isDesktop(): boolean { diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index cfb4024914..192687feac 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -12,7 +12,7 @@ use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys; use editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ScrollDelta}; use editor::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use editor::messages::portfolio::document::utility_types::network_interface::ImportOrExport; -use editor::messages::portfolio::utility_types::{FontCatalog, FontCatalogFamily, Platform}; +use editor::messages::portfolio::utility_types::{FontCatalog, FontCatalogFamily}; use editor::messages::prelude::*; use editor::messages::tool::tool_messages::tool_prelude::WidgetId; use graph_craft::document::NodeId; @@ -31,7 +31,7 @@ use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, ImageData, window}; #[cfg(not(feature = "native"))] use crate::EDITOR; #[cfg(not(feature = "native"))] -use editor::application::Editor; +use editor::application::{Editor, Environment, Host, Platform}; static IMAGE_DATA_HASH: AtomicU64 = AtomicU64::new(0); @@ -43,14 +43,7 @@ fn calculate_hash(t: &T) -> u64 { hasher.finish() } -/// Set the random seed used by the editor by calling this from JS upon initialization. -/// This is necessary because WASM doesn't have a random number generator. -#[wasm_bindgen(js_name = setRandomSeed)] -pub fn set_random_seed(seed: u64) { - editor::application::set_uuid_seed(seed); -} - -/// Provides a handle to access the raw WASM memory. +/// Provides a handle to access the raw Wasm memory. #[wasm_bindgen(js_name = wasmMemory)] pub fn wasm_memory() -> JsValue { wasm_bindgen::memory() @@ -89,9 +82,20 @@ impl EditorHandle { #[wasm_bindgen] impl EditorHandle { #[cfg(not(feature = "native"))] - #[wasm_bindgen(constructor)] - pub fn new(frontend_message_handler_callback: js_sys::Function) -> Self { - let editor = Editor::new(); + pub fn create(platform: String, uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle { + let editor = Editor::new( + Environment { + platform: Platform::Web, + host: match platform.as_str() { + "Linux" => Host::Linux, + "Mac" => Host::Mac, + "Windows" => Host::Windows, + _ => unreachable!(), + }, + }, + uuid_random_seed, + ); + let editor_handle = EditorHandle { frontend_message_handler_callback }; if EDITOR.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor))).is_none() { log::error!("Attempted to initialize the editor more than once"); @@ -103,8 +107,7 @@ impl EditorHandle { } #[cfg(feature = "native")] - #[wasm_bindgen(constructor)] - pub fn new(frontend_message_handler_callback: js_sys::Function) -> Self { + pub fn create(_platform: String, _uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle { let editor_handle = EditorHandle { frontend_message_handler_callback }; if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() { log::error!("Attempted to initialize the editor handle more than once"); @@ -184,18 +187,10 @@ impl EditorHandle { // ======================================================================== #[wasm_bindgen(js_name = initAfterFrontendReady)] - pub fn init_after_frontend_ready(&self, platform: String) { + pub fn init_after_frontend_ready(&self) { #[cfg(feature = "native")] crate::native_communcation::initialize_native_communication(); - // Send initialization messages - let platform = match platform.as_str() { - "Windows" => Platform::Windows, - "Mac" => Platform::Mac, - "Linux" => Platform::Linux, - _ => Platform::Unknown, - }; - self.dispatch(GlobalsMessage::SetPlatform { platform }); self.dispatch(PortfolioMessage::Init); // Poll node graph evaluation on `requestAnimationFrame`