mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Make gleam optional for compositor, switch various names from glutin to winit
This commit is contained in:
parent
3695fc4efc
commit
7fa295d8e6
10 changed files with 187 additions and 154 deletions
|
@ -22,6 +22,7 @@ matrix:
|
||||||
- curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -y
|
- curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -y
|
||||||
- source ~/.profile
|
- source ~/.profile
|
||||||
script:
|
script:
|
||||||
|
#- ./mach cargo check -p compositing --no-default-features
|
||||||
- ./mach build -d --verbose
|
- ./mach build -d --verbose
|
||||||
- ./mach test-unit
|
- ./mach test-unit
|
||||||
- ./mach clean
|
- ./mach clean
|
||||||
|
|
|
@ -60,6 +60,7 @@ install:
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- mach clean-nightlies --keep 2 --force
|
- mach clean-nightlies --keep 2 --force
|
||||||
|
#- mach cargo check -p compositing --no-default-features
|
||||||
- mach build -d -v
|
- mach build -d -v
|
||||||
- mach test-unit
|
- mach test-unit
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,13 @@ build = "build.rs"
|
||||||
name = "compositing"
|
name = "compositing"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
euclid = "0.17"
|
euclid = "0.17"
|
||||||
gfx_traits = {path = "../gfx_traits"}
|
gfx_traits = {path = "../gfx_traits"}
|
||||||
gleam = "0.4.34"
|
gleam = { version = "0.4.34", optional = true }
|
||||||
image = "0.18"
|
image = "0.18"
|
||||||
ipc-channel = "0.10"
|
ipc-channel = "0.10"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
|
@ -8,12 +8,16 @@ use compositor_thread::{CompositorProxy, CompositorReceiver};
|
||||||
use compositor_thread::{InitialCompositorState, Msg};
|
use compositor_thread::{InitialCompositorState, Msg};
|
||||||
use euclid::{TypedPoint2D, TypedVector2D, TypedScale};
|
use euclid::{TypedPoint2D, TypedVector2D, TypedScale};
|
||||||
use gfx_traits::Epoch;
|
use gfx_traits::Epoch;
|
||||||
use gleam::gl;
|
#[cfg(feature = "gleam")]
|
||||||
use image::{DynamicImage, ImageFormat, RgbImage};
|
use gl;
|
||||||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
#[cfg(feature = "gleam")]
|
||||||
|
use image::{DynamicImage, ImageFormat};
|
||||||
|
use ipc_channel::ipc;
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId};
|
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 nonzero::NonZeroU32;
|
||||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||||
use script_traits::{AnimationState, AnimationTickType, ConstellationMsg, LayoutControlMsg};
|
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::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
||||||
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
|
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
use servo_geometry::{DeviceIndependentPixel, DeviceUintLength};
|
use servo_geometry::DeviceIndependentPixel;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::{File, create_dir_all};
|
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 webrender_api::{LayoutVector2D, ScrollEventPhase, ScrollLocation};
|
||||||
use windowing::{self, EmbedderCoordinates, MouseWindowEvent, WebRenderDebugOption, WindowMethods};
|
use windowing::{self, EmbedderCoordinates, MouseWindowEvent, WebRenderDebugOption, WindowMethods};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum UnableToComposite {
|
enum UnableToComposite {
|
||||||
WindowUnprepared,
|
WindowUnprepared,
|
||||||
|
@ -176,9 +181,6 @@ pub struct IOCompositor<Window: WindowMethods> {
|
||||||
/// The webrender interface, if enabled.
|
/// The webrender interface, if enabled.
|
||||||
webrender_api: webrender_api::RenderApi,
|
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.
|
/// Map of the pending paint metrics per layout thread.
|
||||||
/// The layout thread for each specific pipeline expects the compositor to
|
/// The layout thread for each specific pipeline expects the compositor to
|
||||||
/// paint frames with specific given IDs (epoch). Once the compositor paints
|
/// paint frames with specific given IDs (epoch). Once the compositor paints
|
||||||
|
@ -254,58 +256,6 @@ enum CompositeTarget {
|
||||||
PngFile
|
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)]
|
#[derive(Clone)]
|
||||||
pub struct RenderNotifier {
|
pub struct RenderNotifier {
|
||||||
compositor_proxy: CompositorProxy,
|
compositor_proxy: CompositorProxy,
|
||||||
|
@ -343,17 +293,15 @@ impl webrender_api::RenderNotifier for RenderNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Window: WindowMethods> IOCompositor<Window> {
|
impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
fn new(window: Rc<Window>, state: InitialCompositorState)
|
fn new(window: Rc<Window>, state: InitialCompositorState) -> Self {
|
||||||
-> IOCompositor<Window> {
|
|
||||||
let composite_target = match opts::get().output_file {
|
let composite_target = match opts::get().output_file {
|
||||||
Some(_) => CompositeTarget::PngFile,
|
Some(_) => CompositeTarget::PngFile,
|
||||||
None => CompositeTarget::Window
|
None => CompositeTarget::Window
|
||||||
};
|
};
|
||||||
|
|
||||||
IOCompositor {
|
IOCompositor {
|
||||||
gl: window.gl(),
|
|
||||||
embedder_coordinates: window.get_coordinates(),
|
embedder_coordinates: window.get_coordinates(),
|
||||||
window: window,
|
window,
|
||||||
port: state.receiver,
|
port: state.receiver,
|
||||||
root_pipeline: None,
|
root_pipeline: None,
|
||||||
pipeline_details: HashMap::new(),
|
pipeline_details: HashMap::new(),
|
||||||
|
@ -362,7 +310,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
touch_handler: TouchHandler::new(),
|
touch_handler: TouchHandler::new(),
|
||||||
pending_scroll_zoom_events: Vec::new(),
|
pending_scroll_zoom_events: Vec::new(),
|
||||||
waiting_for_results_of_scroll: false,
|
waiting_for_results_of_scroll: false,
|
||||||
composite_target: composite_target,
|
composite_target,
|
||||||
shutdown_state: ShutdownState::NotShuttingDown,
|
shutdown_state: ShutdownState::NotShuttingDown,
|
||||||
page_zoom: TypedScale::new(1.0),
|
page_zoom: TypedScale::new(1.0),
|
||||||
viewport_zoom: PinchZoomFactor::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);
|
let mut compositor = IOCompositor::new(window, state);
|
||||||
|
|
||||||
// Set the size of the root layer.
|
// 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
|
/// Sets or unsets the animations-running flag for the given pipeline, and schedules a
|
||||||
/// recomposite if necessary.
|
/// recomposite if necessary.
|
||||||
fn change_running_animations_state(&mut self,
|
fn change_running_animations_state(
|
||||||
pipeline_id: PipelineId,
|
&mut self,
|
||||||
animation_state: AnimationState) {
|
pipeline_id: PipelineId,
|
||||||
|
animation_state: AnimationState,
|
||||||
|
) {
|
||||||
match animation_state {
|
match animation_state {
|
||||||
AnimationState::AnimationsPresent => {
|
AnimationState::AnimationsPresent => {
|
||||||
let visible = self.pipeline_details(pipeline_id).visible;
|
let visible = self.pipeline_details(pipeline_id).visible;
|
||||||
|
@ -1285,9 +1235,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_target_info = match target {
|
let rt_info = match target {
|
||||||
CompositeTarget::Window => RenderTargetInfo::empty(),
|
#[cfg(feature = "gleam")]
|
||||||
_ => initialize_png(&*self.gl, width, height)
|
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(), || {
|
profile(ProfilerCategory::Compositing, None, self.time_profiler_chan.clone(), || {
|
||||||
|
@ -1332,24 +1291,25 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
|
|
||||||
let rv = match target {
|
let rv = match target {
|
||||||
CompositeTarget::Window => None,
|
CompositeTarget::Window => None,
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
CompositeTarget::WindowAndPng => {
|
CompositeTarget::WindowAndPng => {
|
||||||
let img = self.draw_img(render_target_info,
|
let img = gl::draw_img(&*self.window.gl(), rt_info, width, height);
|
||||||
width,
|
|
||||||
height);
|
|
||||||
Some(Image {
|
Some(Image {
|
||||||
width: img.width(),
|
width: img.width(),
|
||||||
height: img.height(),
|
height: img.height(),
|
||||||
format: PixelFormat::RGB8,
|
format: PixelFormat::RGB8,
|
||||||
bytes: IpcSharedMemory::from_bytes(&*img),
|
bytes: ipc::IpcSharedMemory::from_bytes(&*img),
|
||||||
id: None,
|
id: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
CompositeTarget::PngFile => {
|
CompositeTarget::PngFile => {
|
||||||
|
let gl = &*self.window.gl();
|
||||||
profile(ProfilerCategory::ImageSaving, None, self.time_profiler_chan.clone(), || {
|
profile(ProfilerCategory::ImageSaving, None, self.time_profiler_chan.clone(), || {
|
||||||
match opts::get().output_file.as_ref() {
|
match opts::get().output_file.as_ref() {
|
||||||
Some(path) => match File::create(path) {
|
Some(path) => match File::create(path) {
|
||||||
Ok(mut file) => {
|
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);
|
let dynamic_image = DynamicImage::ImageRgb8(img);
|
||||||
if let Err(e) = dynamic_image.save(&mut file, ImageFormat::PNG) {
|
if let Err(e) = dynamic_image.save(&mut file, ImageFormat::PNG) {
|
||||||
error!("Failed to save {} ({}).", path, e);
|
error!("Failed to save {} ({}).", path, e);
|
||||||
|
@ -1362,6 +1322,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
});
|
});
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "gleam"))]
|
||||||
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Perform the page flip. This will likely block for a while.
|
// Perform the page flip. This will likely block for a while.
|
||||||
|
@ -1378,44 +1340,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
Ok(rv)
|
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) {
|
fn composite_if_necessary(&mut self, reason: CompositingReason) {
|
||||||
if self.composition_request == CompositionRequest::NoCompositingNecessary {
|
if self.composition_request == CompositionRequest::NoCompositingNecessary {
|
||||||
if opts::get().is_running_problem_test {
|
if opts::get().is_running_problem_test {
|
||||||
|
|
97
components/compositing/gl.rs
Normal file
97
components/compositing/gl.rs
Normal 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!")
|
||||||
|
}
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
extern crate euclid;
|
extern crate euclid;
|
||||||
extern crate gfx_traits;
|
extern crate gfx_traits;
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
extern crate gleam;
|
extern crate gleam;
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
extern crate image;
|
extern crate image;
|
||||||
extern crate ipc_channel;
|
extern crate ipc_channel;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
@ -38,6 +40,8 @@ use style_traits::CSSPixel;
|
||||||
|
|
||||||
mod compositor;
|
mod compositor;
|
||||||
pub mod compositor_thread;
|
pub mod compositor_thread;
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
|
mod gl;
|
||||||
mod touch;
|
mod touch;
|
||||||
pub mod windowing;
|
pub mod windowing;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use compositor_thread::EventLoopWaker;
|
use compositor_thread::EventLoopWaker;
|
||||||
use euclid::TypedScale;
|
use euclid::TypedScale;
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
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};
|
||||||
|
@ -13,6 +14,7 @@ use script_traits::{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};
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use style_traits::DevicePixel;
|
use style_traits::DevicePixel;
|
||||||
use webrender_api::{DeviceIntPoint, DevicePoint, DeviceUintSize, DeviceUintRect, ScrollLocation};
|
use webrender_api::{DeviceIntPoint, DevicePoint, DeviceUintSize, DeviceUintRect, ScrollLocation};
|
||||||
|
@ -126,6 +128,7 @@ pub trait WindowMethods {
|
||||||
/// 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;
|
||||||
/// Return the GL function pointer trait.
|
/// Return the GL function pointer trait.
|
||||||
|
#[cfg(feature = "gleam")]
|
||||||
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.
|
/// Returns a thread-safe object to wake up the window's event loop.
|
||||||
fn create_event_loop_waker(&self) -> Box<EventLoopWaker>;
|
fn create_event_loop_waker(&self) -> Box<EventLoopWaker>;
|
||||||
|
|
|
@ -32,7 +32,7 @@ bluetooth_traits = {path = "../bluetooth_traits"}
|
||||||
bluetooth = {path = "../bluetooth"}
|
bluetooth = {path = "../bluetooth"}
|
||||||
canvas = {path = "../canvas"}
|
canvas = {path = "../canvas"}
|
||||||
canvas_traits = {path = "../canvas_traits"}
|
canvas_traits = {path = "../canvas_traits"}
|
||||||
compositing = {path = "../compositing"}
|
compositing = {path = "../compositing", features = ["gleam"]}
|
||||||
constellation = {path = "../constellation"}
|
constellation = {path = "../constellation"}
|
||||||
debugger = {path = "../debugger"}
|
debugger = {path = "../debugger"}
|
||||||
devtools = {path = "../devtools"}
|
devtools = {path = "../devtools"}
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use servo::msg::constellation_msg::{self, Key, KeyModifiers};
|
use servo::msg::constellation_msg::{self, Key, KeyModifiers};
|
||||||
use winit::{self, VirtualKeyCode};
|
use winit::VirtualKeyCode;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct GlutinKeyModifiers: u8 {
|
pub struct WinitKeyModifiers: u8 {
|
||||||
const LEFT_CONTROL = 1;
|
const LEFT_CONTROL = 1;
|
||||||
const RIGHT_CONTROL = 2;
|
const RIGHT_CONTROL = 2;
|
||||||
const LEFT_SHIFT = 4;
|
const LEFT_SHIFT = 4;
|
||||||
|
@ -131,7 +131,7 @@ 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, ()> {
|
||||||
// TODO(negge): add more key mappings
|
// TODO(negge): add more key mappings
|
||||||
match key {
|
match key {
|
||||||
VirtualKeyCode::A => Ok(Key::A),
|
VirtualKeyCode::A => Ok(Key::A),
|
||||||
|
@ -242,18 +242,18 @@ pub fn glutin_key_to_script_key(key: winit::VirtualKeyCode) -> Result<constellat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
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);
|
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);
|
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);
|
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.insert(KeyModifiers::SUPER);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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};
|
use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use gdi32;
|
use gdi32;
|
||||||
use gleam::gl;
|
use gleam::gl;
|
||||||
use glutin::{self, Api, GlContext, GlRequest};
|
use glutin::{Api, ContextBuilder, GlContext, GlRequest, GlWindow};
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
use osmesa_sys;
|
use osmesa_sys;
|
||||||
use servo::compositing::compositor_thread::EventLoopWaker;
|
use servo::compositing::compositor_thread::EventLoopWaker;
|
||||||
|
@ -31,7 +31,7 @@ use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time;
|
use std::time;
|
||||||
use super::keyutils::{self, GlutinKeyModifiers};
|
use super::keyutils::{self, WinitKeyModifiers};
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use user32;
|
use user32;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
@ -138,7 +138,7 @@ impl HeadlessContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum WindowKind {
|
enum WindowKind {
|
||||||
Window(glutin::GlWindow, RefCell<winit::EventsLoop>),
|
Window(GlWindow, RefCell<winit::EventsLoop>),
|
||||||
Headless(HeadlessContext),
|
Headless(HeadlessContext),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ pub struct Window {
|
||||||
mouse_down_point: Cell<TypedPoint2D<i32, DevicePixel>>,
|
mouse_down_point: Cell<TypedPoint2D<i32, DevicePixel>>,
|
||||||
event_queue: RefCell<Vec<WindowEvent>>,
|
event_queue: RefCell<Vec<WindowEvent>>,
|
||||||
mouse_pos: Cell<TypedPoint2D<i32, DevicePixel>>,
|
mouse_pos: Cell<TypedPoint2D<i32, DevicePixel>>,
|
||||||
key_modifiers: Cell<GlutinKeyModifiers>,
|
key_modifiers: Cell<WinitKeyModifiers>,
|
||||||
last_pressed_key: Cell<Option<Key>>,
|
last_pressed_key: Cell<Option<Key>>,
|
||||||
animation_state: Cell<AnimationState>,
|
animation_state: Cell<AnimationState>,
|
||||||
fullscreen: Cell<bool>,
|
fullscreen: Cell<bool>,
|
||||||
|
@ -203,7 +203,7 @@ impl Window {
|
||||||
|
|
||||||
window_builder = builder_with_platform_options(window_builder);
|
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_gl(Window::gl_version())
|
||||||
.with_vsync(opts::get().enable_vsync);
|
.with_vsync(opts::get().enable_vsync);
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ impl Window {
|
||||||
context_builder = context_builder.with_multisampling(MULTISAMPLES)
|
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.");
|
.expect("Failed to create window.");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -270,7 +270,7 @@ impl Window {
|
||||||
mouse_down_point: Cell::new(TypedPoint2D::new(0, 0)),
|
mouse_down_point: Cell::new(TypedPoint2D::new(0, 0)),
|
||||||
|
|
||||||
mouse_pos: 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),
|
last_pressed_key: Cell::new(None),
|
||||||
gl: gl.clone(),
|
gl: gl.clone(),
|
||||||
|
@ -347,13 +347,13 @@ impl Window {
|
||||||
if self.is_animating() {
|
if self.is_animating() {
|
||||||
// We block on compositing (servo_callback ends up calling swap_buffers)
|
// We block on compositing (servo_callback ends up calling swap_buffers)
|
||||||
events_loop.borrow_mut().poll_events(|e| {
|
events_loop.borrow_mut().poll_events(|e| {
|
||||||
self.glutin_event_to_servo_event(e);
|
self.winit_event_to_servo_event(e);
|
||||||
});
|
});
|
||||||
stop = servo_callback();
|
stop = servo_callback();
|
||||||
} else {
|
} 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| {
|
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.event_queue.borrow().is_empty() {
|
||||||
if !self.suspended.get() {
|
if !self.suspended.get() {
|
||||||
stop = servo_callback();
|
stop = servo_callback();
|
||||||
|
@ -398,7 +398,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_received_character(&self, ch: char) {
|
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) {
|
if keyutils::is_identifier_ignorable(&ch) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -425,14 +425,14 @@ impl Window {
|
||||||
|
|
||||||
fn toggle_keyboard_modifiers(&self, virtual_key_code: VirtualKeyCode) {
|
fn toggle_keyboard_modifiers(&self, virtual_key_code: VirtualKeyCode) {
|
||||||
match virtual_key_code {
|
match virtual_key_code {
|
||||||
VirtualKeyCode::LControl => self.toggle_modifier(GlutinKeyModifiers::LEFT_CONTROL),
|
VirtualKeyCode::LControl => self.toggle_modifier(WinitKeyModifiers::LEFT_CONTROL),
|
||||||
VirtualKeyCode::RControl => self.toggle_modifier(GlutinKeyModifiers::RIGHT_CONTROL),
|
VirtualKeyCode::RControl => self.toggle_modifier(WinitKeyModifiers::RIGHT_CONTROL),
|
||||||
VirtualKeyCode::LShift => self.toggle_modifier(GlutinKeyModifiers::LEFT_SHIFT),
|
VirtualKeyCode::LShift => self.toggle_modifier(WinitKeyModifiers::LEFT_SHIFT),
|
||||||
VirtualKeyCode::RShift => self.toggle_modifier(GlutinKeyModifiers::RIGHT_SHIFT),
|
VirtualKeyCode::RShift => self.toggle_modifier(WinitKeyModifiers::RIGHT_SHIFT),
|
||||||
VirtualKeyCode::LAlt => self.toggle_modifier(GlutinKeyModifiers::LEFT_ALT),
|
VirtualKeyCode::LAlt => self.toggle_modifier(WinitKeyModifiers::LEFT_ALT),
|
||||||
VirtualKeyCode::RAlt => self.toggle_modifier(GlutinKeyModifiers::RIGHT_ALT),
|
VirtualKeyCode::RAlt => self.toggle_modifier(WinitKeyModifiers::RIGHT_ALT),
|
||||||
VirtualKeyCode::LWin => self.toggle_modifier(GlutinKeyModifiers::LEFT_SUPER),
|
VirtualKeyCode::LWin => self.toggle_modifier(WinitKeyModifiers::LEFT_SUPER),
|
||||||
VirtualKeyCode::RWin => self.toggle_modifier(GlutinKeyModifiers::RIGHT_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) {
|
fn handle_keyboard_input(&self, element_state: ElementState, virtual_key_code: VirtualKeyCode) {
|
||||||
self.toggle_keyboard_modifiers(virtual_key_code);
|
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 {
|
let state = match element_state {
|
||||||
ElementState::Pressed => KeyState::Pressed,
|
ElementState::Pressed => KeyState::Pressed,
|
||||||
ElementState::Released => KeyState::Released,
|
ElementState::Released => KeyState::Released,
|
||||||
|
@ -450,12 +450,12 @@ impl Window {
|
||||||
self.last_pressed_key.set(Some(key));
|
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));
|
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 {
|
match event {
|
||||||
Event::WindowEvent {
|
Event::WindowEvent {
|
||||||
event: winit::WindowEvent::ReceivedCharacter(ch),
|
event: winit::WindowEvent::ReceivedCharacter(ch),
|
||||||
|
@ -505,7 +505,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
let scroll_location = ScrollLocation::Delta(TypedVector2D::new(dx, dy));
|
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);
|
let event = WindowEvent::Scroll(scroll_location, self.mouse_pos.get(), phase);
|
||||||
self.event_queue.borrow_mut().push(event);
|
self.event_queue.borrow_mut().push(event);
|
||||||
},
|
},
|
||||||
|
@ -515,7 +515,7 @@ impl Window {
|
||||||
} => {
|
} => {
|
||||||
use servo::script_traits::TouchId;
|
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 id = TouchId(touch.id as i32);
|
||||||
let point = TypedPoint2D::new(touch.location.0 as f32, touch.location.1 as f32);
|
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));
|
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();
|
let mut modifiers = self.key_modifiers.get();
|
||||||
modifiers.toggle(modifier);
|
modifiers.toggle(modifier);
|
||||||
self.key_modifiers.set(modifiers);
|
self.key_modifiers.set(modifiers);
|
||||||
|
@ -636,7 +636,7 @@ impl Window {
|
||||||
WindowKind::Window(ref window, ..) => {
|
WindowKind::Window(ref window, ..) => {
|
||||||
use winit::MouseCursor;
|
use winit::MouseCursor;
|
||||||
|
|
||||||
let glutin_cursor = match cursor {
|
let winit_cursor = match cursor {
|
||||||
CursorKind::Auto => MouseCursor::Default,
|
CursorKind::Auto => MouseCursor::Default,
|
||||||
CursorKind::None => MouseCursor::NoneCursor,
|
CursorKind::None => MouseCursor::NoneCursor,
|
||||||
CursorKind::Default => MouseCursor::Default,
|
CursorKind::Default => MouseCursor::Default,
|
||||||
|
@ -674,7 +674,7 @@ impl Window {
|
||||||
CursorKind::ZoomIn => MouseCursor::ZoomIn,
|
CursorKind::ZoomIn => MouseCursor::ZoomIn,
|
||||||
CursorKind::ZoomOut => MouseCursor::ZoomOut,
|
CursorKind::ZoomOut => MouseCursor::ZoomOut,
|
||||||
};
|
};
|
||||||
window.set_cursor(glutin_cursor);
|
window.set_cursor(winit_cursor);
|
||||||
}
|
}
|
||||||
WindowKind::Headless(..) => {}
|
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 {
|
match phase {
|
||||||
TouchPhase::Started => TouchEventType::Down,
|
TouchPhase::Started => TouchEventType::Down,
|
||||||
TouchPhase::Moved => TouchEventType::Move,
|
TouchPhase::Moved => TouchEventType::Move,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue