aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--components/embedder_traits/lib.rs10
-rw-r--r--ports/glutin/browser.rs5
-rw-r--r--ports/libsimpleservo/api/Cargo.toml1
-rw-r--r--ports/libsimpleservo/api/src/lib.rs30
-rw-r--r--ports/libsimpleservo/capi/src/lib.rs42
-rw-r--r--support/hololens/ServoApp/ServoControl/Servo.cpp11
-rw-r--r--support/hololens/ServoApp/ServoControl/Servo.h7
-rw-r--r--support/hololens/ServoApp/ServoControl/ServoControl.cpp32
-rw-r--r--support/hololens/ServoApp/ServoControl/ServoControl.h3
10 files changed, 132 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cf9f0fb33db..772adcc29ef 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5400,6 +5400,7 @@ dependencies = [
"core-foundation 0.6.4",
"getopts",
"gl_generator 0.11.0",
+ "ipc-channel",
"libc",
"libloading",
"libservo",
diff --git a/components/embedder_traits/lib.rs b/components/embedder_traits/lib.rs
index 45fa6e1d7b4..961cd5e53a4 100644
--- a/components/embedder_traits/lib.rs
+++ b/components/embedder_traits/lib.rs
@@ -107,6 +107,13 @@ impl EmbedderReceiver {
}
#[derive(Deserialize, Serialize)]
+pub enum ContextMenuResult {
+ Dismissed,
+ Ignored,
+ Selected(usize),
+}
+
+#[derive(Deserialize, Serialize)]
pub enum PromptDefinition {
/// Show a message.
Alert(String, IpcSender<()>),
@@ -149,6 +156,8 @@ pub enum EmbedderMsg {
ResizeTo(DeviceIntSize),
/// Show dialog to user
Prompt(PromptDefinition, PromptOrigin),
+ /// Show a context menu to the user
+ ShowContextMenu(IpcSender<ContextMenuResult>, Vec<String>),
/// Whether or not to allow a pipeline to load a url.
AllowNavigationRequest(PipelineId, ServoUrl),
/// Whether or not to allow script to open a new tab/browser
@@ -235,6 +244,7 @@ impl Debug for EmbedderMsg {
EmbedderMsg::ReportProfile(..) => write!(f, "ReportProfile"),
EmbedderMsg::MediaSessionEvent(..) => write!(f, "MediaSessionEvent"),
EmbedderMsg::OnDevtoolsStarted(..) => write!(f, "OnDevtoolsStarted"),
+ EmbedderMsg::ShowContextMenu(..) => write!(f, "ShowContextMenu"),
}
}
}
diff --git a/ports/glutin/browser.rs b/ports/glutin/browser.rs
index 3aec703c8fc..d92eb1bde9b 100644
--- a/ports/glutin/browser.rs
+++ b/ports/glutin/browser.rs
@@ -8,7 +8,7 @@ use euclid::{Point2D, Vector2D};
use keyboard_types::{Key, KeyboardEvent, Modifiers, ShortcutMatcher};
use servo::compositing::windowing::{WebRenderDebugOption, WindowEvent};
use servo::embedder_traits::{
- EmbedderMsg, FilterPattern, PermissionRequest, PromptDefinition, PromptOrigin, PromptResult,
+ ContextMenuResult, EmbedderMsg, FilterPattern, PermissionRequest, PromptDefinition, PromptOrigin, PromptResult,
PermissionPrompt,
};
use servo::msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
@@ -521,6 +521,9 @@ where
Err(()) => error!("Error running devtools server"),
}
},
+ EmbedderMsg::ShowContextMenu(sender, _) => {
+ let _ = sender.send(ContextMenuResult::Ignored);
+ }
}
}
}
diff --git a/ports/libsimpleservo/api/Cargo.toml b/ports/libsimpleservo/api/Cargo.toml
index 66a0cd83a3d..61dc1106de3 100644
--- a/ports/libsimpleservo/api/Cargo.toml
+++ b/ports/libsimpleservo/api/Cargo.toml
@@ -8,6 +8,7 @@ publish = false
[dependencies]
getopts = "0.2.11"
+ipc-channel = "0.14"
libservo = { path = "../../../components/servo" }
log = "0.4"
servo-media = { git = "https://github.com/servo/media" }
diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs
index 98a2029d402..c876ffb9fc0 100644
--- a/ports/libsimpleservo/api/src/lib.rs
+++ b/ports/libsimpleservo/api/src/lib.rs
@@ -8,11 +8,12 @@ extern crate log;
pub mod gl_glue;
pub use servo::embedder_traits::{
- MediaSessionPlaybackState, PermissionPrompt, PermissionRequest, PromptResult,
+ ContextMenuResult, MediaSessionPlaybackState, PermissionPrompt, PermissionRequest, PromptResult,
};
pub use servo::script_traits::{MediaSessionActionType, MouseButton};
use getopts::Options;
+use ipc_channel::ipc::IpcSender;
use servo::canvas::{SurfaceProviders, WebGlExecutor};
use servo::compositing::windowing::{
AnimationState, EmbedderCoordinates, EmbedderMethods, MouseWindowEvent, WindowEvent,
@@ -103,6 +104,8 @@ pub trait HostTrait {
fn prompt_ok_cancel(&self, msg: String, trusted: bool) -> PromptResult;
/// Ask for string
fn prompt_input(&self, msg: String, default: String, trusted: bool) -> Option<String>;
+ /// Show context menu
+ fn show_context_menu(&self, items: Vec<String>);
/// Page starts loading.
/// "Reload button" should be disabled.
/// "Stop button" should be enabled.
@@ -164,6 +167,7 @@ pub struct ServoGlue {
browsers: Vec<BrowserId>,
events: Vec<WindowEvent>,
current_url: Option<ServoUrl>,
+ context_menu_sender: Option<IpcSender<ContextMenuResult>>,
}
pub fn servo_version() -> String {
@@ -240,6 +244,7 @@ pub fn init(
browsers: vec![],
events: vec![],
current_url: Some(url.clone()),
+ context_menu_sender: None,
};
let browser_id = BrowserId::new();
let _ = servo_glue.process_event(WindowEvent::NewBrowser(url, browser_id));
@@ -503,6 +508,18 @@ impl ServoGlue {
}
}
+ pub fn on_context_menu_closed(
+ &mut self,
+ result: ContextMenuResult,
+ ) -> Result<(), &'static str> {
+ if let Some(sender) = self.context_menu_sender.take() {
+ let _ = sender.send(result);
+ } else {
+ warn!("Trying to close a context menu when no context menu is active");
+ }
+ Ok(())
+ }
+
fn process_event(&mut self, event: WindowEvent) -> Result<(), &'static str> {
self.events.push(event);
if !self.batch_mode {
@@ -562,6 +579,17 @@ impl ServoGlue {
EmbedderMsg::AllowUnload(sender) => {
let _ = sender.send(true);
},
+ EmbedderMsg::ShowContextMenu(sender, items) => {
+ if self.context_menu_sender.is_some() {
+ warn!(
+ "Trying to show a context menu when a context menu is already active"
+ );
+ let _ = sender.send(ContextMenuResult::Ignored);
+ } else {
+ self.context_menu_sender = Some(sender);
+ self.callbacks.host_callbacks.show_context_menu(items);
+ }
+ },
EmbedderMsg::Prompt(definition, origin) => {
let cb = &self.callbacks.host_callbacks;
let trusted = origin == PromptOrigin::Trusted;
diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs
index 2fd0e48fabe..d55d9f41175 100644
--- a/ports/libsimpleservo/capi/src/lib.rs
+++ b/ports/libsimpleservo/capi/src/lib.rs
@@ -17,7 +17,7 @@ use env_logger;
use log::LevelFilter;
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
use simpleservo::{
- Coordinates, EventLoopWaker, HostTrait, InitOptions, MediaSessionActionType,
+ ContextMenuResult, Coordinates, EventLoopWaker, HostTrait, InitOptions, MediaSessionActionType,
MediaSessionPlaybackState, MouseButton, PromptResult, VRInitOptions,
};
use std::ffi::{CStr, CString};
@@ -230,6 +230,7 @@ pub struct CHostCallbacks {
trusted: bool,
) -> *const c_char,
pub on_devtools_started: extern "C" fn(result: CDevtoolsServerState, port: c_uint),
+ pub show_context_menu: extern "C" fn(items_list: *const *const c_char, items_size: u32),
}
/// Servo options
@@ -332,6 +333,25 @@ impl CMediaSessionActionType {
}
}
+#[repr(C)]
+pub enum CContextMenuResult {
+ Ignored,
+ Selected,
+ // Can't use Dismissed. Already used by PromptResult. See:
+ // https://github.com/servo/servo/issues/25986
+ Dismissed_,
+}
+
+impl CContextMenuResult {
+ pub fn convert(&self, idx: u32) -> ContextMenuResult {
+ match self {
+ CContextMenuResult::Ignored => ContextMenuResult::Ignored,
+ CContextMenuResult::Dismissed_ => ContextMenuResult::Dismissed,
+ CContextMenuResult::Selected => ContextMenuResult::Selected(idx as usize),
+ }
+ }
+}
+
/// The returned string is not freed. This will leak.
#[no_mangle]
pub extern "C" fn servo_version() -> *const c_char {
@@ -495,6 +515,14 @@ pub extern "C" fn set_batch_mode(batch: bool) {
}
#[no_mangle]
+pub extern "C" fn on_context_menu_closed(result: CContextMenuResult, item: u32) {
+ catch_any_panic(|| {
+ debug!("on_context_menu_closed");
+ call(|s| s.on_context_menu_closed(result.convert(item)));
+ });
+}
+
+#[no_mangle]
pub extern "C" fn resize(width: i32, height: i32) {
catch_any_panic(|| {
debug!("resize {}/{}", width, height);
@@ -874,4 +902,16 @@ impl HostTrait for HostCallbacks {
},
}
}
+
+ fn show_context_menu(&self, items: Vec<String>) {
+ debug!("show_context_menu");
+ let size = items.len() as u32;
+ let cstrs: Vec<CString> = items
+ .into_iter()
+ .map(|i| CString::new(i).expect("Can't create string"))
+ .collect();
+ let ptrs: Vec<*const c_char> = cstrs.iter().map(|cstr| cstr.as_ptr()).collect();
+ (self.0.show_context_menu)(ptrs.as_ptr(), size);
+ // let _ = cstrs; // Don't drop these too early
+ }
}
diff --git a/support/hololens/ServoApp/ServoControl/Servo.cpp b/support/hololens/ServoApp/ServoControl/Servo.cpp
index 88c2376283b..96438300ac4 100644
--- a/support/hololens/ServoApp/ServoControl/Servo.cpp
+++ b/support/hololens/ServoApp/ServoControl/Servo.cpp
@@ -43,7 +43,7 @@ void on_ime_state_changed(bool aShow) {
sServo->Delegate().OnServoIMEStateChanged(aShow);
}
-void set_clipboard_contents(const char *content) {
+void set_clipboard_contents(const char *) {
// FIXME
}
@@ -67,6 +67,14 @@ void prompt_alert(const char *message, bool trusted) {
sServo->Delegate().OnServoPromptAlert(char2hstring(message), trusted);
}
+void show_context_menu(const char *const *items_list, uint32_t items_size) {
+ std::vector<winrt::hstring> items;
+ for (uint32_t i = 0; i < items_size; i++) {
+ items.push_back(char2hstring(items_list[i]));
+ }
+ sServo->Delegate().OnServoShowContextMenu(items);
+}
+
void on_devtools_started(Servo::DevtoolsServerState result,
const unsigned int port) {
sServo->Delegate().OnServoDevtoolsStarted(
@@ -150,6 +158,7 @@ Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
c.prompt_yes_no = &prompt_yes_no;
c.prompt_input = &prompt_input;
c.on_devtools_started = &on_devtools_started;
+ c.show_context_menu = &show_context_menu;
capi::register_panic_handler(&on_panic);
diff --git a/support/hololens/ServoApp/ServoControl/Servo.h b/support/hololens/ServoApp/ServoControl/Servo.h
index 1667118b499..2b396f6d09d 100644
--- a/support/hololens/ServoApp/ServoControl/Servo.h
+++ b/support/hololens/ServoApp/ServoControl/Servo.h
@@ -29,6 +29,7 @@ public:
typedef capi::CMouseButton MouseButton;
typedef capi::CPromptResult PromptResult;
+ typedef capi::CContextMenuResult ContextMenuResult;
typedef capi::CMediaSessionActionType MediaSessionActionType;
typedef capi::CMediaSessionPlaybackState MediaSessionPlaybackState;
typedef capi::CDevtoolsServerState DevtoolsServerState;
@@ -74,6 +75,9 @@ public:
void SendMediaSessionAction(capi::CMediaSessionActionType action) {
capi::media_session_action(action);
}
+ void ContextMenuClosed(capi::CContextMenuResult res, unsigned int idx) {
+ capi::on_context_menu_closed(res, idx);
+ }
private:
ServoDelegate &mDelegate;
@@ -95,12 +99,13 @@ public:
virtual bool OnServoAllowNavigation(hstring) = 0;
virtual void OnServoAnimatingChanged(bool) = 0;
virtual void OnServoIMEStateChanged(bool) = 0;
- virtual void OnServoDevtoolsStarted(bool, unsigned int) = 0;
+ virtual void OnServoDevtoolsStarted(bool, const unsigned int) = 0;
virtual void Flush() = 0;
virtual void MakeCurrent() = 0;
virtual void OnServoMediaSessionMetadata(hstring, hstring, hstring) = 0;
virtual void OnServoMediaSessionPlaybackStateChange(int) = 0;
virtual void OnServoPromptAlert(hstring, bool) = 0;
+ virtual void OnServoShowContextMenu(std::vector<hstring>) = 0;
virtual Servo::PromptResult OnServoPromptOkCancel(hstring, bool) = 0;
virtual Servo::PromptResult OnServoPromptYesNo(hstring, bool) = 0;
virtual std::optional<hstring> OnServoPromptInput(hstring, hstring, bool) = 0;
diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.cpp b/support/hololens/ServoApp/ServoControl/ServoControl.cpp
index cf3393f976e..810efed02e1 100644
--- a/support/hololens/ServoApp/ServoControl/ServoControl.cpp
+++ b/support/hololens/ServoApp/ServoControl/ServoControl.cpp
@@ -233,9 +233,9 @@ void ServoControl::OnSurfaceWheelChanged(
void ServoControl::OnSurfaceResized(IInspectable const &,
SizeChangedEventArgs const &e) {
auto size = e.NewSize();
- auto w = size.Width * mDPI;
- auto h = size.Height * mDPI;
- RunOnGLThread([=] { mServo->SetSize(w, h); });
+ auto w = (size.Width * mDPI);
+ auto h = (size.Height * mDPI);
+ RunOnGLThread([=] { mServo->SetSize((GLsizei)w, (GLsizei)h); });
}
void ServoControl::GoBack() {
@@ -435,7 +435,7 @@ void ServoControl::OnServoAnimatingChanged(bool animating) {
WakeConditionVariable(&mGLCondVar);
}
-void ServoControl::OnServoIMEStateChanged(bool aShow) {
+void ServoControl::OnServoIMEStateChanged(bool) {
// FIXME:
// https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-implementingtextandtextrange
}
@@ -564,6 +564,30 @@ void ServoControl::OnServoDevtoolsStarted(bool success,
});
}
+void ServoControl::OnServoShowContextMenu(std::vector<winrt::hstring> items) {
+ RunOnUIThread([=] {
+ MessageDialog msg{L"Menu"};
+ for (auto i = 0; i < items.size(); i++) {
+ UICommand cmd{items[i], [=](auto) {
+ RunOnGLThread([=] {
+ mServo->ContextMenuClosed(
+ Servo::ContextMenuResult::Selected, i);
+ });
+ }};
+ msg.Commands().Append(cmd);
+ }
+ UICommand cancel{L"Cancel", [=](auto) {
+ RunOnGLThread([=] {
+ mServo->ContextMenuClosed(
+ Servo::ContextMenuResult::Dismissed_, 0);
+ });
+ }};
+ msg.Commands().Append(cancel);
+ msg.CancelCommandIndex((uint32_t)items.size());
+ msg.ShowAsync();
+ });
+}
+
template <typename Callable> void ServoControl::RunOnUIThread(Callable cb) {
Dispatcher().RunAsync(CoreDispatcherPriority::High, cb);
}
diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.h b/support/hololens/ServoApp/ServoControl/ServoControl.h
index 685f038311b..889c3510bfb 100644
--- a/support/hololens/ServoApp/ServoControl/ServoControl.h
+++ b/support/hololens/ServoApp/ServoControl/ServoControl.h
@@ -117,12 +117,13 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
winrt::hstring);
virtual void OnServoMediaSessionPlaybackStateChange(int);
virtual void OnServoPromptAlert(winrt::hstring, bool);
+ virtual void OnServoShowContextMenu(std::vector<winrt::hstring>);
virtual servo::Servo::PromptResult OnServoPromptOkCancel(winrt::hstring,
bool);
virtual servo::Servo::PromptResult OnServoPromptYesNo(winrt::hstring, bool);
virtual std::optional<hstring> OnServoPromptInput(winrt::hstring,
winrt::hstring, bool);
- virtual void OnServoDevtoolsStarted(bool success, const unsigned int port);
+ virtual void OnServoDevtoolsStarted(bool, const unsigned int);
DevtoolsStatus GetDevtoolsStatus();