Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more implementations #1

Merged
merged 5 commits into from
Mar 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 54 additions & 6 deletions src/api/emscripten/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,40 @@ 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<unsafe extern "C" fn(
eventType: ::libc::c_int,
fullscreenChangeEvent: *const EmscriptenFullscreenChangeEvent,
userData: *mut ::libc::c_void) -> 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::<EmscriptenFullscreenChangeEvent>(), 280usize);
assert_eq!(::std::mem::align_of::<EmscriptenFullscreenChangeEvent>(), 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::<EmscriptenPointerlockChangeEvent>(), 260usize);
assert_eq!(::std::mem::align_of::<EmscriptenPointerlockChangeEvent>(), 4usize);
}

pub const EMSCRIPTEN_EVENT_KEYDOWN: libc::c_int = 2;
pub const EMSCRIPTEN_EVENT_KEYUP: libc::c_int = 3;

Expand Down Expand Up @@ -76,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<unsafe extern "C" fn(eventType: libc::c_int, pointerlockChangeEvent: *const EmscriptenPointerlockChangeEvent, userData: *mut libc::c_void) -> EM_BOOL>;

#[repr(C)]
pub struct EmscriptenWebGLContextAttributes {
pub alpha: EM_BOOL,
Expand Down Expand Up @@ -130,18 +166,16 @@ 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;

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);
Expand All @@ -157,4 +191,18 @@ 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;

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;

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);
}
139 changes: 115 additions & 24 deletions src/api/emscripten/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mod ffi;
mod keyboard;

pub struct Window {
cursor_state: RefCell<::CursorState>,
context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE,
events: Box<RefCell<VecDeque<Event>>>,
}
Expand Down Expand Up @@ -64,10 +65,10 @@ 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)
window_builder: winit::WindowBuilder)
-> Result<Window, CreationError> {

// getting the default values of attributes
Expand Down Expand Up @@ -130,10 +131,25 @@ impl Window {

// TODO: emscripten_set_webglcontextrestored_callback

Ok(Window {
let window = Window {
cursor_state: RefCell::new(::CursorState::Normal),
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]
Expand All @@ -151,17 +167,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))
}
}

Expand All @@ -172,11 +184,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]
Expand Down Expand Up @@ -219,21 +227,54 @@ 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> {
Ok(())
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]
pub fn hidpi_factor(&self) -> f32 {
1.0
unsafe { ffi::emscripten_get_device_pixel_ratio() as f32 }
}

#[inline]
pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
Ok(())
}

Expand All @@ -244,7 +285,7 @@ impl Window {

#[inline]
pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> {
unimplemented!()
self.get_inner_size()
}

#[inline]
Expand All @@ -259,7 +300,7 @@ impl Window {

#[inline]
pub fn hdpi_factor(&self) -> f32 {
unimplemented!();
self.hidpi_factor()
}
}

Expand Down Expand Up @@ -303,7 +344,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);
}
Expand All @@ -327,6 +370,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,
Expand Down Expand Up @@ -398,3 +447,45 @@ 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
}

// 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);
}
}