diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs index f403bdaa348..fbeb81bfce7 100644 --- a/ports/cef/browser.rs +++ b/ports/cef/browser.rs @@ -9,7 +9,8 @@ use interfaces::{CefBrowser, CefBrowserHost, CefClient, CefFrame, CefRequestCont use interfaces::{cef_browser_t, cef_browser_host_t, cef_client_t, cef_frame_t}; use interfaces::{cef_request_context_t}; use msg::constellation_msg::TraversalDirection; -use servo::Browser; +use servo::{BrowserId, Servo}; +use servo::ipc_channel::ipc; use servo::servo_url::ServoUrl; use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t}; use window; @@ -29,26 +30,34 @@ thread_local!(pub static BROWSERS: RefCell> = RefCell::new(vec!( pub enum ServoBrowser { Invalid, - OnScreen(Browser), - OffScreen(Browser), + OnScreen(Servo, BrowserId), + OffScreen(Servo, BrowserId), } impl ServoBrowser { fn handle_event(&mut self, event: WindowEvent) { match *self { - ServoBrowser::OnScreen(ref mut browser) => { browser.handle_events(vec![event]); } - ServoBrowser::OffScreen(ref mut browser) => { browser.handle_events(vec![event]); } + ServoBrowser::OnScreen(ref mut browser, _) => { browser.handle_events(vec![event]); } + ServoBrowser::OffScreen(ref mut browser, _) => { browser.handle_events(vec![event]); } ServoBrowser::Invalid => {} } } pub fn pinch_zoom_level(&self) -> f32 { match *self { - ServoBrowser::OnScreen(ref browser) => browser.pinch_zoom_level(), - ServoBrowser::OffScreen(ref browser) => browser.pinch_zoom_level(), + ServoBrowser::OnScreen(ref browser, _) => browser.pinch_zoom_level(), + ServoBrowser::OffScreen(ref browser, _) => browser.pinch_zoom_level(), ServoBrowser::Invalid => 1.0, } } + + pub fn get_browser_id(&self) -> BrowserId { + match *self { + ServoBrowser::Invalid => unreachable!(), + ServoBrowser::OnScreen(_, id) => id, + ServoBrowser::OffScreen(_, id) => id, + } + } } cef_class_impl! { @@ -70,11 +79,11 @@ cef_class_impl! { }} fn go_back(&this,) -> () {{ - this.send_window_event(WindowEvent::Navigation(TraversalDirection::Back(1))); + this.send_window_event(WindowEvent::Navigation(this.get_browser_id(), TraversalDirection::Back(1))); }} fn go_forward(&this,) -> () {{ - this.send_window_event(WindowEvent::Navigation(TraversalDirection::Forward(1))); + this.send_window_event(WindowEvent::Navigation(this.get_browser_id(), TraversalDirection::Forward(1))); }} // Returns the main (top-level) frame for the browser window. @@ -124,9 +133,13 @@ impl ServoCefBrowser { let (glutin_window, servo_browser) = if window_info.windowless_rendering_enabled == 0 { let parent_window = glutin_app::WindowID::new(window_info.parent_window as *mut _); let glutin_window = glutin_app::create_window(Some(parent_window)); - let servo_browser = Browser::new(glutin_window.clone(), target_url); + let mut servo_browser = Servo::new(glutin_window.clone()); + let (sender, receiver) = ipc::channel().unwrap(); + servo_browser.handle_events(vec![WindowEvent::NewBrowser(target_url, sender)]); + let browser_id = receiver.recv().unwrap(); + servo_browser.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]); window_handle = glutin_window.platform_window().window as cef_window_handle_t; - (Some(glutin_window), ServoBrowser::OnScreen(servo_browser)) + (Some(glutin_window), ServoBrowser::OnScreen(servo_browser, browser_id)) } else { (None, ServoBrowser::Invalid) }; @@ -155,6 +168,7 @@ impl ServoCefBrowser { pub trait ServoCefBrowserExtensions { fn init(&self, window_info: &cef_window_info_t); + fn get_browser_id(&self) -> BrowserId; fn send_window_event(&self, event: WindowEvent); fn pinch_zoom_level(&self) -> f32; } @@ -165,8 +179,12 @@ impl ServoCefBrowserExtensions for CefBrowser { let window = window::Window::new(window_info.width, window_info.height); window.set_browser(self.clone()); let home_url = ServoUrl::parse("about:blank").unwrap(); - let servo_browser = Browser::new(window.clone(), home_url); - *self.downcast().servo_browser.borrow_mut() = ServoBrowser::OffScreen(servo_browser); + let mut servo_browser = Servo::new(window.clone()); + let (sender, receiver) = ipc::channel().unwrap(); + servo_browser.handle_events(vec![WindowEvent::NewBrowser(home_url, sender)]); + let browser_id = receiver.recv().unwrap(); + servo_browser.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]); + *self.downcast().servo_browser.borrow_mut() = ServoBrowser::OffScreen(servo_browser, browser_id); } self.downcast().host.set_browser((*self).clone()); @@ -176,6 +194,10 @@ impl ServoCefBrowserExtensions for CefBrowser { } } + fn get_browser_id(&self) -> BrowserId { + self.downcast().servo_browser.borrow().get_browser_id() + } + fn send_window_event(&self, event: WindowEvent) { let browser = self.downcast(); diff --git a/ports/cef/frame.rs b/ports/cef/frame.rs index 82f72e627cc..387d515faba 100644 --- a/ports/cef/frame.rs +++ b/ports/cef/frame.rs @@ -8,6 +8,7 @@ use interfaces::{CefBrowser, CefFrame, CefStringVisitor, cef_frame_t, cef_string use types::{cef_string_t, cef_string_userfree_t}; use compositing::windowing::WindowEvent; +use servo::servo_url::ServoUrl; use std::cell::RefCell; pub struct ServoCefFrame { @@ -34,7 +35,9 @@ full_cef_class_impl! { let this = this.downcast(); let url = String::from_utf16(url).unwrap(); *this.url.borrow_mut() = url.clone(); - let event = WindowEvent::LoadUrl(url); + let id = this.browser.borrow().as_ref().unwrap().get_browser_id(); + let url = ServoUrl::parse(&url).or(ServoUrl::parse("about:blank")).unwrap(); + let event = WindowEvent::LoadUrl(id, url); this.browser.borrow_mut().as_mut().unwrap().send_window_event(event); }} fn get_url(&this,) -> cef_string_userfree_t {{ @@ -60,7 +63,10 @@ impl ServoCefFrameExtensions for CefFrame { *self.downcast().browser.borrow_mut() = Some(browser) } fn load(&self) { - let event = WindowEvent::LoadUrl(self.downcast().url.borrow().clone()); + let id = self.downcast().browser.borrow().as_ref().unwrap().get_browser_id(); + let url = self.downcast().url.borrow(); + let url = ServoUrl::parse(&*url).or(ServoUrl::parse("about:blank")).unwrap(); + let event = WindowEvent::LoadUrl(id, url); self.downcast().browser.borrow_mut().as_mut().unwrap().send_window_event(event); } } diff --git a/ports/cef/window.rs b/ports/cef/window.rs index 4fe62cfd601..ebead54b8b4 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -24,6 +24,7 @@ use gleam::gl; use msg::constellation_msg::{Key, KeyModifiers}; use net_traits::net_error_list::NetError; use script_traits::LoadData; +use servo::BrowserId; use servo::ipc_channel::ipc::IpcSender; use servo_geometry::DeviceIndependentPixel; use std::cell::RefCell; @@ -233,7 +234,7 @@ impl WindowMethods for Window { } } - fn client_window(&self) -> (Size2D, Point2D) { + fn client_window(&self, _: BrowserId) -> (Size2D, Point2D) { let size = self.size().to_untyped(); let width = size.width as u32; let height = size.height as u32; @@ -241,15 +242,15 @@ impl WindowMethods for Window { (Size2D::new(width, height), Point2D::zero()) } - fn set_inner_size(&self, _size: Size2D) { + fn set_inner_size(&self, _: BrowserId, _size: Size2D) { } - fn set_position(&self, _point: Point2D) { + fn set_position(&self, _: BrowserId, _point: Point2D) { } - fn set_fullscreen_state(&self, _state: bool) { + fn set_fullscreen_state(&self, _: BrowserId, _state: bool) { } fn present(&self) { @@ -327,7 +328,7 @@ impl WindowMethods for Window { } } - fn set_favicon(&self, url: ServoUrl) { + fn set_favicon(&self, _: BrowserId, url: ServoUrl) { let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -336,7 +337,7 @@ impl WindowMethods for Window { browser.downcast().favicons.borrow_mut().push(url.into_string()); } - fn status(&self, info: Option) { + fn status(&self, _: BrowserId, info: Option) { let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -353,7 +354,7 @@ impl WindowMethods for Window { } } - fn load_start(&self) { + fn load_start(&self, _: BrowserId) { let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -372,7 +373,7 @@ impl WindowMethods for Window { } } - fn load_end(&self) { + fn load_end(&self, _: BrowserId) { // FIXME(pcwalton): The status code 200 is a lie. let browser = self.cef_browser.borrow(); let browser = match *browser { @@ -398,7 +399,7 @@ impl WindowMethods for Window { } } - fn load_error(&self, code: NetError, url: String) { + fn load_error(&self, _: BrowserId, code: NetError, url: String) { let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -415,7 +416,7 @@ impl WindowMethods for Window { } } - fn head_parsed(&self) { + fn head_parsed(&self, _: BrowserId) { let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -427,7 +428,7 @@ impl WindowMethods for Window { } } - fn set_page_title(&self, string: Option) { + fn set_page_title(&self, _: BrowserId, string: Option) { let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -448,7 +449,7 @@ impl WindowMethods for Window { *frame.title.borrow_mut() = str; } - fn history_changed(&self, history: Vec, current: usize) { + fn history_changed(&self, _: BrowserId, history: Vec, current: usize) { let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -470,7 +471,7 @@ impl WindowMethods for Window { } } - fn handle_key(&self, _: Option, _: Key, _: KeyModifiers) { + fn handle_key(&self, _: Option, _: Option, _: Key, _: KeyModifiers) { // TODO(negge) } @@ -491,7 +492,7 @@ impl WindowMethods for Window { } } - fn allow_navigation(&self, _: ServoUrl, response_chan: IpcSender) { + fn allow_navigation(&self, _: BrowserId, _: ServoUrl, response_chan: IpcSender) { if let Err(e) = response_chan.send(true) { warn!("Failed to send allow_navigation() response: {}", e); }; diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 1f82d7fb3c2..1e35d36b610 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -182,6 +182,10 @@ pub struct Window { mouse_down_point: Cell>, event_queue: RefCell>, + /// id of the top level browsing context. It is unique as tabs + /// are not supported yet. None until created. + browser_id: Cell>, + mouse_pos: Cell>, key_modifiers: Cell, current_url: RefCell>, @@ -217,6 +221,10 @@ fn window_creation_scale_factor() -> ScaleFactor, parent: Option) -> Rc { @@ -309,6 +317,8 @@ impl Window { mouse_down_button: Cell::new(None), mouse_down_point: Cell::new(Point2D::new(0, 0)), + browser_id: Cell::new(None), + mouse_pos: Cell::new(Point2D::new(0, 0)), key_modifiers: Cell::new(KeyModifiers::empty()), current_url: RefCell::new(None), @@ -929,20 +939,22 @@ impl Window { } #[cfg(not(target_os = "win"))] - fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) { + fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers, browser_id: BrowserId) { match (mods, key) { (CMD_OR_CONTROL, Key::LeftBracket) => { - self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Back(1))); + let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1)); + self.event_queue.borrow_mut().push(event); } (CMD_OR_CONTROL, Key::RightBracket) => { - self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Forward(1))); + let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1)); + self.event_queue.borrow_mut().push(event); } _ => {} } } #[cfg(target_os = "win")] - fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) { + fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers, browser_id: BrowserId) { } } @@ -1203,6 +1215,10 @@ impl WindowMethods for Window { /// Helper function to handle keyboard events. fn handle_key(&self, _: Option, ch: Option, key: Key, mods: constellation_msg::KeyModifiers) { + let browser_id = match self.browser_id.get() { + Some(id) => id, + None => { unreachable!("Can't get keys without a browser"); } + }; match (mods, ch, key) { (_, Some('+'), _) => { if mods & !SHIFT == CMD_OR_CONTROL { @@ -1222,10 +1238,12 @@ impl WindowMethods for Window { } (NONE, None, Key::NavigateForward) => { - self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Forward(1))); + let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1)); + self.event_queue.borrow_mut().push(event); } (NONE, None, Key::NavigateBackward) => { - self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Back(1))); + let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1)); + self.event_queue.borrow_mut().push(event); } (NONE, None, Key::Escape) => { @@ -1235,10 +1253,12 @@ impl WindowMethods for Window { } (CMD_OR_ALT, None, Key::Right) => { - self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Forward(1))); + let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1)); + self.event_queue.borrow_mut().push(event); } (CMD_OR_ALT, None, Key::Left) => { - self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Back(1))); + let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1)); + self.event_queue.borrow_mut().push(event); } (NONE, None, Key::PageDown) => { @@ -1284,7 +1304,7 @@ impl WindowMethods for Window { } (CMD_OR_CONTROL, Some('r'), _) => { if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() { - self.event_queue.borrow_mut().push(WindowEvent::Reload); + self.event_queue.borrow_mut().push(WindowEvent::Reload(browser_id)); } } (CMD_OR_CONTROL, Some('q'), _) => { @@ -1297,7 +1317,7 @@ impl WindowMethods for Window { } _ => { - self.platform_handle_key(key, mods); + self.platform_handle_key(key, mods, browser_id); } } } diff --git a/ports/servo/main.rs b/ports/servo/main.rs index ff99c9c5afa..2a2227486a6 100644 --- a/ports/servo/main.rs +++ b/ports/servo/main.rs @@ -4,7 +4,7 @@ //! The `servo` test application. //! -//! Creates a `Browser` instance with a simple implementation of +//! Creates a `Servo` instance with a simple implementation of //! the compositor's `WindowMethods` to create a working web browser. //! //! This browser's implementation of `WindowMethods` is built on top @@ -31,12 +31,13 @@ extern crate servo; extern crate sig; use backtrace::Backtrace; -use servo::Browser; +use servo::Servo; use servo::compositing::windowing::WindowEvent; #[cfg(target_os = "android")] use servo::config; use servo::config::opts::{self, ArgumentParsingResult, parse_url_or_filename}; use servo::config::servo_version; +use servo::ipc_channel::ipc; use servo::servo_config::prefs::PREFS; use servo::servo_url::ServoUrl; use std::env; @@ -155,20 +156,26 @@ fn main() { let target_url = cmdline_url.or(pref_url).or(blank_url).unwrap(); - // Our wrapper around `Browser` that also implements some + // Our wrapper around `ServoWrapper` that also implements some // callbacks required by the glutin window implementation. - let mut browser = BrowserWrapper { - browser: Browser::new(window.clone(), target_url) + let mut servo_wrapper = ServoWrapper { + servo: Servo::new(window.clone()) }; - browser.browser.setup_logging(); + let (sender, receiver) = ipc::channel().unwrap(); + servo_wrapper.servo.handle_events(vec![WindowEvent::NewBrowser(target_url, sender)]); + let browser_id = receiver.recv().unwrap(); + window.set_browser_id(browser_id); + servo_wrapper.servo.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]); - register_glutin_resize_handler(&window, &mut browser); + servo_wrapper.servo.setup_logging(); + + register_glutin_resize_handler(&window, &mut servo_wrapper); // Feed events from the window to the browser until the browser // says to stop. loop { - let should_continue = browser.browser.handle_events(window.wait_events()); + let should_continue = servo_wrapper.servo.handle_events(window.wait_events()); if !should_continue { break; } @@ -179,7 +186,7 @@ fn main() { platform::deinit() } -fn register_glutin_resize_handler(window: &Rc, browser: &mut BrowserWrapper) { +fn register_glutin_resize_handler(window: &Rc, browser: &mut ServoWrapper) { unsafe { window.set_nested_event_loop_listener(browser); } @@ -191,21 +198,21 @@ fn unregister_glutin_resize_handler(window: &Rc) { } } -struct BrowserWrapper { - browser: Browser, +struct ServoWrapper { + servo: Servo, } -impl app::NestedEventLoopListener for BrowserWrapper { +impl app::NestedEventLoopListener for ServoWrapper { fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool { let is_resize = match event { WindowEvent::Resize(..) => true, _ => false, }; - if !self.browser.handle_events(vec![event]) { + if !self.servo.handle_events(vec![event]) { return false; } if is_resize { - self.browser.repaint_synchronously() + self.servo.repaint_synchronously() } true }