From ea322a38d53b73cfdc8924765b81fb5b65db776c Mon Sep 17 00:00:00 2001 From: Wu Yuwei Date: Fri, 22 Nov 2024 12:13:12 +0900 Subject: [PATCH] Rearrange platform code blocks --- Cargo.toml | 2 +- src/context_menu.rs | 41 ++++++++------- src/webview.rs | 4 +- src/window.rs | 119 ++++++++++++++++++++------------------------ 4 files changed, 80 insertions(+), 86 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3350426..e30f93a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,7 +108,7 @@ headers = "0.3" versoview_messages = { path = "./versoview_messages" } [target.'cfg(all(unix, not(apple), not(android)))'.dependencies] -serde_json = "1.0.132" +serde_json = "1.0" serde = { workspace = true } [target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies] diff --git a/src/context_menu.rs b/src/context_menu.rs index b1feb91..3f0c348 100644 --- a/src/context_menu.rs +++ b/src/context_menu.rs @@ -24,20 +24,38 @@ use webrender_api::units::DeviceIntRect; #[cfg(linux)] use winit::dpi::PhysicalPosition; -/// Context Menu inner menu +/// Basic menu type building block #[cfg(any(target_os = "macos", target_os = "windows"))] pub struct Menu(pub MudaMenu); -/// Context Menu inner menu +/// Basic menu type building block #[cfg(linux)] #[derive(Debug, Clone)] pub struct Menu(pub Vec); +/// The Context Menu of the Window. It will be opened when users right click on any window's +/// webview. +/// +/// **Platform Specific** +/// - macOS / Windows: This will be native context menu supported by each OS. +/// - Wayland: Winit doesn't support popup surface of Wayland at the moment. So we utilize a custom +/// webview implementation. +#[derive(Debug, Clone)] +pub struct ContextMenu { + #[cfg(any(target_os = "macos", target_os = "windows"))] + menu: MudaMenu, + #[cfg(linux)] + menu_items: Vec, + /// The webview that the context menu is attached to + #[cfg(linux)] + webview: WebView, +} + impl ContextMenu { /// Create context menu with custom items /// /// **Platform Specific** /// - macOS / Windows: Creates a context menu by muda crate with natvie OS support - /// - Linux: Creates a context menu with webview implementation + /// - Wayland: Creates a context menu with webview implementation pub fn new_with_menu(menu: Menu) -> Self { #[cfg(any(target_os = "macos", target_os = "windows"))] { @@ -56,12 +74,6 @@ impl ContextMenu { } } -/// Context Menu -#[cfg(any(target_os = "macos", target_os = "windows"))] -pub struct ContextMenu { - menu: MudaMenu, -} - #[cfg(any(target_os = "macos", target_os = "windows"))] impl ContextMenu { /// Show the context menu on current cursor position @@ -93,15 +105,6 @@ impl ContextMenu { } } -/// Context Menu -#[cfg(linux)] -#[derive(Debug, Clone)] -pub struct ContextMenu { - menu_items: Vec, - /// The webview that the context menu is attached to - webview: WebView, -} - #[cfg(linux)] impl ContextMenu { /// Show the context menu to current cursor position @@ -218,7 +221,7 @@ impl MenuItem { /// Context Menu Click Result #[cfg(linux)] #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ContextMenuClickResult { +pub struct ContextMenuResult { /// The id of the menu ite /// Get the label of the menu item pub id: String, /// Close the context menu diff --git a/src/webview.rs b/src/webview.rs index 8c05add..a870dff 100644 --- a/src/webview.rs +++ b/src/webview.rs @@ -15,7 +15,7 @@ use webrender_api::units::DeviceIntRect; use crate::{compositor::IOCompositor, verso::send_to_constellation, window::Window}; #[cfg(linux)] -use crate::context_menu::ContextMenuClickResult; +use crate::context_menu::ContextMenuResult; /// A web view is an area to display web browsing context. It's what user will treat as a "web page". #[derive(Debug, Clone)] @@ -314,7 +314,7 @@ impl Window { if msg.starts_with("CONTEXT_MENU:") { let json_str_msg = msg.strip_prefix("CONTEXT_MENU:").unwrap(); let result = - serde_json::from_str::(json_str_msg).unwrap(); + serde_json::from_str::(json_str_msg).unwrap(); self.handle_context_menu_event(sender, result); } diff --git a/src/window.rs b/src/window.rs index 8eb900e..2b0c7ed 100644 --- a/src/window.rs +++ b/src/window.rs @@ -62,10 +62,10 @@ pub struct Window { current_history_index: usize, /// State to indicate if the window is resizing. pub(crate) resizing: bool, + // TODO: These two fields should unified once we figure out servo's menu events. /// Linux context_menu #[cfg(linux)] pub(crate) context_menu: Option, - /// Global menu event receiver for muda crate #[cfg(any(target_os = "macos", target_os = "windows"))] menu_event_receiver: MenuEventReceiver, @@ -290,38 +290,33 @@ impl Window { /* handle context menu */ // TODO(context-menu): should create on ShowContextMenu event - #[cfg(linux)] - { - match (state, button) { - (ElementState::Pressed, winit::event::MouseButton::Right) => { - if self.context_menu.is_none() { - self.context_menu = Some(self.show_context_menu(sender)); - return; - } - } - (ElementState::Released, winit::event::MouseButton::Right) => { - if self.context_menu.is_some() { - return; - } - } - _ => {} - } - // TODO(context-menu): ignore first release event after context menu open or close to prevent click on background element - } - - #[cfg(any(target_os = "macos", target_os = "windows"))] - if *button == winit::event::MouseButton::Right && *state == ElementState::Pressed { - { + match (state, button) { + #[cfg(any(target_os = "macos", target_os = "windows"))] + (ElementState::Pressed, winit::event::MouseButton::Right) => { self.show_context_menu(); // FIXME: there's chance to lose the event since the channel is async. if let Ok(event) = self.menu_event_receiver.try_recv() { self.handle_context_menu_event(sender, event); } } + #[cfg(linux)] + (ElementState::Pressed, winit::event::MouseButton::Right) => { + if self.context_menu.is_none() { + self.context_menu = Some(self.show_context_menu(sender)); + return; + } + } + #[cfg(linux)] + // TODO(context-menu): ignore first release event after context menu open or close to prevent click on background element + (ElementState::Released, winit::event::MouseButton::Right) => { + if self.context_menu.is_some() { + return; + } + } + _ => {} } /* handle Windows and Linux non-decoration window resize */ - #[cfg(any(linux, target_os = "windows"))] { if *state == ElementState::Pressed && *button == winit::event::MouseButton::Left @@ -603,7 +598,7 @@ impl Window { } } -// Dummy Context Menu +// Context Menu methods impl Window { #[cfg(any(target_os = "macos", target_os = "windows"))] pub(crate) fn show_context_menu(&self) { @@ -626,38 +621,6 @@ impl Window { context_menu.show(self.window.window_handle().unwrap()); } - #[cfg(any(target_os = "macos", target_os = "windows"))] - fn handle_context_menu_event(&self, sender: &Sender, event: MenuEvent) { - // TODO: should be more flexible to handle different menu items - match event.id().0.as_str() { - "back" => { - send_to_constellation( - sender, - ConstellationMsg::TraverseHistory( - self.webview.as_ref().unwrap().webview_id, - TraversalDirection::Back(1), - ), - ); - } - "forward" => { - send_to_constellation( - sender, - ConstellationMsg::TraverseHistory( - self.webview.as_ref().unwrap().webview_id, - TraversalDirection::Forward(1), - ), - ); - } - "reload" => { - send_to_constellation( - sender, - ConstellationMsg::Reload(self.webview.as_ref().unwrap().webview_id), - ); - } - _ => {} - } - } - #[cfg(linux)] pub(crate) fn show_context_menu(&mut self, sender: &Sender) -> ContextMenu { use crate::context_menu::MenuItem; @@ -673,7 +636,7 @@ impl Window { ); let reload = MenuItem::new(Some("reload"), "Reload", true); - let mut context_menu = ContextMenu::new_with_menu(Menu([back, forward, reload].to_vec())); + let mut context_menu = ContextMenu::new_with_menu(Menu(vec![back, forward, reload])); let position = self.mouse_position.get().unwrap(); context_menu.show(sender, self, position); @@ -692,6 +655,38 @@ impl Window { } } + #[cfg(any(target_os = "macos", target_os = "windows"))] + fn handle_context_menu_event(&self, sender: &Sender, event: MenuEvent) { + // TODO: should be more flexible to handle different menu items + match event.id().0.as_str() { + "back" => { + send_to_constellation( + sender, + ConstellationMsg::TraverseHistory( + self.webview.as_ref().unwrap().webview_id, + TraversalDirection::Back(1), + ), + ); + } + "forward" => { + send_to_constellation( + sender, + ConstellationMsg::TraverseHistory( + self.webview.as_ref().unwrap().webview_id, + TraversalDirection::Forward(1), + ), + ); + } + "reload" => { + send_to_constellation( + sender, + ConstellationMsg::Reload(self.webview.as_ref().unwrap().webview_id), + ); + } + _ => {} + } + } + /// Handle linux context menu event // TODO(context-menu): should make the call in synchronous way after calling show_context_menu, otherwise // we'll have to deal with constellation sender and other parameter's lifetime, also we lose the context that why this context menu popup @@ -699,13 +694,9 @@ impl Window { pub(crate) fn handle_context_menu_event( &mut self, sender: &Sender, - event: crate::context_menu::ContextMenuClickResult, + event: crate::context_menu::ContextMenuResult, ) { - // FIXME: (context-menu) find the reason that close after doing action (traverse history) will hang the window - // Close context menu somehow must put before other actions, or it will hang the window - if event.close { - self.close_context_menu(sender); - } + self.close_context_menu(sender); match event.id.as_str() { "back" => { send_to_constellation(