From 191cd5724569767a8d9352b3ba5a87a4055a1f05 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Sun, 12 Feb 2017 14:35:33 -0500 Subject: [PATCH 01/21] Buildable for emscripten --- Cargo.toml | 2 + src/api/emscripten/mod.rs | 48 +++- src/events.rs | 4 + src/lib.rs | 7 + src/platform/emscripten/event.rs | 1 + src/platform/emscripten/mod.rs | 2 + src/platform/emscripten/window.rs | 1 + src/platform/emscripten/winit.rs | 438 ++++++++++++++++++++++++++++++ src/window.rs | 7 + 9 files changed, 506 insertions(+), 4 deletions(-) create mode 100644 src/platform/emscripten/event.rs create mode 100644 src/platform/emscripten/window.rs create mode 100644 src/platform/emscripten/winit.rs diff --git a/Cargo.toml b/Cargo.toml index 7fc4166610..b6a31a8eba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,8 @@ build = "build.rs" lazy_static = "0.2.0" libc = "0.2" shared_library = "0.1.0" + +[target.'cfg(not(target_os = "emscripten"))'.dependencies] winit = "0.5.10" [build-dependencies] diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 59c894646c..f3578e81ae 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -14,6 +14,8 @@ use PixelFormat; use PixelFormatRequirements; use WindowAttributes; +use ::platform::winit; + use std::collections::VecDeque; use platform::PlatformSpecificWindowBuilderAttributes; @@ -21,6 +23,7 @@ mod ffi; pub struct Window { context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, + winit_window: winit::Window, } pub struct PollEventsIterator<'a> { @@ -32,6 +35,7 @@ impl<'a> Iterator for PollEventsIterator<'a> { #[inline] fn next(&mut self) -> Option { + // TODO None } } @@ -45,6 +49,7 @@ impl<'a> Iterator for WaitEventsIterator<'a> { #[inline] fn next(&mut self) -> Option { + // TODO None } } @@ -62,6 +67,8 @@ impl WindowProxy { #[derive(Clone)] pub struct MonitorId; +pub type AvailableMonitorsIter = VecDeque; + #[inline] pub fn get_available_monitors() -> VecDeque { let mut list = VecDeque::new(); @@ -92,9 +99,12 @@ impl MonitorId { } impl Window { - pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements, - opengl: &GlAttributes<&Window>, _: &PlatformSpecificWindowBuilderAttributes) -> Result - { + pub fn new(_: &WindowAttributes, + pf_reqs: &PixelFormatRequirements, + opengl: &GlAttributes<&Window>, + _: &PlatformSpecificWindowBuilderAttributes, + winit_builder: winit::WindowBuilder) + -> Result { // getting the default values of attributes let mut attributes = unsafe { use std::mem; @@ -126,8 +136,10 @@ impl Window { // TODO: emscripten_set_webglcontextrestored_callback + let winit_window = try!(winit_builder.build()); Ok(Window { - context: context + context: context, + winit_window: winit_window }) } @@ -210,6 +222,7 @@ impl Window { #[inline] pub fn set_window_resize_callback(&mut self, _: Option) { + // TODO } #[inline] @@ -230,6 +243,31 @@ impl Window { pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { Ok(()) } + + #[inline] + pub fn get_inner_size_points(&self) -> Option<(u32, u32)> { + unimplemented!(); + } + + #[inline] + pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> { + unimplemented!(); + } + + #[inline] + pub fn as_winit_window(&self) -> &winit::Window { + &self.winit_window + } + + #[inline] + pub fn as_winit_window_mut(&mut self) -> &mut winit::Window { + &mut self.winit_window + } + + #[inline] + pub fn hdpi_factor(&self) -> f32 { + unimplemented!(); + } } impl GlContext for Window { @@ -295,3 +333,5 @@ fn error_to_str(code: ffi::EMSCRIPTEN_RESULT) -> &'static str { _ => "Undocumented error" } } + + diff --git a/src/events.rs b/src/events.rs index fc933be34e..1ef0131985 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1 +1,5 @@ +#[cfg(not(target_os = "emscripten"))] pub use winit::{Event, TouchPhase, Touch, ScanCode, ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode}; + +#[cfg(target_os = "emscripten")] +pub use super::platform::winit::{Event, TouchPhase, Touch, ScanCode, ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode}; diff --git a/src/lib.rs b/src/lib.rs index b0340ba168..91681f258b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,12 @@ extern crate shared_library; extern crate libc; +#[cfg(not(target_os = "emscripten"))] extern crate winit; +#[cfg(target_os = "emscripten")] +mod winit { + pub use platform::winit::*; +} #[cfg(target_os = "windows")] extern crate winapi; @@ -67,6 +72,8 @@ pub use headless::{HeadlessRendererBuilder, HeadlessContext}; pub use window::{WindowProxy, PollEventsIterator, WaitEventsIterator}; pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor}; pub use winit::NativeMonitorId; +#[cfg(target_os = "emscripten")] +pub use winit::native_monitor; use std::io; diff --git a/src/platform/emscripten/event.rs b/src/platform/emscripten/event.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/platform/emscripten/event.rs @@ -0,0 +1 @@ + diff --git a/src/platform/emscripten/mod.rs b/src/platform/emscripten/mod.rs index a1b95cb0f1..e21ea374a3 100644 --- a/src/platform/emscripten/mod.rs +++ b/src/platform/emscripten/mod.rs @@ -1,5 +1,7 @@ #![cfg(target_os = "emscripten")] +pub mod winit; + use Api; use ContextError; use CreationError; diff --git a/src/platform/emscripten/window.rs b/src/platform/emscripten/window.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/platform/emscripten/window.rs @@ -0,0 +1 @@ + diff --git a/src/platform/emscripten/winit.rs b/src/platform/emscripten/winit.rs new file mode 100644 index 0000000000..515d45d34b --- /dev/null +++ b/src/platform/emscripten/winit.rs @@ -0,0 +1,438 @@ +use std::collections::VecDeque; +use std::path::PathBuf; + +use CreationError; + +pub use api::emscripten::{WindowProxy, MonitorId, get_available_monitors, AvailableMonitorsIter}; +pub use api::emscripten::{get_primary_monitor, WaitEventsIterator, PollEventsIterator}; + +pub use native_monitor::NativeMonitorId; + +#[derive(Clone, Debug)] +pub enum Event { + Resized(u32, u32), + Moved(i32, i32), + Closed, + DroppedFile(PathBuf), + ReceivedCharacter(char), + Focused(bool), + KeyboardInput(ElementState, ScanCode, Option), + MouseMoved(i32, i32), + MouseEntered, + MouseLeft, + MouseWheel(MouseScrollDelta, TouchPhase), + MouseInput(ElementState, MouseButton), + TouchpadPressure(f32, i64), + Awakened, + Refresh, + Suspended(bool), + Touch(Touch), +} + +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub enum TouchPhase { + Started, + Moved, + Ended, + Cancelled, +} + +#[derive(Debug, Clone, Copy)] +pub struct Touch { + pub phase: TouchPhase, + pub location: (f64, f64), + pub id: u64, +} + +pub type ScanCode = u8; + +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub enum ElementState { + Pressed, + Released, +} + +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub enum MouseButton { + Left, + Right, + Middle, + Other(u8) +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum MouseScrollDelta { + LineDelta(f32, f32), + PixelDelta(f32, f32), +} + +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub enum VirtualKeyCode { + Key1, + Key2, + Key3, + Key4, + Key5, + Key6, + Key7, + Key8, + Key9, + Key0, + A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + Escape, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + Snapshot, + Scroll, + Pause, + Insert, + Home, + Delete, + End, + PageDown, + PageUp, + Left, + Up, + Right, + Down, + Back, + Return, + Space, + Compose, + Numlock, + Numpad0, + Numpad1, + Numpad2, + Numpad3, + Numpad4, + Numpad5, + Numpad6, + Numpad7, + Numpad8, + Numpad9, + AbntC1, + AbntC2, + Add, + Apostrophe, + Apps, + At, + Ax, + Backslash, + Calculator, + Capital, + Colon, + Comma, + Convert, + Decimal, + Divide, + Equals, + Grave, + Kana, + Kanji, + LAlt, + LBracket, + LControl, + LMenu, + LShift, + LWin, + Mail, + MediaSelect, + MediaStop, + Minus, + Multiply, + Mute, + MyComputer, + NavigateForward, + NavigateBackward, + NextTrack, + NoConvert, + NumpadComma, + NumpadEnter, + NumpadEquals, + OEM102, + Period, + PlayPause, + Power, + PrevTrack, + RAlt, + RBracket, + RControl, + RMenu, + RShift, + RWin, + Semicolon, + Slash, + Sleep, + Stop, + Subtract, + Sysrq, + Tab, + Underline, + Unlabeled, + VolumeDown, + VolumeUp, + Wake, + WebBack, + WebFavorites, + WebForward, + WebHome, + WebRefresh, + WebSearch, + WebStop, + Yen, +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum CursorState { + Normal, + Hide, + Grab, +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum MouseCursor { + Default, + Crosshair, + Hand, + Arrow, + Move, + Text, + Wait, + Help, + Progress, + NotAllowed, + ContextMenu, + NoneCursor, + Cell, + VerticalText, + Alias, + Copy, + NoDrop, + Grab, + Grabbing, + AllScroll, + ZoomIn, + ZoomOut, + EResize, + NResize, + NeResize, + NwResize, + SResize, + SeResize, + SwResize, + WResize, + EwResize, + NsResize, + NeswResize, + NwseResize, + ColResize, + RowResize, +} + + +#[derive(Clone)] +pub struct WindowBuilder { + pub window: WindowAttributes +} + +impl WindowBuilder { + /// Initializes a new `WindowBuilder` with default values. + #[inline] + pub fn new() -> WindowBuilder { + WindowBuilder { + window: WindowAttributes::default() + } + } + + /// Requests the window to be of specific dimensions. + /// + /// Width and height are in pixels. + #[inline] + pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder { + self.window.dimensions = Some((width, height)); + self + } + + /// Sets a minimum dimension size for the window + /// + /// Width and height are in pixels. + #[inline] + pub fn with_min_dimensions(mut self, width: u32, height: u32) -> WindowBuilder { + self.window.min_dimensions = Some((width, height)); + self + } + + /// Sets a maximum dimension size for the window + /// + /// Width and height are in pixels. + #[inline] + pub fn with_max_dimensions(mut self, width: u32, height: u32) -> WindowBuilder { + self.window.max_dimensions = Some((width, height)); + self + } + + /// Requests a specific title for the window. + #[inline] + pub fn with_title>(mut self, title: T) -> WindowBuilder { + self.window.title = title.into(); + self + } + + /// Requests fullscreen mode. + /// + /// If you don't specify dimensions for the window, it will match the monitor's. + #[inline] + pub fn with_fullscreen(mut self, monitor: MonitorId) -> WindowBuilder { + self.window.monitor = Some(monitor); + self + } + + /// Sets whether the window will be initially hidden or visible. + #[inline] + pub fn with_visibility(mut self, visible: bool) -> WindowBuilder { + self.window.visible = visible; + self + } + + /// Sets whether the background of the window should be transparent. + #[inline] + pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder { + self.window.transparent = transparent; + self + } + + /// Sets whether the window should have a border, a title bar, etc. + #[inline] + pub fn with_decorations(mut self, decorations: bool) -> WindowBuilder { + self.window.decorations = decorations; + self + } + + /// Enables multitouch + #[inline] + pub fn with_multitouch(mut self) -> WindowBuilder { + self.window.multitouch = true; + self + } + + /// Builds the window. + /// + /// Error should be very rare and only occur in case of permission denied, incompatible system, + /// out of memory, etc. + pub fn build(mut self) -> Result { + // resizing the window to the dimensions of the monitor when fullscreen + if self.window.dimensions.is_none() && self.window.monitor.is_some() { + self.window.dimensions = Some(self.window.monitor.as_ref().unwrap().get_dimensions()) + } + + // default dimensions + if self.window.dimensions.is_none() { + self.window.dimensions = Some((1024, 768)); + } + + // building + Ok(Window::new()) + } + + /// Builds the window. + /// + /// The context is build in a *strict* way. That means that if the backend couldn't give + /// you what you requested, an `Err` will be returned. + #[inline] + pub fn build_strict(self) -> Result { + self.build() + } +} + +pub struct Window; + +impl Window { + pub fn new() -> Window { + Window + } +} + + +// Copied from winit +pub mod native_monitor { + /// Native platform identifier for a monitor. Different platforms use fundamentally different types + /// to represent a monitor ID. + #[derive(Clone, PartialEq, Eq)] + pub enum NativeMonitorId { + /// Cocoa and X11 use a numeric identifier to represent a monitor. + Numeric(u32), + + /// Win32 uses a Unicode string to represent a monitor. + Name(String), + + /// Other platforms (Android) don't support monitor identification. + Unavailable + } +} + +#[derive(Clone)] +pub struct WindowAttributes { + pub dimensions: Option<(u32, u32)>, + pub min_dimensions: Option<(u32, u32)>, + pub max_dimensions: Option<(u32, u32)>, + pub monitor: Option, + pub title: String, + pub visible: bool, + pub transparent: bool, + pub decorations: bool, + pub multitouch: bool, +} + +impl Default for WindowAttributes { + fn default() -> WindowAttributes { + WindowAttributes { + dimensions: None, + min_dimensions: None, + max_dimensions: None, + monitor: None, + title: "glutin window".to_owned(), + visible: true, + transparent: false, + decorations: true, + multitouch: false, + } + } +} diff --git a/src/window.rs b/src/window.rs index 990fb001e3..05ca5d72f8 100644 --- a/src/window.rs +++ b/src/window.rs @@ -11,6 +11,9 @@ use Robustness; use Window; use WindowBuilder; +#[cfg(target_os = "emscripten")] +use platform::winit; + pub use winit::WindowProxy; pub use winit::AvailableMonitorsIter; pub use winit::{get_primary_monitor, get_available_monitors}; @@ -19,6 +22,7 @@ pub use winit::MonitorId; use libc; use platform; +#[cfg(not(target_os = "emscripten"))] use winit; use Event; @@ -239,6 +243,9 @@ impl<'a> WindowBuilder<'a> { } } +// #[cfg(target_os = "emscripten")] +// pub use platform::window::WindowBuilder; + /// An iterator for the `wait_events` function. pub struct WaitEventsIterator<'a>(platform::WaitEventsIterator<'a>); From d9dac49174352d708b36eb23bc0fb219744c158c Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Sun, 12 Feb 2017 14:50:54 -0500 Subject: [PATCH 02/21] Minor cleanup --- src/platform/emscripten/event.rs | 1 - src/platform/emscripten/window.rs | 1 - src/platform/emscripten/winit.rs | 8 ++++---- 3 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 src/platform/emscripten/event.rs delete mode 100644 src/platform/emscripten/window.rs diff --git a/src/platform/emscripten/event.rs b/src/platform/emscripten/event.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/src/platform/emscripten/event.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/platform/emscripten/window.rs b/src/platform/emscripten/window.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/src/platform/emscripten/window.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/platform/emscripten/winit.rs b/src/platform/emscripten/winit.rs index 515d45d34b..91ee1f3079 100644 --- a/src/platform/emscripten/winit.rs +++ b/src/platform/emscripten/winit.rs @@ -1,4 +1,3 @@ -use std::collections::VecDeque; use std::path::PathBuf; use CreationError; @@ -369,7 +368,7 @@ impl WindowBuilder { } // building - Ok(Window::new()) + Window::new(self) } /// Builds the window. @@ -385,8 +384,9 @@ impl WindowBuilder { pub struct Window; impl Window { - pub fn new() -> Window { - Window + pub fn new(_: WindowBuilder) -> Result { + // TODO: maybe resize the window to builder dimensions + Ok(Window) } } From 3af812b2fb8e47486d57fb0a838176b51fe8f0d5 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Mon, 13 Feb 2017 10:36:57 -0500 Subject: [PATCH 03/21] Remove duplication of winit from emscripten platform --- Cargo.toml | 2 +- src/api/emscripten/mod.rs | 53 +--- src/events.rs | 4 - src/lib.rs | 7 - src/platform/emscripten/mod.rs | 6 +- src/platform/emscripten/winit.rs | 438 ------------------------------- src/window.rs | 7 - 7 files changed, 9 insertions(+), 508 deletions(-) delete mode 100644 src/platform/emscripten/winit.rs diff --git a/Cargo.toml b/Cargo.toml index b6a31a8eba..13bc556cbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ lazy_static = "0.2.0" libc = "0.2" shared_library = "0.1.0" -[target.'cfg(not(target_os = "emscripten"))'.dependencies] winit = "0.5.10" [build-dependencies] @@ -46,3 +45,4 @@ dwmapi-sys = "0.1" osmesa-sys = "0.1.0" wayland-client = { version = "0.7.4", features = ["egl", "dlopen"] } x11-dl = "2.4" + diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index f3578e81ae..820a7ac180 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -14,7 +14,9 @@ use PixelFormat; use PixelFormatRequirements; use WindowAttributes; -use ::platform::winit; +use winit; +pub use winit::WindowProxy; + use std::collections::VecDeque; use platform::PlatformSpecificWindowBuilderAttributes; @@ -54,50 +56,6 @@ impl<'a> Iterator for WaitEventsIterator<'a> { } } -#[derive(Clone)] -pub struct WindowProxy; - -impl WindowProxy { - #[inline] - pub fn wakeup_event_loop(&self) { - unimplemented!() - } -} - -#[derive(Clone)] -pub struct MonitorId; - -pub type AvailableMonitorsIter = VecDeque; - -#[inline] -pub fn get_available_monitors() -> VecDeque { - let mut list = VecDeque::new(); - list.push_back(MonitorId); - list -} - -#[inline] -pub fn get_primary_monitor() -> MonitorId { - MonitorId -} - -impl MonitorId { - #[inline] - pub fn get_name(&self) -> Option { - Some("Canvas".to_owned()) - } - - #[inline] - pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId { - ::native_monitor::NativeMonitorId::Unavailable - } - - #[inline] - pub fn get_dimensions(&self) -> (u32, u32) { - unimplemented!() - } -} - impl Window { pub fn new(_: &WindowAttributes, pf_reqs: &PixelFormatRequirements, @@ -105,6 +63,8 @@ impl Window { _: &PlatformSpecificWindowBuilderAttributes, winit_builder: winit::WindowBuilder) -> Result { + + let winit_window = winit_builder.build().unwrap(); // getting the default values of attributes let mut attributes = unsafe { use std::mem; @@ -136,7 +96,6 @@ impl Window { // TODO: emscripten_set_webglcontextrestored_callback - let winit_window = try!(winit_builder.build()); Ok(Window { context: context, winit_window: winit_window @@ -202,7 +161,7 @@ impl Window { #[inline] pub fn create_window_proxy(&self) -> WindowProxy { - WindowProxy + self.winit_window.create_window_proxy() } #[inline] diff --git a/src/events.rs b/src/events.rs index 1ef0131985..fc933be34e 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,5 +1 @@ -#[cfg(not(target_os = "emscripten"))] pub use winit::{Event, TouchPhase, Touch, ScanCode, ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode}; - -#[cfg(target_os = "emscripten")] -pub use super::platform::winit::{Event, TouchPhase, Touch, ScanCode, ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode}; diff --git a/src/lib.rs b/src/lib.rs index 91681f258b..b0340ba168 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,12 +31,7 @@ extern crate shared_library; extern crate libc; -#[cfg(not(target_os = "emscripten"))] extern crate winit; -#[cfg(target_os = "emscripten")] -mod winit { - pub use platform::winit::*; -} #[cfg(target_os = "windows")] extern crate winapi; @@ -72,8 +67,6 @@ pub use headless::{HeadlessRendererBuilder, HeadlessContext}; pub use window::{WindowProxy, PollEventsIterator, WaitEventsIterator}; pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor}; pub use winit::NativeMonitorId; -#[cfg(target_os = "emscripten")] -pub use winit::native_monitor; use std::io; diff --git a/src/platform/emscripten/mod.rs b/src/platform/emscripten/mod.rs index e21ea374a3..2df072613f 100644 --- a/src/platform/emscripten/mod.rs +++ b/src/platform/emscripten/mod.rs @@ -1,7 +1,5 @@ #![cfg(target_os = "emscripten")] -pub mod winit; - use Api; use ContextError; use CreationError; @@ -10,8 +8,8 @@ use GlContext; use PixelFormat; use PixelFormatRequirements; -pub use api::emscripten::{Window, WindowProxy, MonitorId, get_available_monitors}; -pub use api::emscripten::{get_primary_monitor, WaitEventsIterator, PollEventsIterator}; +pub use api::emscripten::{Window, WindowProxy}; +pub use api::emscripten::{WaitEventsIterator, PollEventsIterator}; pub struct HeadlessContext(Window); diff --git a/src/platform/emscripten/winit.rs b/src/platform/emscripten/winit.rs deleted file mode 100644 index 91ee1f3079..0000000000 --- a/src/platform/emscripten/winit.rs +++ /dev/null @@ -1,438 +0,0 @@ -use std::path::PathBuf; - -use CreationError; - -pub use api::emscripten::{WindowProxy, MonitorId, get_available_monitors, AvailableMonitorsIter}; -pub use api::emscripten::{get_primary_monitor, WaitEventsIterator, PollEventsIterator}; - -pub use native_monitor::NativeMonitorId; - -#[derive(Clone, Debug)] -pub enum Event { - Resized(u32, u32), - Moved(i32, i32), - Closed, - DroppedFile(PathBuf), - ReceivedCharacter(char), - Focused(bool), - KeyboardInput(ElementState, ScanCode, Option), - MouseMoved(i32, i32), - MouseEntered, - MouseLeft, - MouseWheel(MouseScrollDelta, TouchPhase), - MouseInput(ElementState, MouseButton), - TouchpadPressure(f32, i64), - Awakened, - Refresh, - Suspended(bool), - Touch(Touch), -} - -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -pub enum TouchPhase { - Started, - Moved, - Ended, - Cancelled, -} - -#[derive(Debug, Clone, Copy)] -pub struct Touch { - pub phase: TouchPhase, - pub location: (f64, f64), - pub id: u64, -} - -pub type ScanCode = u8; - -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -pub enum ElementState { - Pressed, - Released, -} - -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -pub enum MouseButton { - Left, - Right, - Middle, - Other(u8) -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum MouseScrollDelta { - LineDelta(f32, f32), - PixelDelta(f32, f32), -} - -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -pub enum VirtualKeyCode { - Key1, - Key2, - Key3, - Key4, - Key5, - Key6, - Key7, - Key8, - Key9, - Key0, - A, - B, - C, - D, - E, - F, - G, - H, - I, - J, - K, - L, - M, - N, - O, - P, - Q, - R, - S, - T, - U, - V, - W, - X, - Y, - Z, - Escape, - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - F13, - F14, - F15, - Snapshot, - Scroll, - Pause, - Insert, - Home, - Delete, - End, - PageDown, - PageUp, - Left, - Up, - Right, - Down, - Back, - Return, - Space, - Compose, - Numlock, - Numpad0, - Numpad1, - Numpad2, - Numpad3, - Numpad4, - Numpad5, - Numpad6, - Numpad7, - Numpad8, - Numpad9, - AbntC1, - AbntC2, - Add, - Apostrophe, - Apps, - At, - Ax, - Backslash, - Calculator, - Capital, - Colon, - Comma, - Convert, - Decimal, - Divide, - Equals, - Grave, - Kana, - Kanji, - LAlt, - LBracket, - LControl, - LMenu, - LShift, - LWin, - Mail, - MediaSelect, - MediaStop, - Minus, - Multiply, - Mute, - MyComputer, - NavigateForward, - NavigateBackward, - NextTrack, - NoConvert, - NumpadComma, - NumpadEnter, - NumpadEquals, - OEM102, - Period, - PlayPause, - Power, - PrevTrack, - RAlt, - RBracket, - RControl, - RMenu, - RShift, - RWin, - Semicolon, - Slash, - Sleep, - Stop, - Subtract, - Sysrq, - Tab, - Underline, - Unlabeled, - VolumeDown, - VolumeUp, - Wake, - WebBack, - WebFavorites, - WebForward, - WebHome, - WebRefresh, - WebSearch, - WebStop, - Yen, -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum CursorState { - Normal, - Hide, - Grab, -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum MouseCursor { - Default, - Crosshair, - Hand, - Arrow, - Move, - Text, - Wait, - Help, - Progress, - NotAllowed, - ContextMenu, - NoneCursor, - Cell, - VerticalText, - Alias, - Copy, - NoDrop, - Grab, - Grabbing, - AllScroll, - ZoomIn, - ZoomOut, - EResize, - NResize, - NeResize, - NwResize, - SResize, - SeResize, - SwResize, - WResize, - EwResize, - NsResize, - NeswResize, - NwseResize, - ColResize, - RowResize, -} - - -#[derive(Clone)] -pub struct WindowBuilder { - pub window: WindowAttributes -} - -impl WindowBuilder { - /// Initializes a new `WindowBuilder` with default values. - #[inline] - pub fn new() -> WindowBuilder { - WindowBuilder { - window: WindowAttributes::default() - } - } - - /// Requests the window to be of specific dimensions. - /// - /// Width and height are in pixels. - #[inline] - pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder { - self.window.dimensions = Some((width, height)); - self - } - - /// Sets a minimum dimension size for the window - /// - /// Width and height are in pixels. - #[inline] - pub fn with_min_dimensions(mut self, width: u32, height: u32) -> WindowBuilder { - self.window.min_dimensions = Some((width, height)); - self - } - - /// Sets a maximum dimension size for the window - /// - /// Width and height are in pixels. - #[inline] - pub fn with_max_dimensions(mut self, width: u32, height: u32) -> WindowBuilder { - self.window.max_dimensions = Some((width, height)); - self - } - - /// Requests a specific title for the window. - #[inline] - pub fn with_title>(mut self, title: T) -> WindowBuilder { - self.window.title = title.into(); - self - } - - /// Requests fullscreen mode. - /// - /// If you don't specify dimensions for the window, it will match the monitor's. - #[inline] - pub fn with_fullscreen(mut self, monitor: MonitorId) -> WindowBuilder { - self.window.monitor = Some(monitor); - self - } - - /// Sets whether the window will be initially hidden or visible. - #[inline] - pub fn with_visibility(mut self, visible: bool) -> WindowBuilder { - self.window.visible = visible; - self - } - - /// Sets whether the background of the window should be transparent. - #[inline] - pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder { - self.window.transparent = transparent; - self - } - - /// Sets whether the window should have a border, a title bar, etc. - #[inline] - pub fn with_decorations(mut self, decorations: bool) -> WindowBuilder { - self.window.decorations = decorations; - self - } - - /// Enables multitouch - #[inline] - pub fn with_multitouch(mut self) -> WindowBuilder { - self.window.multitouch = true; - self - } - - /// Builds the window. - /// - /// Error should be very rare and only occur in case of permission denied, incompatible system, - /// out of memory, etc. - pub fn build(mut self) -> Result { - // resizing the window to the dimensions of the monitor when fullscreen - if self.window.dimensions.is_none() && self.window.monitor.is_some() { - self.window.dimensions = Some(self.window.monitor.as_ref().unwrap().get_dimensions()) - } - - // default dimensions - if self.window.dimensions.is_none() { - self.window.dimensions = Some((1024, 768)); - } - - // building - Window::new(self) - } - - /// Builds the window. - /// - /// The context is build in a *strict* way. That means that if the backend couldn't give - /// you what you requested, an `Err` will be returned. - #[inline] - pub fn build_strict(self) -> Result { - self.build() - } -} - -pub struct Window; - -impl Window { - pub fn new(_: WindowBuilder) -> Result { - // TODO: maybe resize the window to builder dimensions - Ok(Window) - } -} - - -// Copied from winit -pub mod native_monitor { - /// Native platform identifier for a monitor. Different platforms use fundamentally different types - /// to represent a monitor ID. - #[derive(Clone, PartialEq, Eq)] - pub enum NativeMonitorId { - /// Cocoa and X11 use a numeric identifier to represent a monitor. - Numeric(u32), - - /// Win32 uses a Unicode string to represent a monitor. - Name(String), - - /// Other platforms (Android) don't support monitor identification. - Unavailable - } -} - -#[derive(Clone)] -pub struct WindowAttributes { - pub dimensions: Option<(u32, u32)>, - pub min_dimensions: Option<(u32, u32)>, - pub max_dimensions: Option<(u32, u32)>, - pub monitor: Option, - pub title: String, - pub visible: bool, - pub transparent: bool, - pub decorations: bool, - pub multitouch: bool, -} - -impl Default for WindowAttributes { - fn default() -> WindowAttributes { - WindowAttributes { - dimensions: None, - min_dimensions: None, - max_dimensions: None, - monitor: None, - title: "glutin window".to_owned(), - visible: true, - transparent: false, - decorations: true, - multitouch: false, - } - } -} diff --git a/src/window.rs b/src/window.rs index 05ca5d72f8..990fb001e3 100644 --- a/src/window.rs +++ b/src/window.rs @@ -11,9 +11,6 @@ use Robustness; use Window; use WindowBuilder; -#[cfg(target_os = "emscripten")] -use platform::winit; - pub use winit::WindowProxy; pub use winit::AvailableMonitorsIter; pub use winit::{get_primary_monitor, get_available_monitors}; @@ -22,7 +19,6 @@ pub use winit::MonitorId; use libc; use platform; -#[cfg(not(target_os = "emscripten"))] use winit; use Event; @@ -243,9 +239,6 @@ impl<'a> WindowBuilder<'a> { } } -// #[cfg(target_os = "emscripten")] -// pub use platform::window::WindowBuilder; - /// An iterator for the `wait_events` function. pub struct WaitEventsIterator<'a>(platform::WaitEventsIterator<'a>); From a6c7877000a249eeb1d4d525bcc11eec3e9f1b05 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Mon, 13 Feb 2017 11:38:19 -0500 Subject: [PATCH 04/21] Remove winit_window from emscripten target --- src/api/emscripten/mod.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 820a7ac180..6c7ebabc85 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -25,7 +25,6 @@ mod ffi; pub struct Window { context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, - winit_window: winit::Window, } pub struct PollEventsIterator<'a> { @@ -61,10 +60,9 @@ impl Window { pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&Window>, _: &PlatformSpecificWindowBuilderAttributes, - winit_builder: winit::WindowBuilder) + _: winit::WindowBuilder) -> Result { - let winit_window = winit_builder.build().unwrap(); // getting the default values of attributes let mut attributes = unsafe { use std::mem; @@ -98,7 +96,6 @@ impl Window { Ok(Window { context: context, - winit_window: winit_window }) } @@ -161,7 +158,7 @@ impl Window { #[inline] pub fn create_window_proxy(&self) -> WindowProxy { - self.winit_window.create_window_proxy() + unimplemented!() } #[inline] @@ -205,22 +202,22 @@ impl Window { #[inline] pub fn get_inner_size_points(&self) -> Option<(u32, u32)> { - unimplemented!(); + unimplemented!() } #[inline] pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> { - unimplemented!(); + unimplemented!() } #[inline] pub fn as_winit_window(&self) -> &winit::Window { - &self.winit_window + unimplemented!() } #[inline] pub fn as_winit_window_mut(&mut self) -> &mut winit::Window { - &mut self.winit_window + unimplemented!() } #[inline] From dfa621d7b9ab70e57c4d116134755bb4575c5ffd Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Wed, 15 Feb 2017 00:04:38 -0500 Subject: [PATCH 05/21] Add mouse callbacks --- src/api/emscripten/ffi.rs | 66 ++++++++++++++++++++++++++++++++++ src/api/emscripten/mod.rs | 74 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 138 insertions(+), 2 deletions(-) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index d16a1dd841..d8d97e44e2 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -4,6 +4,9 @@ use libc; +pub const EM_FALSE: EM_BOOL = 0; +pub const EM_TRUE: EM_BOOL = 1; + pub type EM_BOOL = libc::c_int; pub type EM_UTF8 = libc::c_char; pub type EMSCRIPTEN_WEBGL_CONTEXT_HANDLE = libc::c_int; @@ -14,6 +17,59 @@ pub type em_webgl_context_callback = extern fn(libc::c_int, *const libc::c_void, pub type em_callback_func = unsafe extern fn(); +pub const EMSCRIPTEN_EVENT_KEYDOWN: libc::c_int = 2; + +// pub const EMSCRIPTEN_EVENT_CLICK: libc::c_int = 4; +pub const EMSCRIPTEN_EVENT_MOUSEDOWN: libc::c_int = 5; +pub const EMSCRIPTEN_EVENT_MOUSEUP: libc::c_int = 6; +pub const EMSCRIPTEN_EVENT_MOUSEMOVE: libc::c_int = 8; + +pub const EM_HTML5_SHORT_STRING_LEN_BYTES: usize = 32; + +#[repr(C)] +pub struct EmscriptenMouseEvent { + pub timestamp: libc::c_double, + pub screen_x: libc::c_long, + pub screen_y: libc::c_long, + pub client_x: libc::c_long, + pub client_y: libc::c_long, + pub ctrl_key: EM_BOOL, + pub shift_key: EM_BOOL, + pub alt_key: EM_BOOL, + pub meta_key: EM_BOOL, + pub button: libc::c_ushort, + pub buttons: libc::c_ushort, + pub movement_x: libc::c_long, + pub movement_y: libc::c_long, + pub target_x: libc::c_long, + pub target_y: libc::c_long, + pub canvas_x: libc::c_long, + pub canvas_y: libc::c_long, + padding: libc::c_long +} + +#[repr(C)] +pub struct EmscriptenKeyboardEvent { + pub key: [EM_UTF8; EM_HTML5_SHORT_STRING_LEN_BYTES], + pub code: [EM_UTF8; EM_HTML5_SHORT_STRING_LEN_BYTES], + pub location: libc::c_ulong, + pub ctrlKey: EM_BOOL, + pub shiftKey: EM_BOOL, + pub altKey: EM_BOOL, + pub metaKey: EM_BOOL, + pub repeat: EM_BOOL, + pub locale: [EM_UTF8; EM_HTML5_SHORT_STRING_LEN_BYTES], + pub charValue: [EM_UTF8; EM_HTML5_SHORT_STRING_LEN_BYTES], + pub charCode: libc::c_ulong, + pub keyCode: libc::c_ulong, + pub which: libc::c_ulong, +} + +pub type em_mouse_callback_func = extern fn(libc::c_int, *const EmscriptenMouseEvent, *mut libc::c_void) + -> EM_BOOL; +pub type em_keyboard_callback_func = extern fn(libc::c_int, *const EmscriptenKeyboardEvent, *mut libc::c_void) + -> EM_BOOL; + #[repr(C)] pub struct EmscriptenWebGLContextAttributes { pub alpha: EM_BOOL, @@ -83,4 +139,14 @@ extern { pub fn emscripten_sleep(delay: libc::c_uint); pub fn emscripten_set_main_loop(func : em_callback_func, fps : libc::c_int, simulate_infinite_loop : libc::c_int); + + + pub fn emscripten_set_mousemove_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_mouse_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_set_mousedown_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_mouse_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_set_mouseup_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_mouse_callback_func) -> EMSCRIPTEN_RESULT; + + + pub fn emscripten_set_keydown_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_keyboard_callback_func) -> EMSCRIPTEN_RESULT; } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 6c7ebabc85..2abaa228da 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -17,14 +17,20 @@ use WindowAttributes; use winit; pub use winit::WindowProxy; +use ElementState; +use MouseButton; +use VirtualKeyCode; +use std::cell::RefCell; use std::collections::VecDeque; +use std::ops::Deref; use platform::PlatformSpecificWindowBuilderAttributes; mod ffi; pub struct Window { context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, + events: Box>>, } pub struct PollEventsIterator<'a> { @@ -36,8 +42,7 @@ impl<'a> Iterator for PollEventsIterator<'a> { #[inline] fn next(&mut self) -> Option { - // TODO - None + self.window.events.deref().borrow_mut().pop_front() } } @@ -55,6 +60,8 @@ impl<'a> Iterator for WaitEventsIterator<'a> { } } +const CANVAS_NAME: &'static str = "#canvas\0"; + impl Window { pub fn new(_: &WindowAttributes, pf_reqs: &PixelFormatRequirements, @@ -92,10 +99,32 @@ impl Window { context }; + let events = Box::new(RefCell::new(VecDeque::new())); + + { + use std::mem; + // TODO: set up more event callbacks + unsafe { + ffi::emscripten_set_mousemove_callback(CANVAS_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + mouse_callback); + ffi::emscripten_set_mousedown_callback(CANVAS_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + mouse_callback); + ffi::emscripten_set_mouseup_callback(CANVAS_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + mouse_callback); + } + } + // TODO: emscripten_set_webglcontextrestored_callback Ok(Window { context: context, + events: events, }) } @@ -291,3 +320,44 @@ fn error_to_str(code: ffi::EMSCRIPTEN_RESULT) -> &'static str { } +extern fn mouse_callback( + event_type: libc::c_int, + event: *const ffi::EmscriptenMouseEvent, + event_queue: *mut libc::c_void) -> ffi::EM_BOOL { + // println!("callback {} {:p} {:p} !", event_type, event, event_queue); + unsafe { + use std::mem; + let queue: &RefCell> = mem::transmute(event_queue); + match event_type { + ffi::EMSCRIPTEN_EVENT_MOUSEMOVE => { + queue.borrow_mut().push_back(Event::MouseMoved( + (*event).client_x as i32, + (*event).client_y as i32)); + }, + ffi::EMSCRIPTEN_EVENT_MOUSEDOWN => { + queue.borrow_mut().push_back(Event::MouseInput( + ElementState::Pressed, + match (*event).button { + 0 => MouseButton::Left, + 1 => MouseButton::Middle, + 2 => MouseButton::Right, + other => MouseButton::Other(other as u8), + })); + }, + ffi::EMSCRIPTEN_EVENT_MOUSEUP => { + queue.borrow_mut().push_back(Event::MouseInput( + ElementState::Released, + match (*event).button { + 0 => MouseButton::Left, + 1 => MouseButton::Middle, + 2 => MouseButton::Right, + other => MouseButton::Other(other as u8), + })); + }, + _ => { + } + } + } + ffi::EM_TRUE +} + From aa471ad831796bf7c905b156aa7abd3199d25979 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Wed, 15 Feb 2017 00:43:30 -0500 Subject: [PATCH 06/21] Add keyboard callbacks --- src/api/emscripten/ffi.rs | 3 +++ src/api/emscripten/mod.rs | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index d8d97e44e2..193ee8081d 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -18,6 +18,7 @@ pub type em_webgl_context_callback = extern fn(libc::c_int, *const libc::c_void, pub type em_callback_func = unsafe extern fn(); pub const EMSCRIPTEN_EVENT_KEYDOWN: libc::c_int = 2; +pub const EMSCRIPTEN_EVENT_KEYUP: libc::c_int = 3; // pub const EMSCRIPTEN_EVENT_CLICK: libc::c_int = 4; pub const EMSCRIPTEN_EVENT_MOUSEDOWN: libc::c_int = 5; @@ -149,4 +150,6 @@ extern { pub fn emscripten_set_keydown_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_keyboard_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_set_keyup_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_keyboard_callback_func) -> EMSCRIPTEN_RESULT; } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 2abaa228da..27ab9eb0c7 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -61,6 +61,7 @@ impl<'a> Iterator for WaitEventsIterator<'a> { } const CANVAS_NAME: &'static str = "#canvas\0"; +const DOCUMENT_NAME: &'static str = "#document\0"; impl Window { pub fn new(_: &WindowAttributes, @@ -117,6 +118,14 @@ impl Window { mem::transmute(events.deref()), ffi::EM_FALSE, mouse_callback); + ffi::emscripten_set_keydown_callback(DOCUMENT_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + keyboard_callback); + ffi::emscripten_set_keyup_callback(DOCUMENT_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + keyboard_callback); } } @@ -361,3 +370,46 @@ extern fn mouse_callback( ffi::EM_TRUE } +extern fn keyboard_callback( + event_type: libc::c_int, + event: *const ffi::EmscriptenKeyboardEvent, + event_queue: *mut libc::c_void) -> ffi::EM_BOOL { + println!("keyevent {}", event_type); + unsafe { + use std::mem; + let queue: &RefCell> = mem::transmute(event_queue); + match event_type { + ffi::EMSCRIPTEN_EVENT_KEYDOWN => { + queue.borrow_mut().push_back(Event::KeyboardInput( + ElementState::Pressed, + key_translate((*event).key), + key_translate_virt((*event).key, (*event).location))); + }, + ffi::EMSCRIPTEN_EVENT_KEYUP => { + queue.borrow_mut().push_back(Event::KeyboardInput( + ElementState::Released, + key_translate((*event).key), + key_translate_virt((*event).key, (*event).location))); + }, + _ => { + } + } + } + ffi::EM_TRUE +} + +fn key_translate(input: [ffi::EM_UTF8; ffi:: EM_HTML5_SHORT_STRING_LEN_BYTES]) -> u8 { + use std::str; + let slice = &input[0..input.iter().take_while(|x| **x != 0).count()]; + let key = str::from_utf8(&slice).unwrap(); + if key.chars().count() == 1 { + key.as_bytes()[0] + } else { + 0 + } +} + +fn key_translate_virt(input: [ffi::EM_UTF8; ffi:: EM_HTML5_SHORT_STRING_LEN_BYTES], location: libc::c_ulong) -> Option { + // TODO + None +} From 600e1a603aa0920cd95cd87c1e9687fbb198ca11 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Wed, 15 Feb 2017 09:31:22 -0500 Subject: [PATCH 07/21] Update key to virtual code mapping --- src/api/emscripten/ffi.rs | 5 + src/api/emscripten/keyboard.rs | 460 +++++++++++++++++++++++++++++++++ src/api/emscripten/mod.rs | 27 +- 3 files changed, 473 insertions(+), 19 deletions(-) create mode 100644 src/api/emscripten/keyboard.rs diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index 193ee8081d..ebde37cae3 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -27,6 +27,11 @@ pub const EMSCRIPTEN_EVENT_MOUSEMOVE: libc::c_int = 8; pub const EM_HTML5_SHORT_STRING_LEN_BYTES: usize = 32; +pub const DOM_KEY_LOCATION_STANDARD: libc::c_ulong = 0x00; +pub const DOM_KEY_LOCATION_LEFT: libc::c_ulong = 0x01; +pub const DOM_KEY_LOCATION_RIGHT: libc::c_ulong = 0x02; +pub const DOM_KEY_LOCATION_NUMPAD: libc::c_ulong = 0x03; + #[repr(C)] pub struct EmscriptenMouseEvent { pub timestamp: libc::c_double, diff --git a/src/api/emscripten/keyboard.rs b/src/api/emscripten/keyboard.rs new file mode 100644 index 0000000000..31e258b102 --- /dev/null +++ b/src/api/emscripten/keyboard.rs @@ -0,0 +1,460 @@ +use libc; + +use VirtualKeyCode; + +use super::ffi; + +pub fn key_translate(input: [ffi::EM_UTF8; ffi:: EM_HTML5_SHORT_STRING_LEN_BYTES]) -> u8 { + use std::str; + let slice = &input[0..input.iter().take_while(|x| **x != 0).count()]; + if slice.len() == 1 { + slice[0] + } else { + 0 + } +} + +pub fn key_translate_virt(input: [ffi::EM_UTF8; ffi:: EM_HTML5_SHORT_STRING_LEN_BYTES], location: libc::c_ulong) -> Option { + use std::str; + let slice = &input[0..input.iter().take_while(|x| **x != 0).count()]; + let key = str::from_utf8(&slice).unwrap(); + use VirtualKeyCode::*; + match key { + "Alt" => match location { + ffi::DOM_KEY_LOCATION_LEFT => Some(LAlt), + ffi::DOM_KEY_LOCATION_RIGHT => Some(RAlt), + _ => None, + }, + "AltGraph" => None, + "CapsLock" => None, + "Control" => match location { + ffi::DOM_KEY_LOCATION_LEFT => Some(LControl), + ffi::DOM_KEY_LOCATION_RIGHT => Some(RControl), + _ => None, + }, + "Fn" => None, + "FnLock" => None, + "Hyper" => None, + "Meta" => None, + "NumLock" => Some(Numlock), + "ScrollLock" => Some(Scroll), + "Shift" => match location { + ffi::DOM_KEY_LOCATION_LEFT => Some(LShift), + ffi::DOM_KEY_LOCATION_RIGHT => Some(RShift), + _ => None, + }, + "Super" => None, + "Symbol" => None, + "SymbolLock" => None, + + "Enter" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(NumpadEnter), + _ => Some(Return), + }, + "Tab" => Some(Tab), + " " => Some(Space), + + "ArrowDown" => Some(Down), + "ArrowLeft" => Some(Left), + "ArrowRight" => Some(Right), + "ArrowUp" => Some(Up), + "End" => None, + "Home" => None, + "PageDown" => None, + "PageUp" => None, + + "Backspace" => Some(Back), + "Clear" => None, + "Copy" => None, + "CrSel" => None, + "Cut" => None, + "Delete" => None, + "EraseEof" => None, + "ExSel" => None, + "Insert" => Some(Insert), + "Paste" => None, + "Redo" => None, + "Undo" => None, + + "Accept" => None, + "Again" => None, + "Attn" => None, + "Cancel" => None, + "ContextMenu" => None, + "Escape" => Some(Escape), + "Execute" => None, + "Find" => None, + "Finish" => None, + "Help" => None, + "Pause" => Some(Pause), + "Play" => None, + "Props" => None, + "Select" => None, + "ZoomIn" => None, + "ZoomOut" => None, + + "BrightnessDown" => None, + "BrightnessUp" => None, + "Eject" => None, + "LogOff" => None, + "Power" => Some(Power), + "PowerOff" => None, + "PrintScreen" => Some(Snapshot), + "Hibernate" => None, + "Standby" => Some(Sleep), + "WakeUp" => Some(Wake), + + "AllCandidates" => None, + "Alphanumeric" => None, + "CodeInput" => None, + "Compose" => Some(Compose), + "Convert" => Some(Convert), + "Dead" => None, + "FinalMode" => None, + "GroupFirst" => None, + "GroupLast" => None, + "GroupNext" => None, + "GroupPrevious" => None, + "ModeChange" => None, + "NextCandidate" => None, + "NonConvert" => None, + "PreviousCandidate" => None, + "Process" => None, + "SingleCandidate" => None, + + "HangulMode" => None, + "HanjaMode" => None, + "JunjaMode" => None, + + "Eisu" => None, + "Hankaku" => None, + "Hiragana" => None, + "HiraganaKatakana" => None, + "KanaMode" => Some(Kana), + "KanjiMode" => Some(Kanji), + "Romaji" => None, + "Zenkaku" => None, + "ZenkakuHanaku" => None, + + "F1" => Some(F1), + "F2" => Some(F2), + "F3" => Some(F3), + "F4" => Some(F4), + "F5" => Some(F5), + "F6" => Some(F6), + "F7" => Some(F7), + "F8" => Some(F8), + "F9" => Some(F9), + "F10" => Some(F10), + "F11" => Some(F11), + "F12" => Some(F12), + "F13" => Some(F13), + "F14" => Some(F14), + "F15" => Some(F15), + "F16" => None, + "F17" => None, + "F18" => None, + "F19" => None, + "F20" => None, + "Soft1" => None, + "Soft2" => None, + "Soft3" => None, + "Soft4" => None, + + "AppSwitch" => None, + "Call" => None, + "Camera" => None, + "CameraFocus" => None, + "EndCall" => None, + "GoBack" => None, + "GoHome" => None, + "HeadsetHook" => None, + "LastNumberRedial" => None, + "Notification" => None, + "MannerMode" => None, + "VoiceDial" => None, + + "ChannelDown" => None, + "ChannelUp" => None, + "MediaFastForward" => None, + "MediaPause" => None, + "MediaPlay" => None, + "MediaPlayPause" => Some(PlayPause), + "MediaRecord" => None, + "MediaRewind" => None, + "MediaStop" => Some(MediaStop), + "MediaTrackNext" => Some(NextTrack), + "MediaTrackPrevious" => Some(PrevTrack), + + "AudioBalanceLeft" => None, + "AudioBalanceRight" => None, + "AudioBassDown" => None, + "AudioBassBoostDown" => None, + "AudioBassBoostToggle" => None, + "AudioBassBoostUp" => None, + "AudioBassUp" => None, + "AudioFaderFront" => None, + "AudioFaderRear" => None, + "AudioSurroundModeNext" => None, + "AudioTrebleDown" => None, + "AudioTrebleUp" => None, + "AudioVolumeDown" => Some(VolumeDown), + "AudioVolumeMute" => Some(Mute), + "AudioVolumeUp" => Some(VolumeUp), + "MicrophoneToggle" => None, + "MicrophoneVolumeDown" => None, + "MicrophoneVolumeMute" => None, + "MicrophoneVolumeUp" => None, + + "TV" => None, + "TV3DMode" => None, + "TVAntennaCable" => None, + "TVAudioDescription" => None, + "TVAudioDescriptionMixDown" => None, + "TVAudioDescriptionMixUp" => None, + "TVContentsMenu" => None, + "TVDataService" => None, + "TVInput" => None, + "TVInputComponent1" => None, + "TVInputComponent2" => None, + "TVInputComposite1" => None, + "TVInputComposite2" => None, + "TVInputHDM1" => None, + "TVInputHDM2" => None, + "TVInputHDM3" => None, + "TVInputHDM4" => None, + "TVInputVGA1" => None, + "TVMediaContext" => None, + "TVNetwork" => None, + "TVNumberEntry" => None, + "TVPower" => None, + "TVRadioService" => None, + "TVSatellite" => None, + "TVSatelliteBS" => None, + "TVSatelliteCS" => None, + "TVSatelliteToggle" => None, + "TVTerrestrialAnalog" => None, + "TVTerrestrialDigital" => None, + "TVTimer" => None, + + "AVRInput" => None, + "AVRPower" => None, + "ColorF0Red" => None, + "ColorF1Green" => None, + "ColorF2Yellow" => None, + "ColorF3Blue" => None, + "ColorF4Grey" => None, + "ColorF5Brown" => None, + "ClosedCaptionToggle" => None, + "Dimmer" => None, + "DisplaySwap" => None, + "DVR" => None, + "Exit" => None, + "FavoriteClear0" => None, + "FavoriteClear1" => None, + "FavoriteClear2" => None, + "FavoriteClear3" => None, + "FavoriteRecall0" => None, + "FavoriteRecall1" => None, + "FavoriteRecall2" => None, + "FavoriteRecall3" => None, + "FavoriteStore0" => None, + "FavoriteStore1" => None, + "FavoriteStore2" => None, + "FavoriteStore3" => None, + "FavoriteStore4" => None, + "Guide" => None, + "GuideNextDay" => None, + "GuidePreviousDay" => None, + "Info" => None, + "InstantReplay" => None, + "Link" => None, + "ListProgram" => None, + "LiveContent" => None, + "Lock" => None, + "MediaApps" => None, + "MediaAudioTrack" => None, + "MediaLast" => None, + "MediaSkipBackward" => None, + "MediaSkipForward" => None, + "MediaStepBackward" => None, + "MediaStepForward" => None, + "MediaTopMenu" => None, + "NavigateIn" => None, + "NavigateNext" => None, + "NavigateOut" => None, + "NavigatePrevious" => None, + "NextFavoriteChannel" => None, + "NextUserProfile" => None, + "OnDemand" => None, + "Pairing" => None, + "PinPDown" => None, + "PinPMove" => None, + "PinPToggle" => None, + "PinPUp" => None, + "PlaySpeedDown" => None, + "PlaySpeedReset" => None, + "PlaySpeedUp" => None, + "RandomToggle" => None, + "RcLowBattery" => None, + "RecordSpeedNext" => None, + "RfBypass" => None, + "ScanChannelsToggle" => None, + "ScreenModeNext" => None, + "Settings" => None, + "SplitScreenToggle" => None, + "STBInput" => None, + "STBPower" => None, + "Subtitle" => None, + "Teletext" => None, + "VideoModeNext" => None, + "Wink" => None, + "ZoomToggle" => None, + + "SpeechCorrectionList" => None, + "SpeechInputToggle" => None, + + "Close" => None, + "New" => None, + "Open" => None, + "Print" => None, + "Save" => None, + "SpellCheck" => None, + "MailForward" => None, + "MailReply" => None, + "MailSend" => None, + + "LaunchCalculator" => Some(Calculator), + "LaunchCalendar" => None, + "LaunchContacts" => None, + "LaunchMail" => Some(Mail), + "LaunchMediaPlayer" => None, + "LaunchMusicPlayer" => None, + "LaunchMyComputer" => Some(MyComputer), + "LaunchPhone" => None, + "LaunchScreenSaver" => None, + "LaunchSpreadsheet" => None, + "LaunchWebCam" => None, + "LaunchWordProcessor" => None, + "LaunchApplication1" => None, + "LaunchApplication2" => None, + "LaunchApplication3" => None, + "LaunchApplication4" => None, + "LaunchApplication5" => None, + "LaunchApplication6" => None, + "LaunchApplication7" => None, + "LaunchApplication8" => None, + "LaunchApplication9" => None, + "LaunchApplication10" => None, + "LaunchApplication11" => None, + "LaunchApplication12" => None, + "LaunchApplication13" => None, + "LaunchApplication14" => None, + "LaunchApplication15" => None, + "LaunchApplication16" => None, + + "BrowserBack" => Some(WebBack), + "BrowserFavorites" => Some(WebFavorites), + "BrowserForward" => Some(WebForward), + "BrowserHome" => Some(WebHome), + "BrowserRefresh" => Some(WebRefresh), + "BrowserSearch" => Some(WebSearch), + "BrowserStop" => Some(WebStop), + + "Decimal" => Some(Decimal), + "Key11" => None, + "Key12" => None, + "Multiply" | "*" => Some(Multiply), + "Add" | "+" => Some(Add), + // "Clear" => None, + "Divide" => Some(Divide), + "Subtract" | "-" => Some(Subtract), + "Separator" => None, + "0" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad0), + _ => Some(Key0), + }, + "1" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad1), + _ => Some(Key1), + }, + "2" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad2), + _ => Some(Key2), + }, + "3" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad3), + _ => Some(Key3), + }, + "4" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad4), + _ => Some(Key4), + }, + "5" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad5), + _ => Some(Key5), + }, + "6" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad6), + _ => Some(Key6), + }, + "7" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad7), + _ => Some(Key7), + }, + "8" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad8), + _ => Some(Key8), + }, + "9" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad9), + _ => Some(Key9), + }, + + "A" | "a" => Some(A), + "B" | "b" => Some(B), + "C" | "c" => Some(C), + "D" | "d" => Some(D), + "E" | "e" => Some(E), + "F" | "f" => Some(F), + "G" | "g" => Some(G), + "H" | "h" => Some(H), + "I" | "i" => Some(I), + "J" | "j" => Some(J), + "K" | "k" => Some(K), + "L" | "l" => Some(L), + "M" | "m" => Some(M), + "N" | "n" => Some(N), + "O" | "o" => Some(O), + "P" | "p" => Some(P), + "Q" | "q" => Some(Q), + "R" | "r" => Some(R), + "S" | "s" => Some(S), + "T" | "t" => Some(T), + "U" | "u" => Some(U), + "V" | "v" => Some(V), + "W" | "w" => Some(W), + "X" | "x" => Some(X), + "Y" | "y" => Some(Y), + "Z" | "z" => Some(Z), + + "'" => Some(Apostrophe), + "\\" => Some(Backslash), + ":" => Some(Colon), + "," => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(NumpadComma), + _ => Some(Comma), + }, + "=" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(NumpadEquals), + _ => Some(Equals), + }, + "{" => Some(LBracket), + "." => Some(Period), + "}" => Some(RBracket), + ";" => Some(Semicolon), + "/" => Some(Slash), + + _ => None, + } +} diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 27ab9eb0c7..a6925d5f7b 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -27,6 +27,7 @@ use std::ops::Deref; use platform::PlatformSpecificWindowBuilderAttributes; mod ffi; +mod keyboard; pub struct Window { context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, @@ -378,18 +379,21 @@ extern fn keyboard_callback( unsafe { use std::mem; let queue: &RefCell> = mem::transmute(event_queue); + let code = keyboard::key_translate((*event).key); + let virtual_key = keyboard::key_translate_virt( + (*event).key, (*event).location); match event_type { ffi::EMSCRIPTEN_EVENT_KEYDOWN => { queue.borrow_mut().push_back(Event::KeyboardInput( ElementState::Pressed, - key_translate((*event).key), - key_translate_virt((*event).key, (*event).location))); + code, + virtual_key)); }, ffi::EMSCRIPTEN_EVENT_KEYUP => { queue.borrow_mut().push_back(Event::KeyboardInput( ElementState::Released, - key_translate((*event).key), - key_translate_virt((*event).key, (*event).location))); + code, + virtual_key)); }, _ => { } @@ -398,18 +402,3 @@ extern fn keyboard_callback( ffi::EM_TRUE } -fn key_translate(input: [ffi::EM_UTF8; ffi:: EM_HTML5_SHORT_STRING_LEN_BYTES]) -> u8 { - use std::str; - let slice = &input[0..input.iter().take_while(|x| **x != 0).count()]; - let key = str::from_utf8(&slice).unwrap(); - if key.chars().count() == 1 { - key.as_bytes()[0] - } else { - 0 - } -} - -fn key_translate_virt(input: [ffi::EM_UTF8; ffi:: EM_HTML5_SHORT_STRING_LEN_BYTES], location: libc::c_ulong) -> Option { - // TODO - None -} From af606e2f570fbd8e81f35aa36aa7d67c9baca4ac Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Wed, 15 Feb 2017 09:33:56 -0500 Subject: [PATCH 08/21] Remove excessive logging --- src/api/emscripten/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index a6925d5f7b..af5b2536e4 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -334,7 +334,6 @@ extern fn mouse_callback( event_type: libc::c_int, event: *const ffi::EmscriptenMouseEvent, event_queue: *mut libc::c_void) -> ffi::EM_BOOL { - // println!("callback {} {:p} {:p} !", event_type, event, event_queue); unsafe { use std::mem; let queue: &RefCell> = mem::transmute(event_queue); @@ -375,7 +374,6 @@ extern fn keyboard_callback( event_type: libc::c_int, event: *const ffi::EmscriptenKeyboardEvent, event_queue: *mut libc::c_void) -> ffi::EM_BOOL { - println!("keyevent {}", event_type); unsafe { use std::mem; let queue: &RefCell> = mem::transmute(event_queue); From 8ca74e5d7486d5bda2b87a858dc5d8cc1edb9957 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Fri, 17 Feb 2017 05:24:29 -0500 Subject: [PATCH 09/21] Update winit version to 0.5.11 and remove unnecssary use statements --- Cargo.toml | 3 +-- src/api/emscripten/keyboard.rs | 1 - src/api/emscripten/mod.rs | 6 ++---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 13bc556cbb..4b04dfc184 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ lazy_static = "0.2.0" libc = "0.2" shared_library = "0.1.0" -winit = "0.5.10" +winit = "0.5.11" [build-dependencies] gl_generator = "0.5" @@ -45,4 +45,3 @@ dwmapi-sys = "0.1" osmesa-sys = "0.1.0" wayland-client = { version = "0.7.4", features = ["egl", "dlopen"] } x11-dl = "2.4" - diff --git a/src/api/emscripten/keyboard.rs b/src/api/emscripten/keyboard.rs index 31e258b102..5e9293bb70 100644 --- a/src/api/emscripten/keyboard.rs +++ b/src/api/emscripten/keyboard.rs @@ -5,7 +5,6 @@ use VirtualKeyCode; use super::ffi; pub fn key_translate(input: [ffi::EM_UTF8; ffi:: EM_HTML5_SHORT_STRING_LEN_BYTES]) -> u8 { - use std::str; let slice = &input[0..input.iter().take_while(|x| **x != 0).count()]; if slice.len() == 1 { slice[0] diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index af5b2536e4..4011d0b5b1 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -19,7 +19,6 @@ pub use winit::WindowProxy; use ElementState; use MouseButton; -use VirtualKeyCode; use std::cell::RefCell; use std::collections::VecDeque; @@ -56,8 +55,7 @@ impl<'a> Iterator for WaitEventsIterator<'a> { #[inline] fn next(&mut self) -> Option { - // TODO - None + unimplemented!() } } @@ -73,7 +71,7 @@ impl Window { -> Result { // getting the default values of attributes - let mut attributes = unsafe { + let attributes = unsafe { use std::mem; let mut attributes: ffi::EmscriptenWebGLContextAttributes = mem::uninitialized(); ffi::emscripten_webgl_init_context_attributes(&mut attributes); From 7c1c4b9f951174a856e44b7d4255f35550c44094 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Tue, 21 Feb 2017 08:35:58 -0500 Subject: [PATCH 10/21] Use canvas coordinates instead of client coordinates --- src/api/emscripten/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 4011d0b5b1..393527b134 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -338,8 +338,8 @@ extern fn mouse_callback( match event_type { ffi::EMSCRIPTEN_EVENT_MOUSEMOVE => { queue.borrow_mut().push_back(Event::MouseMoved( - (*event).client_x as i32, - (*event).client_y as i32)); + (*event).canvas_x as i32, + (*event).canvas_y as i32)); }, ffi::EMSCRIPTEN_EVENT_MOUSEDOWN => { queue.borrow_mut().push_back(Event::MouseInput( From 84848af2ba3fae45e2ed9078f6a26d9bbc2c598f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 18 Mar 2017 15:58:34 +0100 Subject: [PATCH 11/21] fix warnings --- src/api/emscripten/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 393527b134..473e7cc8bf 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -64,8 +64,8 @@ const DOCUMENT_NAME: &'static str = "#document\0"; impl Window { pub fn new(_: &WindowAttributes, - pf_reqs: &PixelFormatRequirements, - opengl: &GlAttributes<&Window>, + _pf_reqs: &PixelFormatRequirements, + _opengl: &GlAttributes<&Window>, _: &PlatformSpecificWindowBuilderAttributes, _: winit::WindowBuilder) -> Result { @@ -219,11 +219,11 @@ impl Window { } #[inline] - pub fn set_cursor(&self, cursor: MouseCursor) { + pub fn set_cursor(&self, _cursor: MouseCursor) { } #[inline] - pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> { Ok(()) } @@ -233,7 +233,7 @@ impl Window { } #[inline] - pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { + pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> { Ok(()) } From acd4405546818fcc48c44c985b0b584b35ebc7f1 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 18 Mar 2017 16:22:57 +0100 Subject: [PATCH 12/21] implement hidpi factor --- src/api/emscripten/ffi.rs | 2 ++ src/api/emscripten/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index ebde37cae3..1102cf74c9 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -157,4 +157,6 @@ extern { pub fn emscripten_set_keydown_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_keyboard_callback_func) -> EMSCRIPTEN_RESULT; pub fn emscripten_set_keyup_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_keyboard_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_get_device_pixel_ratio() -> f64; } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 473e7cc8bf..a9f3b4a683 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -229,7 +229,7 @@ impl Window { #[inline] pub fn hidpi_factor(&self) -> f32 { - 1.0 + unsafe { ffi::emscripten_get_device_pixel_ratio() as f32 } } #[inline] @@ -259,7 +259,7 @@ impl Window { #[inline] pub fn hdpi_factor(&self) -> f32 { - unimplemented!(); + self.hidpi_factor() } } From 10b3b77a0204ef2c206f654b89f609b1ff1b6061 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 18 Mar 2017 17:04:51 +0100 Subject: [PATCH 13/21] impl get set size --- src/api/emscripten/ffi.rs | 10 ++++------ src/api/emscripten/mod.rs | 20 ++++++-------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index 1102cf74c9..ffbf2db6eb 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -136,12 +136,6 @@ extern { pub fn emscripten_exit_fullscreen() -> EMSCRIPTEN_RESULT; - pub fn emscripten_set_element_css_size(target: *const libc::c_char, width: libc::c_double, - height: libc::c_double) -> EMSCRIPTEN_RESULT; - - pub fn emscripten_get_element_css_size(target: *const libc::c_char, width: *mut libc::c_double, - height: *mut libc::c_double) -> EMSCRIPTEN_RESULT; - pub fn emscripten_sleep(delay: libc::c_uint); pub fn emscripten_set_main_loop(func : em_callback_func, fps : libc::c_int, simulate_infinite_loop : libc::c_int); @@ -159,4 +153,8 @@ extern { pub fn emscripten_set_keyup_callback(target: *const libc::c_char, user_data: *mut libc::c_void, use_capture: EM_BOOL, callback: em_keyboard_callback_func) -> EMSCRIPTEN_RESULT; pub fn emscripten_get_device_pixel_ratio() -> f64; + + pub fn emscripten_set_canvas_size(width: libc::c_int, height: libc::c_int); + + pub fn emscripten_get_canvas_size(width: *mut libc::c_int, height: *mut libc::c_int, isFullscreen: *mut libc::c_int); } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index a9f3b4a683..6cea9e058b 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -151,17 +151,13 @@ impl Window { pub fn get_inner_size(&self) -> Option<(u32, u32)> { unsafe { - use std::{mem, ptr}; + use std::mem; let mut width = mem::uninitialized(); let mut height = mem::uninitialized(); + let mut fullscreen = mem::uninitialized(); - if ffi::emscripten_get_element_css_size(ptr::null(), &mut width, &mut height) - != ffi::EMSCRIPTEN_RESULT_SUCCESS - { - None - } else { - Some((width as u32, height as u32)) - } + ffi::emscripten_get_canvas_size(&mut width, &mut height, &mut fullscreen); + Some((width as u32, height as u32)) } } @@ -172,11 +168,7 @@ impl Window { #[inline] pub fn set_inner_size(&self, width: u32, height: u32) { - unsafe { - use std::ptr; - ffi::emscripten_set_element_css_size(ptr::null(), width as libc::c_double, height - as libc::c_double); - } + unsafe { ffi::emscripten_set_canvas_size(width as i32, height as i32); } } #[inline] @@ -244,7 +236,7 @@ impl Window { #[inline] pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> { - unimplemented!() + self.get_inner_size() } #[inline] From b8cdab7aeeb2cc4ee557629ed878cac48ae32393 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 18 Mar 2017 17:56:16 +0100 Subject: [PATCH 14/21] impl fullscreen and window dimensions --- src/api/emscripten/ffi.rs | 24 ++++++++++++++++++++++++ src/api/emscripten/mod.rs | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index ffbf2db6eb..dbfc84482c 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -17,6 +17,28 @@ pub type em_webgl_context_callback = extern fn(libc::c_int, *const libc::c_void, pub type em_callback_func = unsafe extern fn(); +pub type em_fullscreenchange_callback_func = Option EM_BOOL>; + +#[repr(C)] +pub struct EmscriptenFullscreenChangeEvent { + pub isFullscreen: ::libc::c_int, + pub fullscreenEnabled: ::libc::c_int, + pub nodeName: [::libc::c_char; 128usize], + pub id: [::libc::c_char; 128usize], + pub elementWidth: ::libc::c_int, + pub elementHeight: ::libc::c_int, + pub screenWidth: ::libc::c_int, + pub screenHeight: ::libc::c_int, +} +#[test] +fn bindgen_test_layout_EmscriptenFullscreenChangeEvent() { + assert_eq!(::std::mem::size_of::(), 280usize); + assert_eq!(::std::mem::align_of::(), 4usize); +} + pub const EMSCRIPTEN_EVENT_KEYDOWN: libc::c_int = 2; pub const EMSCRIPTEN_EVENT_KEYUP: libc::c_int = 3; @@ -157,4 +179,6 @@ extern { pub fn emscripten_set_canvas_size(width: libc::c_int, height: libc::c_int); pub fn emscripten_get_canvas_size(width: *mut libc::c_int, height: *mut libc::c_int, isFullscreen: *mut libc::c_int); + + pub fn emscripten_set_fullscreenchange_callback(target: *const libc::c_char, userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_fullscreenchange_callback_func) -> EMSCRIPTEN_RESULT; } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 6cea9e058b..009af4bef3 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -67,7 +67,7 @@ impl Window { _pf_reqs: &PixelFormatRequirements, _opengl: &GlAttributes<&Window>, _: &PlatformSpecificWindowBuilderAttributes, - _: winit::WindowBuilder) + window_builder: winit::WindowBuilder) -> Result { // getting the default values of attributes @@ -130,10 +130,24 @@ impl Window { // TODO: emscripten_set_webglcontextrestored_callback - Ok(Window { + let window = Window { context: context, events: events, - }) + }; + + if window_builder.window.monitor.is_some() { + use std::ptr; + unsafe { + em_try(ffi::emscripten_request_fullscreen(ptr::null(), ffi::EM_TRUE)) + .map_err(|e| ::CreationError::OsError(e))?; + em_try(ffi::emscripten_set_fullscreenchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, Some(fullscreen_callback))) + .map_err(|e| ::CreationError::OsError(e))?; + } + } else if let Some((w, h)) = window_builder.window.dimensions { + window.set_inner_size(w, h); + } + + Ok(window) } #[inline] @@ -295,7 +309,9 @@ impl GlContext for Window { impl Drop for Window { fn drop(&mut self) { + use std::ptr; unsafe { + ffi::emscripten_set_fullscreenchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, None); ffi::emscripten_exit_fullscreen(); ffi::emscripten_webgl_destroy_context(self.context); } @@ -319,6 +335,12 @@ fn error_to_str(code: ffi::EMSCRIPTEN_RESULT) -> &'static str { } } +fn em_try(res: ffi::EMSCRIPTEN_RESULT) -> Result<(), String> { + match res { + ffi::EMSCRIPTEN_RESULT_SUCCESS | ffi::EMSCRIPTEN_RESULT_DEFERRED => Ok(()), + r @ _ => Err(error_to_str(r).to_string()), + } +} extern fn mouse_callback( event_type: libc::c_int, @@ -390,3 +412,14 @@ extern fn keyboard_callback( ffi::EM_TRUE } +// In case of fullscreen window this method will request fullscreen on change +#[allow(non_snake_case)] +unsafe extern "C" fn fullscreen_callback( + _eventType: libc::c_int, + _fullscreenChangeEvent: *const ffi::EmscriptenFullscreenChangeEvent, + _userData: *mut libc::c_void) -> ffi::EM_BOOL +{ + use std::ptr; + ffi::emscripten_request_fullscreen(ptr::null(), ffi::EM_TRUE); + ffi::EM_FALSE +} From e84423590fde21f5a95d530da4f29754d2252421 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sun, 19 Mar 2017 16:29:55 +0100 Subject: [PATCH 15/21] impl set_cursor_state grab mode use pointerlock https://www.w3.org/TR/pointerlock/ this behavior is not the same as other backend. I wanted this because as set_cursor_position is not available on emscripten backend. the only way to have a FPS camera is to use pointerlock. So you can use grab to have FPS camera on emscripten. also show_mouse is implement in javascript as in a pull request that hasn't been merged https://github.com/kripken/emscripten/pull/4616 --- src/api/emscripten/ffi.rs | 24 ++++++++++++++ src/api/emscripten/mod.rs | 70 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index dbfc84482c..5ec6b60e21 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -39,6 +39,18 @@ fn bindgen_test_layout_EmscriptenFullscreenChangeEvent() { assert_eq!(::std::mem::align_of::(), 4usize); } +#[repr(C)] +pub struct EmscriptenPointerlockChangeEvent { + pub isActive: ::libc::c_int, + pub nodeName: [::libc::c_char; 128usize], + pub id: [::libc::c_char; 128usize], +} +#[test] +fn bindgen_test_layout_EmscriptenPointerlockChangeEvent() { + assert_eq!(::std::mem::size_of::(), 260usize); + assert_eq!(::std::mem::align_of::(), 4usize); +} + pub const EMSCRIPTEN_EVENT_KEYDOWN: libc::c_int = 2; pub const EMSCRIPTEN_EVENT_KEYUP: libc::c_int = 3; @@ -98,6 +110,8 @@ pub type em_mouse_callback_func = extern fn(libc::c_int, *const EmscriptenMouseE pub type em_keyboard_callback_func = extern fn(libc::c_int, *const EmscriptenKeyboardEvent, *mut libc::c_void) -> EM_BOOL; +pub type em_pointerlockchange_callback_func = Option EM_BOOL>; + #[repr(C)] pub struct EmscriptenWebGLContextAttributes { pub alpha: EM_BOOL, @@ -152,6 +166,10 @@ extern { // note: this function is not documented but is used by the ports of glfw, SDL and EGL pub fn emscripten_GetProcAddress(name: *const libc::c_char) -> *const libc::c_void; + pub fn emscripten_request_pointerlock(target: *const libc::c_char, + deferUntilInEventHandler: EM_BOOL) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_exit_pointerlock() -> EMSCRIPTEN_RESULT; pub fn emscripten_request_fullscreen(target: *const libc::c_char, deferUntilInEventHandler: EM_BOOL) -> EMSCRIPTEN_RESULT; @@ -181,4 +199,10 @@ extern { pub fn emscripten_get_canvas_size(width: *mut libc::c_int, height: *mut libc::c_int, isFullscreen: *mut libc::c_int); pub fn emscripten_set_fullscreenchange_callback(target: *const libc::c_char, userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_fullscreenchange_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_set_pointerlockchange_callback(target: *const libc::c_char, userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_pointerlockchange_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_hide_mouse(); + + pub fn emscripten_asm_const(code: *const libc::c_char); } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 009af4bef3..f356715027 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -29,6 +29,7 @@ mod ffi; mod keyboard; pub struct Window { + cursor_state: RefCell<::CursorState>, context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, events: Box>>, } @@ -131,6 +132,7 @@ impl Window { // TODO: emscripten_set_webglcontextrestored_callback let window = Window { + cursor_state: RefCell::new(::CursorState::Normal), context: context, events: events, }; @@ -229,8 +231,41 @@ impl Window { } #[inline] - pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> { - Ok(()) + pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + use std::ptr; + unsafe { + use ::CursorState::*; + + let mut old_state = self.cursor_state.borrow_mut(); + if state == *old_state { + return Ok(()); + } + + // Set or unset grab callback + match state { + Hide | Normal => em_try(ffi::emscripten_set_pointerlockchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, None))?, + Grab => em_try(ffi::emscripten_set_pointerlockchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, Some(pointerlockchange_callback)))?, + } + + // Go back to normal cursor state + match *old_state { + Hide => show_mouse(), + Grab => em_try(ffi::emscripten_exit_pointerlock())?, + Normal => (), + } + + // Set cursor from normal cursor state + match state { + Hide => ffi::emscripten_hide_mouse(), + Grab => em_try(ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE))?, + Normal => (), + } + + // Update + *old_state = state; + + Ok(()) + } } #[inline] @@ -423,3 +458,34 @@ unsafe extern "C" fn fullscreen_callback( ffi::emscripten_request_fullscreen(ptr::null(), ffi::EM_TRUE); ffi::EM_FALSE } + +// In case of pointer grabbed this method will request pointer lock on change +#[allow(non_snake_case)] +unsafe extern "C" fn pointerlockchange_callback( + _eventType: libc::c_int, + _pointerlockChangeEvent: *const ffi::EmscriptenPointerlockChangeEvent, + _userData: *mut libc::c_void) -> ffi::EM_BOOL +{ + use std::ptr; + ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE); + ffi::EM_FALSE +} + +fn show_mouse() { + // Hide mouse hasn't show mouse equivalent. + // There is a pull request on emscripten that hasn't been merged #4616 + // that contains: + // + // var styleSheet = document.styleSheets[0]; + // var rules = styleSheet.cssRules; + // for (var i = 0; i < rules.length; i++) { + // if (rules[i].cssText.substr(0, 6) == 'canvas') { + // styleSheet.deleteRule(i); + // i--; + // } + // } + // styleSheet.insertRule('canvas.emscripten { border: none; cursor: auto; }', 0); + unsafe { + ffi::emscripten_asm_const(b"var styleSheet = document.styleSheets[0]; var rules = styleSheet.cssRules; for (var i = 0; i < rules.length; i++) { if (rules[i].cssText.substr(0, 6) == 'canvas') { styleSheet.deleteRule(i); i--; } } styleSheet.insertRule('canvas.emscripten { border: none; cursor: auto; }', 0);\0" as *const u8); + } +} From 35322ce3cd471f60c5325fb1cefa8b01a15a60ac Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 22 Mar 2017 19:03:45 +0100 Subject: [PATCH 16/21] implement of touchevent --- src/api/emscripten/ffi.rs | 64 +++++++++++++++++++++++++++ src/api/emscripten/mod.rs | 91 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index 5ec6b60e21..80134d165c 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -59,6 +59,11 @@ pub const EMSCRIPTEN_EVENT_MOUSEDOWN: libc::c_int = 5; pub const EMSCRIPTEN_EVENT_MOUSEUP: libc::c_int = 6; pub const EMSCRIPTEN_EVENT_MOUSEMOVE: libc::c_int = 8; +pub const EMSCRIPTEN_EVENT_TOUCHSTART: libc::c_int = 22; +pub const EMSCRIPTEN_EVENT_TOUCHEND: libc::c_int = 23; +pub const EMSCRIPTEN_EVENT_TOUCHMOVE: libc::c_int = 24; +pub const EMSCRIPTEN_EVENT_TOUCHCANCEL: libc::c_int = 25; + pub const EM_HTML5_SHORT_STRING_LEN_BYTES: usize = 32; pub const DOM_KEY_LOCATION_STANDARD: libc::c_ulong = 0x00; @@ -112,6 +117,8 @@ pub type em_keyboard_callback_func = extern fn(libc::c_int, *const EmscriptenKey pub type em_pointerlockchange_callback_func = Option EM_BOOL>; +pub type em_touch_callback_func = Option EM_BOOL>; + #[repr(C)] pub struct EmscriptenWebGLContextAttributes { pub alpha: EM_BOOL, @@ -127,6 +134,55 @@ pub struct EmscriptenWebGLContextAttributes { pub enableExtensionsByDefault: EM_BOOL, } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct EmscriptenTouchPoint { + pub identifier: libc::c_long, + pub screenX: libc::c_long, + pub screenY: libc::c_long, + pub clientX: libc::c_long, + pub clientY: libc::c_long, + pub pageX: libc::c_long, + pub pageY: libc::c_long, + pub isChanged: libc::c_int, + pub onTarget: libc::c_int, + pub targetX: libc::c_long, + pub targetY: libc::c_long, + pub canvasX: libc::c_long, + pub canvasY: libc::c_long, +} + +#[test] +fn bindgen_test_layout_EmscriptenTouchPoint() { + assert_eq!(::std::mem::size_of::() , 96usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} + +impl Clone for EmscriptenTouchPoint { + fn clone(&self) -> Self { *self } +} + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct EmscriptenTouchEvent { + pub numTouches: libc::c_int, + pub ctrlKey: libc::c_int, + pub shiftKey: libc::c_int, + pub altKey: libc::c_int, + pub metaKey: libc::c_int, + pub touches: [EmscriptenTouchPoint; 32usize], +} + +#[test] +fn bindgen_test_layout_EmscriptenTouchEvent() { + assert_eq!(::std::mem::size_of::() , 3096usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} + +impl Clone for EmscriptenTouchEvent { + fn clone(&self) -> Self { *self } +} + // values for EMSCRIPTEN_RESULT pub const EMSCRIPTEN_RESULT_SUCCESS: libc::c_int = 0; pub const EMSCRIPTEN_RESULT_DEFERRED: libc::c_int = 1; @@ -205,4 +261,12 @@ extern { pub fn emscripten_hide_mouse(); pub fn emscripten_asm_const(code: *const libc::c_char); + + pub fn emscripten_set_touchstart_callback(target: *const libc::c_char, userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_touch_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_set_touchend_callback(target: *const libc::c_char, userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_touch_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_set_touchmove_callback(target: *const libc::c_char, userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_touch_callback_func) -> EMSCRIPTEN_RESULT; + + pub fn emscripten_set_touchcancel_callback(target: *const libc::c_char, userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_touch_callback_func) -> EMSCRIPTEN_RESULT; } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index f356715027..e2d4344c4e 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -21,7 +21,7 @@ use ElementState; use MouseButton; use std::cell::RefCell; -use std::collections::VecDeque; +use std::collections::{VecDeque, BTreeMap}; use std::ops::Deref; use platform::PlatformSpecificWindowBuilderAttributes; @@ -126,6 +126,22 @@ impl Window { mem::transmute(events.deref()), ffi::EM_FALSE, keyboard_callback); + ffi::emscripten_set_touchstart_callback(CANVAS_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + Some(touch_callback)); + ffi::emscripten_set_touchend_callback(CANVAS_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + Some(touch_callback)); + ffi::emscripten_set_touchmove_callback(CANVAS_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + Some(touch_callback)); + ffi::emscripten_set_touchcancel_callback(CANVAS_NAME.as_ptr(), + mem::transmute(events.deref()), + ffi::EM_FALSE, + Some(touch_callback)); } } @@ -447,6 +463,79 @@ extern fn keyboard_callback( ffi::EM_TRUE } +thread_local! { + static ACTIVE_TOUCHES: RefCell> = RefCell::new(BTreeMap::new()); +} + +extern fn touch_callback( + event_type: libc::c_int, + event: *const ffi::EmscriptenTouchEvent, + event_queue: *mut libc::c_void) -> ffi::EM_BOOL { + unsafe { + use std::mem; + + ACTIVE_TOUCHES.with(|active_touches| { + let mut active_touches = active_touches.borrow_mut(); + let queue: &RefCell> = mem::transmute(event_queue); + let mut queue = queue.borrow_mut(); + + match event_type { + ffi::EMSCRIPTEN_EVENT_TOUCHSTART => { + // Check for all new identifier + for touch in 0..(*event).numTouches as usize { + let touch = (*event).touches[touch]; + if !active_touches.contains_key(&touch.identifier) { + active_touches.insert(touch.identifier, (touch.canvasX, touch.canvasY)); + queue.push_back(Event::Touch( winit::Touch { + phase: winit::TouchPhase::Started, + location: (touch.canvasX as f64, touch.canvasY as f64), + id: touch.identifier as u64, + })) + } + } + }, + ffi::EMSCRIPTEN_EVENT_TOUCHEND | ffi::EMSCRIPTEN_EVENT_TOUCHCANCEL => { + // Check for event that are not onTarget + let phase = match event_type { + ffi::EMSCRIPTEN_EVENT_TOUCHEND => winit::TouchPhase::Ended, + ffi::EMSCRIPTEN_EVENT_TOUCHCANCEL => winit::TouchPhase::Cancelled, + _ => unreachable!(), + }; + for touch in 0..(*event).numTouches as usize { + let touch = (*event).touches[touch]; + if touch.onTarget == 0 { + active_touches.remove(&touch.identifier); + queue.push_back(Event::Touch( winit::Touch { + phase: phase, + location: (touch.canvasX as f64, touch.canvasY as f64), + id: touch.identifier as u64, + })) + } + } + } + ffi::EMSCRIPTEN_EVENT_TOUCHMOVE => { + // check for all event that have changed coordinates + for touch in 0..(*event).numTouches as usize { + let touch = (*event).touches[touch]; + if let Some(active_touch) = active_touches.get_mut(&touch.identifier) { + if active_touch.0 != touch.canvasX || active_touch.1 != touch.canvasY { + *active_touch = (touch.canvasX, touch.canvasY); + queue.push_back(Event::Touch( winit::Touch { + phase: winit::TouchPhase::Moved, + location: (touch.canvasX as f64, touch.canvasY as f64), + id: touch.identifier as u64, + })) + } + } + } + } + _ => () + } + }); + } + ffi::EM_TRUE +} + // In case of fullscreen window this method will request fullscreen on change #[allow(non_snake_case)] unsafe extern "C" fn fullscreen_callback( From 9e3fab260c85718b7914df23602517efbb55dad6 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Mar 2017 23:08:17 +0200 Subject: [PATCH 17/21] fix mouse grab two fixes: * when mouse is grabbed send relative mousemove event * when mouse grabbed is refused, ask again. --- src/api/emscripten/ffi.rs | 2 + src/api/emscripten/mod.rs | 232 ++++++++++++++++++++++---------------- 2 files changed, 138 insertions(+), 96 deletions(-) diff --git a/src/api/emscripten/ffi.rs b/src/api/emscripten/ffi.rs index 80134d165c..9343ef7460 100644 --- a/src/api/emscripten/ffi.rs +++ b/src/api/emscripten/ffi.rs @@ -227,6 +227,8 @@ extern { pub fn emscripten_exit_pointerlock() -> EMSCRIPTEN_RESULT; + pub fn emscripten_get_pointerlock_status(pointerlockStatus: *mut EmscriptenPointerlockChangeEvent) -> EMSCRIPTEN_RESULT; + pub fn emscripten_request_fullscreen(target: *const libc::c_char, deferUntilInEventHandler: EM_BOOL) -> EMSCRIPTEN_RESULT; diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index e2d4344c4e..c046e13ae0 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -28,10 +28,15 @@ use platform::PlatformSpecificWindowBuilderAttributes; mod ffi; mod keyboard; +pub struct InnerWindow { + cursor_state: ::CursorState, + events: VecDeque, + active_touches: BTreeMap, +} + pub struct Window { - cursor_state: RefCell<::CursorState>, + inner: Box>, context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, - events: Box>>, } pub struct PollEventsIterator<'a> { @@ -43,7 +48,7 @@ impl<'a> Iterator for PollEventsIterator<'a> { #[inline] fn next(&mut self) -> Option { - self.window.events.deref().borrow_mut().pop_front() + self.window.inner.deref().borrow_mut().events.pop_front() } } @@ -100,59 +105,65 @@ impl Window { context }; - let events = Box::new(RefCell::new(VecDeque::new())); + + let window = Window { + inner: Box::new(RefCell::new(InnerWindow { + events: VecDeque::new(), + cursor_state: ::CursorState::Normal, + active_touches: BTreeMap::new(), + })), + context: context, + }; { use std::mem; // TODO: set up more event callbacks unsafe { ffi::emscripten_set_mousemove_callback(CANVAS_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, mouse_callback); ffi::emscripten_set_mousedown_callback(CANVAS_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, mouse_callback); ffi::emscripten_set_mouseup_callback(CANVAS_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, mouse_callback); ffi::emscripten_set_keydown_callback(DOCUMENT_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, keyboard_callback); ffi::emscripten_set_keyup_callback(DOCUMENT_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, keyboard_callback); ffi::emscripten_set_touchstart_callback(CANVAS_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, Some(touch_callback)); ffi::emscripten_set_touchend_callback(CANVAS_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, Some(touch_callback)); ffi::emscripten_set_touchmove_callback(CANVAS_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, Some(touch_callback)); ffi::emscripten_set_touchcancel_callback(CANVAS_NAME.as_ptr(), - mem::transmute(events.deref()), + mem::transmute(window.inner.deref()), ffi::EM_FALSE, Some(touch_callback)); + ffi::emscripten_set_pointerlockchange_callback(CANVAS_NAME.as_ptr(), + mem::transmute(window.inner.deref()), + ffi::EM_FALSE, + Some(pointerlockchange_callback)); } } // TODO: emscripten_set_webglcontextrestored_callback - let window = Window { - cursor_state: RefCell::new(::CursorState::Normal), - context: context, - events: events, - }; - if window_builder.window.monitor.is_some() { use std::ptr; unsafe { @@ -252,17 +263,11 @@ impl Window { unsafe { use ::CursorState::*; - let mut old_state = self.cursor_state.borrow_mut(); + let ref mut old_state = self.inner.borrow_mut().cursor_state; if state == *old_state { return Ok(()); } - // Set or unset grab callback - match state { - Hide | Normal => em_try(ffi::emscripten_set_pointerlockchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, None))?, - Grab => em_try(ffi::emscripten_set_pointerlockchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, Some(pointerlockchange_callback)))?, - } - // Go back to normal cursor state match *old_state { Hide => show_mouse(), @@ -362,6 +367,7 @@ impl Drop for Window { fn drop(&mut self) { use std::ptr; unsafe { + ffi::emscripten_set_pointerlockchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, None); ffi::emscripten_set_fullscreenchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, None); ffi::emscripten_exit_fullscreen(); ffi::emscripten_webgl_destroy_context(self.context); @@ -396,18 +402,39 @@ fn em_try(res: ffi::EMSCRIPTEN_RESULT) -> Result<(), String> { extern fn mouse_callback( event_type: libc::c_int, event: *const ffi::EmscriptenMouseEvent, - event_queue: *mut libc::c_void) -> ffi::EM_BOOL { + user_data: *mut libc::c_void) -> ffi::EM_BOOL { unsafe { use std::mem; - let queue: &RefCell> = mem::transmute(event_queue); + use std::ptr; + + let inner_window: &RefCell = mem::transmute(user_data); + let mut inner_window = inner_window.borrow_mut(); + match event_type { ffi::EMSCRIPTEN_EVENT_MOUSEMOVE => { - queue.borrow_mut().push_back(Event::MouseMoved( - (*event).canvas_x as i32, - (*event).canvas_y as i32)); + // send relative move if cursor is grabbed + match inner_window.cursor_state { + ::CursorState::Grab => inner_window.events.push_back( + Event::MouseMoved( + (*event).movement_x as i32, + (*event).movement_y as i32)), + _ => inner_window.events.push_back( + Event::MouseMoved( + (*event).canvas_x as i32, + (*event).canvas_y as i32)), + } }, ffi::EMSCRIPTEN_EVENT_MOUSEDOWN => { - queue.borrow_mut().push_back(Event::MouseInput( + // call pointerlock if needed + if let ::CursorState::Grab = inner_window.cursor_state { + let mut pointerlock_status: ffi::EmscriptenPointerlockChangeEvent = mem::uninitialized(); + ffi::emscripten_get_pointerlock_status(&mut pointerlock_status); + if pointerlock_status.isActive == ffi::EM_FALSE { + ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE); + } + } + + inner_window.events.push_back(Event::MouseInput( ElementState::Pressed, match (*event).button { 0 => MouseButton::Left, @@ -417,7 +444,7 @@ extern fn mouse_callback( })); }, ffi::EMSCRIPTEN_EVENT_MOUSEUP => { - queue.borrow_mut().push_back(Event::MouseInput( + inner_window.events.push_back(Event::MouseInput( ElementState::Released, match (*event).button { 0 => MouseButton::Left, @@ -436,22 +463,24 @@ extern fn mouse_callback( extern fn keyboard_callback( event_type: libc::c_int, event: *const ffi::EmscriptenKeyboardEvent, - event_queue: *mut libc::c_void) -> ffi::EM_BOOL { + user_data: *mut libc::c_void) -> ffi::EM_BOOL { unsafe { use std::mem; - let queue: &RefCell> = mem::transmute(event_queue); + let inner_window: &RefCell = mem::transmute(user_data); + let mut inner_window = inner_window.borrow_mut(); + let code = keyboard::key_translate((*event).key); let virtual_key = keyboard::key_translate_virt( (*event).key, (*event).location); match event_type { ffi::EMSCRIPTEN_EVENT_KEYDOWN => { - queue.borrow_mut().push_back(Event::KeyboardInput( + inner_window.events.push_back(Event::KeyboardInput( ElementState::Pressed, code, virtual_key)); }, ffi::EMSCRIPTEN_EVENT_KEYUP => { - queue.borrow_mut().push_back(Event::KeyboardInput( + inner_window.events.push_back(Event::KeyboardInput( ElementState::Released, code, virtual_key)); @@ -463,75 +492,77 @@ extern fn keyboard_callback( ffi::EM_TRUE } -thread_local! { - static ACTIVE_TOUCHES: RefCell> = RefCell::new(BTreeMap::new()); -} - extern fn touch_callback( event_type: libc::c_int, event: *const ffi::EmscriptenTouchEvent, - event_queue: *mut libc::c_void) -> ffi::EM_BOOL { + user_data: *mut libc::c_void) -> ffi::EM_BOOL { unsafe { use std::mem; - ACTIVE_TOUCHES.with(|active_touches| { - let mut active_touches = active_touches.borrow_mut(); - let queue: &RefCell> = mem::transmute(event_queue); - let mut queue = queue.borrow_mut(); - - match event_type { - ffi::EMSCRIPTEN_EVENT_TOUCHSTART => { - // Check for all new identifier - for touch in 0..(*event).numTouches as usize { - let touch = (*event).touches[touch]; - if !active_touches.contains_key(&touch.identifier) { - active_touches.insert(touch.identifier, (touch.canvasX, touch.canvasY)); - queue.push_back(Event::Touch( winit::Touch { - phase: winit::TouchPhase::Started, - location: (touch.canvasX as f64, touch.canvasY as f64), - id: touch.identifier as u64, - })) - } + let inner_window: &RefCell = mem::transmute(user_data); + let mut inner_window = inner_window.borrow_mut(); + + match event_type { + ffi::EMSCRIPTEN_EVENT_TOUCHSTART => { + // Check for all new identifier + for touch in 0..(*event).numTouches as usize { + let touch = (*event).touches[touch]; + if !inner_window.active_touches.contains_key(&touch.identifier) { + inner_window.active_touches.insert(touch.identifier, (touch.canvasX, touch.canvasY)); + inner_window.events.push_back(Event::Touch( winit::Touch { + phase: winit::TouchPhase::Started, + location: (touch.canvasX as f64, touch.canvasY as f64), + id: touch.identifier as u64, + })) } - }, - ffi::EMSCRIPTEN_EVENT_TOUCHEND | ffi::EMSCRIPTEN_EVENT_TOUCHCANCEL => { - // Check for event that are not onTarget - let phase = match event_type { - ffi::EMSCRIPTEN_EVENT_TOUCHEND => winit::TouchPhase::Ended, - ffi::EMSCRIPTEN_EVENT_TOUCHCANCEL => winit::TouchPhase::Cancelled, - _ => unreachable!(), - }; - for touch in 0..(*event).numTouches as usize { - let touch = (*event).touches[touch]; - if touch.onTarget == 0 { - active_touches.remove(&touch.identifier); - queue.push_back(Event::Touch( winit::Touch { - phase: phase, - location: (touch.canvasX as f64, touch.canvasY as f64), - id: touch.identifier as u64, - })) - } + } + }, + ffi::EMSCRIPTEN_EVENT_TOUCHEND | ffi::EMSCRIPTEN_EVENT_TOUCHCANCEL => { + // Check for event that are not onTarget + let phase = match event_type { + ffi::EMSCRIPTEN_EVENT_TOUCHEND => winit::TouchPhase::Ended, + ffi::EMSCRIPTEN_EVENT_TOUCHCANCEL => winit::TouchPhase::Cancelled, + _ => unreachable!(), + }; + for touch in 0..(*event).numTouches as usize { + let touch = (*event).touches[touch]; + if touch.onTarget == 0 { + inner_window.active_touches.remove(&touch.identifier); + inner_window.events.push_back(Event::Touch( winit::Touch { + phase: phase, + location: (touch.canvasX as f64, touch.canvasY as f64), + id: touch.identifier as u64, + })) } } - ffi::EMSCRIPTEN_EVENT_TOUCHMOVE => { - // check for all event that have changed coordinates - for touch in 0..(*event).numTouches as usize { - let touch = (*event).touches[touch]; - if let Some(active_touch) = active_touches.get_mut(&touch.identifier) { - if active_touch.0 != touch.canvasX || active_touch.1 != touch.canvasY { - *active_touch = (touch.canvasX, touch.canvasY); - queue.push_back(Event::Touch( winit::Touch { - phase: winit::TouchPhase::Moved, - location: (touch.canvasX as f64, touch.canvasY as f64), - id: touch.identifier as u64, - })) - } + } + ffi::EMSCRIPTEN_EVENT_TOUCHMOVE => { + // check for all event that have changed coordinates + for touch in 0..(*event).numTouches as usize { + let touch = (*event).touches[touch]; + + let diff = if let Some(active_touch) = inner_window.active_touches.get_mut(&touch.identifier) { + if active_touch.0 != touch.canvasX || active_touch.1 != touch.canvasY { + *active_touch = (touch.canvasX, touch.canvasY); + true + } else { + false } + } else { + false + }; + + if diff { + inner_window.events.push_back(Event::Touch( winit::Touch { + phase: winit::TouchPhase::Moved, + location: (touch.canvasX as f64, touch.canvasY as f64), + id: touch.identifier as u64, + })) } } - _ => () } - }); + _ => () + } } ffi::EM_TRUE } @@ -552,11 +583,20 @@ unsafe extern "C" fn fullscreen_callback( #[allow(non_snake_case)] unsafe extern "C" fn pointerlockchange_callback( _eventType: libc::c_int, - _pointerlockChangeEvent: *const ffi::EmscriptenPointerlockChangeEvent, - _userData: *mut libc::c_void) -> ffi::EM_BOOL + pointerlockChangeEvent: *const ffi::EmscriptenPointerlockChangeEvent, + user_data: *mut libc::c_void) -> ffi::EM_BOOL { + use std::mem; use std::ptr; - ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE); + + let inner_window: &RefCell = mem::transmute(user_data); + let inner_window = inner_window.borrow(); + + if let ::CursorState::Grab = inner_window.cursor_state { + if (*pointerlockChangeEvent).isActive == ffi::EM_FALSE { + ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE); + } + } ffi::EM_FALSE } From 352e3eef6b6bfc9c19b11254b6bc2d72f7cdfee3 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Mar 2017 23:36:39 +0200 Subject: [PATCH 18/21] catch more error --- src/api/emscripten/mod.rs | 70 +++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index c046e13ae0..1eec96c0a6 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -119,46 +119,66 @@ impl Window { use std::mem; // TODO: set up more event callbacks unsafe { - ffi::emscripten_set_mousemove_callback(CANVAS_NAME.as_ptr(), + em_try(ffi::emscripten_set_mousemove_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - mouse_callback); - ffi::emscripten_set_mousedown_callback(CANVAS_NAME.as_ptr(), + mouse_callback)) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_mousemove_callback: {}", e)))?; + em_try(ffi::emscripten_set_mousedown_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - mouse_callback); - ffi::emscripten_set_mouseup_callback(CANVAS_NAME.as_ptr(), + mouse_callback)) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_mousedown_callback: {}", e)))?; + em_try(ffi::emscripten_set_mouseup_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - mouse_callback); - ffi::emscripten_set_keydown_callback(DOCUMENT_NAME.as_ptr(), + mouse_callback)) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_mouseup_callback: {}", e)))?; + em_try(ffi::emscripten_set_keydown_callback(DOCUMENT_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - keyboard_callback); - ffi::emscripten_set_keyup_callback(DOCUMENT_NAME.as_ptr(), + keyboard_callback)) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_keydown_callback: {}", e)))?; + em_try(ffi::emscripten_set_keyup_callback(DOCUMENT_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - keyboard_callback); - ffi::emscripten_set_touchstart_callback(CANVAS_NAME.as_ptr(), + keyboard_callback)) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_keyup_callback: {}", e)))?; + em_try(ffi::emscripten_set_touchstart_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - Some(touch_callback)); - ffi::emscripten_set_touchend_callback(CANVAS_NAME.as_ptr(), + Some(touch_callback))) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_touchstart_callback: {}", e)))?; + em_try(ffi::emscripten_set_touchend_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - Some(touch_callback)); - ffi::emscripten_set_touchmove_callback(CANVAS_NAME.as_ptr(), + Some(touch_callback))) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_touchend_callback: {}", e)))?; + em_try(ffi::emscripten_set_touchmove_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - Some(touch_callback)); - ffi::emscripten_set_touchcancel_callback(CANVAS_NAME.as_ptr(), + Some(touch_callback))) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_touchmove_callback: {}", e)))?; + em_try(ffi::emscripten_set_touchcancel_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - Some(touch_callback)); - ffi::emscripten_set_pointerlockchange_callback(CANVAS_NAME.as_ptr(), + Some(touch_callback))) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_touchcancel_callback: {}", e)))?; + em_try(ffi::emscripten_set_pointerlockchange_callback(CANVAS_NAME.as_ptr(), mem::transmute(window.inner.deref()), ffi::EM_FALSE, - Some(pointerlockchange_callback)); + Some(pointerlockchange_callback))) + .map_err(|e| ::CreationError::OsError( + format!("Error while calling emscripten_set_pointerlockchange_callback: {}", e)))?; } } @@ -168,9 +188,9 @@ impl Window { use std::ptr; unsafe { em_try(ffi::emscripten_request_fullscreen(ptr::null(), ffi::EM_TRUE)) - .map_err(|e| ::CreationError::OsError(e))?; + .map_err(|e| ::CreationError::OsError(format!("Error while calling emscripten_request_fullscreen: {}", e)))?; em_try(ffi::emscripten_set_fullscreenchange_callback(ptr::null(), 0 as *mut libc::c_void, ffi::EM_FALSE, Some(fullscreen_callback))) - .map_err(|e| ::CreationError::OsError(e))?; + .map_err(|e| ::CreationError::OsError(format!("Error while calling emscripten_set_fullscreenchange_callback: {}", e)))?; } } else if let Some((w, h)) = window_builder.window.dimensions { window.set_inner_size(w, h); @@ -271,14 +291,16 @@ impl Window { // Go back to normal cursor state match *old_state { Hide => show_mouse(), - Grab => em_try(ffi::emscripten_exit_pointerlock())?, + Grab => em_try(ffi::emscripten_exit_pointerlock()) + .map_err(|e| format!("Error while calling emscripten_exit_pointerlock: {}", e))?, Normal => (), } // Set cursor from normal cursor state match state { Hide => ffi::emscripten_hide_mouse(), - Grab => em_try(ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE))?, + Grab => em_try(ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE)) + .map_err(|e| format!("Error while calling emscripten_request_pointerlock: {}", e))?, Normal => (), } From 51ce5a3ce9b968db69522746828740836e3203c8 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Mar 2017 23:44:44 +0200 Subject: [PATCH 19/21] coding style --- src/api/emscripten/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 1eec96c0a6..e354537db3 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -120,21 +120,21 @@ impl Window { // TODO: set up more event callbacks unsafe { em_try(ffi::emscripten_set_mousemove_callback(CANVAS_NAME.as_ptr(), - mem::transmute(window.inner.deref()), - ffi::EM_FALSE, - mouse_callback)) + mem::transmute(window.inner.deref()), + ffi::EM_FALSE, + mouse_callback)) .map_err(|e| ::CreationError::OsError( format!("Error while calling emscripten_set_mousemove_callback: {}", e)))?; em_try(ffi::emscripten_set_mousedown_callback(CANVAS_NAME.as_ptr(), - mem::transmute(window.inner.deref()), - ffi::EM_FALSE, - mouse_callback)) + mem::transmute(window.inner.deref()), + ffi::EM_FALSE, + mouse_callback)) .map_err(|e| ::CreationError::OsError( format!("Error while calling emscripten_set_mousedown_callback: {}", e)))?; em_try(ffi::emscripten_set_mouseup_callback(CANVAS_NAME.as_ptr(), - mem::transmute(window.inner.deref()), - ffi::EM_FALSE, - mouse_callback)) + mem::transmute(window.inner.deref()), + ffi::EM_FALSE, + mouse_callback)) .map_err(|e| ::CreationError::OsError( format!("Error while calling emscripten_set_mouseup_callback: {}", e)))?; em_try(ffi::emscripten_set_keydown_callback(DOCUMENT_NAME.as_ptr(), From 791260bff886a9c883dfbe731af64da7ece26bf3 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Mar 2017 22:01:24 +0200 Subject: [PATCH 20/21] consume event for pointerlock and fullscreen change --- src/api/emscripten/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index e354537db3..5eaa4fa89d 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -598,7 +598,7 @@ unsafe extern "C" fn fullscreen_callback( { use std::ptr; ffi::emscripten_request_fullscreen(ptr::null(), ffi::EM_TRUE); - ffi::EM_FALSE + ffi::EM_TRUE } // In case of pointer grabbed this method will request pointer lock on change @@ -619,7 +619,7 @@ unsafe extern "C" fn pointerlockchange_callback( ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE); } } - ffi::EM_FALSE + ffi::EM_TRUE } fn show_mouse() { From f2f099c4cdd63748fe899a5d9d47e3ebd07b4ded Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Mar 2017 22:09:12 +0200 Subject: [PATCH 21/21] check result of get pointer lock status --- src/api/emscripten/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 5eaa4fa89d..a99f6b6bd2 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -450,9 +450,10 @@ extern fn mouse_callback( // call pointerlock if needed if let ::CursorState::Grab = inner_window.cursor_state { let mut pointerlock_status: ffi::EmscriptenPointerlockChangeEvent = mem::uninitialized(); - ffi::emscripten_get_pointerlock_status(&mut pointerlock_status); - if pointerlock_status.isActive == ffi::EM_FALSE { - ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE); + if ffi::emscripten_get_pointerlock_status(&mut pointerlock_status) == ffi::EMSCRIPTEN_RESULT_SUCCESS { + if pointerlock_status.isActive == ffi::EM_FALSE { + ffi::emscripten_request_pointerlock(ptr::null(), ffi::EM_TRUE); + } } }