mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
hybrid window system - glut for android and glfw for others
This commit is contained in:
parent
0fd7c651cb
commit
730c10e6aa
3 changed files with 256 additions and 2 deletions
247
src/components/main/platform/common/glut_windowing.rs
Normal file
247
src/components/main/platform/common/glut_windowing.rs
Normal file
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue