mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
split window code and browser code in two different files
This commit is contained in:
parent
34c2150e4f
commit
1cdba8843d
9 changed files with 478 additions and 417 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2698,14 +2698,12 @@ dependencies = [
|
|||
"libservo 0.0.1",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)",
|
||||
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script_traits 0.0.1",
|
||||
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_config 0.0.1",
|
||||
"servo_geometry 0.0.1",
|
||||
"servo_url 0.0.1",
|
||||
"sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style_traits 0.0.1",
|
||||
"tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -141,6 +141,8 @@ pub enum EmbedderMsg {
|
|||
LoadComplete(TopLevelBrowsingContextId),
|
||||
/// A pipeline panicked. First string is the reason, second one is the backtrace.
|
||||
Panic(TopLevelBrowsingContextId, String, Option<String>),
|
||||
/// Servo has shut down
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
/// Messages from the painting thread and the constellation thread to the compositor thread.
|
||||
|
@ -239,6 +241,7 @@ impl Debug for EmbedderMsg {
|
|||
EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"),
|
||||
EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
|
||||
EmbedderMsg::Panic(..) => write!(f, "Panic"),
|
||||
EmbedderMsg::Shutdown => write!(f, "Shutdown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ use webvr::{WebVRThread, WebVRCompositorHandler};
|
|||
pub use gleam::gl;
|
||||
pub use servo_config as config;
|
||||
pub use servo_url as url;
|
||||
pub use msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
|
||||
pub use msg::constellation_msg::{KeyState, TopLevelBrowsingContextId as BrowserId};
|
||||
|
||||
/// The in-process interface to Servo.
|
||||
///
|
||||
|
@ -372,6 +372,14 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
|
|||
|
||||
(_, ShutdownState::ShuttingDown) => {},
|
||||
|
||||
(EmbedderMsg::KeyEvent(top_level_browsing_context, ch, key, state, modified),
|
||||
ShutdownState::NotShuttingDown) => {
|
||||
if state == KeyState::Pressed {
|
||||
let msg = EmbedderMsg::KeyEvent(top_level_browsing_context, ch, key, state, modified);
|
||||
self.embedder_events.push(msg);
|
||||
}
|
||||
},
|
||||
|
||||
(msg, ShutdownState::NotShuttingDown) => {
|
||||
self.embedder_events.push(msg);
|
||||
},
|
||||
|
@ -383,7 +391,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
|
|||
::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>) {
|
||||
if self.compositor.receive_messages() {
|
||||
self.receive_messages();
|
||||
}
|
||||
|
@ -392,8 +400,9 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
|
|||
}
|
||||
if self.compositor.shutdown_state != ShutdownState::FinishedShuttingDown {
|
||||
self.compositor.perform_updates();
|
||||
} else {
|
||||
self.embedder_events.push(EmbedderMsg::Shutdown);
|
||||
}
|
||||
self.compositor.shutdown_state != ShutdownState::FinishedShuttingDown
|
||||
}
|
||||
|
||||
pub fn repaint_synchronously(&mut self) {
|
||||
|
|
|
@ -43,11 +43,9 @@ glutin = "0.13"
|
|||
libservo = {path = "../../components/servo"}
|
||||
log = "0.3.5"
|
||||
msg = {path = "../../components/msg"}
|
||||
net_traits = {path = "../../components/net_traits"}
|
||||
script_traits = {path = "../../components/script_traits"}
|
||||
servo_geometry = {path = "../../components/geometry"}
|
||||
servo_config = {path = "../../components/config"}
|
||||
servo_url = {path = "../../components/url"}
|
||||
style_traits = {path = "../../components/style_traits"}
|
||||
tinyfiledialogs = "3.0"
|
||||
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
||||
|
|
319
ports/servo/browser.rs
Normal file
319
ports/servo/browser.rs
Normal file
|
@ -0,0 +1,319 @@
|
|||
/* 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 compositing::compositor_thread::EmbedderMsg;
|
||||
use compositing::windowing::{WebRenderDebugOption, WindowEvent};
|
||||
use euclid::{TypedPoint2D, TypedVector2D};
|
||||
use glutin_app::keyutils::{CMD_OR_CONTROL, CMD_OR_ALT};
|
||||
use glutin_app::window::{Window, LINE_HEIGHT};
|
||||
use msg::constellation_msg::{Key, TopLevelBrowsingContextId as BrowserId};
|
||||
use msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
|
||||
use script_traits::TouchEventType;
|
||||
use servo::net_traits::pub_domains::is_reg_domain;
|
||||
use servo::servo_url::ServoUrl;
|
||||
use servo_config::prefs::PREFS;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use tinyfiledialogs;
|
||||
use webrender_api::ScrollLocation;
|
||||
|
||||
pub struct Browser {
|
||||
current_url: Option<ServoUrl>,
|
||||
/// id of the top level browsing context. It is unique as tabs
|
||||
/// are not supported yet. None until created.
|
||||
browser_id: Option<BrowserId>,
|
||||
|
||||
title: Option<String>,
|
||||
status: Option<String>,
|
||||
favicon: Option<ServoUrl>,
|
||||
loading_state: Option<LoadingState>,
|
||||
window: Rc<Window>,
|
||||
event_queue: Vec<WindowEvent>,
|
||||
shutdown_requested: bool,
|
||||
}
|
||||
|
||||
enum LoadingState {
|
||||
Connecting,
|
||||
Loading,
|
||||
Loaded,
|
||||
}
|
||||
|
||||
impl Browser {
|
||||
pub fn new(window: Rc<Window>) -> Browser {
|
||||
Browser {
|
||||
title: None,
|
||||
current_url: None,
|
||||
browser_id: None,
|
||||
status: None,
|
||||
favicon: None,
|
||||
loading_state: None,
|
||||
window: window,
|
||||
event_queue: Vec::new(),
|
||||
shutdown_requested: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_events(&mut self) -> Vec<WindowEvent> {
|
||||
mem::replace(&mut self.event_queue, Vec::new())
|
||||
}
|
||||
|
||||
pub fn set_browser_id(&mut self, browser_id: BrowserId) {
|
||||
self.browser_id = Some(browser_id);
|
||||
}
|
||||
|
||||
pub fn handle_window_events(&mut self, events: Vec<WindowEvent>) {
|
||||
for event in events {
|
||||
match event {
|
||||
WindowEvent::KeyEvent(ch, key, state, mods) => {
|
||||
self.handle_key_from_window(ch, key, state, mods);
|
||||
},
|
||||
event => {
|
||||
self.event_queue.push(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown_requested(&self) -> bool {
|
||||
self.shutdown_requested
|
||||
}
|
||||
|
||||
/// Handle key events before sending them to Servo.
|
||||
fn handle_key_from_window(&mut self, ch: Option<char>, key: Key, state: KeyState, mods: KeyModifiers) {
|
||||
match (mods, ch, key) {
|
||||
(CMD_OR_CONTROL, Some('r'), _) => {
|
||||
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
|
||||
if let Some(id) = self.browser_id {
|
||||
self.event_queue.push(WindowEvent::Reload(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('l'), _) => {
|
||||
if let Some(id) = self.browser_id {
|
||||
let url: String = if let Some(ref current_url) = self.current_url {
|
||||
current_url.to_string()
|
||||
} else {
|
||||
String::from("")
|
||||
};
|
||||
let title = "URL or search query";
|
||||
if let Some(input) = tinyfiledialogs::input_box(title, title, &url) {
|
||||
if let Some(url) = sanitize_url(&input) {
|
||||
self.event_queue.push(WindowEvent::LoadUrl(id, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('q'), _) => {
|
||||
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
|
||||
self.event_queue.push(WindowEvent::Quit);
|
||||
}
|
||||
}
|
||||
(_, Some('3'), _) => if mods ^ KeyModifiers::CONTROL == KeyModifiers::SHIFT {
|
||||
self.event_queue.push(WindowEvent::CaptureWebRender);
|
||||
}
|
||||
(KeyModifiers::CONTROL, None, Key::F10) => {
|
||||
let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::RenderTargetDebug);
|
||||
self.event_queue.push(event);
|
||||
}
|
||||
(KeyModifiers::CONTROL, None, Key::F11) => {
|
||||
let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::TextureCacheDebug);
|
||||
self.event_queue.push(event);
|
||||
}
|
||||
(KeyModifiers::CONTROL, None, Key::F12) => {
|
||||
let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::Profiler);
|
||||
self.event_queue.push(event);
|
||||
}
|
||||
(CMD_OR_ALT, None, Key::Right) | (KeyModifiers::NONE, None, Key::NavigateForward) => {
|
||||
if let Some(id) = self.browser_id {
|
||||
let event = WindowEvent::Navigation(id, TraversalDirection::Forward(1));
|
||||
self.event_queue.push(event);
|
||||
}
|
||||
}
|
||||
(CMD_OR_ALT, None, Key::Left) | (KeyModifiers::NONE, None, Key::NavigateBackward) => {
|
||||
if let Some(id) = self.browser_id {
|
||||
let event = WindowEvent::Navigation(id, TraversalDirection::Back(1));
|
||||
self.event_queue.push(event);
|
||||
}
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::Escape) => {
|
||||
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
|
||||
self.event_queue.push(WindowEvent::Quit);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let event = self.platform_handle_key(key, mods);
|
||||
self.event_queue.push(event.unwrap_or(WindowEvent::KeyEvent(ch, key, state, mods)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "win"))]
|
||||
fn platform_handle_key(&self, key: Key, mods: KeyModifiers) -> Option<WindowEvent> {
|
||||
match (mods, key, self.browser_id) {
|
||||
(CMD_OR_CONTROL, Key::LeftBracket, Some(id)) => {
|
||||
Some(WindowEvent::Navigation(id, TraversalDirection::Back(1)))
|
||||
}
|
||||
(CMD_OR_CONTROL, Key::RightBracket, Some(id)) => {
|
||||
Some(WindowEvent::Navigation(id, TraversalDirection::Forward(1)))
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "win")]
|
||||
fn platform_handle_key(&self, key: Key, mods: KeyModifiers) -> Option<WindowEvent> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Handle key events after they have been handled by Servo.
|
||||
fn handle_key_from_servo(&mut self, _: Option<BrowserId>, ch: Option<char>,
|
||||
key: Key, _: KeyState, mods: KeyModifiers) {
|
||||
match (mods, ch, key) {
|
||||
(_, Some('+'), _) => {
|
||||
if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL {
|
||||
self.event_queue.push(WindowEvent::Zoom(1.1));
|
||||
} else if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL | KeyModifiers::ALT {
|
||||
self.event_queue.push(WindowEvent::PinchZoom(1.1));
|
||||
}
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('-'), _) => {
|
||||
self.event_queue.push(WindowEvent::Zoom(1.0 / 1.1));
|
||||
}
|
||||
(_, Some('-'), _) if mods == CMD_OR_CONTROL | KeyModifiers::ALT => {
|
||||
self.event_queue.push(WindowEvent::PinchZoom(1.0 / 1.1));
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('0'), _) => {
|
||||
self.event_queue.push(WindowEvent::ResetZoom);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::PageDown) => {
|
||||
let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
|
||||
-self.window.page_height() + 2.0 * LINE_HEIGHT));
|
||||
self.scroll_window_from_key(scroll_location, TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::PageUp) => {
|
||||
let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
|
||||
self.window.page_height() - 2.0 * LINE_HEIGHT));
|
||||
self.scroll_window_from_key(scroll_location, TouchEventType::Move);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::Home) => {
|
||||
self.scroll_window_from_key(ScrollLocation::Start, TouchEventType::Move);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::End) => {
|
||||
self.scroll_window_from_key(ScrollLocation::End, TouchEventType::Move);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::Up) => {
|
||||
self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(0.0, 3.0 * LINE_HEIGHT)),
|
||||
TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::Down) => {
|
||||
self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(0.0, -3.0 * LINE_HEIGHT)),
|
||||
TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::Left) => {
|
||||
self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(LINE_HEIGHT, 0.0)),
|
||||
TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::Right) => {
|
||||
self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(-LINE_HEIGHT, 0.0)),
|
||||
TouchEventType::Move);
|
||||
}
|
||||
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn scroll_window_from_key(&mut self, scroll_location: ScrollLocation, phase: TouchEventType) {
|
||||
let event = WindowEvent::Scroll(scroll_location, TypedPoint2D::zero(), phase);
|
||||
self.event_queue.push(event);
|
||||
}
|
||||
|
||||
pub fn handle_servo_events(&mut self, events: Vec<EmbedderMsg>) {
|
||||
for event in events {
|
||||
match event {
|
||||
EmbedderMsg::Status(_browser_id, status) => {
|
||||
self.status = status;
|
||||
},
|
||||
EmbedderMsg::ChangePageTitle(_browser_id, title) => {
|
||||
self.title = title;
|
||||
|
||||
let fallback_title: String = if let Some(ref current_url) = self.current_url {
|
||||
current_url.to_string()
|
||||
} else {
|
||||
String::from("Untitled")
|
||||
};
|
||||
let title = match self.title {
|
||||
Some(ref title) if title.len() > 0 => &**title,
|
||||
_ => &fallback_title,
|
||||
};
|
||||
let title = format!("{} - Servo", title);
|
||||
self.window.set_title(&title);
|
||||
}
|
||||
EmbedderMsg::MoveTo(_browser_id, point) => {
|
||||
self.window.set_position(point);
|
||||
}
|
||||
EmbedderMsg::ResizeTo(_browser_id, size) => {
|
||||
self.window.set_inner_size(size);
|
||||
}
|
||||
EmbedderMsg::AllowNavigation(_browser_id, _url, response_chan) => {
|
||||
if let Err(e) = response_chan.send(true) {
|
||||
warn!("Failed to send allow_navigation() response: {}", e);
|
||||
};
|
||||
}
|
||||
EmbedderMsg::KeyEvent(browser_id, ch, key, state, modified) => {
|
||||
self.handle_key_from_servo(browser_id, ch, key, state, modified);
|
||||
}
|
||||
EmbedderMsg::SetCursor(cursor) => {
|
||||
self.window.set_cursor(cursor);
|
||||
}
|
||||
EmbedderMsg::NewFavicon(_browser_id, url) => {
|
||||
self.favicon = Some(url);
|
||||
}
|
||||
EmbedderMsg::HeadParsed(_browser_id, ) => {
|
||||
self.loading_state = Some(LoadingState::Loading);
|
||||
}
|
||||
EmbedderMsg::HistoryChanged(_browser_id, entries, current) => {
|
||||
self.current_url = Some(entries[current].url.clone());
|
||||
}
|
||||
EmbedderMsg::SetFullscreenState(_browser_id, state) => {
|
||||
self.window.set_fullscreen(state);
|
||||
}
|
||||
EmbedderMsg::LoadStart(_browser_id) => {
|
||||
self.loading_state = Some(LoadingState::Connecting);
|
||||
}
|
||||
EmbedderMsg::LoadComplete(_browser_id) => {
|
||||
self.loading_state = Some(LoadingState::Loaded);
|
||||
}
|
||||
EmbedderMsg::Shutdown => {
|
||||
self.shutdown_requested = true;
|
||||
},
|
||||
EmbedderMsg::Panic(_browser_id, _reason, _backtrace) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn sanitize_url(request: &str) -> Option<ServoUrl> {
|
||||
let request = request.trim();
|
||||
ServoUrl::parse(&request).ok()
|
||||
.or_else(|| {
|
||||
if request.contains('/') || is_reg_domain(request) {
|
||||
ServoUrl::parse(&format!("http://{}", request)).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).or_else(|| {
|
||||
PREFS.get("shell.searchpage").as_string().and_then(|s: &str| {
|
||||
let url = s.replace("%s", request);
|
||||
ServoUrl::parse(&url).ok()
|
||||
})
|
||||
})
|
||||
}
|
|
@ -332,7 +332,7 @@ pub fn is_printable(key_code: VirtualKeyCode) -> bool {
|
|||
|
||||
/// Detect if given char is default ignorable in unicode
|
||||
/// http://www.unicode.org/L2/L2002/02368-default-ignorable.pdf
|
||||
pub fn is_identifier_ignorable(&self, ch: &char) -> bool {
|
||||
pub fn is_identifier_ignorable(ch: &char) -> bool {
|
||||
match *ch {
|
||||
'\u{0000}'...'\u{0008}' | '\u{000E}'...'\u{001F}' |
|
||||
'\u{007F}'...'\u{0084}' | '\u{0086}'...'\u{009F}' |
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
//! A simple application that uses glutin to open a window for Servo to display in.
|
||||
|
||||
mod keyutils;
|
||||
pub mod keyutils;
|
||||
pub mod window;
|
||||
|
||||
use servo_config::opts;
|
||||
|
|
|
@ -4,26 +4,20 @@
|
|||
|
||||
//! A windowing implementation using glutin.
|
||||
|
||||
use compositing::compositor_thread::{EmbedderMsg, EventLoopWaker};
|
||||
use compositing::compositor_thread::EventLoopWaker;
|
||||
use compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent};
|
||||
use compositing::windowing::{EmbedderCoordinates, WebRenderDebugOption, WindowMethods};
|
||||
use compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
||||
use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
|
||||
#[cfg(target_os = "windows")]
|
||||
use gdi32;
|
||||
use gleam::gl;
|
||||
use glutin;
|
||||
use glutin::{Api, GlContext, GlRequest};
|
||||
use msg::constellation_msg::{self, Key, TopLevelBrowsingContextId as BrowserId};
|
||||
use msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
|
||||
use net_traits::pub_domains::is_reg_domain;
|
||||
use glutin::{self, Api, GlContext, GlRequest};
|
||||
use msg::constellation_msg::{Key, KeyState};
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
use osmesa_sys;
|
||||
use script_traits::{LoadData, TouchEventType};
|
||||
use servo::ipc_channel::ipc::IpcSender;
|
||||
use script_traits::TouchEventType;
|
||||
use servo_config::opts;
|
||||
use servo_config::prefs::PREFS;
|
||||
use servo_geometry::DeviceIndependentPixel;
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::{Cell, RefCell};
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
use std::ffi::CString;
|
||||
|
@ -36,8 +30,7 @@ use std::thread;
|
|||
use std::time;
|
||||
use style_traits::DevicePixel;
|
||||
use style_traits::cursor::CursorKind;
|
||||
use super::keyutils::{self, CMD_OR_ALT, CMD_OR_CONTROL, GlutinKeyModifiers};
|
||||
use tinyfiledialogs;
|
||||
use super::keyutils::{self, GlutinKeyModifiers};
|
||||
#[cfg(target_os = "windows")]
|
||||
use user32;
|
||||
use webrender_api::{DeviceIntPoint, DeviceUintRect, DeviceUintSize, ScrollLocation};
|
||||
|
@ -50,7 +43,7 @@ use winit::os::macos::{ActivationPolicy, WindowBuilderExt};
|
|||
|
||||
|
||||
// This should vary by zoom level and maybe actual text size (focused or under cursor)
|
||||
const LINE_HEIGHT: f32 = 38.0;
|
||||
pub const LINE_HEIGHT: f32 = 38.0;
|
||||
|
||||
const MULTISAMPLES: u16 = 16;
|
||||
|
||||
|
@ -154,25 +147,14 @@ pub struct Window {
|
|||
kind: WindowKind,
|
||||
screen_size: TypedSize2D<u32, DeviceIndependentPixel>,
|
||||
inner_size: Cell<TypedSize2D<u32, DeviceIndependentPixel>>,
|
||||
|
||||
mouse_down_button: Cell<Option<winit::MouseButton>>,
|
||||
mouse_down_point: Cell<TypedPoint2D<i32, DevicePixel>>,
|
||||
event_queue: RefCell<Vec<WindowEvent>>,
|
||||
|
||||
/// id of the top level browsing context. It is unique as tabs
|
||||
/// are not supported yet. None until created.
|
||||
browser_id: Cell<Option<BrowserId>>,
|
||||
|
||||
mouse_pos: Cell<TypedPoint2D<i32, DevicePixel>>,
|
||||
key_modifiers: Cell<GlutinKeyModifiers>,
|
||||
current_url: RefCell<Option<ServoUrl>>,
|
||||
|
||||
last_pressed_key: Cell<Option<constellation_msg::Key>>,
|
||||
|
||||
last_pressed_key: Cell<Option<Key>>,
|
||||
animation_state: Cell<AnimationState>,
|
||||
|
||||
fullscreen: Cell<bool>,
|
||||
|
||||
gl: Rc<gl::Gl>,
|
||||
suspended: Cell<bool>,
|
||||
}
|
||||
|
@ -191,10 +173,6 @@ fn window_creation_scale_factor() -> TypedScale<f32, DeviceIndependentPixel, Dev
|
|||
|
||||
|
||||
impl Window {
|
||||
pub fn set_browser_id(&self, browser_id: BrowserId) {
|
||||
self.browser_id.set(Some(browser_id));
|
||||
}
|
||||
|
||||
pub fn new(is_foreground: bool,
|
||||
window_size: TypedSize2D<u32, DeviceIndependentPixel>) -> Rc<Window> {
|
||||
let win_size: DeviceUintSize = (window_size.to_f32() * window_creation_scale_factor()).to_u32();
|
||||
|
@ -291,11 +269,8 @@ impl Window {
|
|||
mouse_down_button: Cell::new(None),
|
||||
mouse_down_point: Cell::new(TypedPoint2D::new(0, 0)),
|
||||
|
||||
browser_id: Cell::new(None),
|
||||
|
||||
mouse_pos: Cell::new(TypedPoint2D::new(0, 0)),
|
||||
key_modifiers: Cell::new(GlutinKeyModifiers::empty()),
|
||||
current_url: RefCell::new(None),
|
||||
|
||||
last_pressed_key: Cell::new(None),
|
||||
gl: gl.clone(),
|
||||
|
@ -311,6 +286,107 @@ impl Window {
|
|||
Rc::new(window)
|
||||
}
|
||||
|
||||
pub fn get_events(&self) -> Vec<WindowEvent> {
|
||||
mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
|
||||
}
|
||||
|
||||
pub fn page_height(&self) -> f32 {
|
||||
let dpr = self.hidpi_factor();
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, _) => {
|
||||
let (_, height) = window.get_inner_size().expect("Failed to get window inner size.");
|
||||
height as f32 * dpr.get()
|
||||
},
|
||||
WindowKind::Headless(ref context) => {
|
||||
context.height as f32 * dpr.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_title(&self, title: &str) {
|
||||
if let WindowKind::Window(ref window, _) = self.kind {
|
||||
window.set_title(title);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_inner_size(&self, size: DeviceUintSize) {
|
||||
if let WindowKind::Window(ref window, _) = self.kind {
|
||||
let size = size.to_f32() / self.hidpi_factor();
|
||||
window.set_inner_size(size.width as u32, size.height as u32)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_position(&self, point: DeviceIntPoint) {
|
||||
if let WindowKind::Window(ref window, _) = self.kind {
|
||||
let point = point.to_f32() / self.hidpi_factor();
|
||||
window.set_position(point.x as i32, point.y as i32)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_fullscreen(&self, state: bool) {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, ..) => {
|
||||
if self.fullscreen.get() != state {
|
||||
window.set_fullscreen(None);
|
||||
}
|
||||
},
|
||||
WindowKind::Headless(..) => {}
|
||||
}
|
||||
self.fullscreen.set(state);
|
||||
}
|
||||
|
||||
fn is_animating(&self) -> bool {
|
||||
self.animation_state.get() == AnimationState::Animating && !self.suspended.get()
|
||||
}
|
||||
|
||||
pub fn run<T>(&self, mut servo_callback: T) where T: FnMut() -> bool {
|
||||
match self.kind {
|
||||
WindowKind::Window(_, ref events_loop) => {
|
||||
let mut stop = false;
|
||||
loop {
|
||||
if self.is_animating() {
|
||||
// We block on compositing (servo_callback ends up calling swap_buffers)
|
||||
events_loop.borrow_mut().poll_events(|e| {
|
||||
self.glutin_event_to_servo_event(e);
|
||||
});
|
||||
stop = servo_callback();
|
||||
} else {
|
||||
// We block on glutin's event loop (window events)
|
||||
events_loop.borrow_mut().run_forever(|e| {
|
||||
self.glutin_event_to_servo_event(e);
|
||||
if !self.event_queue.borrow().is_empty() {
|
||||
if !self.suspended.get() {
|
||||
stop = servo_callback();
|
||||
}
|
||||
}
|
||||
if stop || self.is_animating() {
|
||||
winit::ControlFlow::Break
|
||||
} else {
|
||||
winit::ControlFlow::Continue
|
||||
}
|
||||
});
|
||||
}
|
||||
if stop {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowKind::Headless(..) => {
|
||||
loop {
|
||||
// Sleep the main thread to avoid using 100% CPU
|
||||
// This can be done better, see comments in #18777
|
||||
if self.event_queue.borrow().is_empty() {
|
||||
thread::sleep(time::Duration::from_millis(5));
|
||||
}
|
||||
let stop = servo_callback();
|
||||
if stop {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
|
||||
fn gl_version() -> GlRequest {
|
||||
return GlRequest::Specific(Api::OpenGl, (3, 2));
|
||||
|
@ -379,7 +455,7 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_window_event(&self, event: winit::Event) {
|
||||
fn glutin_event_to_servo_event(&self, event: winit::Event) {
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
event: winit::WindowEvent::ReceivedCharacter(ch),
|
||||
|
@ -416,13 +492,22 @@ impl Window {
|
|||
event: winit::WindowEvent::MouseWheel { delta, phase, .. },
|
||||
..
|
||||
} => {
|
||||
let (dx, dy) = match delta {
|
||||
let (mut dx, mut dy) = match delta {
|
||||
MouseScrollDelta::LineDelta(dx, dy) => (dx, dy * LINE_HEIGHT),
|
||||
MouseScrollDelta::PixelDelta(dx, dy) => (dx, dy),
|
||||
};
|
||||
// Scroll events snap to the major axis of movement, with vertical
|
||||
// preferred over horizontal.
|
||||
if dy.abs() >= dx.abs() {
|
||||
dx = 0.0;
|
||||
} else {
|
||||
dy = 0.0;
|
||||
}
|
||||
|
||||
let scroll_location = ScrollLocation::Delta(TypedVector2D::new(dx, dy));
|
||||
let phase = glutin_phase_to_touch_event_type(phase);
|
||||
self.scroll_window(scroll_location, phase);
|
||||
let event = WindowEvent::Scroll(scroll_location, self.mouse_pos.get(), phase);
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
},
|
||||
Event::WindowEvent {
|
||||
event: winit::WindowEvent::Touch(touch),
|
||||
|
@ -481,22 +566,6 @@ impl Window {
|
|||
self.key_modifiers.set(modifiers);
|
||||
}
|
||||
|
||||
/// Helper function to send a scroll event.
|
||||
fn scroll_window(&self, mut scroll_location: ScrollLocation, phase: TouchEventType) {
|
||||
// Scroll events snap to the major axis of movement, with vertical
|
||||
// preferred over horizontal.
|
||||
if let ScrollLocation::Delta(ref mut delta) = scroll_location {
|
||||
if delta.y.abs() >= delta.x.abs() {
|
||||
delta.x = 0.0;
|
||||
} else {
|
||||
delta.y = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
let event = WindowEvent::Scroll(scroll_location, self.mouse_pos.get(), phase);
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
|
||||
/// Helper function to handle a click
|
||||
fn handle_mouse(&self, button: winit::MouseButton,
|
||||
action: winit::ElementState,
|
||||
|
@ -532,115 +601,6 @@ impl Window {
|
|||
self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(event));
|
||||
}
|
||||
|
||||
pub fn get_events(&self) -> Vec<WindowEvent> {
|
||||
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 {
|
||||
self.animation_state.get() == AnimationState::Animating && !self.suspended.get()
|
||||
}
|
||||
|
||||
pub fn run<T>(&self, mut servo_callback: T) where T: FnMut() -> bool {
|
||||
match self.kind {
|
||||
WindowKind::Window(_, ref events_loop) => {
|
||||
let mut stop = false;
|
||||
loop {
|
||||
if self.is_animating() {
|
||||
// We block on compositing (servo_callback ends up calling swap_buffers)
|
||||
events_loop.borrow_mut().poll_events(|e| {
|
||||
self.handle_window_event(e);
|
||||
});
|
||||
stop = servo_callback();
|
||||
} else {
|
||||
// We block on glutin's event loop (window events)
|
||||
events_loop.borrow_mut().run_forever(|e| {
|
||||
self.handle_window_event(e);
|
||||
if !self.event_queue.borrow().is_empty() {
|
||||
if !self.suspended.get() {
|
||||
stop = servo_callback();
|
||||
}
|
||||
}
|
||||
if stop || self.is_animating() {
|
||||
winit::ControlFlow::Break
|
||||
} else {
|
||||
winit::ControlFlow::Continue
|
||||
}
|
||||
});
|
||||
}
|
||||
if stop {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowKind::Headless(..) => {
|
||||
loop {
|
||||
// Sleep the main thread to avoid using 100% CPU
|
||||
// This can be done better, see comments in #18777
|
||||
if self.event_queue.borrow().is_empty() {
|
||||
thread::sleep(time::Duration::from_millis(5));
|
||||
}
|
||||
let stop = servo_callback();
|
||||
if stop {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "win"))]
|
||||
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers, browser_id: BrowserId) {
|
||||
match (mods, key) {
|
||||
(CMD_OR_CONTROL, Key::LeftBracket) => {
|
||||
let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1));
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
(CMD_OR_CONTROL, Key::RightBracket) => {
|
||||
let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1));
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "win")]
|
||||
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers, browser_id: BrowserId) {
|
||||
}
|
||||
|
||||
fn page_height(&self) -> f32 {
|
||||
let dpr = self.hidpi_factor();
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, _) => {
|
||||
let (_, height) = window.get_inner_size().expect("Failed to get window inner size.");
|
||||
height as f32 * dpr.get()
|
||||
},
|
||||
WindowKind::Headless(ref context) => {
|
||||
context.height as f32 * dpr.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn hidpi_factor(&self) -> TypedScale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||
match self.kind {
|
||||
|
@ -660,84 +620,8 @@ impl Window {
|
|||
TypedScale::new(ppi as f32 / 96.0)
|
||||
}
|
||||
|
||||
fn set_inner_size(&self, _: BrowserId, size: DeviceUintSize) {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, ..) => {
|
||||
let size = size.to_f32() / self.hidpi_factor();
|
||||
window.set_inner_size(size.width as u32, size.height as u32)
|
||||
}
|
||||
WindowKind::Headless(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_position(&self, _: BrowserId, point: DeviceIntPoint) {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, ..) => {
|
||||
let point = point.to_f32() / self.hidpi_factor();
|
||||
window.set_position(point.x as i32, point.y as i32)
|
||||
}
|
||||
WindowKind::Headless(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_fullscreen_state(&self, _: BrowserId, state: bool) {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, ..) => {
|
||||
if self.fullscreen.get() != state {
|
||||
window.set_fullscreen(None);
|
||||
}
|
||||
},
|
||||
WindowKind::Headless(..) => {}
|
||||
}
|
||||
self.fullscreen.set(state);
|
||||
}
|
||||
|
||||
fn set_page_title(&self, _: BrowserId, title: Option<String>) {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, ..) => {
|
||||
let fallback_title: String = if let Some(ref current_url) = *self.current_url.borrow() {
|
||||
current_url.to_string()
|
||||
} else {
|
||||
String::from("Untitled")
|
||||
};
|
||||
|
||||
let title = match title {
|
||||
Some(ref title) if title.len() > 0 => &**title,
|
||||
_ => &fallback_title,
|
||||
};
|
||||
let title = format!("{} - Servo", title);
|
||||
window.set_title(&title);
|
||||
}
|
||||
WindowKind::Headless(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn status(&self, _: BrowserId, _: Option<String>) {
|
||||
}
|
||||
|
||||
fn load_start(&self, _: BrowserId) {
|
||||
}
|
||||
|
||||
fn load_end(&self, _: BrowserId) {
|
||||
if opts::get().no_native_titlebar {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, ..) => {
|
||||
window.show();
|
||||
}
|
||||
WindowKind::Headless(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn history_changed(&self, _: BrowserId, history: Vec<LoadData>, current: usize) {
|
||||
*self.current_url.borrow_mut() = Some(history[current].url.clone());
|
||||
}
|
||||
|
||||
fn head_parsed(&self, _: BrowserId) {
|
||||
}
|
||||
|
||||
/// Has no effect on Android.
|
||||
fn set_cursor(&self, cursor: CursorKind) {
|
||||
pub fn set_cursor(&self, cursor: CursorKind) {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window, ..) => {
|
||||
use winit::MouseCursor;
|
||||
|
@ -785,152 +669,6 @@ impl Window {
|
|||
WindowKind::Headless(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_favicon(&self, _: BrowserId, _: ServoUrl) {
|
||||
}
|
||||
|
||||
/// Helper function to handle keyboard events.
|
||||
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() {
|
||||
Some(id) => id,
|
||||
None => { unreachable!("Can't get keys without a browser"); }
|
||||
};
|
||||
match (mods, ch, key) {
|
||||
(_, Some('+'), _) => {
|
||||
if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Zoom(1.1));
|
||||
} else if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL | KeyModifiers::ALT {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::PinchZoom(1.1));
|
||||
}
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('-'), _) => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Zoom(1.0 / 1.1));
|
||||
}
|
||||
(_, Some('-'), _) if mods == CMD_OR_CONTROL | KeyModifiers::ALT => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::PinchZoom(1.0 / 1.1));
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('0'), _) => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::ResetZoom);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::NavigateForward) => {
|
||||
let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1));
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::NavigateBackward) => {
|
||||
let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1));
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::Escape) => {
|
||||
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Quit);
|
||||
}
|
||||
}
|
||||
|
||||
(CMD_OR_ALT, None, Key::Right) => {
|
||||
let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1));
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
(CMD_OR_ALT, None, Key::Left) => {
|
||||
let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1));
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::PageDown) => {
|
||||
let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
|
||||
-self.page_height() + 2.0 * LINE_HEIGHT));
|
||||
self.scroll_window(scroll_location,
|
||||
TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::PageUp) => {
|
||||
let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
|
||||
self.page_height() - 2.0 * LINE_HEIGHT));
|
||||
self.scroll_window(scroll_location,
|
||||
TouchEventType::Move);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::Home) => {
|
||||
self.scroll_window(ScrollLocation::Start, TouchEventType::Move);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::End) => {
|
||||
self.scroll_window(ScrollLocation::End, TouchEventType::Move);
|
||||
}
|
||||
|
||||
(KeyModifiers::NONE, None, Key::Up) => {
|
||||
self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(0.0, 3.0 * LINE_HEIGHT)),
|
||||
TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::Down) => {
|
||||
self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(0.0, -3.0 * LINE_HEIGHT)),
|
||||
TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::Left) => {
|
||||
self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(LINE_HEIGHT, 0.0)), TouchEventType::Move);
|
||||
}
|
||||
(KeyModifiers::NONE, None, Key::Right) => {
|
||||
self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(-LINE_HEIGHT, 0.0)), TouchEventType::Move);
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('r'), _) => {
|
||||
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Reload(browser_id));
|
||||
}
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('l'), _) => {
|
||||
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
|
||||
let url: String = if let Some(ref url) = *self.current_url.borrow() {
|
||||
url.to_string()
|
||||
} else {
|
||||
String::from("")
|
||||
};
|
||||
let title = "URL or search query";
|
||||
if let Some(input) = tinyfiledialogs::input_box(title, title, &url) {
|
||||
if let Some(url) = sanitize_url(&input) {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::LoadUrl(browser_id, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(CMD_OR_CONTROL, Some('q'), _) => {
|
||||
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Quit);
|
||||
}
|
||||
}
|
||||
(_, Some('3'), _) => if mods ^ KeyModifiers::CONTROL == KeyModifiers::SHIFT {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::CaptureWebRender);
|
||||
}
|
||||
(KeyModifiers::CONTROL, None, Key::F10) => {
|
||||
let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::RenderTargetDebug);
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
(KeyModifiers::CONTROL, None, Key::F11) => {
|
||||
let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::TextureCacheDebug);
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
(KeyModifiers::CONTROL, None, Key::F12) => {
|
||||
let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::Profiler);
|
||||
self.event_queue.borrow_mut().push(event);
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.platform_handle_key(key, mods, browser_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn allow_navigation(&self, _: BrowserId, _: ServoUrl, response_chan: IpcSender<bool>) {
|
||||
if let Err(e) = response_chan.send(true) {
|
||||
warn!("Failed to send allow_navigation() response: {}", e);
|
||||
};
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -1046,20 +784,3 @@ fn glutin_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
|
|||
TouchPhase::Cancelled => TouchEventType::Cancel,
|
||||
}
|
||||
}
|
||||
|
||||
fn sanitize_url(request: &str) -> Option<ServoUrl> {
|
||||
let request = request.trim();
|
||||
ServoUrl::parse(&request).ok()
|
||||
.or_else(|| {
|
||||
if request.contains('/') || is_reg_domain(request) {
|
||||
ServoUrl::parse(&format!("http://{}", request)).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).or_else(|| {
|
||||
PREFS.get("shell.searchpage").as_string().and_then(|s: &str| {
|
||||
let url = s.replace("%s", request);
|
||||
ServoUrl::parse(&url).ok()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -29,13 +29,11 @@ extern crate glutin;
|
|||
// The window backed by glutin
|
||||
#[macro_use] extern crate log;
|
||||
extern crate msg;
|
||||
extern crate net_traits;
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))] extern crate osmesa_sys;
|
||||
extern crate script_traits;
|
||||
extern crate servo;
|
||||
extern crate servo_config;
|
||||
extern crate servo_geometry;
|
||||
extern crate servo_url;
|
||||
#[cfg(all(feature = "unstable", not(target_os = "android")))]
|
||||
#[macro_use]
|
||||
extern crate sig;
|
||||
|
@ -63,6 +61,8 @@ use std::panic;
|
|||
use std::process;
|
||||
use std::thread;
|
||||
|
||||
mod browser;
|
||||
|
||||
pub mod platform {
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use platform::macos::deinit;
|
||||
|
@ -163,6 +163,8 @@ fn main() {
|
|||
|
||||
let window = glutin_app::create_window();
|
||||
|
||||
let mut browser = browser::Browser::new(window.clone());
|
||||
|
||||
// If the url is not provided, we fallback to the homepage in PREFS,
|
||||
// or a blank page in case the homepage is not set either.
|
||||
let cwd = env::current_dir().unwrap();
|
||||
|
@ -178,23 +180,34 @@ fn main() {
|
|||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
servo.handle_events(vec![WindowEvent::NewBrowser(target_url, sender)]);
|
||||
let browser_id = receiver.recv().unwrap();
|
||||
window.set_browser_id(browser_id);
|
||||
browser.set_browser_id(browser_id);
|
||||
servo.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]);
|
||||
|
||||
servo.setup_logging();
|
||||
|
||||
window.run(|| {
|
||||
let win_events = window.get_events();
|
||||
let servo_events = servo.get_events();
|
||||
|
||||
// FIXME: this could be handled by Servo. We don't need
|
||||
// a repaint_synchronously function exposed.
|
||||
let need_resize = win_events.iter().any(|e| match *e {
|
||||
WindowEvent::Resize => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
});
|
||||
let stop = !servo.handle_events(win_events);
|
||||
|
||||
browser.handle_servo_events(servo_events);
|
||||
browser.handle_window_events(win_events);
|
||||
|
||||
if browser.shutdown_requested() {
|
||||
return true;
|
||||
}
|
||||
|
||||
servo.handle_events(browser.get_events());
|
||||
if need_resize {
|
||||
servo.repaint_synchronously();
|
||||
}
|
||||
window.handle_servo_events(servo.get_events());
|
||||
stop
|
||||
false
|
||||
});
|
||||
|
||||
servo.deinit();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue