mirror of
https://github.com/servo/servo.git
synced 2025-06-08 00:23:30 +00:00
Dispatch touch events and perform default touch actions.
This is currently limited to simple single-touch actions. It does not include momentum scrolling or pinch zooming.
This commit is contained in:
parent
4ed15a8853
commit
fe7460f34d
9 changed files with 276 additions and 15 deletions
|
@ -26,7 +26,7 @@ use layers::rendergl;
|
|||
use layers::rendergl::RenderContext;
|
||||
use layers::scene::Scene;
|
||||
use layout_traits::LayoutControlChan;
|
||||
use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind};
|
||||
use msg::compositor_msg::{Epoch, EventResult, FrameTreeId, LayerId, LayerKind};
|
||||
use msg::compositor_msg::{LayerProperties, ScrollPolicy};
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use msg::constellation_msg::{AnimationState, Image, PixelFormat};
|
||||
|
@ -35,7 +35,8 @@ use msg::constellation_msg::{NavigationDirection, PipelineId, WindowSizeData};
|
|||
use pipeline::CompositionPipeline;
|
||||
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
|
||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg};
|
||||
use script_traits::CompositorEvent::{TouchDownEvent, TouchMoveEvent, TouchUpEvent};
|
||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg, MouseButton};
|
||||
use scrolling::ScrollingTimerProxy;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
@ -59,6 +60,9 @@ const BUFFER_MAP_SIZE: usize = 10000000;
|
|||
const MAX_ZOOM: f32 = 8.0;
|
||||
const MIN_ZOOM: f32 = 0.1;
|
||||
|
||||
/// Minimum number of ScreenPx to begin touch scrolling.
|
||||
const TOUCH_PAN_MIN_SCREEN_PX: f32 = 20.0;
|
||||
|
||||
/// Holds the state when running reftests that determines when it is
|
||||
/// safe to save the output image.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
@ -68,6 +72,23 @@ enum ReadyState {
|
|||
ReadyToSaveImage,
|
||||
}
|
||||
|
||||
/// The states of the touch input state machine.
|
||||
///
|
||||
/// TODO: Currently Add support for "flinging" (scrolling inertia), pinch zooming, better
|
||||
/// support for multiple touch points.
|
||||
enum TouchState {
|
||||
/// Not tracking any touch point
|
||||
Nothing,
|
||||
/// A touchstart event was dispatched to the page, but the response wasn't received yet.
|
||||
WaitingForScript,
|
||||
/// Script is consuming the current touch point; don't perform default actions.
|
||||
DefaultPrevented,
|
||||
/// A single touch point is active and may perform click or pan default actions.
|
||||
Touching,
|
||||
/// A single touch point is active and has started panning.
|
||||
Panning,
|
||||
}
|
||||
|
||||
/// NB: Never block on the constellation, because sometimes the constellation blocks on us.
|
||||
pub struct IOCompositor<Window: WindowMethods> {
|
||||
/// The application window.
|
||||
|
@ -156,6 +177,15 @@ pub struct IOCompositor<Window: WindowMethods> {
|
|||
/// Pending scroll to fragment event, if any
|
||||
fragment_point: Option<Point2D<f32>>,
|
||||
|
||||
/// Touch input state machine
|
||||
touch_gesture_state: TouchState,
|
||||
|
||||
/// When tracking a touch for gesture detection, the point where it started
|
||||
first_touch_point: Option<TypedPoint2D<DevicePixel, f32>>,
|
||||
|
||||
/// When tracking a touch for gesture detection, its most recent point
|
||||
last_touch_point: Option<TypedPoint2D<DevicePixel, f32>>,
|
||||
|
||||
/// Pending scroll events.
|
||||
pending_scroll_events: Vec<ScrollEvent>,
|
||||
|
||||
|
@ -295,6 +325,9 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
channel_to_self: state.sender.clone_compositor_proxy(),
|
||||
scrolling_timer: ScrollingTimerProxy::new(state.sender),
|
||||
composition_request: CompositionRequest::NoCompositingNecessary,
|
||||
touch_gesture_state: TouchState::Nothing,
|
||||
first_touch_point: None,
|
||||
last_touch_point: None,
|
||||
pending_scroll_events: Vec::new(),
|
||||
composite_target: composite_target,
|
||||
shutdown_state: ShutdownState::NotShuttingDown,
|
||||
|
@ -502,6 +535,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
(Msg::TouchEventProcessed(result), ShutdownState::NotShuttingDown) => {
|
||||
match self.touch_gesture_state {
|
||||
TouchState::WaitingForScript => {
|
||||
self.touch_gesture_state = match result {
|
||||
EventResult::DefaultAllowed => TouchState::Touching,
|
||||
EventResult::DefaultPrevented => TouchState::DefaultPrevented,
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
(Msg::SetCursor(cursor), ShutdownState::NotShuttingDown) => {
|
||||
self.window.set_cursor(cursor)
|
||||
}
|
||||
|
@ -1097,6 +1142,109 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
fn on_touch_down(&mut self, identifier: i32, point: TypedPoint2D<DevicePixel, f32>) {
|
||||
match self.touch_gesture_state {
|
||||
TouchState::Nothing => {
|
||||
// TODO: Don't wait for script if we know the page has no touch event listeners.
|
||||
self.first_touch_point = Some(point);
|
||||
self.last_touch_point = Some(point);
|
||||
self.touch_gesture_state = TouchState::WaitingForScript;
|
||||
}
|
||||
TouchState::WaitingForScript => {
|
||||
// TODO: Queue events while waiting for script?
|
||||
}
|
||||
TouchState::DefaultPrevented => {}
|
||||
TouchState::Touching => {}
|
||||
TouchState::Panning => {}
|
||||
}
|
||||
if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
|
||||
result.layer.send_event(self, TouchDownEvent(identifier, result.point.to_untyped()));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_touch_move(&mut self, identifier: i32, point: TypedPoint2D<DevicePixel, f32>) {
|
||||
match self.touch_gesture_state {
|
||||
TouchState::Nothing => warn!("Got unexpected touch move event"),
|
||||
|
||||
TouchState::WaitingForScript => {
|
||||
// TODO: Queue events while waiting for script?
|
||||
}
|
||||
TouchState::Touching => {
|
||||
match self.first_touch_point {
|
||||
Some(p0) => {
|
||||
let delta = point - p0;
|
||||
let px: TypedPoint2D<ScreenPx, _> = delta / self.device_pixels_per_screen_px();
|
||||
let px = px.to_untyped();
|
||||
|
||||
if px.x.abs() > TOUCH_PAN_MIN_SCREEN_PX ||
|
||||
px.y.abs() > TOUCH_PAN_MIN_SCREEN_PX
|
||||
{
|
||||
self.touch_gesture_state = TouchState::Panning;
|
||||
self.on_scroll_window_event(delta, point.cast().unwrap());
|
||||
}
|
||||
}
|
||||
None => warn!("first_touch_point not set")
|
||||
}
|
||||
}
|
||||
TouchState::Panning => {
|
||||
match self.last_touch_point {
|
||||
Some(p0) => {
|
||||
let delta = point - p0;
|
||||
self.on_scroll_window_event(delta, point.cast().unwrap());
|
||||
}
|
||||
None => warn!("last_touch_point not set")
|
||||
}
|
||||
}
|
||||
TouchState::DefaultPrevented => {
|
||||
// Send the event to script.
|
||||
if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
|
||||
result.layer.send_event(self,
|
||||
TouchMoveEvent(identifier, result.point.to_untyped()));
|
||||
}
|
||||
}
|
||||
}
|
||||
self.last_touch_point = Some(point);
|
||||
}
|
||||
|
||||
fn on_touch_up(&mut self, identifier: i32, point: TypedPoint2D<DevicePixel, f32>) {
|
||||
// TODO: Track the number of active touch points, and don't reset stuff until it is zero.
|
||||
self.first_touch_point = None;
|
||||
self.last_touch_point = None;
|
||||
|
||||
// Send the event to script.
|
||||
if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
|
||||
result.layer.send_event(self, TouchUpEvent(identifier, result.point.to_untyped()));
|
||||
}
|
||||
|
||||
match self.touch_gesture_state {
|
||||
TouchState::Nothing => warn!("Got unexpected touch up event"),
|
||||
|
||||
TouchState::WaitingForScript => {}
|
||||
TouchState::Touching => {
|
||||
// TODO: If the duration exceeds some threshold, send a contextmenu event instead.
|
||||
// TODO: Don't send a click if preventDefault is called on the touchend event.
|
||||
self.simulate_mouse_click(point);
|
||||
}
|
||||
TouchState::Panning => {}
|
||||
TouchState::DefaultPrevented => {}
|
||||
}
|
||||
self.touch_gesture_state = TouchState::Nothing;
|
||||
}
|
||||
|
||||
/// http://w3c.github.io/touch-events/#mouse-events
|
||||
fn simulate_mouse_click(&self, p: TypedPoint2D<DevicePixel, f32>) {
|
||||
match self.find_topmost_layer_at_point(p / self.scene.scale) {
|
||||
Some(HitTestResult { layer, point }) => {
|
||||
let button = MouseButton::Left;
|
||||
layer.send_mouse_move_event(self, point);
|
||||
layer.send_mouse_event(self, MouseWindowEvent::MouseDown(button, p), point);
|
||||
layer.send_mouse_event(self, MouseWindowEvent::MouseUp(button, p), point);
|
||||
layer.send_mouse_event(self, MouseWindowEvent::Click(button, p), point);
|
||||
}
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn on_scroll_window_event(&mut self,
|
||||
delta: TypedPoint2D<DevicePixel, f32>,
|
||||
cursor: TypedPoint2D<DevicePixel, i32>) {
|
||||
|
|
|
@ -12,7 +12,8 @@ use layers::color::Color;
|
|||
use layers::geometry::LayerPixel;
|
||||
use layers::layers::{Layer, LayerBufferSet};
|
||||
use msg::compositor_msg::{Epoch, LayerId, LayerProperties, ScrollPolicy};
|
||||
use msg::constellation_msg::{PipelineId};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_traits::CompositorEvent;
|
||||
use script_traits::CompositorEvent::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
|
||||
use script_traits::ConstellationControlMsg;
|
||||
use std::rc::Rc;
|
||||
|
@ -132,6 +133,11 @@ pub trait CompositorLayer {
|
|||
cursor: TypedPoint2D<LayerPixel, f32>)
|
||||
where Window: WindowMethods;
|
||||
|
||||
fn send_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
event: CompositorEvent)
|
||||
where Window: WindowMethods;
|
||||
|
||||
fn clamp_scroll_offset_and_scroll_layer(&self,
|
||||
new_offset: TypedPoint2D<LayerPixel, f32>)
|
||||
-> ScrollEventResult;
|
||||
|
@ -372,22 +378,22 @@ impl CompositorLayer for Layer<CompositorData> {
|
|||
MouseWindowEvent::MouseUp(button, _) =>
|
||||
MouseUpEvent(button, event_point),
|
||||
};
|
||||
|
||||
if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) {
|
||||
pipeline.script_chan
|
||||
.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message))
|
||||
.unwrap();
|
||||
}
|
||||
self.send_event(compositor, message);
|
||||
}
|
||||
|
||||
fn send_mouse_move_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
cursor: TypedPoint2D<LayerPixel, f32>)
|
||||
where Window: WindowMethods {
|
||||
let message = MouseMoveEvent(cursor.to_untyped());
|
||||
self.send_event(compositor, MouseMoveEvent(cursor.to_untyped()));
|
||||
}
|
||||
|
||||
fn send_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
event: CompositorEvent) where Window: WindowMethods {
|
||||
if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) {
|
||||
let _ = pipeline.script_chan
|
||||
.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
|
||||
.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), event));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use headless;
|
|||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use layers::layers::{BufferRequest, LayerBufferSet};
|
||||
use layers::platform::surface::{NativeDisplay, NativeSurface};
|
||||
use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerProperties};
|
||||
use msg::compositor_msg::{Epoch, EventResult, FrameTreeId, LayerId, LayerProperties};
|
||||
use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg};
|
||||
use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId};
|
||||
use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState};
|
||||
|
@ -94,6 +94,10 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
|
|||
ScriptToCompositorMsg::SendKeyEvent(key, key_state, key_modifiers) => {
|
||||
compositor_proxy.send(Msg::KeyEvent(key, key_state, key_modifiers))
|
||||
}
|
||||
|
||||
ScriptToCompositorMsg::TouchEventProcessed(result) => {
|
||||
compositor_proxy.send(Msg::TouchEventProcessed(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +193,8 @@ pub enum Msg {
|
|||
RecompositeAfterScroll,
|
||||
/// Sends an unconsumed key event back to the compositor.
|
||||
KeyEvent(Key, KeyState, KeyModifiers),
|
||||
/// Script has handled a touch event, and either prevented or allowed default actions.
|
||||
TouchEventProcessed(EventResult),
|
||||
/// Changes the cursor.
|
||||
SetCursor(Cursor),
|
||||
/// Composite to a PNG file and return the Image over a passed channel.
|
||||
|
@ -238,6 +244,7 @@ impl Debug for Msg {
|
|||
Msg::ScrollTimeout(..) => write!(f, "ScrollTimeout"),
|
||||
Msg::RecompositeAfterScroll => write!(f, "RecompositeAfterScroll"),
|
||||
Msg::KeyEvent(..) => write!(f, "KeyEvent"),
|
||||
Msg::TouchEventProcessed(..) => write!(f, "TouchEventProcessed"),
|
||||
Msg::SetCursor(..) => write!(f, "SetCursor"),
|
||||
Msg::CreatePng(..) => write!(f, "CreatePng"),
|
||||
Msg::PaintTaskExited(..) => write!(f, "PaintTaskExited"),
|
||||
|
|
|
@ -120,6 +120,7 @@ impl CompositorEventListener for NullCompositor {
|
|||
Msg::ChangePageTitle(..) |
|
||||
Msg::ChangePageUrl(..) |
|
||||
Msg::KeyEvent(..) |
|
||||
Msg::TouchEventProcessed(..) |
|
||||
Msg::SetCursor(..) |
|
||||
Msg::ViewportConstrained(..) => {}
|
||||
Msg::CreatePng(..) |
|
||||
|
|
|
@ -160,5 +160,12 @@ pub enum ScriptToCompositorMsg {
|
|||
GetClientWindow(IpcSender<(Size2D<u32>, Point2D<i32>)>),
|
||||
MoveTo(Point2D<i32>),
|
||||
ResizeTo(Size2D<u32>),
|
||||
TouchEventProcessed(EventResult),
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum EventResult {
|
||||
DefaultAllowed,
|
||||
DefaultPrevented,
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible};
|
|||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::RootedReference;
|
||||
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root};
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::trace::RootedVec;
|
||||
use dom::bindings::utils::XMLName::InvalidXMLName;
|
||||
|
@ -60,6 +61,9 @@ use dom::processinginstruction::ProcessingInstruction;
|
|||
use dom::range::Range;
|
||||
use dom::servohtmlparser::ServoHTMLParser;
|
||||
use dom::text::Text;
|
||||
use dom::touch::Touch;
|
||||
use dom::touchevent::TouchEvent;
|
||||
use dom::touchlist::TouchList;
|
||||
use dom::treewalker::TreeWalker;
|
||||
use dom::uievent::UIEvent;
|
||||
use dom::window::{ReflowReason, Window};
|
||||
|
@ -699,6 +703,55 @@ impl Document {
|
|||
ReflowReason::MouseEvent);
|
||||
}
|
||||
|
||||
pub fn handle_touch_event(&self,
|
||||
js_runtime: *mut JSRuntime,
|
||||
identifier: i32,
|
||||
point: Point2D<f32>,
|
||||
event_name: String) -> bool {
|
||||
let node = match self.hit_test(&point) {
|
||||
Some(node_address) => node::from_untrusted_node_address(js_runtime, node_address),
|
||||
None => return false
|
||||
};
|
||||
let el = match node.downcast::<Element>() {
|
||||
Some(el) => Root::from_ref(el),
|
||||
None => {
|
||||
let parent = node.r().GetParentNode();
|
||||
match parent.and_then(Root::downcast::<Element>) {
|
||||
Some(parent) => parent,
|
||||
None => return false
|
||||
}
|
||||
},
|
||||
};
|
||||
let target = el.upcast::<EventTarget>();
|
||||
|
||||
let x = Finite::wrap(point.x as f64);
|
||||
let y = Finite::wrap(point.y as f64);
|
||||
|
||||
let window = self.window.root();
|
||||
|
||||
let touch = Touch::new(window.r(), identifier, target, x, y, x, y);
|
||||
let mut touches = RootedVec::new();
|
||||
touches.push(JS::from_rooted(&touch));
|
||||
let touches = TouchList::new(window.r(), touches.r());
|
||||
|
||||
let event = TouchEvent::new(window.r(),
|
||||
event_name,
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::Cancelable,
|
||||
Some(window.r()),
|
||||
0i32,
|
||||
&touches, &touches, &touches,
|
||||
// FIXME: modifier keys
|
||||
false, false, false, false);
|
||||
let event = event.upcast::<Event>();
|
||||
let result = event.fire(target);
|
||||
|
||||
window.r().reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::MouseEvent);
|
||||
result
|
||||
}
|
||||
|
||||
/// The entry point for all key processing for web content
|
||||
pub fn dispatch_key_event(&self,
|
||||
key: Key,
|
||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::conversions::Castable;
|
|||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, MutHeap, Root};
|
||||
use dom::bindings::utils::reflect_dom_object;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::event::{EventBubbles, EventCancelable};
|
||||
use dom::touchlist::TouchList;
|
||||
use dom::uievent::UIEvent;
|
||||
use dom::window::Window;
|
||||
|
|
|
@ -60,7 +60,7 @@ use layout_interface::{ReflowQueryType};
|
|||
use layout_interface::{self, LayoutChan, NewLayoutTaskInfo, ReflowGoal, ScriptLayoutChan};
|
||||
use libc;
|
||||
use mem::heap_size_of_self_and_children;
|
||||
use msg::compositor_msg::{LayerId, ScriptToCompositorMsg};
|
||||
use msg::compositor_msg::{EventResult, LayerId, ScriptToCompositorMsg};
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use msg::constellation_msg::{ConstellationChan, FocusType, LoadData};
|
||||
use msg::constellation_msg::{MozBrowserEvent, PipelineExitType, PipelineId};
|
||||
|
@ -79,6 +79,7 @@ use profile_traits::time::{self, ProfilerCategory, profile};
|
|||
use script_traits::CompositorEvent::{ClickEvent, ResizeEvent};
|
||||
use script_traits::CompositorEvent::{KeyEvent, MouseMoveEvent};
|
||||
use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent};
|
||||
use script_traits::CompositorEvent::{TouchDownEvent, TouchMoveEvent, TouchUpEvent};
|
||||
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
||||
use script_traits::{InitialScriptState, MouseButton, NewLayoutInfo};
|
||||
use script_traits::{OpaqueScriptLayoutChannel, ScriptState, ScriptTaskFactory};
|
||||
|
@ -1784,6 +1785,27 @@ impl ScriptTask {
|
|||
std_mem::swap(&mut *self.mouse_over_targets.borrow_mut(), &mut *mouse_over_targets);
|
||||
}
|
||||
|
||||
TouchDownEvent(identifier, point) => {
|
||||
let default_action_allowed =
|
||||
self.handle_touch_event(pipeline_id, identifier, point, "touchstart");
|
||||
if default_action_allowed {
|
||||
// TODO: Wait to see if preventDefault is called on the first touchmove event.
|
||||
self.compositor.borrow_mut().send(ScriptToCompositorMsg::TouchEventProcessed(
|
||||
EventResult::DefaultAllowed)).unwrap();
|
||||
} else {
|
||||
self.compositor.borrow_mut().send(ScriptToCompositorMsg::TouchEventProcessed(
|
||||
EventResult::DefaultPrevented)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
TouchMoveEvent(identifier, point) => {
|
||||
self.handle_touch_event(pipeline_id, identifier, point, "touchmove");
|
||||
}
|
||||
|
||||
TouchUpEvent(identifier, point) => {
|
||||
self.handle_touch_event(pipeline_id, identifier, point, "touchend");
|
||||
}
|
||||
|
||||
KeyEvent(key, state, modifiers) => {
|
||||
let page = get_page(&self.root_page(), pipeline_id);
|
||||
let document = page.document();
|
||||
|
@ -1803,6 +1825,17 @@ impl ScriptTask {
|
|||
document.r().handle_mouse_event(self.js_runtime.rt(), button, point, mouse_event_type);
|
||||
}
|
||||
|
||||
fn handle_touch_event(&self,
|
||||
pipeline_id: PipelineId,
|
||||
identifier: i32,
|
||||
point: Point2D<f32>,
|
||||
event_name: &str) -> bool {
|
||||
let page = get_page(&self.root_page(), pipeline_id);
|
||||
let document = page.document();
|
||||
document.r().handle_touch_event(self.js_runtime.rt(), identifier, point,
|
||||
event_name.to_owned())
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#navigating-across-documents
|
||||
/// The entry point for content to notify that a new load has been requested
|
||||
/// for the given pipeline (specifically the "navigate" algorithm).
|
||||
|
|
|
@ -150,7 +150,7 @@ pub enum ConstellationControlMsg {
|
|||
}
|
||||
|
||||
/// The mouse button involved in the event.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum MouseButton {
|
||||
/// The left mouse button.
|
||||
Left,
|
||||
|
@ -172,6 +172,12 @@ pub enum CompositorEvent {
|
|||
MouseUpEvent(MouseButton, Point2D<f32>),
|
||||
/// The mouse was moved over a point.
|
||||
MouseMoveEvent(Point2D<f32>),
|
||||
/// A touch began at a point.
|
||||
TouchDownEvent(i32, Point2D<f32>),
|
||||
/// A touch was moved over a point.
|
||||
TouchMoveEvent(i32, Point2D<f32>),
|
||||
/// A touch ended at a point.
|
||||
TouchUpEvent(i32, Point2D<f32>),
|
||||
/// A key was pressed.
|
||||
KeyEvent(Key, KeyState, KeyModifiers),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue