Skip to content

Commit

Permalink
organize code
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Tsai committed Nov 14, 2024
1 parent 80961bc commit 0c63a6d
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 110 deletions.
4 changes: 3 additions & 1 deletion resources/context_menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
justify-content: start;
}
.menu-item {
cursor: pointer;
display: inline-block;
height: 30px;
width: 100%;
Expand All @@ -27,6 +28,7 @@
border-radius: 5px;
}
.menu-item.disabled {
cursor: default;
background: #dfdfdf;
color: #505050;
cursor: pointer;
Expand Down Expand Up @@ -61,7 +63,7 @@
} else {
menuItem.onclick = (ev) => {
// accept left click only
if (ev.buttons != 1) {
if (ev.buttons !== 1) {
return;
}
const msg = JSON.stringify({
Expand Down
87 changes: 52 additions & 35 deletions src/context_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@ use raw_window_handle::{HasWindowHandle, RawWindowHandle};

/* Wayland Implementation */
#[cfg(linux)]
use crate::webview::WebView;
use crate::{verso::send_to_constellation, webview::WebView, window::Window};
#[cfg(linux)]
use compositing_traits::ConstellationMsg;
#[cfg(linux)]
use crossbeam_channel::Sender;
#[cfg(linux)]
use serde::{Deserialize, Serialize};
#[cfg(linux)]
use webrender_api::units::DeviceIntPoint;
use servo_url::ServoUrl;
#[cfg(linux)]
use webrender_api::units::DeviceIntRect;
#[cfg(linux)]
use winit::dpi::PhysicalPosition;

/// Context Menu
#[cfg(any(target_os = "macos", target_os = "windows"))]
Expand Down Expand Up @@ -65,7 +71,7 @@ impl ContextMenu {
pub struct ContextMenu {
menu_items: Vec<MenuItem>,
/// The webview that the context menu is attached to
pub webview: Option<WebView>,
webview: WebView,
}

#[cfg(linux)]
Expand All @@ -74,19 +80,48 @@ impl ContextMenu {
///
/// Often used by calling window.alert() or window.confirm() in the web page.
pub fn new_with_menu(menu_items: Vec<MenuItem>) -> Self {
let webview_id = WebViewId::new();
let webview = WebView::new(webview_id, DeviceIntRect::zero());

Self {
menu_items,
webview: None,
webview,
}
}
/// Set the context menu's options
pub fn set_menu_items(&mut self, menu_items: Vec<MenuItem>) {
self.menu_items = menu_items;

/// Show the context menu to current cursor position
pub fn show(
&mut self,
sender: &Sender<ConstellationMsg>,
window: &mut Window,
position: PhysicalPosition<f64>,
) {
let scale_factor = window.scale_factor();
self.set_position(position, scale_factor);

send_to_constellation(
sender,
ConstellationMsg::NewWebView(self.resource_url(), self.webview.webview_id),
);
window.append_dialog_webview(self.webview.clone());
}

/// Get webview of the context menu
pub fn webview(&self) -> &WebView {
&self.webview
}

/// Get resource URL of the context menu
fn resource_url(&self) -> ServoUrl {
let items_json: String = self.to_items_json();
let url_str = format!("verso://context_menu.html?items={}", items_json);
ServoUrl::parse(&url_str).unwrap()
}
/// Show the context menu on position
pub fn create_webview(&mut self, position: DeviceIntPoint, scale_factor: f64) -> WebView {

/// Set the position of the context menu
fn set_position(&mut self, position: PhysicalPosition<f64>, scale_factor: f64) {
// Translate position to origin
let origin = Point2D::new(position.x, position.y);
let origin = Point2D::new(position.x as i32, position.y as i32);

// Calculate menu size
// Each menu item is 30px height
Expand All @@ -96,17 +131,11 @@ impl ContextMenu {
let size = Size2D::new(menu_width as i32, menu_height as i32);
let rect = DeviceIntRect::from_origin_and_size(origin, size);

let webview_id = WebViewId::new();
let webview = WebView::new(webview_id, rect);
// let url = ServoUrl::parse("https://example.com").unwrap();

self.webview = Some(webview.clone());

webview
self.webview.set_size(rect);
}

/// get item json
pub fn to_items_json(&self) -> String {
fn to_items_json(&self) -> String {
serde_json::to_string(&self.menu_items).unwrap()
}
}
Expand All @@ -115,8 +144,10 @@ impl ContextMenu {
#[derive(Debug, Clone, Serialize)]
pub struct MenuItem {
id: String,
label: String,
enabled: bool,
/// label of the menu item
pub label: String,
/// Whether the menu item is enabled
pub enabled: bool,
}

impl MenuItem {
Expand All @@ -133,27 +164,13 @@ impl MenuItem {
pub fn id(&self) -> &str {
&self.id
}
/// Get the label of the menu item
pub fn label(&self) -> &str {
&self.label
}
/// Set the label of the menu item
pub fn set_label(&mut self, label: &str) -> &Self {
self.label = label.to_string();
self
}
/// Enable or disable menu item
pub fn set_enabled(&mut self, enabled: bool) -> &Self {
self.enabled = enabled;
self
}
}

/// Context Menu Click Result
#[cfg(linux)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContextMenuClickResult {
/// The id of the menu item
/// The id of the menu ite /// Get the label of the menu item
pub id: String,
/// Close the context menu
pub close: bool,
Expand Down
132 changes: 58 additions & 74 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,7 @@ impl Window {
// Close old context menu
self.close_context_menu(sender);
// Create new context menu
self.context_menu = Some(self.create_context_menu());
self.show_context_menu(sender);
self.context_menu = Some(self.show_context_menu(sender));
return;
}
_ => {}
Expand Down Expand Up @@ -447,19 +446,6 @@ impl Window {
}
}

/// Close the context menu
///
/// If context menu exists, return true.
pub(crate) fn close_context_menu(&mut self, sender: &Sender<ConstellationMsg>) -> bool {
if let Some(context_menu) = self.context_menu.take() {
if let Some(webview) = context_menu.webview {
send_to_constellation(sender, ConstellationMsg::CloseWebView(webview.webview_id));
return true;
}
}
false
}

/// Handle servo messages. Return true if it requests a new window
pub fn handle_servo_message(
&mut self,
Expand All @@ -478,13 +464,11 @@ impl Window {
}
}
if let Some(context_menu) = &self.context_menu {
if let Some(webview) = &context_menu.webview {
if webview.webview_id == webview_id {
self.handle_servo_messages_with_context_menu(
webview_id, message, sender, clipboard, compositor,
);
return false;
}
if context_menu.webview().webview_id == webview_id {
self.handle_servo_messages_with_context_menu(
webview_id, message, sender, clipboard, compositor,
);
return false;
}
}
// Handle message in Verso WebView
Expand Down Expand Up @@ -514,8 +498,8 @@ impl Window {
}

/// Append a dialog webview to the window.
pub fn append_dialog_webview(&mut self, webview: &WebView) {
self.dialog_webviews.push(webview.clone());
pub fn append_dialog_webview(&mut self, webview: WebView) {
self.dialog_webviews.push(webview);
}

/// Remove a dialog webview from the window.
Expand Down Expand Up @@ -660,9 +644,42 @@ 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 create_context_menu(&mut self) -> ContextMenu {
pub(crate) fn show_context_menu(&mut self, sender: &Sender<ConstellationMsg>) -> ContextMenu {
use crate::context_menu::MenuItem;

let history_len = self.history.len();

// items
Expand All @@ -674,27 +691,27 @@ impl Window {
);
let reload = MenuItem::new(Some("reload"), "Reload", true);

ContextMenu::new_with_menu([back, forward, reload].to_vec())
let mut context_menu = ContextMenu::new_with_menu([back, forward, reload].to_vec());

let position = self.mouse_position.get().unwrap();
context_menu.show(sender, self, position);

context_menu
}

/// Close the context menu
///
/// If context menu exists, return true.
#[cfg(linux)]
pub(crate) fn show_context_menu(&mut self, sender: &Sender<ConstellationMsg>) {
let scale_factor = self.scale_factor();

if let Some(ref mut context_menu) = self.context_menu {
let mouse_position = self.mouse_position.get().unwrap();
let position = Point2D::new(mouse_position.x as i32, mouse_position.y as i32);
let items_json = context_menu.to_items_json();
let url_str = format!("verso://context_menu.html?items={}", items_json);
let url = ServoUrl::parse(&url_str).unwrap();
let menu_webview = context_menu.create_webview(position, scale_factor);
pub(crate) fn close_context_menu(&mut self, sender: &Sender<ConstellationMsg>) -> bool {
if let Some(context_menu) = self.context_menu.take() {
send_to_constellation(
sender,
ConstellationMsg::NewWebView(url, menu_webview.webview_id),
ConstellationMsg::CloseWebView(context_menu.webview().webview_id),
);

self.append_dialog_webview(&menu_webview);
return true;
}
false
}

#[cfg(linux)]
Expand All @@ -711,9 +728,8 @@ impl Window {
return self
.context_menu
.as_ref()
.and_then(|context_menu| context_menu.webview.as_ref())
.and_then(|webview| {
if webview.webview_id == webview_id {
.and_then(|context_menu| {
if context_menu.webview().webview_id == webview_id {
return Some(true);
}
None
Expand Down Expand Up @@ -766,38 +782,6 @@ 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),
);
}
_ => {}
}
}
}

// Non-decorated window resizing for Windows and Linux.
Expand Down

0 comments on commit 0c63a6d

Please sign in to comment.