wayland: mugrate to new API

This commit is contained in:
Victor Berger 2017-03-04 14:04:01 +01:00
parent 9aaa788434
commit 7336cacf07
6 changed files with 310 additions and 305 deletions

View file

@ -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(_) => {

View file

@ -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) => ()
}

View 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)
}
}

View file

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

View file

@ -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 _);
}
}
}
}

View file

@ -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;
}
}