diff --git a/Cargo.lock b/Cargo.lock index bc7eb3b2151..bd65dc2099b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2307,10 +2307,10 @@ dependencies = [ name = "libmlservo" version = "0.0.1" dependencies = [ - "keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "libservo 0.0.1", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "simpleservo 0.0.1", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2336,6 +2336,7 @@ dependencies = [ "gfx 0.0.1", "gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "layout_thread 0.0.1", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index d3ecc14f7db..5a2f0e66e40 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -51,6 +51,7 @@ euclid = "0.19" gfx = {path = "../gfx"} gleam = "0.6" ipc-channel = "0.11" +keyboard-types = "0.4" layout_thread = {path = "../layout_thread"} log = "0.4" msg = {path = "../msg"} diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 0eed4aa6c1d..95a02c25afc 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -112,6 +112,7 @@ use webrender::{RendererKind, ShaderPrecacheFlags}; use webvr::{VRServiceManager, WebVRCompositorHandler, WebVRThread}; pub use gleam::gl; +pub use keyboard_types; pub use msg::constellation_msg::TopLevelBrowsingContextId as BrowserId; pub use servo_config as config; pub use servo_url as url; diff --git a/ports/libmlservo/Cargo.toml b/ports/libmlservo/Cargo.toml index 3cb1f156aaf..b0db3605df2 100644 --- a/ports/libmlservo/Cargo.toml +++ b/ports/libmlservo/Cargo.toml @@ -13,8 +13,8 @@ test = false bench = false [dependencies] -keyboard-types = "0.4" libservo = { path = "../../components/servo", features = ["no_static_freetype"] } +simpleservo = { path = "../libsimpleservo/api", features = ["no_static_freetype"] } log = "0.4" servo-egl = "0.2" smallvec = "0.6" diff --git a/ports/libmlservo/src/lib.rs b/ports/libmlservo/src/lib.rs index 59799d40828..25035ba9aa7 100644 --- a/ports/libmlservo/src/lib.rs +++ b/ports/libmlservo/src/lib.rs @@ -7,45 +7,24 @@ use egl::egl::EGLDisplay; use egl::egl::EGLSurface; use egl::egl::MakeCurrent; use egl::egl::SwapBuffers; -use egl::eglext::eglGetProcAddress; -use keyboard_types::Key; -use keyboard_types::KeyState; -use keyboard_types::KeyboardEvent; use log::info; use log::warn; -use servo::compositing::windowing::AnimationState; -use servo::compositing::windowing::EmbedderCoordinates; -use servo::compositing::windowing::MouseWindowEvent; -use servo::compositing::windowing::WindowEvent; -use servo::compositing::windowing::WindowMethods; -use servo::embedder_traits::resources::Resource; -use servo::embedder_traits::resources::ResourceReaderMethods; -use servo::embedder_traits::EmbedderMsg; -use servo::embedder_traits::EventLoopWaker; -use servo::euclid::TypedPoint2D; -use servo::euclid::TypedRect; use servo::euclid::TypedScale; -use servo::euclid::TypedSize2D; -use servo::gl; -use servo::gl::Gl; -use servo::gl::GlesFns; -use servo::msg::constellation_msg::TraversalDirection; -use servo::script_traits::MouseButton; -use servo::script_traits::TouchEventType; +use servo::keyboard_types::Key; use servo::servo_url::ServoUrl; use servo::webrender_api::DevicePixel; use servo::webrender_api::DevicePoint; use servo::webrender_api::LayoutPixel; -use servo::webrender_api::ScrollLocation; -use servo::BrowserId; -use servo::Servo; +use simpleservo::{ + self, deinit, gl_glue, EventLoopWaker, HostTrait, InitOptions, MouseButton, ServoGlue, SERVO, +}; use smallvec::SmallVec; +use std::cell::Cell; use std::ffi::CStr; use std::ffi::CString; use std::io::Write; use std::os::raw::c_char; use std::os::raw::c_void; -use std::path::PathBuf; use std::rc::Rc; use std::thread; use std::time::Duration; @@ -90,7 +69,10 @@ pub enum MLKeyType { pub struct MLLogger(extern "C" fn(MLLogLevel, *const c_char)); #[repr(transparent)] -pub struct MLHistoryUpdate(extern "C" fn(MLApp, bool, *const c_char, bool)); +pub struct MLHistoryUpdate(extern "C" fn(MLApp, bool, bool)); + +#[repr(transparent)] +pub struct MLURLUpdate(extern "C" fn(MLApp, *const c_char)); #[repr(transparent)] pub struct MLKeyboard(extern "C" fn(MLApp, bool)); @@ -101,6 +83,16 @@ pub struct MLApp(*mut c_void); const LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info; +fn call(f: F) -> Result +where + F: FnOnce(&mut ServoGlue) -> Result, +{ + SERVO.with(|s| match s.borrow_mut().as_mut() { + Some(ref mut s) => (f)(s), + None => Err("Servo is not available in this thread"), + }) +} + #[no_mangle] pub unsafe extern "C" fn init_servo( ctxt: EGLContext, @@ -109,150 +101,72 @@ pub unsafe extern "C" fn init_servo( app: MLApp, logger: MLLogger, history_update: MLHistoryUpdate, + url_update: MLURLUpdate, keyboard: MLKeyboard, url: *const c_char, width: u32, height: u32, hidpi: f32, ) -> *mut ServoInstance { - // Servo initialization goes here! - servo::embedder_traits::resources::set(Box::new(ResourceReaderInstance::new())); let _ = log::set_boxed_logger(Box::new(logger)); log::set_max_level(LOG_LEVEL); - let gl = GlesFns::load_with(|symbol| { - let cstr = CString::new(symbol).expect("Failed to convert GL symbol to a char*"); - eglGetProcAddress(cstr.as_ptr() as _) as _ - }); - info!("OpenGL version {}", gl.get_string(gl::VERSION)); - let window = Rc::new(WindowInstance { - ctxt: ctxt, - surf: surf, - disp: disp, - gl: gl, + let gl = gl_glue::egl::init().expect("EGL initialization failure"); + + let url = CStr::from_ptr(url).to_str().unwrap_or("about:blank"); + let opts = InitOptions { + args: None, + url: Some(url.to_string()), width: width, height: height, - hidpi: hidpi, + density: hidpi, + enable_subpixel_text_antialiasing: false, + vr_pointer: None, + }; + let wakeup = Box::new(EventLoopWakerInstance); + let shut_down_complete = Rc::new(Cell::new(false)); + let callbacks = Box::new(HostCallbacks { + app, + ctxt, + surf, + disp, + shut_down_complete: shut_down_complete.clone(), + history_update, + url_update, + keyboard, }); - info!("Starting servo"); - let mut servo = Servo::new(window); - let browser_id = BrowserId::new(); - - let blank_url = ServoUrl::parse("about:blank").expect("Failed to parse about:blank!"); - let url = CStr::from_ptr(url).to_str().unwrap_or("about:blank"); - let url = ServoUrl::parse(url).unwrap_or(blank_url); - servo.handle_events(vec![WindowEvent::NewBrowser(url, browser_id)]); + simpleservo::init(opts, gl, wakeup, callbacks).expect("error initializing Servo"); let result = Box::new(ServoInstance { - app: app, - browser_id: browser_id, - history_update: history_update, - keyboard: keyboard, scroll_state: ScrollState::TriggerUp, scroll_scale: TypedScale::new(SCROLL_SCALE / hidpi), - servo: servo, + shut_down_complete, }); Box::into_raw(result) } #[no_mangle] -pub unsafe extern "C" fn heartbeat_servo(servo: *mut ServoInstance) { - // Servo heartbeat goes here! - if let Some(servo) = servo.as_mut() { - servo.servo.handle_events(vec![]); - for (browser_id, event) in servo.servo.get_events() { - match event { - // Respond to any messages with a response channel - // to avoid deadlocking the constellation - EmbedderMsg::AllowNavigationRequest(pipeline_id, _url) => { - if let Some(_browser_id) = browser_id { - let window_event = WindowEvent::AllowNavigationResponse(pipeline_id, true); - servo.servo.handle_events(vec![window_event]); - } - }, - EmbedderMsg::GetSelectedBluetoothDevice(_, sender) => { - let _ = sender.send(None); - }, - EmbedderMsg::AllowUnload(sender) => { - let _ = sender.send(true); - }, - EmbedderMsg::Alert(_, sender) => { - let _ = sender.send(()); - }, - EmbedderMsg::AllowOpeningBrowser(sender) => { - let _ = sender.send(false); - }, - // Update the history UI - EmbedderMsg::HistoryChanged(urls, index) => { - if let Some(url) = urls.get(index) { - if let Ok(cstr) = CString::new(url.as_str()) { - let can_go_back = index > 0; - let can_go_fwd = (index + 1) < urls.len(); - (servo.history_update.0)( - servo.app, - can_go_back, - cstr.as_ptr(), - can_go_fwd, - ); - } - } - }, - EmbedderMsg::ShowIME(..) => (servo.keyboard.0)(servo.app, true), - EmbedderMsg::HideIME => (servo.keyboard.0)(servo.app, false), - // Ignore most messages for now - EmbedderMsg::ChangePageTitle(..) | - EmbedderMsg::BrowserCreated(..) | - EmbedderMsg::LoadStart | - EmbedderMsg::LoadComplete | - EmbedderMsg::CloseBrowser | - EmbedderMsg::Status(..) | - EmbedderMsg::SelectFiles(..) | - EmbedderMsg::MoveTo(..) | - EmbedderMsg::ResizeTo(..) | - EmbedderMsg::Keyboard(..) | - EmbedderMsg::SetCursor(..) | - EmbedderMsg::NewFavicon(..) | - EmbedderMsg::HeadParsed | - EmbedderMsg::SetFullscreenState(..) | - EmbedderMsg::Shutdown | - EmbedderMsg::Panic(..) => {}, - } - } - } +pub unsafe extern "C" fn heartbeat_servo(_servo: *mut ServoInstance) { + let _ = call(|s| s.perform_updates()); } #[no_mangle] pub unsafe extern "C" fn keyboard_servo( - servo: *mut ServoInstance, + _servo: *mut ServoInstance, key_code: char, key_type: MLKeyType, ) { - if let Some(servo) = servo.as_mut() { - let key = match key_type { - MLKeyType::kCharacter => Key::Character([key_code].iter().collect()), - MLKeyType::kBackspace => Key::Backspace, - MLKeyType::kEnter => Key::Enter, - _ => return, - }; - - let key_down = KeyboardEvent { - state: KeyState::Down, - key: key, - ..KeyboardEvent::default() - }; - - let key_up = KeyboardEvent { - state: KeyState::Up, - ..key_down.clone() - }; - - // TODO: can the ML1 generate separate press and release events? - servo.servo.handle_events(vec![ - WindowEvent::Keyboard(key_down), - WindowEvent::Keyboard(key_up), - ]); - } + let key = match key_type { + MLKeyType::kCharacter => Key::Character([key_code].iter().collect()), + MLKeyType::kBackspace => Key::Backspace, + MLKeyType::kEnter => Key::Enter, + _ => return, + }; + // TODO: can the ML1 generate separate press and release events? + let key2 = key.clone(); + let _ = call(move |s| s.key_down(key2)); + let _ = call(move |s| s.key_up(key)); } // Some magic numbers. @@ -269,41 +183,31 @@ pub unsafe extern "C" fn move_servo(servo: *mut ServoInstance, x: f32, y: f32) { // Servo's cursor was moved if let Some(servo) = servo.as_mut() { let point = DevicePoint::new(x, y); - let (new_state, window_events) = match servo.scroll_state { - ScrollState::TriggerUp => ( - ScrollState::TriggerUp, - vec![WindowEvent::MouseWindowMoveEventClass(point)], - ), + match servo.scroll_state { + ScrollState::TriggerUp => { + servo.scroll_state = ScrollState::TriggerUp; + let _ = call(|s| s.move_mouse(x, y)); + }, ScrollState::TriggerDown(start) if (start - point).square_length() < DRAG_CUTOFF_SQUARED => { return; } - ScrollState::TriggerDown(start) => ( - ScrollState::TriggerDragging(start, point), - vec![ - WindowEvent::MouseWindowMoveEventClass(point), - WindowEvent::Scroll( - ScrollLocation::Delta((point - start) * servo.scroll_scale), - start.to_i32(), - TouchEventType::Down, - ), - ], - ), - ScrollState::TriggerDragging(start, prev) => ( - ScrollState::TriggerDragging(start, point), - vec![ - WindowEvent::MouseWindowMoveEventClass(point), - WindowEvent::Scroll( - ScrollLocation::Delta((point - prev) * servo.scroll_scale), - start.to_i32(), - TouchEventType::Move, - ), - ], - ), - }; - servo.scroll_state = new_state; - servo.servo.handle_events(window_events); + ScrollState::TriggerDown(start) => { + servo.scroll_state = ScrollState::TriggerDragging(start, point); + let _ = call(|s| s.move_mouse(x, y)); + let delta = (point - start) * servo.scroll_scale; + let start = start.to_i32(); + let _ = call(|s| s.scroll_start(delta.x, delta.y, start.x, start.y)); + }, + ScrollState::TriggerDragging(start, prev) => { + servo.scroll_state = ScrollState::TriggerDragging(start, point); + let _ = call(|s| s.move_mouse(x, y)); + let delta = (point - prev) * servo.scroll_scale; + let start = start.to_i32(); + let _ = call(|s| s.scroll(delta.x, delta.y, start.x, start.y)); + }, + } } } @@ -312,83 +216,54 @@ pub unsafe extern "C" fn trigger_servo(servo: *mut ServoInstance, x: f32, y: f32 // Servo was triggered if let Some(servo) = servo.as_mut() { let point = DevicePoint::new(x, y); - let (new_state, window_events) = match servo.scroll_state { - ScrollState::TriggerUp if down => ( - ScrollState::TriggerDown(point), - vec![WindowEvent::MouseWindowEventClass( - MouseWindowEvent::MouseDown(MouseButton::Left, point), - )], - ), - ScrollState::TriggerDown(start) if !down => ( - ScrollState::TriggerUp, - vec![ - WindowEvent::MouseWindowEventClass(MouseWindowEvent::MouseUp( - MouseButton::Left, - start, - )), - WindowEvent::MouseWindowEventClass(MouseWindowEvent::Click( - MouseButton::Left, - start, - )), - WindowEvent::MouseWindowMoveEventClass(point), - ], - ), - ScrollState::TriggerDragging(start, prev) if !down => ( - ScrollState::TriggerUp, - vec![ - WindowEvent::Scroll( - ScrollLocation::Delta((point - prev) * servo.scroll_scale), - start.to_i32(), - TouchEventType::Up, - ), - WindowEvent::MouseWindowEventClass(MouseWindowEvent::MouseUp( - MouseButton::Left, - point, - )), - WindowEvent::MouseWindowMoveEventClass(point), - ], - ), + match servo.scroll_state { + ScrollState::TriggerUp if down => { + servo.scroll_state = ScrollState::TriggerDown(point); + let _ = call(|s| s.mouse_down(x, y, MouseButton::Left)); + }, + ScrollState::TriggerDown(start) if !down => { + servo.scroll_state = ScrollState::TriggerUp; + let _ = call(|s| s.mouse_up(start.x, start.y, MouseButton::Left)); + let _ = call(|s| s.click(start.x, start.y)); + let _ = call(|s| s.move_mouse(start.x, start.y)); + }, + ScrollState::TriggerDragging(start, prev) if !down => { + servo.scroll_state = ScrollState::TriggerUp; + let delta = (point - prev) * servo.scroll_scale; + let start = start.to_i32(); + let _ = call(|s| s.scroll_end(delta.x, delta.y, start.x, start.y)); + let _ = call(|s| s.mouse_up(x, y, MouseButton::Left)); + }, _ => return, - }; - servo.scroll_state = new_state; - servo.servo.handle_events(window_events); + } } } #[no_mangle] -pub unsafe extern "C" fn traverse_servo(servo: *mut ServoInstance, delta: i32) { +pub unsafe extern "C" fn traverse_servo(_servo: *mut ServoInstance, delta: i32) { // Traverse the session history - if let Some(servo) = servo.as_mut() { - let window_event = if delta == 0 { - WindowEvent::Reload(servo.browser_id) - } else if delta < 0 { - WindowEvent::Navigation(servo.browser_id, TraversalDirection::Back(-delta as usize)) - } else { - WindowEvent::Navigation( - servo.browser_id, - TraversalDirection::Forward(delta as usize), - ) - }; - servo.servo.handle_events(vec![window_event]); + if delta == 0 { + let _ = call(|s| s.reload()); + } else if delta < 0 { + let _ = call(|s| s.go_back()); + } else { + let _ = call(|s| s.go_forward()); } } #[no_mangle] -pub unsafe extern "C" fn navigate_servo(servo: *mut ServoInstance, text: *const c_char) { - if let Some(servo) = servo.as_mut() { - let text = CStr::from_ptr(text) - .to_str() - .expect("Failed to convert text to UTF-8"); - let url = ServoUrl::parse(text).unwrap_or_else(|_| { - let mut search = ServoUrl::parse("https://duckduckgo.com") - .expect("Failed to parse search URL") - .into_url(); - search.query_pairs_mut().append_pair("q", text); - ServoUrl::from_url(search) - }); - let window_event = WindowEvent::LoadUrl(servo.browser_id, url); - servo.servo.handle_events(vec![window_event]); - } +pub unsafe extern "C" fn navigate_servo(_servo: *mut ServoInstance, text: *const c_char) { + let text = CStr::from_ptr(text) + .to_str() + .expect("Failed to convert text to UTF-8"); + let url = ServoUrl::parse(text).unwrap_or_else(|_| { + let mut search = ServoUrl::parse("https://duckduckgo.com") + .expect("Failed to parse search URL") + .into_url(); + search.query_pairs_mut().append_pair("q", text); + ServoUrl::from_url(search) + }); + let _ = call(|s| s.load_uri(url.as_str())); } // Some magic numbers for shutdown @@ -398,44 +273,68 @@ const SHUTDOWN_POLL_INTERVAL: Duration = Duration::from_millis(100); #[no_mangle] pub unsafe extern "C" fn discard_servo(servo: *mut ServoInstance) { if let Some(servo) = servo.as_mut() { - let mut servo = Box::from_raw(servo); + let servo = Box::from_raw(servo); let finish = Instant::now() + SHUTDOWN_DURATION; - servo.servo.handle_events(vec![WindowEvent::Quit]); - 'outer: loop { - for (_, msg) in servo.servo.get_events() { - if let EmbedderMsg::Shutdown = msg { - break 'outer; - } - } + let _ = call(|s| s.request_shutdown()); + while !servo.shut_down_complete.get() { + let _ = call(|s| s.perform_updates()); if Instant::now() > finish { warn!("Incomplete shutdown."); - break 'outer; } thread::sleep(SHUTDOWN_POLL_INTERVAL); - servo.servo.handle_events(vec![]); } - servo.servo.deinit(); + deinit(); + } +} + +struct HostCallbacks { + ctxt: EGLContext, + surf: EGLSurface, + disp: EGLDisplay, + shut_down_complete: Rc>, + history_update: MLHistoryUpdate, + url_update: MLURLUpdate, + app: MLApp, + keyboard: MLKeyboard, +} + +impl HostTrait for HostCallbacks { + fn flush(&self) { + SwapBuffers(self.disp, self.surf); + } + + fn make_current(&self) { + MakeCurrent(self.disp, self.surf, self.surf, self.ctxt); + } + + fn on_load_started(&self) {} + fn on_load_ended(&self) {} + fn on_title_changed(&self, _title: String) {} + fn on_url_changed(&self, url: String) { + if let Ok(cstr) = CString::new(url.as_str()) { + (self.url_update.0)(self.app, cstr.as_ptr()); + } + } + + fn on_history_changed(&self, can_go_back: bool, can_go_forward: bool) { + (self.history_update.0)(self.app, can_go_back, can_go_forward); + } + + fn on_animating_changed(&self, _animating: bool) {} + + fn on_shutdown_complete(&self) { + self.shut_down_complete.set(true); + } + + fn on_ime_state_changed(&self, show: bool) { + (self.keyboard.0)(self.app, show) } } pub struct ServoInstance { - app: MLApp, - browser_id: BrowserId, - history_update: MLHistoryUpdate, - keyboard: MLKeyboard, - servo: Servo, scroll_state: ScrollState, scroll_scale: TypedScale, -} - -struct WindowInstance { - ctxt: EGLContext, - surf: EGLSurface, - disp: EGLDisplay, - gl: Rc, - width: u32, - height: u32, - hidpi: f32, + shut_down_complete: Rc>, } #[derive(Clone, Copy)] @@ -445,52 +344,8 @@ enum ScrollState { TriggerDragging(DevicePoint, DevicePoint), } -impl WindowMethods for WindowInstance { - fn present(&self) { - SwapBuffers(self.disp, self.surf); - } - - fn prepare_for_composite(&self) -> bool { - MakeCurrent(self.disp, self.surf, self.surf, self.ctxt); - true - } - - fn gl(&self) -> Rc { - self.gl.clone() - } - - fn create_event_loop_waker(&self) -> Box { - Box::new(EventLoopWakerInstance::new()) - } - - fn get_coordinates(&self) -> EmbedderCoordinates { - EmbedderCoordinates { - hidpi_factor: TypedScale::new(self.hidpi), - screen: TypedSize2D::new(self.width as i32, self.height as i32), - screen_avail: TypedSize2D::new(self.width as i32, self.height as i32), - window: ( - TypedSize2D::new(self.width as i32, self.height as i32), - TypedPoint2D::new(0, 0), - ), - framebuffer: TypedSize2D::new(self.width as i32, self.height as i32), - viewport: TypedRect::new( - TypedPoint2D::new(0, 0), - TypedSize2D::new(self.width as i32, self.height as i32), - ), - } - } - - fn set_animation_state(&self, _state: AnimationState) {} -} - struct EventLoopWakerInstance; -impl EventLoopWakerInstance { - fn new() -> EventLoopWakerInstance { - EventLoopWakerInstance - } -} - impl EventLoopWaker for EventLoopWakerInstance { fn clone(&self) -> Box { Box::new(EventLoopWakerInstance) @@ -499,47 +354,6 @@ impl EventLoopWaker for EventLoopWakerInstance { fn wake(&self) {} } -struct ResourceReaderInstance; - -impl ResourceReaderInstance { - fn new() -> ResourceReaderInstance { - ResourceReaderInstance - } -} - -impl ResourceReaderMethods for ResourceReaderInstance { - fn read(&self, res: Resource) -> Vec { - Vec::from(match res { - Resource::Preferences => &include_bytes!("../../../resources/prefs.json")[..], - Resource::HstsPreloadList => { - &include_bytes!("../../../resources/hsts_preload.json")[..] - }, - Resource::SSLCertificates => &include_bytes!("../../../resources/certs")[..], - Resource::BadCertHTML => &include_bytes!("../../../resources/badcert.html")[..], - Resource::NetErrorHTML => &include_bytes!("../../../resources/neterror.html")[..], - Resource::UserAgentCSS => &include_bytes!("../../../resources/user-agent.css")[..], - Resource::ServoCSS => &include_bytes!("../../../resources/servo.css")[..], - Resource::PresentationalHintsCSS => { - &include_bytes!("../../../resources/presentational-hints.css")[..] - }, - Resource::QuirksModeCSS => &include_bytes!("../../../resources/quirks-mode.css")[..], - Resource::RippyPNG => &include_bytes!("../../../resources/rippy.png")[..], - Resource::DomainList => &include_bytes!("../../../resources/public_domains.txt")[..], - Resource::BluetoothBlocklist => { - &include_bytes!("../../../resources/gatt_blocklist.txt")[..] - }, - }) - } - - fn sandbox_access_files(&self) -> Vec { - vec![] - } - - fn sandbox_access_files_dirs(&self) -> Vec { - vec![] - } -} - impl log::Log for MLLogger { fn enabled(&self, metadata: &log::Metadata) -> bool { metadata.level() <= LOG_LEVEL diff --git a/ports/libsimpleservo/api/Cargo.toml b/ports/libsimpleservo/api/Cargo.toml index 11e6f03ee5f..a656314b0a2 100644 --- a/ports/libsimpleservo/api/Cargo.toml +++ b/ports/libsimpleservo/api/Cargo.toml @@ -39,3 +39,4 @@ oculusvr = ["libservo/oculusvr"] native-bluetooth = ["libservo/native-bluetooth"] webgl_backtrace = ["libservo/webgl_backtrace"] js_backtrace = ["libservo/js_backtrace"] +no_static_freetype = ["libservo/no_static_freetype"] diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index f805951c2d2..4f493fc54e0 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -7,14 +7,17 @@ extern crate log; pub mod gl_glue; +pub use servo::script_traits::MouseButton; + use servo::compositing::windowing::{ AnimationState, EmbedderCoordinates, MouseWindowEvent, WindowEvent, WindowMethods, }; use servo::embedder_traits::resources::{self, Resource, ResourceReaderMethods}; use servo::embedder_traits::EmbedderMsg; use servo::euclid::{TypedPoint2D, TypedScale, TypedSize2D, TypedVector2D}; +use servo::keyboard_types::{Key, KeyState, KeyboardEvent}; use servo::msg::constellation_msg::TraversalDirection; -use servo::script_traits::{MouseButton, TouchEventType, TouchId}; +use servo::script_traits::{TouchEventType, TouchId}; use servo::servo_config::opts; use servo::servo_config::prefs::{PrefValue, PREFS}; use servo::servo_url::ServoUrl; @@ -82,6 +85,8 @@ pub trait HostTrait { fn on_animating_changed(&self, animating: bool); /// Servo finished shutting down. fn on_shutdown_complete(&self); + /// A text input is focused. + fn on_ime_state_changed(&self, show: bool); } pub struct ServoGlue { @@ -276,12 +281,12 @@ impl ServoGlue { /// Start scrolling. /// x/y are scroll coordinates. /// dx/dy are scroll deltas. - pub fn scroll_start(&mut self, dx: i32, dy: i32, x: u32, y: u32) -> Result<(), &'static str> { - let delta = TypedVector2D::new(dx as f32, dy as f32); + pub fn scroll_start(&mut self, dx: f32, dy: f32, x: i32, y: i32) -> Result<(), &'static str> { + let delta = TypedVector2D::new(dx, dy); let scroll_location = webrender_api::ScrollLocation::Delta(delta); let event = WindowEvent::Scroll( scroll_location, - TypedPoint2D::new(x as i32, y as i32), + TypedPoint2D::new(x, y), TouchEventType::Down, ); self.process_event(event) @@ -290,12 +295,12 @@ impl ServoGlue { /// Scroll. /// x/y are scroll coordinates. /// dx/dy are scroll deltas. - pub fn scroll(&mut self, dx: i32, dy: i32, x: u32, y: u32) -> Result<(), &'static str> { - let delta = TypedVector2D::new(dx as f32, dy as f32); + pub fn scroll(&mut self, dx: f32, dy: f32, x: i32, y: i32) -> Result<(), &'static str> { + let delta = TypedVector2D::new(dx, dy); let scroll_location = webrender_api::ScrollLocation::Delta(delta); let event = WindowEvent::Scroll( scroll_location, - TypedPoint2D::new(x as i32, y as i32), + TypedPoint2D::new(x, y), TouchEventType::Move, ); self.process_event(event) @@ -304,14 +309,11 @@ impl ServoGlue { /// End scrolling. /// x/y are scroll coordinates. /// dx/dy are scroll deltas. - pub fn scroll_end(&mut self, dx: i32, dy: i32, x: u32, y: u32) -> Result<(), &'static str> { - let delta = TypedVector2D::new(dx as f32, dy as f32); + pub fn scroll_end(&mut self, dx: f32, dy: f32, x: i32, y: i32) -> Result<(), &'static str> { + let delta = TypedVector2D::new(dx, dy); let scroll_location = webrender_api::ScrollLocation::Delta(delta); - let event = WindowEvent::Scroll( - scroll_location, - TypedPoint2D::new(x as i32, y as i32), - TouchEventType::Up, - ); + let event = + WindowEvent::Scroll(scroll_location, TypedPoint2D::new(x, y), TouchEventType::Up); self.process_event(event) } @@ -355,6 +357,27 @@ impl ServoGlue { self.process_event(event) } + /// Register a mouse movement. + pub fn move_mouse(&mut self, x: f32, y: f32) -> Result<(), &'static str> { + let point = TypedPoint2D::new(x, y); + let event = WindowEvent::MouseWindowMoveEventClass(point); + self.process_event(event) + } + + /// Register a mouse button press. + pub fn mouse_down(&mut self, x: f32, y: f32, button: MouseButton) -> Result<(), &'static str> { + let point = TypedPoint2D::new(x, y); + let event = WindowEvent::MouseWindowEventClass(MouseWindowEvent::MouseDown(button, point)); + self.process_event(event) + } + + /// Register a mouse button release. + pub fn mouse_up(&mut self, x: f32, y: f32, button: MouseButton) -> Result<(), &'static str> { + let point = TypedPoint2D::new(x, y); + let event = WindowEvent::MouseWindowEventClass(MouseWindowEvent::MouseUp(button, point)); + self.process_event(event) + } + /// Start pinchzoom. /// x/y are pinch origin coordinates. pub fn pinchzoom_start(&mut self, factor: f32, _x: u32, _y: u32) -> Result<(), &'static str> { @@ -374,13 +397,30 @@ impl ServoGlue { } /// Perform a click. - pub fn click(&mut self, x: u32, y: u32) -> Result<(), &'static str> { - let mouse_event = - MouseWindowEvent::Click(MouseButton::Left, TypedPoint2D::new(x as f32, y as f32)); + pub fn click(&mut self, x: f32, y: f32) -> Result<(), &'static str> { + let mouse_event = MouseWindowEvent::Click(MouseButton::Left, TypedPoint2D::new(x, y)); let event = WindowEvent::MouseWindowEventClass(mouse_event); self.process_event(event) } + pub fn key_down(&mut self, key: Key) -> Result<(), &'static str> { + let key_event = KeyboardEvent { + state: KeyState::Down, + key, + ..KeyboardEvent::default() + }; + self.process_event(WindowEvent::Keyboard(key_event)) + } + + pub fn key_up(&mut self, key: Key) -> Result<(), &'static str> { + let key_event = KeyboardEvent { + state: KeyState::Up, + key, + ..KeyboardEvent::default() + }; + self.process_event(WindowEvent::Keyboard(key_event)) + } + fn process_event(&mut self, event: WindowEvent) -> Result<(), &'static str> { self.events.push(event); if !self.batch_mode { diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index 56d85609101..acbf2b0c440 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -40,6 +40,7 @@ pub struct CHostCallbacks { pub on_history_changed: extern "C" fn(can_go_back: bool, can_go_forward: bool), pub on_animating_changed: extern "C" fn(animating: bool), pub on_shutdown_complete: extern "C" fn(), + pub on_ime_state_changed: extern "C" fn(show: bool), } /// Servo options @@ -191,19 +192,19 @@ pub extern "C" fn go_forward() { #[no_mangle] pub extern "C" fn scroll_start(dx: i32, dy: i32, x: i32, y: i32) { debug!("scroll_start"); - call(|s| s.scroll_start(dx as i32, dy as i32, x as u32, y as u32)); + call(|s| s.scroll_start(dx as f32, dy as f32, x, y)); } #[no_mangle] pub extern "C" fn scroll_end(dx: i32, dy: i32, x: i32, y: i32) { debug!("scroll_end"); - call(|s| s.scroll_end(dx as i32, dy as i32, x as u32, y as u32)); + call(|s| s.scroll_end(dx as f32, dy as f32, x, y)); } #[no_mangle] pub extern "C" fn scroll(dx: i32, dy: i32, x: i32, y: i32) { debug!("scroll"); - call(|s| s.scroll(dx as i32, dy as i32, x as u32, y as u32)); + call(|s| s.scroll(dx as f32, dy as f32, x, y)); } #[no_mangle] @@ -251,7 +252,7 @@ pub extern "C" fn pinchzoom_end(factor: f32, x: i32, y: i32) { #[no_mangle] pub extern "C" fn click(x: i32, y: i32) { debug!("click"); - call(|s| s.click(x as u32, y as u32)); + call(|s| s.click(x as f32, y as f32)); } pub struct WakeupCallback(extern "C" fn()); @@ -330,4 +331,9 @@ impl HostTrait for HostCallbacks { debug!("on_shutdown_complete"); (self.0.on_shutdown_complete)(); } + + fn on_ime_state_changed(&self, show: bool) { + debug!("on_ime_state_changed"); + (self.0.on_ime_state_changed)(show); + } } diff --git a/ports/libsimpleservo/jniapi/src/lib.rs b/ports/libsimpleservo/jniapi/src/lib.rs index e3375db7de5..7f287485677 100644 --- a/ports/libsimpleservo/jniapi/src/lib.rs +++ b/ports/libsimpleservo/jniapi/src/lib.rs @@ -200,7 +200,7 @@ pub fn Java_org_mozilla_servoview_JNIServo_scrollStart( ) { debug!("scrollStart"); call(&env, |s| { - s.scroll_start(dx as i32, dy as i32, x as u32, y as u32) + s.scroll_start(dx as f32, dy as f32, x as i32, y as i32) }); } @@ -215,7 +215,7 @@ pub fn Java_org_mozilla_servoview_JNIServo_scrollEnd( ) { debug!("scrollEnd"); call(&env, |s| { - s.scroll_end(dx as i32, dy as i32, x as u32, y as u32) + s.scroll_end(dx as f32, dy as f32, x as i32, y as i32) }); } @@ -229,7 +229,7 @@ pub fn Java_org_mozilla_servoview_JNIServo_scroll( y: jint, ) { debug!("scroll"); - call(&env, |s| s.scroll(dx as i32, dy as i32, x as u32, y as u32)); + call(&env, |s| s.scroll(dx as f32, dy as f32, x as i32, y as i32)); } #[no_mangle] @@ -321,7 +321,7 @@ pub fn Java_org_mozilla_servoview_JNIServo_pinchZoomEnd( #[no_mangle] pub fn Java_org_mozilla_servoview_JNIServo_click(env: JNIEnv, _: JClass, x: jint, y: jint) { debug!("click"); - call(&env, |s| s.click(x as u32, y as u32)); + call(&env, |s| s.click(x as f32, y as f32)); } pub struct WakeupCallback { @@ -454,6 +454,8 @@ impl HostTrait for HostCallbacks { ) .unwrap(); } + + fn on_ime_state_changed(&self, _show: bool) {} } fn initialize_android_glue(env: &JNIEnv, activity: JObject) { diff --git a/support/magicleap/Servo2D/code/inc/Servo2D.h b/support/magicleap/Servo2D/code/inc/Servo2D.h index 88ccbf6cc76..e127332b52d 100644 --- a/support/magicleap/Servo2D/code/inc/Servo2D.h +++ b/support/magicleap/Servo2D/code/inc/Servo2D.h @@ -59,7 +59,12 @@ public: /** * Update the browser history UI */ - void updateHistory(bool canGoBack, const char* url, bool canGoForward); + void updateHistory(bool canGoBack, bool canGoForward); + + /** + * Update the browser url bar. + */ + void updateUrl(const char* url); /** * Make the keyboard visible diff --git a/support/magicleap/Servo2D/code/src/Servo2D.cpp b/support/magicleap/Servo2D/code/src/Servo2D.cpp index c0abce98ec2..6056ebcada2 100644 --- a/support/magicleap/Servo2D/code/src/Servo2D.cpp +++ b/support/magicleap/Servo2D/code/src/Servo2D.cpp @@ -48,9 +48,15 @@ void logger(MLLogLevel lvl, char* msg) { } // A function which updates the history ui, suitable for passing into Servo -typedef void (*MLHistoryUpdate)(Servo2D* app, bool canGoBack, char* url, bool canGoForward); -void history(Servo2D* app, bool canGoBack, char* url, bool canGoForward) { - app->updateHistory(canGoBack, url, canGoForward); +typedef void (*MLHistoryUpdate)(Servo2D* app, bool canGoBack, bool canGoForward); +void history(Servo2D* app, bool canGoBack, bool canGoForward) { + app->updateHistory(canGoBack, canGoForward); +} + +// A function which updates the url ui, suitable for passing into Servo +typedef void (*MLURLUpdate)(Servo2D* app, char* url); +void url(Servo2D* app, char* url) { + app->updateUrl(url); } // A function to show or hide the keyboard @@ -61,7 +67,7 @@ void keyboard(Servo2D* app, bool visible) { // The functions Servo provides for hooking up to the ML. extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay, - Servo2D*, MLLogger, MLHistoryUpdate, MLKeyboard, + Servo2D*, MLLogger, MLHistoryUpdate, MLURLUpdate, MLKeyboard, const char* url, int width, int height, float hidpi); extern "C" void heartbeat_servo(ServoInstance*); extern "C" void keyboard_servo(ServoInstance*, char32_t code, lumin::ui::KeyType keyType); @@ -165,7 +171,7 @@ int Servo2D::init() { EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); // Hook into servo - servo_ = init_servo(ctx, surf, dpy, this, logger, history, keyboard, HOME_PAGE, VIEWPORT_W, VIEWPORT_H, HIDPI); + servo_ = init_servo(ctx, surf, dpy, this, logger, history, url, keyboard, HOME_PAGE, VIEWPORT_W, VIEWPORT_H, HIDPI); if (!servo_) { ML_LOG(Error, "Servo2D Failed to init servo instance"); abort(); @@ -401,8 +407,11 @@ bool Servo2D::keyboardEventListener(const lumin::ui::KeyboardEvent::EventData& e return true; } -void Servo2D::updateHistory(bool canGoBack, const char* url, bool canGoForward) { - back_button_->setEnabled(canGoBack); - fwd_button_->setEnabled(canGoForward); +void Servo2D::updateUrl(const char* url) { url_bar_->setText(url); } + +void Servo2D::updateHistory(bool canGoBack, bool canGoForward) { + back_button_->setEnabled(canGoBack); + fwd_button_->setEnabled(canGoForward); +}