Skip to content

Commit

Permalink
Hook up the back and forward buttons to history traversal in Magic Le…
Browse files Browse the repository at this point in the history
…ap Servo2D
  • Loading branch information
Alan Jeffrey committed Oct 30, 2018
1 parent 4ead817 commit c8fa64b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 25 deletions.
58 changes: 39 additions & 19 deletions ports/libmlservo/src/lib.rs
Expand Up @@ -24,29 +24,25 @@ 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;
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,
Expand All @@ -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()));
Expand All @@ -93,25 +89,29 @@ 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);
servo.handle_events(vec![
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<WindowInstance>).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
Expand Down Expand Up @@ -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<WindowInstance>).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<WindowInstance>);
Box::from_raw(servo);
}
}

pub struct ServoInstance {
browser_id: BrowserId,
servo: Servo<WindowInstance>,
}

struct WindowInstance {
ctxt: EGLContext,
surf: EGLSurface,
Expand All @@ -192,7 +212,7 @@ impl WindowMethods for WindowInstance {
SwapBuffers(self.disp, self.surf);
}

fn prepare_for_composite(&self, _w: Length<u32, DevicePixel>, _h: Length<u32, DevicePixel>) -> 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
Expand Down
4 changes: 2 additions & 2 deletions support/magicleap/Servo2D/code/inc/Servo2D.h
Expand Up @@ -11,7 +11,7 @@
#include <lumin/resource/PlanarResource.h>
#include <SceneDescriptor.h>

typedef void* ServoInstance;
typedef struct Opaque ServoInstance;

/**
* Servo2D Landscape Application
Expand Down Expand Up @@ -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
};
30 changes: 26 additions & 4 deletions support/magicleap/Servo2D/code/src/Servo2D.cpp
Expand Up @@ -6,6 +6,7 @@
#include <lumin/node/RootNode.h>
#include <lumin/node/QuadNode.h>
#include <lumin/ui/Cursor.h>
#include <lumin/ui/node/UiButton.h>
#include <ml_logging.h>
#include <scenesGen.h>
#include <SceneDescriptor.h>
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit c8fa64b

Please sign in to comment.