mirror of
https://github.com/servo/servo.git
synced 2025-06-25 17:44:33 +01:00
Impelemented zooming and slightly better scrolling.
This commit is contained in:
parent
fb2ce2c00c
commit
160f58e90a
3 changed files with 86 additions and 10 deletions
|
@ -126,6 +126,9 @@ fn run_main_loop(port: Port<Msg>,
|
||||||
let page_size = @mut Size2D(0f32, 0f32);
|
let page_size = @mut Size2D(0f32, 0f32);
|
||||||
let window_size = @mut Size2D(800, 600);
|
let window_size = @mut Size2D(800, 600);
|
||||||
|
|
||||||
|
// Keeps track of the current zoom factor
|
||||||
|
let world_zoom = @mut 1f32;
|
||||||
|
|
||||||
let check_for_messages: @fn() = || {
|
let check_for_messages: @fn() = || {
|
||||||
// Periodically check if the script task responded to our last resize event
|
// Periodically check if the script task responded to our last resize event
|
||||||
resize_rate_limiter.check_resize_response();
|
resize_rate_limiter.check_resize_response();
|
||||||
|
@ -248,16 +251,65 @@ fn run_main_loop(port: Port<Msg>,
|
||||||
*world_offset = world_offset_copy - delta;
|
*world_offset = world_offset_copy - delta;
|
||||||
|
|
||||||
// Clamp the world offset to the screen size.
|
// Clamp the world offset to the screen size.
|
||||||
let max_x = (page_size.width - window_size.width as f32).max(&0.0);
|
let max_x = (page_size.width * *world_zoom - window_size.width as f32).max(&0.0);
|
||||||
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
|
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
|
||||||
let max_y = (page_size.height - window_size.height as f32).max(&0.0);
|
let max_y = (page_size.height * *world_zoom - window_size.height as f32).max(&0.0);
|
||||||
world_offset.y = world_offset.y.clamp(&0.0, &max_y);
|
world_offset.y = world_offset.y.clamp(&0.0, &max_y);
|
||||||
|
|
||||||
debug!("compositor: scrolled to %?", *world_offset);
|
debug!("compositor: scrolled to %?", *world_offset);
|
||||||
|
|
||||||
root_layer.common.set_transform(identity().translate(-world_offset.x,
|
let mut scroll_transform = identity();
|
||||||
-world_offset.y,
|
|
||||||
0.0));
|
scroll_transform = scroll_transform.translate(window_size.width as f32 / 2f32 * *world_zoom - world_offset.x,
|
||||||
|
window_size.height as f32 / 2f32 * *world_zoom - world_offset.y,
|
||||||
|
0.0);
|
||||||
|
scroll_transform = scroll_transform.scale(*world_zoom, *world_zoom, 1f32);
|
||||||
|
scroll_transform = scroll_transform.translate(window_size.width as f32 / -2f32,
|
||||||
|
window_size.height as f32 / -2f32,
|
||||||
|
0.0);
|
||||||
|
|
||||||
|
root_layer.common.set_transform(scroll_transform);
|
||||||
|
|
||||||
|
window.set_needs_display()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// When the user pinch-zooms, scale the layer
|
||||||
|
do window.set_zoom_callback |delta| {
|
||||||
|
let zoom_const = 0.01;
|
||||||
|
let old_world_zoom = *world_zoom;
|
||||||
|
|
||||||
|
// Determine zoom amount
|
||||||
|
*world_zoom = (*world_zoom + delta.y * zoom_const).max(&1.0);
|
||||||
|
|
||||||
|
// Update world offset
|
||||||
|
let corner_to_center_x = world_offset.x + window_size.width as f32 / 2f32;
|
||||||
|
let new_corner_to_center_x = corner_to_center_x * *world_zoom / old_world_zoom;
|
||||||
|
world_offset.x = world_offset.x + new_corner_to_center_x - corner_to_center_x;
|
||||||
|
|
||||||
|
let corner_to_center_y = world_offset.y + window_size.height as f32 / 2f32;
|
||||||
|
let new_corner_to_center_y = corner_to_center_y * *world_zoom / old_world_zoom;
|
||||||
|
world_offset.y = world_offset.y + new_corner_to_center_y - corner_to_center_y;
|
||||||
|
|
||||||
|
// Clamp to page bounds when zooming out
|
||||||
|
let max_x = (page_size.width * *world_zoom - window_size.width as f32).max(&0.0);
|
||||||
|
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
|
||||||
|
let max_y = (page_size.height * *world_zoom - window_size.height as f32).max(&0.0);
|
||||||
|
world_offset.y = world_offset.y.clamp(&0.0, &max_y);
|
||||||
|
|
||||||
|
|
||||||
|
// Apply transformations
|
||||||
|
let mut zoom_transform = identity();
|
||||||
|
zoom_transform = zoom_transform.translate(window_size.width as f32 / 2f32 * *world_zoom - world_offset.x,
|
||||||
|
window_size.height as f32 / 2f32 * *world_zoom - world_offset.y,
|
||||||
|
0.0);
|
||||||
|
zoom_transform = zoom_transform.scale(*world_zoom, *world_zoom, 1f32);
|
||||||
|
zoom_transform = zoom_transform.translate(window_size.width as f32 / -2f32,
|
||||||
|
window_size.height as f32 / -2f32,
|
||||||
|
0.0);
|
||||||
|
root_layer.common.set_transform(zoom_transform);
|
||||||
|
|
||||||
|
|
||||||
window.set_needs_display()
|
window.set_needs_display()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
/// least on desktops. It is designed for testing Servo without the need of a UI.
|
/// least on desktops. It is designed for testing Servo without the need of a UI.
|
||||||
|
|
||||||
use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, ClickCallback};
|
use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, ClickCallback};
|
||||||
use windowing::{ResizeCallback, ScrollCallback, WindowMethods};
|
use windowing::{ResizeCallback, ScrollCallback, ZoomCallback, WindowMethods};
|
||||||
|
|
||||||
use alert::{Alert, AlertMethods};
|
use alert::{Alert, AlertMethods};
|
||||||
use core::libc::c_int;
|
use core::libc::c_int;
|
||||||
|
@ -37,8 +37,10 @@ pub struct Window {
|
||||||
load_url_callback: Option<LoadUrlCallback>,
|
load_url_callback: Option<LoadUrlCallback>,
|
||||||
click_callback: Option<ClickCallback>,
|
click_callback: Option<ClickCallback>,
|
||||||
scroll_callback: Option<ScrollCallback>,
|
scroll_callback: Option<ScrollCallback>,
|
||||||
|
zoom_callback: Option<ZoomCallback>,
|
||||||
|
|
||||||
drag_origin: Point2D<c_int>,
|
drag_origin: Point2D<c_int>,
|
||||||
|
down_button: c_int
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowMethods<Application> for Window {
|
impl WindowMethods<Application> for Window {
|
||||||
|
@ -57,10 +59,14 @@ impl WindowMethods<Application> for Window {
|
||||||
load_url_callback: None,
|
load_url_callback: None,
|
||||||
click_callback: None,
|
click_callback: None,
|
||||||
scroll_callback: None,
|
scroll_callback: None,
|
||||||
|
zoom_callback: None,
|
||||||
|
|
||||||
drag_origin: Point2D(0, 0),
|
drag_origin: Point2D(0, 0),
|
||||||
|
down_button: 0 // FIXME: Hacky solution to 2 button mouse.
|
||||||
|
// Replace with tkuehn's code.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Register event handlers.
|
// Register event handlers.
|
||||||
do glut::reshape_func(window.glut_window) |width, height| {
|
do glut::reshape_func(window.glut_window) |width, height| {
|
||||||
match window.resize_callback {
|
match window.resize_callback {
|
||||||
|
@ -78,8 +84,9 @@ impl WindowMethods<Application> for Window {
|
||||||
do glut::keyboard_func |key, _, _| {
|
do glut::keyboard_func |key, _, _| {
|
||||||
window.handle_key(key)
|
window.handle_key(key)
|
||||||
}
|
}
|
||||||
do glut::mouse_func |_, _, x, y| {
|
do glut::mouse_func |button, _, x, y| {
|
||||||
window.handle_click(x, y);
|
window.handle_click(x, y);
|
||||||
|
window.down_button = button;
|
||||||
window.start_drag(x, y)
|
window.start_drag(x, y)
|
||||||
}
|
}
|
||||||
do glut::motion_func |x, y| {
|
do glut::motion_func |x, y| {
|
||||||
|
@ -124,6 +131,11 @@ impl WindowMethods<Application> for Window {
|
||||||
self.scroll_callback = Some(new_scroll_callback)
|
self.scroll_callback = Some(new_scroll_callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Registers a zoom to be run when the user zooms.
|
||||||
|
pub fn set_zoom_callback(&mut self, new_zoom_callback: ZoomCallback) {
|
||||||
|
self.zoom_callback = Some(new_zoom_callback)
|
||||||
|
}
|
||||||
|
|
||||||
/// Spins the event loop.
|
/// Spins the event loop.
|
||||||
pub fn check_loop(@mut self) {
|
pub fn check_loop(@mut self) {
|
||||||
glut::check_loop()
|
glut::check_loop()
|
||||||
|
@ -163,9 +175,16 @@ impl Window {
|
||||||
let delta = new_point - self.drag_origin;
|
let delta = new_point - self.drag_origin;
|
||||||
self.drag_origin = new_point;
|
self.drag_origin = new_point;
|
||||||
|
|
||||||
match self.scroll_callback {
|
if self.down_button == 2 {
|
||||||
None => {}
|
match self.zoom_callback {
|
||||||
Some(callback) => callback(Point2D(delta.x as f32, delta.y as f32)),
|
None => {}
|
||||||
|
Some(callback) => callback(Point2D(delta.x as f32, delta.y as f32)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match self.scroll_callback {
|
||||||
|
None => {}
|
||||||
|
Some(callback) => callback(Point2D(delta.x as f32, delta.y as f32)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@ pub type ClickCallback = @fn(Point2D<f32>);
|
||||||
/// Type of the function that is called when the user scrolls.
|
/// Type of the function that is called when the user scrolls.
|
||||||
pub type ScrollCallback = @fn(Point2D<f32>);
|
pub type ScrollCallback = @fn(Point2D<f32>);
|
||||||
|
|
||||||
|
///Type of the function that is called when the user zooms.
|
||||||
|
pub type ZoomCallback = @fn(Point2D<f32>);
|
||||||
|
|
||||||
/// Methods for an abstract Application.
|
/// Methods for an abstract Application.
|
||||||
pub trait ApplicationMethods {
|
pub trait ApplicationMethods {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
|
@ -46,6 +49,8 @@ pub trait WindowMethods<A> {
|
||||||
pub fn set_click_callback(&mut self, new_click_callback: ClickCallback);
|
pub fn set_click_callback(&mut self, new_click_callback: ClickCallback);
|
||||||
/// Registers a callback to run when the user scrolls.
|
/// Registers a callback to run when the user scrolls.
|
||||||
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback);
|
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback);
|
||||||
|
/// Registers a callback to run when the user zooms.
|
||||||
|
pub fn set_zoom_callback(&mut self, new_zoom_callback: ZoomCallback);
|
||||||
|
|
||||||
/// Spins the event loop.
|
/// Spins the event loop.
|
||||||
pub fn check_loop(@mut self);
|
pub fn check_loop(@mut self);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue