diff options
author | Jack Moffitt <jack@metajack.im> | 2013-07-04 12:53:48 -0600 |
---|---|---|
committer | Jack Moffitt <jack@metajack.im> | 2013-07-04 12:54:30 -0600 |
commit | e0e5e1a2a7c33d265e1995a02211a8926980ce82 (patch) | |
tree | cda850c00115d59af0be4b57d27fa9fa4150ac7e | |
parent | 39e759fb20582f257f04bf3f99429cfb8adcb2e0 (diff) | |
download | servo-e0e5e1a2a7c33d265e1995a02211a8926980ce82.tar.gz servo-e0e5e1a2a7c33d265e1995a02211a8926980ce82.zip |
Replace glut with glfw.
Also fixes initial window size to get based on the windowing code instead of
being hardcoded everywhere. This code works on HiDPI displays, but does not
appropriately scale the output up yet.
-rw-r--r-- | mk/sub.mk | 9 | ||||
-rw-r--r-- | src/components/main/compositing/mod.rs | 41 | ||||
-rw-r--r-- | src/components/main/pipeline.rs | 5 | ||||
-rw-r--r-- | src/components/main/platform/common/glfw_windowing.rs (renamed from src/components/main/platform/common/glut_windowing.rs) | 145 | ||||
-rw-r--r-- | src/components/main/platform/mod.rs | 4 | ||||
-rwxr-xr-x | src/components/main/servo.rc | 2 | ||||
-rw-r--r-- | src/components/main/windowing.rs | 2 | ||||
-rw-r--r-- | src/components/script/script_task.rs | 11 | ||||
m--------- | src/support/azure/rust-azure | 0 | ||||
m--------- | src/support/layers/rust-layers | 0 | ||||
m--------- | src/support/skia/skia | 0 |
11 files changed, 113 insertions, 106 deletions
diff --git a/mk/sub.mk b/mk/sub.mk index f0a66c2825a..79f67e72954 100644 --- a/mk/sub.mk +++ b/mk/sub.mk @@ -29,6 +29,7 @@ NATIVE_BUILDS += \ skia \ nss \ nspr \ + glfw \ $(NULL) # NOTE: the make magic can only compute transitive build dependencies, @@ -40,18 +41,22 @@ NATIVE_BUILDS += \ DEPS_rust-azure += \ rust-opengles \ rust-layers \ - rust-glut \ rust-geom \ + glfw-rs \ + glfw \ skia \ $(NULL) +DEPS_glfw-rs += \ + glfw \ + $(NULL) + DEPS_rust-glut += \ rust-opengles \ $(NULL) DEPS_rust-layers += \ rust-geom \ - rust-glut \ rust-opengles \ $(NULL) diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs index ebd1a81636f..2dc4794a420 100644 --- a/src/components/main/compositing/mod.rs +++ b/src/components/main/compositing/mod.rs @@ -23,6 +23,8 @@ use std::comm; use std::comm::{Chan, SharedChan, Port}; use std::num::Orderable; use std::task; +use extra::uv_global_loop; +use extra::timer; use geom::matrix::identity; use geom::point::Point2D; use geom::size::Size2D; @@ -80,15 +82,24 @@ impl CompositorChan { chan: SharedChan::new(chan), } } + pub fn send(&self, msg: Msg) { self.chan.send(msg); } + + pub fn get_size(&self) -> Size2D<int> { + let (port, chan) = comm::stream(); + self.chan.send(GetSize(chan)); + port.recv() + } } /// Messages to the compositor. pub enum Msg { /// Requests that the compositor shut down. Exit, + /// Requests the window size + GetSize(Chan<Size2D<int>>), /// Requests the compositors GL context. GetGLContext(Chan<AzGLContext>), /// Requests that the compositor paint the given layer buffer set for the given page size. @@ -169,15 +180,18 @@ impl CompositorTask { // list. This is only here because we don't have that logic in the renderer yet. let context = rendergl::init_render_context(); let root_layer = @mut ContainerLayer(); - let scene = @mut Scene(ContainerLayerKind(root_layer), Size2D(800.0f32, 600.0), identity()); + let window_size = window.size(); + let scene = @mut Scene(ContainerLayerKind(root_layer), window_size, identity()); let done = @mut false; + let recomposite = @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 page_size = @mut Size2D(0f32, 0f32); - let window_size = @mut Size2D(800, 600); + let window_size = @mut Size2D(window_size.width as int, + window_size.height as int); // Keeps track of the current zoom factor let world_zoom = @mut 1f32; @@ -271,6 +285,11 @@ impl CompositorTask { response_chan.send(CompositorAck(new_pipeline_id)); } + GetSize(chan) => { + let size = window.size(); + chan.send(Size2D(size.width as int, size.height as int)); + } + GetGLContext(chan) => chan.send(current_gl_context()), Paint(id, new_layer_buffer_set, new_size) => { @@ -343,14 +362,14 @@ impl CompositorTask { // TODO: Recycle the old buffers; send them back to the renderer to reuse if // it wishes. - window.set_needs_display(); + *recomposite = true; } } } }; let profiler_chan = self.profiler_chan.clone(); - do window.set_composite_callback { + let composite = || { do profile(time::CompositingCategory, profiler_chan.clone()) { debug!("compositor: compositing"); // Adjust the layer dimensions as necessary to correspond to the size of the window. @@ -361,7 +380,7 @@ impl CompositorTask { } window.present(); - } + }; // When the user scrolls, move the layer around. do window.set_scroll_callback |delta| { @@ -390,7 +409,7 @@ impl CompositorTask { root_layer.common.set_transform(scroll_transform); - window.set_needs_display() + *recomposite = true; } @@ -429,8 +448,7 @@ impl CompositorTask { 0.0); root_layer.common.set_transform(zoom_transform); - - window.set_needs_display() + *recomposite = true; } // Enter the main event loop. @@ -440,6 +458,13 @@ impl CompositorTask { // Check for messages coming from the windowing system. window.check_loop(); + + if *recomposite { + *recomposite = false; + composite(); + } + + timer::sleep(&uv_global_loop::get(), 100); } self.shutdown_chan.send(()) diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs index ab9ccc6cade..42f76d1b537 100644 --- a/src/components/main/pipeline.rs +++ b/src/components/main/pipeline.rs @@ -57,13 +57,14 @@ impl Pipeline { profiler_chan); ScriptTask::create(id, - compositor_chan, + compositor_chan.clone(), layout_chan.clone(), script_port, script_chan.clone(), constellation_chan, resource_task, - image_cache_task); + image_cache_task, + compositor_chan.get_size()); Pipeline::new(id, script_chan, diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glfw_windowing.rs index 95fd22d9ef4..4aadfea486b 100644 --- a/src/components/main/platform/common/glut_windowing.rs +++ b/src/components/main/platform/common/glfw_windowing.rs @@ -2,10 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -//! A windowing implementation using GLUT. -/// -/// GLUT is a very old and bare-bones toolkit. However, it has good cross-platform support, at -/// least on desktops. It is designed for testing Servo without the need of a UI. +//! A windowing implementation using GLFW. use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, MouseCallback}; use windowing::{ResizeCallback, ScrollCallback, WindowMethods, WindowMouseEvent, WindowClickEvent}; @@ -17,10 +14,8 @@ use geom::point::Point2D; use geom::size::Size2D; use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState}; use servo_msg::compositor_msg::{FinishedLoading, Loading, PerformingLayout, ReadyState}; -use glut::glut::{ACTIVE_CTRL, ACTIVE_SHIFT, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight}; -use glut::glut::WindowWidth; -use glut::glut; -use glut::machack; + +use glfw; static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' ]; @@ -29,15 +24,21 @@ pub struct Application; impl ApplicationMethods for Application { pub fn new() -> Application { - glut::init(); - glut::init_display_mode(DOUBLE); + glfw::private::WindowDataMap::init(); + unsafe { glfw::ll::glfwInit(); } Application } } +impl Drop for Application { + fn finalize(&self) { + unsafe { glfw::ll::glfwTerminate(); } + } +} + /// The type of a window. pub struct Window { - glut_window: glut::Window, + glfw_window: glfw::Window, composite_callback: Option<CompositeCallback>, resize_callback: Option<ResizeCallback>, @@ -60,13 +61,13 @@ pub struct Window { impl WindowMethods<Application> for Window { /// Creates a new window. pub fn new(_: &Application) -> @mut Window { - // Create the GLUT window. - unsafe { glut::glutInitWindowSize(800, 600); } - let glut_window = glut::create_window(~"Servo"); + // Create the GLFW window. + let glfw_window = glfw::Window::create(800, 600, "Servo", glfw::Windowed).unwrap(); + glfw_window.make_context_current(); // Create our window object. let window = @mut Window { - glut_window: glut_window, + glfw_window: glfw_window, composite_callback: None, resize_callback: None, @@ -86,68 +87,51 @@ impl WindowMethods<Application> for Window { throbber_frame: 0, }; - // Spin the event loop every 50 ms to allow the Rust channels to be polled. - // - // This requirement is pretty much the nail in the coffin for GLUT's usefulness. - // - // FIXME(pcwalton): What a mess. - let register_timer_callback: @mut @fn() = @mut ||{}; - *register_timer_callback = || { - glut::timer_func(50, *register_timer_callback); - window.throbber_frame = (window.throbber_frame + 1) % (THROBBER.len() as u8); - window.update_window_title() - }; - // Register event handlers. - do glut::reshape_func(window.glut_window) |width, height| { + do window.glfw_window.set_framebuffer_size_callback |_win, width, height| { match window.resize_callback { None => {} Some(callback) => callback(width as uint, height as uint), } } - do glut::display_func { + do window.glfw_window.set_refresh_callback |_win| { // FIXME(pcwalton): This will not work with multiple windows. match window.composite_callback { None => {} Some(callback) => callback(), } + window.present(); } - do glut::keyboard_func |key, _, _| { - window.handle_key(key) + do window.glfw_window.set_key_callback |_win, key, _scancode, action, mods| { + if action == glfw::PRESS { + window.handle_key(key, mods) + } } - do glut::mouse_func |button, state, x, y| { + do window.glfw_window.set_mouse_button_callback |win, button, action, _mods| { + let (x, y) = win.get_cursor_pos(); if button < 3 { - window.handle_mouse(button, state, x, y); + window.handle_mouse(button, action, x as i32, y as i32); } } - do glut::mouse_wheel_func |wheel, direction, _x, _y| { - let delta = if HAVE_PRECISE_MOUSE_WHEEL { - (direction as f32) / 10000.0 - } else { - (direction as f32) * 30.0 - }; - - match wheel { - 1 => window.handle_scroll(Point2D(delta, 0.0)), - 2 => window.handle_zoom(delta), - _ => window.handle_scroll(Point2D(0.0, delta)), - } + do window.glfw_window.set_scroll_callback |_win, x_offset, y_offset| { + let dx = (x_offset as f32) * 30.0; + let dy = (y_offset as f32) * 30.0; + + window.handle_scroll(Point2D(dx, dy)); } - (*register_timer_callback)(); - - machack::perform_scroll_wheel_hack(); window } /// Returns the size of the window. pub fn size(&self) -> Size2D<f32> { - Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32) + let (width, height) = self.glfw_window.get_framebuffer_size(); + Size2D(width as f32, height as f32) } /// Presents the window to the screen (perhaps by page flipping). pub fn present(&mut self) { - glut::swap_buffers(); + self.glfw_window.swap_buffers(); } /// Registers a callback to run when a composite event occurs. @@ -187,12 +171,9 @@ impl WindowMethods<Application> for Window { /// 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() + glfw::poll_events(); + self.throbber_frame = (self.throbber_frame + 1) % (THROBBER.len() as u8); + self.update_window_title(); } /// Sets the ready state. @@ -214,71 +195,65 @@ impl Window { let throbber = THROBBER[self.throbber_frame]; match self.ready_state { Loading => { - glut::set_window_title(self.glut_window, fmt!("%c Loading — Servo", throbber)) + self.glfw_window.set_title(fmt!("%c Loading — Servo", throbber)) } PerformingLayout => { - glut::set_window_title(self.glut_window, - fmt!("%c Performing Layout — Servo", throbber)) + self.glfw_window.set_title(fmt!("%c Performing Layout — Servo", throbber)) } FinishedLoading => { match self.render_state { RenderingRenderState => { - glut::set_window_title(self.glut_window, - fmt!("%c Rendering — Servo", throbber)) + self.glfw_window.set_title(fmt!("%c Rendering — Servo", throbber)) } - IdleRenderState => glut::set_window_title(self.glut_window, "Servo"), + IdleRenderState => self.glfw_window.set_title("Servo"), } } } } /// Helper function to handle keyboard events. - fn handle_key(&self, key: u8) { - debug!("got key: %?", key); - let modifiers = glut::get_modifiers(); + fn handle_key(&self, key: c_int, mods: c_int) { match key { - 12 => self.load_url(), // Ctrl+L - 31 if (modifiers & ACTIVE_CTRL) != 0 => { // Ctrl+- + glfw::KEY_L if mods & glfw::MOD_CONTROL != 0 => self.load_url(), // Ctrl+L + glfw::KEY_EQUAL if mods & glfw::MOD_CONTROL != 0 => { // Ctrl-+ + for self.zoom_callback.iter().advance |&callback| { + callback(1.1); + } + } + glfw::KEY_MINUS if mods & glfw::MOD_CONTROL != 0 => { // Ctrl-- for self.zoom_callback.iter().advance |&callback| { - callback(-0.1); + callback(0.90909090909); } } - 127 => { + glfw::KEY_BACKSPACE if mods & glfw::MOD_SHIFT != 0 => { // Shift-Backspace for self.navigation_callback.iter().advance |&callback| { - if (modifiers & ACTIVE_SHIFT) != 0 { // Shift+Backspace - callback(Forward); - } - else { - callback(Back); - } + callback(Forward); } } - c => match c as char { - '=' if (modifiers & ACTIVE_CTRL) != 0 => { // Ctrl++ - for self.zoom_callback.iter().advance |&callback| { - callback(0.1); - } + glfw::KEY_BACKSPACE => { // Backspace + for self.navigation_callback.iter().advance |&callback| { + callback(Back); } - _ => {} } + _ => {} } } /// Helper function to handle a click - fn handle_mouse(&self, button: c_int, state: c_int, x: c_int, y: c_int) { + fn handle_mouse(&self, button: c_int, action: c_int, x: c_int, y: c_int) { // FIXME(tkuehn): max pixel dist should be based on pixel density let max_pixel_dist = 10f; match self.mouse_callback { None => {} Some(callback) => { let event: WindowMouseEvent; - match state { - glut::MOUSE_DOWN => { + match action { + glfw::PRESS => { event = WindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32)); *self.mouse_down_point = Point2D(x, y); *self.mouse_down_button = button; } - glut::MOUSE_UP => { + glfw::RELEASE => { event = WindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32)); if *self.mouse_down_button == button { let pixel_dist = *self.mouse_down_point - Point2D(x, y); diff --git a/src/components/main/platform/mod.rs b/src/components/main/platform/mod.rs index fdbd3bf42d9..3467234d0e6 100644 --- a/src/components/main/platform/mod.rs +++ b/src/components/main/platform/mod.rs @@ -5,13 +5,13 @@ //! Platform-specific functionality for Servo. #[cfg(not(shared_gl_windowing))] -pub use platform::common::glut_windowing::{Application, Window}; +pub use platform::common::glfw_windowing::{Application, Window}; #[cfg(shared_gl_windowing)] pub use platform::common::shared_gl_windowing::{Application, Window}; pub mod common { #[cfg(not(shared_gl_windowing))] - pub mod glut_windowing; + pub mod glfw_windowing; #[cfg(shared_gl_windowing)] pub mod shared_gl_windowing; } diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc index 3ee37198619..424e90b33f3 100755 --- a/src/components/main/servo.rc +++ b/src/components/main/servo.rc @@ -15,7 +15,7 @@ extern mod alert; extern mod azure; extern mod geom; extern mod gfx (name = "gfx"); -extern mod glut; +extern mod glfw; extern mod http_client; extern mod js; extern mod layers; diff --git a/src/components/main/windowing.rs b/src/components/main/windowing.rs index 8a102c055c4..edf4bd3800f 100644 --- a/src/components/main/windowing.rs +++ b/src/components/main/windowing.rs @@ -70,8 +70,6 @@ pub trait WindowMethods<A> { /// 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); /// Sets the ready state of the current page. pub fn set_ready_state(@mut self, ready_state: ReadyState); /// Sets the render state of the current page. diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 4d46b241b3c..e6d2ef28436 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -183,7 +183,8 @@ impl ScriptTask { script_chan: ScriptChan, constellation_chan: ConstellationChan, resource_task: ResourceTask, - img_cache_task: ImageCacheTask) + img_cache_task: ImageCacheTask, + initial_size: Size2D<int>) -> @mut ScriptTask { let js_runtime = js::rust::rt(); let js_context = js_runtime.cx(); @@ -219,7 +220,7 @@ impl ScriptTask { root_frame: None, - window_size: Size2D(800u, 600), + window_size: Size2D(initial_size.width as uint, initial_size.height as uint), damage: None, last_loaded_url: None, @@ -253,7 +254,8 @@ impl ScriptTask { script_chan: ScriptChan, constellation_chan: ConstellationChan, resource_task: ResourceTask, - image_cache_task: ImageCacheTask) { + image_cache_task: ImageCacheTask, + initial_size: Size2D<int>) { let compositor = Cell::new(compositor); let script_port = Cell::new(script_port); // FIXME: rust#6399 @@ -267,7 +269,8 @@ impl ScriptTask { script_chan.clone(), constellation_chan.clone(), resource_task.clone(), - image_cache_task.clone()); + image_cache_task.clone(), + initial_size); script_task.start(); } } diff --git a/src/support/azure/rust-azure b/src/support/azure/rust-azure -Subproject 6daaffe3b6cf226c6da4979d0fb907a8258b028 +Subproject d265202c324d566a52d5946e08ad148dcf06825 diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers -Subproject a1454f07d3df11b16dc88bedf79d20693bfc3bb +Subproject 41b967cf1a1bf91227a4e8ee52c82a228eeb7e9 diff --git a/src/support/skia/skia b/src/support/skia/skia -Subproject 3f41e98925b9d4c0d4074046388e73f0e0032ab +Subproject f889ab32a6fc249b2a8667a7c7c1e5c24d5daf7 |