Add queuing of pinch zoom events

This commit is contained in:
Matt Brubeck 2015-12-14 14:25:09 -08:00
parent eb2a37d41c
commit 40776b9492

View file

@ -179,8 +179,8 @@ pub struct IOCompositor<Window: WindowMethods> {
/// Touch input state machine /// Touch input state machine
touch_handler: TouchHandler, touch_handler: TouchHandler,
/// Pending scroll events. /// Pending scroll/zoom events.
pending_scroll_events: Vec<ScrollEvent>, pending_scroll_zoom_events: Vec<ScrollZoomEvent>,
/// Used by the logic that determines when it is safe to output an /// Used by the logic that determines when it is safe to output an
/// image for the reftest framework. /// image for the reftest framework.
@ -197,8 +197,12 @@ pub struct IOCompositor<Window: WindowMethods> {
last_mouse_move_recipient: Option<PipelineId>, last_mouse_move_recipient: Option<PipelineId>,
} }
pub struct ScrollEvent { pub struct ScrollZoomEvent {
/// Change the pinch zoom level by this factor
magnification: f32,
/// Scroll by this offset
delta: TypedPoint2D<DevicePixel, f32>, delta: TypedPoint2D<DevicePixel, f32>,
/// Apply changes to the frame at this location
cursor: TypedPoint2D<DevicePixel, i32>, cursor: TypedPoint2D<DevicePixel, i32>,
} }
@ -324,7 +328,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
scrolling_timer: ScrollingTimerProxy::new(state.sender), scrolling_timer: ScrollingTimerProxy::new(state.sender),
composition_request: CompositionRequest::NoCompositingNecessary, composition_request: CompositionRequest::NoCompositingNecessary,
touch_handler: TouchHandler::new(), touch_handler: TouchHandler::new(),
pending_scroll_events: Vec::new(), pending_scroll_zoom_events: Vec::new(),
composite_target: composite_target, composite_target: composite_target,
shutdown_state: ShutdownState::NotShuttingDown, shutdown_state: ShutdownState::NotShuttingDown,
page_zoom: ScaleFactor::new(1.0), page_zoom: ScaleFactor::new(1.0),
@ -1198,8 +1202,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
} }
TouchAction::Zoom(magnification, scroll_delta) => { TouchAction::Zoom(magnification, scroll_delta) => {
let cursor = Point2D::typed(-1, -1); // Make sure this hits the base layer. let cursor = Point2D::typed(-1, -1); // Make sure this hits the base layer.
self.on_pinch_zoom_window_event(magnification); self.pending_scroll_zoom_events.push(ScrollZoomEvent {
self.on_scroll_window_event(scroll_delta, cursor); magnification: magnification,
delta: scroll_delta,
cursor: cursor,
});
self.composite_if_necessary(CompositingReason::Zoom);
} }
TouchAction::DispatchEvent => { TouchAction::DispatchEvent => {
if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) { if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
@ -1250,7 +1258,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn on_scroll_window_event(&mut self, fn on_scroll_window_event(&mut self,
delta: TypedPoint2D<DevicePixel, f32>, delta: TypedPoint2D<DevicePixel, f32>,
cursor: TypedPoint2D<DevicePixel, i32>) { cursor: TypedPoint2D<DevicePixel, i32>) {
self.pending_scroll_events.push(ScrollEvent { self.pending_scroll_zoom_events.push(ScrollZoomEvent {
magnification: 1.0,
delta: delta, delta: delta,
cursor: cursor, cursor: cursor,
}); });
@ -1259,20 +1268,30 @@ impl<Window: WindowMethods> IOCompositor<Window> {
} }
fn process_pending_scroll_events(&mut self) { fn process_pending_scroll_events(&mut self) {
let had_scroll_events = self.pending_scroll_events.len() > 0; let had_events = self.pending_scroll_zoom_events.len() > 0;
for scroll_event in std_mem::replace(&mut self.pending_scroll_events, for event in std_mem::replace(&mut self.pending_scroll_zoom_events,
Vec::new()) { Vec::new()) {
let delta = scroll_event.delta / self.scene.scale; let delta = event.delta / self.scene.scale;
let cursor = scroll_event.cursor.as_f32() / self.scene.scale; let cursor = event.cursor.as_f32() / self.scene.scale;
if let Some(ref mut layer) = self.scene.root { if let Some(ref mut layer) = self.scene.root {
layer.handle_scroll_event(delta, cursor); layer.handle_scroll_event(delta, cursor);
} }
if event.magnification != 1.0 {
self.zoom_action = true;
self.zoom_time = precise_time_s();
self.viewport_zoom = ScaleFactor::new(
(self.viewport_zoom.get() * event.magnification)
.min(self.max_viewport_zoom.as_ref().map_or(MAX_ZOOM, ScaleFactor::get))
.max(self.min_viewport_zoom.as_ref().map_or(MIN_ZOOM, ScaleFactor::get)));
self.update_zoom_transform();
}
self.perform_updates_after_scroll(); self.perform_updates_after_scroll();
} }
if had_scroll_events { if had_events {
self.send_viewport_rects_for_all_layers(); self.send_viewport_rects_for_all_layers();
} }
} }
@ -1400,36 +1419,13 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.send_window_size(); self.send_window_size();
} }
// TODO(pcwalton): I think this should go through the same queuing as scroll events do. /// Simulate a pinch zoom
fn on_pinch_zoom_window_event(&mut self, magnification: f32) { fn on_pinch_zoom_window_event(&mut self, magnification: f32) {
use num::Float; self.pending_scroll_zoom_events.push(ScrollZoomEvent {
magnification: magnification,
self.zoom_action = true; delta: Point2D::typed(0.0, 0.0), // TODO: Scroll to keep the center in view?
self.zoom_time = precise_time_s(); cursor: Point2D::typed(-1, -1), // Make sure this hits the base layer.
let old_viewport_zoom = self.viewport_zoom; });
let viewport_zoom = ScaleFactor::new((self.viewport_zoom.get() * magnification)
.min(self.max_viewport_zoom.as_ref().map_or(MAX_ZOOM, ScaleFactor::get))
.max(self.min_viewport_zoom.as_ref().map_or(MIN_ZOOM, ScaleFactor::get)));
self.viewport_zoom = viewport_zoom;
self.update_zoom_transform();
// Scroll as needed
let window_size = self.window_size.as_f32();
let page_delta: TypedPoint2D<LayerPixel, f32> = Point2D::typed(
window_size.width.get() * (viewport_zoom.inv() - old_viewport_zoom.inv()).get() * 0.5,
window_size.height.get() * (viewport_zoom.inv() - old_viewport_zoom.inv()).get() * 0.5);
let cursor = Point2D::typed(-1f32, -1f32); // Make sure this hits the base layer.
match self.scene.root {
Some(ref mut layer) => {
layer.handle_scroll_event(page_delta, cursor);
}
None => { }
}
self.send_viewport_rects_for_all_layers();
self.composite_if_necessary(CompositingReason::Zoom); self.composite_if_necessary(CompositingReason::Zoom);
} }