diff --git a/ports/libmlservo/src/lib.rs b/ports/libmlservo/src/lib.rs index 6b5bb2e6d00..78150ef1643 100644 --- a/ports/libmlservo/src/lib.rs +++ b/ports/libmlservo/src/lib.rs @@ -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,17 +182,84 @@ 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) { +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 (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 window_event = if trigger { - WindowEvent::MouseWindowEventClass(MouseWindowEvent::Click(MouseButton::Left, point)) - } else { - WindowEvent::MouseWindowMoveEventClass(point) + 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.servo.handle_events(vec![window_event]); + servo.scroll_state = new_state; + servo.servo.handle_events(window_events); } } @@ -234,6 +307,8 @@ pub struct ServoInstance { browser_id: BrowserId, history_update: MLHistoryUpdate, servo: Servo, + scroll_state: ScrollState, + scroll_scale: TypedScale, } 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); diff --git a/support/magicleap/Servo2D/code/inc/Servo2D.h b/support/magicleap/Servo2D/code/inc/Servo2D.h index 29477cf3cd8..559817ea280 100644 --- a/support/magicleap/Servo2D/code/inc/Servo2D.h +++ b/support/magicleap/Servo2D/code/inc/Servo2D.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -100,8 +101,8 @@ protected: */ 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. diff --git a/support/magicleap/Servo2D/code/src/Servo2D.cpp b/support/magicleap/Servo2D/code/src/Servo2D.cpp index d24316490b6..81babf942c5 100644 --- a/support/magicleap/Servo2D/code/src/Servo2D.cpp +++ b/support/magicleap/Servo2D/code/src/Servo2D.cpp @@ -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(event)); - case lumin::ServerEventType::kKeyInputEvent: - return keyEventListener(static_cast(event)); + case lumin::ServerEventType::kGestureInputEvent: + return gestureEventListener(static_cast(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; }