From 66e31aa0bd224008635a0c9d52f4de4ace731a93 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 17 May 2013 19:28:40 -0700 Subject: [PATCH] Implement the beginnings of scrolling via dragging. There are tearing problems and GLUT does not support the mouse wheel. Still, it's a start! --- src/components/servo/compositing/mod.rs | 26 ++++++++++- .../servo/platform/common/glut_windowing.rs | 43 ++++++++++++++++++- src/components/servo/windowing.rs | 8 ++++ src/support/layers/rust-layers | 2 +- 4 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/components/servo/compositing/mod.rs b/src/components/servo/compositing/mod.rs index 18eb3d8c7a4..dec19f9313d 100644 --- a/src/components/servo/compositing/mod.rs +++ b/src/components/servo/compositing/mod.rs @@ -106,6 +106,11 @@ fn run_main_loop(po: Port, script_chan: SharedChan, opts: &Opts) let key_handlers: @mut ~[Chan<()>] = @mut ~[]; let done = @mut false; + // FIXME: This should not be a separate offset applied after the fact but rather should be + // applied to the layers themselves on a per-layer basis. However, this won't work until scroll + // positions are sent to content. + let world_offset = @mut Point2D(0f32, 0f32); + let check_for_messages: @fn() = || { // Periodically check if the script task responded to our last resize event resize_rate_limiter.check_resize_response(); @@ -164,8 +169,11 @@ fn run_main_loop(po: Port, script_chan: SharedChan, opts: &Opts) }; // Set the layer's transform. - let (x, y) = (buffer.rect.origin.x as f32, buffer.rect.origin.y as f32); - let transform = original_layer_transform.translate(x, y, 0.0); + let mut origin = Point2D(buffer.rect.origin.x as f32, + buffer.rect.origin.y as f32); + let transform = original_layer_transform.translate(origin.x, + origin.y, + 0.0); let transform = transform.scale(width as f32, height as f32, 1.0); image_layer.common.set_transform(transform) } @@ -178,6 +186,7 @@ fn run_main_loop(po: Port, script_chan: SharedChan, opts: &Opts) do window.set_composite_callback { do time::time(~"compositing") { + debug!("compositor: compositing"); // Adjust the layer dimensions as necessary to correspond to the size of the window. scene.size = window.size(); @@ -200,6 +209,19 @@ fn run_main_loop(po: Port, script_chan: SharedChan, opts: &Opts) script_chan.send(LoadMsg(url::make_url(url_string.to_str(), None))) } + // When the user scrolls, move the layer around. + do window.set_scroll_callback |delta| { + // FIXME: Can't use `+=` due to a Rust bug. + let world_offset_copy = *world_offset; + *world_offset = world_offset_copy + delta; + + debug!("compositor: scrolled to %?", *world_offset); + + root_layer.common.set_transform(identity().translate(world_offset.x, world_offset.y, 0.0)); + + window.set_needs_display() + } + // Enter the main event loop. while !*done { // Check for new messages coming from the rendering task. diff --git a/src/components/servo/platform/common/glut_windowing.rs b/src/components/servo/platform/common/glut_windowing.rs index abb5f4b9591..1e33c66b277 100644 --- a/src/components/servo/platform/common/glut_windowing.rs +++ b/src/components/servo/platform/common/glut_windowing.rs @@ -8,9 +8,11 @@ /// least on desktops. It is designed for testing Servo without the need of a UI. use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, ResizeCallback}; -use windowing::{WindowMethods}; +use windowing::{ScrollCallback, WindowMethods}; use alert::{Alert, AlertMethods}; +use core::libc::c_int; +use geom::point::Point2D; use geom::size::Size2D; use glut::glut::{DOUBLE, WindowHeight, WindowWidth}; use glut::glut; @@ -33,6 +35,9 @@ pub struct Window { composite_callback: Option, resize_callback: Option, load_url_callback: Option, + scroll_callback: Option, + + drag_origin: Point2D, } impl WindowMethods for Window { @@ -49,6 +54,9 @@ impl WindowMethods for Window { composite_callback: None, resize_callback: None, load_url_callback: None, + scroll_callback: None, + + drag_origin: Point2D(0, 0), }; // Register event handlers. @@ -68,6 +76,12 @@ impl WindowMethods for Window { do glut::keyboard_func |key, _, _| { window.handle_key(key) } + do glut::mouse_func |_, _, x, y| { + window.start_drag(x, y) + } + do glut::motion_func |x, y| { + window.continue_drag(x, y) + } window } @@ -98,10 +112,20 @@ impl WindowMethods for Window { self.load_url_callback = Some(new_load_url_callback) } + /// Registers a callback to be run when the user scrolls. + pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback) { + self.scroll_callback = Some(new_scroll_callback) + } + /// Spins the event loop. pub fn check_loop(@mut self) { glut::check_loop() } + + /// Schedules a redisplay. + pub fn set_needs_display(@mut self) { + glut::post_redisplay() + } } impl Window { @@ -113,6 +137,23 @@ impl Window { } } + /// Helper function to start a drag. + fn start_drag(&mut self, x: c_int, y: c_int) { + self.drag_origin = Point2D(x, y) + } + + /// Helper function to continue a drag. + fn continue_drag(&mut self, x: c_int, y: c_int) { + let new_point = Point2D(x, y); + let delta = new_point - self.drag_origin; + self.drag_origin = new_point; + + match self.scroll_callback { + None => {} + Some(callback) => callback(Point2D(delta.x as f32, delta.y as f32)), + } + } + /// Helper function to pop up an alert box prompting the user to load a URL. fn load_url(&self) { match self.load_url_callback { diff --git a/src/components/servo/windowing.rs b/src/components/servo/windowing.rs index 8c642727a7f..708ea4105ec 100644 --- a/src/components/servo/windowing.rs +++ b/src/components/servo/windowing.rs @@ -4,6 +4,7 @@ //! Abstract windowing methods. The concrete implementations of these can be found in `platform/`. +use geom::point::Point2D; use geom::size::Size2D; /// Type of the function that is called when the screen is to be redisplayed. @@ -15,6 +16,9 @@ pub type ResizeCallback = @fn(uint, uint); /// Type of the function that is called when a new URL is to be loaded. pub type LoadUrlCallback = @fn(&str); +/// Type of the function that is called when the user scrolls. +pub type ScrollCallback = @fn(Point2D); + /// Methods for an abstract Application. pub trait ApplicationMethods { fn new() -> Self; @@ -34,8 +38,12 @@ pub trait WindowMethods { pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback); /// Registers a callback to run when a new URL is to be loaded. pub fn set_load_url_callback(&mut self, new_load_url_callback: LoadUrlCallback); + /// Registers a callback to run when the user scrolls. + pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback); /// Spins the event loop. pub fn check_loop(@mut self); + /// Schedules a redisplay at the next turn of the event loop. + pub fn set_needs_display(@mut self); } diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers index 60036bce5d9..af960707afc 160000 --- a/src/support/layers/rust-layers +++ b/src/support/layers/rust-layers @@ -1 +1 @@ -Subproject commit 60036bce5d9962777467b6763c8642d9ce294cc7 +Subproject commit af960707afc666ac38591f1f0545f18a1bb89471