mirror of
https://github.com/servo/servo.git
synced 2025-09-30 00:29:14 +01:00
ports/cef: Implement accelerated compositing for the CEF port.
This commit is contained in:
parent
315e166cf7
commit
8b2aadc30b
35 changed files with 1746 additions and 642 deletions
2
ports/android/glut_app/Cargo.lock
generated
2
ports/android/glut_app/Cargo.lock
generated
|
@ -327,7 +327,7 @@ source = "git+https://github.com/bjz/gl-rs.git#79cd3b3f9f19aa0e39f6af572fc8673a6
|
|||
[[package]]
|
||||
name = "layers"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/rust-layers#0f6edd58b3b572f2aac97567b752c15db5fa1982"
|
||||
source = "git+https://github.com/servo/rust-layers#63d1093f2a01a6fb9599ea6d932aadf79598451f"
|
||||
dependencies = [
|
||||
"cgl 0.0.1 (git+https://github.com/servo/rust-cgl)",
|
||||
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
||||
|
|
|
@ -19,8 +19,8 @@ use geom::scale_factor::ScaleFactor;
|
|||
use geom::size::TypedSize2D;
|
||||
use layers::geometry::DevicePixel;
|
||||
use layers::platform::surface::NativeGraphicsMetadata;
|
||||
use msg::compositor_msg::{IdlePaintState, PaintState};
|
||||
use msg::compositor_msg::{Blank, ReadyState};
|
||||
use msg::compositor_msg::{Blank, IdlePaintState, PaintState, ReadyState};
|
||||
use msg::constellation_msg::LoadData;
|
||||
use util::geometry::ScreenPx;
|
||||
|
||||
use glut::glut::{ACTIVE_SHIFT, WindowHeight};
|
||||
|
@ -176,19 +176,23 @@ impl WindowMethods for Window {
|
|||
/// Sets the ready state.
|
||||
fn set_ready_state(&self, ready_state: ReadyState) {
|
||||
self.ready_state.set(ready_state);
|
||||
//FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily blocked.
|
||||
//self.update_window_title()
|
||||
// FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily
|
||||
// blocked.
|
||||
//
|
||||
// self.update_window_title()
|
||||
}
|
||||
|
||||
/// Sets the paint state.
|
||||
fn set_paint_state(&self, paint_state: PaintState) {
|
||||
self.paint_state.set(paint_state);
|
||||
//FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily blocked.
|
||||
//self.update_window_title()
|
||||
// FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily
|
||||
// blocked.
|
||||
//
|
||||
// self.update_window_title()
|
||||
}
|
||||
|
||||
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
|
||||
//FIXME: Do nothing in GLUT now.
|
||||
// FIXME: Do nothing in GLUT now.
|
||||
ScaleFactor(1.0)
|
||||
}
|
||||
|
||||
|
@ -198,6 +202,22 @@ impl WindowMethods for Window {
|
|||
display: GetCurrentDisplay(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_page_title(&self, _: Option<String>) {
|
||||
// TODO(pcwalton)
|
||||
}
|
||||
|
||||
fn set_page_load_data(&self, _: LoadData) {
|
||||
// TODO(pcwalton)
|
||||
}
|
||||
|
||||
fn load_end(&self) {
|
||||
// TODO(pcwalton)
|
||||
}
|
||||
|
||||
fn prepare_for_composite(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
|
8
ports/cef/Cargo.lock
generated
8
ports/cef/Cargo.lock
generated
|
@ -3,6 +3,7 @@ name = "embedding"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"azure 0.1.0 (git+https://github.com/servo/rust-azure)",
|
||||
"cocoa 0.1.1 (git+https://github.com/servo/rust-cocoa)",
|
||||
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
||||
"core_text 0.1.0 (git+https://github.com/servo/rust-core-text)",
|
||||
"devtools 0.0.1",
|
||||
|
@ -56,6 +57,11 @@ dependencies = [
|
|||
"gleam 0.0.1 (git+https://github.com/servo/gleam)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/servo/rust-cocoa#084f8e1baf40391eb12819d16765af25ca96c7ec"
|
||||
|
||||
[[package]]
|
||||
name = "compositing"
|
||||
version = "0.0.1"
|
||||
|
@ -358,7 +364,7 @@ source = "git+https://github.com/bjz/gl-rs.git#79cd3b3f9f19aa0e39f6af572fc8673a6
|
|||
[[package]]
|
||||
name = "layers"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/rust-layers#b068d2a96d54bf173b548aece36f5ea4ef9353cf"
|
||||
source = "git+https://github.com/servo/rust-layers#0f6edd58b3b572f2aac97567b752c15db5fa1982"
|
||||
dependencies = [
|
||||
"cgl 0.0.1 (git+https://github.com/servo/rust-cgl)",
|
||||
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
||||
|
|
|
@ -65,3 +65,6 @@ git = "https://github.com/servo/rust-core-graphics"
|
|||
|
||||
[dependencies.core_text]
|
||||
git = "https://github.com/servo/rust-core-text"
|
||||
|
||||
[dependencies.cocoa]
|
||||
git = "https://github.com/servo/rust-cocoa"
|
||||
|
|
|
@ -2,38 +2,90 @@
|
|||
* 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/. */
|
||||
|
||||
use interfaces::{CefBrowser, CefClient, CefRequestContext, cef_browser_t, cef_client_t};
|
||||
use interfaces::{cef_request_context_t};
|
||||
use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t};
|
||||
|
||||
use browser_host::{ServoCefBrowserHost, ServoCefBrowserHostExtensions};
|
||||
use core::{mod, OffScreenGlobals, OnScreenGlobals, globals};
|
||||
use eutil::Downcast;
|
||||
use frame::ServoCefFrame;
|
||||
use interfaces::{CefBrowser, CefBrowserHost, CefClient, CefFrame, CefRequestContext};
|
||||
use interfaces::{cef_browser_t, cef_browser_host_t, cef_client_t, cef_frame_t};
|
||||
use interfaces::{cef_request_context_t};
|
||||
use servo::Browser;
|
||||
use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t};
|
||||
use window;
|
||||
|
||||
use compositing::windowing::{Back, Forward, NavigationWindowEvent};
|
||||
use glfw_app;
|
||||
use libc::c_int;
|
||||
use servo::Browser;
|
||||
use servo_util::opts;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
cef_class_impl! {
|
||||
ServoCefBrowser : CefBrowser, cef_browser_t {
|
||||
fn get_host(&this) -> *mut cef_browser_host_t {
|
||||
this.downcast().host.clone()
|
||||
}
|
||||
|
||||
fn go_back(&_this) -> () {
|
||||
core::send_window_event(NavigationWindowEvent(Back));
|
||||
}
|
||||
|
||||
fn go_forward(&_this) -> () {
|
||||
core::send_window_event(NavigationWindowEvent(Forward));
|
||||
}
|
||||
|
||||
// Returns the main (top-level) frame for the browser window.
|
||||
fn get_main_frame(&this) -> *mut cef_frame_t {
|
||||
this.downcast().frame.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ServoCefBrowser {
|
||||
/// A reference to the browser's primary frame.
|
||||
pub frame: CefFrame,
|
||||
/// A reference to the browser's host.
|
||||
pub host: CefBrowserHost,
|
||||
/// A reference to the browser client.
|
||||
pub client: CefClient,
|
||||
pub servo_browser: RefCell<Option<Browser<glfw_app::window::Window>>>,
|
||||
pub window: RefCell<Option<Rc<glfw_app::window::Window>>>,
|
||||
/// Whether the on-created callback has fired yet.
|
||||
pub callback_executed: Cell<bool>,
|
||||
}
|
||||
|
||||
impl ServoCefBrowser {
|
||||
pub fn new(client: CefClient) -> ServoCefBrowser {
|
||||
pub fn new(window_info: &cef_window_info_t, client: CefClient) -> ServoCefBrowser {
|
||||
let frame = ServoCefFrame::new().as_cef_interface();
|
||||
let host = ServoCefBrowserHost::new(client.clone()).as_cef_interface();
|
||||
if window_info.windowless_rendering_enabled == 0 {
|
||||
let glfw_window = glfw_app::create_window();
|
||||
globals.replace(Some(OnScreenGlobals(RefCell::new(glfw_window.clone()),
|
||||
RefCell::new(Browser::new(Some(glfw_window))))));
|
||||
}
|
||||
|
||||
ServoCefBrowser {
|
||||
frame: frame,
|
||||
host: host,
|
||||
client: client,
|
||||
servo_browser: RefCell::new(None),
|
||||
window: RefCell::new(None),
|
||||
callback_executed: Cell::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cef_class_impl! {
|
||||
ServoCefBrowser : CefBrowser, cef_browser_t {}
|
||||
trait ServoCefBrowserExtensions {
|
||||
fn init(&self, window_info: &cef_window_info_t);
|
||||
}
|
||||
|
||||
impl ServoCefBrowserExtensions for CefBrowser {
|
||||
fn init(&self, window_info: &cef_window_info_t) {
|
||||
if window_info.windowless_rendering_enabled != 0 {
|
||||
let window = window::Window::new();
|
||||
let servo_browser = Browser::new(Some(window.clone()));
|
||||
window.set_browser(self.clone());
|
||||
globals.replace(Some(OffScreenGlobals(RefCell::new(window),
|
||||
RefCell::new(servo_browser))));
|
||||
}
|
||||
|
||||
self.downcast().host.set_browser((*self).clone());
|
||||
}
|
||||
}
|
||||
|
||||
local_data_key!(pub GLOBAL_BROWSERS: RefCell<Vec<CefBrowser>>)
|
||||
|
@ -50,12 +102,16 @@ pub fn browser_callback_after_created(browser: CefBrowser) {
|
|||
browser.downcast().callback_executed.set(true);
|
||||
}
|
||||
|
||||
fn browser_host_create(client: CefClient, callback_executed: bool) -> CefBrowser {
|
||||
fn browser_host_create(window_info: &cef_window_info_t,
|
||||
client: CefClient,
|
||||
callback_executed: bool)
|
||||
-> CefBrowser {
|
||||
let mut urls = Vec::new();
|
||||
urls.push("http://s27.postimg.org/vqbtrolyr/servo.jpg".to_string());
|
||||
let mut opts = opts::default_opts();
|
||||
opts.urls = urls;
|
||||
let browser = ServoCefBrowser::new(client).as_cef_interface();
|
||||
let browser = ServoCefBrowser::new(window_info, client).as_cef_interface();
|
||||
browser.init(window_info);
|
||||
if callback_executed {
|
||||
browser_callback_after_created(browser.clone());
|
||||
}
|
||||
|
@ -73,32 +129,30 @@ fn browser_host_create(client: CefClient, callback_executed: bool) -> CefBrowser
|
|||
}
|
||||
|
||||
cef_static_method_impls! {
|
||||
fn cef_browser_host_create_browser(_window_info: *const cef_window_info_t,
|
||||
fn cef_browser_host_create_browser(window_info: *const cef_window_info_t,
|
||||
client: *mut cef_client_t,
|
||||
_url: *const cef_string_t,
|
||||
_browser_settings: *const cef_browser_settings_t,
|
||||
_request_context: *mut cef_request_context_t)
|
||||
-> c_int {
|
||||
let _window_info: &cef_window_info_t = _window_info;
|
||||
let client: CefClient = client;
|
||||
let _url: &[u16] = _url;
|
||||
let _browser_settings: &cef_browser_settings_t = _browser_settings;
|
||||
let _request_context: CefRequestContext = _request_context;
|
||||
browser_host_create(client, false);
|
||||
browser_host_create(window_info, client, false);
|
||||
1i32
|
||||
}
|
||||
|
||||
fn cef_browser_host_create_browser_sync(_window_info: *const cef_window_info_t,
|
||||
fn cef_browser_host_create_browser_sync(window_info: *const cef_window_info_t,
|
||||
client: *mut cef_client_t,
|
||||
_url: *const cef_string_t,
|
||||
_browser_settings: *const cef_browser_settings_t,
|
||||
_request_context: *mut cef_request_context_t)
|
||||
-> *mut cef_browser_t {
|
||||
let _window_info: &cef_window_info_t = _window_info;
|
||||
let client: CefClient = client;
|
||||
let _url: &[u16] = _url;
|
||||
let _browser_settings: &cef_browser_settings_t = _browser_settings;
|
||||
let _request_context: CefRequestContext = _request_context;
|
||||
browser_host_create(client, true)
|
||||
browser_host_create(window_info, client, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
158
ports/cef/browser_host.rs
Normal file
158
ports/cef/browser_host.rs
Normal file
|
@ -0,0 +1,158 @@
|
|||
/* 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/. */
|
||||
|
||||
use core;
|
||||
use eutil::Downcast;
|
||||
use interfaces::{CefBrowser, CefBrowserHost, CefClient, cef_browser_host_t, cef_client_t};
|
||||
use types::{KEYEVENT_CHAR, KEYEVENT_KEYDOWN, KEYEVENT_KEYUP, KEYEVENT_RAWKEYDOWN, cef_key_event};
|
||||
use types::{cef_mouse_button_type_t, cef_mouse_event, cef_rect_t};
|
||||
|
||||
use compositing::windowing::{InitializeCompositingWindowEvent, KeyEvent, MouseWindowClickEvent};
|
||||
use compositing::windowing::{MouseWindowEventClass, MouseWindowMouseUpEvent, PinchZoomWindowEvent};
|
||||
use compositing::windowing::{ResizeWindowEvent, ScrollWindowEvent};
|
||||
use geom::point::TypedPoint2D;
|
||||
use geom::size::TypedSize2D;
|
||||
use libc::{c_double, c_int};
|
||||
use servo_msg::constellation_msg::{mod, KeyModifiers, Pressed, Released, Repeated};
|
||||
use std::cell::RefCell;
|
||||
|
||||
pub struct ServoCefBrowserHost {
|
||||
/// A reference to the browser.
|
||||
pub browser: RefCell<Option<CefBrowser>>,
|
||||
/// A reference to the client.
|
||||
pub client: CefClient,
|
||||
}
|
||||
|
||||
cef_class_impl! {
|
||||
ServoCefBrowserHost : CefBrowserHost, cef_browser_host_t {
|
||||
fn get_client(&this) -> *mut cef_client_t {
|
||||
this.downcast().client.clone()
|
||||
}
|
||||
|
||||
fn was_resized(&this) -> () {
|
||||
let mut rect = cef_rect_t::zero();
|
||||
this.get_client()
|
||||
.get_render_handler()
|
||||
.get_backing_rect(this.downcast().browser.borrow().clone().unwrap(), &mut rect);
|
||||
let size = TypedSize2D(rect.width as uint, rect.height as uint);
|
||||
core::send_window_event(ResizeWindowEvent(size));
|
||||
core::repaint_synchronously();
|
||||
}
|
||||
|
||||
fn send_key_event(&_this, event: *const cef_key_event) -> () {
|
||||
// FIXME(pcwalton): So awful. But it's nearly midnight here and I have to get
|
||||
// Google working.
|
||||
let event: &cef_key_event = event;
|
||||
let key = match (*event).character as u8 {
|
||||
b'a' | b'A' => constellation_msg::KeyA,
|
||||
b'b' | b'B' => constellation_msg::KeyB,
|
||||
b'c' | b'C' => constellation_msg::KeyC,
|
||||
b'd' | b'D' => constellation_msg::KeyD,
|
||||
b'e' | b'E' => constellation_msg::KeyE,
|
||||
b'f' | b'F' => constellation_msg::KeyF,
|
||||
b'g' | b'G' => constellation_msg::KeyG,
|
||||
b'h' | b'H' => constellation_msg::KeyH,
|
||||
b'i' | b'I' => constellation_msg::KeyI,
|
||||
b'j' | b'J' => constellation_msg::KeyJ,
|
||||
b'k' | b'K' => constellation_msg::KeyK,
|
||||
b'l' | b'L' => constellation_msg::KeyL,
|
||||
b'm' | b'M' => constellation_msg::KeyM,
|
||||
b'n' | b'N' => constellation_msg::KeyN,
|
||||
b'o' | b'O' => constellation_msg::KeyO,
|
||||
b'p' | b'P' => constellation_msg::KeyP,
|
||||
b'q' | b'Q' => constellation_msg::KeyQ,
|
||||
b'r' | b'R' => constellation_msg::KeyR,
|
||||
b's' | b'S' => constellation_msg::KeyS,
|
||||
b't' | b'T' => constellation_msg::KeyT,
|
||||
b'u' | b'U' => constellation_msg::KeyU,
|
||||
b'v' | b'V' => constellation_msg::KeyV,
|
||||
b'w' | b'W' => constellation_msg::KeyW,
|
||||
b'x' | b'X' => constellation_msg::KeyX,
|
||||
b'y' | b'Y' => constellation_msg::KeyY,
|
||||
b'z' | b'Z' => constellation_msg::KeyZ,
|
||||
b'0' => constellation_msg::Key0,
|
||||
b'1' => constellation_msg::Key1,
|
||||
b'2' => constellation_msg::Key2,
|
||||
b'3' => constellation_msg::Key3,
|
||||
b'4' => constellation_msg::Key4,
|
||||
b'5' => constellation_msg::Key5,
|
||||
b'6' => constellation_msg::Key6,
|
||||
b'7' => constellation_msg::Key7,
|
||||
b'8' => constellation_msg::Key8,
|
||||
b'9' => constellation_msg::Key9,
|
||||
b'\n' | b'\r' => constellation_msg::KeyEnter,
|
||||
_ => constellation_msg::KeySpace,
|
||||
};
|
||||
let key_state = match (*event).t {
|
||||
KEYEVENT_RAWKEYDOWN => Pressed,
|
||||
KEYEVENT_KEYDOWN | KEYEVENT_CHAR => Repeated,
|
||||
KEYEVENT_KEYUP => Released,
|
||||
};
|
||||
let key_modifiers = KeyModifiers::empty(); // TODO(pcwalton)
|
||||
core::send_window_event(KeyEvent(key, key_state, key_modifiers))
|
||||
}
|
||||
|
||||
fn send_mouse_click_event(&_this,
|
||||
event: *const cef_mouse_event,
|
||||
mouse_button_type: cef_mouse_button_type_t,
|
||||
mouse_up: c_int,
|
||||
_click_count: c_int)
|
||||
-> () {
|
||||
let event: &cef_mouse_event = event;
|
||||
let button_type = mouse_button_type as uint;
|
||||
let point = TypedPoint2D((*event).x as f32, (*event).y as f32);
|
||||
if mouse_up != 0 {
|
||||
core::send_window_event(MouseWindowEventClass(MouseWindowClickEvent(button_type,
|
||||
point)))
|
||||
} else {
|
||||
core::send_window_event(MouseWindowEventClass(MouseWindowMouseUpEvent(button_type,
|
||||
point)))
|
||||
}
|
||||
}
|
||||
|
||||
fn send_mouse_wheel_event(&_this,
|
||||
event: *const cef_mouse_event,
|
||||
delta_x: c_int,
|
||||
delta_y: c_int)
|
||||
-> () {
|
||||
let event: &cef_mouse_event = event;
|
||||
let delta = TypedPoint2D(delta_x as f32, delta_y as f32);
|
||||
let origin = TypedPoint2D((*event).x as i32, (*event).y as i32);
|
||||
core::send_window_event(ScrollWindowEvent(delta, origin))
|
||||
}
|
||||
|
||||
fn get_zoom_level(&_this) -> c_double {
|
||||
core::pinch_zoom_level() as c_double
|
||||
}
|
||||
|
||||
fn set_zoom_level(&this, new_zoom_level: c_double) -> () {
|
||||
let old_zoom_level = this.get_zoom_level();
|
||||
core::send_window_event(PinchZoomWindowEvent((new_zoom_level / old_zoom_level) as f32))
|
||||
}
|
||||
|
||||
fn initialize_compositing(&_this) -> () {
|
||||
core::send_window_event(InitializeCompositingWindowEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ServoCefBrowserHost {
|
||||
pub fn new(client: CefClient) -> ServoCefBrowserHost {
|
||||
ServoCefBrowserHost {
|
||||
browser: RefCell::new(None),
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ServoCefBrowserHostExtensions {
|
||||
fn set_browser(&self, browser: CefBrowser);
|
||||
}
|
||||
|
||||
impl ServoCefBrowserHostExtensions for CefBrowserHost {
|
||||
fn set_browser(&self, browser: CefBrowser) {
|
||||
*self.downcast().browser.borrow_mut() = Some(browser)
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ pub fn command_line_init(argc: c_int, argv: *const *const u8) {
|
|||
#[no_mangle]
|
||||
pub extern "C" fn command_line_get_switch_value(cmd: *mut cef_command_line_t, name: *const cef_string_t) -> cef_string_userfree_t {
|
||||
if cmd.is_null() || name.is_null() {
|
||||
return cef_string::empty_utf16_string()
|
||||
return cef_string::empty_utf16_userfree_string()
|
||||
}
|
||||
unsafe {
|
||||
//technically cef_string_t can be any type of character size
|
||||
|
@ -67,11 +67,11 @@ pub extern "C" fn command_line_get_switch_value(cmd: *mut cef_command_line_t, na
|
|||
&mut string,
|
||||
1);
|
||||
});
|
||||
return string
|
||||
return cef_string::string_to_userfree_string(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
return cef_string::empty_utf16_string()
|
||||
return cef_string::empty_utf16_userfree_string()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -2,19 +2,43 @@
|
|||
* 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/. */
|
||||
|
||||
use browser::{GLOBAL_BROWSERS, browser_callback_after_created};
|
||||
use command_line::command_line_init;
|
||||
use interfaces::cef_app_t;
|
||||
use eutil::Downcast;
|
||||
use switches::{KPROCESSTYPE, KWAITFORDEBUGGER};
|
||||
use types::{cef_main_args_t, cef_settings_t};
|
||||
use window;
|
||||
|
||||
use compositing::windowing::{IdleWindowEvent, WindowEvent};
|
||||
use geom::size::TypedSize2D;
|
||||
use glfw_app;
|
||||
use libc::funcs::c95::string::strlen;
|
||||
use libc::{c_char, c_int, c_void};
|
||||
use native;
|
||||
use rustrt::local::Local;
|
||||
use servo::Browser;
|
||||
use std::slice;
|
||||
use servo_util::opts;
|
||||
use servo_util::opts::OpenGL;
|
||||
use std::c_str::CString;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::rt;
|
||||
|
||||
const MAX_RENDERING_THREADS: uint = 128;
|
||||
|
||||
// TODO(pcwalton): Get the home page via the CEF API.
|
||||
static HOME_URL: &'static str = "http://s27.postimg.org/vqbtrolyr/servo.jpg";
|
||||
|
||||
// TODO(pcwalton): Support multiple windows.
|
||||
pub enum ServoCefGlobals {
|
||||
OnScreenGlobals(RefCell<Rc<glfw_app::window::Window>>,
|
||||
RefCell<Browser<glfw_app::window::Window>>),
|
||||
OffScreenGlobals(RefCell<Rc<window::Window>>, RefCell<Browser<window::Window>>),
|
||||
}
|
||||
|
||||
local_data_key!(pub globals: ServoCefGlobals)
|
||||
|
||||
local_data_key!(pub message_queue: RefCell<Vec<WindowEvent>>)
|
||||
|
||||
// Copied from `libnative/lib.rs`.
|
||||
static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
|
||||
|
||||
static CEF_API_HASH_UNIVERSAL: &'static [u8] = b"8efd129f4afc344bd04b2feb7f73a149b6c4e27f\0";
|
||||
#[cfg(target_os="windows")]
|
||||
|
@ -26,68 +50,109 @@ static CEF_API_HASH_PLATFORM: &'static [u8] = b"2bc564c3871965ef3a2531b528bda3e1
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
|
||||
_settings: *mut cef_settings_t,
|
||||
settings: *mut cef_settings_t,
|
||||
application: *mut cef_app_t,
|
||||
_windows_sandbox_info: *const c_void)
|
||||
-> c_int {
|
||||
if args.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
rt::init((*args).argc as int, (*args).argv);
|
||||
command_line_init((*args).argc, (*args).argv);
|
||||
(*application).get_browser_process_handler.map(|cb| {
|
||||
let handler = cb(application);
|
||||
if handler.is_not_null() {
|
||||
(*handler).on_context_initialized.map(|hcb| hcb(handler));
|
||||
}
|
||||
});
|
||||
|
||||
if !application.is_null() {
|
||||
(*application).get_browser_process_handler.map(|cb| {
|
||||
let handler = cb(application);
|
||||
if handler.is_not_null() {
|
||||
(*handler).on_context_initialized.map(|hcb| hcb(handler));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
create_rust_task();
|
||||
|
||||
message_queue.replace(Some(RefCell::new(Vec::new())));
|
||||
|
||||
let urls = vec![HOME_URL.to_string()];
|
||||
opts::set_opts(opts::Opts {
|
||||
urls: urls,
|
||||
n_paint_threads: 1,
|
||||
gpu_painting: false,
|
||||
tile_size: 512,
|
||||
device_pixels_per_px: None,
|
||||
time_profiler_period: None,
|
||||
memory_profiler_period: None,
|
||||
enable_experimental: false,
|
||||
nonincremental_layout: false,
|
||||
layout_threads: unsafe {
|
||||
if ((*settings).rendering_threads as uint) < 1 {
|
||||
1
|
||||
} else if (*settings).rendering_threads as uint > MAX_RENDERING_THREADS {
|
||||
MAX_RENDERING_THREADS
|
||||
} else {
|
||||
(*settings).rendering_threads as uint
|
||||
}
|
||||
},
|
||||
output_file: None,
|
||||
headless: false,
|
||||
hard_fail: false,
|
||||
bubble_inline_sizes_separately: false,
|
||||
show_debug_borders: false,
|
||||
show_debug_fragment_borders: false,
|
||||
enable_text_antialiasing: true,
|
||||
trace_layout: false,
|
||||
devtools_port: None,
|
||||
initial_window_size: TypedSize2D(800, 600),
|
||||
profile_tasks: false,
|
||||
user_agent: None,
|
||||
dump_flow_tree: false,
|
||||
validate_display_list_geometry: false,
|
||||
render_api: OpenGL,
|
||||
});
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// Copied from `libnative/lib.rs`.
|
||||
fn create_rust_task() {
|
||||
let something_around_the_top_of_the_stack = 1;
|
||||
let addr = &something_around_the_top_of_the_stack as *const int;
|
||||
let my_stack_top = addr as uint;
|
||||
|
||||
// FIXME #11359 we just assume that this thread has a stack of a
|
||||
// certain size, and estimate that there's at most 20KB of stack
|
||||
// frames above our current position.
|
||||
|
||||
let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;
|
||||
|
||||
let task = native::task::new((my_stack_bottom, my_stack_top), rt::thread::main_guard_page());
|
||||
Local::put(task);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_shutdown() {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_run_message_loop() {
|
||||
native::start(0, 0 as *const *const u8, proc() {
|
||||
GLOBAL_BROWSERS.get().map(|refcellbrowsers| {
|
||||
let browsers = refcellbrowsers.borrow();
|
||||
let mut num = browsers.len();
|
||||
for active_browser in browsers.iter() {
|
||||
*active_browser.downcast().window.borrow_mut() =
|
||||
Some(glfw_app::create_window());
|
||||
*active_browser.downcast().servo_browser.borrow_mut() =
|
||||
Some(Browser::new((*active_browser.downcast()
|
||||
.window
|
||||
.borrow()).clone()));
|
||||
if !active_browser.downcast().callback_executed.get() {
|
||||
browser_callback_after_created((*active_browser).clone());
|
||||
}
|
||||
}
|
||||
while num > 0 {
|
||||
for active_browser in browsers.iter()
|
||||
.filter(|&active_browser| {
|
||||
active_browser.downcast()
|
||||
.servo_browser
|
||||
.borrow()
|
||||
.is_some()
|
||||
}) {
|
||||
let ref mut browser = active_browser.downcast();
|
||||
let mut servobrowser = browser.servo_browser.borrow_mut().take().unwrap();
|
||||
if !servobrowser.handle_event(browser.window
|
||||
.borrow_mut()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.wait_events()) {
|
||||
servobrowser.shutdown();
|
||||
num -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
let mut the_globals = globals.get();
|
||||
let the_globals = the_globals.as_mut().unwrap();
|
||||
match **the_globals {
|
||||
OnScreenGlobals(ref window, ref browser) => {
|
||||
while browser.borrow_mut().handle_event(window.borrow_mut().wait_events()) {}
|
||||
}
|
||||
OffScreenGlobals(ref window, ref browser) => {
|
||||
while browser.borrow_mut().handle_event(window.borrow_mut().wait_events()) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_do_message_loop_work() {
|
||||
send_window_event(IdleWindowEvent)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -95,33 +160,91 @@ pub extern "C" fn cef_quit_message_loop() {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_execute_process(args: *const cef_main_args_t,
|
||||
pub extern "C" fn cef_execute_process(_args: *const cef_main_args_t,
|
||||
_app: *mut cef_app_t,
|
||||
_windows_sandbox_info: *mut c_void)
|
||||
-> c_int {
|
||||
unsafe {
|
||||
if args.is_null() {
|
||||
println!("args must be passed");
|
||||
return -1;
|
||||
}
|
||||
for i in range(0u, (*args).argc as uint) {
|
||||
let u = (*args).argv.offset(i as int) as *const u8;
|
||||
slice::raw::buf_as_slice(u, strlen(u as *const i8) as uint, |s| {
|
||||
if s.starts_with("--".as_bytes()) {
|
||||
if s.slice_from(2) == KWAITFORDEBUGGER.as_bytes() {
|
||||
//FIXME: this is NOT functionally equivalent to chromium!
|
||||
-1
|
||||
}
|
||||
|
||||
//this should be a pause() call with an installed signal
|
||||
//handler callback, something which is impossible now in rust
|
||||
} else if s.slice_from(2) == KPROCESSTYPE.as_bytes() {
|
||||
//TODO: run other process now
|
||||
}
|
||||
}
|
||||
});
|
||||
pub fn send_window_event(event: WindowEvent) {
|
||||
message_queue.get().as_mut().unwrap().borrow_mut().push(event);
|
||||
|
||||
let mut the_globals = globals.get();
|
||||
let the_globals = match the_globals.as_mut() {
|
||||
None => return,
|
||||
Some(the_globals) => the_globals,
|
||||
};
|
||||
loop {
|
||||
match **the_globals {
|
||||
OnScreenGlobals(_, ref browser) => {
|
||||
match browser.try_borrow_mut() {
|
||||
None => {
|
||||
// We're trying to send an event while processing another one. This will
|
||||
// cause general badness, so queue up that event instead of immediately
|
||||
// processing it.
|
||||
break
|
||||
}
|
||||
Some(ref mut browser) => {
|
||||
let event = match message_queue.get()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.borrow_mut()
|
||||
.pop() {
|
||||
None => return,
|
||||
Some(event) => event,
|
||||
};
|
||||
browser.handle_event(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
OffScreenGlobals(_, ref browser) => {
|
||||
match browser.try_borrow_mut() {
|
||||
None => {
|
||||
// We're trying to send an event while processing another one. This will
|
||||
// cause general badness, so queue up that event instead of immediately
|
||||
// processing it.
|
||||
break
|
||||
}
|
||||
Some(ref mut browser) => {
|
||||
let event = match message_queue.get()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.borrow_mut()
|
||||
.pop() {
|
||||
None => return,
|
||||
Some(event) => event,
|
||||
};
|
||||
browser.handle_event(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//process type not specified, must be browser process (NOOP)
|
||||
-1
|
||||
}
|
||||
|
||||
macro_rules! browser_method_delegate(
|
||||
( $( fn $method:ident ( ) -> $return_type:ty ; )* ) => (
|
||||
$(
|
||||
pub fn $method() -> $return_type {
|
||||
let mut the_globals = globals.get();
|
||||
let the_globals = match the_globals.as_mut() {
|
||||
None => panic!("{}: no globals created", stringify!($method)),
|
||||
Some(the_globals) => the_globals,
|
||||
};
|
||||
match **the_globals {
|
||||
OnScreenGlobals(_, ref browser) => browser.borrow_mut().$method(),
|
||||
OffScreenGlobals(_, ref browser) => browser.borrow_mut().$method(),
|
||||
}
|
||||
}
|
||||
)*
|
||||
)
|
||||
)
|
||||
|
||||
browser_method_delegate! {
|
||||
fn repaint_synchronously() -> ();
|
||||
fn pinch_zoom_level() -> f32;
|
||||
fn get_title_for_main_frame() -> ();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -133,6 +256,16 @@ pub extern "C" fn cef_api_hash(entry: c_int) -> *const c_char {
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_log(_file: *const c_char,
|
||||
_line: c_int,
|
||||
_severity: c_int,
|
||||
message: *const c_char) {
|
||||
unsafe {
|
||||
println!("{}", CString::new(message, false))
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_get_min_log_level() -> c_int {
|
||||
0
|
||||
|
|
45
ports/cef/frame.rs
Normal file
45
ports/cef/frame.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* 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/. */
|
||||
|
||||
use eutil::Downcast;
|
||||
use interfaces::{CefFrame, CefStringVisitor, cef_frame_t, cef_string_visitor_t};
|
||||
use types::{cef_string_t, cef_string_userfree_t};
|
||||
|
||||
use core;
|
||||
use compositing::windowing::LoadUrlWindowEvent;
|
||||
use std::cell::RefCell;
|
||||
|
||||
pub struct ServoCefFrame {
|
||||
pub title_visitor: RefCell<Option<CefStringVisitor>>,
|
||||
pub url: RefCell<String>,
|
||||
}
|
||||
|
||||
impl ServoCefFrame {
|
||||
pub fn new() -> ServoCefFrame {
|
||||
ServoCefFrame {
|
||||
title_visitor: RefCell::new(None),
|
||||
url: RefCell::new(String::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cef_class_impl! {
|
||||
ServoCefFrame : CefFrame, cef_frame_t {
|
||||
fn load_url(&this, url: *const cef_string_t) -> () {
|
||||
let this = this.downcast();
|
||||
*this.url.borrow_mut() = String::from_utf16(url).unwrap();
|
||||
core::send_window_event(LoadUrlWindowEvent(String::from_utf16(url).unwrap()));
|
||||
}
|
||||
fn get_url(&this) -> cef_string_userfree_t {
|
||||
let this = this.downcast();
|
||||
(*this.url.borrow()).clone()
|
||||
}
|
||||
fn get_text(&this, visitor: *mut cef_string_visitor_t) -> () {
|
||||
let this = this.downcast();
|
||||
*this.title_visitor.borrow_mut() = Some(visitor);
|
||||
core::get_title_for_main_frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,11 +14,12 @@ extern crate log;
|
|||
extern crate "plugins" as servo_plugins;
|
||||
|
||||
extern crate servo;
|
||||
extern crate compositing;
|
||||
|
||||
extern crate azure;
|
||||
extern crate compositing;
|
||||
extern crate geom;
|
||||
extern crate gfx;
|
||||
extern crate gleam;
|
||||
extern crate glfw;
|
||||
extern crate glfw_app;
|
||||
extern crate js;
|
||||
|
@ -34,9 +35,14 @@ extern crate stb_image;
|
|||
|
||||
extern crate green;
|
||||
extern crate native;
|
||||
extern crate rustrt;
|
||||
extern crate libc;
|
||||
extern crate "url" as std_url;
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
extern crate cgl;
|
||||
#[cfg(target_os="macos")]
|
||||
extern crate cocoa;
|
||||
#[cfg(target_os="macos")]
|
||||
extern crate core_graphics;
|
||||
#[cfg(target_os="macos")]
|
||||
|
@ -46,14 +52,17 @@ extern crate core_text;
|
|||
pub mod macros;
|
||||
|
||||
pub mod browser;
|
||||
pub mod browser_host;
|
||||
pub mod command_line;
|
||||
pub mod cookie;
|
||||
pub mod core;
|
||||
pub mod drag_data;
|
||||
pub mod eutil;
|
||||
pub mod frame;
|
||||
pub mod interfaces;
|
||||
pub mod print_settings;
|
||||
pub mod process_message;
|
||||
pub mod render_handler;
|
||||
pub mod request;
|
||||
pub mod request_context;
|
||||
pub mod response;
|
||||
|
@ -67,8 +76,9 @@ pub mod switches;
|
|||
pub mod task;
|
||||
pub mod types;
|
||||
pub mod urlrequest;
|
||||
pub mod values;
|
||||
pub mod v8;
|
||||
pub mod values;
|
||||
pub mod window;
|
||||
pub mod wrappers;
|
||||
pub mod xml_reader;
|
||||
pub mod zip_reader;
|
||||
|
|
19
ports/cef/render_handler.rs
Normal file
19
ports/cef/render_handler.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* 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/. */
|
||||
|
||||
use interfaces::{CefBrowser, CefRenderHandler};
|
||||
use types::PET_VIEW;
|
||||
|
||||
use std::ptr;
|
||||
|
||||
pub trait CefRenderHandlerExtensions {
|
||||
fn paint(&self, browser: CefBrowser);
|
||||
}
|
||||
|
||||
impl CefRenderHandlerExtensions for CefRenderHandler {
|
||||
fn paint(&self, browser: CefBrowser) {
|
||||
self.on_paint(browser, PET_VIEW, 0, ptr::null(), &mut (), 0, 0)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
|
||||
use eutil::slice_to_str;
|
||||
use libc::{mod, size_t, c_int, c_ushort,c_void};
|
||||
use libc::{mod, size_t, c_int, c_ushort, c_void};
|
||||
use libc::types::os::arch::c95::wchar_t;
|
||||
use std::char;
|
||||
use std::mem;
|
||||
|
@ -54,7 +54,7 @@ pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_string_userfree_utf16_free(cs: *mut cef_string_userfree_utf16_t) {
|
||||
pub extern "C" fn cef_string_userfree_utf16_free(cs: cef_string_userfree_utf16_t) {
|
||||
unsafe {
|
||||
cef_string_utf16_clear(cs);
|
||||
libc::free(cs as *mut c_void)
|
||||
|
@ -269,19 +269,6 @@ pub extern "C" fn cef_string_utf8_to_wide(src: *const u8, src_len: size_t, outpu
|
|||
})
|
||||
}
|
||||
|
||||
/// Wraps a borrowed reference to a UTF-16 CEF string.
|
||||
pub struct CefStringRef<'a> {
|
||||
pub c_object: &'a *const cef_string_utf16_t,
|
||||
}
|
||||
|
||||
impl<'a> CefStringRef<'a> {
|
||||
pub unsafe fn from_c_object(c_object: &'a *const cef_string_utf16_t) -> CefStringRef<'a> {
|
||||
CefStringRef {
|
||||
c_object: c_object,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cef_string_wide_to_utf8(src: *const wchar_t, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
|
||||
if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
|
||||
|
@ -321,3 +308,16 @@ pub fn empty_utf16_string() -> cef_string_utf16_t {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn string_to_userfree_string(string: cef_string_utf16_t) -> cef_string_userfree_utf16_t {
|
||||
unsafe {
|
||||
let allocation: cef_string_userfree_utf16_t =
|
||||
mem::transmute(libc::malloc(mem::size_of::<cef_string_utf16_t>() as size_t));
|
||||
ptr::write(allocation, string);
|
||||
allocation
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty_utf16_userfree_string() -> cef_string_userfree_utf16_t {
|
||||
string_to_userfree_string(empty_utf16_string())
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ use std::collections::TreeMap;
|
|||
use std::iter::AdditiveIterator;
|
||||
use std::mem;
|
||||
use std::string::String;
|
||||
use string::{cef_string_userfree_utf16_alloc,cef_string_userfree_utf16_free,cef_string_utf16_set};
|
||||
use string::{cef_string_userfree_utf16_alloc, cef_string_userfree_utf16_free};
|
||||
use string::{cef_string_utf16_set};
|
||||
use types::{cef_string_multimap_t,cef_string_t};
|
||||
|
||||
fn string_multimap_to_treemap(smm: *mut cef_string_multimap_t) -> *mut TreeMap<String, Vec<*mut cef_string_t>> {
|
||||
|
|
File diff suppressed because it is too large
Load diff
284
ports/cef/window.rs
Normal file
284
ports/cef/window.rs
Normal file
|
@ -0,0 +1,284 @@
|
|||
/* 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/. */
|
||||
|
||||
//! Off-screen windows.
|
||||
//!
|
||||
//! This is used for off-screen rendering mode only; on-screen windows (the default embedding mode)
|
||||
//! are managed by a platform toolkit (GLFW or Glutin).
|
||||
|
||||
use eutil::Downcast;
|
||||
use interfaces::CefBrowser;
|
||||
use render_handler::CefRenderHandlerExtensions;
|
||||
use types::cef_rect_t;
|
||||
use wrappers::Utf16Encoder;
|
||||
|
||||
use compositing::compositor_task::{mod, CompositorProxy, CompositorReceiver};
|
||||
use compositing::windowing::{IdleWindowEvent, WindowEvent, WindowMethods};
|
||||
use geom::scale_factor::ScaleFactor;
|
||||
use geom::size::TypedSize2D;
|
||||
use gleam::gl;
|
||||
use layers::geometry::DevicePixel;
|
||||
use layers::platform::surface::NativeGraphicsMetadata;
|
||||
use libc::{c_char, c_void};
|
||||
use servo_msg::compositor_msg::{Blank, FinishedLoading, Loading, PerformingLayout, PaintState};
|
||||
use servo_msg::compositor_msg::{ReadyState};
|
||||
use servo_msg::constellation_msg::LoadData;
|
||||
use servo_util::geometry::ScreenPx;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
use std::ptr;
|
||||
|
||||
/// The type of an off-screen window.
|
||||
#[deriving(Clone)]
|
||||
pub struct Window {
|
||||
cef_browser: RefCell<Option<CefBrowser>>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
/// Creates a new window.
|
||||
pub fn new() -> Rc<Window> {
|
||||
const RTLD_DEFAULT: *mut c_void = (-2) as *mut c_void;
|
||||
|
||||
extern {
|
||||
fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void;
|
||||
}
|
||||
|
||||
gl::load_with(|s| {
|
||||
unsafe {
|
||||
let c_str = s.to_c_str();
|
||||
dlsym(RTLD_DEFAULT, c_str.as_ptr()) as *const c_void
|
||||
}
|
||||
});
|
||||
|
||||
Rc::new(Window {
|
||||
cef_browser: RefCell::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the current browser.
|
||||
pub fn set_browser(&self, browser: CefBrowser) {
|
||||
*self.cef_browser.borrow_mut() = Some(browser)
|
||||
}
|
||||
|
||||
/// Currently unimplemented.
|
||||
pub fn wait_events(&self) -> WindowEvent {
|
||||
IdleWindowEvent
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowMethods for Window {
|
||||
fn framebuffer_size(&self) -> TypedSize2D<DevicePixel,uint> {
|
||||
let browser = self.cef_browser.borrow();
|
||||
match *browser {
|
||||
None => TypedSize2D(400, 300),
|
||||
Some(ref browser) => {
|
||||
let mut rect = cef_rect_t::zero();
|
||||
browser.get_host()
|
||||
.get_client()
|
||||
.get_render_handler()
|
||||
.get_backing_rect((*browser).clone(), &mut rect);
|
||||
TypedSize2D(rect.width as uint, rect.height as uint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size(&self) -> TypedSize2D<ScreenPx,f32> {
|
||||
let browser = self.cef_browser.borrow();
|
||||
match *browser {
|
||||
None => TypedSize2D(400.0, 300.0),
|
||||
Some(ref browser) => {
|
||||
let mut rect = cef_rect_t::zero();
|
||||
browser.get_host()
|
||||
.get_client()
|
||||
.get_render_handler()
|
||||
.get_view_rect((*browser).clone(), &mut rect);
|
||||
TypedSize2D(rect.width as f32, rect.height as f32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn present(&self) {
|
||||
let browser = self.cef_browser.borrow();
|
||||
match *browser {
|
||||
None => {}
|
||||
Some(ref browser) => {
|
||||
browser.get_host().get_client().get_render_handler().on_present(browser.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_ready_state(&self, ready_state: ReadyState) {
|
||||
let browser = self.cef_browser.borrow();
|
||||
let browser = match *browser {
|
||||
None => return,
|
||||
Some(ref browser) => browser,
|
||||
};
|
||||
let is_loading = match ready_state {
|
||||
Blank | FinishedLoading => 0,
|
||||
Loading | PerformingLayout => 1,
|
||||
};
|
||||
browser.get_host()
|
||||
.get_client()
|
||||
.get_load_handler()
|
||||
.on_loading_state_change(browser.clone(), is_loading, 1, 1);
|
||||
}
|
||||
|
||||
fn set_paint_state(&self, _: PaintState) {
|
||||
// TODO(pcwalton)
|
||||
}
|
||||
|
||||
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx,DevicePixel,f32> {
|
||||
let browser = self.cef_browser.borrow();
|
||||
match *browser {
|
||||
None => ScaleFactor(1.0),
|
||||
Some(ref browser) => {
|
||||
let mut view_rect = cef_rect_t::zero();
|
||||
browser.get_host()
|
||||
.get_client()
|
||||
.get_render_handler()
|
||||
.get_view_rect((*browser).clone(), &mut view_rect);
|
||||
let mut backing_rect = cef_rect_t::zero();
|
||||
browser.get_host()
|
||||
.get_client()
|
||||
.get_render_handler()
|
||||
.get_backing_rect((*browser).clone(), &mut backing_rect);
|
||||
ScaleFactor(backing_rect.width as f32 / view_rect.width as f32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
fn native_metadata(&self) -> NativeGraphicsMetadata {
|
||||
use cgl::{CGLGetCurrentContext, CGLGetPixelFormat};
|
||||
|
||||
// FIXME(pcwalton)
|
||||
unsafe {
|
||||
NativeGraphicsMetadata {
|
||||
pixel_format: CGLGetPixelFormat(CGLGetCurrentContext()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
fn native_metadata(&self) -> NativeGraphicsMetadata {
|
||||
// TODO(pcwalton)
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn create_compositor_channel(_: &Option<Rc<Window>>)
|
||||
-> (Box<CompositorProxy+Send>, Box<CompositorReceiver>) {
|
||||
let (sender, receiver) = channel();
|
||||
(box CefCompositorProxy {
|
||||
sender: sender,
|
||||
} as Box<CompositorProxy+Send>,
|
||||
box receiver as Box<CompositorReceiver>)
|
||||
}
|
||||
|
||||
fn prepare_for_composite(&self) -> bool {
|
||||
let browser = self.cef_browser.borrow();
|
||||
match *browser {
|
||||
None => {}
|
||||
Some(ref browser) => {
|
||||
browser.get_host().get_client().get_render_handler().paint(browser.clone());
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn load_end(&self) {
|
||||
// FIXME(pcwalton): The status code 200 is a lie.
|
||||
let browser = self.cef_browser.borrow();
|
||||
let browser = match *browser {
|
||||
None => return,
|
||||
Some(ref browser) => browser,
|
||||
};
|
||||
browser.get_host()
|
||||
.get_client()
|
||||
.get_load_handler()
|
||||
.on_load_end((*browser).clone(), browser.get_main_frame(), 200);
|
||||
}
|
||||
|
||||
fn set_page_title(&self, string: Option<String>) {
|
||||
let browser = self.cef_browser.borrow();
|
||||
let browser = match *browser {
|
||||
None => return,
|
||||
Some(ref browser) => browser,
|
||||
};
|
||||
let frame = browser.get_main_frame();
|
||||
let frame = frame.downcast();
|
||||
let mut title_visitor = frame.title_visitor.borrow_mut();
|
||||
match &mut *title_visitor {
|
||||
&None => {}
|
||||
&Some(ref mut visitor) => {
|
||||
match string {
|
||||
None => visitor.visit(&[]),
|
||||
Some(string) => {
|
||||
let utf16_chars: Vec<u16> = Utf16Encoder::new(string.chars()).collect();
|
||||
visitor.visit(utf16_chars.as_slice())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_page_load_data(&self, load_data: LoadData) {
|
||||
let browser = self.cef_browser.borrow();
|
||||
let browser = match *browser {
|
||||
None => return,
|
||||
Some(ref browser) => browser,
|
||||
};
|
||||
let frame = browser.get_main_frame();
|
||||
let frame = frame.downcast();
|
||||
*frame.url.borrow_mut() = load_data.url.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
struct CefCompositorProxy {
|
||||
sender: Sender<compositor_task::Msg>,
|
||||
}
|
||||
|
||||
impl CompositorProxy for CefCompositorProxy {
|
||||
#[cfg(target_os="macos")]
|
||||
fn send(&mut self, msg: compositor_task::Msg) {
|
||||
use cocoa::appkit::{NSApp, NSApplication, NSApplicationDefined, NSAutoreleasePool};
|
||||
use cocoa::appkit::{NSEvent, NSPoint};
|
||||
use cocoa::base::nil;
|
||||
|
||||
// Send a message and kick the OS event loop awake.
|
||||
self.sender.send(msg);
|
||||
|
||||
unsafe {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
let event =
|
||||
NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2(
|
||||
nil,
|
||||
NSApplicationDefined,
|
||||
NSPoint::new(0.0, 0.0),
|
||||
0,
|
||||
0.0,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
NSApp().postEvent_atStart_(event, false);
|
||||
pool.drain();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
fn send(&mut self, msg: compositor_task::Msg) {
|
||||
// FIXME(pcwalton): Kick the GTK event loop awake?
|
||||
self.sender.send(msg);
|
||||
}
|
||||
|
||||
fn clone_compositor_proxy(&self) -> Box<CompositorProxy+Send> {
|
||||
box CefCompositorProxy {
|
||||
sender: self.sender.clone(),
|
||||
} as Box<CompositorProxy+Send>
|
||||
}
|
||||
}
|
||||
|
|
@ -21,9 +21,9 @@ use types::{cef_load_handler_t, cef_menu_item_type_t, cef_mouse_button_type_t};
|
|||
use types::{cef_mouse_event, cef_navigation_type_t};
|
||||
use types::{cef_page_range_t, cef_paint_element_type_t, cef_point_t, cef_postdataelement_type_t};
|
||||
use types::{cef_popup_features_t, cef_process_id_t};
|
||||
use types::{cef_rect_t, cef_request_context_t, cef_request_handler_t};
|
||||
use types::{cef_rect_t, cef_request_handler_t};
|
||||
use types::{cef_resource_type_t};
|
||||
use types::{cef_screen_info_t, cef_size_t, cef_string_t};
|
||||
use types::{cef_screen_info_t, cef_size_t, cef_string_t, cef_string_userfree_t};
|
||||
use types::{cef_string_list_t, cef_string_map_t, cef_string_multimap_t, cef_string_utf16};
|
||||
use types::{cef_termination_status_t, cef_text_input_context_t, cef_thread_id_t};
|
||||
use types::{cef_time_t, cef_transition_type_t, cef_urlrequest_status_t};
|
||||
|
@ -126,7 +126,6 @@ cef_noop_wrapper!(*mut cef_geolocation_handler_t)
|
|||
cef_noop_wrapper!(*mut cef_jsdialog_handler_t)
|
||||
cef_noop_wrapper!(*mut cef_keyboard_handler_t)
|
||||
cef_noop_wrapper!(*mut cef_load_handler_t)
|
||||
cef_noop_wrapper!(*mut cef_request_context_t)
|
||||
cef_noop_wrapper!(*mut cef_request_handler_t)
|
||||
cef_noop_wrapper!(*mut cef_string_list_t)
|
||||
cef_noop_wrapper!(*mut cef_string_utf16)
|
||||
|
@ -181,9 +180,8 @@ cef_unimplemented_wrapper!(cef_string_t, String)
|
|||
impl<'a> CefWrap<*const cef_string_t> for &'a [u16] {
|
||||
fn to_c(buffer: &'a [u16]) -> *const cef_string_t {
|
||||
unsafe {
|
||||
let ptr: *mut c_ushort =
|
||||
mem::transmute(libc::calloc(1, ((buffer.len() * 2) + 1) as u64));
|
||||
ptr::copy_memory(ptr, mem::transmute(buffer.as_ptr()), (buffer.len() * 2) as uint);
|
||||
let ptr: *mut c_ushort = mem::transmute(libc::malloc(((buffer.len() + 1) * 2) as u64));
|
||||
ptr::copy_memory(ptr, mem::transmute(buffer.as_ptr()), buffer.len());
|
||||
*ptr.offset(buffer.len() as int) = 0;
|
||||
|
||||
// FIXME(pcwalton): This leaks!! We should instead have the caller pass some scratch
|
||||
|
@ -240,6 +238,71 @@ impl<'a,'b> CefWrap<*mut *const c_char> for &'a mut &'b str {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> CefWrap<cef_string_userfree_t> for String {
|
||||
fn to_c(string: String) -> cef_string_userfree_t {
|
||||
let utf16_chars: Vec<u16> = Utf16Encoder::new(string.chars()).collect();
|
||||
|
||||
let boxed_string;
|
||||
unsafe {
|
||||
let buffer = libc::malloc((mem::size_of::<c_ushort>() as u64) *
|
||||
((utf16_chars.len() + 1) as u64 + 1)) as *mut u16;
|
||||
for (i, ch) in utf16_chars.iter().enumerate() {
|
||||
*buffer.offset(i as int) = *ch
|
||||
}
|
||||
*buffer.offset(utf16_chars.len() as int) = 0;
|
||||
|
||||
boxed_string = libc::malloc(mem::size_of::<cef_string_utf16>() as u64) as
|
||||
*mut cef_string_utf16;
|
||||
ptr::write(&mut (*boxed_string).str, buffer);
|
||||
ptr::write(&mut (*boxed_string).length, utf16_chars.len() as u64);
|
||||
ptr::write(&mut (*boxed_string).dtor, Some(free_utf16_buffer));
|
||||
mem::forget(utf16_chars);
|
||||
}
|
||||
boxed_string
|
||||
}
|
||||
unsafe fn to_rust(_: cef_string_userfree_t) -> String {
|
||||
panic!("unimplemented CEF type conversion: cef_string_userfree_t")
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn free_utf16_buffer(buffer: *mut c_ushort) {
|
||||
unsafe {
|
||||
libc::free(buffer as *mut c_void)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(pcwalton): Post Rust-upgrade, remove this and use `collections::str::Utf16Encoder`.
|
||||
pub struct Utf16Encoder<I> {
|
||||
chars: I,
|
||||
extra: u16,
|
||||
}
|
||||
|
||||
impl<I> Utf16Encoder<I> {
|
||||
pub fn new(chars: I) -> Utf16Encoder<I> where I: Iterator<char> {
|
||||
Utf16Encoder {
|
||||
chars: chars,
|
||||
extra: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Iterator<u16> for Utf16Encoder<I> where I: Iterator<char> {
|
||||
fn next(&mut self) -> Option<u16> {
|
||||
if self.extra != 0 {
|
||||
return Some(mem::replace(&mut self.extra, 0))
|
||||
}
|
||||
|
||||
let mut buf = [0u16, ..2];
|
||||
self.chars.next().map(|ch| {
|
||||
let n = ch.encode_utf16(buf.as_mut_slice()).unwrap_or(0);
|
||||
if n == 2 {
|
||||
self.extra = buf[1]
|
||||
}
|
||||
buf[0]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CefWrap<cef_string_t> for &'a mut String {
|
||||
fn to_c(_: &'a mut String) -> cef_string_t {
|
||||
panic!("unimplemented CEF type conversion: &'a mut String")
|
||||
|
|
|
@ -23,9 +23,9 @@ use gleam::gl;
|
|||
use layers::geometry::DevicePixel;
|
||||
use layers::platform::surface::NativeGraphicsMetadata;
|
||||
use libc::c_int;
|
||||
use msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
|
||||
use msg::compositor_msg::{IdlePaintState, PaintState, PaintingPaintState};
|
||||
use msg::constellation_msg;
|
||||
use msg::compositor_msg::{Blank, FinishedLoading, IdlePaintState, Loading, PaintState};
|
||||
use msg::compositor_msg::{PaintingPaintState, PerformingLayout, ReadyState};
|
||||
use msg::constellation_msg::{mod, LoadData};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::comm::Receiver;
|
||||
use std::rc::Rc;
|
||||
|
@ -97,6 +97,15 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn wait_events(&self) -> WindowEvent {
|
||||
self.wait_or_poll_events(|glfw| glfw.wait_events())
|
||||
}
|
||||
|
||||
pub fn poll_events(&self) -> WindowEvent {
|
||||
self.wait_or_poll_events(|glfw| glfw.poll_events())
|
||||
}
|
||||
|
||||
/// Helper method to factor out functionality from `poll_events` and `wait_events`.
|
||||
fn wait_or_poll_events(&self, callback: |glfw: &glfw::Glfw|) -> WindowEvent {
|
||||
{
|
||||
let mut event_queue = self.event_queue.borrow_mut();
|
||||
if !event_queue.is_empty() {
|
||||
|
@ -104,7 +113,7 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
self.glfw.wait_events();
|
||||
callback(&self.glfw);
|
||||
for (_, event) in glfw::flush_messages(&self.events) {
|
||||
self.handle_window_event(&self.glfw_window, event);
|
||||
}
|
||||
|
@ -196,6 +205,16 @@ impl WindowMethods for Window {
|
|||
} as Box<CompositorProxy+Send>,
|
||||
box receiver as Box<CompositorReceiver>)
|
||||
}
|
||||
|
||||
fn prepare_for_composite(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn load_end(&self) {}
|
||||
|
||||
fn set_page_title(&self, _: Option<String>) {}
|
||||
|
||||
fn set_page_load_data(&self, _: LoadData) {}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue