Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support scrolling in Magic Leap Servo #22076

Merged
merged 1 commit into from Nov 1, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Support scrolling in Magic Leap Servo

  • Loading branch information
asajeffrey committed Nov 1, 2018
commit 3970c4ffbe2d0101041d3f8b377b4b02b6276188
@@ -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;
@@ -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)
@@ -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
@@ -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 {
@@ -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);
@@ -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>
@@ -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.
@@ -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*);
@@ -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;
}
@@ -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;
}

@@ -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;
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.