-
-
Notifications
You must be signed in to change notification settings - Fork 481
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
312 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,5 +5,6 @@ pub mod dlopen; | |
pub mod egl; | ||
pub mod glx; | ||
pub mod osmesa; | ||
pub mod wayland; | ||
pub mod win32; | ||
pub mod x11; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,309 @@ | ||
#![cfg(target_os = "linux")] | ||
|
||
use self::wayland::egl::{EGLSurface, is_egl_available}; | ||
use self::wayland::core::{Display, Registry, Compositor, Shell, ShellSurface, | ||
Seat, Pointer, default_display, WSurface}; | ||
|
||
use libc; | ||
use api::dlopen; | ||
use api::egl::Context as EglContext; | ||
|
||
use BuilderAttribs; | ||
use CreationError; | ||
use Event; | ||
use PixelFormat; | ||
use CursorState; | ||
use MouseCursor; | ||
|
||
use std::collections::VecDeque; | ||
use std::sync::{Arc, Mutex}; | ||
use std::ffi::CString; | ||
|
||
extern crate wayland_client as wayland; | ||
|
||
pub struct WaylandContext { | ||
pub display: Display, | ||
pub registry: Registry, | ||
pub compositor: Compositor, | ||
pub shell: Shell, | ||
pub seat: Seat | ||
} | ||
|
||
impl WaylandContext { | ||
pub fn new() -> Option<WaylandContext> { | ||
let display = match default_display() { | ||
Some(d) => d, | ||
None => return None, | ||
}; | ||
let registry = display.get_registry(); | ||
// let the registry get its events | ||
display.sync_roundtrip(); | ||
let compositor = match registry.get_compositor() { | ||
Some(c) => c, | ||
None => return None, | ||
}; | ||
let shell = match registry.get_shell() { | ||
Some(s) => s, | ||
None => return None, | ||
}; | ||
let seat = match registry.get_seats().into_iter().next() { | ||
Some(s) => s, | ||
None => return None, | ||
}; | ||
// let the other globals get their events | ||
display.sync_roundtrip(); | ||
Some(WaylandContext { | ||
display: display, | ||
registry: registry, | ||
compositor: compositor, | ||
shell: shell, | ||
seat: seat, | ||
}) | ||
} | ||
} | ||
|
||
|
||
pub struct Window { | ||
wayland_context: WaylandContext, | ||
shell_surface: ShellSurface<EGLSurface>, | ||
pointer: Option<Pointer<WSurface>>, | ||
pending_events: Arc<Mutex<VecDeque<Event>>>, | ||
pub context: EglContext, | ||
} | ||
|
||
// It is okay, as the window is completely self-owned: it has its | ||
// own wayland connexion. | ||
unsafe impl Send for Window {} | ||
|
||
#[derive(Clone)] | ||
pub struct WindowProxy; | ||
|
||
impl WindowProxy { | ||
pub fn wakeup_event_loop(&self) { | ||
unimplemented!() | ||
} | ||
} | ||
|
||
pub struct MonitorID; | ||
|
||
pub fn get_available_monitors() -> VecDeque<MonitorID> { | ||
VecDeque::new() | ||
} | ||
pub fn get_primary_monitor() -> MonitorID { | ||
MonitorID | ||
} | ||
|
||
impl MonitorID { | ||
pub fn get_name(&self) -> Option<String> { | ||
unimplemented!(); | ||
} | ||
|
||
pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId { | ||
::native_monitor::NativeMonitorId::Unavailable | ||
} | ||
|
||
pub fn get_dimensions(&self) -> (u32, u32) { | ||
unimplemented!(); | ||
} | ||
} | ||
|
||
|
||
pub struct PollEventsIterator<'a> { | ||
window: &'a Window, | ||
} | ||
|
||
impl<'a> Iterator for PollEventsIterator<'a> { | ||
type Item = Event; | ||
|
||
fn next(&mut self) -> Option<Event> { | ||
self.window.wayland_context.display.dispatch_pending(); | ||
self.window.pending_events.lock().unwrap().pop_front() | ||
} | ||
} | ||
|
||
pub struct WaitEventsIterator<'a> { | ||
window: &'a Window, | ||
} | ||
|
||
impl<'a> Iterator for WaitEventsIterator<'a> { | ||
type Item = Event; | ||
|
||
fn next(&mut self) -> Option<Event> { | ||
self.window.wayland_context.display.dispatch(); | ||
self.window.pending_events.lock().unwrap().pop_front() | ||
} | ||
} | ||
|
||
impl Window { | ||
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> { | ||
use self::wayland::internals::FFI; | ||
|
||
let wayland_context = match WaylandContext::new() { | ||
Some(c) => c, | ||
None => return Err(CreationError::NotSupported), | ||
}; | ||
|
||
if !is_egl_available() { return Err(CreationError::NotSupported) } | ||
|
||
let (w, h) = builder.dimensions.unwrap_or((800, 600)); | ||
|
||
let surface = EGLSurface::new( | ||
wayland_context.compositor.create_surface(), | ||
w as i32, | ||
h as i32 | ||
); | ||
|
||
let context = { | ||
let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) }; | ||
if libegl.is_null() { | ||
return Err(CreationError::NotSupported); | ||
} | ||
let egl = ::api::egl::ffi::egl::Egl::load_with(|sym| { | ||
let sym = CString::new(sym).unwrap(); | ||
unsafe { dlopen::dlsym(libegl, sym.as_ptr()) } | ||
}); | ||
try!(EglContext::new( | ||
egl, | ||
builder, | ||
Some(wayland_context.display.ptr() as *const _), | ||
surface.ptr() as *const _ | ||
)) | ||
}; | ||
|
||
let shell_surface = wayland_context.shell.get_shell_surface(surface); | ||
shell_surface.set_toplevel(); | ||
let events = Arc::new(Mutex::new(VecDeque::new())); | ||
|
||
let mut pointer = wayland_context.seat.get_pointer(); | ||
if let Some(ref mut p) = pointer { | ||
// set the events callbacks | ||
let motion_events = events.clone(); | ||
p.set_motion_action(move |_, _, x, y| { | ||
motion_events.lock().unwrap().push_back(Event::Moved(x as i32,y as i32)) | ||
}); | ||
let action_events = events.clone(); | ||
p.set_button_action(move |_, _, b, s| { | ||
use self::wayland::core::ButtonState; | ||
use MouseButton; | ||
use ElementState; | ||
let button = match b { | ||
0x110 => MouseButton::Left, | ||
0x111 => MouseButton::Right, | ||
0x112 => MouseButton::Middle, | ||
_ => return | ||
}; | ||
let state = match s { | ||
ButtonState::WL_POINTER_BUTTON_STATE_RELEASED => ElementState::Released, | ||
ButtonState::WL_POINTER_BUTTON_STATE_PRESSED => ElementState::Pressed | ||
}; | ||
action_events.lock().unwrap().push_back(Event::MouseInput(state, button)); | ||
}); | ||
} | ||
|
||
Ok(Window { | ||
wayland_context: wayland_context, | ||
shell_surface: shell_surface, | ||
pointer: pointer, | ||
pending_events: events, | ||
context: context | ||
}) | ||
} | ||
|
||
pub fn is_closed(&self) -> bool { | ||
false | ||
} | ||
|
||
pub fn set_title(&self, title: &str) { | ||
} | ||
|
||
pub fn show(&self) { | ||
} | ||
|
||
pub fn hide(&self) { | ||
} | ||
|
||
pub fn get_position(&self) -> Option<(i32, i32)> { | ||
unimplemented!() | ||
} | ||
|
||
pub fn set_position(&self, x: i32, y: i32) { | ||
} | ||
|
||
pub fn get_inner_size(&self) -> Option<(u32, u32)> { | ||
unimplemented!() | ||
} | ||
|
||
pub fn get_outer_size(&self) -> Option<(u32, u32)> { | ||
unimplemented!() | ||
} | ||
|
||
pub fn set_inner_size(&self, _x: u32, _y: u32) { | ||
unimplemented!() | ||
} | ||
|
||
pub fn create_window_proxy(&self) -> WindowProxy { | ||
unimplemented!() | ||
} | ||
|
||
pub fn poll_events(&self) -> PollEventsIterator { | ||
PollEventsIterator { | ||
window: self | ||
} | ||
} | ||
|
||
pub fn wait_events(&self) -> WaitEventsIterator { | ||
WaitEventsIterator { | ||
window: self | ||
} | ||
} | ||
|
||
pub unsafe fn make_current(&self) { | ||
self.context.make_current() | ||
} | ||
|
||
pub fn is_current(&self) -> bool { | ||
self.context.is_current() | ||
} | ||
|
||
pub fn get_proc_address(&self, addr: &str) -> *const () { | ||
self.context.get_proc_address(addr) | ||
} | ||
|
||
pub fn swap_buffers(&self) { | ||
self.context.swap_buffers() | ||
} | ||
|
||
pub fn platform_display(&self) -> *mut libc::c_void { | ||
unimplemented!() | ||
} | ||
|
||
pub fn platform_window(&self) -> *mut libc::c_void { | ||
unimplemented!() | ||
} | ||
|
||
pub fn get_api(&self) -> ::Api { | ||
self.context.get_api() | ||
} | ||
|
||
pub fn get_pixel_format(&self) -> PixelFormat { | ||
self.context.get_pixel_format().clone() | ||
} | ||
|
||
pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) { | ||
} | ||
|
||
pub fn set_cursor(&self, cursor: MouseCursor) { | ||
} | ||
|
||
pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { | ||
Ok(()) | ||
} | ||
|
||
pub fn hidpi_factor(&self) -> f32 { | ||
1.0 | ||
} | ||
|
||
pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { | ||
Ok(()) | ||
} | ||
} |