Auto merge of #20658 - kvark:deglify, r=emilio

Make gleam optional for compositor, switch various names from glutin to winit

<!-- Please describe your changes on the following line: -->
The PR goes an extra step towards discriminating GL to a level of an optional dependency. This would ease up the transition to gfx-hal when the time calls for it, and upstreams some of the patches we've been using locally, cleans up some of the old cruft along the way.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach build-geckolib` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #20612

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____ it's just refactoring

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20658)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-04-19 16:18:14 -04:00 committed by GitHub
commit 89bf7c2a92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 288 additions and 252 deletions

View file

@ -22,6 +22,8 @@ matrix:
- curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -y
- source ~/.profile
script:
# see https://github.com/servo/servo/issues/20664
#- ./mach cargo check -p compositing --no-default-features
- ./mach build -d --verbose
- ./mach test-unit
- ./mach clean

View file

@ -60,6 +60,8 @@ install:
build_script:
- mach clean-nightlies --keep 2 --force
# see https://github.com/servo/servo/issues/20664
#- mach cargo check -p compositing --no-default-features
- mach build -d -v
- mach test-unit

View file

@ -10,10 +10,13 @@ build = "build.rs"
name = "compositing"
path = "lib.rs"
[features]
default = []
[dependencies]
euclid = "0.17"
gfx_traits = {path = "../gfx_traits"}
gleam = "0.4.34"
gleam = { version = "0.4.34", optional = true }
image = "0.18"
ipc-channel = "0.10"
libc = "0.2"

View file

@ -8,12 +8,16 @@ use compositor_thread::{CompositorProxy, CompositorReceiver};
use compositor_thread::{InitialCompositorState, Msg};
use euclid::{TypedPoint2D, TypedVector2D, TypedScale};
use gfx_traits::Epoch;
use gleam::gl;
use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcSharedMemory};
#[cfg(feature = "gleam")]
use gl;
#[cfg(feature = "gleam")]
use image::{DynamicImage, ImageFormat};
use ipc_channel::ipc;
use libc::c_void;
use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId};
use net_traits::image::base::{Image, PixelFormat};
use net_traits::image::base::Image;
#[cfg(feature = "gleam")]
use net_traits::image::base::PixelFormat;
use nonzero::NonZeroU32;
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::{AnimationState, AnimationTickType, ConstellationMsg, LayoutControlMsg};
@ -21,7 +25,7 @@ use script_traits::{MouseButton, MouseEventType, ScrollState, TouchEventType, To
use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
use servo_config::opts;
use servo_geometry::{DeviceIndependentPixel, DeviceUintLength};
use servo_geometry::DeviceIndependentPixel;
use std::collections::HashMap;
use std::env;
use std::fs::{File, create_dir_all};
@ -39,6 +43,7 @@ use webrender_api::{self, DeviceIntPoint, DevicePoint, HitTestFlags, HitTestResu
use webrender_api::{LayoutVector2D, ScrollEventPhase, ScrollLocation};
use windowing::{self, EmbedderCoordinates, MouseWindowEvent, WebRenderDebugOption, WindowMethods};
#[derive(Debug, PartialEq)]
enum UnableToComposite {
WindowUnprepared,
@ -176,9 +181,6 @@ pub struct IOCompositor<Window: WindowMethods> {
/// The webrender interface, if enabled.
webrender_api: webrender_api::RenderApi,
/// GL functions interface (may be GL or GLES)
gl: Rc<gl::Gl>,
/// Map of the pending paint metrics per layout thread.
/// The layout thread for each specific pipeline expects the compositor to
/// paint frames with specific given IDs (epoch). Once the compositor paints
@ -254,58 +256,6 @@ enum CompositeTarget {
PngFile
}
struct RenderTargetInfo {
framebuffer_ids: Vec<gl::GLuint>,
renderbuffer_ids: Vec<gl::GLuint>,
texture_ids: Vec<gl::GLuint>,
}
impl RenderTargetInfo {
fn empty() -> RenderTargetInfo {
RenderTargetInfo {
framebuffer_ids: Vec::new(),
renderbuffer_ids: Vec::new(),
texture_ids: Vec::new(),
}
}
}
fn initialize_png(gl: &gl::Gl, width: DeviceUintLength, height: DeviceUintLength) -> RenderTargetInfo {
let framebuffer_ids = gl.gen_framebuffers(1);
gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);
let texture_ids = gl.gen_textures(1);
gl.bind_texture(gl::TEXTURE_2D, texture_ids[0]);
gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as gl::GLint, width.get() as gl::GLsizei,
height.get() as gl::GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None);
gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as gl::GLint);
gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as gl::GLint);
gl.framebuffer_texture_2d(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D,
texture_ids[0], 0);
gl.bind_texture(gl::TEXTURE_2D, 0);
let renderbuffer_ids = gl.gen_renderbuffers(1);
let depth_rb = renderbuffer_ids[0];
gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb);
gl.renderbuffer_storage(gl::RENDERBUFFER,
gl::DEPTH_COMPONENT24,
width.get() as gl::GLsizei,
height.get() as gl::GLsizei);
gl.framebuffer_renderbuffer(gl::FRAMEBUFFER,
gl::DEPTH_ATTACHMENT,
gl::RENDERBUFFER,
depth_rb);
RenderTargetInfo {
framebuffer_ids: framebuffer_ids,
renderbuffer_ids: renderbuffer_ids,
texture_ids: texture_ids,
}
}
#[derive(Clone)]
pub struct RenderNotifier {
compositor_proxy: CompositorProxy,
@ -343,17 +293,15 @@ impl webrender_api::RenderNotifier for RenderNotifier {
}
impl<Window: WindowMethods> IOCompositor<Window> {
fn new(window: Rc<Window>, state: InitialCompositorState)
-> IOCompositor<Window> {
fn new(window: Rc<Window>, state: InitialCompositorState) -> Self {
let composite_target = match opts::get().output_file {
Some(_) => CompositeTarget::PngFile,
None => CompositeTarget::Window
};
IOCompositor {
gl: window.gl(),
embedder_coordinates: window.get_coordinates(),
window: window,
window,
port: state.receiver,
root_pipeline: None,
pipeline_details: HashMap::new(),
@ -362,7 +310,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
touch_handler: TouchHandler::new(),
pending_scroll_zoom_events: Vec::new(),
waiting_for_results_of_scroll: false,
composite_target: composite_target,
composite_target,
shutdown_state: ShutdownState::NotShuttingDown,
page_zoom: TypedScale::new(1.0),
viewport_zoom: PinchZoomFactor::new(1.0),
@ -384,7 +332,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
pub fn create(window: Rc<Window>, state: InitialCompositorState) -> IOCompositor<Window> {
pub fn create(window: Rc<Window>, state: InitialCompositorState) -> Self {
let mut compositor = IOCompositor::new(window, state);
// Set the size of the root layer.
@ -567,9 +515,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
/// Sets or unsets the animations-running flag for the given pipeline, and schedules a
/// recomposite if necessary.
fn change_running_animations_state(&mut self,
pipeline_id: PipelineId,
animation_state: AnimationState) {
fn change_running_animations_state(
&mut self,
pipeline_id: PipelineId,
animation_state: AnimationState,
) {
match animation_state {
AnimationState::AnimationsPresent => {
let visible = self.pipeline_details(pipeline_id).visible;
@ -1285,9 +1235,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
let render_target_info = match target {
CompositeTarget::Window => RenderTargetInfo::empty(),
_ => initialize_png(&*self.gl, width, height)
let rt_info = match target {
#[cfg(feature = "gleam")]
CompositeTarget::Window => {
gl::RenderTargetInfo::default()
}
#[cfg(feature = "gleam")]
CompositeTarget::WindowAndPng |
CompositeTarget::PngFile => {
gl::initialize_png(&*self.window.gl(), width, height)
}
#[cfg(not(feature = "gleam"))]
_ => ()
};
profile(ProfilerCategory::Compositing, None, self.time_profiler_chan.clone(), || {
@ -1332,24 +1291,25 @@ impl<Window: WindowMethods> IOCompositor<Window> {
let rv = match target {
CompositeTarget::Window => None,
#[cfg(feature = "gleam")]
CompositeTarget::WindowAndPng => {
let img = self.draw_img(render_target_info,
width,
height);
let img = gl::draw_img(&*self.window.gl(), rt_info, width, height);
Some(Image {
width: img.width(),
height: img.height(),
format: PixelFormat::RGB8,
bytes: IpcSharedMemory::from_bytes(&*img),
bytes: ipc::IpcSharedMemory::from_bytes(&*img),
id: None,
})
}
#[cfg(feature = "gleam")]
CompositeTarget::PngFile => {
let gl = &*self.window.gl();
profile(ProfilerCategory::ImageSaving, None, self.time_profiler_chan.clone(), || {
match opts::get().output_file.as_ref() {
Some(path) => match File::create(path) {
Ok(mut file) => {
let img = self.draw_img(render_target_info, width, height);
let img = gl::draw_img(gl, rt_info, width, height);
let dynamic_image = DynamicImage::ImageRgb8(img);
if let Err(e) = dynamic_image.save(&mut file, ImageFormat::PNG) {
error!("Failed to save {} ({}).", path, e);
@ -1362,6 +1322,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
});
None
}
#[cfg(not(feature = "gleam"))]
_ => None,
};
// Perform the page flip. This will likely block for a while.
@ -1378,44 +1340,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
Ok(rv)
}
fn draw_img(&self,
render_target_info: RenderTargetInfo,
width: DeviceUintLength,
height: DeviceUintLength)
-> RgbImage {
let width = width.get() as usize;
let height = height.get() as usize;
// For some reason, OSMesa fails to render on the 3rd
// attempt in headless mode, under some conditions.
// I think this can only be some kind of synchronization
// bug in OSMesa, but explicitly un-binding any vertex
// array here seems to work around that bug.
// See https://github.com/servo/servo/issues/18606.
self.gl.bind_vertex_array(0);
let mut pixels = self.gl.read_pixels(0, 0,
width as gl::GLsizei,
height as gl::GLsizei,
gl::RGB, gl::UNSIGNED_BYTE);
self.gl.bind_framebuffer(gl::FRAMEBUFFER, 0);
self.gl.delete_buffers(&render_target_info.texture_ids);
self.gl.delete_renderbuffers(&render_target_info.renderbuffer_ids);
self.gl.delete_framebuffers(&render_target_info.framebuffer_ids);
// flip image vertically (texture is upside down)
let orig_pixels = pixels.clone();
let stride = width * 3;
for y in 0..height {
let dst_start = y * stride;
let src_start = (height - y - 1) * stride;
let src_slice = &orig_pixels[src_start .. src_start + stride];
(&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]);
}
RgbImage::from_raw(width as u32, height as u32, pixels).expect("Flipping image failed!")
}
fn composite_if_necessary(&mut self, reason: CompositingReason) {
if self.composition_request == CompositionRequest::NoCompositingNecessary {
if opts::get().is_running_problem_test {

View file

@ -0,0 +1,97 @@
/* 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 gleam::gl;
use image::RgbImage;
use servo_geometry::DeviceUintLength;
#[derive(Default)]
pub struct RenderTargetInfo {
framebuffer_ids: Vec<gl::GLuint>,
renderbuffer_ids: Vec<gl::GLuint>,
texture_ids: Vec<gl::GLuint>,
}
pub fn initialize_png(
gl: &gl::Gl, width: DeviceUintLength, height: DeviceUintLength
) -> RenderTargetInfo {
let framebuffer_ids = gl.gen_framebuffers(1);
gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);
let texture_ids = gl.gen_textures(1);
gl.bind_texture(gl::TEXTURE_2D, texture_ids[0]);
gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as gl::GLint, width.get() as gl::GLsizei,
height.get() as gl::GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None);
gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as gl::GLint);
gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as gl::GLint);
gl.framebuffer_texture_2d(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D,
texture_ids[0], 0);
gl.bind_texture(gl::TEXTURE_2D, 0);
let renderbuffer_ids = gl.gen_renderbuffers(1);
let depth_rb = renderbuffer_ids[0];
gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb);
gl.renderbuffer_storage(gl::RENDERBUFFER,
gl::DEPTH_COMPONENT24,
width.get() as gl::GLsizei,
height.get() as gl::GLsizei);
gl.framebuffer_renderbuffer(gl::FRAMEBUFFER,
gl::DEPTH_ATTACHMENT,
gl::RENDERBUFFER,
depth_rb);
RenderTargetInfo {
framebuffer_ids,
renderbuffer_ids,
texture_ids,
}
}
pub fn draw_img(
gl: &gl::Gl,
render_target_info: RenderTargetInfo,
width: DeviceUintLength,
height: DeviceUintLength,
) -> RgbImage {
let width = width.get() as usize;
let height = height.get() as usize;
// For some reason, OSMesa fails to render on the 3rd
// attempt in headless mode, under some conditions.
// I think this can only be some kind of synchronization
// bug in OSMesa, but explicitly un-binding any vertex
// array here seems to work around that bug.
// See https://github.com/servo/servo/issues/18606.
gl.bind_vertex_array(0);
let mut pixels = gl.read_pixels(
0, 0,
width as gl::GLsizei,
height as gl::GLsizei,
gl::RGB, gl::UNSIGNED_BYTE,
);
gl.bind_framebuffer(gl::FRAMEBUFFER, 0);
gl.delete_buffers(&render_target_info.texture_ids);
gl.delete_renderbuffers(&render_target_info.renderbuffer_ids);
gl.delete_framebuffers(&render_target_info.framebuffer_ids);
// flip image vertically (texture is upside down)
let orig_pixels = pixels.clone();
let stride = width * 3;
for y in 0..height {
let dst_start = y * stride;
let src_start = (height - y - 1) * stride;
let src_slice = &orig_pixels[src_start .. src_start + stride];
(&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]);
}
RgbImage::from_raw(width as u32, height as u32, pixels)
.expect("Flipping image failed!")
}

View file

@ -6,7 +6,9 @@
extern crate euclid;
extern crate gfx_traits;
#[cfg(feature = "gleam")]
extern crate gleam;
#[cfg(feature = "gleam")]
extern crate image;
extern crate ipc_channel;
extern crate libc;
@ -38,6 +40,8 @@ use style_traits::CSSPixel;
mod compositor;
pub mod compositor_thread;
#[cfg(feature = "gleam")]
mod gl;
mod touch;
pub mod windowing;

View file

@ -6,6 +6,7 @@
use compositor_thread::EventLoopWaker;
use euclid::TypedScale;
#[cfg(feature = "gleam")]
use gleam::gl;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection};
@ -13,6 +14,7 @@ use script_traits::{MouseButton, TouchEventType, TouchId};
use servo_geometry::{DeviceIndependentPixel, DeviceUintLength};
use servo_url::ServoUrl;
use std::fmt::{Debug, Error, Formatter};
#[cfg(feature = "gleam")]
use std::rc::Rc;
use style_traits::DevicePixel;
use webrender_api::{DeviceIntPoint, DevicePoint, DeviceUintSize, DeviceUintRect, ScrollLocation};
@ -126,6 +128,7 @@ pub trait WindowMethods {
/// proceed and false if it should not.
fn prepare_for_composite(&self, width: DeviceUintLength, height: DeviceUintLength) -> bool;
/// Return the GL function pointer trait.
#[cfg(feature = "gleam")]
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>;

View file

@ -32,7 +32,7 @@ bluetooth_traits = {path = "../bluetooth_traits"}
bluetooth = {path = "../bluetooth"}
canvas = {path = "../canvas"}
canvas_traits = {path = "../canvas_traits"}
compositing = {path = "../compositing"}
compositing = {path = "../compositing", features = ["gleam"]}
constellation = {path = "../constellation"}
debugger = {path = "../debugger"}
devtools = {path = "../devtools"}

View file

@ -3,10 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use servo::msg::constellation_msg::{self, Key, KeyModifiers};
use winit::{self, VirtualKeyCode};
use winit::VirtualKeyCode;
bitflags! {
pub struct GlutinKeyModifiers: u8 {
pub struct WinitKeyModifiers: u8 {
const LEFT_CONTROL = 1;
const RIGHT_CONTROL = 2;
const LEFT_SHIFT = 4;
@ -131,129 +131,130 @@ pub fn char_to_script_key(c: char) -> Option<constellation_msg::Key> {
}
}
pub fn glutin_key_to_script_key(key: winit::VirtualKeyCode) -> Result<constellation_msg::Key, ()> {
pub fn winit_key_to_script_key(key: VirtualKeyCode) -> Result<constellation_msg::Key, ()> {
use winit::VirtualKeyCode::*;
// TODO(negge): add more key mappings
match key {
VirtualKeyCode::A => Ok(Key::A),
VirtualKeyCode::B => Ok(Key::B),
VirtualKeyCode::C => Ok(Key::C),
VirtualKeyCode::D => Ok(Key::D),
VirtualKeyCode::E => Ok(Key::E),
VirtualKeyCode::F => Ok(Key::F),
VirtualKeyCode::G => Ok(Key::G),
VirtualKeyCode::H => Ok(Key::H),
VirtualKeyCode::I => Ok(Key::I),
VirtualKeyCode::J => Ok(Key::J),
VirtualKeyCode::K => Ok(Key::K),
VirtualKeyCode::L => Ok(Key::L),
VirtualKeyCode::M => Ok(Key::M),
VirtualKeyCode::N => Ok(Key::N),
VirtualKeyCode::O => Ok(Key::O),
VirtualKeyCode::P => Ok(Key::P),
VirtualKeyCode::Q => Ok(Key::Q),
VirtualKeyCode::R => Ok(Key::R),
VirtualKeyCode::S => Ok(Key::S),
VirtualKeyCode::T => Ok(Key::T),
VirtualKeyCode::U => Ok(Key::U),
VirtualKeyCode::V => Ok(Key::V),
VirtualKeyCode::W => Ok(Key::W),
VirtualKeyCode::X => Ok(Key::X),
VirtualKeyCode::Y => Ok(Key::Y),
VirtualKeyCode::Z => Ok(Key::Z),
Ok(match key {
A => Key::A,
B => Key::B,
C => Key::C,
D => Key::D,
E => Key::E,
F => Key::F,
G => Key::G,
H => Key::H,
I => Key::I,
J => Key::J,
K => Key::K,
L => Key::L,
M => Key::M,
N => Key::N,
O => Key::O,
P => Key::P,
Q => Key::Q,
R => Key::R,
S => Key::S,
T => Key::T,
U => Key::U,
V => Key::V,
W => Key::W,
X => Key::X,
Y => Key::Y,
Z => Key::Z,
VirtualKeyCode::Numpad0 => Ok(Key::Kp0),
VirtualKeyCode::Numpad1 => Ok(Key::Kp1),
VirtualKeyCode::Numpad2 => Ok(Key::Kp2),
VirtualKeyCode::Numpad3 => Ok(Key::Kp3),
VirtualKeyCode::Numpad4 => Ok(Key::Kp4),
VirtualKeyCode::Numpad5 => Ok(Key::Kp5),
VirtualKeyCode::Numpad6 => Ok(Key::Kp6),
VirtualKeyCode::Numpad7 => Ok(Key::Kp7),
VirtualKeyCode::Numpad8 => Ok(Key::Kp8),
VirtualKeyCode::Numpad9 => Ok(Key::Kp9),
Numpad0 => Key::Kp0,
Numpad1 => Key::Kp1,
Numpad2 => Key::Kp2,
Numpad3 => Key::Kp3,
Numpad4 => Key::Kp4,
Numpad5 => Key::Kp5,
Numpad6 => Key::Kp6,
Numpad7 => Key::Kp7,
Numpad8 => Key::Kp8,
Numpad9 => Key::Kp9,
VirtualKeyCode::Key0 => Ok(Key::Num0),
VirtualKeyCode::Key1 => Ok(Key::Num1),
VirtualKeyCode::Key2 => Ok(Key::Num2),
VirtualKeyCode::Key3 => Ok(Key::Num3),
VirtualKeyCode::Key4 => Ok(Key::Num4),
VirtualKeyCode::Key5 => Ok(Key::Num5),
VirtualKeyCode::Key6 => Ok(Key::Num6),
VirtualKeyCode::Key7 => Ok(Key::Num7),
VirtualKeyCode::Key8 => Ok(Key::Num8),
VirtualKeyCode::Key9 => Ok(Key::Num9),
Key0 => Key::Num0,
Key1 => Key::Num1,
Key2 => Key::Num2,
Key3 => Key::Num3,
Key4 => Key::Num4,
Key5 => Key::Num5,
Key6 => Key::Num6,
Key7 => Key::Num7,
Key8 => Key::Num8,
Key9 => Key::Num9,
VirtualKeyCode::Return => Ok(Key::Enter),
VirtualKeyCode::Space => Ok(Key::Space),
VirtualKeyCode::Escape => Ok(Key::Escape),
VirtualKeyCode::Equals => Ok(Key::Equal),
VirtualKeyCode::Minus => Ok(Key::Minus),
VirtualKeyCode::Back => Ok(Key::Backspace),
VirtualKeyCode::PageDown => Ok(Key::PageDown),
VirtualKeyCode::PageUp => Ok(Key::PageUp),
Return => Key::Enter,
Space => Key::Space,
Escape => Key::Escape,
Equals => Key::Equal,
Minus => Key::Minus,
Back => Key::Backspace,
PageDown => Key::PageDown,
PageUp => Key::PageUp,
VirtualKeyCode::Insert => Ok(Key::Insert),
VirtualKeyCode::Home => Ok(Key::Home),
VirtualKeyCode::Delete => Ok(Key::Delete),
VirtualKeyCode::End => Ok(Key::End),
Insert => Key::Insert,
Home => Key::Home,
Delete => Key::Delete,
End => Key::End,
VirtualKeyCode::Left => Ok(Key::Left),
VirtualKeyCode::Up => Ok(Key::Up),
VirtualKeyCode::Right => Ok(Key::Right),
VirtualKeyCode::Down => Ok(Key::Down),
Left => Key::Left,
Up => Key::Up,
Right => Key::Right,
Down => Key::Down,
VirtualKeyCode::LShift => Ok(Key::LeftShift),
VirtualKeyCode::LControl => Ok(Key::LeftControl),
VirtualKeyCode::LAlt => Ok(Key::LeftAlt),
VirtualKeyCode::LWin => Ok(Key::LeftSuper),
VirtualKeyCode::RShift => Ok(Key::RightShift),
VirtualKeyCode::RControl => Ok(Key::RightControl),
VirtualKeyCode::RAlt => Ok(Key::RightAlt),
VirtualKeyCode::RWin => Ok(Key::RightSuper),
LShift => Key::LeftShift,
LControl => Key::LeftControl,
LAlt => Key::LeftAlt,
LWin => Key::LeftSuper,
RShift => Key::RightShift,
RControl => Key::RightControl,
RAlt => Key::RightAlt,
RWin => Key::RightSuper,
VirtualKeyCode::Apostrophe => Ok(Key::Apostrophe),
VirtualKeyCode::Backslash => Ok(Key::Backslash),
VirtualKeyCode::Comma => Ok(Key::Comma),
VirtualKeyCode::Grave => Ok(Key::GraveAccent),
VirtualKeyCode::LBracket => Ok(Key::LeftBracket),
VirtualKeyCode::Period => Ok(Key::Period),
VirtualKeyCode::RBracket => Ok(Key::RightBracket),
VirtualKeyCode::Semicolon => Ok(Key::Semicolon),
VirtualKeyCode::Slash => Ok(Key::Slash),
VirtualKeyCode::Tab => Ok(Key::Tab),
VirtualKeyCode::Subtract => Ok(Key::Minus),
Apostrophe => Key::Apostrophe,
Backslash => Key::Backslash,
Comma => Key::Comma,
Grave => Key::GraveAccent,
LBracket => Key::LeftBracket,
Period => Key::Period,
RBracket => Key::RightBracket,
Semicolon => Key::Semicolon,
Slash => Key::Slash,
Tab => Key::Tab,
Subtract => Key::Minus,
VirtualKeyCode::F1 => Ok(Key::F1),
VirtualKeyCode::F2 => Ok(Key::F2),
VirtualKeyCode::F3 => Ok(Key::F3),
VirtualKeyCode::F4 => Ok(Key::F4),
VirtualKeyCode::F5 => Ok(Key::F5),
VirtualKeyCode::F6 => Ok(Key::F6),
VirtualKeyCode::F7 => Ok(Key::F7),
VirtualKeyCode::F8 => Ok(Key::F8),
VirtualKeyCode::F9 => Ok(Key::F9),
VirtualKeyCode::F10 => Ok(Key::F10),
VirtualKeyCode::F11 => Ok(Key::F11),
VirtualKeyCode::F12 => Ok(Key::F12),
F1 => Key::F1,
F2 => Key::F2,
F3 => Key::F3,
F4 => Key::F4,
F5 => Key::F5,
F6 => Key::F6,
F7 => Key::F7,
F8 => Key::F8,
F9 => Key::F9,
F10 => Key::F10,
F11 => Key::F11,
F12 => Key::F12,
VirtualKeyCode::NavigateBackward => Ok(Key::NavigateBackward),
VirtualKeyCode::NavigateForward => Ok(Key::NavigateForward),
_ => Err(()),
}
NavigateBackward => Key::NavigateBackward,
NavigateForward => Key::NavigateForward,
_ => return Err(()),
})
}
pub fn glutin_mods_to_script_mods(modifiers: GlutinKeyModifiers) -> constellation_msg::KeyModifiers {
pub fn winit_mods_to_script_mods(modifiers: WinitKeyModifiers) -> constellation_msg::KeyModifiers {
let mut result = constellation_msg::KeyModifiers::empty();
if modifiers.intersects(GlutinKeyModifiers::LEFT_SHIFT | GlutinKeyModifiers::RIGHT_SHIFT) {
if modifiers.intersects(WinitKeyModifiers::LEFT_SHIFT | WinitKeyModifiers::RIGHT_SHIFT) {
result.insert(KeyModifiers::SHIFT);
}
if modifiers.intersects(GlutinKeyModifiers::LEFT_CONTROL | GlutinKeyModifiers::RIGHT_CONTROL) {
if modifiers.intersects(WinitKeyModifiers::LEFT_CONTROL | WinitKeyModifiers::RIGHT_CONTROL) {
result.insert(KeyModifiers::CONTROL);
}
if modifiers.intersects(GlutinKeyModifiers::LEFT_ALT | GlutinKeyModifiers::RIGHT_ALT) {
if modifiers.intersects(WinitKeyModifiers::LEFT_ALT | WinitKeyModifiers::RIGHT_ALT) {
result.insert(KeyModifiers::ALT);
}
if modifiers.intersects(GlutinKeyModifiers::LEFT_SUPER | GlutinKeyModifiers::RIGHT_SUPER) {
if modifiers.intersects(WinitKeyModifiers::LEFT_SUPER | WinitKeyModifiers::RIGHT_SUPER) {
result.insert(KeyModifiers::SUPER);
}
result

View file

@ -2,13 +2,13 @@
* 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/. */
//! A windowing implementation using glutin.
//! A windowing implementation using winit.
use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
#[cfg(target_os = "windows")]
use gdi32;
use gleam::gl;
use glutin::{self, Api, GlContext, GlRequest};
use glutin::{Api, ContextBuilder, GlContext, GlRequest, GlWindow};
#[cfg(any(target_os = "linux", target_os = "macos"))]
use osmesa_sys;
use servo::compositing::compositor_thread::EventLoopWaker;
@ -31,7 +31,7 @@ use std::rc::Rc;
use std::sync::Arc;
use std::thread;
use std::time;
use super::keyutils::{self, GlutinKeyModifiers};
use super::keyutils::{self, WinitKeyModifiers};
#[cfg(target_os = "windows")]
use user32;
#[cfg(target_os = "windows")]
@ -138,7 +138,7 @@ impl HeadlessContext {
}
enum WindowKind {
Window(glutin::GlWindow, RefCell<winit::EventsLoop>),
Window(GlWindow, RefCell<winit::EventsLoop>),
Headless(HeadlessContext),
}
@ -151,7 +151,7 @@ pub struct Window {
mouse_down_point: Cell<TypedPoint2D<i32, DevicePixel>>,
event_queue: RefCell<Vec<WindowEvent>>,
mouse_pos: Cell<TypedPoint2D<i32, DevicePixel>>,
key_modifiers: Cell<GlutinKeyModifiers>,
key_modifiers: Cell<WinitKeyModifiers>,
last_pressed_key: Cell<Option<Key>>,
animation_state: Cell<AnimationState>,
fullscreen: Cell<bool>,
@ -203,7 +203,7 @@ impl Window {
window_builder = builder_with_platform_options(window_builder);
let mut context_builder = glutin::ContextBuilder::new()
let mut context_builder = ContextBuilder::new()
.with_gl(Window::gl_version())
.with_vsync(opts::get().enable_vsync);
@ -211,7 +211,7 @@ impl Window {
context_builder = context_builder.with_multisampling(MULTISAMPLES)
}
let glutin_window = glutin::GlWindow::new(window_builder, context_builder, &events_loop)
let glutin_window = GlWindow::new(window_builder, context_builder, &events_loop)
.expect("Failed to create window.");
unsafe {
@ -270,7 +270,7 @@ impl Window {
mouse_down_point: Cell::new(TypedPoint2D::new(0, 0)),
mouse_pos: Cell::new(TypedPoint2D::new(0, 0)),
key_modifiers: Cell::new(GlutinKeyModifiers::empty()),
key_modifiers: Cell::new(WinitKeyModifiers::empty()),
last_pressed_key: Cell::new(None),
gl: gl.clone(),
@ -347,13 +347,13 @@ impl Window {
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);
self.winit_event_to_servo_event(e);
});
stop = servo_callback();
} else {
// We block on glutin's event loop (window events)
// We block on winit's event loop (window events)
events_loop.borrow_mut().run_forever(|e| {
self.glutin_event_to_servo_event(e);
self.winit_event_to_servo_event(e);
if !self.event_queue.borrow().is_empty() {
if !self.suspended.get() {
stop = servo_callback();
@ -398,7 +398,7 @@ impl Window {
}
fn handle_received_character(&self, ch: char) {
let modifiers = keyutils::glutin_mods_to_script_mods(self.key_modifiers.get());
let modifiers = keyutils::winit_mods_to_script_mods(self.key_modifiers.get());
if keyutils::is_identifier_ignorable(&ch) {
return
}
@ -425,14 +425,14 @@ impl Window {
fn toggle_keyboard_modifiers(&self, virtual_key_code: VirtualKeyCode) {
match virtual_key_code {
VirtualKeyCode::LControl => self.toggle_modifier(GlutinKeyModifiers::LEFT_CONTROL),
VirtualKeyCode::RControl => self.toggle_modifier(GlutinKeyModifiers::RIGHT_CONTROL),
VirtualKeyCode::LShift => self.toggle_modifier(GlutinKeyModifiers::LEFT_SHIFT),
VirtualKeyCode::RShift => self.toggle_modifier(GlutinKeyModifiers::RIGHT_SHIFT),
VirtualKeyCode::LAlt => self.toggle_modifier(GlutinKeyModifiers::LEFT_ALT),
VirtualKeyCode::RAlt => self.toggle_modifier(GlutinKeyModifiers::RIGHT_ALT),
VirtualKeyCode::LWin => self.toggle_modifier(GlutinKeyModifiers::LEFT_SUPER),
VirtualKeyCode::RWin => self.toggle_modifier(GlutinKeyModifiers::RIGHT_SUPER),
VirtualKeyCode::LControl => self.toggle_modifier(WinitKeyModifiers::LEFT_CONTROL),
VirtualKeyCode::RControl => self.toggle_modifier(WinitKeyModifiers::RIGHT_CONTROL),
VirtualKeyCode::LShift => self.toggle_modifier(WinitKeyModifiers::LEFT_SHIFT),
VirtualKeyCode::RShift => self.toggle_modifier(WinitKeyModifiers::RIGHT_SHIFT),
VirtualKeyCode::LAlt => self.toggle_modifier(WinitKeyModifiers::LEFT_ALT),
VirtualKeyCode::RAlt => self.toggle_modifier(WinitKeyModifiers::RIGHT_ALT),
VirtualKeyCode::LWin => self.toggle_modifier(WinitKeyModifiers::LEFT_SUPER),
VirtualKeyCode::RWin => self.toggle_modifier(WinitKeyModifiers::RIGHT_SUPER),
_ => {}
}
}
@ -440,7 +440,7 @@ impl Window {
fn handle_keyboard_input(&self, element_state: ElementState, virtual_key_code: VirtualKeyCode) {
self.toggle_keyboard_modifiers(virtual_key_code);
if let Ok(key) = keyutils::glutin_key_to_script_key(virtual_key_code) {
if let Ok(key) = keyutils::winit_key_to_script_key(virtual_key_code) {
let state = match element_state {
ElementState::Pressed => KeyState::Pressed,
ElementState::Released => KeyState::Released,
@ -450,12 +450,12 @@ impl Window {
self.last_pressed_key.set(Some(key));
}
}
let modifiers = keyutils::glutin_mods_to_script_mods(self.key_modifiers.get());
let modifiers = keyutils::winit_mods_to_script_mods(self.key_modifiers.get());
self.event_queue.borrow_mut().push(WindowEvent::KeyEvent(None, key, state, modifiers));
}
}
fn glutin_event_to_servo_event(&self, event: winit::Event) {
fn winit_event_to_servo_event(&self, event: winit::Event) {
match event {
Event::WindowEvent {
event: winit::WindowEvent::ReceivedCharacter(ch),
@ -505,7 +505,7 @@ impl Window {
}
let scroll_location = ScrollLocation::Delta(TypedVector2D::new(dx, dy));
let phase = glutin_phase_to_touch_event_type(phase);
let phase = winit_phase_to_touch_event_type(phase);
let event = WindowEvent::Scroll(scroll_location, self.mouse_pos.get(), phase);
self.event_queue.borrow_mut().push(event);
},
@ -515,7 +515,7 @@ impl Window {
} => {
use servo::script_traits::TouchId;
let phase = glutin_phase_to_touch_event_type(touch.phase);
let phase = winit_phase_to_touch_event_type(touch.phase);
let id = TouchId(touch.id as i32);
let point = TypedPoint2D::new(touch.location.0 as f32, touch.location.1 as f32);
self.event_queue.borrow_mut().push(WindowEvent::Touch(phase, id, point));
@ -560,7 +560,7 @@ impl Window {
}
}
fn toggle_modifier(&self, modifier: GlutinKeyModifiers) {
fn toggle_modifier(&self, modifier: WinitKeyModifiers) {
let mut modifiers = self.key_modifiers.get();
modifiers.toggle(modifier);
self.key_modifiers.set(modifiers);
@ -636,7 +636,7 @@ impl Window {
WindowKind::Window(ref window, ..) => {
use winit::MouseCursor;
let glutin_cursor = match cursor {
let winit_cursor = match cursor {
CursorKind::Auto => MouseCursor::Default,
CursorKind::None => MouseCursor::NoneCursor,
CursorKind::Default => MouseCursor::Default,
@ -674,7 +674,7 @@ impl Window {
CursorKind::ZoomIn => MouseCursor::ZoomIn,
CursorKind::ZoomOut => MouseCursor::ZoomOut,
};
window.set_cursor(glutin_cursor);
window.set_cursor(winit_cursor);
}
WindowKind::Headless(..) => {}
}
@ -786,7 +786,7 @@ impl WindowMethods for Window {
}
}
fn glutin_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
fn winit_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
match phase {
TouchPhase::Started => TouchEventType::Down,
TouchPhase::Moved => TouchEventType::Move,