aboutsummaryrefslogtreecommitdiffstats
path: root/components/servo/examples/winit_minimal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/servo/examples/winit_minimal.rs')
-rw-r--r--components/servo/examples/winit_minimal.rs153
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(),
+ }
}
}
},