aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/platform/common/glut_windowing.rs247
-rw-r--r--src/components/main/platform/mod.rs8
-rwxr-xr-xsrc/components/main/servo.rc3
3 files changed, 256 insertions, 2 deletions
diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glut_windowing.rs
new file mode 100644
index 00000000000..e02bc04d7cb
--- /dev/null
+++ b/src/components/main/platform/common/glut_windowing.rs
@@ -0,0 +1,247 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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.
+
+use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
+use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
+use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
+use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
+use windowing::{Forward, Back};
+
+use alert::{Alert, AlertMethods};
+use std::libc::c_int;
+use geom::point::Point2D;
+use geom::size::Size2D;
+use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
+use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
+
+use glut::glut::{ACTIVE_CTRL, ACTIVE_SHIFT, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight};
+use glut::glut::WindowWidth;
+use glut::glut;
+
+static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' ];
+
+/// A structure responsible for setting up and tearing down the entire windowing system.
+pub struct Application;
+
+impl ApplicationMethods for Application {
+ fn new() -> Application {
+ glut::init();
+ glut::init_display_mode(DOUBLE);
+ Application
+ }
+}
+
+impl Drop for Application {
+ fn drop(&self) {
+ }
+}
+
+/// The type of a window.
+pub struct Window {
+ glut_window: glut::Window,
+
+ event_queue: @mut ~[WindowEvent],
+
+ drag_origin: Point2D<c_int>,
+
+ mouse_down_button: @mut c_int,
+ mouse_down_point: @mut Point2D<c_int>,
+
+ ready_state: ReadyState,
+ render_state: RenderState,
+ throbber_frame: u8,
+}
+
+impl WindowMethods<Application> for Window {
+ /// Creates a new window.
+ fn new(_: &Application) -> @mut Window {
+ // Create the GLUT window.
+ unsafe { glut::glutInitWindowSize(800, 600); }
+ let glut_window = glut::create_window(~"Servo");
+
+ // Create our window object.
+ let window = @mut Window {
+ glut_window: glut_window,
+
+ event_queue: @mut ~[],
+
+ drag_origin: Point2D(0 as c_int, 0),
+
+ mouse_down_button: @mut 0,
+ mouse_down_point: @mut Point2D(0 as c_int, 0),
+
+ ready_state: Blank,
+ render_state: IdleRenderState,
+ throbber_frame: 0,
+ };
+
+ let event_queue = window.event_queue;
+
+ // Register event handlers.
+ do glut::reshape_func(window.glut_window) |width, height| {
+ event_queue.push(ResizeWindowEvent(width as uint, height as uint))
+ }
+ do glut::keyboard_func |key, _, _| {
+ window.handle_key(key)
+ }
+ do glut::mouse_func |button, state, x, y| {
+ if button < 3 {
+ window.handle_mouse(button, state, x, y);
+ }
+ else {
+ match button {
+ 3 => {
+ event_queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32)));
+ },
+ 4 => {
+ event_queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32)));
+ },
+ _ => {}
+ }
+ }
+ }
+
+ window
+ }
+
+ /// Returns the size of the window.
+ fn size(&self) -> Size2D<f32> {
+ Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
+ }
+
+ /// Presents the window to the screen (perhaps by page flipping).
+ fn present(&mut self) {
+ glut::swap_buffers();
+ }
+
+ fn recv(@mut self) -> WindowEvent {
+ if !self.event_queue.is_empty() {
+ return self.event_queue.shift()
+ }
+ glut::check_loop();
+ if !self.event_queue.is_empty() {
+ self.event_queue.shift()
+ } else {
+ IdleWindowEvent
+ }
+ }
+
+ /// Sets the ready state.
+ fn set_ready_state(@mut self, ready_state: ReadyState) {
+ self.ready_state = ready_state;
+ //FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily blocked.
+ //self.update_window_title()
+ }
+
+ /// Sets the render state.
+ fn set_render_state(@mut self, render_state: RenderState) {
+ if self.ready_state == FinishedLoading &&
+ self.render_state == RenderingRenderState &&
+ render_state == IdleRenderState {
+ // page loaded
+ self.event_queue.push(FinishedWindowEvent);
+ }
+
+ self.render_state = render_state;
+ //FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily blocked.
+ //self.update_window_title()
+ }
+
+ fn hidpi_factor(@mut self) -> f32 {
+ //FIXME: Do nothing in GLUT now.
+ 0f32
+ }
+}
+
+impl Window {
+ /// Helper function to set the window title in accordance with the ready state.
+ fn update_window_title(&self) {
+ let throbber = THROBBER[self.throbber_frame];
+ match self.ready_state {
+ Blank => {
+ glut::set_window_title(self.glut_window, fmt!("Blank"))
+ }
+ Loading => {
+ glut::set_window_title(self.glut_window, fmt!("%c Loading . Servo", throbber))
+ }
+ PerformingLayout => {
+ glut::set_window_title(self.glut_window, fmt!("%c Performing Layout . Servo", throbber))
+ }
+ FinishedLoading => {
+ match self.render_state {
+ RenderingRenderState => {
+ glut::set_window_title(self.glut_window, fmt!("%c Rendering . Servo", throbber))
+ }
+ IdleRenderState => glut::set_window_title(self.glut_window, "Servo"),
+ }
+ }
+ }
+ }
+
+ /// Helper function to handle keyboard events.
+ fn handle_key(&self, key: u8) {
+ debug!("got key: %?", key);
+ let modifiers = glut::get_modifiers();
+ match key {
+ 42 => self.load_url(),
+ 43 => self.event_queue.push(ZoomWindowEvent(1.1)),
+ 45 => self.event_queue.push(ZoomWindowEvent(0.909090909)),
+ 56 => self.event_queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32))),
+ 50 => self.event_queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32))),
+ 127 => {
+ if (modifiers & ACTIVE_SHIFT) != 0 {
+ self.event_queue.push(NavigationWindowEvent(Forward));
+ }
+ else {
+ self.event_queue.push(NavigationWindowEvent(Back));
+ }
+ }
+ _ => {}
+ }
+ }
+
+ /// Helper function to handle a click
+ fn handle_mouse(&self, button: c_int, state: c_int, x: c_int, y: c_int) {
+ // FIXME(tkuehn): max pixel dist should be based on pixel density
+ let max_pixel_dist = 10f;
+ let event = match state {
+ glut::MOUSE_DOWN => {
+ *self.mouse_down_point = Point2D(x, y);
+ *self.mouse_down_button = button;
+ MouseWindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32))
+ }
+ glut::MOUSE_UP => {
+ if *self.mouse_down_button == button {
+ let pixel_dist = *self.mouse_down_point - Point2D(x, y);
+ let pixel_dist = ((pixel_dist.x * pixel_dist.x +
+ pixel_dist.y * pixel_dist.y) as float).sqrt();
+ if pixel_dist < max_pixel_dist {
+ let click_event = MouseWindowClickEvent(button as uint,
+ Point2D(x as f32, y as f32));
+ self.event_queue.push(MouseWindowEventClass(click_event));
+ }
+ }
+ MouseWindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32))
+ }
+ _ => fail!("I cannot recognize the type of mouse action that occured. :-(")
+ };
+ self.event_queue.push(MouseWindowEventClass(event));
+ }
+
+ /// Helper function to pop up an alert box prompting the user to load a URL.
+ fn load_url(&self) {
+ 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.
+ self.event_queue.push(LoadUrlWindowEvent(~"http://purple.com/"))
+ } else {
+ self.event_queue.push(LoadUrlWindowEvent(value))
+ }
+ }
+}
+
diff --git a/src/components/main/platform/mod.rs b/src/components/main/platform/mod.rs
index 3467234d0e6..7160c692f35 100644
--- a/src/components/main/platform/mod.rs
+++ b/src/components/main/platform/mod.rs
@@ -4,13 +4,17 @@
//! Platform-specific functionality for Servo.
-#[cfg(not(shared_gl_windowing))]
+#[cfg(not(shared_gl_windowing), target_os="android")]
+pub use platform::common::glut_windowing::{Application, Window};
+#[cfg(not(shared_gl_windowing), not(target_os="android"))]
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))]
+ #[cfg(not(shared_gl_windowing), target_os="android")]
+ pub mod glut_windowing;
+ #[cfg(not(shared_gl_windowing), not(target_os="android"))]
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 0fceaf5ab6b..f1fbcfd2a36 100755
--- a/src/components/main/servo.rc
+++ b/src/components/main/servo.rc
@@ -15,8 +15,11 @@ extern mod alert;
extern mod azure;
extern mod geom;
extern mod gfx (name = "gfx");
+#[cfg(not(target_os="android"))]
extern mod glfw;
//extern mod http_client;
+#[cfg(target_os="android")]
+extern mod glut;
extern mod js;
extern mod layers;
extern mod newcss (name = "css");