mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
forward EmbedderMsg to embedder
This commit is contained in:
parent
10abe03948
commit
5e33dcd29d
4 changed files with 151 additions and 238 deletions
|
@ -9,14 +9,12 @@ use euclid::TypedScale;
|
||||||
use gleam::gl;
|
use gleam::gl;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection};
|
use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection};
|
||||||
use net_traits::net_error_list::NetError;
|
use script_traits::{MouseButton, TouchEventType, TouchId};
|
||||||
use script_traits::{LoadData, MouseButton, TouchEventType, TouchId};
|
|
||||||
use servo_geometry::{DeviceIndependentPixel, DeviceUintLength};
|
use servo_geometry::{DeviceIndependentPixel, DeviceUintLength};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::fmt::{Debug, Error, Formatter};
|
use std::fmt::{Debug, Error, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use style_traits::DevicePixel;
|
use style_traits::DevicePixel;
|
||||||
use style_traits::cursor::CursorKind;
|
|
||||||
use webrender_api::{DeviceIntPoint, DevicePoint, DeviceUintSize, DeviceUintRect, ScrollLocation};
|
use webrender_api::{DeviceIntPoint, DevicePoint, DeviceUintSize, DeviceUintRect, ScrollLocation};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -123,64 +121,23 @@ pub enum AnimationState {
|
||||||
pub trait WindowMethods {
|
pub trait WindowMethods {
|
||||||
/// Presents the window to the screen (perhaps by page flipping).
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
fn present(&self);
|
fn present(&self);
|
||||||
|
|
||||||
/// Get the coordinates of the native window, the screen and the framebuffer.
|
|
||||||
fn get_coordinates(&self) -> EmbedderCoordinates;
|
|
||||||
/// Set the size inside of borders and head
|
|
||||||
fn set_inner_size(&self, ctx: TopLevelBrowsingContextId, size: DeviceUintSize);
|
|
||||||
/// Set the window position
|
|
||||||
fn set_position(&self, ctx: TopLevelBrowsingContextId, point: DeviceIntPoint);
|
|
||||||
/// Set fullscreen state
|
|
||||||
fn set_fullscreen_state(&self, ctx: TopLevelBrowsingContextId, state: bool);
|
|
||||||
|
|
||||||
/// Sets the page title for the current page.
|
|
||||||
fn set_page_title(&self, ctx: TopLevelBrowsingContextId, title: Option<String>);
|
|
||||||
/// Called when the browser chrome should display a status message.
|
|
||||||
fn status(&self, ctx: TopLevelBrowsingContextId, Option<String>);
|
|
||||||
/// Called when the browser has started loading a frame.
|
|
||||||
fn load_start(&self, ctx: TopLevelBrowsingContextId);
|
|
||||||
/// Called when the browser is done loading a frame.
|
|
||||||
fn load_end(&self, ctx: TopLevelBrowsingContextId);
|
|
||||||
/// Called when the browser encounters an error while loading a URL
|
|
||||||
fn load_error(&self, ctx: TopLevelBrowsingContextId, code: NetError, url: String);
|
|
||||||
/// Wether or not to follow a link
|
|
||||||
fn allow_navigation(&self, ctx: TopLevelBrowsingContextId, url: ServoUrl, IpcSender<bool>);
|
|
||||||
/// Called when the <head> tag has finished parsing
|
|
||||||
fn head_parsed(&self, ctx: TopLevelBrowsingContextId);
|
|
||||||
/// Called when the history state has changed.
|
|
||||||
fn history_changed(&self, ctx: TopLevelBrowsingContextId, Vec<LoadData>, usize);
|
|
||||||
|
|
||||||
/// Returns a thread-safe object to wake up the window's event loop.
|
|
||||||
fn create_event_loop_waker(&self) -> Box<EventLoopWaker>;
|
|
||||||
|
|
||||||
/// Requests that the window system prepare a composite. Typically this will involve making
|
/// Requests that the window system prepare a composite. Typically this will involve making
|
||||||
/// some type of platform-specific graphics context current. Returns true if the composite may
|
/// some type of platform-specific graphics context current. Returns true if the composite may
|
||||||
/// proceed and false if it should not.
|
/// proceed and false if it should not.
|
||||||
fn prepare_for_composite(&self, width: DeviceUintLength, height: DeviceUintLength) -> bool;
|
fn prepare_for_composite(&self, width: DeviceUintLength, height: DeviceUintLength) -> bool;
|
||||||
|
|
||||||
/// Sets the cursor to be used in the window.
|
|
||||||
fn set_cursor(&self, cursor: CursorKind);
|
|
||||||
|
|
||||||
/// Process a key event.
|
|
||||||
fn handle_key(&self, ctx: Option<TopLevelBrowsingContextId>, ch: Option<char>, key: Key, mods: KeyModifiers);
|
|
||||||
|
|
||||||
/// Does this window support a clipboard
|
|
||||||
fn supports_clipboard(&self) -> bool;
|
|
||||||
|
|
||||||
/// Add a favicon
|
|
||||||
fn set_favicon(&self, ctx: TopLevelBrowsingContextId, url: ServoUrl);
|
|
||||||
|
|
||||||
/// Return the GL function pointer trait.
|
/// Return the GL function pointer trait.
|
||||||
fn gl(&self) -> Rc<gl::Gl>;
|
fn gl(&self) -> Rc<gl::Gl>;
|
||||||
|
/// Returns a thread-safe object to wake up the window's event loop.
|
||||||
|
fn create_event_loop_waker(&self) -> Box<EventLoopWaker>;
|
||||||
|
/// Get the coordinates of the native window, the screen and the framebuffer.
|
||||||
|
fn get_coordinates(&self) -> EmbedderCoordinates;
|
||||||
|
/// Does this window support a clipboard
|
||||||
|
fn supports_clipboard(&self) -> bool;
|
||||||
/// Set whether the application is currently animating.
|
/// Set whether the application is currently animating.
|
||||||
/// Typically, when animations are active, the window
|
/// Typically, when animations are active, the window
|
||||||
/// will want to avoid blocking on UI events, and just
|
/// will want to avoid blocking on UI events, and just
|
||||||
/// run the event loop at the vsync interval.
|
/// run the event loop at the vsync interval.
|
||||||
fn set_animation_state(&self, _state: AnimationState) {}
|
fn set_animation_state(&self, _state: AnimationState);
|
||||||
|
|
||||||
/// Called when a pipeline panics.
|
|
||||||
fn handle_panic(&self, browser_id: TopLevelBrowsingContextId, reason: String, backtrace: Option<String>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|
|
@ -86,7 +86,6 @@ use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use log::{Log, LogMetadata, LogRecord};
|
use log::{Log, LogMetadata, LogRecord};
|
||||||
use msg::constellation_msg::KeyState;
|
|
||||||
use net::resource_thread::new_resource_threads;
|
use net::resource_thread::new_resource_threads;
|
||||||
use net_traits::IpcSend;
|
use net_traits::IpcSend;
|
||||||
use profile::mem as profile_mem;
|
use profile::mem as profile_mem;
|
||||||
|
@ -124,7 +123,8 @@ pub use msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
|
||||||
pub struct Servo<Window: WindowMethods + 'static> {
|
pub struct Servo<Window: WindowMethods + 'static> {
|
||||||
compositor: IOCompositor<Window>,
|
compositor: IOCompositor<Window>,
|
||||||
constellation_chan: Sender<ConstellationMsg>,
|
constellation_chan: Sender<ConstellationMsg>,
|
||||||
embedder_receiver: EmbedderReceiver
|
embedder_receiver: EmbedderReceiver,
|
||||||
|
embedder_events: Vec<EmbedderMsg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Window> Servo<Window> where Window: WindowMethods + 'static {
|
impl<Window> Servo<Window> where Window: WindowMethods + 'static {
|
||||||
|
@ -255,6 +255,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
|
||||||
compositor: compositor,
|
compositor: compositor,
|
||||||
constellation_chan: constellation_chan,
|
constellation_chan: constellation_chan,
|
||||||
embedder_receiver: embedder_receiver,
|
embedder_receiver: embedder_receiver,
|
||||||
|
embedder_events: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,83 +372,17 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
|
||||||
|
|
||||||
(_, ShutdownState::ShuttingDown) => {},
|
(_, ShutdownState::ShuttingDown) => {},
|
||||||
|
|
||||||
(EmbedderMsg::Status(top_level_browsing_context, message), ShutdownState::NotShuttingDown) => {
|
(msg, ShutdownState::NotShuttingDown) => {
|
||||||
self.compositor.window.status(top_level_browsing_context, message);
|
self.embedder_events.push(msg);
|
||||||
},
|
},
|
||||||
|
|
||||||
(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::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);
|
|
||||||
},
|
|
||||||
(EmbedderMsg::Panic(top_level_browsing_context, reason, backtrace),
|
|
||||||
ShutdownState::NotShuttingDown) => {
|
|
||||||
self.compositor.window.handle_panic(top_level_browsing_context, reason, backtrace);
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_events(&mut self) -> Vec<EmbedderMsg> {
|
||||||
|
::std::mem::replace(&mut self.embedder_events, Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
|
pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
|
||||||
if self.compositor.receive_messages() {
|
if self.compositor.receive_messages() {
|
||||||
self.receive_messages();
|
self.receive_messages();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
//! A windowing implementation using glutin.
|
//! A windowing implementation using glutin.
|
||||||
|
|
||||||
use compositing::compositor_thread::EventLoopWaker;
|
use compositing::compositor_thread::{EmbedderMsg, EventLoopWaker};
|
||||||
use compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent};
|
use compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent};
|
||||||
use compositing::windowing::{EmbedderCoordinates, WebRenderDebugOption, WindowMethods};
|
use compositing::windowing::{EmbedderCoordinates, WebRenderDebugOption, WindowMethods};
|
||||||
use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
|
use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
|
||||||
|
@ -15,7 +15,6 @@ use glutin;
|
||||||
use glutin::{Api, GlContext, GlRequest};
|
use glutin::{Api, GlContext, GlRequest};
|
||||||
use msg::constellation_msg::{self, Key, TopLevelBrowsingContextId as BrowserId};
|
use msg::constellation_msg::{self, Key, TopLevelBrowsingContextId as BrowserId};
|
||||||
use msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
|
use msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
|
||||||
use net_traits::net_error_list::NetError;
|
|
||||||
use net_traits::pub_domains::is_reg_domain;
|
use net_traits::pub_domains::is_reg_domain;
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
use osmesa_sys;
|
use osmesa_sys;
|
||||||
|
@ -582,6 +581,27 @@ impl Window {
|
||||||
mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
|
mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_servo_events(&self, events: Vec<EmbedderMsg>) {
|
||||||
|
for event in events {
|
||||||
|
match event {
|
||||||
|
EmbedderMsg::Status(top_level_browsing_context, message) => self.status(top_level_browsing_context, message),
|
||||||
|
EmbedderMsg::ChangePageTitle(top_level_browsing_context, title) => self.set_page_title(top_level_browsing_context, title),
|
||||||
|
EmbedderMsg::MoveTo(top_level_browsing_context, point) => self.set_position(top_level_browsing_context, point),
|
||||||
|
EmbedderMsg::ResizeTo(top_level_browsing_context, size) => self.set_inner_size(top_level_browsing_context, size),
|
||||||
|
EmbedderMsg::AllowNavigation(top_level_browsing_context, url, response_chan) => self.allow_navigation(top_level_browsing_context, url, response_chan),
|
||||||
|
EmbedderMsg::KeyEvent(top_level_browsing_context, ch, key, state, modified) => self.handle_key(top_level_browsing_context, ch, key, state, modified),
|
||||||
|
EmbedderMsg::SetCursor(cursor) => self.set_cursor(cursor),
|
||||||
|
EmbedderMsg::NewFavicon(top_level_browsing_context, url) => self.set_favicon(top_level_browsing_context, url),
|
||||||
|
EmbedderMsg::HeadParsed(top_level_browsing_context, ) => self.head_parsed(top_level_browsing_context, ),
|
||||||
|
EmbedderMsg::HistoryChanged(top_level_browsing_context, entries, current) => self.history_changed(top_level_browsing_context, entries, current),
|
||||||
|
EmbedderMsg::SetFullscreenState(top_level_browsing_context, state) => self.set_fullscreen_state(top_level_browsing_context, state),
|
||||||
|
EmbedderMsg::LoadStart(top_level_browsing_context) => self.load_start(top_level_browsing_context),
|
||||||
|
EmbedderMsg::LoadComplete(top_level_browsing_context) => self.load_end(top_level_browsing_context),
|
||||||
|
EmbedderMsg::Panic(top_level_browsing_context, reason, backtrace) => self.handle_panic(top_level_browsing_context, reason, backtrace),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_animating(&self) -> bool {
|
fn is_animating(&self) -> bool {
|
||||||
self.animation_state.get() == AnimationState::Animating && !self.suspended.get()
|
self.animation_state.get() == AnimationState::Animating && !self.suspended.get()
|
||||||
}
|
}
|
||||||
|
@ -913,56 +933,6 @@ impl Window {
|
||||||
let ppi = unsafe { gdi32::GetDeviceCaps(hdc, winapi::wingdi::LOGPIXELSY) };
|
let ppi = unsafe { gdi32::GetDeviceCaps(hdc, winapi::wingdi::LOGPIXELSY) };
|
||||||
TypedScale::new(ppi as f32 / 96.0)
|
TypedScale::new(ppi as f32 / 96.0)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl WindowMethods for Window {
|
|
||||||
fn gl(&self) -> Rc<gl::Gl> {
|
|
||||||
self.gl.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
|
||||||
let dpr = self.hidpi_factor();
|
|
||||||
match self.kind {
|
|
||||||
WindowKind::Window(ref window, _) => {
|
|
||||||
// TODO(ajeffrey): can this fail?
|
|
||||||
let (width, height) = window.get_outer_size().expect("Failed to get window outer size.");
|
|
||||||
let (x, y) = window.get_position().unwrap_or((0, 0));
|
|
||||||
let win_size = (TypedSize2D::new(width as f32, height as f32) * dpr).to_u32();
|
|
||||||
let win_origin = (TypedPoint2D::new(x as f32, y as f32) * dpr).to_i32();
|
|
||||||
let screen = (self.screen_size.to_f32() * dpr).to_u32();
|
|
||||||
|
|
||||||
let (width, height) = window.get_inner_size().expect("Failed to get window inner size.");
|
|
||||||
let inner_size = (TypedSize2D::new(width as f32, height as f32) * dpr).to_u32();
|
|
||||||
|
|
||||||
let viewport = DeviceUintRect::new(TypedPoint2D::zero(), inner_size);
|
|
||||||
|
|
||||||
EmbedderCoordinates {
|
|
||||||
viewport: viewport,
|
|
||||||
framebuffer: inner_size,
|
|
||||||
window: (win_size, win_origin),
|
|
||||||
screen: screen,
|
|
||||||
// FIXME: Glutin doesn't have API for available size. Fallback to screen size
|
|
||||||
screen_avail: screen,
|
|
||||||
hidpi_factor: dpr,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
WindowKind::Headless(ref context) => {
|
|
||||||
let size = (TypedSize2D::new(context.width, context.height).to_f32() * dpr).to_u32();
|
|
||||||
EmbedderCoordinates {
|
|
||||||
viewport: DeviceUintRect::new(TypedPoint2D::zero(), size),
|
|
||||||
framebuffer: size,
|
|
||||||
window: (size, TypedPoint2D::zero()),
|
|
||||||
screen: size,
|
|
||||||
screen_avail: size,
|
|
||||||
hidpi_factor: dpr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_animation_state(&self, state: AnimationState) {
|
|
||||||
self.animation_state.set(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_inner_size(&self, _: BrowserId, size: DeviceUintSize) {
|
fn set_inner_size(&self, _: BrowserId, size: DeviceUintSize) {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
|
@ -996,53 +966,6 @@ impl WindowMethods for Window {
|
||||||
self.fullscreen.set(state);
|
self.fullscreen.set(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn present(&self) {
|
|
||||||
match self.kind {
|
|
||||||
WindowKind::Window(ref window, ..) => {
|
|
||||||
if let Err(err) = window.swap_buffers() {
|
|
||||||
warn!("Failed to swap window buffers ({}).", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WindowKind::Headless(..) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_event_loop_waker(&self) -> Box<EventLoopWaker> {
|
|
||||||
struct GlutinEventLoopWaker {
|
|
||||||
proxy: Option<Arc<winit::EventsLoopProxy>>,
|
|
||||||
}
|
|
||||||
impl GlutinEventLoopWaker {
|
|
||||||
fn new(window: &Window) -> GlutinEventLoopWaker {
|
|
||||||
let proxy = match window.kind {
|
|
||||||
WindowKind::Window(_, ref events_loop) => {
|
|
||||||
Some(Arc::new(events_loop.borrow().create_proxy()))
|
|
||||||
},
|
|
||||||
WindowKind::Headless(..) => {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
GlutinEventLoopWaker { proxy }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl EventLoopWaker for GlutinEventLoopWaker {
|
|
||||||
fn wake(&self) {
|
|
||||||
// kick the OS event loop awake.
|
|
||||||
if let Some(ref proxy) = self.proxy {
|
|
||||||
if let Err(err) = proxy.wakeup() {
|
|
||||||
warn!("Failed to wake up event loop ({}).", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn clone(&self) -> Box<EventLoopWaker + Send> {
|
|
||||||
Box::new(GlutinEventLoopWaker {
|
|
||||||
proxy: self.proxy.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Box::new(GlutinEventLoopWaker::new(&self))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_page_title(&self, _: BrowserId, title: Option<String>) {
|
fn set_page_title(&self, _: BrowserId, title: Option<String>) {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
WindowKind::Window(ref window, ..) => {
|
WindowKind::Window(ref window, ..) => {
|
||||||
|
@ -1084,9 +1007,6 @@ impl WindowMethods for Window {
|
||||||
*self.current_url.borrow_mut() = Some(history[current].url.clone());
|
*self.current_url.borrow_mut() = Some(history[current].url.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_error(&self, _: BrowserId, _: NetError, _: String) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn head_parsed(&self, _: BrowserId) {
|
fn head_parsed(&self, _: BrowserId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1143,12 +1063,11 @@ impl WindowMethods for Window {
|
||||||
fn set_favicon(&self, _: BrowserId, _: ServoUrl) {
|
fn set_favicon(&self, _: BrowserId, _: ServoUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_for_composite(&self, _width: Length<u32, DevicePixel>, _height: Length<u32, DevicePixel>) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper function to handle keyboard events.
|
/// Helper function to handle keyboard events.
|
||||||
fn handle_key(&self, _: Option<BrowserId>, ch: Option<char>, key: Key, mods: constellation_msg::KeyModifiers) {
|
fn handle_key(&self, _: Option<BrowserId>, ch: Option<char>, key: Key, state: KeyState, mods: constellation_msg::KeyModifiers) {
|
||||||
|
if state == KeyState::Pressed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let browser_id = match self.browser_id.get() {
|
let browser_id = match self.browser_id.get() {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => { unreachable!("Can't get keys without a browser"); }
|
None => { unreachable!("Can't get keys without a browser"); }
|
||||||
|
@ -1283,12 +1202,113 @@ impl WindowMethods for Window {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn supports_clipboard(&self) -> bool {
|
fn handle_panic(&self, _: BrowserId, _reason: String, _backtrace: Option<String>) {
|
||||||
|
// Nothing to do here yet. The crash has already been reported on the console.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowMethods for Window {
|
||||||
|
fn gl(&self) -> Rc<gl::Gl> {
|
||||||
|
self.gl.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||||
|
let dpr = self.hidpi_factor();
|
||||||
|
match self.kind {
|
||||||
|
WindowKind::Window(ref window, _) => {
|
||||||
|
// TODO(ajeffrey): can this fail?
|
||||||
|
let (width, height) = window.get_outer_size().expect("Failed to get window outer size.");
|
||||||
|
let (x, y) = window.get_position().unwrap_or((0, 0));
|
||||||
|
let win_size = (TypedSize2D::new(width as f32, height as f32) * dpr).to_u32();
|
||||||
|
let win_origin = (TypedPoint2D::new(x as f32, y as f32) * dpr).to_i32();
|
||||||
|
let screen = (self.screen_size.to_f32() * dpr).to_u32();
|
||||||
|
|
||||||
|
let (width, height) = window.get_inner_size().expect("Failed to get window inner size.");
|
||||||
|
let inner_size = (TypedSize2D::new(width as f32, height as f32) * dpr).to_u32();
|
||||||
|
|
||||||
|
let viewport = DeviceUintRect::new(TypedPoint2D::zero(), inner_size);
|
||||||
|
|
||||||
|
EmbedderCoordinates {
|
||||||
|
viewport: viewport,
|
||||||
|
framebuffer: inner_size,
|
||||||
|
window: (win_size, win_origin),
|
||||||
|
screen: screen,
|
||||||
|
// FIXME: Glutin doesn't have API for available size. Fallback to screen size
|
||||||
|
screen_avail: screen,
|
||||||
|
hidpi_factor: dpr,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
WindowKind::Headless(ref context) => {
|
||||||
|
let size = (TypedSize2D::new(context.width, context.height).to_f32() * dpr).to_u32();
|
||||||
|
EmbedderCoordinates {
|
||||||
|
viewport: DeviceUintRect::new(TypedPoint2D::zero(), size),
|
||||||
|
framebuffer: size,
|
||||||
|
window: (size, TypedPoint2D::zero()),
|
||||||
|
screen: size,
|
||||||
|
screen_avail: size,
|
||||||
|
hidpi_factor: dpr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn present(&self) {
|
||||||
|
match self.kind {
|
||||||
|
WindowKind::Window(ref window, ..) => {
|
||||||
|
if let Err(err) = window.swap_buffers() {
|
||||||
|
warn!("Failed to swap window buffers ({}).", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WindowKind::Headless(..) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_event_loop_waker(&self) -> Box<EventLoopWaker> {
|
||||||
|
struct GlutinEventLoopWaker {
|
||||||
|
proxy: Option<Arc<winit::EventsLoopProxy>>,
|
||||||
|
}
|
||||||
|
impl GlutinEventLoopWaker {
|
||||||
|
fn new(window: &Window) -> GlutinEventLoopWaker {
|
||||||
|
let proxy = match window.kind {
|
||||||
|
WindowKind::Window(_, ref events_loop) => {
|
||||||
|
Some(Arc::new(events_loop.borrow().create_proxy()))
|
||||||
|
},
|
||||||
|
WindowKind::Headless(..) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GlutinEventLoopWaker { proxy }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl EventLoopWaker for GlutinEventLoopWaker {
|
||||||
|
fn wake(&self) {
|
||||||
|
// kick the OS event loop awake.
|
||||||
|
if let Some(ref proxy) = self.proxy {
|
||||||
|
if let Err(err) = proxy.wakeup() {
|
||||||
|
warn!("Failed to wake up event loop ({}).", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn clone(&self) -> Box<EventLoopWaker + Send> {
|
||||||
|
Box::new(GlutinEventLoopWaker {
|
||||||
|
proxy: self.proxy.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::new(GlutinEventLoopWaker::new(&self))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_animation_state(&self, state: AnimationState) {
|
||||||
|
self.animation_state.set(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_for_composite(&self, _width: Length<u32, DevicePixel>, _height: Length<u32, DevicePixel>) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_panic(&self, _: BrowserId, _reason: String, _backtrace: Option<String>) {
|
fn supports_clipboard(&self) -> bool {
|
||||||
// Nothing to do here yet. The crash has already been reported on the console.
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,15 +184,16 @@ fn main() {
|
||||||
servo.setup_logging();
|
servo.setup_logging();
|
||||||
|
|
||||||
window.run(|| {
|
window.run(|| {
|
||||||
let events = window.get_events();
|
let win_events = window.get_events();
|
||||||
let need_resize = events.iter().any(|e| match *e {
|
let need_resize = win_events.iter().any(|e| match *e {
|
||||||
WindowEvent::Resize => true,
|
WindowEvent::Resize => true,
|
||||||
_ => false
|
_ => false
|
||||||
});
|
});
|
||||||
let stop = !servo.handle_events(events);
|
let stop = !servo.handle_events(win_events);
|
||||||
if need_resize {
|
if need_resize {
|
||||||
servo.repaint_synchronously();
|
servo.repaint_synchronously();
|
||||||
}
|
}
|
||||||
|
window.handle_servo_events(servo.get_events());
|
||||||
stop
|
stop
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue