diff options
Diffstat (limited to 'components/servo/examples/winit_minimal.rs')
-rw-r--r-- | components/servo/examples/winit_minimal.rs | 153 |
1 files changed, 79 insertions, 74 deletions
diff --git a/components/servo/examples/winit_minimal.rs b/components/servo/examples/winit_minimal.rs index 8a7ea1a78d5..d7a2a43584f 100644 --- a/components/servo/examples/winit_minimal.rs +++ b/components/servo/examples/winit_minimal.rs @@ -2,19 +2,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use std::error::Error; use std::rc::Rc; -use compositing::windowing::{AnimationState, EmbedderEvent, EmbedderMethods, WindowMethods}; -use embedder_traits::EmbedderMsg; +use compositing::windowing::{AnimationState, EmbedderMethods, WindowMethods}; use euclid::{Point2D, Scale, Size2D}; -use servo::{Servo, WebView}; +use servo::{Servo, TouchEventType, WebView}; use servo_geometry::DeviceIndependentPixel; use surfman::{Connection, SurfaceType}; use tracing::warn; use url::Url; -use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DevicePixel}; +use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DevicePixel, LayoutVector2D}; +use webrender_api::ScrollLocation; use webrender_traits::SurfmanRenderingContext; use winit::application::ApplicationHandler; use winit::dpi::{PhysicalPosition, PhysicalSize}; @@ -34,20 +34,48 @@ fn main() -> Result<(), Box<dyn Error>> { let mut app = App::new(&event_loop); event_loop.run_app(&mut app)?; - if let App::Running { servo, .. } = app { - servo.deinit(); + if let App::Running(state) = app { + if let Some(state) = Rc::into_inner(state) { + state.servo.deinit(); + } } Ok(()) } +struct AppState { + window_delegate: Rc<WindowDelegate>, + servo: Servo, + webviews: RefCell<Vec<WebView>>, +} + +impl ::servo::WebViewDelegate for AppState { + fn notify_ready_to_show(&self, webview: WebView) { + let rect = self + .window_delegate + .get_coordinates() + .get_viewport() + .to_f32(); + webview.focus(); + webview.move_resize(rect); + webview.raise_to_top(true); + } + + fn notify_new_frame_ready(&self, _: WebView) { + self.servo.present(); + } + + fn request_open_auxiliary_webview(&self, parent_webview: WebView) -> Option<WebView> { + let webview = self.servo.new_auxiliary_webview(); + webview.set_delegate(parent_webview.delegate()); + self.webviews.borrow_mut().push(webview.clone()); + Some(webview) + } +} + enum App { Initial(Waker), - Running { - window_delegate: Rc<WindowDelegate>, - servo: Servo, - webviews: Vec<WebView>, - }, + Running(Rc<AppState>), } impl App { @@ -103,15 +131,20 @@ impl ApplicationHandler<WakerEvent> for App { compositing::CompositeTarget::ContextFbo, ); servo.setup_logging(); - let webviews = vec![servo.new_webview( - Url::parse("https://demo.servo.org/experiments/twgl-tunnel/") - .expect("Guaranteed by argument"), - )]; - *self = Self::Running { + + let app_state = Rc::new(AppState { window_delegate, servo, - webviews, - }; + webviews: Default::default(), + }); + + // Make a new WebView and assign the `AppState` as the delegate. + let url = Url::parse("https://servo.org").expect("Guaranteed by argument"); + let webview = app_state.servo.new_webview(url); + webview.set_delegate(app_state.clone()); + app_state.webviews.borrow_mut().push(webview); + + *self = Self::Running(app_state); } } @@ -121,69 +154,41 @@ impl ApplicationHandler<WakerEvent> for App { _window_id: winit::window::WindowId, event: WindowEvent, ) { - if let Self::Running { - window_delegate, - servo, - webviews, - } = self - { - for message in servo.get_events().collect::<Vec<_>>() { - match message { - // FIXME: rust-analyzer autocompletes this as top_level_browsing_context_id - EmbedderMsg::WebViewOpened(webview_id) => { - // TODO: We currently assume `webview` refers to the same webview as `_webview_id` - let rect = window_delegate.get_coordinates().get_viewport().to_f32(); - if let Some(webview) = - webviews.iter().find(|webview| webview.id() == webview_id) - { - webview.focus(); - webview.move_resize(rect); - webview.raise_to_top(true); - } - }, - EmbedderMsg::AllowOpeningWebView(_, webview_id_sender) => { - let webview = servo.new_auxiliary_webview(); - let _ = webview_id_sender.send(Some(webview.id())); - webviews.push(webview); - }, - EmbedderMsg::AllowNavigationRequest(_, pipeline_id, _) => { - servo.handle_events([EmbedderEvent::AllowNavigationResponse( - pipeline_id, - true, - )]); - }, - _ => {}, - } - } - // FIXME: still needed for the compositor to actually run - servo.handle_events([]); + if let Self::Running(state) = self { + state.servo.spin_event_loop(); } + match event { WindowEvent::CloseRequested => { event_loop.exit(); }, WindowEvent::RedrawRequested => { - if let Self::Running { - window_delegate, - servo, - .. - } = self - { - servo.present(); - window_delegate.window.request_redraw(); + if let Self::Running(state) = self { + state.webviews.borrow().last().unwrap().composite(); + state.servo.present(); } }, - WindowEvent::MouseInput { .. } => { - // When the window is clicked, close the last webview by dropping its handle, - // then show the next most recently opened webview. - // - // TODO: Test closing webviews a better way, so that we can use mouse input to test - // input handling. - if let Self::Running { webviews, .. } = self { - let _ = webviews.pop(); - match webviews.last() { - Some(last) => last.show(true), - None => event_loop.exit(), + WindowEvent::MouseWheel { .. } => { + if let Self::Running(state) = self { + if let Some(webview) = state.webviews.borrow().last() { + webview.notify_scroll_event( + ScrollLocation::Delta(LayoutVector2D::new(0., -20.)), + DeviceIntPoint::new(10, 10), + TouchEventType::Down, + ); + } + } + }, + WindowEvent::KeyboardInput { event, .. } => { + // When pressing 'q' close the latest WebView, then show the next most recently + // opened view or quit when none are left. + if event.logical_key.to_text() == Some("q") { + if let Self::Running(state) = self { + let _ = state.webviews.borrow_mut().pop(); + match state.webviews.borrow().last() { + Some(last) => last.show(true), + None => event_loop.exit(), + } } } }, |