mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
wayland: mugrate to new API
This commit is contained in:
parent
9aaa788434
commit
7336cacf07
|
@ -129,7 +129,12 @@ impl Window2 {
|
|||
{
|
||||
match *UNIX_BACKEND {
|
||||
UnixBackend::Wayland(ref ctxt) => {
|
||||
wayland::Window2::new(events_loop, ctxt.clone(), window).map(Window2::Wayland)
|
||||
if let EventsLoop::Wayland(ref evlp) = *events_loop {
|
||||
wayland::Window2::new(evlp, ctxt.clone(), window).map(Window2::Wayland)
|
||||
} else {
|
||||
// It is not possible to instanciate an EventsLoop not matching its backend
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
|
||||
UnixBackend::X(ref connec) => {
|
||||
|
@ -299,8 +304,8 @@ pub enum EventsLoop {
|
|||
impl EventsLoop {
|
||||
pub fn new() -> EventsLoop {
|
||||
match *UNIX_BACKEND {
|
||||
UnixBackend::Wayland(_) => {
|
||||
EventsLoop::Wayland(wayland::EventsLoop::new())
|
||||
UnixBackend::Wayland(ref ctxt) => {
|
||||
EventsLoop::Wayland(wayland::EventsLoop::new(ctxt.clone()))
|
||||
},
|
||||
|
||||
UnixBackend::X(_) => {
|
||||
|
|
|
@ -10,7 +10,7 @@ use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subc
|
|||
wl_display, wl_registry, wl_output, wl_surface, wl_pointer,
|
||||
wl_keyboard};
|
||||
|
||||
use super::wayland_window;
|
||||
use super::{wayland_window, EventsLoopSink, make_wid};
|
||||
use super::wayland_kbd::MappedKeyboard;
|
||||
use super::keyboard::KbdHandler;
|
||||
|
||||
|
@ -27,7 +27,7 @@ wayland_env!(InnerEnv,
|
|||
|
||||
enum KbdType {
|
||||
Mapped(MappedKeyboard<KbdHandler>),
|
||||
Plain(Option<Arc<Mutex<VecDeque<Event>>>>)
|
||||
Plain(Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>)
|
||||
}
|
||||
|
||||
struct WaylandEnv {
|
||||
|
@ -35,10 +35,10 @@ struct WaylandEnv {
|
|||
inner: EnvHandler<InnerEnv>,
|
||||
monitors: Vec<OutputInfo>,
|
||||
my_id: usize,
|
||||
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<VecDeque<Event>>>)>,
|
||||
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
|
||||
seat: Option<wl_seat::WlSeat>,
|
||||
mouse: Option<wl_pointer::WlPointer>,
|
||||
mouse_focus: Option<Arc<Mutex<VecDeque<Event>>>>,
|
||||
mouse_focus: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
|
||||
mouse_location: (i32, i32),
|
||||
axis_buffer: Option<(f32, f32)>,
|
||||
axis_discrete_buffer: Option<(i32, i32)>,
|
||||
|
@ -252,16 +252,15 @@ impl WaylandContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_window<H: wayland_window::Handler>(&self)
|
||||
-> (Arc<wl_surface::WlSurface>, Arc<Mutex<VecDeque<Event>>>, wayland_window::DecoratedSurface<H>)
|
||||
pub fn create_window<H: wayland_window::Handler>(&self, sink: Arc<Mutex<EventsLoopSink>>)
|
||||
-> (Arc<wl_surface::WlSurface>, wayland_window::DecoratedSurface<H>)
|
||||
{
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead"));
|
||||
let eventiter = Arc::new(Mutex::new(VecDeque::new()));
|
||||
env.windows.push((surface.clone(), eventiter.clone()));
|
||||
env.windows.push((surface.clone(), sink));
|
||||
let decorated = wayland_window::DecoratedSurface::new(
|
||||
&*surface, 800, 600,
|
||||
&env.inner.compositor,
|
||||
|
@ -271,7 +270,7 @@ impl WaylandContext {
|
|||
env.get_seat(),
|
||||
false
|
||||
).expect("Failed to create a tmpfile buffer.");
|
||||
(surface, eventiter, decorated)
|
||||
(surface, decorated)
|
||||
}
|
||||
|
||||
pub fn prune_dead_windows(&self) {
|
||||
|
@ -397,13 +396,13 @@ impl wl_pointer::Handler for WaylandEnv {
|
|||
surface_y: f64)
|
||||
{
|
||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||
for &(ref window, ref eviter) in &self.windows {
|
||||
for &(ref window, ref sink) in &self.windows {
|
||||
if window.equals(surface) {
|
||||
self.mouse_focus = Some(eviter.clone());
|
||||
self.mouse_focus = Some((window.clone(), sink.clone()));
|
||||
let (w, h) = self.mouse_location;
|
||||
let mut event_queue = eviter.lock().unwrap();
|
||||
event_queue.push_back(Event::MouseEntered);
|
||||
event_queue.push_back(Event::MouseMoved(w, h));
|
||||
let mut event_queue = sink.lock().unwrap();
|
||||
event_queue.push_event(Event::MouseEntered, make_wid(window));
|
||||
event_queue.push_event(Event::MouseMoved(w, h), make_wid(window));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -416,10 +415,10 @@ impl wl_pointer::Handler for WaylandEnv {
|
|||
surface: &wl_surface::WlSurface)
|
||||
{
|
||||
self.mouse_focus = None;
|
||||
for &(ref window, ref eviter) in &self.windows {
|
||||
for &(ref window, ref sink) in &self.windows {
|
||||
if window.equals(surface) {
|
||||
let mut event_queue = eviter.lock().unwrap();
|
||||
event_queue.push_back(Event::MouseLeft);
|
||||
let mut event_queue = sink.lock().unwrap();
|
||||
event_queue.push_event(Event::MouseLeft, make_wid(window));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -433,10 +432,11 @@ impl wl_pointer::Handler for WaylandEnv {
|
|||
surface_y: f64)
|
||||
{
|
||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||
if let Some(ref eviter) = self.mouse_focus {
|
||||
if let Some((ref window, ref sink)) = self.mouse_focus {
|
||||
let (w,h) = self.mouse_location;
|
||||
eviter.lock().unwrap().push_back(
|
||||
Event::MouseMoved(w, h)
|
||||
sink.lock().unwrap().push_event(
|
||||
Event::MouseMoved(w, h),
|
||||
make_wid(window)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -449,7 +449,7 @@ impl wl_pointer::Handler for WaylandEnv {
|
|||
button: u32,
|
||||
state: wl_pointer::ButtonState)
|
||||
{
|
||||
if let Some(ref eviter) = self.mouse_focus {
|
||||
if let Some((ref window, ref sink)) = self.mouse_focus {
|
||||
let state = match state {
|
||||
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
|
||||
wl_pointer::ButtonState::Released => ElementState::Released
|
||||
|
@ -461,8 +461,9 @@ impl wl_pointer::Handler for WaylandEnv {
|
|||
// TODO figure out the translation ?
|
||||
_ => return
|
||||
};
|
||||
eviter.lock().unwrap().push_back(
|
||||
Event::MouseInput(state, button)
|
||||
sink.lock().unwrap().push_event(
|
||||
Event::MouseInput(state, button),
|
||||
make_wid(window)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -492,20 +493,22 @@ impl wl_pointer::Handler for WaylandEnv {
|
|||
{
|
||||
let axis_buffer = self.axis_buffer.take();
|
||||
let axis_discrete_buffer = self.axis_discrete_buffer.take();
|
||||
if let Some(ref eviter) = self.mouse_focus {
|
||||
if let Some((ref window, ref sink)) = self.mouse_focus {
|
||||
if let Some((x, y)) = axis_discrete_buffer {
|
||||
eviter.lock().unwrap().push_back(
|
||||
sink.lock().unwrap().push_event(
|
||||
Event::MouseWheel(
|
||||
MouseScrollDelta::LineDelta(x as f32, y as f32),
|
||||
self.axis_state
|
||||
)
|
||||
),
|
||||
make_wid(window)
|
||||
);
|
||||
} else if let Some((x, y)) = axis_buffer {
|
||||
eviter.lock().unwrap().push_back(
|
||||
sink.lock().unwrap().push_event(
|
||||
Event::MouseWheel(
|
||||
MouseScrollDelta::PixelDelta(x as f32, y as f32),
|
||||
self.axis_state
|
||||
)
|
||||
),
|
||||
make_wid(window)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -574,24 +577,24 @@ impl wl_keyboard::Handler for WaylandEnv {
|
|||
surface: &wl_surface::WlSurface,
|
||||
keys: Vec<u8>)
|
||||
{
|
||||
let mut opt_eviter = None;
|
||||
for &(ref window, ref eviter) in &self.windows {
|
||||
let mut opt_sink = None;
|
||||
for &(ref window, ref sink) in &self.windows {
|
||||
if window.equals(surface) {
|
||||
opt_eviter = Some(eviter.clone());
|
||||
opt_sink = Some((window.clone(), sink.clone()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(ref eviter) = opt_eviter {
|
||||
if let Some((ref window, ref sink)) = opt_sink {
|
||||
// send focused event
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
guard.push_back(Event::Focused(true));
|
||||
let mut guard = sink.lock().unwrap();
|
||||
guard.push_event(Event::Focused(true), make_wid(window));
|
||||
}
|
||||
match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => {
|
||||
h.handler().target = opt_eviter;
|
||||
h.handler().target = opt_sink;
|
||||
h.enter(evqh, proxy, serial, surface, keys);
|
||||
},
|
||||
KbdType::Plain(ref mut opt) => { *opt = opt_eviter; }
|
||||
KbdType::Plain(ref mut opt) => { *opt = opt_sink; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,17 +604,17 @@ impl wl_keyboard::Handler for WaylandEnv {
|
|||
serial: u32,
|
||||
surface: &wl_surface::WlSurface)
|
||||
{
|
||||
let opt_eviter = match self.kbd_handler {
|
||||
let opt_sink = match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => {
|
||||
let eviter = h.handler().target.take();
|
||||
let sink = h.handler().target.take();
|
||||
h.leave(evqh, proxy, serial, surface);
|
||||
eviter
|
||||
sink
|
||||
},
|
||||
KbdType::Plain(ref mut opt) => opt.take()
|
||||
};
|
||||
if let Some(eviter) = opt_eviter {
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
guard.push_back(Event::Focused(false));
|
||||
if let Some((ref window, ref sink)) = opt_sink {
|
||||
let mut guard = sink.lock().unwrap();
|
||||
guard.push_event(Event::Focused(false), make_wid(window));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,12 +628,12 @@ impl wl_keyboard::Handler for WaylandEnv {
|
|||
{
|
||||
match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state),
|
||||
KbdType::Plain(Some(ref eviter)) => {
|
||||
KbdType::Plain(Some((ref window, ref sink))) => {
|
||||
let state = match state {
|
||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||
};
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
let mut guard = sink.lock().unwrap();
|
||||
// This is fallback impl if libxkbcommon was not available
|
||||
// This case should probably never happen, as most wayland
|
||||
// compositors _need_ libxkbcommon anyway...
|
||||
|
@ -638,12 +641,15 @@ impl wl_keyboard::Handler for WaylandEnv {
|
|||
// In this case, we don't have the modifiers state information
|
||||
// anyway, as we need libxkbcommon to interpret it (it is
|
||||
// supposed to be serialized by the compositor using libxkbcommon)
|
||||
guard.push_back(Event::KeyboardInput(
|
||||
state,
|
||||
key as u8,
|
||||
None,
|
||||
ModifiersState::default()
|
||||
));
|
||||
guard.push_event(
|
||||
Event::KeyboardInput(
|
||||
state,
|
||||
key as u8,
|
||||
None,
|
||||
ModifiersState::default()
|
||||
),
|
||||
make_wid(window)
|
||||
);
|
||||
},
|
||||
KbdType::Plain(None) => ()
|
||||
}
|
||||
|
|
184
src/platform/linux/wayland/event_loop.rs
Normal file
184
src/platform/linux/wayland/event_loop.rs
Normal file
|
@ -0,0 +1,184 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
use super::{DecoratedHandler, WindowId, WaylandContext};
|
||||
|
||||
use wayland_client::EventQueue;
|
||||
use super::wayland_window::DecoratedSurface;
|
||||
|
||||
pub struct EventsLoopSink {
|
||||
callback: Option<*mut FnMut(::Event)>,
|
||||
queue: VecDeque<::Event>
|
||||
}
|
||||
|
||||
unsafe impl Send for EventsLoopSink { }
|
||||
|
||||
impl EventsLoopSink {
|
||||
pub fn new() -> EventsLoopSink {
|
||||
EventsLoopSink {
|
||||
callback: None,
|
||||
queue: VecDeque::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
|
||||
let evt = ::Event::WindowEvent {
|
||||
event: evt,
|
||||
window_id: ::WindowId(::platform::WindowId::Wayland(wid))
|
||||
};
|
||||
if let Some(cb) = self.callback {
|
||||
unsafe { (&mut *cb)(evt) }
|
||||
} else {
|
||||
self.queue.push_back(evt)
|
||||
}
|
||||
}
|
||||
|
||||
// This function is only safe of the set callback is unset before exclusive
|
||||
// access to the wayland EventQueue is finished.
|
||||
//
|
||||
// The callback also cannot be used any longer as long as it has not been
|
||||
// cleared from the Sink.
|
||||
unsafe fn set_callback(&mut self, cb: &mut FnMut(::Event)) {
|
||||
let cb: &mut FnMut(::Event) = ::std::mem::transmute(cb);
|
||||
self.callback = Some(cb as *mut _);
|
||||
}
|
||||
|
||||
fn with_callback<F: FnOnce(&mut FnMut(::Event))>(&mut self, f: F) {
|
||||
if let Some(cb) = self.callback {
|
||||
f(unsafe {&mut *cb})
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_callback(&mut self) {
|
||||
self.callback = None
|
||||
}
|
||||
|
||||
fn drain_queue<F: FnMut(::Event)>(&mut self, cb: &mut F) {
|
||||
for evt in self.queue.drain(..) {
|
||||
cb(evt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventsLoop {
|
||||
ctxt: Arc<WaylandContext>,
|
||||
evq: Arc<Mutex<EventQueue>>,
|
||||
decorated_ids: Mutex<Vec<(usize, WindowId)>>,
|
||||
sink: Arc<Mutex<EventsLoopSink>>,
|
||||
interrupted: AtomicBool,
|
||||
}
|
||||
|
||||
impl EventsLoop {
|
||||
pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop {
|
||||
let evq = ctxt.display.create_event_queue();
|
||||
EventsLoop {
|
||||
ctxt: ctxt,
|
||||
evq: Arc::new(Mutex::new(evq)),
|
||||
decorated_ids: Mutex::new(Vec::new()),
|
||||
sink: Arc::new(Mutex::new(EventsLoopSink::new())),
|
||||
interrupted: AtomicBool::new(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_sink(&self) -> Arc<Mutex<EventsLoopSink>> {
|
||||
self.sink.clone()
|
||||
}
|
||||
|
||||
pub fn get_event_queue(&self) -> Arc<Mutex<EventQueue>> {
|
||||
self.evq.clone()
|
||||
}
|
||||
|
||||
pub fn register_window(&self, decorated_id: usize, wid: WindowId) {
|
||||
self.decorated_ids.lock().unwrap().push((decorated_id, wid));
|
||||
}
|
||||
|
||||
fn process_resize(evq: &mut EventQueue, ids: &[(usize, WindowId)], callback: &mut FnMut(::Event))
|
||||
{
|
||||
let mut state = evq.state();
|
||||
for &(decorated_id, window_id) in ids {
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
||||
if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) {
|
||||
decorated.resize(w as i32, h as i32);
|
||||
callback(
|
||||
::Event::WindowEvent {
|
||||
window_id: ::WindowId(::platform::WindowId::Wayland(window_id)),
|
||||
event: ::WindowEvent::Resized(w,h)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interrupt(&self) {
|
||||
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn poll_events<F>(&self, mut callback: F)
|
||||
where F: FnMut(::Event)
|
||||
{
|
||||
// send pending requests to the server...
|
||||
self.ctxt.flush();
|
||||
|
||||
// first of all, get exclusive access to this event queue
|
||||
let mut evq_guard = self.evq.lock().unwrap();
|
||||
|
||||
// dispatch stored events:
|
||||
self.sink.lock().unwrap().drain_queue(&mut callback);
|
||||
|
||||
// read some events from the socket if some are waiting & queue is empty
|
||||
if let Some(guard) = evq_guard.prepare_read() {
|
||||
guard.read_events().expect("Wayland connection unexpectedly lost");
|
||||
}
|
||||
|
||||
// set the callback into the sink
|
||||
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
|
||||
|
||||
// then do the actual dispatching
|
||||
self.ctxt.dispatch_pending();
|
||||
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||
|
||||
let mut sink_guard = self.sink.lock().unwrap();
|
||||
|
||||
// events where probably dispatched, process resize
|
||||
let ids_guard = self.decorated_ids.lock().unwrap();
|
||||
sink_guard.with_callback(
|
||||
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
|
||||
);
|
||||
|
||||
sink_guard.clear_callback();
|
||||
// we must keep callback alive up to this point!
|
||||
drop(callback);
|
||||
|
||||
}
|
||||
|
||||
pub fn run_forever<F>(&self, mut callback: F)
|
||||
where F: FnMut(::Event)
|
||||
{
|
||||
// send pending requests to the server...
|
||||
self.ctxt.flush();
|
||||
|
||||
// first of all, get exclusive access to this event queue
|
||||
let mut evq_guard = self.evq.lock().unwrap();
|
||||
|
||||
// dispatch stored events:
|
||||
self.sink.lock().unwrap().drain_queue(&mut callback);
|
||||
|
||||
// set the callback into the sink
|
||||
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
|
||||
|
||||
while !self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
|
||||
self.ctxt.dispatch();
|
||||
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||
let ids_guard = self.decorated_ids.lock().unwrap();
|
||||
self.sink.lock().unwrap().with_callback(
|
||||
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
|
||||
);
|
||||
self.ctxt.flush();
|
||||
}
|
||||
|
||||
self.sink.lock().unwrap().clear_callback();
|
||||
// we must keep callback alive up to this point!
|
||||
drop(callback)
|
||||
}
|
||||
}
|
|
@ -1,16 +1,15 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use {VirtualKeyCode, ElementState, WindowEvent as Event};
|
||||
|
||||
use events::ModifiersState;
|
||||
|
||||
use super::wayland_kbd;
|
||||
use super::{wayland_kbd, make_wid, EventsLoopSink};
|
||||
use wayland_client::EventQueueHandle;
|
||||
use wayland_client::protocol::wl_keyboard;
|
||||
use wayland_client::protocol::{wl_keyboard, wl_surface};
|
||||
|
||||
pub struct KbdHandler {
|
||||
pub target: Option<Arc<Mutex<VecDeque<Event>>>>
|
||||
pub target: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>
|
||||
}
|
||||
|
||||
impl KbdHandler {
|
||||
|
@ -31,14 +30,14 @@ impl wayland_kbd::Handler for KbdHandler {
|
|||
state: wl_keyboard::KeyState,
|
||||
utf8: Option<String>)
|
||||
{
|
||||
if let Some(ref eviter) = self.target {
|
||||
if let Some((ref window, ref sink)) = self.target {
|
||||
let state = match state {
|
||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||
};
|
||||
let vkcode = key_to_vkey(rawkey, keysym);
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
guard.push_back(
|
||||
let mut guard = sink.lock().unwrap();
|
||||
guard.push_event(
|
||||
Event::KeyboardInput(
|
||||
state,
|
||||
rawkey as u8,
|
||||
|
@ -49,13 +48,14 @@ impl wayland_kbd::Handler for KbdHandler {
|
|||
alt: mods.alt,
|
||||
logo: mods.logo
|
||||
}
|
||||
)
|
||||
),
|
||||
make_wid(window)
|
||||
);
|
||||
// send char event only on key press, not release
|
||||
if let ElementState::Released = state { return }
|
||||
if let Some(txt) = utf8 {
|
||||
for chr in txt.chars() {
|
||||
guard.push_back(Event::ReceivedCharacter(chr));
|
||||
guard.push_event(Event::ReceivedCharacter(chr), make_wid(window));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,122 +1,17 @@
|
|||
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
|
||||
|
||||
use self::window::Window;
|
||||
pub use self::window::{Window as Window2, WindowId};
|
||||
pub use self::event_loop::EventsLoop;
|
||||
pub use self::context::{WaylandContext, MonitorId, get_available_monitors,
|
||||
get_primary_monitor};
|
||||
|
||||
use self::window::{make_wid, DecoratedHandler};
|
||||
use self::event_loop::EventsLoopSink;
|
||||
|
||||
extern crate wayland_kbd;
|
||||
extern crate wayland_window;
|
||||
|
||||
use CreationError;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
mod context;
|
||||
mod event_loop;
|
||||
mod keyboard;
|
||||
mod window;
|
||||
|
||||
// API TRANSITION
|
||||
//
|
||||
// We don't use the gen_api_transistion!() macro but rather do the expansion manually:
|
||||
//
|
||||
// As this module is nested into platform/linux, its code is not _exactly_ the same as
|
||||
// the one generated by the macro.
|
||||
|
||||
pub struct EventsLoop {
|
||||
windows: ::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>,
|
||||
interrupted: ::std::sync::atomic::AtomicBool,
|
||||
}
|
||||
|
||||
impl EventsLoop {
|
||||
pub fn new() -> EventsLoop {
|
||||
EventsLoop {
|
||||
windows: ::std::sync::Mutex::new(vec![]),
|
||||
interrupted: ::std::sync::atomic::AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interrupt(&self) {
|
||||
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn poll_events<F>(&self, mut callback: F)
|
||||
where F: FnMut(::Event)
|
||||
{
|
||||
let windows = self.windows.lock().unwrap();
|
||||
for window in windows.iter() {
|
||||
for event in window.poll_events() {
|
||||
callback(::Event::WindowEvent {
|
||||
window_id: ::WindowId(::platform::WindowId::Wayland(WindowId(&**window as *const Window as usize))),
|
||||
event: event,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_forever<F>(&self, mut callback: F)
|
||||
where F: FnMut(::Event)
|
||||
{
|
||||
self.interrupted.store(false, ::std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
// Yeah that's a very bad implementation.
|
||||
loop {
|
||||
self.poll_events(|e| callback(e));
|
||||
::std::thread::sleep(::std::time::Duration::from_millis(5));
|
||||
if self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(usize);
|
||||
|
||||
pub struct Window2 {
|
||||
pub window: ::std::sync::Arc<Window>,
|
||||
events_loop: ::std::sync::Weak<::platform::EventsLoop>,
|
||||
}
|
||||
|
||||
impl ::std::ops::Deref for Window2 {
|
||||
type Target = Window;
|
||||
#[inline]
|
||||
fn deref(&self) -> &Window {
|
||||
&*self.window
|
||||
}
|
||||
}
|
||||
|
||||
impl Window2 {
|
||||
pub fn new(events_loop: ::std::sync::Arc<::platform::EventsLoop>, ctxt: Arc<WaylandContext>,
|
||||
window: &::WindowAttributes)
|
||||
-> Result<Window2, CreationError>
|
||||
{
|
||||
let win = ::std::sync::Arc::new(try!(Window::new(ctxt, window)));
|
||||
if let ::platform::EventsLoop::Wayland(ref ev) = *events_loop {
|
||||
ev.windows.lock().unwrap().push(win.clone());
|
||||
} else {
|
||||
// It should not be possible to create an eventloop not matching the backend
|
||||
// in use
|
||||
unreachable!()
|
||||
}
|
||||
Ok(Window2 {
|
||||
window: win,
|
||||
events_loop: ::std::sync::Arc::downgrade(&events_loop),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn id(&self) -> WindowId {
|
||||
WindowId(&*self.window as *const Window as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window2 {
|
||||
fn drop(&mut self) {
|
||||
if let Some(ev) = self.events_loop.upgrade() {
|
||||
if let ::platform::EventsLoop::Wayland(ref ev) = *ev {
|
||||
let mut windows = ev.windows.lock().unwrap();
|
||||
windows.retain(|w| &**w as *const Window != &*self.window as *const _);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,141 +1,80 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use wayland_client::{EventQueue, EventQueueHandle, Init};
|
||||
use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy};
|
||||
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
|
||||
|
||||
use {CreationError, MouseCursor, CursorState, WindowEvent as Event, WindowAttributes};
|
||||
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
||||
use platform::MonitorId as PlatformMonitorId;
|
||||
|
||||
use super::WaylandContext;
|
||||
use super::{WaylandContext, EventsLoop};
|
||||
use super::wayland_window;
|
||||
use super::wayland_window::DecoratedSurface;
|
||||
|
||||
pub struct Window {
|
||||
ctxt: Arc<WaylandContext>,
|
||||
evq: Mutex<EventQueue>,
|
||||
eviter: Arc<Mutex<VecDeque<Event>>>,
|
||||
evq: Arc<Mutex<EventQueue>>,
|
||||
surface: Arc<wl_surface::WlSurface>,
|
||||
size: Mutex<(u32, u32)>,
|
||||
handler_id: usize,
|
||||
decorated_id: usize
|
||||
}
|
||||
|
||||
pub struct PollEventsIterator<'a> {
|
||||
window: &'a Window,
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(usize);
|
||||
|
||||
impl<'a> Iterator for PollEventsIterator<'a> {
|
||||
type Item = Event;
|
||||
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
self.window.next_event(false)
|
||||
}
|
||||
#[inline]
|
||||
pub fn make_wid(s: &wl_surface::WlSurface) -> WindowId {
|
||||
WindowId(s.ptr() as usize)
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError>
|
||||
pub fn new(evlp: &EventsLoop, ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError>
|
||||
{
|
||||
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
||||
|
||||
let mut evq = ctxt.display.create_event_queue();
|
||||
|
||||
let (surface, eviter, decorated) = ctxt.create_window::<DecoratedHandler>();
|
||||
let (surface, decorated) = ctxt.create_window::<DecoratedHandler>(evlp.get_sink());
|
||||
|
||||
// init DecoratedSurface
|
||||
let decorated_id = evq.add_handler_with_init(decorated);
|
||||
{
|
||||
let mut state = evq.state();
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
||||
*(decorated.handler()) = Some(DecoratedHandler::new());
|
||||
let evq = evlp.get_event_queue();
|
||||
let decorated_id = {
|
||||
let mut evq_guard = evq.lock().unwrap();
|
||||
let decorated_id = evq_guard.add_handler_with_init(decorated);
|
||||
{
|
||||
let mut state = evq_guard.state();
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
||||
*(decorated.handler()) = Some(DecoratedHandler::new());
|
||||
|
||||
if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor {
|
||||
ctxt.with_output(monitor_id.clone(), |output| {
|
||||
decorated.set_fullscreen(
|
||||
wl_shell_surface::FullscreenMethod::Default,
|
||||
0,
|
||||
Some(output)
|
||||
)
|
||||
});
|
||||
} else if attributes.decorations {
|
||||
decorated.set_decorate(true);
|
||||
if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor {
|
||||
ctxt.with_output(monitor_id.clone(), |output| {
|
||||
decorated.set_fullscreen(
|
||||
wl_shell_surface::FullscreenMethod::Default,
|
||||
0,
|
||||
Some(output)
|
||||
)
|
||||
});
|
||||
} else if attributes.decorations {
|
||||
decorated.set_decorate(true);
|
||||
}
|
||||
// Finally, set the decorations size
|
||||
decorated.resize(width as i32, height as i32);
|
||||
}
|
||||
// Finally, set the decorations size
|
||||
decorated.resize(width as i32, height as i32);
|
||||
}
|
||||
|
||||
// init general handler
|
||||
let handler = WindowHandler::new();
|
||||
let handler_id = evq.add_handler_with_init(handler);
|
||||
|
||||
Ok(Window {
|
||||
decorated_id
|
||||
};
|
||||
let me = Window {
|
||||
ctxt: ctxt,
|
||||
evq: Mutex::new(evq),
|
||||
eviter: eviter,
|
||||
evq: evq,
|
||||
surface: surface,
|
||||
size: Mutex::new((width, height)),
|
||||
handler_id: handler_id,
|
||||
decorated_id: decorated_id
|
||||
})
|
||||
}
|
||||
|
||||
fn process_resize(&self) {
|
||||
let mut evq_guard = self.evq.lock().unwrap();
|
||||
let mut state = evq_guard.state();
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
||||
if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) {
|
||||
decorated.resize(w as i32, h as i32);
|
||||
*self.size.lock().unwrap() = (w, h);
|
||||
self.eviter.lock().unwrap().push_back(Event::Resized(w,h));
|
||||
}
|
||||
}
|
||||
|
||||
fn next_event(&self, block: bool) -> Option<Event> {
|
||||
let mut evt = {
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
guard.pop_front()
|
||||
};
|
||||
if evt.is_some() { return evt }
|
||||
|
||||
// There is no event in the queue, we need to fetch more
|
||||
|
||||
// flush the display
|
||||
self.ctxt.flush();
|
||||
|
||||
// read some events if some are waiting & queue is empty
|
||||
if let Some(guard) = self.evq.lock().unwrap().prepare_read() {
|
||||
guard.read_events().expect("Wayland connection unexpectedly lost");
|
||||
}
|
||||
|
||||
// try a pending dispatch
|
||||
{
|
||||
self.ctxt.dispatch_pending();
|
||||
self.evq.lock().unwrap().dispatch_pending()
|
||||
.expect("Wayland connection unexpectedly lost");
|
||||
// some events were dispatched, need to process a potential resising
|
||||
self.process_resize();
|
||||
}
|
||||
|
||||
evt = {
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
guard.pop_front()
|
||||
};
|
||||
|
||||
while block && evt.is_none() {
|
||||
// no event waiting, need to repopulate!
|
||||
{
|
||||
self.ctxt.flush();
|
||||
self.ctxt.dispatch();
|
||||
self.evq.lock().unwrap().dispatch_pending()
|
||||
.expect("Wayland connection unexpectedly lost");
|
||||
// some events were dispatched, need to process a potential resising
|
||||
self.process_resize();
|
||||
}
|
||||
// try again
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
evt = guard.pop_front();
|
||||
}
|
||||
evt
|
||||
evlp.register_window(me.decorated_id, me.id());
|
||||
|
||||
Ok(me)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn id(&self) -> WindowId {
|
||||
make_wid(&self.surface)
|
||||
}
|
||||
|
||||
pub fn set_title(&self, title: &str) {
|
||||
|
@ -186,13 +125,6 @@ impl Window {
|
|||
decorated.resize(x as i32, y as i32);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn poll_events(&self) -> PollEventsIterator {
|
||||
PollEventsIterator {
|
||||
window: self
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor(&self, _cursor: MouseCursor) {
|
||||
// TODO
|
||||
|
@ -237,13 +169,14 @@ impl Drop for Window {
|
|||
}
|
||||
}
|
||||
|
||||
struct DecoratedHandler {
|
||||
pub struct DecoratedHandler {
|
||||
newsize: Option<(u32, u32)>
|
||||
}
|
||||
|
||||
impl DecoratedHandler {
|
||||
fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }}
|
||||
fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
||||
|
||||
pub fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
||||
self.newsize.take()
|
||||
}
|
||||
}
|
||||
|
@ -258,21 +191,3 @@ impl wayland_window::Handler for DecoratedHandler {
|
|||
self.newsize = Some((max(width,1) as u32, max(height,1) as u32));
|
||||
}
|
||||
}
|
||||
|
||||
struct WindowHandler {
|
||||
my_id: usize,
|
||||
}
|
||||
|
||||
impl WindowHandler {
|
||||
fn new() -> WindowHandler {
|
||||
WindowHandler {
|
||||
my_id: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Init for WindowHandler {
|
||||
fn init(&mut self, _evqh: &mut EventQueueHandle, index: usize) {
|
||||
self.my_id = index;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue