Skip to content

Commit

Permalink
Support scrolling in Magic Leap Servo
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Jeffrey committed Nov 1, 2018
1 parent 95bfaa0 commit 3970c4f
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 16 deletions.
94 changes: 88 additions & 6 deletions ports/libmlservo/src/lib.rs
Expand Up @@ -33,8 +33,12 @@ use servo::gl::Gl;
use servo::gl::GlesFns;
use servo::msg::constellation_msg::TraversalDirection;
use servo::script_traits::MouseButton;
use servo::script_traits::TouchEventType;
use servo::servo_url::ServoUrl;
use servo::webrender_api::DevicePixel;
use servo::webrender_api::DevicePoint;
use servo::webrender_api::LayoutPixel;
use servo::webrender_api::ScrollLocation;
use smallvec::SmallVec;
use std::ffi::CStr;
use std::ffi::CString;
Expand Down Expand Up @@ -113,6 +117,8 @@ pub unsafe extern "C" fn init_servo(ctxt: EGLContext,
app: app,
browser_id: browser_id,
history_update: history_update,
scroll_state: ScrollState::TriggerUp,
scroll_scale: TypedScale::new(SCROLL_SCALE / hidpi),
servo: servo,
});
Box::into_raw(result)
Expand Down Expand Up @@ -176,20 +182,87 @@ pub unsafe extern "C" fn heartbeat_servo(servo: *mut ServoInstance) {
}
}

// Some magic numbers.

// How far does the cursor have to move for it to count as a drag rather than a click?
// (In device pixels squared, to avoid taking a sqrt when calculating move distance.)
const DRAG_CUTOFF_SQUARED: f32 = 100.0;

// How much should we scale scrolling by?
const SCROLL_SCALE: f32 = 3.0;

#[no_mangle]
pub unsafe extern "C" fn cursor_servo(servo: *mut ServoInstance, x: f32, y: f32, trigger: bool) {
// Servo was triggered
pub unsafe extern "C" fn move_servo(servo: *mut ServoInstance, x: f32, y: f32) {
// Servo's cursor was moved
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)
let (new_state, window_event) = match servo.scroll_state {
ScrollState::TriggerUp => (
ScrollState::TriggerUp,
WindowEvent::MouseWindowMoveEventClass(point),
),
ScrollState::TriggerDown(start) if (start - point).square_length() < DRAG_CUTOFF_SQUARED => return,
ScrollState::TriggerDown(start) => (
ScrollState::TriggerDragging(start, point),
WindowEvent::Scroll(
ScrollLocation::Delta((point - start) * servo.scroll_scale),
start.to_i32(),
TouchEventType::Down
),
),
ScrollState::TriggerDragging(start, prev) => (
ScrollState::TriggerDragging(start, point),
WindowEvent::Scroll(
ScrollLocation::Delta((point - prev) * servo.scroll_scale),
start.to_i32(),
TouchEventType::Move
),
),
};
servo.scroll_state = new_state;
servo.servo.handle_events(vec![window_event]);
}
}

#[no_mangle]
pub unsafe extern "C" fn trigger_servo(servo: *mut ServoInstance, x: f32, y: f32, down: bool) {
// Servo was triggered
if let Some(servo) = servo.as_mut() {
let point = DevicePoint::new(x, y);
let (new_state, window_events) = match servo.scroll_state {
ScrollState::TriggerUp if down => (
ScrollState::TriggerDown(point),
vec![
WindowEvent::MouseWindowEventClass(MouseWindowEvent::MouseDown(MouseButton::Left, point)),
],
),
ScrollState::TriggerDown(start) if !down => (
ScrollState::TriggerUp,
vec![
WindowEvent::MouseWindowEventClass(MouseWindowEvent::MouseUp(MouseButton::Left, start)),
WindowEvent::MouseWindowEventClass(MouseWindowEvent::Click(MouseButton::Left, start)),
WindowEvent::MouseWindowMoveEventClass(point),
],
),
ScrollState::TriggerDragging(start, prev) if !down => (
ScrollState::TriggerUp,
vec![
WindowEvent::Scroll(
ScrollLocation::Delta((point - prev) * servo.scroll_scale),
start.to_i32(),
TouchEventType::Up
),
WindowEvent::MouseWindowEventClass(MouseWindowEvent::MouseUp(MouseButton::Left, point)),
WindowEvent::MouseWindowMoveEventClass(point),
],
),
_ => return,
};
servo.scroll_state = new_state;
servo.servo.handle_events(window_events);
}
}

#[no_mangle]
pub unsafe extern "C" fn traverse_servo(servo: *mut ServoInstance, delta: i32) {
// Traverse the session history
Expand Down Expand Up @@ -234,6 +307,8 @@ pub struct ServoInstance {
browser_id: BrowserId,
history_update: MLHistoryUpdate,
servo: Servo<WindowInstance>,
scroll_state: ScrollState,
scroll_scale: TypedScale<f32, DevicePixel, LayoutPixel>,
}

struct WindowInstance {
Expand All @@ -246,6 +321,13 @@ struct WindowInstance {
hidpi: f32,
}

#[derive(Clone, Copy)]
enum ScrollState {
TriggerUp,
TriggerDown(DevicePoint),
TriggerDragging(DevicePoint, DevicePoint),
}

impl WindowMethods for WindowInstance {
fn present(&self) {
SwapBuffers(self.disp, self.surf);
Expand Down
3 changes: 2 additions & 1 deletion support/magicleap/Servo2D/code/inc/Servo2D.h
Expand Up @@ -5,6 +5,7 @@
#include <lumin/LandscapeApp.h>
#include <lumin/Prism.h>
#include <lumin/event/ServerEvent.h>
#include <lumin/event/GestureInputEventData.h>
#include <lumin/event/KeyInputEventData.h>
#include <lumin/event/ControlTouchPadInputEventData.h>
#include <lumin/node/QuadNode.h>
Expand Down Expand Up @@ -100,8 +101,8 @@ class Servo2D : public lumin::LandscapeApp {
*/
virtual bool eventListener(lumin::ServerEvent* event) override;
bool touchpadEventListener(lumin::ControlTouchPadInputEventData* event);
bool keyEventListener(lumin::KeyInputEventData* event);
void urlBarEventListener();
bool gestureEventListener(lumin::GestureInputEventData* event);

/**
* Get the current cursor position, with respect to the viewport.
Expand Down
20 changes: 11 additions & 9 deletions support/magicleap/Servo2D/code/src/Servo2D.cpp
Expand Up @@ -45,7 +45,8 @@ extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay,
Servo2D*, MLLogger, MLHistoryUpdate,
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 trigger_servo(ServoInstance*, float x, float y, bool down);
extern "C" void move_servo(ServoInstance*, float x, float y);
extern "C" void traverse_servo(ServoInstance*, int delta);
extern "C" void navigate_servo(ServoInstance*, const char* text);
extern "C" void discard_servo(ServoInstance*);
Expand Down Expand Up @@ -220,8 +221,8 @@ bool Servo2D::eventListener(lumin::ServerEvent* event) {
switch (event->getServerEventType()) {
case lumin::ServerEventType::kControlTouchPadInputEvent:
return touchpadEventListener(static_cast<lumin::ControlTouchPadInputEventData*>(event));
case lumin::ServerEventType::kKeyInputEvent:
return keyEventListener(static_cast<lumin::KeyInputEventData*>(event));
case lumin::ServerEventType::kGestureInputEvent:
return gestureEventListener(static_cast<lumin::GestureInputEventData*>(event));
default:
return false;
}
Expand Down Expand Up @@ -257,14 +258,15 @@ bool Servo2D::touchpadEventListener(lumin::ControlTouchPadInputEventData* event)
return false;
}

// Inform Servo of the trigger
cursor_servo(servo_, pos.x, pos.y, false);
// Inform Servo of the move
move_servo(servo_, pos.x, pos.y);
return true;
}

bool Servo2D::keyEventListener(lumin::KeyInputEventData* event) {
// Only respond to trigger keys
if (event->keyCode() != lumin::input::KeyCodes::AKEYCODE_EX_TRIGGER) {
bool Servo2D::gestureEventListener(lumin::GestureInputEventData* event) {
// Only respond to trigger up or down
lumin::input::GestureType typ = event->getGesture();
if (typ != lumin::input::GestureType::TriggerDown && typ != lumin::input::GestureType::TriggerUp) {
return false;
}

Expand All @@ -280,7 +282,7 @@ bool Servo2D::keyEventListener(lumin::KeyInputEventData* event) {
}

// Inform Servo of the trigger
cursor_servo(servo_, pos.x, pos.y, true);
trigger_servo(servo_, pos.x, pos.y, typ == lumin::input::GestureType::TriggerDown);
return true;
}

Expand Down

0 comments on commit 3970c4f

Please sign in to comment.