From c8fa64b93a7596c9a1c57fec2655c8e938921052 Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Tue, 30 Oct 2018 12:05:19 -0500 Subject: [PATCH] Hook up the back and forward buttons to history traversal in Magic Leap Servo2D --- ports/libmlservo/src/lib.rs | 58 +++++++++++++------ support/magicleap/Servo2D/code/inc/Servo2D.h | 4 +- .../magicleap/Servo2D/code/src/Servo2D.cpp | 30 ++++++++-- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/ports/libmlservo/src/lib.rs b/ports/libmlservo/src/lib.rs index 8b59f64300d5..08b84ada37ff 100644 --- a/ports/libmlservo/src/lib.rs +++ b/ports/libmlservo/src/lib.rs @@ -24,7 +24,6 @@ use servo::embedder_traits::EmbedderMsg; use servo::embedder_traits::EventLoopWaker; use servo::embedder_traits::resources::Resource; use servo::embedder_traits::resources::ResourceReaderMethods; -use servo::euclid::Length; use servo::euclid::TypedPoint2D; use servo::euclid::TypedRect; use servo::euclid::TypedScale; @@ -32,21 +31,18 @@ use servo::euclid::TypedSize2D; use servo::gl; use servo::gl::Gl; use servo::gl::GlesFns; +use servo::msg::constellation_msg::TraversalDirection; use servo::script_traits::MouseButton; use servo::servo_url::ServoUrl; -use servo::style_traits::DevicePixel; use servo::webrender_api::DevicePoint; use smallvec::SmallVec; use std::ffi::CStr; use std::ffi::CString; use std::io::Write; use std::os::raw::c_char; -use std::os::raw::c_void; use std::path::PathBuf; use std::rc::Rc; -type ServoInstance = *mut c_void; - #[repr(u32)] pub enum MLLogLevel { Fatal = 0, @@ -70,7 +66,7 @@ pub unsafe extern "C" fn init_servo(ctxt: EGLContext, url: *const c_char, width: u32, height: u32, - hidpi: f32) -> ServoInstance + hidpi: f32) -> *mut ServoInstance { // Servo initialization goes here! servo::embedder_traits::resources::set(Box::new(ResourceReaderInstance::new())); @@ -93,9 +89,9 @@ pub unsafe extern "C" fn init_servo(ctxt: EGLContext, }); info!("Starting servo"); - let mut servo = Box::new(Servo::new(window)); - + let mut servo = Servo::new(window); let browser_id = BrowserId::new(); + let blank_url = ServoUrl::parse("about:blank").expect("Failed to parse about:blank!"); let url = CStr::from_ptr(url).to_str().unwrap_or("about:blank"); let url = ServoUrl::parse(url).unwrap_or(blank_url); @@ -103,15 +99,19 @@ pub unsafe extern "C" fn init_servo(ctxt: EGLContext, WindowEvent::NewBrowser(url, browser_id), ]); - Box::into_raw(servo) as ServoInstance + let result = Box::new(ServoInstance { + browser_id: browser_id, + servo: servo, + }); + Box::into_raw(result) } #[no_mangle] -pub unsafe extern "C" fn heartbeat_servo(servo: ServoInstance) { +pub unsafe extern "C" fn heartbeat_servo(servo: *mut ServoInstance) { // Servo heartbeat goes here! - if let Some(servo) = (servo as *mut Servo).as_mut() { - servo.handle_events(vec![]); - for ((_browser_id, event)) in servo.get_events() { + if let Some(servo) = servo.as_mut() { + servo.servo.handle_events(vec![]); + for ((_browser_id, event)) in servo.servo.get_events() { match event { // Respond to any messages with a response channel // to avoid deadlocking the constellation @@ -156,27 +156,47 @@ pub unsafe extern "C" fn heartbeat_servo(servo: ServoInstance) { } #[no_mangle] -pub unsafe extern "C" fn cursor_servo(servo: ServoInstance, x: f32, y: f32, trigger: bool) { +pub unsafe extern "C" fn cursor_servo(servo: *mut ServoInstance, x: f32, y: f32, trigger: bool) { // Servo was triggered - if let Some(servo) = (servo as *mut Servo).as_mut() { + if let Some(servo) = servo.as_mut() { let point = DevicePoint::new(x, y); let window_event = if trigger { WindowEvent::MouseWindowEventClass(MouseWindowEvent::Click(MouseButton::Left, point)) } else { WindowEvent::MouseWindowMoveEventClass(point) }; - servo.handle_events(vec![window_event]); + servo.servo.handle_events(vec![window_event]); + } +} + +#[no_mangle] +pub unsafe extern "C" fn traverse_servo(servo: *mut ServoInstance, delta: i32) { + // Traverse the session history + if let Some(servo) = servo.as_mut() { + let window_event = if delta == 0 { + WindowEvent::Reload(servo.browser_id) + } else if delta < 0 { + WindowEvent::Navigation(servo.browser_id, TraversalDirection::Back(-delta as usize)) + } else { + WindowEvent::Navigation(servo.browser_id, TraversalDirection::Forward(delta as usize)) + }; + servo.servo.handle_events(vec![window_event]); } } #[no_mangle] -pub unsafe extern "C" fn discard_servo(servo: ServoInstance) { +pub unsafe extern "C" fn discard_servo(servo: *mut ServoInstance) { // Servo drop goes here! if !servo.is_null() { - Box::from_raw(servo as *mut Servo); + Box::from_raw(servo); } } +pub struct ServoInstance { + browser_id: BrowserId, + servo: Servo, +} + struct WindowInstance { ctxt: EGLContext, surf: EGLSurface, @@ -192,7 +212,7 @@ impl WindowMethods for WindowInstance { SwapBuffers(self.disp, self.surf); } - fn prepare_for_composite(&self, _w: Length, _h: Length) -> bool { + fn prepare_for_composite(&self) -> bool { MakeCurrent(self.disp, self.surf, self.surf, self.ctxt); self.gl.viewport(0, 0, self.width as i32, self.height as i32); true diff --git a/support/magicleap/Servo2D/code/inc/Servo2D.h b/support/magicleap/Servo2D/code/inc/Servo2D.h index 2f76c306e7ce..490c6d60ece7 100644 --- a/support/magicleap/Servo2D/code/inc/Servo2D.h +++ b/support/magicleap/Servo2D/code/inc/Servo2D.h @@ -11,7 +11,7 @@ #include #include -typedef void* ServoInstance; +typedef struct Opaque ServoInstance; /** * Servo2D Landscape Application @@ -104,5 +104,5 @@ class Servo2D : public lumin::LandscapeApp { lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders. lumin::PlanarResource* plane_ = nullptr; // the plane we're rendering into lumin::QuadNode* content_node_ = nullptr; // the node containing the plane - ServoInstance servo_ = nullptr; // the servo instance we're embedding + ServoInstance* servo_ = nullptr; // the servo instance we're embedding }; diff --git a/support/magicleap/Servo2D/code/src/Servo2D.cpp b/support/magicleap/Servo2D/code/src/Servo2D.cpp index 9b830ac6ca0b..54600362d09e 100644 --- a/support/magicleap/Servo2D/code/src/Servo2D.cpp +++ b/support/magicleap/Servo2D/code/src/Servo2D.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -36,11 +37,12 @@ void logger(MLLogLevel lvl, char* msg) { // The functions Servo provides for hooking up to the ML. // For the moment, this doesn't handle input events. -extern "C" ServoInstance init_servo(EGLContext, EGLSurface, EGLDisplay, MLLogger, +extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay, MLLogger, const char* url, int width, int height, float hidpi); -extern "C" void heartbeat_servo(ServoInstance); -extern "C" void cursor_servo(ServoInstance, float x, float y, bool triggered); -extern "C" void discard_servo(ServoInstance); +extern "C" void heartbeat_servo(ServoInstance*); +extern "C" void cursor_servo(ServoInstance*, float x, float y, bool triggered); +extern "C" void traverse_servo(ServoInstance*, int delta); +extern "C" void discard_servo(ServoInstance*); // Create a Servo2D instance Servo2D::Servo2D() { @@ -125,6 +127,26 @@ int Servo2D::init() { return 1; } + // Add a callback to the back button + std::string back_button_id = Servo2D_exportedNodes::backButton; + lumin::ui::UiButton* back_button = lumin::ui::UiButton::CastFrom(prism_->findNode(back_button_id, root_node)); + if (!back_button) { + ML_LOG(Error, "Servo2D Failed to get back button"); + abort(); + return 1; + } + back_button->onActivateSub(std::bind(traverse_servo, servo_, -1)); + + // Add a callback to the forward button + std::string fwd_button_id = Servo2D_exportedNodes::fwdButton; + lumin::ui::UiButton* fwd_button = lumin::ui::UiButton::CastFrom(prism_->findNode(fwd_button_id, root_node)); + if (!fwd_button) { + ML_LOG(Error, "Servo2D Failed to get forward button"); + abort(); + return 1; + } + fwd_button->onActivateSub(std::bind(traverse_servo, servo_, +1)); + return 0; }