mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #8641 - notriddle:no_headless, r=glennw
No more headless compositor. Just the normal one. Fixes #8573 <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8641) <!-- Reviewable:end -->
This commit is contained in:
commit
aac2da75f4
26 changed files with 121 additions and 474 deletions
|
@ -525,6 +525,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
(Msg::InitializeLayersForPipeline(pipeline_id, epoch, properties),
|
||||
ShutdownState::NotShuttingDown) => {
|
||||
debug!("initializing layers for pipeline: {:?}", pipeline_id);
|
||||
self.pipeline_details(pipeline_id).current_epoch = epoch;
|
||||
|
||||
self.collect_old_layers(pipeline_id, &properties);
|
||||
|
@ -542,7 +543,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
(Msg::GetNativeDisplay(chan),
|
||||
ShutdownState::NotShuttingDown) => {
|
||||
chan.send(Some(self.native_display.clone())).unwrap();
|
||||
chan.send(self.native_display.clone()).unwrap();
|
||||
}
|
||||
|
||||
(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id),
|
||||
|
@ -641,7 +642,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
reply.send(img).unwrap();
|
||||
}
|
||||
|
||||
(Msg::PaintThreadExited(pipeline_id), ShutdownState::NotShuttingDown) => {
|
||||
(Msg::PaintThreadExited(pipeline_id), _) => {
|
||||
debug!("compositor learned about paint thread exiting: {:?}", pipeline_id);
|
||||
self.remove_pipeline_root_layer(pipeline_id);
|
||||
}
|
||||
|
||||
|
@ -690,8 +692,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
reports_chan.send(reports);
|
||||
}
|
||||
|
||||
(Msg::PipelineExited(pipeline_id), _) => {
|
||||
(Msg::PipelineExited(pipeline_id, sender), _) => {
|
||||
debug!("Compositor got pipeline exited: {:?}", pipeline_id);
|
||||
self.pending_subpages.remove(&pipeline_id);
|
||||
self.remove_pipeline_root_layer(pipeline_id);
|
||||
sender.send(()).unwrap();
|
||||
}
|
||||
|
||||
// When we are shutting_down, we need to avoid performing operations
|
||||
|
|
|
@ -9,7 +9,6 @@ use compositor::{self, CompositingReason};
|
|||
use euclid::point::Point2D;
|
||||
use euclid::size::Size2D;
|
||||
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerProperties, PaintListener};
|
||||
use headless;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use layers::layers::{BufferRequest, LayerBufferSet};
|
||||
use layers::platform::surface::{NativeDisplay, NativeSurface};
|
||||
|
@ -98,6 +97,8 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
|
|||
ScriptToCompositorMsg::TouchEventProcessed(result) => {
|
||||
compositor_proxy.send(Msg::TouchEventProcessed(result))
|
||||
}
|
||||
|
||||
ScriptToCompositorMsg::Exited => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +124,7 @@ impl PaintListener for Box<CompositorProxy + 'static + Send> {
|
|||
// just return None in this case, since the paint thread
|
||||
// will exit shortly and never actually be requested
|
||||
// to paint buffers by the compositor.
|
||||
port.recv().unwrap_or(None)
|
||||
port.recv().ok()
|
||||
}
|
||||
|
||||
fn assign_painted_buffers(&mut self,
|
||||
|
@ -174,9 +175,7 @@ pub enum Msg {
|
|||
/// Requests the compositor's graphics metadata. Graphics metadata is what the painter needs
|
||||
/// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this
|
||||
/// is the pixel format.
|
||||
///
|
||||
/// The headless compositor returns `None`.
|
||||
GetNativeDisplay(Sender<Option<NativeDisplay>>),
|
||||
GetNativeDisplay(Sender<NativeDisplay>),
|
||||
|
||||
/// Tells the compositor to create or update the layers for a pipeline if necessary
|
||||
/// (i.e. if no layer with that ID exists).
|
||||
|
@ -233,7 +232,11 @@ pub enum Msg {
|
|||
/// Resize the window to size
|
||||
ResizeTo(Size2D<u32>),
|
||||
/// A pipeline was shut down.
|
||||
PipelineExited(PipelineId),
|
||||
// This message acts as a synchronization point between the constellation,
|
||||
// when it shuts down a pipeline, to the compositor; when the compositor
|
||||
// sends a reply on the IpcSender, the constellation knows it's safe to
|
||||
// tear down the other threads associated with this pipeline.
|
||||
PipelineExited(PipelineId, IpcSender<()>),
|
||||
}
|
||||
|
||||
impl Debug for Msg {
|
||||
|
@ -276,20 +279,12 @@ impl Debug for Msg {
|
|||
pub struct CompositorThread;
|
||||
|
||||
impl CompositorThread {
|
||||
pub fn create<Window>(window: Option<Rc<Window>>,
|
||||
pub fn create<Window>(window: Rc<Window>,
|
||||
state: InitialCompositorState)
|
||||
-> Box<CompositorEventListener + 'static>
|
||||
where Window: WindowMethods + 'static {
|
||||
match window {
|
||||
Some(window) => {
|
||||
box compositor::IOCompositor::create(window, state)
|
||||
as Box<CompositorEventListener>
|
||||
}
|
||||
None => {
|
||||
box headless::NullCompositor::create(state)
|
||||
as Box<CompositorEventListener>
|
||||
}
|
||||
}
|
||||
box compositor::IOCompositor::create(window, state)
|
||||
as Box<CompositorEventListener>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -648,8 +648,13 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
}
|
||||
// Update pipeline url after redirections
|
||||
Request::Script(FromScriptMsg::SetFinalUrl(pipeline_id, final_url)) => {
|
||||
debug!("constellation got set final url message");
|
||||
self.mut_pipeline(pipeline_id).url = final_url;
|
||||
// The script may have finished loading after we already started shutting down.
|
||||
if let Some(ref mut pipeline) = self.pipelines.get_mut(&pipeline_id) {
|
||||
debug!("constellation got set final url message");
|
||||
pipeline.url = final_url;
|
||||
} else {
|
||||
debug!("constellation got set final url message for dead pipeline");
|
||||
}
|
||||
}
|
||||
Request::Script(FromScriptMsg::MozBrowserEvent(pipeline_id,
|
||||
subpage_id,
|
||||
|
@ -693,9 +698,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
}
|
||||
}
|
||||
}
|
||||
Request::Script(FromScriptMsg::RemoveIFrame(pipeline_id)) => {
|
||||
Request::Script(FromScriptMsg::RemoveIFrame(pipeline_id, sender)) => {
|
||||
debug!("constellation got remove iframe message");
|
||||
self.handle_remove_iframe_msg(pipeline_id);
|
||||
if let Some(sender) = sender {
|
||||
sender.send(()).unwrap();
|
||||
}
|
||||
}
|
||||
Request::Script(FromScriptMsg::NewFavicon(url)) => {
|
||||
debug!("constellation got new favicon message");
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use AnimationTickType;
|
||||
use CompositorMsg as ConstellationMsg;
|
||||
use compositor_thread::{CompositorEventListener, CompositorReceiver};
|
||||
use compositor_thread::{InitialCompositorState, Msg};
|
||||
use euclid::scale_factor::ScaleFactor;
|
||||
use euclid::{Point2D, Size2D};
|
||||
use msg::constellation_msg::WindowSizeData;
|
||||
use profile_traits::mem;
|
||||
use profile_traits::time;
|
||||
use script_traits::AnimationState;
|
||||
use std::sync::mpsc::Sender;
|
||||
use util::opts;
|
||||
use windowing::WindowEvent;
|
||||
|
||||
/// Starts the compositor, which listens for messages on the specified port.
|
||||
///
|
||||
/// This is the null compositor which doesn't draw anything to the screen.
|
||||
/// It's intended for headless testing.
|
||||
pub struct NullCompositor {
|
||||
/// The port on which we receive messages.
|
||||
pub port: Box<CompositorReceiver>,
|
||||
/// A channel to the constellation.
|
||||
constellation_chan: Sender<ConstellationMsg>,
|
||||
/// A channel to the time profiler.
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
/// A channel to the memory profiler.
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
}
|
||||
|
||||
impl NullCompositor {
|
||||
fn new(state: InitialCompositorState) -> NullCompositor {
|
||||
NullCompositor {
|
||||
port: state.receiver,
|
||||
constellation_chan: state.constellation_chan,
|
||||
time_profiler_chan: state.time_profiler_chan,
|
||||
mem_profiler_chan: state.mem_profiler_chan,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(state: InitialCompositorState) -> NullCompositor {
|
||||
let compositor = NullCompositor::new(state);
|
||||
|
||||
// Tell the constellation about the initial fake size.
|
||||
{
|
||||
compositor.constellation_chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
|
||||
initial_viewport: Size2D::typed(800_f32, 600_f32),
|
||||
visible_viewport: Size2D::typed(800_f32, 600_f32),
|
||||
device_pixel_ratio:
|
||||
ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)),
|
||||
})).unwrap();
|
||||
}
|
||||
|
||||
compositor
|
||||
}
|
||||
}
|
||||
|
||||
impl CompositorEventListener for NullCompositor {
|
||||
fn handle_events(&mut self, _: Vec<WindowEvent>) -> bool {
|
||||
match self.port.recv_compositor_msg() {
|
||||
Msg::Exit(chan) => {
|
||||
debug!("shutting down the constellation");
|
||||
self.constellation_chan.send(ConstellationMsg::Exit).unwrap();
|
||||
chan.send(()).unwrap();
|
||||
}
|
||||
|
||||
Msg::ShutdownComplete => {
|
||||
debug!("constellation completed shutdown");
|
||||
|
||||
// Drain compositor port, sometimes messages contain channels that are blocking
|
||||
// another thread from finishing (i.e. SetIds)
|
||||
while self.port.try_recv_compositor_msg().is_some() {}
|
||||
|
||||
self.time_profiler_chan.send(time::ProfilerMsg::Exit);
|
||||
self.mem_profiler_chan.send(mem::ProfilerMsg::Exit);
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Msg::GetNativeDisplay(chan) => {
|
||||
chan.send(None).unwrap();
|
||||
}
|
||||
|
||||
Msg::SetFrameTree(_, response_chan, _) => {
|
||||
response_chan.send(()).unwrap();
|
||||
}
|
||||
|
||||
Msg::GetClientWindow(send) => {
|
||||
let rect = (Size2D::zero(), Point2D::zero());
|
||||
send.send(rect).unwrap();
|
||||
}
|
||||
|
||||
Msg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
|
||||
match animation_state {
|
||||
AnimationState::AnimationsPresent |
|
||||
AnimationState::NoAnimationsPresent |
|
||||
AnimationState::NoAnimationCallbacksPresent => {}
|
||||
AnimationState::AnimationCallbacksPresent => {
|
||||
let msg = ConstellationMsg::TickAnimation(pipeline_id, AnimationTickType::Script);
|
||||
self.constellation_chan.send(msg).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly list ignored messages so that when we add a new one,
|
||||
// we'll notice and think about whether it needs a response, like
|
||||
// SetFrameTree.
|
||||
|
||||
Msg::InitializeLayersForPipeline(..) |
|
||||
Msg::AssignPaintedBuffers(..) |
|
||||
Msg::ScrollFragmentPoint(..) |
|
||||
Msg::Status(..) |
|
||||
Msg::LoadStart(..) |
|
||||
Msg::LoadComplete(..) |
|
||||
Msg::DelayedCompositionTimeout(..) |
|
||||
Msg::Recomposite(..) |
|
||||
Msg::ChangePageTitle(..) |
|
||||
Msg::ChangePageUrl(..) |
|
||||
Msg::KeyEvent(..) |
|
||||
Msg::TouchEventProcessed(..) |
|
||||
Msg::SetCursor(..) |
|
||||
Msg::ViewportConstrained(..) => {}
|
||||
Msg::CreatePng(..) |
|
||||
Msg::PaintThreadExited(..) |
|
||||
Msg::MoveTo(..) |
|
||||
Msg::ResizeTo(..) |
|
||||
Msg::IsReadyToSaveImageReply(..) => {}
|
||||
Msg::NewFavicon(..) => {}
|
||||
Msg::HeadParsed => {}
|
||||
Msg::ReturnUnusedNativeSurfaces(..) => {}
|
||||
Msg::CollectMemoryReports(..) => {}
|
||||
Msg::PipelineExited(..) => {}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn repaint_synchronously(&mut self) {}
|
||||
|
||||
fn pinch_zoom_level(&self) -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
fn title_for_main_frame(&self) {}
|
||||
}
|
|
@ -68,7 +68,6 @@ mod compositor_layer;
|
|||
pub mod compositor_thread;
|
||||
pub mod constellation;
|
||||
mod delayed_composition;
|
||||
mod headless;
|
||||
pub mod pipeline;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub mod sandboxing;
|
||||
|
|
|
@ -28,13 +28,13 @@ use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg};
|
|||
use script_traits::{ScriptToCompositorMsg, ScriptThreadFactory, TimerEventRequest};
|
||||
use std::mem;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use std::thread;
|
||||
use url::Url;
|
||||
use util;
|
||||
use util::geometry::{PagePx, ViewportPx};
|
||||
use util::ipc::OptionalIpcSender;
|
||||
use util::opts::{self, Opts};
|
||||
use util::prefs;
|
||||
use util::thread;
|
||||
use webrender_traits;
|
||||
|
||||
/// A uniquely-identifiable pipeline of script thread, layout thread, and paint thread.
|
||||
|
@ -290,6 +290,13 @@ impl Pipeline {
|
|||
pub fn exit(&self) {
|
||||
debug!("pipeline {:?} exiting", self.id);
|
||||
|
||||
// The compositor wants to know when pipelines shut down too.
|
||||
// It may still have messages to process from these other threads
|
||||
// before they can be safely shut down.
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id, sender));
|
||||
receiver.recv().unwrap();
|
||||
|
||||
// Script thread handles shutting down layout, and layout handles shutting down the painter.
|
||||
// For now, if the script thread has failed, we give up on clean shutdown.
|
||||
if self.script_chan
|
||||
|
@ -300,9 +307,6 @@ impl Pipeline {
|
|||
let _ = self.paint_shutdown_port.recv();
|
||||
let _ = self.layout_shutdown_port.recv();
|
||||
}
|
||||
|
||||
// The compositor wants to know when pipelines shut down too.
|
||||
self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id))
|
||||
}
|
||||
|
||||
pub fn freeze(&self) {
|
||||
|
@ -472,7 +476,7 @@ impl PrivilegedPipelineContent {
|
|||
let compositor_proxy_for_script_listener_thread =
|
||||
self.compositor_proxy.clone_compositor_proxy();
|
||||
let script_to_compositor_port = self.script_to_compositor_port;
|
||||
thread::spawn(move || {
|
||||
thread::spawn_named("CompositorScriptListener".to_owned(), move || {
|
||||
compositor_thread::run_script_listener_thread(
|
||||
compositor_proxy_for_script_listener_thread,
|
||||
script_to_compositor_port)
|
||||
|
|
|
@ -15,7 +15,6 @@ use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
|||
use net_traits::net_error_list::NetError;
|
||||
use script_traits::{MouseButton, TouchEventType, TouchId};
|
||||
use std::fmt::{Debug, Error, Formatter};
|
||||
use std::rc::Rc;
|
||||
use style_traits::cursor::Cursor;
|
||||
use url::Url;
|
||||
use util::geometry::ScreenPx;
|
||||
|
@ -142,7 +141,7 @@ pub trait WindowMethods {
|
|||
///
|
||||
/// This is part of the windowing system because its implementation often involves OS-specific
|
||||
/// magic to wake the up window's event loop.
|
||||
fn create_compositor_channel(_: &Option<Rc<Self>>)
|
||||
fn create_compositor_channel(&self)
|
||||
-> (Box<CompositorProxy + Send>, Box<CompositorReceiver>);
|
||||
|
||||
/// Requests that the window system prepare a composite. Typically this will involve making
|
||||
|
|
|
@ -342,7 +342,7 @@ pub enum Msg {
|
|||
#[derive(Deserialize, Serialize)]
|
||||
pub enum LayoutToPaintMsg {
|
||||
PaintInit(Epoch, Arc<DisplayList>),
|
||||
Exit(IpcSender<()>),
|
||||
Exit,
|
||||
}
|
||||
|
||||
pub enum ChromeToPaintMsg {
|
||||
|
@ -505,21 +505,20 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
|
|||
// FIXME(njn): should eventually measure the paint thread.
|
||||
channel.send(Vec::new())
|
||||
}
|
||||
Msg::FromLayout(LayoutToPaintMsg::Exit(ref response_channel)) => {
|
||||
Msg::FromLayout(LayoutToPaintMsg::Exit) => {
|
||||
// Ask the compositor to remove any layers it is holding for this paint thread.
|
||||
// FIXME(mrobinson): This can probably move back to the constellation now.
|
||||
debug!("PaintThread: Exiting.");
|
||||
self.compositor.notify_paint_thread_exiting(self.id);
|
||||
|
||||
debug!("PaintThread: Exiting.");
|
||||
let _ = response_channel.send(());
|
||||
break;
|
||||
}
|
||||
Msg::FromChrome(ChromeToPaintMsg::Exit) => {
|
||||
// Ask the compositor to remove any layers it is holding for this paint thread.
|
||||
// FIXME(mrobinson): This can probably move back to the constellation now.
|
||||
debug!("PaintThread: Exiting.");
|
||||
self.compositor.notify_paint_thread_exiting(self.id);
|
||||
|
||||
debug!("PaintThread: Exiting.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -777,9 +777,7 @@ impl LayoutThread {
|
|||
traversal.shutdown()
|
||||
}
|
||||
|
||||
let (response_chan, response_port) = ipc::channel().unwrap();
|
||||
self.paint_chan.send(LayoutToPaintMsg::Exit(response_chan)).unwrap();
|
||||
response_port.recv().unwrap()
|
||||
self.paint_chan.send(LayoutToPaintMsg::Exit).unwrap();
|
||||
}
|
||||
|
||||
fn handle_add_stylesheet<'a, 'b>(&self,
|
||||
|
|
|
@ -28,6 +28,7 @@ use dom::node::{Node, UnbindContext, window_from_node, document_from_node};
|
|||
use dom::urlhelper::UrlHelper;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use dom::window::{ReflowReason, Window};
|
||||
use ipc_channel::ipc;
|
||||
use js::jsapi::{JSAutoCompartment, JSAutoRequest, RootedValue, JSContext, MutableHandleValue};
|
||||
use js::jsval::{UndefinedValue, NullValue};
|
||||
use layout_interface::ReflowQueryType;
|
||||
|
@ -559,9 +560,30 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
let window = window_from_node(self);
|
||||
let window = window.r();
|
||||
|
||||
// The only reason we're waiting for the iframe to be totally
|
||||
// removed is to ensure the script thread can't add iframes faster
|
||||
// than the compositor can remove them.
|
||||
//
|
||||
// Since most of this cleanup doesn't happen on same-origin
|
||||
// iframes, and since that would cause a deadlock, don't do it.
|
||||
let ConstellationChan(ref chan) = window.constellation_chan();
|
||||
let msg = ConstellationMsg::RemoveIFrame(pipeline_id);
|
||||
let same_origin = if let Some(self_url) = self.get_url() {
|
||||
let win_url = window_from_node(self).get_url();
|
||||
UrlHelper::SameOrigin(&self_url, &win_url)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let (sender, receiver) = if same_origin {
|
||||
(None, None)
|
||||
} else {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
(Some(sender), Some(receiver))
|
||||
};
|
||||
let msg = ConstellationMsg::RemoveIFrame(pipeline_id, sender);
|
||||
chan.send(msg).unwrap();
|
||||
if let Some(receiver) = receiver {
|
||||
receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
// Resetting the subpage id to None is required here so that
|
||||
// if this iframe is subsequently re-added to the document
|
||||
|
|
|
@ -1060,7 +1060,7 @@ impl Window {
|
|||
// When all these conditions are met, notify the constellation
|
||||
// that this pipeline is ready to write the image (from the script thread
|
||||
// perspective at least).
|
||||
if opts::get().output_file.is_some() && for_display {
|
||||
if (opts::get().output_file.is_some() || opts::get().exit_after_load) && for_display {
|
||||
let document = self.Document();
|
||||
|
||||
// Checks if the html element has reftest-wait attribute present.
|
||||
|
|
|
@ -548,6 +548,7 @@ impl ScriptThreadFactory for ScriptThread {
|
|||
let reporter_name = format!("script-reporter-{}", id);
|
||||
mem_profiler_chan.run_with_memory_reporting(|| {
|
||||
script_thread.start();
|
||||
let _ = script_thread.compositor.borrow_mut().send(ScriptToCompositorMsg::Exited);
|
||||
let _ = script_thread.content_process_shutdown_chan.send(());
|
||||
}, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports);
|
||||
|
||||
|
|
|
@ -365,6 +365,8 @@ pub enum ScriptToCompositorMsg {
|
|||
TouchEventProcessed(EventResult),
|
||||
/// Requests that the compositor shut down.
|
||||
Exit,
|
||||
/// Allow the compositor to free script-specific resources.
|
||||
Exited,
|
||||
}
|
||||
|
||||
/// Whether a DOM event was prevented by web content
|
||||
|
|
|
@ -74,7 +74,7 @@ pub enum ScriptMsg {
|
|||
/// Status message to be displayed in the chrome, eg. a link URL on mouseover.
|
||||
NodeStatus(Option<String>),
|
||||
/// Notification that this iframe should be removed.
|
||||
RemoveIFrame(PipelineId),
|
||||
RemoveIFrame(PipelineId, Option<IpcSender<()>>),
|
||||
/// A load has been requested in an IFrame.
|
||||
ScriptLoadedURLInIFrame(IFrameLoadInfo),
|
||||
/// Requests that the constellation set the contents of the clipboard
|
||||
|
|
|
@ -60,9 +60,7 @@ git = "https://github.com/servo/webrender_traits"
|
|||
git = "https://github.com/servo/webrender"
|
||||
|
||||
[features]
|
||||
default = ["glutin_app", "window", "webdriver"]
|
||||
window = ["glutin_app/window"]
|
||||
headless = ["glutin_app/headless"]
|
||||
default = ["glutin_app", "webdriver"]
|
||||
webdriver = ["webdriver_server"]
|
||||
energy-profiling = ["profile_traits/energy-profiling"]
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ use profile::mem as profile_mem;
|
|||
use profile::time as profile_time;
|
||||
use profile_traits::mem;
|
||||
use profile_traits::time;
|
||||
use std::borrow::Borrow;
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use util::opts;
|
||||
|
@ -103,7 +102,7 @@ pub struct Browser {
|
|||
}
|
||||
|
||||
impl Browser {
|
||||
pub fn new<Window>(window: Option<Rc<Window>>) -> Browser
|
||||
pub fn new<Window>(window: Rc<Window>) -> Browser
|
||||
where Window: WindowMethods + 'static {
|
||||
// Global configuration options, parsed from the command line.
|
||||
let opts = opts::get();
|
||||
|
@ -115,14 +114,8 @@ impl Browser {
|
|||
// messages to client may need to pump a platform-specific event loop
|
||||
// to deliver the message.
|
||||
let (compositor_proxy, compositor_receiver) =
|
||||
WindowMethods::create_compositor_channel(&window);
|
||||
let supports_clipboard = match window {
|
||||
Some(ref win_rc) => {
|
||||
let win: &Window = win_rc.borrow();
|
||||
win.supports_clipboard()
|
||||
}
|
||||
None => false
|
||||
};
|
||||
window.create_compositor_channel();
|
||||
let supports_clipboard = window.supports_clipboard();
|
||||
let time_profiler_chan = profile_time::Profiler::create(opts.time_profiler_period);
|
||||
let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
|
||||
let devtools_chan = opts.devtools_port.map(|port| {
|
||||
|
@ -134,9 +127,7 @@ impl Browser {
|
|||
resource_path.push("shaders");
|
||||
|
||||
// TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
|
||||
let hidpi_factor = window.as_ref()
|
||||
.map(|window| window.hidpi_factor().get())
|
||||
.unwrap_or(1.0);
|
||||
let hidpi_factor = window.hidpi_factor().get();
|
||||
let device_pixel_ratio = match opts.device_pixels_per_px {
|
||||
Some(device_pixels_per_px) => device_pixels_per_px,
|
||||
None => match opts.output_file {
|
||||
|
|
|
@ -32,21 +32,11 @@ extern crate offscreen_gl_context;
|
|||
// The Servo engine
|
||||
extern crate servo;
|
||||
|
||||
use gleam::gl;
|
||||
use offscreen_gl_context::{GLContext, NativeGLContext};
|
||||
use servo::Browser;
|
||||
use servo::compositing::windowing::WindowEvent;
|
||||
use servo::util::opts::{self, ArgumentParsingResult};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn load_gl_when_headless() {
|
||||
gl::load_with(|addr| GLContext::<NativeGLContext>::get_proc_address(addr) as *const _);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn load_gl_when_headless() {}
|
||||
|
||||
fn main() {
|
||||
// Parse the command line options and store them globally
|
||||
let opts_result = opts::from_cmdline_args(&*args());
|
||||
|
@ -69,14 +59,7 @@ fn main() {
|
|||
return servo::run_content_process(token)
|
||||
}
|
||||
|
||||
let window = if opts::get().headless {
|
||||
// Load gl functions even when in headless mode,
|
||||
// to avoid crashing with WebGL
|
||||
load_gl_when_headless();
|
||||
None
|
||||
} else {
|
||||
Some(app::create_window(None))
|
||||
};
|
||||
let window = app::create_window(None);
|
||||
|
||||
// Our wrapper around `Browser` that also implements some
|
||||
// callbacks required by the glutin window implementation.
|
||||
|
@ -84,45 +67,32 @@ fn main() {
|
|||
browser: Browser::new(window.clone()),
|
||||
};
|
||||
|
||||
maybe_register_glutin_resize_handler(&window, &mut browser);
|
||||
register_glutin_resize_handler(&window, &mut browser);
|
||||
|
||||
browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);
|
||||
|
||||
// Feed events from the window to the browser until the browser
|
||||
// says to stop.
|
||||
loop {
|
||||
let should_continue = match window {
|
||||
None => browser.browser.handle_events(Vec::new()),
|
||||
Some(ref window) => browser.browser.handle_events(window.wait_events()),
|
||||
};
|
||||
let should_continue = browser.browser.handle_events(window.wait_events());
|
||||
if !should_continue {
|
||||
break
|
||||
}
|
||||
};
|
||||
|
||||
maybe_unregister_glutin_resize_handler(&window);
|
||||
unregister_glutin_resize_handler(&window);
|
||||
}
|
||||
|
||||
fn maybe_register_glutin_resize_handler(window: &Option<Rc<app::window::Window>>,
|
||||
fn register_glutin_resize_handler(window: &Rc<app::window::Window>,
|
||||
browser: &mut BrowserWrapper) {
|
||||
match *window {
|
||||
None => {}
|
||||
Some(ref window) => {
|
||||
unsafe {
|
||||
window.set_nested_event_loop_listener(browser);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
window.set_nested_event_loop_listener(browser);
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_unregister_glutin_resize_handler(window: &Option<Rc<app::window::Window>>) {
|
||||
match *window {
|
||||
None => {}
|
||||
Some(ref window) => {
|
||||
unsafe {
|
||||
window.remove_nested_event_loop_listener();
|
||||
}
|
||||
}
|
||||
fn unregister_glutin_resize_handler(window: &Rc<app::window::Window>) {
|
||||
unsafe {
|
||||
window.remove_nested_event_loop_listener();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue