mirror of
https://github.com/servo/servo.git
synced 2025-06-25 17:44:33 +01:00
commit
4d0b92d4e1
9 changed files with 188 additions and 93 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -85,3 +85,6 @@
|
||||||
[submodule "src/compiler/rust"]
|
[submodule "src/compiler/rust"]
|
||||||
path = src/compiler/rust
|
path = src/compiler/rust
|
||||||
url = https://github.com/mozilla/rust.git
|
url = https://github.com/mozilla/rust.git
|
||||||
|
[submodule "src/support/alert/rust-alert"]
|
||||||
|
path = src/support/alert/rust-alert
|
||||||
|
url = git://github.com/mozilla-servo/rust-alert.git
|
||||||
|
|
1
configure
vendored
1
configure
vendored
|
@ -398,6 +398,7 @@ AUTOCMD="${LIBTOOLIZE} && autoconf && autoheader && automake --add-missing --cop
|
||||||
# Copied from cairo's autogen.sh. Build fails without
|
# Copied from cairo's autogen.sh. Build fails without
|
||||||
|
|
||||||
CFG_SUBMODULES="\
|
CFG_SUBMODULES="\
|
||||||
|
support/alert/rust-alert \
|
||||||
support/azure/rust-azure \
|
support/azure/rust-azure \
|
||||||
support/css/rust-css \
|
support/css/rust-css \
|
||||||
support/geom/rust-geom \
|
support/geom/rust-geom \
|
||||||
|
|
|
@ -103,6 +103,11 @@ DEPS_rust-io-surface += \
|
||||||
rust-core-foundation \
|
rust-core-foundation \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
DEPS_rust-alert += \
|
||||||
|
rust-core-foundation \
|
||||||
|
rust-cocoa \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
DEPS_sharegl += \
|
DEPS_sharegl += \
|
||||||
rust-core-foundation \
|
rust-core-foundation \
|
||||||
rust-io-surface \
|
rust-io-surface \
|
||||||
|
|
|
@ -17,8 +17,10 @@ use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet};
|
use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet};
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use layers::layers::{Image, ImageData};
|
use layers::layers::{ARGB32Format, BasicImageData, ContainerLayer, ContainerLayerKind, Format};
|
||||||
use layers;
|
use layers::layers::{Image, ImageData, ImageLayer, ImageLayerKind, RGB24Format, WithDataFn};
|
||||||
|
use layers::rendergl;
|
||||||
|
use layers::scene::Scene;
|
||||||
use servo_util::{time, url};
|
use servo_util::{time, url};
|
||||||
|
|
||||||
mod resize_rate_limiter;
|
mod resize_rate_limiter;
|
||||||
|
@ -35,7 +37,7 @@ impl CompositorImpl {
|
||||||
let script_chan = Cell(script_chan);
|
let script_chan = Cell(script_chan);
|
||||||
let chan: Chan<Msg> = do on_osmain |port| {
|
let chan: Chan<Msg> = do on_osmain |port| {
|
||||||
debug!("preparing to enter main loop");
|
debug!("preparing to enter main loop");
|
||||||
mainloop(port, script_chan.take(), &opts);
|
run_main_loop(port, script_chan.take(), &opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
CompositorImpl {
|
CompositorImpl {
|
||||||
|
@ -59,59 +61,56 @@ struct AzureDrawTargetImageData {
|
||||||
size: Size2D<uint>
|
size: Size2D<uint>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl layers::layers::ImageData for AzureDrawTargetImageData {
|
impl ImageData for AzureDrawTargetImageData {
|
||||||
fn size(&self) -> Size2D<uint> {
|
fn size(&self) -> Size2D<uint> {
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
fn stride(&self) -> uint {
|
fn stride(&self) -> uint {
|
||||||
self.data_source_surface.stride() as uint
|
self.data_source_surface.stride() as uint
|
||||||
}
|
}
|
||||||
fn format(&self) -> layers::layers::Format {
|
fn format(&self) -> Format {
|
||||||
// FIXME: This is not always correct. We should query the Azure draw target for the format.
|
// FIXME: This is not always correct. We should query the Azure draw target for the format.
|
||||||
layers::layers::ARGB32Format
|
ARGB32Format
|
||||||
}
|
}
|
||||||
fn with_data(&self, f: layers::layers::WithDataFn) {
|
fn with_data(&self, f: WithDataFn) {
|
||||||
do self.data_source_surface.with_data |data| {
|
do self.data_source_surface.with_data |data| {
|
||||||
f(data);
|
f(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mainloop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
fn run_main_loop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
||||||
let key_handlers: @mut ~[Chan<()>] = @mut ~[];
|
|
||||||
|
|
||||||
let app: Application = ApplicationMethods::new();
|
let app: Application = ApplicationMethods::new();
|
||||||
let window: @mut Window = WindowMethods::new(&app);
|
let window: @mut Window = WindowMethods::new(&app);
|
||||||
|
let resize_rate_limiter = @mut ResizeRateLimiter(script_chan.clone());
|
||||||
|
|
||||||
let surfaces = @mut SurfaceSet(opts.render_backend);
|
let surfaces = @mut SurfaceSet::new(opts.render_backend);
|
||||||
|
let context = rendergl::init_render_context();
|
||||||
let context = layers::rendergl::init_render_context();
|
|
||||||
|
|
||||||
// Create an initial layer tree.
|
// Create an initial layer tree.
|
||||||
//
|
//
|
||||||
// TODO: There should be no initial layer tree until the renderer creates one from the display
|
// TODO: There should be no initial layer tree until the renderer creates one from the display
|
||||||
// list. This is only here because we don't have that logic in the renderer yet.
|
// list. This is only here because we don't have that logic in the renderer yet.
|
||||||
let root_layer = @mut layers::layers::ContainerLayer();
|
let root_layer = @mut ContainerLayer();
|
||||||
let original_layer_transform;
|
let original_layer_transform;
|
||||||
{
|
{
|
||||||
let image_data = @layers::layers::BasicImageData::new(Size2D(0u, 0u),
|
let image_data = @BasicImageData::new(Size2D(0, 0), 0, RGB24Format, ~[]);
|
||||||
0,
|
|
||||||
layers::layers::RGB24Format,
|
|
||||||
~[]);
|
|
||||||
let image = @mut Image::new(image_data as @ImageData);
|
let image = @mut Image::new(image_data as @ImageData);
|
||||||
let image_layer = @mut layers::layers::ImageLayer(image);
|
let image_layer = @mut ImageLayer(image);
|
||||||
original_layer_transform = image_layer.common.transform;
|
original_layer_transform = image_layer.common.transform;
|
||||||
image_layer.common.set_transform(original_layer_transform.scale(800.0, 600.0, 1.0));
|
image_layer.common.set_transform(original_layer_transform.scale(800.0, 600.0, 1.0));
|
||||||
root_layer.add_child(layers::layers::ImageLayerKind(image_layer));
|
root_layer.add_child(ImageLayerKind(image_layer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scene = @mut Scene(ContainerLayerKind(root_layer), Size2D(800.0, 600.0), identity());
|
||||||
let scene = @mut layers::scene::Scene(layers::layers::ContainerLayerKind(root_layer),
|
let key_handlers: @mut ~[Chan<()>] = @mut ~[];
|
||||||
Size2D(800.0, 600.0),
|
|
||||||
identity());
|
|
||||||
|
|
||||||
let done = @mut false;
|
let done = @mut false;
|
||||||
let resize_rate_limiter = @mut ResizeRateLimiter(script_chan.clone());
|
|
||||||
|
// 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() = || {
|
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();
|
||||||
|
@ -120,11 +119,15 @@ fn mainloop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
||||||
while po.peek() {
|
while po.peek() {
|
||||||
match po.recv() {
|
match po.recv() {
|
||||||
AddKeyHandler(key_ch) => key_handlers.push(key_ch),
|
AddKeyHandler(key_ch) => key_handlers.push(key_ch),
|
||||||
BeginDrawing(sender) => lend_surface(surfaces, sender),
|
BeginDrawing(sender) => surfaces.lend(sender),
|
||||||
|
Exit => *done = true,
|
||||||
|
|
||||||
Draw(sender, draw_target) => {
|
Draw(sender, draw_target) => {
|
||||||
debug!("osmain: received new frame");
|
debug!("osmain: received new frame");
|
||||||
return_surface(surfaces, draw_target);
|
|
||||||
lend_surface(surfaces, sender);
|
// Perform a buffer swap.
|
||||||
|
surfaces.put_back(draw_target);
|
||||||
|
surfaces.lend(sender);
|
||||||
|
|
||||||
// Iterate over the children of the container layer.
|
// Iterate over the children of the container layer.
|
||||||
let mut current_layer_child = root_layer.first_child;
|
let mut current_layer_child = root_layer.first_child;
|
||||||
|
@ -149,11 +152,11 @@ fn mainloop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
||||||
current_layer_child = match current_layer_child {
|
current_layer_child = match current_layer_child {
|
||||||
None => {
|
None => {
|
||||||
debug!("osmain: adding new image layer");
|
debug!("osmain: adding new image layer");
|
||||||
image_layer = @mut layers::layers::ImageLayer(image);
|
image_layer = @mut ImageLayer(image);
|
||||||
root_layer.add_child(layers::layers::ImageLayerKind(image_layer));
|
root_layer.add_child(ImageLayerKind(image_layer));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(layers::layers::ImageLayerKind(existing_image_layer)) => {
|
Some(ImageLayerKind(existing_image_layer)) => {
|
||||||
image_layer = existing_image_layer;
|
image_layer = existing_image_layer;
|
||||||
image_layer.set_image(image);
|
image_layer.set_image(image);
|
||||||
|
|
||||||
|
@ -166,16 +169,16 @@ fn mainloop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the layer's transform.
|
// Set the layer's transform.
|
||||||
let x = buffer.rect.origin.x as f32;
|
let mut origin = Point2D(buffer.rect.origin.x as f32,
|
||||||
let y = buffer.rect.origin.y as f32;
|
buffer.rect.origin.y as f32);
|
||||||
image_layer.common.set_transform(
|
let transform = original_layer_transform.translate(origin.x,
|
||||||
original_layer_transform.translate(x, y, 0.0)
|
origin.y,
|
||||||
.scale(width as f32, height as f32, 1.0));
|
0.0);
|
||||||
|
let transform = transform.scale(width as f32, height as f32, 1.0);
|
||||||
|
image_layer.common.set_transform(transform)
|
||||||
}
|
}
|
||||||
surfaces.front.layer_buffer_set.buffers = buffers;
|
|
||||||
}
|
surfaces.front.layer_buffer_set.buffers = buffers
|
||||||
Exit => {
|
|
||||||
*done = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,11 +186,12 @@ fn mainloop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
||||||
|
|
||||||
do window.set_composite_callback {
|
do window.set_composite_callback {
|
||||||
do time::time(~"compositing") {
|
do time::time(~"compositing") {
|
||||||
|
debug!("compositor: compositing");
|
||||||
// Adjust the layer dimensions as necessary to correspond to the size of the window.
|
// Adjust the layer dimensions as necessary to correspond to the size of the window.
|
||||||
scene.size = window.size();
|
scene.size = window.size();
|
||||||
|
|
||||||
// Render the scene.
|
// Render the scene.
|
||||||
layers::rendergl::render_scene(context, scene);
|
rendergl::render_scene(context, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.present();
|
window.present();
|
||||||
|
@ -205,6 +209,19 @@ fn mainloop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
||||||
script_chan.send(LoadMsg(url::make_url(url_string.to_str(), None)))
|
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.
|
// Enter the main event loop.
|
||||||
while !*done {
|
while !*done {
|
||||||
// Check for new messages coming from the rendering task.
|
// Check for new messages coming from the rendering task.
|
||||||
|
@ -230,11 +247,20 @@ struct SurfaceSet {
|
||||||
back: Surface,
|
back: Surface,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lend_surface(surfaces: &mut SurfaceSet, receiver: Chan<LayerBufferSet>) {
|
impl SurfaceSet {
|
||||||
|
/// Creates a new surface set.
|
||||||
|
fn new(backend: BackendType) -> SurfaceSet {
|
||||||
|
SurfaceSet {
|
||||||
|
front: Surface::new(backend),
|
||||||
|
back: Surface::new(backend),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lend(&mut self, receiver: Chan<LayerBufferSet>) {
|
||||||
// We are in a position to lend out the surface?
|
// We are in a position to lend out the surface?
|
||||||
assert!(surfaces.front.have);
|
assert!(self.front.have);
|
||||||
// Ok then take it
|
// Ok then take it
|
||||||
let old_layer_buffers = util::replace(&mut surfaces.front.layer_buffer_set.buffers, ~[]);
|
let old_layer_buffers = util::replace(&mut self.front.layer_buffer_set.buffers, ~[]);
|
||||||
let new_layer_buffers = do old_layer_buffers.map |layer_buffer| {
|
let new_layer_buffers = do old_layer_buffers.map |layer_buffer| {
|
||||||
let draw_target_ref = &layer_buffer.draw_target;
|
let draw_target_ref = &layer_buffer.draw_target;
|
||||||
let layer_buffer = LayerBuffer {
|
let layer_buffer = LayerBuffer {
|
||||||
|
@ -245,32 +271,28 @@ fn lend_surface(surfaces: &mut SurfaceSet, receiver: Chan<LayerBufferSet>) {
|
||||||
debug!("osmain: lending surface %?", layer_buffer);
|
debug!("osmain: lending surface %?", layer_buffer);
|
||||||
layer_buffer
|
layer_buffer
|
||||||
};
|
};
|
||||||
surfaces.front.layer_buffer_set.buffers = old_layer_buffers;
|
self.front.layer_buffer_set.buffers = old_layer_buffers;
|
||||||
|
|
||||||
let new_layer_buffer_set = LayerBufferSet { buffers: new_layer_buffers };
|
let new_layer_buffer_set = LayerBufferSet { buffers: new_layer_buffers };
|
||||||
receiver.send(new_layer_buffer_set);
|
receiver.send(new_layer_buffer_set);
|
||||||
// Now we don't have it
|
// Now we don't have it
|
||||||
surfaces.front.have = false;
|
self.front.have = false;
|
||||||
// But we (hopefully) have another!
|
// But we (hopefully) have another!
|
||||||
util::swap(&mut surfaces.front, &mut surfaces.back);
|
util::swap(&mut self.front, &mut self.back);
|
||||||
// Let's look
|
// Let's look
|
||||||
assert!(surfaces.front.have);
|
assert!(self.front.have);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn return_surface(surfaces: &mut SurfaceSet, layer_buffer_set: LayerBufferSet) {
|
fn put_back(&mut self, layer_buffer_set: LayerBufferSet) {
|
||||||
//#debug("osmain: returning surface %?", layer_buffer_set);
|
|
||||||
// We have room for a return
|
// We have room for a return
|
||||||
assert!(surfaces.front.have);
|
assert!(self.front.have);
|
||||||
assert!(!surfaces.back.have);
|
assert!(!self.back.have);
|
||||||
|
|
||||||
surfaces.back.layer_buffer_set = layer_buffer_set;
|
self.back.layer_buffer_set = layer_buffer_set;
|
||||||
|
|
||||||
// Now we have it again
|
// Now we have it again
|
||||||
surfaces.back.have = true;
|
self.back.have = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SurfaceSet(backend: BackendType) -> SurfaceSet {
|
|
||||||
SurfaceSet { front: Surface(backend), back: Surface(backend) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Surface {
|
struct Surface {
|
||||||
|
@ -278,9 +300,10 @@ struct Surface {
|
||||||
have: bool,
|
have: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Surface(backend: BackendType) -> Surface {
|
impl Surface {
|
||||||
|
fn new(backend: BackendType) -> Surface {
|
||||||
let layer_buffer = LayerBuffer {
|
let layer_buffer = LayerBuffer {
|
||||||
draw_target: DrawTarget::new(backend, Size2D(800i32, 600i32), B8G8R8A8),
|
draw_target: DrawTarget::new(backend, Size2D(800, 600), B8G8R8A8),
|
||||||
rect: Rect(Point2D(0u, 0u), Size2D(800u, 600u)),
|
rect: Rect(Point2D(0u, 0u), Size2D(800u, 600u)),
|
||||||
stride: 800 * 4
|
stride: 800 * 4
|
||||||
};
|
};
|
||||||
|
@ -292,6 +315,7 @@ fn Surface(backend: BackendType) -> Surface {
|
||||||
have: true
|
have: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A function for spawning into the platform's main thread.
|
/// A function for spawning into the platform's main thread.
|
||||||
fn on_osmain<T: Owned>(f: ~fn(po: Port<T>)) -> Chan<T> {
|
fn on_osmain<T: Owned>(f: ~fn(po: Port<T>)) -> Chan<T> {
|
||||||
|
|
|
@ -8,8 +8,11 @@
|
||||||
/// 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, ResizeCallback};
|
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 geom::size::Size2D;
|
||||||
use glut::glut::{DOUBLE, WindowHeight, WindowWidth};
|
use glut::glut::{DOUBLE, WindowHeight, WindowWidth};
|
||||||
use glut::glut;
|
use glut::glut;
|
||||||
|
@ -32,6 +35,9 @@ pub struct Window {
|
||||||
composite_callback: Option<CompositeCallback>,
|
composite_callback: Option<CompositeCallback>,
|
||||||
resize_callback: Option<ResizeCallback>,
|
resize_callback: Option<ResizeCallback>,
|
||||||
load_url_callback: Option<LoadUrlCallback>,
|
load_url_callback: Option<LoadUrlCallback>,
|
||||||
|
scroll_callback: Option<ScrollCallback>,
|
||||||
|
|
||||||
|
drag_origin: Point2D<c_int>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowMethods<Application> for Window {
|
impl WindowMethods<Application> for Window {
|
||||||
|
@ -48,6 +54,9 @@ impl WindowMethods<Application> for Window {
|
||||||
composite_callback: None,
|
composite_callback: None,
|
||||||
resize_callback: None,
|
resize_callback: None,
|
||||||
load_url_callback: None,
|
load_url_callback: None,
|
||||||
|
scroll_callback: None,
|
||||||
|
|
||||||
|
drag_origin: Point2D(0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register event handlers.
|
// Register event handlers.
|
||||||
|
@ -67,6 +76,12 @@ 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| {
|
||||||
|
window.start_drag(x, y)
|
||||||
|
}
|
||||||
|
do glut::motion_func |x, y| {
|
||||||
|
window.continue_drag(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
window
|
window
|
||||||
}
|
}
|
||||||
|
@ -97,10 +112,20 @@ impl WindowMethods<Application> for Window {
|
||||||
self.load_url_callback = Some(new_load_url_callback)
|
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.
|
/// Spins the event loop.
|
||||||
pub fn check_loop(@mut self) {
|
pub fn check_loop(@mut self) {
|
||||||
glut::check_loop()
|
glut::check_loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Schedules a redisplay.
|
||||||
|
pub fn set_needs_display(@mut self) {
|
||||||
|
glut::post_redisplay()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
@ -112,11 +137,38 @@ 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.
|
/// Helper function to pop up an alert box prompting the user to load a URL.
|
||||||
fn load_url(&self) {
|
fn load_url(&self) {
|
||||||
match self.load_url_callback {
|
match self.load_url_callback {
|
||||||
None => error!("no URL callback registered, doing nothing"),
|
None => error!("no URL callback registered, doing nothing"),
|
||||||
Some(callback) => callback("http://purple.com/"),
|
Some(callback) => {
|
||||||
|
let mut alert: Alert = AlertMethods::new("Navigate to:");
|
||||||
|
alert.add_prompt();
|
||||||
|
alert.run();
|
||||||
|
let value = alert.prompt_value();
|
||||||
|
if "" == value { // To avoid crashing on Linux.
|
||||||
|
callback("http://purple.com/")
|
||||||
|
} else {
|
||||||
|
callback(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#[license = "MPL"];
|
#[license = "MPL"];
|
||||||
#[crate_type = "lib"];
|
#[crate_type = "lib"];
|
||||||
|
|
||||||
|
extern mod alert;
|
||||||
extern mod azure;
|
extern mod azure;
|
||||||
extern mod geom;
|
extern mod geom;
|
||||||
extern mod gfx (name = "servo_gfx");
|
extern mod gfx (name = "servo_gfx");
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
|
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
|
||||||
|
|
||||||
|
use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
|
||||||
/// Type of the function that is called when the screen is to be redisplayed.
|
/// 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.
|
/// Type of the function that is called when a new URL is to be loaded.
|
||||||
pub type LoadUrlCallback = @fn(&str);
|
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.
|
/// Methods for an abstract Application.
|
||||||
pub trait ApplicationMethods {
|
pub trait ApplicationMethods {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
|
@ -34,8 +38,12 @@ pub trait WindowMethods<A> {
|
||||||
pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback);
|
pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback);
|
||||||
/// Registers a callback to run when a new URL is to be loaded.
|
/// 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);
|
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.
|
/// Spins the event loop.
|
||||||
pub fn check_loop(@mut self);
|
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
src/support/alert/rust-alert
Submodule
1
src/support/alert/rust-alert
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 0cba81aab4858442e9a995cf3b0149d0d116627c
|
|
@ -1 +1 @@
|
||||||
Subproject commit 60036bce5d9962777467b6763c8642d9ce294cc7
|
Subproject commit af960707afc666ac38591f1f0545f18a1bb89471
|
Loading…
Add table
Add a link
Reference in a new issue