Skip to content

Commit

Permalink
Rearrange platform code blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Wu Yuwei authored and Wu Yuwei committed Nov 22, 2024
1 parent 8d8f29a commit ea322a3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 86 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
41 changes: 22 additions & 19 deletions src/context_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<MenuItem>);

/// 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<MenuItem>,
/// 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"))]
{
Expand All @@ -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
Expand Down Expand Up @@ -93,15 +105,6 @@ impl ContextMenu {
}
}

/// Context Menu
#[cfg(linux)]
#[derive(Debug, Clone)]
pub struct ContextMenu {
menu_items: Vec<MenuItem>,
/// The webview that the context menu is attached to
webview: WebView,
}

#[cfg(linux)]
impl ContextMenu {
/// Show the context menu to current cursor position
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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::<ContextMenuClickResult>(json_str_msg).unwrap();
serde_json::from_str::<ContextMenuResult>(json_str_msg).unwrap();

self.handle_context_menu_event(sender, result);
}
Expand Down
119 changes: 55 additions & 64 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ContextMenu>,

/// Global menu event receiver for muda crate
#[cfg(any(target_os = "macos", target_os = "windows"))]
menu_event_receiver: MenuEventReceiver,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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<ConstellationMsg>, 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<ConstellationMsg>) -> ContextMenu {
use crate::context_menu::MenuItem;
Expand All @@ -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);
Expand All @@ -692,20 +655,48 @@ impl Window {
}
}

#[cfg(any(target_os = "macos", target_os = "windows"))]
fn handle_context_menu_event(&self, sender: &Sender<ConstellationMsg>, 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
#[cfg(linux)]
pub(crate) fn handle_context_menu_event(
&mut self,
sender: &Sender<ConstellationMsg>,
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(
Expand Down

0 comments on commit ea322a3

Please sign in to comment.