aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-08-29 12:57:58 -0500
committerGitHub <noreply@github.com>2017-08-29 12:57:58 -0500
commitef401dd6373a393ff1d76e31e13d1827a5f0571e (patch)
tree96f245aa38371966f9bb3df0379fd680645ac4cb
parent62930d0073fbf07362b02be0bd774986c8fb94e9 (diff)
parent6bca3402a61d5a06103909b35e358e6ec745b522 (diff)
downloadservo-ef401dd6373a393ff1d76e31e13d1827a5f0571e.tar.gz
servo-ef401dd6373a393ff1d76e31e13d1827a5f0571e.zip
Auto merge of #17269 - gterzian:remove_compositor_forwarding_code_and_use_dedicated_mechanism, r=asajeffrey
Remove compositor forwarding code and use dedicated mechanism <!-- Please describe your changes on the following line: --> @paulrouget Here is a first sketch of the proposed "design", handling a first message as a proof of concept, if you could please already take a look before I move all the messages(or method calls) across... thanks --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [ ] `./mach build -d` does not report any errors - [ ] `./mach test-tidy` does not report any errors - [ ] These changes fix #15934 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17269) <!-- Reviewable:end -->
-rw-r--r--components/canvas/gl_context.rs2
-rw-r--r--components/compositing/compositor.rs295
-rw-r--r--components/compositing/compositor_thread.rs141
-rw-r--r--components/compositing/lib.rs1
-rw-r--r--components/constellation/constellation.rs54
-rw-r--r--components/servo/lib.rs232
6 files changed, 432 insertions, 293 deletions
diff --git a/components/canvas/gl_context.rs b/components/canvas/gl_context.rs
index 69a26c0e03c..ae7446e2eb5 100644
--- a/components/canvas/gl_context.rs
+++ b/components/canvas/gl_context.rs
@@ -27,7 +27,7 @@ impl GLContextFactory {
if cfg!(target_os = "windows") {
// Used to dispatch functions from the GLContext thread to the main thread's event loop.
// Required to allow WGL GLContext sharing in Windows.
- GLContextFactory::Native(handle, Some(MainThreadDispatcher::new(proxy.clone_compositor_proxy())))
+ GLContextFactory::Native(handle, Some(MainThreadDispatcher::new(proxy.clone())))
} else {
GLContextFactory::Native(handle, None)
}
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 8ff38e772c3..c7d18be536f 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -11,7 +11,7 @@ use gfx_traits::Epoch;
use gleam::gl;
use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcSharedMemory};
-use msg::constellation_msg::{KeyState, PipelineId, PipelineIndex, PipelineNamespaceId};
+use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId};
use net_traits::image::base::{Image, PixelFormat};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg};
@@ -34,7 +34,7 @@ use touch::{TouchHandler, TouchAction};
use webrender;
use webrender_api::{self, ClipId, DeviceUintRect, DeviceUintSize, LayoutPoint, LayoutVector2D};
use webrender_api::{ScrollEventPhase, ScrollLocation, ScrollClamping};
-use windowing::{self, MouseWindowEvent, WebRenderDebugOption, WindowEvent, WindowMethods};
+use windowing::{self, MouseWindowEvent, WebRenderDebugOption, WindowMethods};
#[derive(Debug, PartialEq)]
enum UnableToComposite {
@@ -94,7 +94,7 @@ enum LayerPixel {}
/// NB: Never block on the constellation, because sometimes the constellation blocks on us.
pub struct IOCompositor<Window: WindowMethods> {
/// The application window.
- window: Rc<Window>,
+ pub window: Rc<Window>,
/// The port on which we receive messages.
port: CompositorReceiver,
@@ -137,7 +137,7 @@ pub struct IOCompositor<Window: WindowMethods> {
/// Tracks whether we are in the process of shutting down, or have shut down and should close
/// the compositor.
- shutdown_state: ShutdownState,
+ pub shutdown_state: ShutdownState,
/// Tracks the last composite time.
last_composite_time: u64,
@@ -216,7 +216,7 @@ enum CompositionRequest {
}
#[derive(Clone, Copy, Debug, PartialEq)]
-enum ShutdownState {
+pub enum ShutdownState {
NotShuttingDown,
ShuttingDown,
FinishedShuttingDown,
@@ -355,7 +355,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
window_rect: window_rect,
scale: ScaleFactor::new(1.0),
scale_factor: scale_factor,
- channel_to_self: state.sender.clone_compositor_proxy(),
+ channel_to_self: state.sender.clone(),
composition_request: CompositionRequest::NoCompositingNecessary,
touch_handler: TouchHandler::new(),
pending_scroll_zoom_events: Vec::new(),
@@ -386,7 +386,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
let mut compositor = IOCompositor::new(window, state);
let compositor_proxy_for_webrender = compositor.channel_to_self
- .clone_compositor_proxy();
+ .clone();
let render_notifier = RenderNotifier::new(compositor_proxy_for_webrender,
compositor.constellation_chan.clone());
compositor.webrender.set_render_notifier(Box::new(render_notifier));
@@ -404,6 +404,13 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.webrender.deinit();
}
+ pub fn maybe_start_shutting_down(&mut self) {
+ if self.shutdown_state == ShutdownState::NotShuttingDown {
+ debug!("Shutting down the constellation for WindowEvent::Quit");
+ self.start_shutting_down();
+ }
+ }
+
fn start_shutting_down(&mut self) {
debug!("Compositor sending Exit message to Constellation");
if let Err(e) = self.constellation_chan.send(ConstellationMsg::Exit) {
@@ -450,10 +457,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.change_running_animations_state(pipeline_id, animation_state);
}
- (Msg::ChangePageTitle(top_level_browsing_context, title), ShutdownState::NotShuttingDown) => {
- self.window.set_page_title(top_level_browsing_context, title);
- }
-
(Msg::SetFrameTree(frame_tree),
ShutdownState::NotShuttingDown) => {
self.set_frame_tree(&frame_tree);
@@ -465,67 +468,15 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.scroll_fragment_to_point(scroll_root_id, point);
}
- (Msg::MoveTo(top_level_browsing_context_id, point),
- ShutdownState::NotShuttingDown) => {
- self.window.set_position(top_level_browsing_context_id, point);
- }
-
- (Msg::ResizeTo(top_level_browsing_context_id, size),
- ShutdownState::NotShuttingDown) => {
- self.window.set_inner_size(top_level_browsing_context_id, size);
- }
-
- (Msg::GetClientWindow(top_level_browsing_context_id, send),
- ShutdownState::NotShuttingDown) => {
- let rect = self.window.client_window(top_level_browsing_context_id);
- if let Err(e) = send.send(rect) {
- warn!("Sending response to get client window failed ({}).", e);
- }
- }
-
- (Msg::Status(top_level_browsing_context_id, message),
- ShutdownState::NotShuttingDown) => {
- self.window.status(top_level_browsing_context_id, message);
- }
-
- (Msg::LoadStart(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => {
- self.window.load_start(top_level_browsing_context_id);
- }
-
- (Msg::LoadComplete(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => {
- // If we're painting in headless mode, schedule a recomposite.
- if opts::get().output_file.is_some() || opts::get().exit_after_load {
- self.composite_if_necessary(CompositingReason::Headless);
- }
-
- // Inform the embedder that the load has finished.
- self.window.load_end(top_level_browsing_context_id);
- }
-
- (Msg::AllowNavigation(top_level_browsing_context_id, url, response_chan),
- ShutdownState::NotShuttingDown) => {
- self.window.allow_navigation(top_level_browsing_context_id, url, response_chan);
- }
-
(Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => {
self.composition_request = CompositionRequest::CompositeNow(reason)
}
- (Msg::KeyEvent(top_level_browsing_context_id, ch, key, state, modified),
- ShutdownState::NotShuttingDown) => {
- if state == KeyState::Pressed {
- self.window.handle_key(top_level_browsing_context_id, ch, key, modified);
- }
- }
(Msg::TouchEventProcessed(result), ShutdownState::NotShuttingDown) => {
self.touch_handler.on_event_processed(result);
}
- (Msg::SetCursor(cursor), ShutdownState::NotShuttingDown) => {
- self.window.set_cursor(cursor)
- }
-
(Msg::CreatePng(reply), ShutdownState::NotShuttingDown) => {
let res = self.composite_specific_target(CompositeTarget::WindowAndPng);
if let Err(ref e) = res {
@@ -558,18 +509,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.composite_if_necessary(CompositingReason::Headless);
}
- (Msg::NewFavicon(top_level_browsing_context_id, url), ShutdownState::NotShuttingDown) => {
- self.window.set_favicon(top_level_browsing_context_id, url);
- }
-
- (Msg::HeadParsed(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => {
- self.window.head_parsed(top_level_browsing_context_id);
- }
-
- (Msg::HistoryChanged(top_level_browsing_context_id, entries, current), ShutdownState::NotShuttingDown) => {
- self.window.history_changed(top_level_browsing_context_id, entries, current);
- }
-
(Msg::PipelineVisibilityChanged(pipeline_id, visible), ShutdownState::NotShuttingDown) => {
self.pipeline_details(pipeline_id).visible = visible;
if visible {
@@ -597,9 +536,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
func();
}
- (Msg::SetFullscreenState(top_level_browsing_context_id, state), ShutdownState::NotShuttingDown) => {
- self.window.set_fullscreen_state(top_level_browsing_context_id, state);
- }
+ (Msg::LoadComplete(_), ShutdownState::NotShuttingDown) => {
+ // If we're painting in headless mode, schedule a recomposite.
+ if opts::get().output_file.is_some() || opts::get().exit_after_load {
+ self.composite_if_necessary(CompositingReason::Headless);
+ }
+ },
(Msg::PendingPaintMetric(pipeline_id, epoch), _) => {
self.pending_paint_metrics.insert(pipeline_id, epoch);
@@ -608,7 +550,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// When we are shutting_down, we need to avoid performing operations
// such as Paint that may crash because we have begun tearing down
// the rest of our resources.
- (_, ShutdownState::ShuttingDown) => { }
+ (_, ShutdownState::ShuttingDown) => {}
}
true
@@ -717,134 +659,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
ScrollClamping::ToContentBounds);
}
- fn handle_window_message(&mut self, event: WindowEvent) {
- match event {
- WindowEvent::Idle => {}
-
- WindowEvent::Refresh => {
- self.composite();
- }
-
- WindowEvent::Resize(size) => {
- self.on_resize_window_event(size);
- }
-
- WindowEvent::LoadUrl(top_level_browsing_context_id, url) => {
- let msg = ConstellationMsg::LoadUrl(top_level_browsing_context_id, url);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Sending load url to constellation failed ({}).", e);
- }
- }
-
- WindowEvent::MouseWindowEventClass(mouse_window_event) => {
- self.on_mouse_window_event_class(mouse_window_event);
- }
-
- WindowEvent::MouseWindowMoveEventClass(cursor) => {
- self.on_mouse_window_move_event_class(cursor);
- }
-
- WindowEvent::Touch(event_type, identifier, location) => {
- match event_type {
- TouchEventType::Down => self.on_touch_down(identifier, location),
- TouchEventType::Move => self.on_touch_move(identifier, location),
- TouchEventType::Up => self.on_touch_up(identifier, location),
- TouchEventType::Cancel => self.on_touch_cancel(identifier, location),
- }
- }
-
- WindowEvent::Scroll(delta, cursor, phase) => {
- match phase {
- TouchEventType::Move => self.on_scroll_window_event(delta, cursor),
- TouchEventType::Up | TouchEventType::Cancel => {
- self.on_scroll_end_window_event(delta, cursor);
- }
- TouchEventType::Down => {
- self.on_scroll_start_window_event(delta, cursor);
- }
- }
- }
-
- WindowEvent::Zoom(magnification) => {
- self.on_zoom_window_event(magnification);
- }
-
- WindowEvent::ResetZoom => {
- self.on_zoom_reset_window_event();
- }
-
- WindowEvent::PinchZoom(magnification) => {
- self.on_pinch_zoom_window_event(magnification);
- }
-
- WindowEvent::Navigation(top_level_browsing_context_id, direction) => {
- let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Sending navigation to constellation failed ({}).", e);
- }
- }
-
- WindowEvent::TouchpadPressure(cursor, pressure, stage) => {
- self.on_touchpad_pressure_event(cursor, pressure, stage);
- }
-
- WindowEvent::KeyEvent(ch, key, state, modifiers) => {
- let msg = ConstellationMsg::KeyEvent(ch, key, state, modifiers);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Sending key event to constellation failed ({}).", e);
- }
- }
-
- WindowEvent::Quit => {
- if self.shutdown_state == ShutdownState::NotShuttingDown {
- debug!("Shutting down the constellation for WindowEvent::Quit");
- self.start_shutting_down();
- }
- }
-
- WindowEvent::Reload(top_level_browsing_context_id) => {
- let msg = ConstellationMsg::Reload(top_level_browsing_context_id);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Sending reload to constellation failed ({}).", e);
- }
- }
-
- WindowEvent::ToggleWebRenderDebug(option) => {
- let mut flags = self.webrender.get_debug_flags();
- let flag = match option {
- WebRenderDebugOption::Profiler => webrender::PROFILER_DBG,
- WebRenderDebugOption::TextureCacheDebug => webrender::TEXTURE_CACHE_DBG,
- WebRenderDebugOption::RenderTargetDebug => webrender::RENDER_TARGET_DBG,
- };
- flags.toggle(flag);
- self.webrender.set_debug_flags(flags);
- self.webrender_api.generate_frame(self.webrender_document, None);
- }
-
- WindowEvent::NewBrowser(url, response_chan) => {
- let msg = ConstellationMsg::NewBrowser(url, response_chan);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Sending NewBrowser message to constellation failed ({}).", e);
- }
- }
-
- WindowEvent::CloseBrowser(ctx) => {
- let msg = ConstellationMsg::CloseBrowser(ctx);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Sending CloseBrowser message to constellation failed ({}).", e);
- }
- }
-
- WindowEvent::SelectBrowser(ctx) => {
- let msg = ConstellationMsg::SelectBrowser(ctx);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Sending SelectBrowser message to constellation failed ({}).", e);
- }
- }
- }
- }
-
- fn on_resize_window_event(&mut self, new_size: DeviceUintSize) {
+ pub fn on_resize_window_event(&mut self, new_size: DeviceUintSize) {
debug!("compositor resizing to {:?}", new_size.to_untyped());
// A size change could also mean a resolution change.
@@ -868,7 +683,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.send_window_size(WindowSizeType::Resize);
}
- fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) {
+ pub fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) {
if opts::get().convert_mouse_to_touch {
match mouse_window_event {
MouseWindowEvent::Click(_, _) => {}
@@ -914,7 +729,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
- fn on_mouse_window_move_event_class(&mut self, cursor: TypedPoint2D<f32, DevicePixel>) {
+ pub fn on_mouse_window_move_event_class(&mut self, cursor: TypedPoint2D<f32, DevicePixel>) {
if opts::get().convert_mouse_to_touch {
self.on_touch_move(TouchId(0), cursor);
return
@@ -956,6 +771,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
+ pub fn on_touch_event(&mut self,
+ event_type: TouchEventType,
+ identifier: TouchId,
+ location: TypedPoint2D<f32, DevicePixel>) {
+ match event_type {
+ TouchEventType::Down => self.on_touch_down(identifier, location),
+ TouchEventType::Move => self.on_touch_move(identifier, location),
+ TouchEventType::Up => self.on_touch_up(identifier, location),
+ TouchEventType::Cancel => self.on_touch_cancel(identifier, location),
+ }
+ }
+
fn on_touch_down(&mut self, identifier: TouchId, point: TypedPoint2D<f32, DevicePixel>) {
self.touch_handler.on_touch_down(identifier, point);
let dppx = self.page_zoom * self.hidpi_factor();
@@ -1021,7 +848,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
translated_point));
}
- fn on_touchpad_pressure_event(&self,
+ pub fn on_touchpad_pressure_event(&self,
point: TypedPoint2D<f32, DevicePixel>,
pressure: f32,
phase: TouchpadPressurePhase) {
@@ -1043,6 +870,21 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.dispatch_mouse_window_event_class(MouseWindowEvent::Click(button, p));
}
+ pub fn on_scroll_event(&mut self,
+ delta: ScrollLocation,
+ cursor: TypedPoint2D<i32, DevicePixel>,
+ phase: TouchEventType) {
+ match phase {
+ TouchEventType::Move => self.on_scroll_window_event(delta, cursor),
+ TouchEventType::Up | TouchEventType::Cancel => {
+ self.on_scroll_end_window_event(delta, cursor);
+ }
+ TouchEventType::Down => {
+ self.on_scroll_start_window_event(delta, cursor);
+ }
+ }
+ }
+
fn on_scroll_window_event(&mut self,
scroll_location: ScrollLocation,
cursor: TypedPoint2D<i32, DevicePixel>) {
@@ -1261,14 +1103,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.scale = ScaleFactor::new(scale.get());
}
- fn on_zoom_reset_window_event(&mut self) {
+ pub fn on_zoom_reset_window_event(&mut self) {
self.page_zoom = ScaleFactor::new(1.0);
self.update_zoom_transform();
self.send_window_size(WindowSizeType::Resize);
self.update_page_zoom_for_webrender();
}
- fn on_zoom_window_event(&mut self, magnification: f32) {
+ pub fn on_zoom_window_event(&mut self, magnification: f32) {
self.page_zoom = ScaleFactor::new((self.page_zoom.get() * magnification)
.max(MIN_ZOOM).min(MAX_ZOOM));
self.update_zoom_transform();
@@ -1282,7 +1124,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
/// Simulate a pinch zoom
- fn on_pinch_zoom_window_event(&mut self, magnification: f32) {
+ pub fn on_pinch_zoom_window_event(&mut self, magnification: f32) {
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
magnification: magnification,
scroll_location: ScrollLocation::Delta(TypedVector2D::zero()), // TODO: Scroll to keep the center in view?
@@ -1385,7 +1227,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
- fn composite(&mut self) {
+ pub fn composite(&mut self) {
let target = self.composite_target;
match self.composite_specific_target(target) {
Ok(_) => if opts::get().output_file.is_some() || opts::get().exit_after_load {
@@ -1580,7 +1422,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
- pub fn handle_events(&mut self, messages: Vec<WindowEvent>) -> bool {
+ pub fn receive_messages(&mut self) -> bool {
// Check for new messages coming from the other threads in the system.
let mut compositor_messages = vec![];
let mut found_recomposite_msg = false;
@@ -1596,19 +1438,17 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
for msg in compositor_messages {
if !self.handle_browser_message(msg) {
- break
+ return false
}
}
+ true
+ }
+ pub fn perform_updates(&mut self) -> bool {
if self.shutdown_state == ShutdownState::FinishedShuttingDown {
return false;
}
- // Handle any messages coming from the windowing system.
- for message in messages {
- self.handle_window_message(message);
- }
-
// If a pinch-zoom happened recently, ask for tiles at the new resolution
if self.zoom_action && precise_time_s() - self.zoom_time > 0.3 {
self.zoom_action = false;
@@ -1624,7 +1464,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
if !self.pending_scroll_zoom_events.is_empty() && !self.waiting_for_results_of_scroll {
self.process_pending_scroll_events()
}
-
self.shutdown_state != ShutdownState::FinishedShuttingDown
}
@@ -1654,6 +1493,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// TODO(gw): Access via WR.
1.0
}
+
+ pub fn toggle_webrender_debug(&mut self, option: WebRenderDebugOption) {
+ let mut flags = self.webrender.get_debug_flags();
+ let flag = match option {
+ WebRenderDebugOption::Profiler => webrender::PROFILER_DBG,
+ WebRenderDebugOption::TextureCacheDebug => webrender::TEXTURE_CACHE_DBG,
+ WebRenderDebugOption::RenderTargetDebug => webrender::RENDER_TARGET_DBG,
+ };
+ flags.toggle(flag);
+ self.webrender.set_debug_flags(flags);
+ self.webrender_api.generate_frame(self.webrender_document, None);
+ }
}
/// Why we performed a composite. This is used for debugging.
diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs
index 08ecfef50d2..03a7b46c7c0 100644
--- a/components/compositing/compositor_thread.rs
+++ b/components/compositing/compositor_thread.rs
@@ -29,6 +29,45 @@ pub trait EventLoopWaker : 'static + Send {
fn wake(&self);
}
+/// Sends messages to the embedder.
+pub struct EmbedderProxy {
+ pub sender: Sender<EmbedderMsg>,
+ pub event_loop_waker: Box<EventLoopWaker>,
+}
+
+impl EmbedderProxy {
+ pub fn send(&self, msg: EmbedderMsg) {
+ // Send a message and kick the OS event loop awake.
+ if let Err(err) = self.sender.send(msg) {
+ warn!("Failed to send response ({}).", err);
+ }
+ self.event_loop_waker.wake();
+ }
+}
+
+impl Clone for EmbedderProxy {
+ fn clone(&self) -> EmbedderProxy {
+ EmbedderProxy {
+ sender: self.sender.clone(),
+ event_loop_waker: self.event_loop_waker.clone(),
+ }
+ }
+}
+
+/// The port that the embedder receives messages on.
+pub struct EmbedderReceiver {
+ pub receiver: Receiver<EmbedderMsg>
+}
+
+impl EmbedderReceiver {
+ pub fn try_recv_embedder_msg(&mut self) -> Option<EmbedderMsg> {
+ self.receiver.try_recv().ok()
+ }
+ pub fn recv_embedder_msg(&mut self) -> EmbedderMsg {
+ self.receiver.recv().unwrap()
+ }
+}
+
/// Sends messages to the compositor.
pub struct CompositorProxy {
pub sender: Sender<Msg>,
@@ -43,7 +82,10 @@ impl CompositorProxy {
}
self.event_loop_waker.wake();
}
- pub fn clone_compositor_proxy(&self) -> CompositorProxy {
+}
+
+impl Clone for CompositorProxy {
+ fn clone(&self) -> CompositorProxy {
CompositorProxy {
sender: self.sender.clone(),
event_loop_waker: self.event_loop_waker.clone(),
@@ -75,6 +117,37 @@ impl RenderListener for CompositorProxy {
}
}
+pub enum EmbedderMsg {
+ /// A status message to be displayed by the browser chrome.
+ Status(TopLevelBrowsingContextId, Option<String>),
+ /// Alerts the embedder that the current page has changed its title.
+ ChangePageTitle(TopLevelBrowsingContextId, Option<String>),
+ /// Move the window to a point
+ MoveTo(TopLevelBrowsingContextId, Point2D<i32>),
+ /// Resize the window to size
+ ResizeTo(TopLevelBrowsingContextId, Size2D<u32>),
+ /// Get Window Informations size and position
+ GetClientWindow(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>, Point2D<i32>)>),
+ /// Wether or not to follow a link
+ AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>),
+ /// Sends an unconsumed key event back to the embedder.
+ KeyEvent(Option<TopLevelBrowsingContextId>, Option<char>, Key, KeyState, KeyModifiers),
+ /// Changes the cursor.
+ SetCursor(Cursor),
+ /// A favicon was detected
+ NewFavicon(TopLevelBrowsingContextId, ServoUrl),
+ /// <head> tag finished parsing
+ HeadParsed(TopLevelBrowsingContextId),
+ /// The history state has changed.
+ HistoryChanged(TopLevelBrowsingContextId, Vec<LoadData>, usize),
+ /// Enter or exit fullscreen
+ SetFullscreenState(TopLevelBrowsingContextId, bool),
+ /// The load of a page has begun
+ LoadStart(TopLevelBrowsingContextId),
+ /// The load of a page has completed
+ LoadComplete(TopLevelBrowsingContextId),
+}
+
/// Messages from the painting thread and the constellation thread to the compositor thread.
pub enum Msg {
/// Requests that the compositor shut down.
@@ -87,46 +160,20 @@ pub enum Msg {
/// Scroll a page in a window
ScrollFragmentPoint(webrender_api::ClipId, Point2D<f32>, bool),
- /// Alerts the compositor that the current page has changed its title.
- ChangePageTitle(TopLevelBrowsingContextId, Option<String>),
/// Alerts the compositor that the given pipeline has changed whether it is running animations.
ChangeRunningAnimationsState(PipelineId, AnimationState),
/// Replaces the current frame tree, typically called during main frame navigation.
SetFrameTree(SendableFrameTree),
- /// The load of a page has begun
- LoadStart(TopLevelBrowsingContextId),
- /// The load of a page has completed
- LoadComplete(TopLevelBrowsingContextId),
- /// The history state has changed.
- HistoryChanged(TopLevelBrowsingContextId, Vec<LoadData>, usize),
- /// Wether or not to follow a link
- AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>),
/// Composite.
Recomposite(CompositingReason),
- /// Sends an unconsumed key event back to the compositor.
- KeyEvent(Option<TopLevelBrowsingContextId>, Option<char>, Key, KeyState, KeyModifiers),
/// Script has handled a touch event, and either prevented or allowed default actions.
TouchEventProcessed(EventResult),
- /// Changes the cursor.
- SetCursor(Cursor),
/// Composite to a PNG file and return the Image over a passed channel.
CreatePng(IpcSender<Option<Image>>),
/// Alerts the compositor that the viewport has been constrained in some manner
ViewportConstrained(PipelineId, ViewportConstraints),
/// A reply to the compositor asking if the output image is stable.
IsReadyToSaveImageReply(bool),
- /// A favicon was detected
- NewFavicon(TopLevelBrowsingContextId, ServoUrl),
- /// <head> tag finished parsing
- HeadParsed(TopLevelBrowsingContextId),
- /// A status message to be displayed by the browser chrome.
- Status(TopLevelBrowsingContextId, Option<String>),
- /// Get Window Informations size and position
- GetClientWindow(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>, Point2D<i32>)>),
- /// Move the window to a point
- MoveTo(TopLevelBrowsingContextId, Point2D<i32>),
- /// Resize the window to size
- ResizeTo(TopLevelBrowsingContextId, Size2D<u32>),
/// Pipeline visibility changed
PipelineVisibilityChanged(PipelineId, bool),
/// WebRender has successfully processed a scroll. The boolean specifies whether a composite is
@@ -142,12 +189,12 @@ pub enum Msg {
/// It's used to dispatch functions from webrender to the main thread's event loop.
/// Required to allow WGL GLContext sharing in Windows.
Dispatch(Box<Fn() + Send>),
- /// Enter or exit fullscreen
- SetFullscreenState(TopLevelBrowsingContextId, bool),
/// Indicates to the compositor that it needs to record the time when the frame with
/// the given ID (epoch) is painted and report it to the layout thread of the given
/// pipeline ID.
PendingPaintMetric(PipelineId, Epoch),
+ /// The load of a page has completed
+ LoadComplete(TopLevelBrowsingContextId),
}
impl Debug for Msg {
@@ -157,31 +204,39 @@ impl Debug for Msg {
Msg::ShutdownComplete => write!(f, "ShutdownComplete"),
Msg::ScrollFragmentPoint(..) => write!(f, "ScrollFragmentPoint"),
Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"),
- Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
Msg::SetFrameTree(..) => write!(f, "SetFrameTree"),
- Msg::LoadComplete(..) => write!(f, "LoadComplete"),
- Msg::AllowNavigation(..) => write!(f, "AllowNavigation"),
- Msg::LoadStart(..) => write!(f, "LoadStart"),
- Msg::HistoryChanged(..) => write!(f, "HistoryChanged"),
Msg::Recomposite(..) => write!(f, "Recomposite"),
- Msg::KeyEvent(..) => write!(f, "KeyEvent"),
Msg::TouchEventProcessed(..) => write!(f, "TouchEventProcessed"),
- Msg::SetCursor(..) => write!(f, "SetCursor"),
Msg::CreatePng(..) => write!(f, "CreatePng"),
Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"),
Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"),
- Msg::NewFavicon(..) => write!(f, "NewFavicon"),
- Msg::HeadParsed(..) => write!(f, "HeadParsed"),
- Msg::Status(..) => write!(f, "Status"),
- Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
- Msg::MoveTo(..) => write!(f, "MoveTo"),
- Msg::ResizeTo(..) => write!(f, "ResizeTo"),
Msg::PipelineVisibilityChanged(..) => write!(f, "PipelineVisibilityChanged"),
Msg::PipelineExited(..) => write!(f, "PipelineExited"),
Msg::NewScrollFrameReady(..) => write!(f, "NewScrollFrameReady"),
Msg::Dispatch(..) => write!(f, "Dispatch"),
- Msg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
Msg::PendingPaintMetric(..) => write!(f, "PendingPaintMetric"),
+ Msg::LoadComplete(..) => write!(f, "LoadComplete"),
+ }
+ }
+}
+
+impl Debug for EmbedderMsg {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ match *self {
+ EmbedderMsg::Status(..) => write!(f, "Status"),
+ EmbedderMsg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
+ EmbedderMsg::MoveTo(..) => write!(f, "MoveTo"),
+ EmbedderMsg::ResizeTo(..) => write!(f, "ResizeTo"),
+ EmbedderMsg::GetClientWindow(..) => write!(f, "GetClientWindow"),
+ EmbedderMsg::AllowNavigation(..) => write!(f, "AllowNavigation"),
+ EmbedderMsg::KeyEvent(..) => write!(f, "KeyEvent"),
+ EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"),
+ EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"),
+ EmbedderMsg::HeadParsed(..) => write!(f, "HeadParsed"),
+ EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"),
+ EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
+ EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"),
+ EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
}
}
}
diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs
index bb1c769eaaf..38371599678 100644
--- a/components/compositing/lib.rs
+++ b/components/compositing/lib.rs
@@ -26,6 +26,7 @@ extern crate webrender_api;
pub use compositor_thread::CompositorProxy;
pub use compositor::IOCompositor;
+pub use compositor::ShutdownState;
use euclid::TypedSize2D;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId;
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index ad15d1673b8..ae286fedd09 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -74,7 +74,7 @@ use canvas::webgl_thread::WebGLThreads;
use canvas_traits::canvas::CanvasMsg;
use clipboard::{ClipboardContext, ClipboardProvider};
use compositing::SendableFrameTree;
-use compositing::compositor_thread::CompositorProxy;
+use compositing::compositor_thread::{CompositorProxy, EmbedderMsg, EmbedderProxy};
use compositing::compositor_thread::Msg as ToCompositorMsg;
use debugger;
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
@@ -169,6 +169,9 @@ pub struct Constellation<Message, LTF, STF> {
/// A channel for the constellation to receive messages from the compositor thread.
compositor_receiver: Receiver<FromCompositorMsg>,
+ /// A channel through which messages can be sent to the embedder.
+ embedder_proxy: EmbedderProxy,
+
/// A channel (the implementation of which is port-specific) for the
/// constellation to send messages to the compositor thread.
compositor_proxy: CompositorProxy,
@@ -306,6 +309,9 @@ pub struct Constellation<Message, LTF, STF> {
/// State needed to construct a constellation.
pub struct InitialConstellationState {
+ /// A channel through which messages can be sent to the embedder.
+ pub embedder_proxy: EmbedderProxy,
+
/// A channel through which messages can be sent to the compositor.
pub compositor_proxy: CompositorProxy,
@@ -537,6 +543,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
layout_receiver: layout_receiver,
network_listener_sender: network_listener_sender,
network_listener_receiver: network_listener_receiver,
+ embedder_proxy: state.embedder_proxy,
compositor_proxy: state.compositor_proxy,
active_browser_id: None,
debugger_chan: state.debugger_chan,
@@ -692,7 +699,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
},
layout_to_constellation_chan: self.layout_sender.clone(),
scheduler_chan: self.scheduler_chan.clone(),
- compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
+ compositor_proxy: self.compositor_proxy.clone(),
devtools_chan: self.devtools_chan.clone(),
bluetooth_thread: self.bluetooth_thread.clone(),
swmanager_thread: self.swmanager_sender.clone(),
@@ -1152,13 +1159,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::NewFavicon(url) => {
debug!("constellation got new favicon message");
if source_is_top_level_pipeline {
- self.compositor_proxy.send(ToCompositorMsg::NewFavicon(source_top_ctx_id, url));
+ self.embedder_proxy.send(EmbedderMsg::NewFavicon(source_top_ctx_id, url));
}
}
FromScriptMsg::HeadParsed => {
debug!("constellation got head parsed message");
if source_is_top_level_pipeline {
- self.compositor_proxy.send(ToCompositorMsg::HeadParsed(source_top_ctx_id));
+ self.embedder_proxy.send(EmbedderMsg::HeadParsed(source_top_ctx_id));
}
}
FromScriptMsg::CreateCanvasPaintThread(size, sender) => {
@@ -1167,7 +1174,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
FromScriptMsg::NodeStatus(message) => {
debug!("constellation got NodeStatus message");
- self.compositor_proxy.send(ToCompositorMsg::Status(source_top_ctx_id, message));
+ self.embedder_proxy.send(EmbedderMsg::Status(source_top_ctx_id, message));
}
FromScriptMsg::SetDocumentState(state) => {
debug!("constellation got SetDocumentState message");
@@ -1185,15 +1192,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
FromScriptMsg::GetClientWindow(send) => {
- self.compositor_proxy.send(ToCompositorMsg::GetClientWindow(source_top_ctx_id, send));
+ self.embedder_proxy.send(EmbedderMsg::GetClientWindow(source_top_ctx_id, send));
}
FromScriptMsg::MoveTo(point) => {
- self.compositor_proxy.send(ToCompositorMsg::MoveTo(source_top_ctx_id, point));
+ self.embedder_proxy.send(EmbedderMsg::MoveTo(source_top_ctx_id, point));
}
FromScriptMsg::ResizeTo(size) => {
- self.compositor_proxy.send(ToCompositorMsg::ResizeTo(source_top_ctx_id, size));
+ self.embedder_proxy.send(EmbedderMsg::ResizeTo(source_top_ctx_id, size));
}
FromScriptMsg::Exit => {
@@ -1205,13 +1212,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::SetTitle(title) => {
if source_is_top_level_pipeline {
- self.compositor_proxy.send(ToCompositorMsg::ChangePageTitle(source_top_ctx_id, title))
+ self.embedder_proxy.send(EmbedderMsg::ChangePageTitle(source_top_ctx_id, title))
}
}
FromScriptMsg::SendKeyEvent(ch, key, key_state, key_modifiers) => {
- let event = ToCompositorMsg::KeyEvent(Some(source_top_ctx_id), ch, key, key_state, key_modifiers);
- self.compositor_proxy.send(event);
+ let event = EmbedderMsg::KeyEvent(Some(source_top_ctx_id), ch, key, key_state, key_modifiers);
+ self.embedder_proxy.send(event);
}
FromScriptMsg::TouchEventProcessed(result) => {
@@ -1244,7 +1251,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.handle_broadcast_storage_event(source_pipeline_id, storage, url, key, old_value, new_value);
}
FromScriptMsg::SetFullscreenState(state) => {
- self.compositor_proxy.send(ToCompositorMsg::SetFullscreenState(source_top_ctx_id, state));
+ self.embedder_proxy.send(EmbedderMsg::SetFullscreenState(source_top_ctx_id, state));
}
}
}
@@ -1687,7 +1694,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
Some((parent_pipeline_id, frame_type)),
script_sender,
layout_sender,
- self.compositor_proxy.clone_compositor_proxy(),
+ self.compositor_proxy.clone(),
is_private || parent_pipeline.is_private,
url.clone(),
parent_pipeline.visible)
@@ -1719,7 +1726,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
fn handle_set_cursor_msg(&mut self, cursor: Cursor) {
- self.compositor_proxy.send(ToCompositorMsg::SetCursor(cursor))
+ self.embedder_proxy.send(EmbedderMsg::SetCursor(cursor))
}
fn handle_change_running_animations_state(&mut self,
@@ -1793,8 +1800,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
load_data: LoadData, replace: bool) -> Option<PipelineId> {
// Allow the embedder to handle the url itself
let (chan, port) = ipc::channel().expect("Failed to create IPC channel!");
- let msg = ToCompositorMsg::AllowNavigation(top_level_browsing_context_id, load_data.url.clone(), chan);
- self.compositor_proxy.send(msg);
+ let msg = EmbedderMsg::AllowNavigation(top_level_browsing_context_id, load_data.url.clone(), chan);
+ self.embedder_proxy.send(msg);
if let Ok(false) = port.recv() {
return None;
}
@@ -1888,7 +1895,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
pipeline_id: PipelineId) {
if self.pipelines.get(&pipeline_id).and_then(|p| p.parent_info).is_none() {
// Notify embedder top level document started loading.
- self.compositor_proxy.send(ToCompositorMsg::LoadStart(top_level_browsing_context_id));
+ self.embedder_proxy.send(EmbedderMsg::LoadStart(top_level_browsing_context_id));
}
}
@@ -1920,8 +1927,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
.any(|change| change.browsing_context_id == top_level_browsing_context_id);
if !current_top_level_pipeline_will_be_replaced {
- // Notify embedder top level document finished loading.
+ // Notify embedder and compositor top level document finished loading.
self.compositor_proxy.send(ToCompositorMsg::LoadComplete(top_level_browsing_context_id));
+ self.embedder_proxy.send(EmbedderMsg::LoadComplete(top_level_browsing_context_id));
}
}
self.handle_subframe_loaded(pipeline_id);
@@ -1989,8 +1997,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
},
None => {
- let event = ToCompositorMsg::KeyEvent(None, ch, key, state, mods);
- self.compositor_proxy.clone_compositor_proxy().send(event);
+ let event = EmbedderMsg::KeyEvent(None, ch, key, state, mods);
+ self.embedder_proxy.clone().send(event);
}
}
}
@@ -2169,7 +2177,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
},
WebDriverCommandMsg::SetWindowSize(top_level_browsing_context_id, size, reply) => {
self.webdriver.resize_channel = Some(reply);
- self.compositor_proxy.send(ToCompositorMsg::ResizeTo(top_level_browsing_context_id, size));
+ self.embedder_proxy.send(EmbedderMsg::ResizeTo(top_level_browsing_context_id, size));
},
WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, reply) => {
self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, false);
@@ -2402,8 +2410,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
.map(&keep_load_data_if_top_browsing_context)
.scan(current_load_data.clone(), &resolve_load_data));
- let msg = ToCompositorMsg::HistoryChanged(top_level_browsing_context_id, entries, current_index);
- self.compositor_proxy.send(msg);
+ let msg = EmbedderMsg::HistoryChanged(top_level_browsing_context_id, entries, current_index);
+ self.embedder_proxy.send(msg);
}
fn load_url_for_webdriver(&mut self,
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 35cfcef64c6..cddc84707d0 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -21,6 +21,7 @@ extern crate env_logger;
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
extern crate gaol;
extern crate gleam;
+#[macro_use]
extern crate log;
pub extern crate bluetooth;
@@ -70,8 +71,9 @@ use bluetooth::BluetoothThreadFactory;
use bluetooth_traits::BluetoothRequest;
use canvas::gl_context::GLContextFactory;
use canvas::webgl_thread::WebGLThreads;
-use compositing::IOCompositor;
+use compositing::{IOCompositor, ShutdownState};
use compositing::compositor_thread::{self, CompositorProxy, CompositorReceiver, InitialCompositorState};
+use compositing::compositor_thread::{EmbedderMsg, EmbedderProxy, EmbedderReceiver};
use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods;
use constellation::{Constellation, InitialConstellationState, UnprivilegedPipelineContent};
@@ -84,6 +86,7 @@ use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{self, IpcSender};
use log::{Log, LogMetadata, LogRecord};
+use msg::constellation_msg::KeyState;
use net::resource_thread::new_resource_threads;
use net_traits::IpcSend;
use profile::mem as profile_mem;
@@ -121,6 +124,7 @@ pub use msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
pub struct Servo<Window: WindowMethods + 'static> {
compositor: IOCompositor<Window>,
constellation_chan: Sender<ConstellationMsg>,
+ embedder_receiver: EmbedderReceiver
}
impl<Window> Servo<Window> where Window: WindowMethods + 'static {
@@ -137,6 +141,8 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
// to deliver the message.
let (compositor_proxy, compositor_receiver) =
create_compositor_channel(window.create_event_loop_waker());
+ let (embedder_proxy, embedder_receiver) =
+ create_embedder_channel(window.create_event_loop_waker());
let supports_clipboard = window.supports_clipboard();
let time_profiler_chan = profile_time::Profiler::create(&opts.time_profiling,
opts.time_profiler_trace_path.clone());
@@ -207,7 +213,8 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
// as the navigation context.
let (constellation_chan, sw_senders) = create_constellation(opts.user_agent.clone(),
opts.config_dir.clone(),
- compositor_proxy.clone_compositor_proxy(),
+ embedder_proxy.clone(),
+ compositor_proxy.clone(),
time_profiler_chan.clone(),
mem_profiler_chan.clone(),
debugger_chan,
@@ -242,11 +249,214 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
Servo {
compositor: compositor,
constellation_chan: constellation_chan,
+ embedder_receiver: embedder_receiver,
+ }
+ }
+
+ fn handle_window_event(&mut self, event: WindowEvent) {
+ match event {
+ WindowEvent::Idle => {
+ }
+
+ WindowEvent::Refresh => {
+ self.compositor.composite();
+ }
+
+ WindowEvent::Resize(size) => {
+ self.compositor.on_resize_window_event(size);
+ }
+
+ WindowEvent::LoadUrl(top_level_browsing_context_id, url) => {
+ let msg = ConstellationMsg::LoadUrl(top_level_browsing_context_id, url);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Sending load url to constellation failed ({}).", e);
+ }
+ }
+
+ WindowEvent::MouseWindowEventClass(mouse_window_event) => {
+ self.compositor.on_mouse_window_event_class(mouse_window_event);
+ }
+
+ WindowEvent::MouseWindowMoveEventClass(cursor) => {
+ self.compositor.on_mouse_window_move_event_class(cursor);
+ }
+
+ WindowEvent::Touch(event_type, identifier, location) => {
+ self.compositor.on_touch_event(event_type, identifier, location);
+ }
+
+ WindowEvent::Scroll(delta, cursor, phase) => {
+ self.compositor.on_scroll_event(delta, cursor, phase);
+ }
+
+ WindowEvent::Zoom(magnification) => {
+ self.compositor.on_zoom_window_event(magnification);
+ }
+
+ WindowEvent::ResetZoom => {
+ self.compositor.on_zoom_reset_window_event();
+ }
+
+ WindowEvent::PinchZoom(magnification) => {
+ self.compositor.on_pinch_zoom_window_event(magnification);
+ }
+
+ WindowEvent::Navigation(top_level_browsing_context_id, direction) => {
+ let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Sending navigation to constellation failed ({}).", e);
+ }
+ }
+
+ WindowEvent::TouchpadPressure(cursor, pressure, stage) => {
+ self.compositor.on_touchpad_pressure_event(cursor, pressure, stage);
+ }
+
+ WindowEvent::KeyEvent(ch, key, state, modifiers) => {
+ let msg = ConstellationMsg::KeyEvent(ch, key, state, modifiers);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Sending key event to constellation failed ({}).", e);
+ }
+ }
+
+ WindowEvent::Quit => {
+ self.compositor.maybe_start_shutting_down();
+ }
+
+ WindowEvent::Reload(top_level_browsing_context_id) => {
+ let msg = ConstellationMsg::Reload(top_level_browsing_context_id);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Sending reload to constellation failed ({}).", e);
+ }
+ }
+
+ WindowEvent::ToggleWebRenderDebug(option) => {
+ self.compositor.toggle_webrender_debug(option);
+ }
+
+ WindowEvent::NewBrowser(url, response_chan) => {
+ let msg = ConstellationMsg::NewBrowser(url, response_chan);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Sending NewBrowser message to constellation failed ({}).", e);
+ }
+ }
+
+ WindowEvent::SelectBrowser(ctx) => {
+ let msg = ConstellationMsg::SelectBrowser(ctx);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Sending SelectBrowser message to constellation failed ({}).", e);
+ }
+ }
+
+ WindowEvent::CloseBrowser(ctx) => {
+ let msg = ConstellationMsg::CloseBrowser(ctx);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Sending CloseBrowser message to constellation failed ({}).", e);
+ }
+ }
+ }
+ }
+
+ fn receive_messages(&mut self) {
+ while let Some(msg) = self.embedder_receiver.try_recv_embedder_msg() {
+ match (msg, self.compositor.shutdown_state) {
+ (_, ShutdownState::FinishedShuttingDown) => {
+ error!("embedder shouldn't be handling messages after compositor has shut down");
+ },
+
+ (_, ShutdownState::ShuttingDown) => {},
+
+ (EmbedderMsg::Status(top_level_browsing_context, message), ShutdownState::NotShuttingDown) => {
+ self.compositor.window.status(top_level_browsing_context, message);
+ },
+
+ (EmbedderMsg::ChangePageTitle(top_level_browsing_context, title), ShutdownState::NotShuttingDown) => {
+ self.compositor.window.set_page_title(top_level_browsing_context, title);
+ },
+
+ (EmbedderMsg::MoveTo(top_level_browsing_context, point),
+ ShutdownState::NotShuttingDown) => {
+ self.compositor.window.set_position(top_level_browsing_context, point);
+ },
+
+ (EmbedderMsg::ResizeTo(top_level_browsing_context, size),
+ ShutdownState::NotShuttingDown) => {
+ self.compositor.window.set_inner_size(top_level_browsing_context, size);
+ },
+
+ (EmbedderMsg::GetClientWindow(top_level_browsing_context, send),
+ ShutdownState::NotShuttingDown) => {
+ let rect = self.compositor.window.client_window(top_level_browsing_context);
+ if let Err(e) = send.send(rect) {
+ warn!("Sending response to get client window failed ({}).", e);
+ }
+ },
+
+ (EmbedderMsg::AllowNavigation(top_level_browsing_context,
+ url,
+ response_chan),
+ ShutdownState::NotShuttingDown) => {
+ self.compositor.window.allow_navigation(top_level_browsing_context, url, response_chan);
+ },
+
+ (EmbedderMsg::KeyEvent(top_level_browsing_context,
+ ch,
+ key,
+ state,
+ modified),
+ ShutdownState::NotShuttingDown) => {
+ if state == KeyState::Pressed {
+ self.compositor.window.handle_key(top_level_browsing_context, ch, key, modified);
+ }
+ },
+
+ (EmbedderMsg::SetCursor(cursor), ShutdownState::NotShuttingDown) => {
+ self.compositor.window.set_cursor(cursor)
+ },
+
+ (EmbedderMsg::NewFavicon(top_level_browsing_context, url), ShutdownState::NotShuttingDown) => {
+ self.compositor.window.set_favicon(top_level_browsing_context, url);
+ },
+
+ (EmbedderMsg::HeadParsed(top_level_browsing_context, ), ShutdownState::NotShuttingDown) => {
+ self.compositor.window.head_parsed(top_level_browsing_context, );
+ },
+
+ (EmbedderMsg::HistoryChanged(top_level_browsing_context, entries, current),
+ ShutdownState::NotShuttingDown) => {
+ self.compositor.window.history_changed(top_level_browsing_context, entries, current);
+ },
+
+ (EmbedderMsg::SetFullscreenState(top_level_browsing_context, state),
+ ShutdownState::NotShuttingDown) => {
+ self.compositor.window.set_fullscreen_state(top_level_browsing_context, state);
+ },
+
+ (EmbedderMsg::LoadStart(top_level_browsing_context), ShutdownState::NotShuttingDown) => {
+ self.compositor.window.load_start(top_level_browsing_context);
+ },
+
+ (EmbedderMsg::LoadComplete(top_level_browsing_context), ShutdownState::NotShuttingDown) => {
+ // Inform the embedder that the load has finished.
+ //
+ // TODO(pcwalton): Specify which frame's load completed.
+ self.compositor.window.load_end(top_level_browsing_context);
+ },
+ }
}
}
pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
- self.compositor.handle_events(events)
+ if self.compositor.receive_messages() {
+ self.receive_messages();
+ }
+ for event in events {
+ self.handle_window_event(event);
+ }
+ if self.compositor.shutdown_state != ShutdownState::FinishedShuttingDown {
+ self.compositor.perform_updates();
+ }
+ self.compositor.shutdown_state != ShutdownState::FinishedShuttingDown
}
pub fn repaint_synchronously(&mut self) {
@@ -274,13 +484,25 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
}
}
+fn create_embedder_channel(event_loop_waker: Box<compositor_thread::EventLoopWaker>)
+ -> (EmbedderProxy, EmbedderReceiver) {
+ let (sender, receiver) = channel();
+ (EmbedderProxy {
+ sender: sender,
+ event_loop_waker: event_loop_waker,
+ },
+ EmbedderReceiver {
+ receiver: receiver
+ })
+}
+
fn create_compositor_channel(event_loop_waker: Box<compositor_thread::EventLoopWaker>)
-> (CompositorProxy, CompositorReceiver) {
let (sender, receiver) = channel();
(CompositorProxy {
sender: sender,
event_loop_waker: event_loop_waker,
- },
+ },
CompositorReceiver {
receiver: receiver
})
@@ -288,6 +510,7 @@ fn create_compositor_channel(event_loop_waker: Box<compositor_thread::EventLoopW
fn create_constellation(user_agent: Cow<'static, str>,
config_dir: Option<PathBuf>,
+ embedder_proxy: EmbedderProxy,
compositor_proxy: CompositorProxy,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
@@ -336,6 +559,7 @@ fn create_constellation(user_agent: Cow<'static, str>,
let initial_state = InitialConstellationState {
compositor_proxy,
+ embedder_proxy,
debugger_chan,
devtools_chan,
bluetooth_thread,