Implement the beginnings of scrolling via dragging.

There are tearing problems and GLUT does not support the mouse wheel.
Still, it's a start!
This commit is contained in:
Patrick Walton 2013-05-17 19:28:40 -07:00
parent 01ce79bc74
commit 66e31aa0bd
4 changed files with 75 additions and 4 deletions

View file

@ -106,6 +106,11 @@ fn run_main_loop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, 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<Msg>, script_chan: SharedChan<ScriptMsg>, 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<Msg>, script_chan: SharedChan<ScriptMsg>, 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<Msg>, script_chan: SharedChan<ScriptMsg>, 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.

View file

@ -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<CompositeCallback>,
resize_callback: Option<ResizeCallback>,
load_url_callback: Option<LoadUrlCallback>,
scroll_callback: Option<ScrollCallback>,
drag_origin: Point2D<c_int>,
}
impl WindowMethods<Application> for Window {
@ -49,6 +54,9 @@ impl WindowMethods<Application> 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<Application> 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<Application> 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 {

View file

@ -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<f32>);
/// Methods for an abstract Application.
pub trait ApplicationMethods {
fn new() -> Self;
@ -34,8 +38,12 @@ pub trait WindowMethods<A> {
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);
}

@ -1 +1 @@
Subproject commit 60036bce5d9962777467b6763c8642d9ce294cc7
Subproject commit af960707afc666ac38591f1f0545f18a1bb89471